diff options
81 files changed, 1548 insertions, 353 deletions
diff --git a/arch/avr32/boards/atstk1000/atstk1000.h b/arch/avr32/boards/atstk1000/atstk1000.h new file mode 100644 index 00000000000..9a49ed036b7 --- /dev/null +++ b/arch/avr32/boards/atstk1000/atstk1000.h @@ -0,0 +1,15 @@ +/* + * ATSTK1000 setup code: Daughterboard interface + * + * Copyright (C) 2007 Atmel 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. + */ +#ifndef __ARCH_AVR32_BOARDS_ATSTK1000_ATSTK1000_H +#define __ARCH_AVR32_BOARDS_ATSTK1000_ATSTK1000_H + +extern struct atmel_lcdfb_info atstk1000_lcdc_data; + +#endif /* __ARCH_AVR32_BOARDS_ATSTK1000_ATSTK1000_H */ diff --git a/arch/avr32/boards/atstk1000/atstk1002.c b/arch/avr32/boards/atstk1000/atstk1002.c index abe6ca203fa..fe1dbe2e28f 100644 --- a/arch/avr32/boards/atstk1000/atstk1002.c +++ b/arch/avr32/boards/atstk1000/atstk1002.c @@ -16,6 +16,8 @@ #include <linux/types.h> #include <linux/spi/spi.h> +#include <video/atmel_lcdc.h> + #include <asm/io.h> #include <asm/setup.h> #include <asm/arch/at32ap7000.h> @@ -23,6 +25,7 @@ #include <asm/arch/init.h> #include <asm/arch/portmux.h> +#include "atstk1000.h" #define SW2_DEFAULT /* MMCI and UART_A available */ @@ -31,9 +34,7 @@ struct eth_addr { }; static struct eth_addr __initdata hw_addr[2]; - static struct eth_platform_data __initdata eth_data[2]; -static struct lcdc_platform_data atstk1000_fb0_data; static struct spi_board_info spi0_board_info[] __initdata = { { @@ -148,9 +149,8 @@ static int __init atstk1002_init(void) set_hw_addr(at32_add_device_eth(0, ð_data[0])); at32_add_device_spi(0, spi0_board_info, ARRAY_SIZE(spi0_board_info)); - atstk1000_fb0_data.fbmem_start = fbmem_start; - atstk1000_fb0_data.fbmem_size = fbmem_size; - at32_add_device_lcdc(0, &atstk1000_fb0_data); + at32_add_device_lcdc(0, &atstk1000_lcdc_data, + fbmem_start, fbmem_size); return 0; } diff --git a/arch/avr32/boards/atstk1000/setup.c b/arch/avr32/boards/atstk1000/setup.c index 2bc4b88d7ed..c9af409ada9 100644 --- a/arch/avr32/boards/atstk1000/setup.c +++ b/arch/avr32/boards/atstk1000/setup.c @@ -8,13 +8,56 @@ * published by the Free Software Foundation. */ #include <linux/bootmem.h> +#include <linux/fb.h> #include <linux/init.h> #include <linux/types.h> #include <linux/linkage.h> -#include <asm/setup.h> +#include <video/atmel_lcdc.h> +#include <asm/setup.h> #include <asm/arch/board.h> +#include "atstk1000.h" + /* Initialized by bootloader-specific startup code. */ struct tag *bootloader_tags __initdata; + +static struct fb_videomode __initdata ltv350qv_modes[] = { + { + .name = "320x240 @ 75", + .refresh = 75, + .xres = 320, .yres = 240, + .pixclock = KHZ2PICOS(6891), + + .left_margin = 17, .right_margin = 33, + .upper_margin = 10, .lower_margin = 10, + .hsync_len = 16, .vsync_len = 1, + + .sync = 0, + .vmode = FB_VMODE_NONINTERLACED, + }, +}; + +static struct fb_monspecs __initdata atstk1000_default_monspecs = { + .manufacturer = "SNG", + .monitor = "LTV350QV", + .modedb = ltv350qv_modes, + .modedb_len = ARRAY_SIZE(ltv350qv_modes), + .hfmin = 14820, + .hfmax = 22230, + .vfmin = 60, + .vfmax = 90, + .dclkmax = 30000000, +}; + +struct atmel_lcdfb_info __initdata atstk1000_lcdc_data = { + .default_bpp = 24, + .default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN, + .default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT + | ATMEL_LCDC_INVCLK + | ATMEL_LCDC_CLKMOD_ALWAYSACTIVE + | ATMEL_LCDC_MEMOR_BIG), + .default_monspecs = &atstk1000_default_monspecs, + .guard_time = 2, +}; diff --git a/arch/avr32/kernel/irq.c b/arch/avr32/kernel/irq.c index fd311248c14..61f2de266f6 100644 --- a/arch/avr32/kernel/irq.c +++ b/arch/avr32/kernel/irq.c @@ -7,15 +7,6 @@ * 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 file contains the code used by various IRQ handling routines: - * asking for different IRQ's should be done through these routines - * instead of just grabbing them. Thus setups with different IRQ numbers - * shouldn't result in any weird surprises, and installing new handlers - * should be easier. - * - * IRQ's are in fact implemented a bit like signal handlers for the kernel. - * Naturally it's not a 1:1 relation, but there are similarities. */ #include <linux/interrupt.h> diff --git a/arch/avr32/kernel/kprobes.c b/arch/avr32/kernel/kprobes.c index 004c94b6fc1..4942ee662e0 100644 --- a/arch/avr32/kernel/kprobes.c +++ b/arch/avr32/kernel/kprobes.c @@ -179,7 +179,7 @@ static int __kprobes post_kprobe_handler(struct pt_regs *regs) return 1; } -static int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) +int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) { struct kprobe *cur = kprobe_running(); @@ -216,11 +216,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, if (post_kprobe_handler(args->regs)) ret = NOTIFY_STOP; break; - case DIE_FAULT: - if (kprobe_running() - && kprobe_fault_handler(args->regs, args->trapnr)) - ret = NOTIFY_STOP; - break; default: break; } diff --git a/arch/avr32/kernel/syscall_table.S b/arch/avr32/kernel/syscall_table.S index 07f6a6fa340..75c81f2dd0b 100644 --- a/arch/avr32/kernel/syscall_table.S +++ b/arch/avr32/kernel/syscall_table.S @@ -292,4 +292,7 @@ sys_call_table: .long sys_shmdt .long sys_shmctl .long sys_utimensat + .long sys_signalfd + .long sys_timerfd /* 280 */ + .long sys_eventfd .long sys_ni_syscall /* r8 is saturated at nr_syscalls */ diff --git a/arch/avr32/mach-at32ap/at32ap7000.c b/arch/avr32/mach-at32ap/at32ap7000.c index 56db45b99a0..1d2bf347a1d 100644 --- a/arch/avr32/mach-at32ap/at32ap7000.c +++ b/arch/avr32/mach-at32ap/at32ap7000.c @@ -6,6 +6,7 @@ * published by the Free Software Foundation. */ #include <linux/clk.h> +#include <linux/fb.h> #include <linux/init.h> #include <linux/platform_device.h> #include <linux/spi/spi.h> @@ -17,6 +18,8 @@ #include <asm/arch/portmux.h> #include <asm/arch/sm.h> +#include <video/atmel_lcdc.h> + #include "clock.h" #include "hmatrix.h" #include "pio.h" @@ -881,20 +884,26 @@ at32_add_device_spi(unsigned int id, struct spi_board_info *b, unsigned int n) /* -------------------------------------------------------------------- * LCDC * -------------------------------------------------------------------- */ -static struct lcdc_platform_data lcdc0_data; -static struct resource lcdc0_resource[] = { +static struct atmel_lcdfb_info atmel_lcdfb0_data; +static struct resource atmel_lcdfb0_resource[] = { { .start = 0xff000000, .end = 0xff000fff, .flags = IORESOURCE_MEM, }, IRQ(1), + { + /* Placeholder for pre-allocated fb memory */ + .start = 0x00000000, + .end = 0x00000000, + .flags = 0, + }, }; -DEFINE_DEV_DATA(lcdc, 0); -DEV_CLK(hclk, lcdc0, hsb, 7); -static struct clk lcdc0_pixclk = { - .name = "pixclk", - .dev = &lcdc0_device.dev, +DEFINE_DEV_DATA(atmel_lcdfb, 0); +DEV_CLK(hck1, atmel_lcdfb0, hsb, 7); +static struct clk atmel_lcdfb0_pixclk = { + .name = "lcdc_clk", + .dev = &atmel_lcdfb0_device.dev, .mode = genclk_mode, .get_rate = genclk_get_rate, .set_rate = genclk_set_rate, @@ -903,13 +912,34 @@ static struct clk lcdc0_pixclk = { }; struct platform_device *__init -at32_add_device_lcdc(unsigned int id, struct lcdc_platform_data *data) +at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data, + unsigned long fbmem_start, unsigned long fbmem_len) { struct platform_device *pdev; + struct atmel_lcdfb_info *info; + struct fb_monspecs *monspecs; + struct fb_videomode *modedb; + unsigned int modedb_size; + + /* + * Do a deep copy of the fb data, monspecs and modedb. Make + * sure all allocations are done before setting up the + * portmux. + */ + monspecs = kmemdup(data->default_monspecs, + sizeof(struct fb_monspecs), GFP_KERNEL); + if (!monspecs) + return NULL; + + modedb_size = sizeof(struct fb_videomode) * monspecs->modedb_len; + modedb = kmemdup(monspecs->modedb, modedb_size, GFP_KERNEL); + if (!modedb) + goto err_dup_modedb; + monspecs->modedb = modedb; switch (id) { case 0: - pdev = &lcdc0_device; + pdev = &atmel_lcdfb0_device; select_peripheral(PC(19), PERIPH_A, 0); /* CC */ select_peripheral(PC(20), PERIPH_A, 0); /* HSYNC */ select_peripheral(PC(21), PERIPH_A, 0); /* PCLK */ @@ -942,19 +972,32 @@ at32_add_device_lcdc(unsigned int id, struct lcdc_platform_data *data) select_peripheral(PD(16), PERIPH_A, 0); /* DATA22 */ select_peripheral(PD(17), PERIPH_A, 0); /* DATA23 */ - clk_set_parent(&lcdc0_pixclk, &pll0); - clk_set_rate(&lcdc0_pixclk, clk_get_rate(&pll0)); + clk_set_parent(&atmel_lcdfb0_pixclk, &pll0); + clk_set_rate(&atmel_lcdfb0_pixclk, clk_get_rate(&pll0)); break; default: - return NULL; + goto err_invalid_id; } - memcpy(pdev->dev.platform_data, data, - sizeof(struct lcdc_platform_data)); + if (fbmem_len) { + pdev->resource[2].start = fbmem_start; + pdev->resource[2].end = fbmem_start + fbmem_len - 1; + pdev->resource[2].flags = IORESOURCE_MEM; + } + + info = pdev->dev.platform_data; + memcpy(info, data, sizeof(struct atmel_lcdfb_info)); + info->default_monspecs = monspecs; platform_device_register(pdev); return pdev; + +err_invalid_id: + kfree(modedb); +err_dup_modedb: + kfree(monspecs); + return NULL; } /* -------------------------------------------------------------------- @@ -1037,8 +1080,8 @@ struct clk *at32_clock_list[] = { &macb1_pclk, &atmel_spi0_spi_clk, &atmel_spi1_spi_clk, - &lcdc0_hclk, - &lcdc0_pixclk, + &atmel_lcdfb0_hck1, + &atmel_lcdfb0_pixclk, &gclk0, &gclk1, &gclk2, @@ -1077,7 +1120,7 @@ void __init at32_clock_init(void) genclk_init_parent(&gclk2); genclk_init_parent(&gclk3); genclk_init_parent(&gclk4); - genclk_init_parent(&lcdc0_pixclk); + genclk_init_parent(&atmel_lcdfb0_pixclk); /* * Turn on all clocks that have at least one user already, and diff --git a/arch/avr32/mm/fault.c b/arch/avr32/mm/fault.c index 88b00b15970..e011f1ce187 100644 --- a/arch/avr32/mm/fault.c +++ b/arch/avr32/mm/fault.c @@ -12,41 +12,30 @@ #include <linux/mm.h> #include <linux/module.h> #include <linux/pagemap.h> - #include <linux/kdebug.h> +#include <linux/kprobes.h> + #include <asm/mmu_context.h> #include <asm/sysreg.h> #include <asm/tlb.h> #include <asm/uaccess.h> #ifdef CONFIG_KPROBES -ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain); - -/* Hook to register for page fault notifications */ -int register_page_fault_notifier(struct notifier_block *nb) +static inline int notify_page_fault(struct pt_regs *regs, int trap) { - return atomic_notifier_chain_register(¬ify_page_fault_chain, nb); -} + int ret = 0; -int unregister_page_fault_notifier(struct notifier_block *nb) -{ - return atomic_notifier_chain_unregister(¬ify_page_fault_chain, nb); -} + if (!user_mode(regs)) { + if (kprobe_running() && kprobe_fault_handler(regs, trap)) + ret = 1; + } -static inline int notify_page_fault(enum die_val val, struct pt_regs *regs, - int trap, int sig) -{ - struct die_args args = { - .regs = regs, - .trapnr = trap, - }; - return atomic_notifier_call_chain(¬ify_page_fault_chain, val, &args); + return ret; } #else -static inline int notify_page_fault(enum die_val val, struct pt_regs *regs, - int trap, int sig) +static inline int notify_page_fault(struct pt_regs *regs, int trap) { - return NOTIFY_DONE; + return 0; } #endif @@ -76,8 +65,7 @@ asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs) long signr; int code; - if (notify_page_fault(DIE_PAGE_FAULT, regs, - ecr, SIGSEGV) == NOTIFY_STOP) + if (notify_page_fault(regs, ecr)) return; address = sysreg_read(TLBEAR); diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index 3549c94467b..c4784494970 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c @@ -791,7 +791,7 @@ static __init int setup_additional_cpus(char *s) early_param("additional_cpus", setup_additional_cpus); /* - * cpu_possible_map should be static, it cannot change as cpu's + * cpu_possible_map should be static, it cannot change as CPUs * are onlined, or offlined. The reason is per-cpu data-structures * are allocated by some modules at init time, and dont expect to * do this dynamically on cpu arrival/departure. diff --git a/arch/ia64/kernel/crash.c b/arch/ia64/kernel/crash.c index aeb79fb28f0..1d64ef478dd 100644 --- a/arch/ia64/kernel/crash.c +++ b/arch/ia64/kernel/crash.c @@ -156,24 +156,30 @@ kdump_init_notifier(struct notifier_block *self, unsigned long val, void *data) if (!kdump_on_init) return NOTIFY_DONE; - if (val != DIE_INIT_MONARCH_ENTER && - val != DIE_INIT_SLAVE_ENTER && + if (val != DIE_INIT_MONARCH_LEAVE && + val != DIE_INIT_SLAVE_LEAVE && + val != DIE_INIT_MONARCH_PROCESS && val != DIE_MCA_RENDZVOUS_LEAVE && val != DIE_MCA_MONARCH_LEAVE) return NOTIFY_DONE; nd = (struct ia64_mca_notify_die *)args->err; - /* Reason code 1 means machine check rendezous*/ - if ((val == DIE_INIT_MONARCH_ENTER || val == DIE_INIT_SLAVE_ENTER) && - nd->sos->rv_rc == 1) + /* Reason code 1 means machine check rendezvous*/ + if ((val == DIE_INIT_MONARCH_LEAVE || val == DIE_INIT_SLAVE_LEAVE + || val == DIE_INIT_MONARCH_PROCESS) && nd->sos->rv_rc == 1) return NOTIFY_DONE; switch (val) { - case DIE_INIT_MONARCH_ENTER: + case DIE_INIT_MONARCH_PROCESS: + atomic_set(&kdump_in_progress, 1); + *(nd->monarch_cpu) = -1; + break; + case DIE_INIT_MONARCH_LEAVE: machine_kdump_on_init(); break; - case DIE_INIT_SLAVE_ENTER: - unw_init_running(kdump_cpu_freeze, NULL); + case DIE_INIT_SLAVE_LEAVE: + if (atomic_read(&kdump_in_progress)) + unw_init_running(kdump_cpu_freeze, NULL); break; case DIE_MCA_RENDZVOUS_LEAVE: if (atomic_read(&kdump_in_progress)) @@ -215,8 +221,10 @@ static ctl_table sys_table[] = { static int machine_crash_setup(void) { + /* be notified before default_monarch_init_process */ static struct notifier_block kdump_init_notifier_nb = { .notifier_call = kdump_init_notifier, + .priority = 1, }; int ret; if((ret = register_die_notifier(&kdump_init_notifier_nb)) != 0) diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index 144b056282a..95f51751523 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S @@ -1585,5 +1585,8 @@ sys_call_table: data8 sys_getcpu data8 sys_epoll_pwait // 1305 data8 sys_utimensat + data8 sys_signalfd + data8 sys_timerfd + data8 sys_eventfd .org sys_call_table + 8*NR_syscalls // guard against failures to increase NR_syscalls diff --git a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c index b4c239685d2..407b4587048 100644 --- a/arch/ia64/kernel/irq.c +++ b/arch/ia64/kernel/irq.c @@ -4,7 +4,7 @@ * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar * * This file contains the code used by various IRQ handling routines: - * asking for different IRQ's should be done through these routines + * asking for different IRQs should be done through these routines * instead of just grabbing them. Thus setups with different IRQ numbers * shouldn't result in any weird surprises, and installing new handlers * should be easier. @@ -12,7 +12,7 @@ * Copyright (C) Ashok Raj<ashok.raj@intel.com>, Intel Corporation 2004 * * 4/14/2004: Added code to handle cpu migration and do safe irq - * migration without lossing interrupts for iosapic + * migration without losing interrupts for iosapic * architecture. */ @@ -190,7 +190,7 @@ void fixup_irqs(void) } /* - * Phase 1: Locate irq's bound to this cpu and + * Phase 1: Locate IRQs bound to this cpu and * relocate them for cpu removal. */ migrate_irqs(); diff --git a/arch/ia64/kernel/irq_lsapic.c b/arch/ia64/kernel/irq_lsapic.c index c2f07beb175..e56a7a36aca 100644 --- a/arch/ia64/kernel/irq_lsapic.c +++ b/arch/ia64/kernel/irq_lsapic.c @@ -23,7 +23,7 @@ lsapic_noop_startup (unsigned int irq) static void lsapic_noop (unsigned int irq) { - /* nuthing to do... */ + /* nothing to do... */ } static int lsapic_retrigger(unsigned int irq) diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c index 72e593e9405..5bc46f15134 100644 --- a/arch/ia64/kernel/kprobes.c +++ b/arch/ia64/kernel/kprobes.c @@ -151,12 +151,12 @@ static uint __kprobes is_cmp_ctype_unc_inst(uint template, uint slot, cmp_inst.l = kprobe_inst; if ((cmp_inst.f.x2 == 0) || (cmp_inst.f.x2 == 1)) { - /* Integere compare - Register Register (A6 type)*/ + /* Integer compare - Register Register (A6 type)*/ if ((cmp_inst.f.tb == 0) && (cmp_inst.f.ta == 0) &&(cmp_inst.f.c == 1)) ctype_unc = 1; } else if ((cmp_inst.f.x2 == 2)||(cmp_inst.f.x2 == 3)) { - /* Integere compare - Immediate Register (A8 type)*/ + /* Integer compare - Immediate Register (A8 type)*/ if ((cmp_inst.f.ta == 0) &&(cmp_inst.f.c == 1)) ctype_unc = 1; } @@ -820,7 +820,7 @@ out: return 1; } -static int __kprobes kprobes_fault_handler(struct pt_regs *regs, int trapnr) +int __kprobes kprobes_fault_handler(struct pt_regs *regs, int trapnr) { struct kprobe *cur = kprobe_running(); struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); @@ -904,13 +904,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, if (post_kprobes_handler(args->regs)) ret = NOTIFY_STOP; break; - case DIE_PAGE_FAULT: - /* kprobe_running() needs smp_processor_id() */ - preempt_disable(); - if (kprobe_running() && - kprobes_fault_handler(args->regs, args->trapnr)) - ret = NOTIFY_STOP; - preempt_enable(); default: break; } @@ -954,7 +947,7 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) /* * Callee owns the argument space and could overwrite it, eg * tail call optimization. So to be absolutely safe - * we save the argument space before transfering the control + * we save the argument space before transferring the control * to instrumented jprobe function which runs in * the process context */ diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c index 26814de6c29..1ead5ea6c5c 100644 --- a/arch/ia64/kernel/mca.c +++ b/arch/ia64/kernel/mca.c @@ -273,7 +273,6 @@ static void ia64_mlogbuf_finish(int wait) mlogbuf_finished = 1; } -EXPORT_SYMBOL(ia64_mlogbuf_finish); /* * Print buffered messages from INIT context. @@ -1477,6 +1476,10 @@ default_monarch_init_process(struct notifier_block *self, unsigned long val, voi struct task_struct *g, *t; if (val != DIE_INIT_MONARCH_PROCESS) return NOTIFY_DONE; +#ifdef CONFIG_KEXEC + if (atomic_read(&kdump_in_progress)) + return NOTIFY_DONE; +#endif /* * FIXME: mlogbuf will brim over with INIT stack dumps. diff --git a/arch/ia64/kernel/mca_drv.c b/arch/ia64/kernel/mca_drv.c index 70b8bdbb7e6..aba813c2c15 100644 --- a/arch/ia64/kernel/mca_drv.c +++ b/arch/ia64/kernel/mca_drv.c @@ -438,7 +438,7 @@ is_mca_global(peidx_table_t *peidx, pal_bus_check_info_t *pbci, * @peidx: pointer of index of processor error section * * Return value: - * target address on Success / 0 on Failue + * target address on Success / 0 on Failure */ static u64 get_target_identifier(peidx_table_t *peidx) @@ -701,7 +701,7 @@ recover_from_processor_error(int platform, slidx_table_t *slidx, return fatal_mca("External bus check fatal status"); /* - * This is a local MCA and estimated as a recoverble error. + * This is a local MCA and estimated as a recoverable error. */ if (platform) return recover_from_platform_error(slidx, peidx, pbci, sos); diff --git a/arch/ia64/kernel/module.c b/arch/ia64/kernel/module.c index 158e3c51bb7..196287928ba 100644 --- a/arch/ia64/kernel/module.c +++ b/arch/ia64/kernel/module.c @@ -861,7 +861,7 @@ apply_relocate (Elf64_Shdr *sechdrs, const char *strtab, unsigned int symindex, /* * Modules contain a single unwind table which covers both the core and the init text * sections but since the two are not contiguous, we need to split this table up such that - * we can register (and unregister) each "segment" seperately. Fortunately, this sounds + * we can register (and unregister) each "segment" separately. Fortunately, this sounds * more complicated than it really is. */ static void diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index e7191ca30b1..b7133cabdbe 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c @@ -1318,7 +1318,7 @@ pfm_reserve_session(struct task_struct *task, int is_syswide, unsigned int cpu) { unsigned long flags; /* - * validy checks on cpu_mask have been done upstream + * validity checks on cpu_mask have been done upstream */ LOCK_PFS(flags); @@ -1384,7 +1384,7 @@ pfm_unreserve_session(pfm_context_t *ctx, int is_syswide, unsigned int cpu) { unsigned long flags; /* - * validy checks on cpu_mask have been done upstream + * validity checks on cpu_mask have been done upstream */ LOCK_PFS(flags); @@ -1835,7 +1835,7 @@ pfm_flush(struct file *filp, fl_owner_t id) /* * remove our file from the async queue, if we use this mode. * This can be done without the context being protected. We come - * here when the context has become unreacheable by other tasks. + * here when the context has become unreachable by other tasks. * * We may still have active monitoring at this point and we may * end up in pfm_overflow_handler(). However, fasync_helper() @@ -2132,7 +2132,7 @@ doit: filp->private_data = NULL; /* - * if we free on the spot, the context is now completely unreacheable + * if we free on the spot, the context is now completely unreachable * from the callers side. The monitored task side is also cut, so we * can freely cut. * @@ -2562,7 +2562,7 @@ pfm_reset_pmu_state(pfm_context_t *ctx) ctx->ctx_all_pmcs[0] = pmu_conf->impl_pmcs[0] & ~0x1; /* - * bitmask of all PMDs that are accesible to this context + * bitmask of all PMDs that are accessible to this context */ ctx->ctx_all_pmds[0] = pmu_conf->impl_pmds[0]; @@ -3395,7 +3395,7 @@ pfm_read_pmds(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs) if (unlikely(!PMD_IS_IMPL(cnum))) goto error; /* * we can only read the register that we use. That includes - * the one we explicitely initialize AND the one we want included + * the one we explicitly initialize AND the one we want included * in the sampling buffer (smpl_regs). * * Having this restriction allows optimization in the ctxsw routine @@ -3715,7 +3715,7 @@ pfm_restart(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs) * if non-blocking, then we ensure that the task will go into * pfm_handle_work() before returning to user mode. * - * We cannot explicitely reset another task, it MUST always + * We cannot explicitly reset another task, it MUST always * be done by the task itself. This works for system wide because * the tool that is controlling the session is logically doing * "self-monitoring". @@ -4644,7 +4644,7 @@ pfm_exit_thread(struct task_struct *task) switch(state) { case PFM_CTX_UNLOADED: /* - * only comes to thios function if pfm_context is not NULL, i.e., cannot + * only comes to this function if pfm_context is not NULL, i.e., cannot * be in unloaded state */ printk(KERN_ERR "perfmon: pfm_exit_thread [%d] ctx unloaded\n", task->pid); @@ -5247,7 +5247,7 @@ pfm_end_notify_user(pfm_context_t *ctx) /* * main overflow processing routine. - * it can be called from the interrupt path or explicitely during the context switch code + * it can be called from the interrupt path or explicitly during the context switch code */ static void pfm_overflow_handler(struct task_struct *task, pfm_context_t *ctx, u64 pmc0, struct pt_regs *regs) diff --git a/arch/ia64/kernel/perfmon_mckinley.h b/arch/ia64/kernel/perfmon_mckinley.h index 9becccda289..c4bec7a9d18 100644 --- a/arch/ia64/kernel/perfmon_mckinley.h +++ b/arch/ia64/kernel/perfmon_mckinley.h @@ -181,7 +181,7 @@ static pmu_config_t pmu_conf_mck={ .pmc_desc = pfm_mck_pmc_desc, .num_ibrs = 8, .num_dbrs = 8, - .use_rr_dbregs = 1 /* debug register are use for range retrictions */ + .use_rr_dbregs = 1 /* debug register are use for range restrictions */ }; diff --git a/arch/ia64/kernel/sal.c b/arch/ia64/kernel/sal.c index 37c876f95db..27c2ef445a5 100644 --- a/arch/ia64/kernel/sal.c +++ b/arch/ia64/kernel/sal.c @@ -134,7 +134,7 @@ set_smp_redirect (int flag) * interrupt redirection. The reason is this would require that * All interrupts be stopped and hard bind the irq to a cpu. * Later when the interrupt is fired we need to set the redir hint - * on again in the vector. This is combersome for something that the + * on again in the vector. This is cumbersome for something that the * user mode irq balancer will solve anyways. */ no_int_routing=1; diff --git a/arch/ia64/kernel/salinfo.c b/arch/ia64/kernel/salinfo.c index 89f6b138a62..25cd75f50ab 100644 --- a/arch/ia64/kernel/salinfo.c +++ b/arch/ia64/kernel/salinfo.c @@ -162,7 +162,7 @@ static DEFINE_SPINLOCK(data_saved_lock); /** salinfo_platform_oemdata - optional callback to decode oemdata from an error * record. * @sect_header: pointer to the start of the section to decode. - * @oemdata: returns vmalloc area containing the decded output. + * @oemdata: returns vmalloc area containing the decoded output. * @oemdata_size: returns length of decoded output (strlen). * * Description: If user space asks for oem data to be decoded by the kernel diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index 9df1efe7487..eaa6a24bc0b 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c @@ -576,7 +576,7 @@ setup_arch (char **cmdline_p) } /* - * Display cpu info for all cpu's. + * Display cpu info for all CPUs. */ static int show_cpuinfo (struct seq_file *m, void *v) @@ -761,7 +761,7 @@ identify_cpu (struct cpuinfo_ia64 *c) c->cpu = smp_processor_id(); /* below default values will be overwritten by identify_siblings() - * for Multi-Threading/Multi-Core capable cpu's + * for Multi-Threading/Multi-Core capable CPUs */ c->threads_per_core = c->cores_per_socket = c->num_log = 1; c->socket_id = -1; @@ -947,7 +947,7 @@ cpu_init (void) ia32_cpu_init(); #endif - /* Clear ITC to eliminiate sched_clock() overflows in human time. */ + /* Clear ITC to eliminate sched_clock() overflows in human time. */ ia64_set_itc(0); /* disable all local interrupt sources: */ diff --git a/arch/ia64/kernel/smp.c b/arch/ia64/kernel/smp.c index 221de380456..b3a47f986e1 100644 --- a/arch/ia64/kernel/smp.c +++ b/arch/ia64/kernel/smp.c @@ -186,7 +186,7 @@ handle_IPI (int irq, void *dev_id) } /* - * Called with preeemption disabled. + * Called with preemption disabled. */ static inline void send_IPI_single (int dest_cpu, int op) @@ -196,7 +196,7 @@ send_IPI_single (int dest_cpu, int op) } /* - * Called with preeemption disabled. + * Called with preemption disabled. */ static inline void send_IPI_allbutself (int op) @@ -210,7 +210,7 @@ send_IPI_allbutself (int op) } /* - * Called with preeemption disabled. + * Called with preemption disabled. */ static inline void send_IPI_all (int op) @@ -223,7 +223,7 @@ send_IPI_all (int op) } /* - * Called with preeemption disabled. + * Called with preemption disabled. */ static inline void send_IPI_self (int op) @@ -252,7 +252,7 @@ kdump_smp_send_init(void) } #endif /* - * Called with preeemption disabled. + * Called with preemption disabled. */ void smp_send_reschedule (int cpu) @@ -261,7 +261,7 @@ smp_send_reschedule (int cpu) } /* - * Called with preeemption disabled. + * Called with preemption disabled. */ static void smp_send_local_flush_tlb (int cpu) diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c index a44792d0f3a..542958079f1 100644 --- a/arch/ia64/kernel/smpboot.c +++ b/arch/ia64/kernel/smpboot.c @@ -694,7 +694,7 @@ int migrate_platform_irqs(unsigned int cpu) set_cpei_target_cpu(new_cpei_cpu); desc = irq_desc + ia64_cpe_irq; /* - * Switch for now, immediatly, we need to do fake intr + * Switch for now, immediately, we need to do fake intr * as other interrupts, but need to study CPEI behaviour with * polling before making changes. */ @@ -840,7 +840,7 @@ __cpu_up (unsigned int cpu) } /* - * Assume that CPU's have been discovered by some platform-dependent interface. For + * Assume that CPUs have been discovered by some platform-dependent interface. For * SoftSDV/Lion, that would be ACPI. * * Setup of the IPI irq handler is done in irq.c:init_IRQ_SMP(). @@ -854,7 +854,7 @@ init_smp_config(void) } *ap_startup; long sal_ret; - /* Tell SAL where to drop the AP's. */ + /* Tell SAL where to drop the APs. */ ap_startup = (struct fptr *) start_ap; sal_ret = ia64_sal_set_vectors(SAL_VECTOR_OS_BOOT_RENDEZ, ia64_tpa(ap_startup->fp), ia64_tpa(ap_startup->gp), 0, 0, 0, 0); diff --git a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c index b8e0d70bf98..15ad85da15a 100644 --- a/arch/ia64/kernel/traps.c +++ b/arch/ia64/kernel/traps.c @@ -304,7 +304,7 @@ handle_fpu_swa (int fp_fault, struct pt_regs *regs, unsigned long isr) * Lower 4 bits are used as a count. Upper bits are a sequence * number that is updated when count is reset. The cmpxchg will * fail is seqno has changed. This minimizes mutiple cpus - * reseting the count. + * resetting the count. */ if (current_jiffies > last.time) (void) cmpxchg_acq(&last.count, count, 16 + (count & ~15)); diff --git a/arch/ia64/kernel/unwind.c b/arch/ia64/kernel/unwind.c index fe1426266b9..7d3dd6cdafa 100644 --- a/arch/ia64/kernel/unwind.c +++ b/arch/ia64/kernel/unwind.c @@ -2,7 +2,7 @@ * Copyright (C) 1999-2004 Hewlett-Packard Co * David Mosberger-Tang <davidm@hpl.hp.com> * Copyright (C) 2003 Fenghua Yu <fenghua.yu@intel.com> - * - Change pt_regs_off() to make it less dependant on pt_regs structure. + * - Change pt_regs_off() to make it less dependent on pt_regs structure. */ /* * This file implements call frame unwind support for the Linux diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c index 38085ac1833..0dbf0e81f8c 100644 --- a/arch/ia64/mm/discontig.c +++ b/arch/ia64/mm/discontig.c @@ -317,7 +317,7 @@ static void __meminit scatter_node_data(void) * node_online_map is not set for hot-added nodes at this time, * because we are halfway through initialization of the new node's * structures. If for_each_online_node() is used, a new node's - * pg_data_ptrs will be not initialized. Insted of using it, + * pg_data_ptrs will be not initialized. Instead of using it, * pgdat_list[] is checked. */ for_each_node(node) { diff --git a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c index 21658e02116..b87f785c241 100644 --- a/arch/ia64/mm/fault.c +++ b/arch/ia64/mm/fault.c @@ -19,36 +19,24 @@ extern void die (char *, struct pt_regs *, long); #ifdef CONFIG_KPROBES -ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain); - -/* Hook to register for page fault notifications */ -int register_page_fault_notifier(struct notifier_block *nb) -{ - return atomic_notifier_chain_register(¬ify_page_fault_chain, nb); -} - -int unregister_page_fault_notifier(struct notifier_block *nb) +static inline int notify_page_fault(struct pt_regs *regs, int trap) { - return atomic_notifier_chain_unregister(¬ify_page_fault_chain, nb); -} + int ret = 0; + + if (!user_mode(regs)) { + /* kprobe_running() needs smp_processor_id() */ + preempt_disable(); + if (kprobe_running() && kprobes_fault_handler(regs, trap)) + ret = 1; + preempt_enable(); + } -static inline int notify_page_fault(enum die_val val, const char *str, - struct pt_regs *regs, long err, int trap, int sig) -{ - struct die_args args = { - .regs = regs, - .str = str, - .err = err, - .trapnr = trap, - .signr = sig - }; - return atomic_notifier_call_chain(¬ify_page_fault_chain, val, &args); + return ret; } #else -static inline int notify_page_fault(enum die_val val, const char *str, - struct pt_regs *regs, long err, int trap, int sig) +static inline int notify_page_fault(struct pt_regs *regs, int trap) { - return NOTIFY_DONE; + return 0; } #endif @@ -117,8 +105,7 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re /* * This is to handle the kprobes on user space access instructions */ - if (notify_page_fault(DIE_PAGE_FAULT, "page fault", regs, code, TRAP_BRKPT, - SIGSEGV) == NOTIFY_STOP) + if (notify_page_fault(regs, TRAP_BRKPT)) return; down_read(&mm->mmap_sem); diff --git a/arch/ia64/sn/kernel/bte.c b/arch/ia64/sn/kernel/bte.c index ff1c5560117..b362d6d6a8c 100644 --- a/arch/ia64/sn/kernel/bte.c +++ b/arch/ia64/sn/kernel/bte.c @@ -63,7 +63,7 @@ static inline void bte_start_transfer(struct bteinfo_s *bte, u64 len, u64 mode) * Use the block transfer engine to move kernel memory from src to dest * using the assigned mode. * - * Paramaters: + * Parameters: * src - physical address of the transfer source. * dest - physical address of the transfer destination. * len - number of bytes to transfer from source to dest. @@ -247,7 +247,7 @@ EXPORT_SYMBOL(bte_copy); * use the block transfer engine to move kernel * memory from src to dest using the assigned mode. * - * Paramaters: + * Parameters: * src - physical address of the transfer source. * dest - physical address of the transfer destination. * len - number of bytes to transfer from source to dest. @@ -255,7 +255,7 @@ EXPORT_SYMBOL(bte_copy); * for IBCT0/1 in the SGI documentation. * * NOTE: If the source, dest, and len are all cache line aligned, - * then it would be _FAR_ preferrable to use bte_copy instead. + * then it would be _FAR_ preferable to use bte_copy instead. */ bte_result_t bte_unaligned_copy(u64 src, u64 dest, u64 len, u64 mode) { @@ -300,7 +300,7 @@ bte_result_t bte_unaligned_copy(u64 src, u64 dest, u64 len, u64 mode) * a standard bte copy. * * One nasty exception to the above rule is when the - * source and destination are not symetrically + * source and destination are not symmetrically * mis-aligned. If the source offset from the first * cache line is different from the destination offset, * we make the first section be the entire transfer @@ -337,7 +337,7 @@ bte_result_t bte_unaligned_copy(u64 src, u64 dest, u64 len, u64 mode) if (footBcopyDest == (headBcopyDest + headBcopyLen)) { /* - * We have two contigous bcopy + * We have two contiguous bcopy * blocks. Merge them. */ headBcopyLen += footBcopyLen; @@ -375,7 +375,7 @@ bte_result_t bte_unaligned_copy(u64 src, u64 dest, u64 len, u64 mode) } else { /* - * The transfer is not symetric, we will + * The transfer is not symmetric, we will * allocate a buffer large enough for all the * data, bte_copy into that buffer and then * bcopy to the destination. diff --git a/arch/ia64/sn/kernel/bte_error.c b/arch/ia64/sn/kernel/bte_error.c index b6fcf8164f2..27c5936ccfe 100644 --- a/arch/ia64/sn/kernel/bte_error.c +++ b/arch/ia64/sn/kernel/bte_error.c @@ -105,7 +105,7 @@ int shub1_bte_error_handler(unsigned long _nodepda) } BTE_PRINTK(("eh:%p:%d Cleaning up\n", err_nodepda, smp_processor_id())); - /* Reenable both bte interfaces */ + /* Re-enable both bte interfaces */ imem.ii_imem_regval = REMOTE_HUB_L(nasid, IIO_IMEM); imem.ii_imem_fld_s.i_b0_esd = imem.ii_imem_fld_s.i_b1_esd = 1; REMOTE_HUB_S(nasid, IIO_IMEM, imem.ii_imem_regval); @@ -243,7 +243,7 @@ bte_crb_error_handler(cnodeid_t cnode, int btenum, /* * The caller has already figured out the error type, we save that - * in the bte handle structure for the thread excercising the + * in the bte handle structure for the thread exercising the * interface to consume. */ bte->bh_error = ioe->ie_errortype + BTEFAIL_OFFSET; diff --git a/arch/ia64/sn/kernel/io_common.c b/arch/ia64/sn/kernel/io_common.c index 7ed72d3faf7..787ed642dd4 100644 --- a/arch/ia64/sn/kernel/io_common.c +++ b/arch/ia64/sn/kernel/io_common.c @@ -479,7 +479,7 @@ sn_io_early_init(void) } /* - * prime sn_pci_provider[]. Individial provider init routines will + * prime sn_pci_provider[]. Individual provider init routines will * override their respective default entries. */ diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c index a9bed5ca2ed..a574fcd163d 100644 --- a/arch/ia64/sn/kernel/setup.c +++ b/arch/ia64/sn/kernel/setup.c @@ -167,7 +167,7 @@ void __init early_sn_setup(void) * IO on SN2 is done via SAL calls, early_printk won't work without this. * * This code duplicates some of the ACPI table parsing that is in efi.c & sal.c. - * Any changes to those file may have to be made hereas well. + * Any changes to those file may have to be made here as well. */ efi_systab = (efi_system_table_t *) __va(ia64_boot_param->efi_systab); config_tables = __va(efi_systab->tables); diff --git a/arch/ia64/sn/kernel/sn2/sn2_smp.c b/arch/ia64/sn/kernel/sn2/sn2_smp.c index 5d318b579fb..033c8a9f000 100644 --- a/arch/ia64/sn/kernel/sn2/sn2_smp.c +++ b/arch/ia64/sn/kernel/sn2/sn2_smp.c @@ -104,7 +104,7 @@ static inline unsigned long wait_piowc(void) * * SN2 PIO writes from separate CPUs are not guaranteed to arrive in order. * Context switching user threads which have memory-mapped MMIO may cause - * PIOs to issue from seperate CPUs, thus the PIO writes must be drained + * PIOs to issue from separate CPUs, thus the PIO writes must be drained * from the previous CPU's Shub before execution resumes on the new CPU. */ void sn_migrate(struct task_struct *task) diff --git a/arch/ia64/sn/kernel/xpc_channel.c b/arch/ia64/sn/kernel/xpc_channel.c index c08db9c2375..44ccc0d789c 100644 --- a/arch/ia64/sn/kernel/xpc_channel.c +++ b/arch/ia64/sn/kernel/xpc_channel.c @@ -293,7 +293,7 @@ xpc_pull_remote_cachelines(struct xpc_partition *part, void *dst, /* - * Pull the remote per partititon specific variables from the specified + * Pull the remote per partition specific variables from the specified * partition. */ enum xpc_retval @@ -461,7 +461,7 @@ xpc_allocate_local_msgqueue(struct xpc_channel *ch) // >>> may want to check for ch->flags & XPC_C_DISCONNECTING between // >>> iterations of the for-loop, bail if set? - // >>> should we impose a minumum #of entries? like 4 or 8? + // >>> should we impose a minimum #of entries? like 4 or 8? for (nentries = ch->local_nentries; nentries > 0; nentries--) { nbytes = nentries * ch->msg_size; @@ -514,7 +514,7 @@ xpc_allocate_remote_msgqueue(struct xpc_channel *ch) // >>> may want to check for ch->flags & XPC_C_DISCONNECTING between // >>> iterations of the for-loop, bail if set? - // >>> should we impose a minumum #of entries? like 4 or 8? + // >>> should we impose a minimum #of entries? like 4 or 8? for (nentries = ch->remote_nentries; nentries > 0; nentries--) { nbytes = nentries * ch->msg_size; @@ -1478,7 +1478,7 @@ xpc_teardown_infrastructure(struct xpc_partition *part) /* - * Before proceding with the teardown we have to wait until all + * Before proceeding with the teardown we have to wait until all * existing references cease. */ wait_event(part->teardown_wq, (atomic_read(&part->references) == 0)); diff --git a/arch/ia64/sn/kernel/xpnet.c b/arch/ia64/sn/kernel/xpnet.c index da721353097..e58fcadff2e 100644 --- a/arch/ia64/sn/kernel/xpnet.c +++ b/arch/ia64/sn/kernel/xpnet.c @@ -531,7 +531,7 @@ xpnet_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) dev_dbg(xpnet, "destination Partitions mask (dp) = 0x%lx\n", dp); /* - * If we wanted to allow promiscous mode to work like an + * If we wanted to allow promiscuous mode to work like an * unswitched network, this would be a good point to OR in a * mask of partitions which should be receiving all packets. */ diff --git a/arch/ia64/sn/pci/pci_dma.c b/arch/ia64/sn/pci/pci_dma.c index 7a291a27151..d79ddacfba2 100644 --- a/arch/ia64/sn/pci/pci_dma.c +++ b/arch/ia64/sn/pci/pci_dma.c @@ -333,7 +333,7 @@ int sn_pci_legacy_read(struct pci_bus *bus, u16 port, u32 *val, u8 size) /* * First, try the SN_SAL_IOIF_PCI_SAFE SAL call which can work * around hw issues at the pci bus level. SGI proms older than - * 4.10 don't implment this. + * 4.10 don't implement this. */ SAL_CALL(isrv, SN_SAL_IOIF_PCI_SAFE, @@ -348,7 +348,7 @@ int sn_pci_legacy_read(struct pci_bus *bus, u16 port, u32 *val, u8 size) /* * If the above failed, retry using the SAL_PROBE call which should * be present in all proms (but which cannot work round PCI chipset - * bugs). This code is retained for compatability with old + * bugs). This code is retained for compatibility with old * pre-4.10 proms, and should be removed at some point in the future. */ @@ -379,7 +379,7 @@ int sn_pci_legacy_write(struct pci_bus *bus, u16 port, u32 val, u8 size) /* * First, try the SN_SAL_IOIF_PCI_SAFE SAL call which can work * around hw issues at the pci bus level. SGI proms older than - * 4.10 don't implment this. + * 4.10 don't implement this. */ SAL_CALL(isrv, SN_SAL_IOIF_PCI_SAFE, @@ -394,7 +394,7 @@ int sn_pci_legacy_write(struct pci_bus *bus, u16 port, u32 val, u8 size) /* * If the above failed, retry using the SAL_PROBE call which should * be present in all proms (but which cannot work round PCI chipset - * bugs). This code is retained for compatability with old + * bugs). This code is retained for compatibility with old * pre-4.10 proms, and should be removed at some point in the future. */ diff --git a/arch/ia64/sn/pci/pcibr/pcibr_ate.c b/arch/ia64/sn/pci/pcibr/pcibr_ate.c index 935029fc400..239b3cedcf2 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_ate.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_ate.c @@ -30,7 +30,7 @@ static void mark_ate(struct ate_resource *ate_resource, int start, int number, /* * find_free_ate: Find the first free ate index starting from the given - * index for the desired consequtive count. + * index for the desired consecutive count. */ static int find_free_ate(struct ate_resource *ate_resource, int start, int count) @@ -88,7 +88,7 @@ static inline int alloc_ate_resource(struct ate_resource *ate_resource, return -1; /* - * Find the required number of free consequtive ates. + * Find the required number of free consecutive ates. */ start_index = find_free_ate(ate_resource, ate_resource->lowest_free_index, @@ -105,7 +105,7 @@ static inline int alloc_ate_resource(struct ate_resource *ate_resource, /* * Allocate "count" contiguous Bridge Address Translation Entries * on the specified bridge to be used for PCI to XTALK mappings. - * Indices in rm map range from 1..num_entries. Indicies returned + * Indices in rm map range from 1..num_entries. Indices returned * to caller range from 0..num_entries-1. * * Return the start index on success, -1 on failure. diff --git a/arch/ia64/sn/pci/pcibr/pcibr_dma.c b/arch/ia64/sn/pci/pcibr/pcibr_dma.c index 95af40cb22f..e626e50a938 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_dma.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_dma.c @@ -201,7 +201,7 @@ pcibr_dmatrans_direct32(struct pcidev_info * info, } /* - * Wrapper routine for free'ing DMA maps + * Wrapper routine for freeing DMA maps * DMA mappings for Direct 64 and 32 do not have any DMA maps. */ void diff --git a/arch/ia64/sn/pci/tioca_provider.c b/arch/ia64/sn/pci/tioca_provider.c index 8a2cb4e691f..b9bedbd6e1d 100644 --- a/arch/ia64/sn/pci/tioca_provider.c +++ b/arch/ia64/sn/pci/tioca_provider.c @@ -223,7 +223,7 @@ tioca_fastwrite_enable(struct tioca_kernel *tioca_kern) /* * Scan all vga controllers on this bus making sure they all - * suport FW. If not, return. + * support FW. If not, return. */ list_for_each_entry(pdev, tioca_kern->ca_devices, bus_list) { @@ -364,7 +364,7 @@ tioca_dma_d48(struct pci_dev *pdev, u64 paddr) * @req_size: len (bytes) to map * * Map @paddr into CA address space using the GART mechanism. The mapped - * dma_addr_t is guarenteed to be contiguous in CA bus space. + * dma_addr_t is guaranteed to be contiguous in CA bus space. */ static dma_addr_t tioca_dma_mapped(struct pci_dev *pdev, u64 paddr, size_t req_size) @@ -526,7 +526,7 @@ tioca_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count, int dma_flags) return 0; /* - * If card is 64 or 48 bit addresable, use a direct mapping. 32 + * If card is 64 or 48 bit addressable, use a direct mapping. 32 * bit direct is so restrictive w.r.t. where the memory resides that * we don't use it even though CA has some support. */ diff --git a/arch/ia64/sn/pci/tioce_provider.c b/arch/ia64/sn/pci/tioce_provider.c index 35f854fb612..f4c0b961a93 100644 --- a/arch/ia64/sn/pci/tioce_provider.c +++ b/arch/ia64/sn/pci/tioce_provider.c @@ -256,9 +256,9 @@ pcidev_to_tioce(struct pci_dev *pdev, struct tioce __iomem **base, * @ct_addr: the coretalk address to map * @len: number of bytes to map * - * Given the addressing type, set up various paramaters that define the + * Given the addressing type, set up various parameters that define the * ATE pool to use. Search for a contiguous block of entries to cover the - * length, and if enough resources exist, fill in the ATE's and construct a + * length, and if enough resources exist, fill in the ATEs and construct a * tioce_dmamap struct to track the mapping. */ static u64 @@ -581,8 +581,8 @@ tioce_do_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count, */ if (!mapaddr && !barrier && dma_mask >= 0xffffffffffUL) { /* - * We have two options for 40-bit mappings: 16GB "super" ATE's - * and 64MB "regular" ATE's. We'll try both if needed for a + * We have two options for 40-bit mappings: 16GB "super" ATEs + * and 64MB "regular" ATEs. We'll try both if needed for a * given mapping but which one we try first depends on the * size. For requests >64MB, prefer to use a super page with * regular as the fallback. Otherwise, try in the reverse order. @@ -687,8 +687,8 @@ tioce_error_intr_handler(int irq, void *arg) } /** - * tioce_reserve_m32 - reserve M32 ate's for the indicated address range - * @tioce_kernel: TIOCE context to reserve ate's for + * tioce_reserve_m32 - reserve M32 ATEs for the indicated address range + * @tioce_kernel: TIOCE context to reserve ATEs for * @base: starting bus address to reserve * @limit: last bus address to reserve * @@ -763,7 +763,7 @@ tioce_kern_init(struct tioce_common *tioce_common) /* * Set PMU pagesize to the largest size available, and zero out - * the ate's. + * the ATEs. */ tioce_mmr = (struct tioce __iomem *)tioce_common->ce_pcibus.bs_base; @@ -784,7 +784,7 @@ tioce_kern_init(struct tioce_common *tioce_common) } /* - * Reserve ATE's corresponding to reserved address ranges. These + * Reserve ATEs corresponding to reserved address ranges. These * include: * * Memory space covered by each PPB mem base/limit register diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile index 6bf6fb65bc2..c749dccacc3 100644 --- a/arch/sparc64/kernel/Makefile +++ b/arch/sparc64/kernel/Makefile @@ -12,7 +12,7 @@ obj-y := process.o setup.o cpu.o idprom.o \ irq.o ptrace.o time.o sys_sparc.o signal.o \ unaligned.o central.o pci.o starfire.o semaphore.o \ power.o sbus.o iommu_common.o sparc64_ksyms.o chmc.o \ - visemul.o prom.o of_device.o + visemul.o prom.o of_device.o hvapi.o obj-$(CONFIG_STACKTRACE) += stacktrace.o obj-$(CONFIG_PCI) += ebus.o isa.o pci_common.o pci_iommu.o \ diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S index c15a3edcb82..732b77cb71f 100644 --- a/arch/sparc64/kernel/entry.S +++ b/arch/sparc64/kernel/entry.S @@ -1843,3 +1843,97 @@ sun4v_cpu_state: mov %o1, %o0 1: retl nop + + /* %o0: API group number + * %o1: pointer to unsigned long major number storage + * %o2: pointer to unsigned long minor number storage + * + * returns %o0: status + */ + .globl sun4v_get_version +sun4v_get_version: + mov HV_CORE_GET_VER, %o5 + mov %o1, %o3 + mov %o2, %o4 + ta HV_CORE_TRAP + stx %o1, [%o3] + retl + stx %o2, [%o4] + + /* %o0: API group number + * %o1: desired major number + * %o2: desired minor number + * %o3: pointer to unsigned long actual minor number storage + * + * returns %o0: status + */ + .globl sun4v_set_version +sun4v_set_version: + mov HV_CORE_SET_VER, %o5 + mov %o3, %o4 + ta HV_CORE_TRAP + retl + stx %o1, [%o4] + + /* %o0: pointer to unsigned long status + * + * returns %o0: signed character + */ + .globl sun4v_con_getchar +sun4v_con_getchar: + mov %o0, %o4 + mov HV_FAST_CONS_GETCHAR, %o5 + clr %o0 + clr %o1 + ta HV_FAST_TRAP + stx %o0, [%o4] + retl + sra %o1, 0, %o0 + + /* %o0: signed long character + * + * returns %o0: status + */ + .globl sun4v_con_putchar +sun4v_con_putchar: + mov HV_FAST_CONS_PUTCHAR, %o5 + ta HV_FAST_TRAP + retl + sra %o0, 0, %o0 + + /* %o0: buffer real address + * %o1: buffer size + * %o2: pointer to unsigned long bytes_read + * + * returns %o0: status + */ + .globl sun4v_con_read +sun4v_con_read: + mov %o2, %o4 + mov HV_FAST_CONS_READ, %o5 + ta HV_FAST_TRAP + brnz %o0, 1f + cmp %o1, -1 /* break */ + be,a,pn %icc, 1f + mov %o1, %o0 + cmp %o1, -2 /* hup */ + be,a,pn %icc, 1f + mov %o1, %o0 + stx %o1, [%o4] +1: retl + nop + + /* %o0: buffer real address + * %o1: buffer size + * %o2: pointer to unsigned long bytes_written + * + * returns %o0: status + */ + .globl sun4v_con_write +sun4v_con_write: + mov %o2, %o4 + mov HV_FAST_CONS_WRITE, %o5 + ta HV_FAST_TRAP + stx %o1, [%o4] + retl + nop diff --git a/arch/sparc64/kernel/hvapi.c b/arch/sparc64/kernel/hvapi.c new file mode 100644 index 00000000000..f03ffc829c7 --- /dev/null +++ b/arch/sparc64/kernel/hvapi.c @@ -0,0 +1,189 @@ +/* hvapi.c: Hypervisor API management. + * + * Copyright (C) 2007 David S. Miller <davem@davemloft.net> + */ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/slab.h> + +#include <asm/hypervisor.h> +#include <asm/oplib.h> + +/* If the hypervisor indicates that the API setting + * calls are unsupported, by returning HV_EBADTRAP or + * HV_ENOTSUPPORTED, we assume that API groups with the + * PRE_API flag set are major 1 minor 0. + */ +struct api_info { + unsigned long group; + unsigned long major; + unsigned long minor; + unsigned int refcnt; + unsigned int flags; +#define FLAG_PRE_API 0x00000001 +}; + +static struct api_info api_table[] = { + { .group = HV_GRP_SUN4V, .flags = FLAG_PRE_API }, + { .group = HV_GRP_CORE, .flags = FLAG_PRE_API }, + { .group = HV_GRP_INTR, }, + { .group = HV_GRP_SOFT_STATE, }, + { .group = HV_GRP_PCI, .flags = FLAG_PRE_API }, + { .group = HV_GRP_LDOM, }, + { .group = HV_GRP_SVC_CHAN, .flags = FLAG_PRE_API }, + { .group = HV_GRP_NCS, .flags = FLAG_PRE_API }, + { .group = HV_GRP_NIAG_PERF, .flags = FLAG_PRE_API }, + { .group = HV_GRP_FIRE_PERF, }, + { .group = HV_GRP_DIAG, .flags = FLAG_PRE_API }, +}; + +static DEFINE_SPINLOCK(hvapi_lock); + +static struct api_info *__get_info(unsigned long group) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(api_table); i++) { + if (api_table[i].group == group) + return &api_table[i]; + } + return NULL; +} + +static void __get_ref(struct api_info *p) +{ + p->refcnt++; +} + +static void __put_ref(struct api_info *p) +{ + if (--p->refcnt == 0) { + unsigned long ignore; + + sun4v_set_version(p->group, 0, 0, &ignore); + p->major = p->minor = 0; + } +} + +/* Register a hypervisor API specification. It indicates the + * API group and desired major+minor. + * + * If an existing API registration exists '0' (success) will + * be returned if it is compatible with the one being registered. + * Otherwise a negative error code will be returned. + * + * Otherwise an attempt will be made to negotiate the requested + * API group/major/minor with the hypervisor, and errors returned + * if that does not succeed. + */ +int sun4v_hvapi_register(unsigned long group, unsigned long major, + unsigned long *minor) +{ + struct api_info *p; + unsigned long flags; + int ret; + + spin_lock_irqsave(&hvapi_lock, flags); + p = __get_info(group); + ret = -EINVAL; + if (p) { + if (p->refcnt) { + ret = -EINVAL; + if (p->major == major) { + *minor = p->minor; + ret = 0; + } + } else { + unsigned long actual_minor; + unsigned long hv_ret; + + hv_ret = sun4v_set_version(group, major, *minor, + &actual_minor); + ret = -EINVAL; + if (hv_ret == HV_EOK) { + *minor = actual_minor; + p->major = major; + p->minor = actual_minor; + ret = 0; + } else if (hv_ret == HV_EBADTRAP || + HV_ENOTSUPPORTED) { + if (p->flags & FLAG_PRE_API) { + if (major == 1) { + p->major = 1; + p->minor = 0; + *minor = 0; + ret = 0; + } + } + } + } + + if (ret == 0) + __get_ref(p); + } + spin_unlock_irqrestore(&hvapi_lock, flags); + + return ret; +} +EXPORT_SYMBOL(sun4v_hvapi_register); + +void sun4v_hvapi_unregister(unsigned long group) +{ + struct api_info *p; + unsigned long flags; + + spin_lock_irqsave(&hvapi_lock, flags); + p = __get_info(group); + if (p) + __put_ref(p); + spin_unlock_irqrestore(&hvapi_lock, flags); +} +EXPORT_SYMBOL(sun4v_hvapi_unregister); + +int sun4v_hvapi_get(unsigned long group, + unsigned long *major, + unsigned long *minor) +{ + struct api_info *p; + unsigned long flags; + int ret; + + spin_lock_irqsave(&hvapi_lock, flags); + ret = -EINVAL; + p = __get_info(group); + if (p && p->refcnt) { + *major = p->major; + *minor = p->minor; + ret = 0; + } + spin_unlock_irqrestore(&hvapi_lock, flags); + + return ret; +} +EXPORT_SYMBOL(sun4v_hvapi_get); + +void __init sun4v_hvapi_init(void) +{ + unsigned long group, major, minor; + + group = HV_GRP_SUN4V; + major = 1; + minor = 0; + if (sun4v_hvapi_register(group, major, &minor)) + goto bad; + + group = HV_GRP_CORE; + major = 1; + minor = 1; + if (sun4v_hvapi_register(group, major, &minor)) + goto bad; + + return; + +bad: + prom_printf("HVAPI: Cannot register API group " + "%lx with major(%u) minor(%u)\n", + group, major, minor); + prom_halt(); +} diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c index 451028341c7..dea9c3c9ec5 100644 --- a/arch/sparc64/kernel/setup.c +++ b/arch/sparc64/kernel/setup.c @@ -269,6 +269,7 @@ void __init per_cpu_patch(void) void __init sun4v_patch(void) { + extern void sun4v_hvapi_init(void); struct sun4v_1insn_patch_entry *p1; struct sun4v_2insn_patch_entry *p2; @@ -300,6 +301,8 @@ void __init sun4v_patch(void) p2++; } + + sun4v_hvapi_init(); } #ifdef CONFIG_SMP diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c index 02c0d52c9f7..7bfbad57879 100644 --- a/drivers/parport/parport_pc.c +++ b/drivers/parport/parport_pc.c @@ -51,6 +51,7 @@ #include <linux/ioport.h> #include <linux/kernel.h> #include <linux/slab.h> +#include <linux/dma-mapping.h> #include <linux/pci.h> #include <linux/pnp.h> #include <linux/platform_device.h> diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c index c3a6bd2e795..96557e6dba6 100644 --- a/drivers/serial/sunhv.c +++ b/drivers/serial/sunhv.c @@ -1,6 +1,6 @@ /* sunhv.c: Serial driver for SUN4V hypervisor console. * - * Copyright (C) 2006 David S. Miller (davem@davemloft.net) + * Copyright (C) 2006, 2007 David S. Miller (davem@davemloft.net) */ #include <linux/module.h> @@ -35,57 +35,51 @@ #define CON_BREAK ((long)-1) #define CON_HUP ((long)-2) -static inline long hypervisor_con_getchar(long *status) -{ - register unsigned long func asm("%o5"); - register unsigned long arg0 asm("%o0"); - register unsigned long arg1 asm("%o1"); - - func = HV_FAST_CONS_GETCHAR; - arg0 = 0; - arg1 = 0; - __asm__ __volatile__("ta %6" - : "=&r" (func), "=&r" (arg0), "=&r" (arg1) - : "0" (func), "1" (arg0), "2" (arg1), - "i" (HV_FAST_TRAP)); +#define IGNORE_BREAK 0x1 +#define IGNORE_ALL 0x2 - *status = arg0; +static char *con_write_page; +static char *con_read_page; - return (long) arg1; -} +static int hung_up = 0; -static inline long hypervisor_con_putchar(long ch) +static void transmit_chars_putchar(struct uart_port *port, struct circ_buf *xmit) { - register unsigned long func asm("%o5"); - register unsigned long arg0 asm("%o0"); + while (!uart_circ_empty(xmit)) { + long status = sun4v_con_putchar(xmit->buf[xmit->tail]); - func = HV_FAST_CONS_PUTCHAR; - arg0 = ch; - __asm__ __volatile__("ta %4" - : "=&r" (func), "=&r" (arg0) - : "0" (func), "1" (arg0), "i" (HV_FAST_TRAP)); + if (status != HV_EOK) + break; - return (long) arg0; + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); + port->icount.tx++; + } } -#define IGNORE_BREAK 0x1 -#define IGNORE_ALL 0x2 +static void transmit_chars_write(struct uart_port *port, struct circ_buf *xmit) +{ + while (!uart_circ_empty(xmit)) { + unsigned long ra = __pa(xmit->buf + xmit->tail); + unsigned long len, status, sent; -static int hung_up = 0; + len = CIRC_CNT_TO_END(xmit->head, xmit->tail, + UART_XMIT_SIZE); + status = sun4v_con_write(ra, len, &sent); + if (status != HV_EOK) + break; + xmit->tail = (xmit->tail + sent) & (UART_XMIT_SIZE - 1); + port->icount.tx += sent; + } +} -static struct tty_struct *receive_chars(struct uart_port *port) +static int receive_chars_getchar(struct uart_port *port, struct tty_struct *tty) { - struct tty_struct *tty = NULL; int saw_console_brk = 0; int limit = 10000; - if (port->info != NULL) /* Unopened serial console */ - tty = port->info->tty; - while (limit-- > 0) { long status; - long c = hypervisor_con_getchar(&status); - unsigned char flag; + long c = sun4v_con_getchar(&status); if (status == HV_EWOULDBLOCK) break; @@ -110,27 +104,90 @@ static struct tty_struct *receive_chars(struct uart_port *port) continue; } - flag = TTY_NORMAL; port->icount.rx++; - if (c == CON_BREAK) { - port->icount.brk++; - if (uart_handle_break(port)) - continue; - flag = TTY_BREAK; - } if (uart_handle_sysrq_char(port, c)) continue; - if ((port->ignore_status_mask & IGNORE_ALL) || - ((port->ignore_status_mask & IGNORE_BREAK) && - (c == CON_BREAK))) + tty_insert_flip_char(tty, c, TTY_NORMAL); + } + + return saw_console_brk; +} + +static int receive_chars_read(struct uart_port *port, struct tty_struct *tty) +{ + int saw_console_brk = 0; + int limit = 10000; + + while (limit-- > 0) { + unsigned long ra = __pa(con_read_page); + unsigned long bytes_read, i; + long stat = sun4v_con_read(ra, PAGE_SIZE, &bytes_read); + + if (stat != HV_EOK) { + bytes_read = 0; + + if (stat == CON_BREAK) { + if (uart_handle_break(port)) + continue; + saw_console_brk = 1; + *con_read_page = 0; + bytes_read = 1; + } else if (stat == CON_HUP) { + hung_up = 1; + uart_handle_dcd_change(port, 0); + continue; + } else { + /* HV_EWOULDBLOCK, etc. */ + break; + } + } + + if (hung_up) { + hung_up = 0; + uart_handle_dcd_change(port, 1); + } + + for (i = 0; i < bytes_read; i++) + uart_handle_sysrq_char(port, con_read_page[i]); + + if (tty == NULL) continue; - tty_insert_flip_char(tty, c, flag); + port->icount.rx += bytes_read; + + tty_insert_flip_string(tty, con_read_page, bytes_read); } - if (saw_console_brk) + return saw_console_brk; +} + +struct sunhv_ops { + void (*transmit_chars)(struct uart_port *port, struct circ_buf *xmit); + int (*receive_chars)(struct uart_port *port, struct tty_struct *tty); +}; + +static struct sunhv_ops bychar_ops = { + .transmit_chars = transmit_chars_putchar, + .receive_chars = receive_chars_getchar, +}; + +static struct sunhv_ops bywrite_ops = { + .transmit_chars = transmit_chars_write, + .receive_chars = receive_chars_read, +}; + +static struct sunhv_ops *sunhv_ops = &bychar_ops; + +static struct tty_struct *receive_chars(struct uart_port *port) +{ + struct tty_struct *tty = NULL; + + if (port->info != NULL) /* Unopened serial console */ + tty = port->info->tty; + + if (sunhv_ops->receive_chars(port, tty)) sun_do_break(); return tty; @@ -147,15 +204,7 @@ static void transmit_chars(struct uart_port *port) if (uart_circ_empty(xmit) || uart_tx_stopped(port)) return; - while (!uart_circ_empty(xmit)) { - long status = hypervisor_con_putchar(xmit->buf[xmit->tail]); - - if (status != HV_EOK) - break; - - xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); - port->icount.tx++; - } + sunhv_ops->transmit_chars(port, xmit); if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(port); @@ -212,7 +261,7 @@ static void sunhv_start_tx(struct uart_port *port) struct circ_buf *xmit = &port->info->xmit; while (!uart_circ_empty(xmit)) { - long status = hypervisor_con_putchar(xmit->buf[xmit->tail]); + long status = sun4v_con_putchar(xmit->buf[xmit->tail]); if (status != HV_EOK) break; @@ -231,9 +280,10 @@ static void sunhv_send_xchar(struct uart_port *port, char ch) spin_lock_irqsave(&port->lock, flags); while (limit-- > 0) { - long status = hypervisor_con_putchar(ch); + long status = sun4v_con_putchar(ch); if (status == HV_EOK) break; + udelay(1); } spin_unlock_irqrestore(&port->lock, flags); @@ -254,15 +304,15 @@ static void sunhv_break_ctl(struct uart_port *port, int break_state) { if (break_state) { unsigned long flags; - int limit = 1000000; + int limit = 10000; spin_lock_irqsave(&port->lock, flags); while (limit-- > 0) { - long status = hypervisor_con_putchar(CON_BREAK); + long status = sun4v_con_putchar(CON_BREAK); if (status == HV_EOK) break; - udelay(2); + udelay(1); } spin_unlock_irqrestore(&port->lock, flags); @@ -359,38 +409,99 @@ static struct uart_driver sunhv_reg = { static struct uart_port *sunhv_port; -static inline void sunhv_console_putchar(struct uart_port *port, char c) +/* Copy 's' into the con_write_page, decoding "\n" into + * "\r\n" along the way. We have to return two lengths + * because the caller needs to know how much to advance + * 's' and also how many bytes to output via con_write_page. + */ +static int fill_con_write_page(const char *s, unsigned int n, + unsigned long *page_bytes) +{ + const char *orig_s = s; + char *p = con_write_page; + int left = PAGE_SIZE; + + while (n--) { + if (*s == '\n') { + if (left < 2) + break; + *p++ = '\r'; + left--; + } else if (left < 1) + break; + *p++ = *s++; + left--; + } + *page_bytes = p - con_write_page; + return s - orig_s; +} + +static void sunhv_console_write_paged(struct console *con, const char *s, unsigned n) { + struct uart_port *port = sunhv_port; unsigned long flags; - int limit = 1000000; spin_lock_irqsave(&port->lock, flags); + while (n > 0) { + unsigned long ra = __pa(con_write_page); + unsigned long page_bytes; + unsigned int cpy = fill_con_write_page(s, n, + &page_bytes); + + n -= cpy; + s += cpy; + while (page_bytes > 0) { + unsigned long written; + int limit = 1000000; + + while (limit--) { + unsigned long stat; + + stat = sun4v_con_write(ra, page_bytes, + &written); + if (stat == HV_EOK) + break; + udelay(1); + } + if (limit <= 0) + break; + page_bytes -= written; + ra += written; + } + } + spin_unlock_irqrestore(&port->lock, flags); +} + +static inline void sunhv_console_putchar(struct uart_port *port, char c) +{ + int limit = 1000000; while (limit-- > 0) { - long status = hypervisor_con_putchar(c); + long status = sun4v_con_putchar(c); if (status == HV_EOK) break; - udelay(2); + udelay(1); } - - spin_unlock_irqrestore(&port->lock, flags); } -static void sunhv_console_write(struct console *con, const char *s, unsigned n) +static void sunhv_console_write_bychar(struct console *con, const char *s, unsigned n) { struct uart_port *port = sunhv_port; + unsigned long flags; int i; + spin_lock_irqsave(&port->lock, flags); for (i = 0; i < n; i++) { if (*s == '\n') sunhv_console_putchar(port, '\r'); sunhv_console_putchar(port, *s++); } + spin_unlock_irqrestore(&port->lock, flags); } static struct console sunhv_console = { .name = "ttyHV", - .write = sunhv_console_write, + .write = sunhv_console_write_bychar, .device = uart_console_device, .flags = CON_PRINTBUFFER, .index = -1, @@ -410,6 +521,7 @@ static inline struct console *SUNHV_CONSOLE(void) static int __devinit hv_probe(struct of_device *op, const struct of_device_id *match) { struct uart_port *port; + unsigned long minor; int err; if (op->irqs[0] == 0xffffffff) @@ -419,6 +531,22 @@ static int __devinit hv_probe(struct of_device *op, const struct of_device_id *m if (unlikely(!port)) return -ENOMEM; + minor = 1; + if (sun4v_hvapi_register(HV_GRP_CORE, 1, &minor) == 0 && + minor >= 1) { + err = -ENOMEM; + con_write_page = kzalloc(PAGE_SIZE, GFP_KERNEL); + if (!con_write_page) + goto out_free_port; + + con_read_page = kzalloc(PAGE_SIZE, GFP_KERNEL); + if (!con_read_page) + goto out_free_con_write_page; + + sunhv_console.write = sunhv_console_write_paged; + sunhv_ops = &bywrite_ops; + } + sunhv_port = port; port->line = 0; @@ -437,7 +565,7 @@ static int __devinit hv_probe(struct of_device *op, const struct of_device_id *m err = uart_register_driver(&sunhv_reg); if (err) - goto out_free_port; + goto out_free_con_read_page; sunhv_reg.tty_driver->name_base = sunhv_reg.minor - 64; sunserial_current_minor += 1; @@ -463,6 +591,12 @@ out_unregister_driver: sunserial_current_minor -= 1; uart_unregister_driver(&sunhv_reg); +out_free_con_read_page: + kfree(con_read_page); + +out_free_con_write_page: + kfree(con_write_page); + out_free_port: kfree(port); sunhv_port = NULL; diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index c0a6dce800a..225d6b2f82d 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c @@ -484,7 +484,7 @@ static int spidev_probe(struct spi_device *spi) * Reusing minors is fine so long as udev or mdev is working. */ mutex_lock(&device_list_lock); - minor = find_first_zero_bit(minors, ARRAY_SIZE(minors)); + minor = find_first_zero_bit(minors, N_SPI_MINORS); if (minor < N_SPI_MINORS) { spidev->dev.parent = &spi->dev; spidev->dev.class = &spidev_class; diff --git a/fs/afs/super.c b/fs/afs/super.c index 579af632c8e..370cecc910d 100644 --- a/fs/afs/super.c +++ b/fs/afs/super.c @@ -47,7 +47,6 @@ struct file_system_type afs_fs_type = { static const struct super_operations afs_super_ops = { .statfs = afs_statfs, .alloc_inode = afs_alloc_inode, - .drop_inode = generic_delete_inode, .write_inode = afs_write_inode, .destroy_inode = afs_destroy_inode, .clear_inode = afs_clear_inode, diff --git a/fs/afs/write.c b/fs/afs/write.c index 28f37516c12..a03b92a0fe1 100644 --- a/fs/afs/write.c +++ b/fs/afs/write.c @@ -206,7 +206,6 @@ int afs_prepare_write(struct file *file, struct page *page, _leave(" = %d [prep]", ret); return ret; } - SetPageUptodate(page); } try_again: @@ -311,8 +310,8 @@ int afs_commit_write(struct file *file, struct page *page, spin_unlock(&vnode->writeback_lock); } + SetPageUptodate(page); set_page_dirty(page); - if (PageDirty(page)) _debug("dirtied"); diff --git a/include/asm-avr32/arch-at32ap/board.h b/include/asm-avr32/arch-at32ap/board.h index 1a7b07d436f..9fd2e32f84b 100644 --- a/include/asm-avr32/arch-at32ap/board.h +++ b/include/asm-avr32/arch-at32ap/board.h @@ -30,11 +30,9 @@ struct spi_board_info; struct platform_device * at32_add_device_spi(unsigned int id, struct spi_board_info *b, unsigned int n); -struct lcdc_platform_data { - unsigned long fbmem_start; - unsigned long fbmem_size; -}; +struct atmel_lcdfb_info; struct platform_device * -at32_add_device_lcdc(unsigned int id, struct lcdc_platform_data *data); +at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data, + unsigned long fbmem_start, unsigned long fbmem_len); #endif /* __ASM_ARCH_BOARD_H */ diff --git a/include/asm-avr32/kdebug.h b/include/asm-avr32/kdebug.h index de419278fc3..7f54e2b15d1 100644 --- a/include/asm-avr32/kdebug.h +++ b/include/asm-avr32/kdebug.h @@ -5,13 +5,22 @@ /* Grossly misnamed. */ enum die_val { - DIE_FAULT, DIE_BREAKPOINT, DIE_SSTEP, - DIE_PAGE_FAULT, }; -int register_page_fault_notifier(struct notifier_block *nb); -int unregister_page_fault_notifier(struct notifier_block *nb); +/* + * These are only here because kprobes.c wants them to implement a + * blatant layering violation. Will hopefully go away soon once all + * architectures are updated. + */ +static inline int register_page_fault_notifier(struct notifier_block *nb) +{ + return 0; +} +static inline int unregister_page_fault_notifier(struct notifier_block *nb) +{ + return 0; +} #endif /* __ASM_AVR32_KDEBUG_H */ diff --git a/include/asm-avr32/kprobes.h b/include/asm-avr32/kprobes.h index 09a5cbe2f89..190a6377c80 100644 --- a/include/asm-avr32/kprobes.h +++ b/include/asm-avr32/kprobes.h @@ -26,6 +26,7 @@ struct arch_specific_insn { kprobe_opcode_t insn[MAX_INSN_SIZE]; }; +extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr); extern int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, void *data); diff --git a/include/asm-avr32/unistd.h b/include/asm-avr32/unistd.h index 2418cce624c..3b4e35b55c8 100644 --- a/include/asm-avr32/unistd.h +++ b/include/asm-avr32/unistd.h @@ -296,9 +296,12 @@ #define __NR_shmctl 277 #define __NR_utimensat 278 +#define __NR_signalfd 279 +#define __NR_timerfd 280 +#define __NR_eventfd 281 #ifdef __KERNEL__ -#define NR_syscalls 279 +#define NR_syscalls 282 #define __ARCH_WANT_IPC_PARSE_VERSION diff --git a/include/asm-ia64/kdebug.h b/include/asm-ia64/kdebug.h index ba211e011a1..320cd8e754e 100644 --- a/include/asm-ia64/kdebug.h +++ b/include/asm-ia64/kdebug.h @@ -28,14 +28,24 @@ */ #include <linux/notifier.h> -extern int register_page_fault_notifier(struct notifier_block *); -extern int unregister_page_fault_notifier(struct notifier_block *); +/* + * These are only here because kprobes.c wants them to implement a + * blatant layering violation. Will hopefully go away soon once all + * architectures are updated. + */ +static inline int register_page_fault_notifier(struct notifier_block *nb) +{ + return 0; +} +static inline int unregister_page_fault_notifier(struct notifier_block *nb) +{ + return 0; +} enum die_val { DIE_BREAK = 1, DIE_FAULT, DIE_OOPS, - DIE_PAGE_FAULT, DIE_MACHINE_HALT, DIE_MACHINE_RESTART, DIE_MCA_MONARCH_ENTER, diff --git a/include/asm-ia64/kprobes.h b/include/asm-ia64/kprobes.h index 2abc98b336f..6382e52ec22 100644 --- a/include/asm-ia64/kprobes.h +++ b/include/asm-ia64/kprobes.h @@ -120,6 +120,7 @@ struct arch_specific_insn { unsigned short slot; }; +extern int kprobes_fault_handler(struct pt_regs *regs, int trapnr); extern int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, void *data); diff --git a/include/asm-ia64/unistd.h b/include/asm-ia64/unistd.h index f049bc40ca7..d7781a2ddef 100644 --- a/include/asm-ia64/unistd.h +++ b/include/asm-ia64/unistd.h @@ -296,11 +296,14 @@ #define __NR_getcpu 1304 #define __NR_epoll_pwait 1305 #define __NR_utimensat 1306 +#define __NR_signalfd 1307 +#define __NR_timerfd 1308 +#define __NR_eventfd 1309 #ifdef __KERNEL__ -#define NR_syscalls 283 /* length of syscall table */ +#define NR_syscalls 286 /* length of syscall table */ #define __ARCH_WANT_SYS_RT_SIGACTION #define __ARCH_WANT_SYS_RT_SIGSUSPEND diff --git a/include/asm-sparc64/hypervisor.h b/include/asm-sparc64/hypervisor.h index 612bf319753..a5558c87556 100644 --- a/include/asm-sparc64/hypervisor.h +++ b/include/asm-sparc64/hypervisor.h @@ -940,6 +940,54 @@ struct hv_fault_status { */ #define HV_FAST_CONS_PUTCHAR 0x61 +/* con_read() + * TRAP: HV_FAST_TRAP + * FUNCTION: HV_FAST_CONS_READ + * ARG0: buffer real address + * ARG1: buffer size in bytes + * RET0: status + * RET1: bytes read or BREAK or HUP + * ERRORS: EWOULDBLOCK No character available. + * + * Reads characters into a buffer from the console device. If no + * character is available then an EWOULDBLOCK error is returned. + * If a character is available, then the returned status is EOK + * and the number of bytes read into the given buffer is provided + * in RET1. + * + * A virtual BREAK is represented by the 64-bit RET1 value -1. + * + * A virtual HUP signal is represented by the 64-bit RET1 value -2. + * + * If BREAK or HUP are indicated, no bytes were read into buffer. + */ +#define HV_FAST_CONS_READ 0x62 + +/* con_write() + * TRAP: HV_FAST_TRAP + * FUNCTION: HV_FAST_CONS_WRITE + * ARG0: buffer real address + * ARG1: buffer size in bytes + * RET0: status + * RET1: bytes written + * ERRORS: EWOULDBLOCK Output buffer currently full, would block + * + * Send a characters in buffer to the console device. Breaks must be + * sent using con_putchar(). + */ +#define HV_FAST_CONS_WRITE 0x63 + +#ifndef __ASSEMBLY__ +extern long sun4v_con_getchar(long *status); +extern long sun4v_con_putchar(long c); +extern long sun4v_con_read(unsigned long buffer, + unsigned long size, + unsigned long *bytes_read); +extern unsigned long sun4v_con_write(unsigned long buffer, + unsigned long size, + unsigned long *bytes_written); +#endif + /* Trap trace services. * * The hypervisor provides a trap tracing capability for privileged @@ -2121,8 +2169,41 @@ struct hv_mmu_statistics { #define HV_FAST_MMUSTAT_INFO 0x103 /* Function numbers for HV_CORE_TRAP. */ -#define HV_CORE_VER 0x00 +#define HV_CORE_SET_VER 0x00 #define HV_CORE_PUTCHAR 0x01 #define HV_CORE_EXIT 0x02 +#define HV_CORE_GET_VER 0x03 + +/* Hypervisor API groups for use with HV_CORE_SET_VER and + * HV_CORE_GET_VER. + */ +#define HV_GRP_SUN4V 0x0000 +#define HV_GRP_CORE 0x0001 +#define HV_GRP_INTR 0x0002 +#define HV_GRP_SOFT_STATE 0x0003 +#define HV_GRP_PCI 0x0100 +#define HV_GRP_LDOM 0x0101 +#define HV_GRP_SVC_CHAN 0x0102 +#define HV_GRP_NCS 0x0103 +#define HV_GRP_NIAG_PERF 0x0200 +#define HV_GRP_FIRE_PERF 0x0201 +#define HV_GRP_DIAG 0x0300 + +#ifndef __ASSEMBLY__ +extern unsigned long sun4v_get_version(unsigned long group, + unsigned long *major, + unsigned long *minor); +extern unsigned long sun4v_set_version(unsigned long group, + unsigned long major, + unsigned long minor, + unsigned long *actual_minor); + +extern int sun4v_hvapi_register(unsigned long group, unsigned long major, + unsigned long *minor); +extern void sun4v_hvapi_unregister(unsigned long group); +extern int sun4v_hvapi_get(unsigned long group, + unsigned long *major, + unsigned long *minor); +#endif #endif /* !(_SPARC64_HYPERVISOR_H) */ diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h index fd6627e2d11..c6c1f4a120e 100644 --- a/include/linux/slub_def.h +++ b/include/linux/slub_def.h @@ -88,7 +88,7 @@ static inline int kmalloc_index(int size) */ WARN_ON_ONCE(size == 0); - if (size >= (1 << KMALLOC_SHIFT_HIGH)) + if (size > (1 << KMALLOC_SHIFT_HIGH)) return -1; if (size > 64 && size <= 96) diff --git a/include/sound/soc.h b/include/sound/soc.h index b1dc364b8f7..db6edba8ef0 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -22,7 +22,7 @@ #include <sound/control.h> #include <sound/ac97_codec.h> -#define SND_SOC_VERSION "0.13.0" +#define SND_SOC_VERSION "0.13.1" /* * Convenience kcontrol builders @@ -83,6 +83,7 @@ #define SND_SOC_DAI_AC97 0x1 #define SND_SOC_DAI_I2S 0x2 #define SND_SOC_DAI_PCM 0x4 +#define SND_SOC_DAI_AC97_BUS 0x8 /* for custom i.e. non ac97_codec.c */ /* * DAI hardware audio formats @@ -278,6 +279,7 @@ struct snd_soc_cpu_ops { struct snd_soc_codec_dai { char *name; int id; + unsigned char type; /* DAI capabilities */ struct snd_soc_pcm_stream playback; diff --git a/include/sound/version.h b/include/sound/version.h index e820f0e7bdd..50ee4fd420f 100644 --- a/include/sound/version.h +++ b/include/sound/version.h @@ -1,3 +1,3 @@ /* include/version.h. Generated by alsa/ksync script. */ #define CONFIG_SND_VERSION "1.0.14rc4" -#define CONFIG_SND_DATE " (Wed May 09 09:51:39 2007 UTC)" +#define CONFIG_SND_DATE " (Wed May 16 09:45:46 2007 UTC)" diff --git a/kernel/power/main.c b/kernel/power/main.c index 40d56a31245..b98b80ccf43 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c @@ -97,25 +97,26 @@ static int suspend_prepare(suspend_state_t state) } } - if (pm_ops->prepare) { - if ((error = pm_ops->prepare(state))) - goto Thaw; - } - suspend_console(); error = device_suspend(PMSG_SUSPEND); if (error) { printk(KERN_ERR "Some devices failed to suspend\n"); - goto Resume_devices; + goto Resume_console; } + if (pm_ops->prepare) { + if ((error = pm_ops->prepare(state))) + goto Resume_devices; + } + error = disable_nonboot_cpus(); if (!error) return 0; enable_nonboot_cpus(); - Resume_devices: pm_finish(state); + Resume_devices: device_resume(); + Resume_console: resume_console(); Thaw: thaw_processes(); diff --git a/mm/filemap.c b/mm/filemap.c index 7b48b2ad00e..edb1b0b5cc8 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -670,7 +670,8 @@ repeat: page = find_lock_page(mapping, index); if (!page) { if (!cached_page) { - cached_page = alloc_page(gfp_mask); + cached_page = + __page_cache_alloc(gfp_mask); if (!cached_page) return NULL; } diff --git a/mm/slub.c b/mm/slub.c index b39c8a69a4f..5e3e8bc9838 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -2522,7 +2522,7 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size, struct kmem_cache *s; down_write(&slub_lock); - s = find_mergeable(size, align, flags, dtor, ctor); + s = find_mergeable(size, align, flags, ctor, dtor); if (s) { s->refcount++; /* diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c index 214d65d94c4..f471f8ad688 100644 --- a/sound/isa/cmi8330.c +++ b/sound/isa/cmi8330.c @@ -109,6 +109,7 @@ module_param_array(wssdma, int, NULL, 0444); MODULE_PARM_DESC(wssdma, "DMA for CMI8330 WSS driver."); #ifdef CONFIG_PNP +static int isa_registered; static int pnp_registered; #endif @@ -686,14 +687,18 @@ static int __init alsa_card_cmi8330_init(void) int err; err = isa_register_driver(&snd_cmi8330_driver, SNDRV_CARDS); - if (err < 0) - return err; #ifdef CONFIG_PNP + if (!err) + isa_registered = 1; + err = pnp_register_card_driver(&cmi8330_pnpc_driver); if (!err) pnp_registered = 1; + + if (isa_registered) + err = 0; #endif - return 0; + return err; } static void __exit alsa_card_cmi8330_exit(void) @@ -701,8 +706,10 @@ static void __exit alsa_card_cmi8330_exit(void) #ifdef CONFIG_PNP if (pnp_registered) pnp_unregister_card_driver(&cmi8330_pnpc_driver); + + if (isa_registered) #endif - isa_unregister_driver(&snd_cmi8330_driver); + isa_unregister_driver(&snd_cmi8330_driver); } module_init(alsa_card_cmi8330_init) diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c index 87f1392a2fa..1a14f33b6ab 100644 --- a/sound/isa/cs423x/cs4236.c +++ b/sound/isa/cs423x/cs4236.c @@ -127,6 +127,7 @@ module_param_array(dma2, int, NULL, 0444); MODULE_PARM_DESC(dma2, "DMA2 # for " IDENT " driver."); #ifdef CONFIG_PNP +static int isa_registered; static int pnpc_registered; #ifdef CS4232 static int pnp_registered; @@ -770,9 +771,9 @@ static int __init alsa_card_cs423x_init(void) int err; err = isa_register_driver(&cs423x_isa_driver, SNDRV_CARDS); - if (err < 0) - return err; #ifdef CONFIG_PNP + if (!err) + isa_registered = 1; #ifdef CS4232 err = pnp_register_driver(&cs4232_pnp_driver); if (!err) @@ -781,8 +782,14 @@ static int __init alsa_card_cs423x_init(void) err = pnp_register_card_driver(&cs423x_pnpc_driver); if (!err) pnpc_registered = 1; -#endif /* CONFIG_PNP */ - return 0; +#ifdef CS4232 + if (pnp_registered) + err = 0; +#endif + if (isa_registered) + err = 0; +#endif + return err; } static void __exit alsa_card_cs423x_exit(void) @@ -794,8 +801,9 @@ static void __exit alsa_card_cs423x_exit(void) if (pnp_registered) pnp_unregister_driver(&cs4232_pnp_driver); #endif -#endif /* CONFIG_PNP */ - isa_unregister_driver(&cs423x_isa_driver); + if (isa_registered) +#endif + isa_unregister_driver(&cs423x_isa_driver); } module_init(alsa_card_cs423x_init) diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c index d2a9c7df0ce..f7732bf90be 100644 --- a/sound/isa/es18xx.c +++ b/sound/isa/es18xx.c @@ -2036,7 +2036,9 @@ module_param_array(dma2, int, NULL, 0444); MODULE_PARM_DESC(dma2, "DMA 2 # for ES18xx driver."); #ifdef CONFIG_PNP -static int pnp_registered, pnpc_registered; +static int isa_registered; +static int pnp_registered; +static int pnpc_registered; static struct pnp_device_id snd_audiodrive_pnpbiosids[] = { { .id = "ESS1869" }, @@ -2466,18 +2468,22 @@ static int __init alsa_card_es18xx_init(void) int err; err = isa_register_driver(&snd_es18xx_isa_driver, SNDRV_CARDS); - if (err < 0) - return err; - #ifdef CONFIG_PNP + if (!err) + isa_registered = 1; + err = pnp_register_driver(&es18xx_pnp_driver); if (!err) pnp_registered = 1; + err = pnp_register_card_driver(&es18xx_pnpc_driver); if (!err) pnpc_registered = 1; + + if (isa_registered || pnp_registered) + err = 0; #endif - return 0; + return err; } static void __exit alsa_card_es18xx_exit(void) @@ -2487,8 +2493,9 @@ static void __exit alsa_card_es18xx_exit(void) pnp_unregister_card_driver(&es18xx_pnpc_driver); if (pnp_registered) pnp_unregister_driver(&es18xx_pnp_driver); + if (isa_registered) #endif - isa_unregister_driver(&snd_es18xx_isa_driver); + isa_unregister_driver(&snd_es18xx_isa_driver); } module_init(alsa_card_es18xx_init) diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c index 3e465725553..0220cdbe1a2 100644 --- a/sound/isa/gus/interwave.c +++ b/sound/isa/gus/interwave.c @@ -135,6 +135,7 @@ struct snd_interwave { #ifdef CONFIG_PNP +static int isa_registered; static int pnp_registered; static struct pnp_card_device_id snd_interwave_pnpids[] = { @@ -934,15 +935,18 @@ static int __init alsa_card_interwave_init(void) int err; err = isa_register_driver(&snd_interwave_driver, SNDRV_CARDS); - if (err < 0) - return err; #ifdef CONFIG_PNP - /* ISA PnP cards */ + if (!err) + isa_registered = 1; + err = pnp_register_card_driver(&interwave_pnpc_driver); if (!err) pnp_registered = 1; + + if (isa_registered) + err = 0; #endif - return 0; + return err; } static void __exit alsa_card_interwave_exit(void) @@ -950,8 +954,9 @@ static void __exit alsa_card_interwave_exit(void) #ifdef CONFIG_PNP if (pnp_registered) pnp_unregister_card_driver(&interwave_pnpc_driver); + if (isa_registered) #endif - isa_unregister_driver(&snd_interwave_driver); + isa_unregister_driver(&snd_interwave_driver); } module_init(alsa_card_interwave_init) diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c index 48743eb85fb..61a323cc0e4 100644 --- a/sound/isa/opl3sa2.c +++ b/sound/isa/opl3sa2.c @@ -92,6 +92,7 @@ module_param_array(opl3sa3_ymode, int, NULL, 0444); MODULE_PARM_DESC(opl3sa3_ymode, "Speaker size selection for 3D Enhancement mode: Desktop/Large Notebook/Small Notebook/HiFi."); #ifdef CONFIG_PNP +static int isa_registered; static int pnp_registered; static int pnpc_registered; #endif @@ -967,17 +968,22 @@ static int __init alsa_card_opl3sa2_init(void) int err; err = isa_register_driver(&snd_opl3sa2_isa_driver, SNDRV_CARDS); - if (err < 0) - return err; #ifdef CONFIG_PNP + if (!err) + isa_registered = 1; + err = pnp_register_driver(&opl3sa2_pnp_driver); if (!err) pnp_registered = 1; + err = pnp_register_card_driver(&opl3sa2_pnpc_driver); if (!err) pnpc_registered = 1; + + if (isa_registered || pnp_registered) + err = 0; #endif - return 0; + return err; } static void __exit alsa_card_opl3sa2_exit(void) @@ -987,8 +993,9 @@ static void __exit alsa_card_opl3sa2_exit(void) pnp_unregister_card_driver(&opl3sa2_pnpc_driver); if (pnp_registered) pnp_unregister_driver(&opl3sa2_pnp_driver); + if (isa_registered) #endif - isa_unregister_driver(&snd_opl3sa2_isa_driver); + isa_unregister_driver(&snd_opl3sa2_isa_driver); } module_init(alsa_card_opl3sa2_init) diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c index 2a19b0a39ed..c4ba24bfd27 100644 --- a/sound/isa/sb/sb16.c +++ b/sound/isa/sb/sb16.c @@ -129,6 +129,7 @@ MODULE_PARM_DESC(seq_ports, "Number of sequencer ports for WaveTable synth."); #endif #ifdef CONFIG_PNP +static int isa_registered; static int pnp_registered; #endif @@ -702,15 +703,18 @@ static int __init alsa_card_sb16_init(void) int err; err = isa_register_driver(&snd_sb16_isa_driver, SNDRV_CARDS); - if (err < 0) - return err; #ifdef CONFIG_PNP - /* PnP cards at last */ + if (!err) + isa_registered = 1; + err = pnp_register_card_driver(&sb16_pnpc_driver); if (!err) pnp_registered = 1; + + if (isa_registered) + err = 0; #endif - return 0; + return err; } static void __exit alsa_card_sb16_exit(void) @@ -718,8 +722,9 @@ static void __exit alsa_card_sb16_exit(void) #ifdef CONFIG_PNP if (pnp_registered) pnp_unregister_card_driver(&sb16_pnpc_driver); + if (isa_registered) #endif - isa_unregister_driver(&snd_sb16_isa_driver); + isa_unregister_driver(&snd_sb16_isa_driver); } module_init(alsa_card_sb16_init) diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c index 08c14978558..9ea417bcf3e 100644 --- a/sound/isa/sscape.c +++ b/sound/isa/sscape.c @@ -69,7 +69,9 @@ module_param_array(dma, int, NULL, 0444); MODULE_PARM_DESC(dma, "DMA # for SoundScape driver."); #ifdef CONFIG_PNP +static int isa_registered; static int pnp_registered; + static struct pnp_card_device_id sscape_pnpids[] = { { .id = "ENS3081", .devs = { { "ENS0000" } } }, { .id = "" } /* end */ @@ -1405,22 +1407,21 @@ static struct pnp_card_driver sscape_pnpc_driver = { static int __init sscape_init(void) { - int ret; + int err; - /* - * First check whether we were passed any parameters. - * These MUST take precedence over ANY automatic way - * of allocating cards, because the operator is - * S-P-E-L-L-I-N-G it out for us... - */ - ret = isa_register_driver(&snd_sscape_driver, SNDRV_CARDS); - if (ret < 0) - return ret; + err = isa_register_driver(&snd_sscape_driver, SNDRV_CARDS); #ifdef CONFIG_PNP - if (pnp_register_card_driver(&sscape_pnpc_driver) == 0) + if (!err) + isa_registered = 1; + + err = pnp_register_card_driver(&sscape_pnpc_driver); + if (!err) pnp_registered = 1; + + if (isa_registered) + err = 0; #endif - return 0; + return err; } static void __exit sscape_exit(void) @@ -1428,8 +1429,9 @@ static void __exit sscape_exit(void) #ifdef CONFIG_PNP if (pnp_registered) pnp_unregister_card_driver(&sscape_pnpc_driver); + if (isa_registered) #endif - isa_unregister_driver(&snd_sscape_driver); + isa_unregister_driver(&snd_sscape_driver); } module_init(sscape_init); diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c index 75673f72385..83c2fc4cfc6 100644 --- a/sound/isa/wavefront/wavefront.c +++ b/sound/isa/wavefront/wavefront.c @@ -86,6 +86,7 @@ module_param_array(use_cs4232_midi, bool, NULL, 0444); MODULE_PARM_DESC(use_cs4232_midi, "Use CS4232 MPU-401 interface (inaccessibly located inside your computer)"); #ifdef CONFIG_PNP +static int isa_registered; static int pnp_registered; static struct pnp_card_device_id snd_wavefront_pnpids[] = { @@ -706,14 +707,18 @@ static int __init alsa_card_wavefront_init(void) int err; err = isa_register_driver(&snd_wavefront_driver, SNDRV_CARDS); - if (err < 0) - return err; #ifdef CONFIG_PNP + if (!err) + isa_registered = 1; + err = pnp_register_card_driver(&wavefront_pnpc_driver); if (!err) pnp_registered = 1; + + if (isa_registered) + err = 0; #endif - return 0; + return err; } static void __exit alsa_card_wavefront_exit(void) @@ -721,8 +726,9 @@ static void __exit alsa_card_wavefront_exit(void) #ifdef CONFIG_PNP if (pnp_registered) pnp_unregister_card_driver(&wavefront_pnpc_driver); + if (isa_registered) #endif - isa_unregister_driver(&snd_wavefront_driver); + isa_unregister_driver(&snd_wavefront_driver); } module_init(alsa_card_wavefront_init) diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index 3eac0f86266..581ebba4d1a 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c @@ -1782,6 +1782,11 @@ static unsigned int ad1981_jacks_blacklist[] = { 0x10140534, /* Thinkpad X31 */ 0x10140537, /* Thinkpad T41p */ 0x10140554, /* Thinkpad T42p/R50p */ + 0x10140567, /* Thinkpad T43p 2668-G7U */ + 0x10140581, /* Thinkpad X41-2527 */ + 0x104380b0, /* Asus A7V8X-MX */ + 0x11790241, /* Toshiba Satellite A-15 S127 */ + 0x144dc01a, /* Samsung NP-X20C004/SEG */ 0 /* end */ }; diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 14649d54b49..8e89d56b640 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -707,7 +707,8 @@ static u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction) direction == HDA_OUTPUT ? AC_PAR_AMP_OUT_CAP : AC_PAR_AMP_IN_CAP); - info->status |= INFO_AMP_CAPS; + if (info->amp_caps) + info->status |= INFO_AMP_CAPS; } return info->amp_caps; } diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index a4ede27af02..34ac6346953 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -93,6 +93,7 @@ enum { ALC262_HP_BPC_D7000_WL, ALC262_HP_BPC_D7000_WF, ALC262_BENQ_ED8, + ALC262_SONY_ASSAMD, ALC262_AUTO, ALC262_MODEL_LAST /* last tag */ }; @@ -118,6 +119,7 @@ enum { ALC861VD_3ST_DIG, ALC861VD_6ST_DIG, ALC861VD_LENOVO, + ALC861VD_DALLAS, ALC861VD_AUTO, ALC861VD_MODEL_LAST, }; @@ -139,8 +141,10 @@ enum { ALC882_6ST_DIG, ALC882_ARIMA, ALC882_W2JC, - ALC882_AUTO, + ALC882_TARGA, + ALC882_ASUS_A7J, ALC885_MACPRO, + ALC882_AUTO, ALC882_MODEL_LAST, }; @@ -152,11 +156,13 @@ enum { ALC883_6ST_DIG, ALC883_TARGA_DIG, ALC883_TARGA_2ch_DIG, - ALC888_DEMO_BOARD, ALC883_ACER, ALC883_MEDION, + ALC883_MEDION_MD2, ALC883_LAPTOP_EAPD, ALC883_LENOVO_101E_2ch, + ALC883_LENOVO_NB0763, + ALC888_LENOVO_MS7195_DIG, ALC883_AUTO, ALC883_MODEL_LAST, }; @@ -4753,6 +4759,35 @@ static int alc882_mux_enum_put(struct snd_kcontrol *kcontrol, } /* + * 2ch mode + */ +static struct hda_verb alc882_3ST_ch2_init[] = { + { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, + { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, + { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, + { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, + { } /* end */ +}; + +/* + * 6ch mode + */ +static struct hda_verb alc882_3ST_ch6_init[] = { + { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, + { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, + { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 }, + { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, + { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, + { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 }, + { } /* end */ +}; + +static struct hda_channel_mode alc882_3ST_6ch_modes[2] = { + { 2, alc882_3ST_ch2_init }, + { 6, alc882_3ST_ch6_init }, +}; + +/* * 6ch mode */ static struct hda_verb alc882_sixstack_ch6_init[] = { @@ -4824,6 +4859,40 @@ static struct snd_kcontrol_new alc882_w2jc_mixer[] = { { } /* end */ }; +static struct snd_kcontrol_new alc882_targa_mixer[] = { + HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), + HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), + HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), + HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), + HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), + HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), + HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), + HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), + HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), + { } /* end */ +}; + +/* Pin assignment: Front=0x14, HP = 0x15, Front = 0x16, ??? + * Front Mic=0x18, Line In = 0x1a, Line In = 0x1b, CD = 0x1c + */ +static struct snd_kcontrol_new alc882_asus_a7j_mixer[] = { + HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Mobile Front Playback Switch", 0x16, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), + HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), + HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), + HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), + HDA_CODEC_VOLUME("Mobile Line Playback Volume", 0x0b, 0x03, HDA_INPUT), + HDA_CODEC_MUTE("Mobile Line Playback Switch", 0x0b, 0x03, HDA_INPUT), + HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), + { } /* end */ +}; + static struct snd_kcontrol_new alc882_chmode_mixer[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -4985,6 +5054,66 @@ static struct hda_verb alc882_macpro_init_verbs[] = { { } }; +static struct hda_verb alc882_targa_verbs[] = { + {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, + {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, + + {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, + {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, + + {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */ + {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */ + {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ + + {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, + {0x01, AC_VERB_SET_GPIO_MASK, 0x03}, + {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03}, + {0x01, AC_VERB_SET_GPIO_DATA, 0x03}, + { } /* end */ +}; + +/* toggle speaker-output according to the hp-jack state */ +static void alc882_targa_automute(struct hda_codec *codec) +{ + unsigned int present; + + present = snd_hda_codec_read(codec, 0x14, 0, + AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; + snd_hda_codec_amp_update(codec, 0x1b, 0, HDA_OUTPUT, 0, + 0x80, present ? 0x80 : 0); + snd_hda_codec_amp_update(codec, 0x1b, 1, HDA_OUTPUT, 0, + 0x80, present ? 0x80 : 0); + snd_hda_codec_write(codec, 1, 0, AC_VERB_SET_GPIO_DATA, present ? 1 : 3); +} + +static void alc882_targa_unsol_event(struct hda_codec *codec, unsigned int res) +{ + /* Looks like the unsol event is incompatible with the standard + * definition. 4bit tag is placed at 26 bit! + */ + if (((res >> 26) == ALC880_HP_EVENT)) { + alc882_targa_automute(codec); + } +} + +static struct hda_verb alc882_asus_a7j_verbs[] = { + {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, + {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, + + {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, + {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, + {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, + + {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */ + {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ + {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */ + + {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */ + {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */ + {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ + { } /* end */ +}; + static void alc882_gpio_mute(struct hda_codec *codec, int pin, int muted) { unsigned int gpiostate, gpiomask, gpiodir; @@ -5152,7 +5281,9 @@ static struct snd_pci_quirk alc882_cfg_tbl[] = { SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC882_6ST_DIG), SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC882_6ST_DIG), SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC882_6ST_DIG), + SND_PCI_QUIRK(0x1462, 0x28fb, "Targa T8", ALC882_TARGA), /* MSI-1049 T8 */ SND_PCI_QUIRK(0x161f, 0x2054, "Arima W820", ALC882_ARIMA), + SND_PCI_QUIRK(0x1043, 0x060d, "Asus A7J", ALC882_ASUS_A7J), SND_PCI_QUIRK(0x1043, 0x81d8, "Asus P5WD", ALC882_6ST_DIG), SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_W2JC), {} @@ -5214,6 +5345,36 @@ static struct alc_config_preset alc882_presets[] = { .channel_mode = alc882_ch_modes, .input_mux = &alc882_capture_source, }, + [ALC882_TARGA] = { + .mixers = { alc882_targa_mixer, alc882_chmode_mixer, + alc882_capture_mixer }, + .init_verbs = { alc882_init_verbs, alc882_targa_verbs}, + .num_dacs = ARRAY_SIZE(alc882_dac_nids), + .dac_nids = alc882_dac_nids, + .dig_out_nid = ALC882_DIGOUT_NID, + .num_adc_nids = ARRAY_SIZE(alc882_adc_nids), + .adc_nids = alc882_adc_nids, + .num_channel_mode = ARRAY_SIZE(alc882_3ST_6ch_modes), + .channel_mode = alc882_3ST_6ch_modes, + .need_dac_fix = 1, + .input_mux = &alc882_capture_source, + .unsol_event = alc882_targa_unsol_event, + .init_hook = alc882_targa_automute, + }, + [ALC882_ASUS_A7J] = { + .mixers = { alc882_asus_a7j_mixer, alc882_chmode_mixer, + alc882_capture_mixer }, + .init_verbs = { alc882_init_verbs, alc882_asus_a7j_verbs}, + .num_dacs = ARRAY_SIZE(alc882_dac_nids), + .dac_nids = alc882_dac_nids, + .dig_out_nid = ALC882_DIGOUT_NID, + .num_adc_nids = ARRAY_SIZE(alc882_adc_nids), + .adc_nids = alc882_adc_nids, + .num_channel_mode = ARRAY_SIZE(alc882_3ST_6ch_modes), + .channel_mode = alc882_3ST_6ch_modes, + .need_dac_fix = 1, + .input_mux = &alc882_capture_source, + }, }; @@ -5441,6 +5602,16 @@ static struct hda_input_mux alc883_lenovo_101e_capture_source = { }, }; +static struct hda_input_mux alc883_lenovo_nb0763_capture_source = { + .num_items = 4, + .items = { + { "Mic", 0x0 }, + { "iMic", 0x1 }, + { "Line", 0x2 }, + { "CD", 0x4 }, + }, +}; + #define alc883_mux_enum_info alc_mux_enum_info #define alc883_mux_enum_get alc_mux_enum_get @@ -5772,6 +5943,58 @@ static struct snd_kcontrol_new alc883_lenovo_101e_2ch_mixer[] = { { } /* end */ }; +static struct snd_kcontrol_new alc883_lenovo_nb0763_mixer[] = { + HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x0, HDA_OUTPUT), + HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 2, HDA_INPUT), + HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), + HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), + HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), + HDA_CODEC_VOLUME("iMic Playback Volume", 0x0b, 0x1, HDA_INPUT), + HDA_CODEC_MUTE("iMic Playback Switch", 0x0b, 0x1, HDA_INPUT), + HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), + HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), + HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + /* .name = "Capture Source", */ + .name = "Input Source", + .count = 2, + .info = alc883_mux_enum_info, + .get = alc883_mux_enum_get, + .put = alc883_mux_enum_put, + }, + { } /* end */ +}; + +static struct snd_kcontrol_new alc883_medion_md2_mixer[] = { + HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), + HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), + HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), + HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), + HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), + HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), + HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), + HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + /* .name = "Capture Source", */ + .name = "Input Source", + .count = 2, + .info = alc883_mux_enum_info, + .get = alc883_mux_enum_get, + .put = alc883_mux_enum_put, + }, + { } /* end */ +}; + static struct snd_kcontrol_new alc883_chmode_mixer[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -5886,6 +6109,93 @@ static struct hda_verb alc883_lenovo_101e_verbs[] = { { } /* end */ }; +static struct hda_verb alc883_lenovo_nb0763_verbs[] = { + {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, + {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, + {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, + {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, + { } /* end */ +}; + +static struct hda_verb alc888_lenovo_ms7195_verbs[] = { + {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, + {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, + {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, + {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_FRONT_EVENT | AC_USRSP_EN}, + {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, + { } /* end */ +}; + +/* toggle front-jack and RCA according to the hp-jack state */ +static void alc888_lenovo_ms7195_front_automute(struct hda_codec *codec) +{ + unsigned int present; + + present = snd_hda_codec_read(codec, 0x1b, 0, + AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; + snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, + 0x80, present ? 0x80 : 0); + snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, + 0x80, present ? 0x80 : 0); + snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, + 0x80, present ? 0x80 : 0); + snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, + 0x80, present ? 0x80 : 0); + +} + +/* toggle RCA according to the front-jack state */ +static void alc888_lenovo_ms7195_rca_automute(struct hda_codec *codec) +{ + unsigned int present; + + present = snd_hda_codec_read(codec, 0x14, 0, + AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; + snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, + 0x80, present ? 0x80 : 0); + snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, + 0x80, present ? 0x80 : 0); + +} +static void alc883_lenovo_ms7195_unsol_event(struct hda_codec *codec, + unsigned int res) +{ + if ((res >> 26) == ALC880_HP_EVENT) + alc888_lenovo_ms7195_front_automute(codec); + if ((res >> 26) == ALC880_FRONT_EVENT) + alc888_lenovo_ms7195_rca_automute(codec); +} + +static struct hda_verb alc883_medion_md2_verbs[] = { + {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, + {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, + + {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, + + {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, + { } /* end */ +}; + +/* toggle speaker-output according to the hp-jack state */ +static void alc883_medion_md2_automute(struct hda_codec *codec) +{ + unsigned int present; + + present = snd_hda_codec_read(codec, 0x14, 0, + AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; + snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, + 0x80, present ? 0x80 : 0); + snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, + 0x80, present ? 0x80 : 0); +} + +static void alc883_medion_md2_unsol_event(struct hda_codec *codec, + unsigned int res) +{ + if ((res >> 26) == ALC880_HP_EVENT) + alc883_medion_md2_automute(codec); +} + /* toggle speaker-output according to the hp-jack state */ static void alc883_tagra_automute(struct hda_codec *codec) { @@ -6051,11 +6361,13 @@ static const char *alc883_models[ALC883_MODEL_LAST] = { [ALC883_6ST_DIG] = "6stack-dig", [ALC883_TARGA_DIG] = "targa-dig", [ALC883_TARGA_2ch_DIG] = "targa-2ch-dig", - [ALC888_DEMO_BOARD] = "6stack-dig-demo", [ALC883_ACER] = "acer", [ALC883_MEDION] = "medion", + [ALC883_MEDION_MD2] = "medion-md2", [ALC883_LAPTOP_EAPD] = "laptop-eapd", [ALC883_LENOVO_101E_2ch] = "lenovo-101e", + [ALC883_LENOVO_NB0763] = "lenovo-nb0763", + [ALC888_LENOVO_MS7195_DIG] = "lenovo-ms7195-dig", [ALC883_AUTO] = "auto", }; @@ -6082,7 +6394,10 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = { SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION), SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC883_LAPTOP_EAPD), SND_PCI_QUIRK(0x8086, 0xd601, "D102GGC", ALC883_3ST_6ch), - SND_PCI_QUIRK(0x17aa, 0x101e, "lenovo 101e", ALC883_LENOVO_101E_2ch), + SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo 101e", ALC883_LENOVO_101E_2ch), + SND_PCI_QUIRK(0x17aa, 0x3bfd, "Lenovo NB0763", ALC883_LENOVO_NB0763), + SND_PCI_QUIRK(0x17aa, 0x2085, "Lenovo NB0763", ALC883_LENOVO_NB0763), + SND_PCI_QUIRK(0x17c0, 0x4071, "MEDION MD2", ALC883_MEDION_MD2), {} }; @@ -6168,19 +6483,6 @@ static struct alc_config_preset alc883_presets[] = { .unsol_event = alc883_tagra_unsol_event, .init_hook = alc883_tagra_automute, }, - [ALC888_DEMO_BOARD] = { - .mixers = { alc883_base_mixer, alc883_chmode_mixer }, - .init_verbs = { alc883_init_verbs }, - .num_dacs = ARRAY_SIZE(alc883_dac_nids), - .dac_nids = alc883_dac_nids, - .dig_out_nid = ALC883_DIGOUT_NID, - .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), - .adc_nids = alc883_adc_nids, - .dig_in_nid = ALC883_DIGIN_NID, - .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes), - .channel_mode = alc883_sixstack_modes, - .input_mux = &alc883_capture_source, - }, [ALC883_ACER] = { .mixers = { alc883_base_mixer, alc883_chmode_mixer }, @@ -6211,6 +6513,20 @@ static struct alc_config_preset alc883_presets[] = { .channel_mode = alc883_sixstack_modes, .input_mux = &alc883_capture_source, }, + [ALC883_MEDION_MD2] = { + .mixers = { alc883_medion_md2_mixer}, + .init_verbs = { alc883_init_verbs, alc883_medion_md2_verbs}, + .num_dacs = ARRAY_SIZE(alc883_dac_nids), + .dac_nids = alc883_dac_nids, + .dig_out_nid = ALC883_DIGOUT_NID, + .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), + .adc_nids = alc883_adc_nids, + .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), + .channel_mode = alc883_3ST_2ch_modes, + .input_mux = &alc883_capture_source, + .unsol_event = alc883_medion_md2_unsol_event, + .init_hook = alc883_medion_md2_automute, + }, [ALC883_LAPTOP_EAPD] = { .mixers = { alc883_base_mixer, alc883_chmode_mixer }, @@ -6236,6 +6552,35 @@ static struct alc_config_preset alc883_presets[] = { .unsol_event = alc883_lenovo_101e_unsol_event, .init_hook = alc883_lenovo_101e_all_automute, }, + [ALC883_LENOVO_NB0763] = { + .mixers = { alc883_lenovo_nb0763_mixer }, + .init_verbs = { alc883_init_verbs, alc883_lenovo_nb0763_verbs}, + .num_dacs = ARRAY_SIZE(alc883_dac_nids), + .dac_nids = alc883_dac_nids, + .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), + .adc_nids = alc883_adc_nids, + .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), + .channel_mode = alc883_3ST_2ch_modes, + .need_dac_fix = 1, + .input_mux = &alc883_lenovo_nb0763_capture_source, + .unsol_event = alc883_medion_md2_unsol_event, + .init_hook = alc883_medion_md2_automute, + }, + [ALC888_LENOVO_MS7195_DIG] = { + .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer }, + .init_verbs = { alc883_init_verbs, alc888_lenovo_ms7195_verbs}, + .num_dacs = ARRAY_SIZE(alc883_dac_nids), + .dac_nids = alc883_dac_nids, + .dig_out_nid = ALC883_DIGOUT_NID, + .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), + .adc_nids = alc883_adc_nids, + .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes), + .channel_mode = alc883_3ST_6ch_modes, + .need_dac_fix = 1, + .input_mux = &alc883_capture_source, + .unsol_event = alc883_lenovo_ms7195_unsol_event, + .init_hook = alc888_lenovo_ms7195_front_automute, + }, }; @@ -6499,6 +6844,18 @@ static struct snd_kcontrol_new alc262_HP_BPC_WildWest_option_mixer[] = { { } /* end */ }; +static struct snd_kcontrol_new alc262_sony_mixer[] = { + HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), + HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), + HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), + { } /* end */ +}; + + + #define alc262_capture_mixer alc882_capture_mixer #define alc262_capture_alt_mixer alc882_capture_alt_mixer @@ -6597,6 +6954,15 @@ static struct hda_verb alc262_hippo1_unsol_verbs[] = { {} }; +static struct hda_verb alc262_sony_unsol_verbs[] = { + {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0}, + {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, + {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, // Front Mic + + {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, + {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, +}; + /* mute/unmute internal speaker according to the hp jack and mute state */ static void alc262_hippo_automute(struct hda_codec *codec, int force) { @@ -7215,6 +7581,7 @@ static const char *alc262_models[ALC262_MODEL_LAST] = { [ALC262_HP_BPC] = "hp-bpc", [ALC262_HP_BPC_D7000_WL]= "hp-bpc-d7000", [ALC262_BENQ_ED8] = "benq", + [ALC262_BENQ_ED8] = "sony-assamd", [ALC262_AUTO] = "auto", }; @@ -7236,6 +7603,9 @@ static struct snd_pci_quirk alc262_cfg_tbl[] = { SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FUJITSU), SND_PCI_QUIRK(0x17ff, 0x058f, "Benq Hippo", ALC262_HIPPO_1), SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_BENQ_ED8), + SND_PCI_QUIRK(0x104d, 0x9015, "Sony 0x9015", ALC262_SONY_ASSAMD), + SND_PCI_QUIRK(0x104d, 0x900e, "Sony ASSAMD", ALC262_SONY_ASSAMD), + SND_PCI_QUIRK(0x104d, 0x1f00, "Sony ASSAMD", ALC262_SONY_ASSAMD), {} }; @@ -7327,6 +7697,17 @@ static struct alc_config_preset alc262_presets[] = { .channel_mode = alc262_modes, .input_mux = &alc262_capture_source, }, + [ALC262_SONY_ASSAMD] = { + .mixers = { alc262_sony_mixer }, + .init_verbs = { alc262_init_verbs, alc262_sony_unsol_verbs}, + .num_dacs = ARRAY_SIZE(alc262_dac_nids), + .dac_nids = alc262_dac_nids, + .hp_nid = 0x02, + .num_channel_mode = ARRAY_SIZE(alc262_modes), + .channel_mode = alc262_modes, + .input_mux = &alc262_capture_source, + .unsol_event = alc262_hippo_unsol_event, + }, }; static int patch_alc262(struct hda_codec *codec) @@ -8599,6 +8980,15 @@ static struct hda_input_mux alc861vd_capture_source = { }, }; +static struct hda_input_mux alc861vd_dallas_capture_source = { + .num_items = 3, + .items = { + { "Front Mic", 0x0 }, + { "ATAPI Mic", 0x1 }, + { "Line In", 0x5 }, + }, +}; + #define alc861vd_mux_enum_info alc_mux_enum_info #define alc861vd_mux_enum_get alc_mux_enum_get @@ -8782,6 +9172,34 @@ static struct snd_kcontrol_new alc861vd_lenovo_mixer[] = { { } /* end */ }; +/* Pin assignment: Front=0x14, HP = 0x15, + * Front Mic=0x18, ATAPI Mic = 0x19, Line In = 0x1d + */ +static struct snd_kcontrol_new alc861vd_dallas_mixer[] = { + HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT), + HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), + HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT), + HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT), + HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), + HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), + HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), + HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x05, HDA_INPUT), + HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x05, HDA_INPUT), + HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + /* .name = "Capture Source", */ + .name = "Input Source", + .count = 1, + .info = alc882_mux_enum_info, + .get = alc882_mux_enum_get, + .put = alc882_mux_enum_put, + }, + { } /* end */ +}; + /* * generic initialization of ADC, input mixers and output mixers */ @@ -8969,6 +9387,70 @@ static void alc861vd_lenovo_unsol_event(struct hda_codec *codec, } } +static struct hda_verb alc861vd_dallas_verbs[] = { + {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, + {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, + {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, + {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, + + {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, + {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, + {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, + {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, + {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, + {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, + {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, + {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, + + {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, + {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, + {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, + {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, + {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, + {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, + {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, + {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, + + {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50}, + {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, + {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50}, + {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, + {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, + {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, + {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, + {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, + + {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, + {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, + {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, + {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, + + {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, + {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, + {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, + + { } /* end */ +}; + +/* toggle speaker-output according to the hp-jack state */ +static void alc861vd_dallas_automute(struct hda_codec *codec) +{ + unsigned int present; + + present = snd_hda_codec_read(codec, 0x15, 0, + AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; + snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, + 0x80, present ? 0x80 : 0); + snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, + 0x80, present ? 0x80 : 0); +} + +static void alc861vd_dallas_unsol_event(struct hda_codec *codec, unsigned int res) +{ + if ((res >> 26) == ALC880_HP_EVENT) + alc861vd_dallas_automute(codec); +} + /* pcm configuration: identiacal with ALC880 */ #define alc861vd_pcm_analog_playback alc880_pcm_analog_playback #define alc861vd_pcm_analog_capture alc880_pcm_analog_capture @@ -8984,6 +9466,7 @@ static const char *alc861vd_models[ALC861VD_MODEL_LAST] = { [ALC861VD_3ST_DIG] = "3stack-digout", [ALC861VD_6ST_DIG] = "6stack-digout", [ALC861VD_LENOVO] = "lenovo", + [ALC861VD_DALLAS] = "dallas", [ALC861VD_AUTO] = "auto", }; @@ -8993,6 +9476,8 @@ static struct snd_pci_quirk alc861vd_cfg_tbl[] = { SND_PCI_QUIRK(0x10de, 0x03f0, "Realtek ALC660 demo", ALC660VD_3ST), SND_PCI_QUIRK(0x1019, 0xa88d, "Realtek ALC660 demo", ALC660VD_3ST), + SND_PCI_QUIRK(0x1179, 0xff00, "DALLAS", ALC861VD_DALLAS), + SND_PCI_QUIRK(0x1179, 0xff01, "DALLAS", ALC861VD_DALLAS), SND_PCI_QUIRK(0x17aa, 0x3802, "Lenovo 3000 C200", ALC861VD_LENOVO), SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo", ALC861VD_LENOVO), {} @@ -9059,6 +9544,19 @@ static struct alc_config_preset alc861vd_presets[] = { .unsol_event = alc861vd_lenovo_unsol_event, .init_hook = alc861vd_lenovo_automute, }, + [ALC861VD_DALLAS] = { + .mixers = { alc861vd_dallas_mixer }, + .init_verbs = { alc861vd_dallas_verbs }, + .num_dacs = ARRAY_SIZE(alc861vd_dac_nids), + .dac_nids = alc861vd_dac_nids, + .num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids), + .adc_nids = alc861vd_adc_nids, + .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes), + .channel_mode = alc861vd_3stack_2ch_modes, + .input_mux = &alc861vd_dallas_capture_source, + .unsol_event = alc861vd_dallas_unsol_event, + .init_hook = alc861vd_dallas_automute, + }, }; /* diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 93ae9c25076..a6a0a80edc3 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -467,6 +467,8 @@ static struct snd_pci_quirk stac9200_cfg_tbl[] = { "Dell XPS M1710", STAC_REF), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cf, "Dell Precision M90", STAC_REF), + SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d6, + "unknown Dell", STAC_REF), {} /* terminator */ }; diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 202f720b34b..da9734073db 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -1799,6 +1799,18 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = { }, { .subvendor = 0x1028, + .subdevice = 0x0186, + .name = "Dell Latitude D810", /* cf. Malone #41015 */ + .type = AC97_TUNE_HP_MUTE_LED + }, + { + .subvendor = 0x1028, + .subdevice = 0x0188, + .name = "Dell Inspiron 6000", + .type = AC97_TUNE_HP_MUTE_LED /* cf. Malone #41015 */ + }, + { + .subvendor = 0x1028, .subdevice = 0x0191, .name = "Dell Inspiron 8600", .type = AC97_TUNE_HP_ONLY @@ -1819,7 +1831,7 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = { .subvendor = 0x103c, .subdevice = 0x088c, .name = "HP nc8000", - .type = AC97_TUNE_MUTE_LED + .type = AC97_TUNE_HP_MUTE_LED }, { .subvendor = 0x103c, @@ -1913,6 +1925,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = { }, { .subvendor = 0x10cf, + .subdevice = 0x127e, + .name = "Fujitsu Lifebook C1211D", + .type = AC97_TUNE_HP_ONLY + }, + { + .subvendor = 0x10cf, .subdevice = 0x12ec, .name = "Fujitsu-Siemens 4010", .type = AC97_TUNE_HP_ONLY diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c index 0cdef971cbd..0b8a6f8b366 100644 --- a/sound/soc/codecs/ac97.c +++ b/sound/soc/codecs/ac97.c @@ -43,8 +43,9 @@ static int ac97_prepare(struct snd_pcm_substream *substream) #define STD_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) -static struct snd_soc_codec_dai ac97_dai = { +struct snd_soc_codec_dai ac97_dai = { .name = "AC97 HiFi", + .type = SND_SOC_DAI_AC97, .playback = { .stream_name = "AC97 Playback", .channels_min = 1, diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index 264413a00ca..986b5d59cef 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c @@ -544,6 +544,7 @@ static int ac97_aux_prepare(struct snd_pcm_substream *substream) struct snd_soc_codec_dai wm9712_dai[] = { { .name = "AC97 HiFi", + .type = SND_SOC_DAI_AC97_BUS, .playback = { .stream_name = "HiFi Playback", .channels_min = 1, diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 36519aef55d..92d5d917b73 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -116,6 +116,7 @@ static int soc_ac97_dev_register(struct snd_soc_codec *codec) static inline const char* get_dai_name(int type) { switch(type) { + case SND_SOC_DAI_AC97_BUS: case SND_SOC_DAI_AC97: return "AC97"; case SND_SOC_DAI_I2S: @@ -1099,7 +1100,8 @@ int snd_soc_register_card(struct snd_soc_device *socdev) continue; } } - if (socdev->machine->dai_link[i].cpu_dai->type == SND_SOC_DAI_AC97) + if (socdev->machine->dai_link[i].codec_dai->type == + SND_SOC_DAI_AC97_BUS) ac97 = 1; } snprintf(codec->card->shortname, sizeof(codec->card->shortname), @@ -1148,11 +1150,21 @@ EXPORT_SYMBOL_GPL(snd_soc_register_card); void snd_soc_free_pcms(struct snd_soc_device *socdev) { struct snd_soc_codec *codec = socdev->codec; +#ifdef CONFIG_SND_SOC_AC97_BUS + struct snd_soc_codec_dai *codec_dai; + int i; +#endif mutex_lock(&codec->mutex); #ifdef CONFIG_SND_SOC_AC97_BUS - if (codec->ac97) - soc_ac97_dev_unregister(codec); + for(i = 0; i < codec->num_dai; i++) { + codec_dai = &codec->dai[i]; + if (codec_dai->type == SND_SOC_DAI_AC97_BUS && codec->ac97) { + soc_ac97_dev_unregister(codec); + goto free_card; + } + } +free_card: #endif if (codec->card) diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c index 7b3bf3545a3..325d4b6b54a 100644 --- a/sound/usb/usbmixer.c +++ b/sound/usb/usbmixer.c @@ -360,7 +360,7 @@ static int get_ctl_value(struct usb_mixer_elem_info *cval, int request, int vali request, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, validx, cval->mixer->ctrlif | (cval->id << 8), - buf, val_len, 100) >= 0) { + buf, val_len, 100) >= val_len) { *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len)); return 0; } diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h index 8fcbe93b258..374fbf657a2 100644 --- a/sound/usb/usbquirks.h +++ b/sound/usb/usbquirks.h @@ -48,6 +48,15 @@ USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS, .idVendor = 0x046d, + .idProduct = 0x0850, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = USB_SUBCLASS_AUDIO_CONTROL +}, +{ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | + USB_DEVICE_ID_MATCH_INT_CLASS | + USB_DEVICE_ID_MATCH_INT_SUBCLASS, + .idVendor = 0x046d, .idProduct = 0x08f0, .bInterfaceClass = USB_CLASS_AUDIO, .bInterfaceSubClass = USB_SUBCLASS_AUDIO_CONTROL |