aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/00-INDEX44
-rw-r--r--Documentation/ABI/testing/sysfs-c2port88
-rw-r--r--Documentation/ABI/testing/sysfs-firmware-acpi16
-rw-r--r--Documentation/DMA-API.txt8
-rw-r--r--Documentation/PCI/00-INDEX2
-rw-r--r--Documentation/PCI/MSI-HOWTO.txt (renamed from Documentation/MSI-HOWTO.txt)0
-rw-r--r--Documentation/acpi/debug.txt148
-rw-r--r--Documentation/arm/mem_alignment2
-rw-r--r--Documentation/blockdev/00-INDEX16
-rw-r--r--Documentation/blockdev/README.DAC960 (renamed from Documentation/README.DAC960)0
-rw-r--r--Documentation/blockdev/cciss.txt (renamed from Documentation/cciss.txt)0
-rw-r--r--Documentation/blockdev/cpqarray.txt (renamed from Documentation/cpqarray.txt)0
-rw-r--r--Documentation/blockdev/floppy.txt (renamed from Documentation/floppy.txt)0
-rw-r--r--Documentation/blockdev/nbd.txt (renamed from Documentation/nbd.txt)0
-rw-r--r--Documentation/blockdev/paride.txt (renamed from Documentation/paride.txt)0
-rw-r--r--Documentation/blockdev/ramdisk.txt (renamed from Documentation/ramdisk.txt)0
-rw-r--r--Documentation/c2port.txt90
-rw-r--r--Documentation/cgroups/freezer-subsystem.txt21
-rw-r--r--Documentation/cpu-freq/user-guide.txt12
-rw-r--r--Documentation/filesystems/ocfs2.txt3
-rw-r--r--Documentation/filesystems/proc.txt27
-rw-r--r--Documentation/filesystems/ramfs-rootfs-initramfs.txt12
-rw-r--r--Documentation/filesystems/xip.txt9
-rw-r--r--Documentation/hwmon/adt746267
-rw-r--r--Documentation/hwmon/lis3lv02d49
-rw-r--r--Documentation/ics932s40131
-rw-r--r--Documentation/input/input-programming.txt3
-rw-r--r--Documentation/ioctl/00-INDEX10
-rw-r--r--Documentation/ioctl/ioctl-number.txt (renamed from Documentation/ioctl-number.txt)0
-rw-r--r--Documentation/kernel-parameters.txt125
-rw-r--r--Documentation/local_ops.txt2
-rw-r--r--Documentation/networking/phy.txt2
-rw-r--r--Documentation/printk-formats.txt35
-rw-r--r--Documentation/serial/00-INDEX24
-rw-r--r--Documentation/serial/README.cycladesZ (renamed from Documentation/README.cycladesZ)0
-rw-r--r--Documentation/serial/computone.txt (renamed from Documentation/computone.txt)2
-rw-r--r--Documentation/serial/digiepca.txt (renamed from Documentation/digiepca.txt)0
-rw-r--r--Documentation/serial/hayes-esp.txt (renamed from Documentation/hayes-esp.txt)0
-rw-r--r--Documentation/serial/moxa-smartio (renamed from Documentation/moxa-smartio)0
-rw-r--r--Documentation/serial/riscom8.txt (renamed from Documentation/riscom8.txt)0
-rw-r--r--Documentation/serial/rocket.txt (renamed from Documentation/rocket.txt)0
-rw-r--r--Documentation/serial/specialix.txt (renamed from Documentation/specialix.txt)0
-rw-r--r--Documentation/serial/stallion.txt (renamed from Documentation/stallion.txt)0
-rw-r--r--Documentation/serial/sx.txt (renamed from Documentation/sx.txt)0
-rw-r--r--Documentation/serial/tty.txt (renamed from Documentation/tty.txt)0
-rw-r--r--Documentation/sound/alsa/ALSA-Configuration.txt325
-rw-r--r--Documentation/sound/alsa/HD-Audio-Models.txt348
-rw-r--r--Documentation/sound/alsa/HD-Audio.txt577
-rw-r--r--Documentation/sound/alsa/Procfile.txt10
-rw-r--r--Documentation/sound/alsa/soc/machine.txt8
-rw-r--r--Documentation/spi/spi-summary2
-rw-r--r--Documentation/tracers/mmiotrace.txt6
-rw-r--r--Documentation/usb/gadget_serial.txt4
-rw-r--r--Documentation/usb/proc_usb_info.txt6
-rw-r--r--Documentation/usb/usbmon.txt12
-rw-r--r--Documentation/w1/masters/omap-hdq46
-rw-r--r--MAINTAINERS50
-rw-r--r--Makefile4
-rw-r--r--arch/Kconfig2
-rw-r--r--arch/alpha/kernel/pci.c2
-rw-r--r--arch/alpha/kernel/smp.c6
-rw-r--r--arch/alpha/kernel/traps.c4
-rw-r--r--arch/arm/common/sa1111.c2
-rw-r--r--arch/arm/configs/corgi_defconfig2
-rw-r--r--arch/arm/include/asm/bitops.h16
-rw-r--r--arch/arm/include/asm/dma-mapping.h13
-rw-r--r--arch/arm/include/asm/hardware/iop3xx-adma.h5
-rw-r--r--arch/arm/include/asm/hardware/iop_adma.h6
-rw-r--r--arch/arm/include/asm/mach/map.h13
-rw-r--r--arch/arm/include/asm/processor.h2
-rw-r--r--arch/arm/kernel/armksyms.c4
-rw-r--r--arch/arm/kernel/traps.c1
-rw-r--r--arch/arm/mach-clps711x/include/mach/hardware.h22
-rw-r--r--arch/arm/mach-clps7500/core.c6
-rw-r--r--arch/arm/mach-clps7500/include/mach/hardware.h6
-rw-r--r--arch/arm/mach-h720x/include/mach/boards.h6
-rw-r--r--arch/arm/mach-integrator/include/mach/platform.h19
-rw-r--r--arch/arm/mach-iop13xx/include/mach/adma.h3
-rw-r--r--arch/arm/mach-omap1/io.c2
-rw-r--r--arch/arm/mach-pxa/include/mach/palmasoc.h13
-rw-r--r--arch/arm/mach-pxa/include/mach/pxafb.h1
-rw-r--r--arch/arm/mach-pxa/include/mach/reset.h5
-rw-r--r--arch/arm/mach-pxa/mioa701.c2
-rw-r--r--arch/arm/mach-pxa/mioa701_bootresume.S1
-rw-r--r--arch/arm/mach-pxa/palmtx.c150
-rw-r--r--arch/arm/mach-pxa/pcm990-baseboard.c1
-rw-r--r--arch/arm/mach-pxa/reset.c7
-rw-r--r--arch/arm/mach-pxa/spitz.c4
-rw-r--r--arch/arm/mach-realview/clock.c2
-rw-r--r--arch/arm/mach-realview/include/mach/platform.h19
-rw-r--r--arch/arm/mach-s3c2410/include/mach/spi-gpio.h1
-rw-r--r--arch/arm/mach-versatile/clock.c2
-rw-r--r--arch/arm/mach-versatile/include/mach/platform.h18
-rw-r--r--arch/arm/mm/alignment.c26
-rw-r--r--arch/arm/mm/cache-feroceon-l2.c4
-rw-r--r--arch/arm/mm/fault.c1
-rw-r--r--arch/arm/mm/mmu.c6
-rw-r--r--arch/arm/plat-iop/setup.c5
-rw-r--r--arch/arm/plat-omap/gpio.c5
-rw-r--r--arch/arm/plat-omap/include/mach/omapfb.h4
-rw-r--r--arch/arm/plat-omap/include/mach/pm.h2
-rw-r--r--arch/arm/plat-omap/sram.c8
-rw-r--r--arch/arm/plat-orion/pcie.c2
-rw-r--r--arch/avr32/boards/favr-32/flash.c2
-rw-r--r--arch/avr32/boards/favr-32/setup.c8
-rw-r--r--arch/avr32/boot/images/Makefile2
-rw-r--r--arch/avr32/configs/atstk1006_defconfig134
-rw-r--r--arch/avr32/mach-at32ap/at32ap700x.c8
-rw-r--r--arch/blackfin/include/asm/bfin-global.h2
-rw-r--r--arch/blackfin/include/asm/dma-mapping.h6
-rw-r--r--arch/blackfin/kernel/bfin_gpio.c2
-rw-r--r--arch/blackfin/kernel/cplb-nompu/cplbinit.c9
-rw-r--r--arch/blackfin/kernel/process.c7
-rw-r--r--arch/blackfin/kernel/setup.c12
-rw-r--r--arch/blackfin/kernel/traps.c11
-rw-r--r--arch/blackfin/mach-common/cache.S8
-rw-r--r--arch/blackfin/mach-common/cpufreq.c14
-rw-r--r--arch/blackfin/mach-common/entry.S2
-rw-r--r--arch/blackfin/mm/sram-alloc.c8
-rw-r--r--arch/frv/kernel/sys_frv.c17
-rw-r--r--arch/ia64/configs/generic_defconfig218
-rw-r--r--arch/ia64/hp/sim/Kconfig1
-rw-r--r--arch/ia64/include/asm/intrinsics.h2
-rw-r--r--arch/ia64/include/asm/paravirt_privop.h12
-rw-r--r--arch/ia64/include/asm/ptrace.h2
-rw-r--r--arch/ia64/kernel/entry.S1
-rw-r--r--arch/ia64/kernel/head.S2
-rw-r--r--arch/ia64/kernel/mca.c2
-rw-r--r--arch/ia64/kernel/paravirt.c2
-rw-r--r--arch/ia64/kernel/pci-dma.c1
-rw-r--r--arch/ia64/kernel/topology.c4
-rw-r--r--arch/ia64/kvm/Kconfig2
-rw-r--r--arch/ia64/kvm/Makefile2
-rw-r--r--arch/ia64/kvm/kvm-ia64.c12
-rw-r--r--arch/ia64/kvm/optvfault.S11
-rw-r--r--arch/ia64/kvm/vcpu.h5
-rw-r--r--arch/ia64/sn/kernel/io_init.c2
-rw-r--r--arch/ia64/sn/kernel/irq.c9
-rw-r--r--arch/ia64/sn/kernel/setup.c9
-rw-r--r--arch/ia64/xen/hypercall.S2
-rw-r--r--arch/m32r/kernel/head.S4
-rw-r--r--arch/m32r/kernel/vmlinux.lds.S1
-rw-r--r--arch/m68k/configs/amiga_defconfig126
-rw-r--r--arch/m68k/configs/apollo_defconfig115
-rw-r--r--arch/m68k/configs/atari_defconfig130
-rw-r--r--arch/m68k/configs/bvme6000_defconfig112
-rw-r--r--arch/m68k/configs/hp300_defconfig115
-rw-r--r--arch/m68k/configs/mac_defconfig125
-rw-r--r--arch/m68k/configs/multi_defconfig129
-rw-r--r--arch/m68k/configs/mvme147_defconfig112
-rw-r--r--arch/m68k/configs/mvme16x_defconfig112
-rw-r--r--arch/m68k/configs/q40_defconfig125
-rw-r--r--arch/m68k/configs/sun3_defconfig124
-rw-r--r--arch/m68k/configs/sun3x_defconfig115
-rw-r--r--arch/m68k/kernel/ints.c2
-rw-r--r--arch/mips/Kconfig.debug2
-rw-r--r--arch/mips/configs/fulong_defconfig921
-rw-r--r--arch/mips/configs/ip22_defconfig518
-rw-r--r--arch/mips/configs/ip32_defconfig1060
-rw-r--r--arch/mips/configs/malta_defconfig631
-rw-r--r--arch/mips/include/asm/asmmacro.h10
-rw-r--r--arch/mips/include/asm/bug.h29
-rw-r--r--arch/mips/include/asm/byteorder.h5
-rw-r--r--arch/mips/include/asm/elf.h2
-rw-r--r--arch/mips/include/asm/mach-rc32434/gpio.h2
-rw-r--r--arch/mips/include/asm/mach-rc32434/rb.h14
-rw-r--r--arch/mips/include/asm/pci.h5
-rw-r--r--arch/mips/include/asm/ptrace.h4
-rw-r--r--arch/mips/include/asm/time.h2
-rw-r--r--arch/mips/kernel/csrc-r4k.c2
-rw-r--r--arch/mips/kernel/scall32-o32.S7
-rw-r--r--arch/mips/kernel/scall64-n32.S2
-rw-r--r--arch/mips/kernel/scall64-o32.S16
-rw-r--r--arch/mips/kernel/vpe.c2
-rw-r--r--arch/mips/mm/dma-default.c3
-rw-r--r--arch/mips/mm/sc-ip22.c2
-rw-r--r--arch/mips/mti-malta/Makefile5
-rw-r--r--arch/mips/mti-malta/malta-amon.c6
-rw-r--r--arch/mips/mti-malta/malta-mtd.c63
-rw-r--r--arch/mips/mti-malta/malta-platform.c107
-rw-r--r--arch/mips/pci/pci.c24
-rw-r--r--arch/mips/rb532/devices.c2
-rw-r--r--arch/mips/rb532/gpio.c193
-rw-r--r--arch/mn10300/Kconfig.debug9
-rw-r--r--arch/mn10300/kernel/entry.S3
-rw-r--r--arch/mn10300/kernel/gdb-io-serial.c2
-rw-r--r--arch/mn10300/kernel/gdb-stub.c24
-rw-r--r--arch/mn10300/kernel/mn10300-serial.c5
-rw-r--r--arch/mn10300/kernel/module.c35
-rw-r--r--arch/mn10300/kernel/setup.c2
-rw-r--r--arch/mn10300/kernel/vmlinux.lds.S22
-rw-r--r--arch/mn10300/mm/misalignment.c538
-rw-r--r--arch/parisc/include/asm/parisc-device.h4
-rw-r--r--arch/parisc/include/asm/posix_types.h3
-rw-r--r--arch/parisc/include/asm/ptrace.h2
-rw-r--r--arch/parisc/include/asm/smp.h2
-rw-r--r--arch/parisc/include/asm/tlbflush.h5
-rw-r--r--arch/parisc/kernel/drivers.c6
-rw-r--r--arch/parisc/kernel/ptrace.c10
-rw-r--r--arch/parisc/kernel/traps.c43
-rw-r--r--arch/powerpc/boot/Makefile1
-rw-r--r--arch/powerpc/boot/dts/mpc832x_rdb.dts4
-rw-r--r--arch/powerpc/boot/dts/mpc8349emitx.dts16
-rw-r--r--arch/powerpc/boot/dts/mpc8572ds.dts2
-rw-r--r--arch/powerpc/configs/40x/virtex_defconfig1176
-rw-r--r--arch/powerpc/configs/44x/virtex5_defconfig234
-rw-r--r--arch/powerpc/configs/52xx/cm5200_defconfig169
-rw-r--r--arch/powerpc/configs/52xx/lite5200b_defconfig206
-rw-r--r--arch/powerpc/configs/52xx/motionpro_defconfig168
-rw-r--r--arch/powerpc/configs/52xx/pcm030_defconfig182
-rw-r--r--arch/powerpc/configs/52xx/tqm5200_defconfig180
-rw-r--r--arch/powerpc/configs/83xx/mpc834x_itx_defconfig2
-rw-r--r--arch/powerpc/configs/86xx/gef_sbc610_defconfig2
-rw-r--r--arch/powerpc/configs/mpc5200_defconfig573
-rw-r--r--arch/powerpc/configs/mpc83xx_defconfig2
-rw-r--r--arch/powerpc/configs/ppc40x_defconfig92
-rw-r--r--arch/powerpc/configs/ppc44x_defconfig92
-rw-r--r--arch/powerpc/include/asm/kvm_ppc.h2
-rw-r--r--arch/powerpc/include/asm/mmu-hash64.h1
-rw-r--r--arch/powerpc/include/asm/ptrace.h2
-rw-r--r--arch/powerpc/kernel/cpu_setup_44x.S8
-rw-r--r--arch/powerpc/kernel/cputable.c3
-rw-r--r--arch/powerpc/kernel/dma.c1
-rw-r--r--arch/powerpc/kernel/entry_64.S8
-rw-r--r--arch/powerpc/kernel/misc_32.S5
-rw-r--r--arch/powerpc/kernel/prom_parse.c7
-rw-r--r--arch/powerpc/kernel/sysfs.c2
-rw-r--r--arch/powerpc/kvm/44x_tlb.c8
-rw-r--r--arch/powerpc/kvm/powerpc.c1
-rw-r--r--arch/powerpc/lib/rheap.c1
-rw-r--r--arch/powerpc/mm/40x_mmu.c16
-rw-r--r--arch/powerpc/mm/hugetlbpage.c5
-rw-r--r--arch/powerpc/mm/numa.c130
-rw-r--r--arch/powerpc/platforms/cell/axon_msi.c39
-rw-r--r--arch/powerpc/platforms/cell/smp.c9
-rw-r--r--arch/powerpc/platforms/cell/spufs/file.c3
-rw-r--r--arch/powerpc/sysdev/bestcomm/Kconfig9
-rw-r--r--arch/powerpc/sysdev/mpic.c11
-rw-r--r--arch/powerpc/sysdev/xilinx_intc.c4
-rw-r--r--arch/s390/defconfig74
-rw-r--r--arch/s390/include/asm/pgtable.h2
-rw-r--r--arch/s390/include/asm/ptrace.h4
-rw-r--r--arch/s390/include/asm/syscall.h28
-rw-r--r--arch/s390/kernel/asm-offsets.c2
-rw-r--r--arch/s390/kernel/compat_signal.c2
-rw-r--r--arch/s390/kernel/entry.S41
-rw-r--r--arch/s390/kernel/entry64.S34
-rw-r--r--arch/s390/kernel/init_task.c2
-rw-r--r--arch/s390/kernel/process.c3
-rw-r--r--arch/s390/kernel/ptrace.c2
-rw-r--r--arch/s390/kernel/setup.c4
-rw-r--r--arch/s390/kernel/signal.c6
-rw-r--r--arch/s390/kernel/sys_s390.c2
-rw-r--r--arch/s390/kernel/time.c13
-rw-r--r--arch/s390/kernel/topology.c11
-rw-r--r--arch/s390/kernel/vmlinux.lds.S3
-rw-r--r--arch/s390/kvm/sigp.c5
-rw-r--r--arch/sh/Kconfig2
-rw-r--r--arch/sh/include/asm/io.h4
-rw-r--r--arch/sh/include/asm/pgtable.h6
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7723.c6
-rw-r--r--arch/sh/kernel/early_printk.c3
-rw-r--r--arch/sh/kernel/timers/timer-tmu.c2
-rw-r--r--arch/sh/lib/copy_page.S11
-rw-r--r--arch/sh/mm/Makefile_322
-rw-r--r--arch/sh/mm/Makefile_642
-rw-r--r--arch/sh/mm/init.c12
-rw-r--r--arch/sh/mm/mmap.c31
-rw-r--r--arch/sh/mm/pg-sh4.c17
-rw-r--r--arch/sparc/include/asm/bitops_32.h1
-rw-r--r--arch/sparc/include/asm/ptrace_32.h10
-rw-r--r--arch/sparc/include/asm/ptrace_64.h11
-rw-r--r--arch/sparc/include/asm/termbits.h11
-rw-r--r--arch/sparc/include/asm/unistd_32.h3
-rw-r--r--arch/sparc/include/asm/unistd_64.h3
-rw-r--r--arch/sparc/kernel/cpu.c2
-rw-r--r--arch/sparc/kernel/head.S2
-rw-r--r--arch/sparc/kernel/of_device.c4
-rw-r--r--arch/sparc/kernel/smp.c4
-rw-r--r--arch/sparc/kernel/sun4d_smp.c4
-rw-r--r--arch/sparc/kernel/sun4m_smp.c2
-rw-r--r--arch/sparc/kernel/systbls.S2
-rw-r--r--arch/sparc/kernel/trampoline.S4
-rw-r--r--arch/sparc/kernel/vmlinux.lds.S1
-rw-r--r--arch/sparc/mm/srmmu.c14
-rw-r--r--arch/sparc64/kernel/ptrace.c2
-rw-r--r--arch/sparc64/kernel/smp.c4
-rw-r--r--arch/sparc64/kernel/sys32.S13
-rw-r--r--arch/sparc64/kernel/systbls.S4
-rw-r--r--arch/sparc64/kernel/visemul.c6
-rw-r--r--arch/sparc64/lib/user_fixup.c2
-rw-r--r--arch/sparc64/mm/init.c2
-rw-r--r--arch/um/drivers/mconsole_kern.c4
-rw-r--r--arch/x86/Kconfig7
-rw-r--r--arch/x86/Kconfig.cpu1
-rw-r--r--arch/x86/boot/tty.c2
-rw-r--r--arch/x86/include/asm/acpi.h1
-rw-r--r--arch/x86/include/asm/amd_iommu_types.h24
-rw-r--r--arch/x86/include/asm/dma-mapping.h6
-rw-r--r--arch/x86/include/asm/ds.h6
-rw-r--r--arch/x86/include/asm/iomap.h (renamed from include/asm-x86/iomap.h)0
-rw-r--r--arch/x86/include/asm/iommu.h1
-rw-r--r--arch/x86/include/asm/mmzone_32.h4
-rw-r--r--arch/x86/include/asm/pci_64.h14
-rw-r--r--arch/x86/include/asm/ptrace.h2
-rw-r--r--arch/x86/include/asm/topology.h2
-rw-r--r--arch/x86/include/asm/uaccess_64.h2
-rw-r--r--arch/x86/include/asm/unistd_64.h4
-rw-r--r--arch/x86/include/asm/vmi.h8
-rw-r--r--arch/x86/kernel/Makefile2
-rw-r--r--arch/x86/kernel/acpi/boot.c1
-rw-r--r--arch/x86/kernel/amd_iommu.c56
-rw-r--r--arch/x86/kernel/amd_iommu_init.c13
-rw-r--r--arch/x86/kernel/apic.c2
-rw-r--r--arch/x86/kernel/cpu/cpufreq/powernow-k8.c18
-rw-r--r--arch/x86/kernel/cpu/cpufreq/powernow-k8.h17
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce_64.c3
-rw-r--r--arch/x86/kernel/ds.c81
-rw-r--r--arch/x86/kernel/early-quirks.c18
-rw-r--r--arch/x86/kernel/es7000_32.c9
-rw-r--r--arch/x86/kernel/i387.c2
-rw-r--r--arch/x86/kernel/io_apic.c62
-rw-r--r--arch/x86/kernel/kvmclock.c2
-rw-r--r--arch/x86/kernel/microcode_core.c19
-rw-r--r--arch/x86/kernel/microcode_intel.c6
-rw-r--r--arch/x86/kernel/mpparse.c3
-rw-r--r--arch/x86/kernel/paravirt-spinlocks.c3
-rw-r--r--arch/x86/kernel/pci-calgary_64.c2
-rw-r--r--arch/x86/kernel/pci-gart_64.c6
-rw-r--r--arch/x86/kernel/reboot.c9
-rw-r--r--arch/x86/kernel/setup.c14
-rw-r--r--arch/x86/kernel/smpboot.c2
-rw-r--r--arch/x86/kernel/tsc_sync.c4
-rw-r--r--arch/x86/kernel/vmi_32.c16
-rw-r--r--arch/x86/kernel/xsave.c2
-rw-r--r--arch/x86/kvm/Kconfig2
-rw-r--r--arch/x86/kvm/i8254.c4
-rw-r--r--arch/x86/kvm/mmu.c4
-rw-r--r--arch/x86/kvm/paging_tmpl.h1
-rw-r--r--arch/x86/kvm/vmx.c7
-rw-r--r--arch/x86/kvm/vmx.h1
-rw-r--r--arch/x86/mach-voyager/voyager_smp.c16
-rw-r--r--arch/x86/mm/numa_32.c35
-rw-r--r--arch/x86/oprofile/nmi_int.c5
-rw-r--r--arch/x86/oprofile/op_model_ppro.c6
-rw-r--r--arch/x86/pci/fixup.c25
-rw-r--r--arch/x86/power/hibernate_32.c4
-rw-r--r--arch/x86/xen/mmu.c21
-rw-r--r--arch/x86/xen/smp.c2
-rw-r--r--arch/x86/xen/xen-ops.h2
-rw-r--r--block/blk-barrier.c4
-rw-r--r--block/blk-core.c26
-rw-r--r--block/blk-map.c8
-rw-r--r--block/blk-settings.c4
-rw-r--r--block/bsg.c2
-rw-r--r--block/compat_ioctl.c31
-rw-r--r--block/elevator.c7
-rw-r--r--block/genhd.c4
-rw-r--r--block/ioctl.c7
-rw-r--r--block/scsi_ioctl.c2
-rw-r--r--crypto/Kconfig36
-rw-r--r--crypto/Makefile18
-rw-r--r--crypto/async_tx/async_xor.c11
-rw-r--r--drivers/acpi/Kconfig22
-rw-r--r--drivers/acpi/Makefile8
-rw-r--r--drivers/acpi/ac.c3
-rw-r--r--drivers/acpi/acpi_memhotplug.c1
-rw-r--r--drivers/acpi/battery.c3
-rw-r--r--drivers/acpi/blacklist.c401
-rw-r--r--drivers/acpi/bus.c3
-rw-r--r--drivers/acpi/button.c3
-rw-r--r--drivers/acpi/cm_sbs.c7
-rw-r--r--drivers/acpi/container.c1
-rw-r--r--drivers/acpi/debug.c15
-rw-r--r--drivers/acpi/ec.c98
-rw-r--r--drivers/acpi/events/evgpe.c2
-rw-r--r--drivers/acpi/events/evxfevnt.c41
-rw-r--r--drivers/acpi/fan.c1
-rw-r--r--drivers/acpi/glue.c40
-rw-r--r--drivers/acpi/osl.c104
-rw-r--r--drivers/acpi/pci_link.c11
-rw-r--r--drivers/acpi/pci_root.c6
-rw-r--r--drivers/acpi/power.c11
-rw-r--r--drivers/acpi/processor_core.c93
-rw-r--r--drivers/acpi/processor_idle.c1
-rw-r--r--drivers/acpi/processor_perflib.c2
-rw-r--r--drivers/acpi/processor_thermal.c1
-rw-r--r--drivers/acpi/processor_throttling.c2
-rw-r--r--drivers/acpi/reboot.c25
-rw-r--r--drivers/acpi/scan.c52
-rw-r--r--drivers/acpi/sleep/main.c40
-rw-r--r--drivers/acpi/sleep/proc.c2
-rw-r--r--drivers/acpi/sleep/wakeup.c8
-rw-r--r--drivers/acpi/system.c48
-rw-r--r--drivers/acpi/tables/tbfadt.c2
-rw-r--r--drivers/acpi/thermal.c9
-rw-r--r--drivers/acpi/toshiba_acpi.c56
-rw-r--r--drivers/acpi/utilities/utglobal.c2
-rw-r--r--drivers/acpi/utils.c16
-rw-r--r--drivers/acpi/video.c42
-rw-r--r--drivers/acpi/video_detect.c267
-rw-r--r--drivers/acpi/wmi.c2
-rw-r--r--drivers/ata/Kconfig44
-rw-r--r--drivers/ata/ata_piix.c22
-rw-r--r--drivers/ata/libata-core.c74
-rw-r--r--drivers/ata/libata-sff.c13
-rw-r--r--drivers/ata/pata_hpt366.c16
-rw-r--r--drivers/ata/pata_ninja32.c9
-rw-r--r--drivers/ata/pata_rb532_cf.c15
-rw-r--r--drivers/ata/pata_sis.c1
-rw-r--r--drivers/atm/horizon.c2
-rw-r--r--drivers/block/Kconfig29
-rw-r--r--drivers/block/cciss.c14
-rw-r--r--drivers/block/floppy.c2
-rw-r--r--drivers/block/pktcdvd.c6
-rw-r--r--drivers/block/ub.c20
-rw-r--r--drivers/block/xen-blkfront.c8
-rw-r--r--drivers/block/xsysace.c23
-rw-r--r--drivers/cdrom/cdrom.c16
-rw-r--r--drivers/char/Kconfig24
-rw-r--r--drivers/char/agp/uninorth-agp.c2
-rw-r--r--drivers/char/cp437.uni12
-rw-r--r--drivers/char/ipmi/ipmi_msghandler.c20
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c16
-rw-r--r--drivers/char/istallion.c4
-rw-r--r--drivers/char/serial167.c2
-rw-r--r--drivers/char/sonypi.c4
-rw-r--r--drivers/char/specialix.c2
-rw-r--r--drivers/char/tty_io.c15
-rw-r--r--drivers/char/vt.c2
-rw-r--r--drivers/char/xilinx_hwicap/buffer_icap.c3
-rw-r--r--drivers/char/xilinx_hwicap/buffer_icap.h3
-rw-r--r--drivers/char/xilinx_hwicap/fifo_icap.c3
-rw-r--r--drivers/char/xilinx_hwicap/fifo_icap.h3
-rw-r--r--drivers/char/xilinx_hwicap/xilinx_hwicap.c12
-rw-r--r--drivers/char/xilinx_hwicap/xilinx_hwicap.h3
-rw-r--r--drivers/crypto/talitos.c4
-rw-r--r--drivers/dma/dmaengine.c7
-rw-r--r--drivers/dma/dmatest.c22
-rw-r--r--drivers/dma/ioat_dma.c5
-rw-r--r--drivers/dma/iop-adma.c27
-rw-r--r--drivers/dma/mv_xor.c15
-rw-r--r--drivers/edac/edac_device.c12
-rw-r--r--drivers/edac/i5000_edac.c4
-rw-r--r--drivers/edac/i82875p_edac.c14
-rw-r--r--drivers/firewire/fw-ohci.c11
-rw-r--r--drivers/firewire/fw-sbp2.c5
-rw-r--r--drivers/firewire/fw-transaction.c3
-rw-r--r--drivers/firewire/fw-transaction.h2
-rw-r--r--drivers/gpio/Kconfig8
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/gpiolib.c2
-rw-r--r--drivers/gpio/xilinx_gpio.c235
-rw-r--r--drivers/gpu/drm/drm_drv.c2
-rw-r--r--drivers/gpu/drm/drm_irq.c4
-rw-r--r--drivers/gpu/drm/i915/i915_dma.c22
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h28
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c722
-rw-r--r--drivers/gpu/drm/i915/i915_gem_proc.c5
-rw-r--r--drivers/gpu/drm/i915/i915_gem_tiling.c7
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c293
-rw-r--r--drivers/gpu/drm/i915/i915_opregion.c18
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h1
-rw-r--r--drivers/gpu/drm/i915/i915_suspend.c6
-rw-r--r--drivers/gpu/drm/mga/mga_dma.c8
-rw-r--r--drivers/gpu/drm/mga/mga_irq.c5
-rw-r--r--drivers/gpu/drm/r128/r128_drv.c6
-rw-r--r--drivers/gpu/drm/r128/r128_drv.h1
-rw-r--r--drivers/gpu/drm/r128/r128_irq.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_cp.c6
-rw-r--r--drivers/gpu/drm/radeon/radeon_drv.h1
-rw-r--r--drivers/gpu/drm/radeon/radeon_irq.c13
-rw-r--r--drivers/gpu/drm/via/via_irq.c1
-rw-r--r--drivers/gpu/drm/via/via_map.c11
-rw-r--r--drivers/hid/hid-apple.c17
-rw-r--r--drivers/hid/hid-core.c20
-rw-r--r--drivers/hid/hid-ids.h4
-rw-r--r--drivers/hid/hid-pl.c2
-rw-r--r--drivers/hid/hidraw.c30
-rw-r--r--drivers/hid/usbhid/hid-core.c43
-rw-r--r--drivers/hid/usbhid/usbhid.h1
-rw-r--r--drivers/hwmon/Kconfig29
-rw-r--r--drivers/hwmon/Makefile2
-rw-r--r--drivers/hwmon/adt7462.c2002
-rw-r--r--drivers/hwmon/adt7470.c75
-rw-r--r--drivers/hwmon/adt7473.c89
-rw-r--r--drivers/hwmon/applesmc.c20
-rw-r--r--drivers/hwmon/ibmaem.c18
-rw-r--r--drivers/hwmon/lis3lv02d.c581
-rw-r--r--drivers/hwmon/lis3lv02d.h149
-rw-r--r--drivers/hwmon/lm85.c52
-rw-r--r--drivers/i2c/busses/i2c-cpm.c1
-rw-r--r--drivers/i2c/busses/i2c-highlander.c4
-rw-r--r--drivers/i2c/busses/i2c-parport.c4
-rw-r--r--drivers/i2c/busses/i2c-pmcmsp.c2
-rw-r--r--drivers/i2c/busses/i2c-s3c2410.c18
-rw-r--r--drivers/i2c/busses/i2c-sh_mobile.c3
-rw-r--r--drivers/i2c/chips/isp1301_omap.c65
-rw-r--r--drivers/i2c/i2c-core.c2
-rw-r--r--drivers/ide/Kconfig14
-rw-r--r--drivers/ide/alim15x3.c2
-rw-r--r--drivers/ide/amd74xx.c11
-rw-r--r--drivers/ide/cs5530.c3
-rw-r--r--drivers/ide/icside.c4
-rw-r--r--drivers/ide/ide-cs.c1
-rw-r--r--drivers/ide/ide-io.c24
-rw-r--r--drivers/ide/ide-iops.c9
-rw-r--r--drivers/ide/ide-probe.c3
-rw-r--r--drivers/ide/pmac.c30
-rw-r--r--drivers/ide/sc1200.c3
-rw-r--r--drivers/ide/sgiioc4.c6
-rw-r--r--drivers/idle/Kconfig3
-rw-r--r--drivers/ieee1394/highlevel.c25
-rw-r--r--drivers/ieee1394/hosts.h4
-rw-r--r--drivers/ieee1394/nodemgr.c8
-rw-r--r--drivers/ieee1394/sbp2.c14
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_provider.c6
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_qp.c1
-rw-r--r--drivers/infiniband/hw/ehca/ehca_classes.h4
-rw-r--r--drivers/infiniband/hw/ehca/ehca_irq.c44
-rw-r--r--drivers/infiniband/hw/ehca/ehca_main.c3
-rw-r--r--drivers/infiniband/hw/ehca/ehca_qp.c31
-rw-r--r--drivers/infiniband/hw/ehca/ehca_reqs.c51
-rw-r--r--drivers/infiniband/hw/ipath/ipath_ruc.c10
-rw-r--r--drivers/infiniband/hw/mlx4/cq.c5
-rw-r--r--drivers/infiniband/hw/mlx4/mr.c1
-rw-r--r--drivers/infiniband/hw/nes/nes.c16
-rw-r--r--drivers/infiniband/hw/nes/nes_hw.h1
-rw-r--r--drivers/infiniband/hw/nes/nes_verbs.c64
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c6
-rw-r--r--drivers/input/ff-memless.c5
-rw-r--r--drivers/input/keyboard/atkbd.c27
-rw-r--r--drivers/input/misc/cm109.c37
-rw-r--r--drivers/input/mouse/hgpk.c2
-rw-r--r--drivers/input/serio/i8042-x86ia64io.h14
-rw-r--r--drivers/input/tablet/wacom.h13
-rw-r--r--drivers/input/tablet/wacom_sys.c228
-rw-r--r--drivers/input/tablet/wacom_wac.c160
-rw-r--r--drivers/input/tablet/wacom_wac.h4
-rw-r--r--drivers/input/touchscreen/elo.c2
-rw-r--r--drivers/input/xen-kbdfront.c6
-rw-r--r--drivers/isdn/hardware/avm/b1isa.c6
-rw-r--r--drivers/isdn/hisax/config.c16
-rw-r--r--drivers/isdn/hysdn/hysdn_net.c4
-rw-r--r--drivers/isdn/i4l/isdn_net.c6
-rw-r--r--drivers/macintosh/rack-meter.c10
-rw-r--r--drivers/md/bitmap.c22
-rw-r--r--drivers/md/dm-mpath.c8
-rw-r--r--drivers/md/dm-raid1.c1
-rw-r--r--drivers/md/dm-stripe.c4
-rw-r--r--drivers/md/dm-table.c2
-rw-r--r--drivers/md/dm.c34
-rw-r--r--drivers/media/dvb/b2c2/Kconfig2
-rw-r--r--drivers/media/dvb/b2c2/flexcop-fe-tuner.c2
-rw-r--r--drivers/media/dvb/b2c2/flexcop-i2c.c6
-rw-r--r--drivers/media/dvb/bt8xx/Kconfig2
-rw-r--r--drivers/media/dvb/dm1105/dm1105.c2
-rw-r--r--drivers/media/dvb/dvb-core/dvb_frontend.c5
-rw-r--r--drivers/media/dvb/dvb-usb/Kconfig46
-rw-r--r--drivers/media/dvb/dvb-usb/af9015.c8
-rw-r--r--drivers/media/dvb/dvb-usb/dib0700.h5
-rw-r--r--drivers/media/dvb/dvb-usb/dib0700_core.c16
-rw-r--r--drivers/media/dvb/dvb-usb/dib0700_devices.c143
-rw-r--r--drivers/media/dvb/dvb-usb/usb-urb.c19
-rw-r--r--drivers/media/dvb/siano/sms-cards.c2
-rw-r--r--drivers/media/dvb/ttpci/Kconfig2
-rw-r--r--drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c15
-rw-r--r--drivers/media/dvb/ttusb-dec/ttusb_dec.c7
-rw-r--r--drivers/media/video/compat_ioctl32.c2
-rw-r--r--drivers/media/video/cx18/Kconfig2
-rw-r--r--drivers/media/video/cx23885/Kconfig4
-rw-r--r--drivers/media/video/cx88/Kconfig2
-rw-r--r--drivers/media/video/em28xx/em28xx-audio.c33
-rw-r--r--drivers/media/video/em28xx/em28xx-core.c58
-rw-r--r--drivers/media/video/em28xx/em28xx-i2c.c10
-rw-r--r--drivers/media/video/em28xx/em28xx-video.c143
-rw-r--r--drivers/media/video/em28xx/em28xx.h6
-rw-r--r--drivers/media/video/gspca/conex.c3
-rw-r--r--drivers/media/video/gspca/finepix.c8
-rw-r--r--drivers/media/video/gspca/gspca.c60
-rw-r--r--drivers/media/video/gspca/gspca.h6
-rw-r--r--drivers/media/video/gspca/pac7311.c3
-rw-r--r--drivers/media/video/gspca/spca501.c3
-rw-r--r--drivers/media/video/gspca/spca505.c4
-rw-r--r--drivers/media/video/gspca/spca561.c3
-rw-r--r--drivers/media/video/gspca/vc032x.c3
-rw-r--r--drivers/media/video/gspca/zc3xx.c3
-rw-r--r--drivers/media/video/pvrusb2/Kconfig2
-rw-r--r--drivers/media/video/s2255drv.c2
-rw-r--r--drivers/media/video/saa7134/Kconfig4
-rw-r--r--drivers/media/video/tvaudio.c231
-rw-r--r--drivers/message/fusion/mptscsih.c3
-rw-r--r--drivers/message/i2o/i2o_block.c2
-rw-r--r--drivers/message/i2o/iop.c1
-rw-r--r--drivers/mfd/da903x.c2
-rw-r--r--drivers/mfd/wm8350-i2c.c15
-rw-r--r--drivers/misc/Kconfig16
-rw-r--r--drivers/misc/Makefile2
-rw-r--r--drivers/misc/acer-wmi.c6
-rw-r--r--drivers/misc/asus-laptop.c10
-rw-r--r--drivers/misc/c2port/Kconfig35
-rw-r--r--drivers/misc/c2port/Makefile3
-rw-r--r--drivers/misc/c2port/c2port-duramar2150.c158
-rw-r--r--drivers/misc/c2port/core.c1003
-rw-r--r--drivers/misc/compal-laptop.c12
-rw-r--r--drivers/misc/eeepc-laptop.c12
-rw-r--r--drivers/misc/fujitsu-laptop.c43
-rw-r--r--drivers/misc/ics932s401.c515
-rw-r--r--drivers/misc/intel_menlow.c10
-rw-r--r--drivers/misc/msi-laptop.c16
-rw-r--r--drivers/misc/sgi-gru/Makefile4
-rw-r--r--drivers/misc/sgi-gru/grufault.c4
-rw-r--r--drivers/misc/sgi-gru/grufile.c2
-rw-r--r--drivers/misc/sony-laptop.c6
-rw-r--r--drivers/misc/thinkpad_acpi.c86
-rw-r--r--drivers/mtd/devices/m25p80.c28
-rw-r--r--drivers/mtd/maps/cdb89712.c13
-rw-r--r--drivers/mtd/maps/h720x-flash.c6
-rw-r--r--drivers/mtd/maps/physmap.c26
-rw-r--r--drivers/mtd/nand/fsl_upm.c8
-rw-r--r--drivers/mtd/nand/pasemi_nand.c1
-rw-r--r--drivers/mtd/nand/pxa3xx_nand.c1
-rw-r--r--drivers/mtd/onenand/omap2.c17
-rw-r--r--drivers/mtd/ubi/eba.c2
-rw-r--r--drivers/mtd/ubi/scan.c2
-rw-r--r--drivers/mtd/ubi/wl.c3
-rw-r--r--drivers/net/Kconfig3
-rw-r--r--drivers/net/Makefile2
-rw-r--r--drivers/net/atl1e/atl1e_hw.c4
-rw-r--r--drivers/net/atlx/atl1.c17
-rw-r--r--drivers/net/atlx/atl2.c8
-rw-r--r--drivers/net/bnx2.c50
-rw-r--r--drivers/net/bnx2.h6
-rw-r--r--drivers/net/chelsio/sge.c4
-rw-r--r--drivers/net/cxgb3/cxgb3_main.c4
-rw-r--r--drivers/net/cxgb3/t3_hw.c8
-rw-r--r--drivers/net/e100.c20
-rw-r--r--drivers/net/e1000/e1000_ethtool.c8
-rw-r--r--drivers/net/e1000/e1000_main.c1
-rw-r--r--drivers/net/e1000e/e1000.h5
-rw-r--r--drivers/net/e1000e/ethtool.c8
-rw-r--r--drivers/net/e1000e/ich8lan.c9
-rw-r--r--drivers/net/e1000e/netdev.c26
-rw-r--r--drivers/net/e1000e/param.c25
-rw-r--r--drivers/net/enc28j60.c18
-rw-r--r--drivers/net/gianfar.c15
-rw-r--r--drivers/net/hp-plus.c2
-rw-r--r--drivers/net/igb/igb_ethtool.c8
-rw-r--r--drivers/net/igb/igb_main.c12
-rw-r--r--drivers/net/ipg.c8
-rw-r--r--drivers/net/ixgbe/ixgbe_main.c68
-rw-r--r--drivers/net/jme.c21
-rw-r--r--drivers/net/jme.h2
-rw-r--r--drivers/net/macvlan.c3
-rw-r--r--drivers/net/mlx4/en_netdev.c8
-rw-r--r--drivers/net/mlx4/en_params.c30
-rw-r--r--drivers/net/mlx4/main.c8
-rw-r--r--drivers/net/mlx4/mlx4.h10
-rw-r--r--drivers/net/mlx4/mlx4_en.h8
-rw-r--r--drivers/net/mlx4/port.c39
-rw-r--r--drivers/net/mv643xx_eth.c5
-rw-r--r--drivers/net/myri10ge/myri10ge.c4
-rw-r--r--drivers/net/netx-eth.c2
-rw-r--r--drivers/net/niu.c293
-rw-r--r--drivers/net/niu.h13
-rw-r--r--drivers/net/pcmcia/axnet_cs.c2
-rw-r--r--drivers/net/pcmcia/ibmtr_cs.c2
-rw-r--r--drivers/net/pcmcia/pcnet_cs.c1
-rw-r--r--drivers/net/phy/marvell.c66
-rw-r--r--drivers/net/phy/mdio_bus.c7
-rw-r--r--drivers/net/phy/phy_device.c47
-rw-r--r--drivers/net/phy/vitesse.c64
-rw-r--r--drivers/net/ppp_generic.c28
-rw-r--r--drivers/net/pppol2tp.c1
-rw-r--r--drivers/net/qla3xxx.c19
-rw-r--r--drivers/net/sh_eth.c4
-rw-r--r--drivers/net/sis900.c1
-rw-r--r--drivers/net/smc911x.c16
-rw-r--r--drivers/net/smc91x.c10
-rw-r--r--drivers/net/spider_net.c4
-rw-r--r--drivers/net/starfire.c5
-rw-r--r--drivers/net/sungem.c144
-rw-r--r--drivers/net/tlan.c23
-rw-r--r--drivers/net/ucc_geth_ethtool.c6
-rw-r--r--drivers/net/usb/asix.c8
-rw-r--r--drivers/net/via-velocity.c2
-rw-r--r--drivers/net/wireless/ath5k/base.c35
-rw-r--r--drivers/net/wireless/ath5k/base.h1
-rw-r--r--drivers/net/wireless/ath5k/debug.c10
-rw-r--r--drivers/net/wireless/ath9k/beacon.c10
-rw-r--r--drivers/net/wireless/ath9k/recv.c19
-rw-r--r--drivers/net/wireless/hostap/hostap_wlan.h5
-rw-r--r--drivers/net/wireless/ipw2200.c4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c13
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-rx.c26
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.c24
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c1
-rw-r--r--drivers/net/wireless/libertas_tf/if_usb.c2
-rw-r--r--drivers/net/wireless/rtl8187_dev.c3
-rw-r--r--drivers/net/wireless/zd1211rw/zd_mac.c2
-rw-r--r--drivers/net/xen-netfront.c6
-rw-r--r--drivers/parport/Kconfig2
-rw-r--r--drivers/parport/parport_serial.c2
-rw-r--r--drivers/pci/hotplug/acpiphp.h2
-rw-r--r--drivers/pci/hotplug/acpiphp_core.c2
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c4
-rw-r--r--drivers/pci/hotplug/ibmphp_core.c5
-rw-r--r--drivers/pci/hotplug/pciehp_core.c23
-rw-r--r--drivers/pci/intel-iommu.c6
-rw-r--r--drivers/pci/pci-acpi.c15
-rw-r--r--drivers/pci/pci.c6
-rw-r--r--drivers/pci/pcie/aer/aerdrv_core.c2
-rw-r--r--drivers/pci/pcie/aspm.c29
-rw-r--r--drivers/pci/quirks.c17
-rw-r--r--drivers/pci/slot.c1
-rw-r--r--drivers/pcmcia/bfin_cf_pcmcia.c2
-rw-r--r--drivers/pcmcia/cistpl.c3
-rw-r--r--drivers/pcmcia/cs.c14
-rw-r--r--drivers/pcmcia/ds.c11
-rw-r--r--drivers/pcmcia/pcmcia_resource.c3
-rw-r--r--drivers/pcmcia/rsrc_nonstatic.c6
-rw-r--r--drivers/rapidio/rio-scan.c4
-rw-r--r--drivers/rapidio/rio.c2
-rw-r--r--drivers/rtc/Kconfig29
-rw-r--r--drivers/rtc/Makefile3
-rw-r--r--drivers/rtc/rtc-ds1390.c220
-rw-r--r--drivers/rtc/rtc-ds1672.c6
-rw-r--r--drivers/rtc/rtc-isl1208.c7
-rw-r--r--drivers/rtc/rtc-max6900.c6
-rw-r--r--drivers/rtc/rtc-rx8581.c281
-rw-r--r--drivers/rtc/rtc-starfire.c66
-rw-r--r--drivers/rtc/rtc-sun4v.c69
-rw-r--r--drivers/rtc/rtc-twl4030.c2
-rw-r--r--drivers/rtc/rtc-wm8350.c514
-rw-r--r--drivers/s390/block/dasd.c5
-rw-r--r--drivers/s390/char/sclp_cmd.c3
-rw-r--r--drivers/s390/cio/device.c4
-rw-r--r--drivers/s390/kvm/kvm_virtio.c4
-rw-r--r--drivers/s390/scsi/zfcp_aux.c3
-rw-r--r--drivers/s390/scsi/zfcp_ccw.c4
-rw-r--r--drivers/s390/scsi/zfcp_dbf.c42
-rw-r--r--drivers/s390/scsi/zfcp_dbf.h8
-rw-r--r--drivers/s390/scsi/zfcp_erp.c8
-rw-r--r--drivers/s390/scsi/zfcp_fc.c7
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c43
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c14
-rw-r--r--drivers/scsi/aacraid/linit.c8
-rw-r--r--drivers/scsi/advansys.c4
-rw-r--r--drivers/scsi/device_handler/scsi_dh_hp_sw.c12
-rw-r--r--drivers/scsi/dpt_i2o.c4
-rw-r--r--drivers/scsi/gdth.c12
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.c2
-rw-r--r--drivers/scsi/ibmvscsi/ibmvstgt.c16
-rw-r--r--drivers/scsi/libiscsi.c11
-rw-r--r--drivers/scsi/megaraid.c11
-rw-r--r--drivers/scsi/megaraid.h2
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.c3
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h1
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c26
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c2
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c1
-rw-r--r--drivers/scsi/qla2xxx/qla_sup.c19
-rw-r--r--drivers/scsi/qla2xxx/qla_version.h2
-rw-r--r--drivers/scsi/scsi_error.c8
-rw-r--r--drivers/scsi/scsi_lib.c25
-rw-r--r--drivers/scsi/sd.c2
-rw-r--r--drivers/scsi/sr.c2
-rw-r--r--drivers/scsi/stex.c2
-rw-r--r--drivers/serial/ioc3_serial.c6
-rw-r--r--drivers/serial/mpc52xx_uart.c4
-rw-r--r--drivers/serial/s3c2440.c2
-rw-r--r--drivers/serial/sh-sci.c22
-rw-r--r--drivers/serial/sh-sci.h16
-rw-r--r--drivers/serial/uartlite.c4
-rw-r--r--drivers/sh/maple/maple.c2
-rw-r--r--drivers/spi/atmel_spi.c3
-rw-r--r--drivers/spi/au1550_spi.c26
-rw-r--r--drivers/spi/mpc52xx_psc_spi.c5
-rw-r--r--drivers/spi/pxa2xx_spi.c24
-rw-r--r--drivers/spi/spi_imx.c70
-rw-r--r--drivers/spi/spi_s3c24xx_gpio.c3
-rw-r--r--drivers/spi/spidev.c4
-rw-r--r--drivers/staging/Kconfig3
-rw-r--r--drivers/usb/class/cdc-acm.c9
-rw-r--r--drivers/usb/class/usbtmc.c1
-rw-r--r--drivers/usb/core/driver.c4
-rw-r--r--drivers/usb/core/message.c1
-rw-r--r--drivers/usb/core/sysfs.c2
-rw-r--r--drivers/usb/core/urb.c4
-rw-r--r--drivers/usb/gadget/f_acm.c4
-rw-r--r--drivers/usb/gadget/f_rndis.c7
-rw-r--r--drivers/usb/gadget/fsl_qe_udc.c3
-rw-r--r--drivers/usb/gadget/fsl_usb2_udc.c3
-rw-r--r--drivers/usb/gadget/pxa25x_udc.c14
-rw-r--r--drivers/usb/host/Kconfig23
-rw-r--r--drivers/usb/host/ehci-hcd.c25
-rw-r--r--drivers/usb/host/ehci-pci.c24
-rw-r--r--drivers/usb/host/ehci-ps3.c1
-rw-r--r--drivers/usb/host/ehci-sched.c4
-rw-r--r--drivers/usb/host/ehci.h12
-rw-r--r--drivers/usb/host/isp1760-if.c22
-rw-r--r--drivers/usb/host/ohci-ps3.c3
-rw-r--r--drivers/usb/host/r8a66597-hcd.c5
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb.c1
-rw-r--r--drivers/usb/misc/vstusb.c2
-rw-r--r--drivers/usb/mon/mon_bin.c5
-rw-r--r--drivers/usb/musb/musb_core.c6
-rw-r--r--drivers/usb/musb/musb_debug.h4
-rw-r--r--drivers/usb/musb/musb_host.c159
-rw-r--r--drivers/usb/musb/musb_host.h1
-rw-r--r--drivers/usb/musb/omap2430.c2
-rw-r--r--drivers/usb/musb/tusb6010.c2
-rw-r--r--drivers/usb/serial/console.c1
-rw-r--r--drivers/usb/serial/cp2101.c3
-rw-r--r--drivers/usb/serial/ftdi_sio.c4
-rw-r--r--drivers/usb/serial/ftdi_sio.h6
-rw-r--r--drivers/usb/serial/option.c41
-rw-r--r--drivers/usb/serial/pl2303.c2
-rw-r--r--drivers/usb/serial/pl2303.h8
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.c55
-rw-r--r--drivers/usb/storage/Kconfig4
-rw-r--r--drivers/usb/storage/unusual_devs.h66
-rw-r--r--drivers/video/atmel_lcdfb.c2
-rw-r--r--drivers/video/aty/radeon_accel.c291
-rw-r--r--drivers/video/aty/radeon_backlight.c2
-rw-r--r--drivers/video/aty/radeon_base.c22
-rw-r--r--drivers/video/aty/radeon_pm.c6
-rw-r--r--drivers/video/aty/radeonfb.h38
-rw-r--r--drivers/video/backlight/da903x.c2
-rw-r--r--drivers/video/backlight/lcd.c11
-rw-r--r--drivers/video/cirrusfb.c3
-rw-r--r--drivers/video/console/fbcon.c15
-rw-r--r--drivers/video/fbmem.c2
-rw-r--r--drivers/video/macfb.c74
-rw-r--r--drivers/video/mb862xx/mb862xxfb.c4
-rw-r--r--drivers/video/omap/Makefile1
-rw-r--r--drivers/video/omap/lcd_sx1.c327
-rw-r--r--drivers/video/omap/omapfb_main.c2
-rw-r--r--drivers/video/pxafb.c5
-rw-r--r--drivers/video/tmiofb.c10
-rw-r--r--drivers/video/via/viafbdev.c17
-rw-r--r--drivers/video/xen-fbfront.c6
-rw-r--r--drivers/video/xilinxfb.c5
-rw-r--r--drivers/w1/masters/Kconfig9
-rw-r--r--drivers/w1/masters/Makefile1
-rw-r--r--drivers/w1/masters/omap_hdq.c725
-rw-r--r--drivers/w1/slaves/Kconfig7
-rw-r--r--drivers/w1/slaves/Makefile2
-rw-r--r--drivers/w1/slaves/w1_bq27000.c123
-rw-r--r--drivers/w1/w1.h1
-rw-r--r--drivers/w1/w1_io.c7
-rw-r--r--drivers/watchdog/hpwdt.c5
-rw-r--r--drivers/watchdog/iTCO_vendor_support.c31
-rw-r--r--drivers/watchdog/iTCO_wdt.c164
-rw-r--r--drivers/watchdog/mtx-1_wdt.c4
-rw-r--r--drivers/xen/balloon.c9
-rw-r--r--fs/9p/fid.c4
-rw-r--r--fs/9p/v9fs.c2
-rw-r--r--fs/9p/vfs_dentry.c9
-rw-r--r--fs/9p/vfs_inode.c6
-rw-r--r--fs/block_dev.c21
-rw-r--r--fs/buffer.c1
-rw-r--r--fs/cifs/CHANGES6
-rw-r--r--fs/cifs/cifs_debug.c277
-rw-r--r--fs/cifs/cifs_dfs_ref.c71
-rw-r--r--fs/cifs/cifs_spnego.c4
-rw-r--r--fs/cifs/cifsfs.c30
-rw-r--r--fs/cifs/cifsglob.h49
-rw-r--r--fs/cifs/cifssmb.c135
-rw-r--r--fs/cifs/connect.c825
-rw-r--r--fs/cifs/file.c105
-rw-r--r--fs/cifs/misc.c93
-rw-r--r--fs/cifs/readdir.c5
-rw-r--r--fs/dlm/lockspace.c2
-rw-r--r--fs/ecryptfs/keystore.c31
-rw-r--r--fs/eventpoll.c85
-rw-r--r--fs/exec.c10
-rw-r--r--fs/exportfs/expfs.c4
-rw-r--r--fs/ext3/super.c7
-rw-r--r--fs/ext4/balloc.c4
-rw-r--r--fs/fcntl.c7
-rw-r--r--fs/hostfs/hostfs.h2
-rw-r--r--fs/hostfs/hostfs_kern.c4
-rw-r--r--fs/hostfs/hostfs_user.c2
-rw-r--r--fs/inotify.c152
-rw-r--r--fs/ioctl.c12
-rw-r--r--fs/lockd/host.c3
-rw-r--r--fs/lockd/svc.c1
-rw-r--r--fs/namei.c2
-rw-r--r--fs/namespace.c4
-rw-r--r--fs/nfsd/nfs4recover.c2
-rw-r--r--fs/nfsd/nfs4state.c1
-rw-r--r--fs/ntfs/debug.h8
-rw-r--r--fs/ocfs2/buffer_head_io.c15
-rw-r--r--fs/ocfs2/dlm/dlmfs.c4
-rw-r--r--fs/ocfs2/dlm/userdlm.h2
-rw-r--r--fs/ocfs2/dlmglue.c3
-rw-r--r--fs/ocfs2/ocfs2.h2
-rw-r--r--fs/ocfs2/ocfs2_fs.h8
-rw-r--r--fs/ocfs2/stack_user.c3
-rw-r--r--fs/ocfs2/xattr.c4
-rw-r--r--fs/partitions/check.c31
-rw-r--r--fs/proc/base.c2
-rw-r--r--fs/proc/proc_sysctl.c1
-rw-r--r--fs/proc/task_mmu.c4
-rw-r--r--fs/ubifs/commit.c4
-rw-r--r--fs/ubifs/debug.c66
-rw-r--r--fs/ubifs/dir.c5
-rw-r--r--fs/ubifs/file.c91
-rw-r--r--fs/ubifs/journal.c8
-rw-r--r--fs/ubifs/key.h4
-rw-r--r--fs/ubifs/lpt_commit.c2
-rw-r--r--fs/ubifs/orphan.c28
-rw-r--r--fs/ubifs/recovery.c17
-rw-r--r--fs/ubifs/replay.c2
-rw-r--r--fs/ubifs/sb.c9
-rw-r--r--fs/ubifs/super.c70
-rw-r--r--fs/ubifs/tnc.c12
-rw-r--r--fs/ubifs/ubifs.h12
-rw-r--r--fs/udf/inode.c1
-rw-r--r--fs/xfs/xfs_rename.c2
-rw-r--r--include/acpi/acoutput.h2
-rw-r--r--include/acpi/acpi_bus.h2
-rw-r--r--include/acpi/acpi_drivers.h22
-rw-r--r--include/acpi/acpixf.h4
-rw-r--r--include/acpi/acpredef.h4
-rw-r--r--include/acpi/actypes.h1
-rw-r--r--include/acpi/platform/aclinux.h6
-rw-r--r--include/asm-generic/atomic.h2
-rw-r--r--include/asm-generic/audit_write.h2
-rw-r--r--include/asm-mn10300/uaccess.h2
-rw-r--r--include/drm/drmP.h1
-rw-r--r--include/linux/acpi.h48
-rw-r--r--include/linux/audit.h6
-rw-r--r--include/linux/blkdev.h10
-rw-r--r--include/linux/c2port.h65
-rw-r--r--include/linux/can/core.h2
-rw-r--r--include/linux/compat.h2
-rw-r--r--include/linux/cpuset.h4
-rw-r--r--include/linux/fs.h33
-rw-r--r--include/linux/ftrace.h3
-rw-r--r--include/linux/genhd.h4
-rw-r--r--include/linux/highmem.h2
-rw-r--r--include/linux/hrtimer.h5
-rw-r--r--include/linux/ide.h8
-rw-r--r--include/linux/idr.h3
-rw-r--r--include/linux/inotify.h11
-rw-r--r--include/linux/input.h4
-rw-r--r--include/linux/irq.h11
-rw-r--r--include/linux/kernel.h42
-rw-r--r--include/linux/libata.h1
-rw-r--r--include/linux/lockdep.h5
-rw-r--r--include/linux/memory.h2
-rw-r--r--include/linux/mfd/wm8350/audio.h38
-rw-r--r--include/linux/mfd/wm8350/rtc.h2
-rw-r--r--include/linux/mlx4/device.h1
-rw-r--r--include/linux/net.h6
-rw-r--r--include/linux/netdevice.h7
-rw-r--r--include/linux/netfilter/nfnetlink_conntrack.h1
-rw-r--r--include/linux/netfilter/x_tables.h2
-rw-r--r--include/linux/page_cgroup.h4
-rw-r--r--include/linux/ratelimit.h7
-rw-r--r--include/linux/ring_buffer.h3
-rw-r--r--include/linux/sched.h4
-rw-r--r--include/linux/security.h12
-rw-r--r--include/linux/serial_core.h3
-rw-r--r--include/linux/slab.h28
-rw-r--r--include/linux/smp.h2
-rw-r--r--include/linux/syscalls.h3
-rw-r--r--include/linux/usb.h2
-rw-r--r--include/linux/usb/ch9.h8
-rw-r--r--include/net/af_unix.h1
-rw-r--r--include/net/irda/irda_device.h4
-rw-r--r--include/net/mac80211.h20
-rw-r--r--include/net/request_sock.h1
-rw-r--r--include/net/sock.h2
-rw-r--r--include/net/timewait_sock.h1
-rw-r--r--include/scsi/scsi_transport_fc.h2
-rw-r--r--include/sound/ac97_codec.h2
-rw-r--r--include/sound/asound.h1
-rw-r--r--include/sound/core.h28
-rw-r--r--include/sound/jack.h2
-rw-r--r--include/sound/l3.h18
-rw-r--r--include/sound/s3c24xx_uda134x.h14
-rw-r--r--include/sound/soc-dai.h231
-rw-r--r--include/sound/soc-dapm.h2
-rw-r--r--include/sound/soc.h206
-rw-r--r--include/sound/uda134x.h26
-rw-r--r--include/sound/version.h2
-rw-r--r--include/video/atmel_lcdc.h2
-rw-r--r--include/video/radeon.h18
-rw-r--r--init/Kconfig8
-rw-r--r--ipc/util.c14
-rw-r--r--kernel/Makefile4
-rw-r--r--kernel/audit.c32
-rw-r--r--kernel/audit_tree.c91
-rw-r--r--kernel/auditfilter.c14
-rw-r--r--kernel/auditsc.c24
-rw-r--r--kernel/cgroup.c31
-rw-r--r--kernel/cgroup_freezer.c19
-rw-r--r--kernel/cpu.c2
-rw-r--r--kernel/cpuset.c33
-rw-r--r--kernel/exit.c9
-rw-r--r--kernel/fork.c27
-rw-r--r--kernel/hrtimer.c9
-rw-r--r--kernel/irq/internals.h2
-rw-r--r--kernel/irq/manage.c68
-rw-r--r--kernel/irq/migration.c11
-rw-r--r--kernel/irq/proc.c2
-rw-r--r--kernel/kallsyms.c17
-rw-r--r--kernel/kprobes.c23
-rw-r--r--kernel/latencytop.c2
-rw-r--r--kernel/lockdep.c4
-rw-r--r--kernel/panic.c1
-rw-r--r--kernel/posix-cpu-timers.c9
-rw-r--r--kernel/posix-timers.c6
-rw-r--r--kernel/power/main.c2
-rw-r--r--kernel/power/swap.c2
-rw-r--r--kernel/profile.c6
-rw-r--r--kernel/ptrace.c4
-rw-r--r--kernel/relay.c16
-rw-r--r--kernel/sched.c25
-rw-r--r--kernel/sched_clock.c6
-rw-r--r--kernel/sched_debug.c5
-rw-r--r--kernel/sched_stats.h15
-rw-r--r--kernel/softlockup.c2
-rw-r--r--kernel/stop_machine.c5
-rw-r--r--kernel/sys_ni.c2
-rw-r--r--kernel/sysctl.c10
-rw-r--r--kernel/time/timekeeping.c22
-rw-r--r--kernel/trace/ftrace.c147
-rw-r--r--kernel/trace/ring_buffer.c118
-rw-r--r--kernel/trace/trace.c1
-rw-r--r--kernel/trace/trace_mmiotrace.c16
-rw-r--r--kernel/trace/trace_stack.c24
-rw-r--r--lib/dynamic_printk.c6
-rw-r--r--lib/idr.c22
-rw-r--r--lib/percpu_counter.c7
-rw-r--r--lib/scatterlist.c2
-rw-r--r--lib/swiotlb.c10
-rw-r--r--mm/backing-dev.c3
-rw-r--r--mm/hugetlb.c5
-rw-r--r--mm/memory_hotplug.c12
-rw-r--r--mm/migrate.c64
-rw-r--r--mm/mlock.c18
-rw-r--r--mm/mmap.c2
-rw-r--r--mm/page_alloc.c4
-rw-r--r--mm/page_cgroup.c63
-rw-r--r--mm/slob.c2
-rw-r--r--mm/slub.c8
-rw-r--r--mm/sparse.c2
-rw-r--r--mm/swap.c20
-rw-r--r--mm/vmalloc.c43
-rw-r--r--mm/vmscan.c46
-rw-r--r--net/9p/Kconfig10
-rw-r--r--net/atm/svc.c6
-rw-r--r--net/bluetooth/rfcomm/core.c2
-rw-r--r--net/bridge/br_netfilter.c13
-rw-r--r--net/can/af_can.c68
-rw-r--r--net/can/bcm.c7
-rw-r--r--net/compat.c54
-rw-r--r--net/core/netpoll.c2
-rw-r--r--net/core/pktgen.c9
-rw-r--r--net/core/rtnetlink.c4
-rw-r--r--net/core/scm.c2
-rw-r--r--net/core/skbuff.c2
-rw-r--r--net/core/sock.c33
-rw-r--r--net/ipv4/af_inet.c1
-rw-r--r--net/ipv4/ip_input.c10
-rw-r--r--net/ipv4/ipmr.c9
-rw-r--r--net/ipv4/netfilter/nf_nat_rule.c2
-rw-r--r--net/ipv4/tcp_htcp.c14
-rw-r--r--net/ipv4/tcp_output.c15
-rw-r--r--net/ipv4/tcp_vegas.c82
-rw-r--r--net/ipv4/udp.c1
-rw-r--r--net/ipv6/datagram.c5
-rw-r--r--net/ipv6/ip6mr.c4
-rw-r--r--net/ipv6/ipv6_sockglue.c5
-rw-r--r--net/ipv6/ndisc.c7
-rw-r--r--net/ipv6/proc.c6
-rw-r--r--net/mac80211/mlme.c22
-rw-r--r--net/mac80211/sta_info.c2
-rw-r--r--net/mac80211/wext.c8
-rw-r--r--net/netfilter/nf_conntrack_core.c2
-rw-r--r--net/netfilter/nf_conntrack_netlink.c7
-rw-r--r--net/netfilter/xt_socket.c2
-rw-r--r--net/netlabel/netlabel_unlabeled.c48
-rw-r--r--net/phonet/af_phonet.c56
-rw-r--r--net/phonet/pep-gprs.c27
-rw-r--r--net/phonet/pn_dev.c2
-rw-r--r--net/phonet/pn_netlink.c3
-rw-r--r--net/rose/af_rose.c10
-rw-r--r--net/sched/sch_api.c2
-rw-r--r--net/sched/sch_generic.c7
-rw-r--r--net/sched/sch_netem.c3
-rw-r--r--net/socket.c81
-rw-r--r--net/sunrpc/auth_generic.c20
-rw-r--r--net/sunrpc/svcsock.c9
-rw-r--r--net/unix/af_unix.c2
-rw-r--r--net/unix/garbage.c13
-rw-r--r--net/wireless/reg.c4
-rw-r--r--net/xfrm/xfrm_policy.c1
-rwxr-xr-xscripts/kernel-doc10
-rw-r--r--sound/ac97_bus.c1
-rw-r--r--sound/aoa/codecs/Makefile4
-rw-r--r--sound/aoa/codecs/onyx.c (renamed from sound/aoa/codecs/snd-aoa-codec-onyx.c)12
-rw-r--r--sound/aoa/codecs/onyx.h (renamed from sound/aoa/codecs/snd-aoa-codec-onyx.h)0
-rw-r--r--sound/aoa/codecs/tas-basstreble.h (renamed from sound/aoa/codecs/snd-aoa-codec-tas-basstreble.h)0
-rw-r--r--sound/aoa/codecs/tas-gain-table.h (renamed from sound/aoa/codecs/snd-aoa-codec-tas-gain-table.h)0
-rw-r--r--sound/aoa/codecs/tas.c (renamed from sound/aoa/codecs/snd-aoa-codec-tas.c)8
-rw-r--r--sound/aoa/codecs/tas.h (renamed from sound/aoa/codecs/snd-aoa-codec-tas.h)0
-rw-r--r--sound/aoa/codecs/toonie.c (renamed from sound/aoa/codecs/snd-aoa-codec-toonie.c)2
-rw-r--r--sound/aoa/core/Makefile8
-rw-r--r--sound/aoa/core/alsa.c (renamed from sound/aoa/core/snd-aoa-alsa.c)4
-rw-r--r--sound/aoa/core/alsa.h (renamed from sound/aoa/core/snd-aoa-alsa.h)0
-rw-r--r--sound/aoa/core/core.c (renamed from sound/aoa/core/snd-aoa-core.c)2
-rw-r--r--sound/aoa/core/gpio-feature.c (renamed from sound/aoa/core/snd-aoa-gpio-feature.c)2
-rw-r--r--sound/aoa/core/gpio-pmf.c (renamed from sound/aoa/core/snd-aoa-gpio-pmf.c)0
-rw-r--r--sound/aoa/fabrics/Makefile2
-rw-r--r--sound/aoa/fabrics/layout.c (renamed from sound/aoa/fabrics/snd-aoa-fabric-layout.c)2
-rw-r--r--sound/aoa/soundbus/i2sbus/Makefile2
-rw-r--r--sound/aoa/soundbus/i2sbus/control.c (renamed from sound/aoa/soundbus/i2sbus/i2sbus-control.c)0
-rw-r--r--sound/aoa/soundbus/i2sbus/core.c (renamed from sound/aoa/soundbus/i2sbus/i2sbus-core.c)4
-rw-r--r--sound/aoa/soundbus/i2sbus/i2sbus.h2
-rw-r--r--sound/aoa/soundbus/i2sbus/interface.h (renamed from sound/aoa/soundbus/i2sbus/i2sbus-interface.h)0
-rw-r--r--sound/aoa/soundbus/i2sbus/pcm.c (renamed from sound/aoa/soundbus/i2sbus/i2sbus-pcm.c)0
-rw-r--r--sound/core/Kconfig21
-rw-r--r--sound/core/Makefile2
-rw-r--r--sound/core/device.c4
-rw-r--r--sound/core/hrtimer.c155
-rw-r--r--sound/core/jack.c15
-rw-r--r--sound/core/rawmidi.c4
-rw-r--r--sound/core/rtctimer.c2
-rw-r--r--sound/core/seq/seq.c4
-rw-r--r--sound/core/timer.c2
-rw-r--r--sound/drivers/Kconfig2
-rw-r--r--sound/drivers/pcsp/pcsp.c8
-rw-r--r--sound/drivers/pcsp/pcsp.h3
-rw-r--r--sound/drivers/pcsp/pcsp_lib.c168
-rw-r--r--sound/drivers/vx/vx_core.c2
-rw-r--r--sound/drivers/vx/vx_pcm.c2
-rw-r--r--sound/isa/sb/sb8.c4
-rw-r--r--sound/pci/Kconfig127
-rw-r--r--sound/pci/ac97/ac97_codec.c2
-rw-r--r--sound/pci/ac97/ac97_patch.c7
-rw-r--r--sound/pci/ca0106/ca0106.h30
-rw-r--r--sound/pci/ca0106/ca0106_main.c550
-rw-r--r--sound/pci/ca0106/ca0106_mixer.c263
-rw-r--r--sound/pci/cs46xx/cs46xx_lib.c5
-rw-r--r--sound/pci/cs5535audio/Makefile3
-rw-r--r--sound/pci/cs5535audio/cs5535audio.c12
-rw-r--r--sound/pci/cs5535audio/cs5535audio.h39
-rw-r--r--sound/pci/cs5535audio/cs5535audio_olpc.c179
-rw-r--r--sound/pci/cs5535audio/cs5535audio_pcm.c15
-rw-r--r--sound/pci/emu10k1/emu10k1_main.c494
-rw-r--r--sound/pci/emu10k1/emumixer.c46
-rw-r--r--sound/pci/es1968.c2
-rw-r--r--sound/pci/hda/Kconfig188
-rw-r--r--sound/pci/hda/Makefile75
-rw-r--r--sound/pci/hda/hda_beep.c10
-rw-r--r--sound/pci/hda/hda_beep.h1
-rw-r--r--sound/pci/hda/hda_codec.c785
-rw-r--r--sound/pci/hda/hda_codec.h107
-rw-r--r--sound/pci/hda/hda_eld.c590
-rw-r--r--sound/pci/hda/hda_generic.c21
-rw-r--r--sound/pci/hda/hda_hwdep.c234
-rw-r--r--sound/pci/hda/hda_intel.c348
-rw-r--r--sound/pci/hda/hda_local.h100
-rw-r--r--sound/pci/hda/hda_patch.h22
-rw-r--r--sound/pci/hda/hda_proc.c91
-rw-r--r--sound/pci/hda/patch_analog.c132
-rw-r--r--sound/pci/hda/patch_atihdmi.c40
-rw-r--r--sound/pci/hda/patch_cmedia.c27
-rw-r--r--sound/pci/hda/patch_conexant.c39
-rw-r--r--sound/pci/hda/patch_intelhdmi.c711
-rw-r--r--sound/pci/hda/patch_nvhdmi.c32
-rw-r--r--sound/pci/hda/patch_realtek.c1663
-rw-r--r--sound/pci/hda/patch_si3054.c35
-rw-r--r--sound/pci/hda/patch_sigmatel.c1641
-rw-r--r--sound/pci/hda/patch_via.c171
-rw-r--r--sound/pci/ice1712/ice1724.c23
-rw-r--r--sound/pci/maestro3.c2
-rw-r--r--sound/pci/mixart/mixart.c4
-rw-r--r--sound/pci/mixart/mixart_core.c2
-rw-r--r--sound/pci/oxygen/oxygen.c4
-rw-r--r--sound/pci/pcxhr/Makefile2
-rw-r--r--sound/pci/pcxhr/pcxhr.c563
-rw-r--r--sound/pci/pcxhr/pcxhr.h76
-rw-r--r--sound/pci/pcxhr/pcxhr_core.c293
-rw-r--r--sound/pci/pcxhr/pcxhr_core.h5
-rw-r--r--sound/pci/pcxhr/pcxhr_hwdep.c158
-rw-r--r--sound/pci/pcxhr/pcxhr_mix22.c820
-rw-r--r--sound/pci/pcxhr/pcxhr_mix22.h56
-rw-r--r--sound/pci/pcxhr/pcxhr_mixer.c556
-rw-r--r--sound/pci/riptide/riptide.c4
-rw-r--r--sound/pci/rme9652/hdsp.c2
-rw-r--r--sound/pci/rme9652/hdspm.c2
-rw-r--r--sound/pcmcia/pdaudiocf/pdaudiocf_irq.c2
-rw-r--r--sound/ppc/pmac.c2
-rw-r--r--sound/ppc/tumbler.c3
-rw-r--r--sound/soc/Kconfig13
-rw-r--r--sound/soc/Makefile12
-rw-r--r--sound/soc/at32/Kconfig34
-rw-r--r--sound/soc/at32/Makefile11
-rw-r--r--sound/soc/at32/at32-pcm.c492
-rw-r--r--sound/soc/at32/at32-pcm.h79
-rw-r--r--sound/soc/at32/at32-ssc.c849
-rw-r--r--sound/soc/at32/at32-ssc.h59
-rw-r--r--sound/soc/at91/Kconfig10
-rw-r--r--sound/soc/at91/Makefile6
-rw-r--r--sound/soc/at91/at91-pcm.c434
-rw-r--r--sound/soc/at91/at91-pcm.h72
-rw-r--r--sound/soc/at91/at91-ssc.c791
-rw-r--r--sound/soc/at91/at91-ssc.h27
-rw-r--r--sound/soc/atmel/Kconfig43
-rw-r--r--sound/soc/atmel/Makefile15
-rw-r--r--sound/soc/atmel/atmel-pcm.c494
-rw-r--r--sound/soc/atmel/atmel-pcm.h86
-rw-r--r--sound/soc/atmel/atmel_ssc_dai.c790
-rw-r--r--sound/soc/atmel/atmel_ssc_dai.h121
-rw-r--r--sound/soc/atmel/playpaq_wm8510.c (renamed from sound/soc/at32/playpaq_wm8510.c)11
-rw-r--r--sound/soc/atmel/sam9g20_wm8731.c328
-rw-r--r--sound/soc/au1x/dbdma2.c3
-rw-r--r--sound/soc/au1x/psc-ac97.c16
-rw-r--r--sound/soc/au1x/psc-i2s.c18
-rw-r--r--sound/soc/au1x/sample-ac97.c4
-rw-r--r--sound/soc/blackfin/Kconfig22
-rw-r--r--sound/soc/blackfin/bf5xx-ac97-pcm.c113
-rw-r--r--sound/soc/blackfin/bf5xx-ac97.c178
-rw-r--r--sound/soc/blackfin/bf5xx-ac97.h35
-rw-r--r--sound/soc/blackfin/bf5xx-ad1980.c8
-rw-r--r--sound/soc/blackfin/bf5xx-ad73311.c10
-rw-r--r--sound/soc/blackfin/bf5xx-i2s-pcm.c12
-rw-r--r--sound/soc/blackfin/bf5xx-i2s.c31
-rw-r--r--sound/soc/blackfin/bf5xx-sport.h2
-rw-r--r--sound/soc/blackfin/bf5xx-ssm2602.c14
-rw-r--r--sound/soc/codecs/Kconfig69
-rw-r--r--sound/soc/codecs/Makefile12
-rw-r--r--sound/soc/codecs/ac97.c7
-rw-r--r--sound/soc/codecs/ad1980.c24
-rw-r--r--sound/soc/codecs/ad73311.c18
-rw-r--r--sound/soc/codecs/ak4535.c19
-rw-r--r--sound/soc/codecs/cs4270.c38
-rw-r--r--sound/soc/codecs/l3.c91
-rw-r--r--sound/soc/codecs/pcm3008.c212
-rw-r--r--sound/soc/codecs/pcm3008.h25
-rw-r--r--sound/soc/codecs/ssm2602.c57
-rw-r--r--sound/soc/codecs/tlv320aic23.c262
-rw-r--r--sound/soc/codecs/tlv320aic26.c22
-rw-r--r--sound/soc/codecs/tlv320aic3x.c166
-rw-r--r--sound/soc/codecs/tlv320aic3x.h60
-rw-r--r--sound/soc/codecs/twl4030.c1317
-rw-r--r--sound/soc/codecs/twl4030.h219
-rw-r--r--sound/soc/codecs/uda134x.c668
-rw-r--r--sound/soc/codecs/uda134x.h36
-rw-r--r--sound/soc/codecs/uda1380.c29
-rw-r--r--sound/soc/codecs/wm8350.c1583
-rw-r--r--sound/soc/codecs/wm8350.h20
-rw-r--r--sound/soc/codecs/wm8510.c19
-rw-r--r--sound/soc/codecs/wm8580.c134
-rw-r--r--sound/soc/codecs/wm8580.h1
-rw-r--r--sound/soc/codecs/wm8728.c585
-rw-r--r--sound/soc/codecs/wm8728.h30
-rw-r--r--sound/soc/codecs/wm8731.c25
-rw-r--r--sound/soc/codecs/wm8750.c19
-rw-r--r--sound/soc/codecs/wm8753.c39
-rw-r--r--sound/soc/codecs/wm8900.c262
-rw-r--r--sound/soc/codecs/wm8900.h6
-rw-r--r--sound/soc/codecs/wm8903.c268
-rw-r--r--sound/soc/codecs/wm8903.h5
-rw-r--r--sound/soc/codecs/wm8971.c19
-rw-r--r--sound/soc/codecs/wm8990.c43
-rw-r--r--sound/soc/codecs/wm8990.h4
-rw-r--r--sound/soc/codecs/wm9712.c12
-rw-r--r--sound/soc/codecs/wm9713.c46
-rw-r--r--sound/soc/davinci/Kconfig10
-rw-r--r--sound/soc/davinci/Makefile2
-rw-r--r--sound/soc/davinci/davinci-evm.c14
-rw-r--r--sound/soc/davinci/davinci-i2s.c257
-rw-r--r--sound/soc/davinci/davinci-pcm.c30
-rw-r--r--sound/soc/davinci/davinci-sffsdr.c157
-rw-r--r--sound/soc/fsl/Kconfig3
-rw-r--r--sound/soc/fsl/fsl_dma.c14
-rw-r--r--sound/soc/fsl/fsl_ssi.c24
-rw-r--r--sound/soc/fsl/mpc5200_psc_i2s.c22
-rw-r--r--sound/soc/fsl/mpc8610_hpcd.c8
-rw-r--r--sound/soc/fsl/soc-of-simple.c12
-rw-r--r--sound/soc/omap/Kconfig35
-rw-r--r--sound/soc/omap/Makefile8
-rw-r--r--sound/soc/omap/n810.c10
-rw-r--r--sound/soc/omap/omap-mcbsp.c61
-rw-r--r--sound/soc/omap/omap-pcm.c16
-rw-r--r--sound/soc/omap/omap2evm.c151
-rw-r--r--sound/soc/omap/omap3beagle.c149
-rw-r--r--sound/soc/omap/omap3pandora.c311
-rw-r--r--sound/soc/omap/osk5912.c10
-rw-r--r--sound/soc/omap/overo.c148
-rw-r--r--sound/soc/omap/sdp3430.c152
-rw-r--r--sound/soc/pxa/Kconfig22
-rw-r--r--sound/soc/pxa/Makefile6
-rw-r--r--sound/soc/pxa/corgi.c12
-rw-r--r--sound/soc/pxa/e800_wm9712.c8
-rw-r--r--sound/soc/pxa/em-x270.c7
-rw-r--r--sound/soc/pxa/palm27x.c269
-rw-r--r--sound/soc/pxa/poodle.c6
-rw-r--r--sound/soc/pxa/pxa-ssp.c931
-rw-r--r--sound/soc/pxa/pxa-ssp.h47
-rw-r--r--sound/soc/pxa/pxa2xx-ac97.c33
-rw-r--r--sound/soc/pxa/pxa2xx-i2s.c35
-rw-r--r--sound/soc/pxa/pxa2xx-pcm.c14
-rw-r--r--sound/soc/pxa/spitz.c6
-rw-r--r--sound/soc/pxa/tosa.c38
-rw-r--r--sound/soc/pxa/zylonite.c219
-rw-r--r--sound/soc/s3c24xx/Kconfig5
-rw-r--r--sound/soc/s3c24xx/Makefile2
-rw-r--r--sound/soc/s3c24xx/ln2440sbc_alc650.c8
-rw-r--r--sound/soc/s3c24xx/neo1973_wm8753.c9
-rw-r--r--sound/soc/s3c24xx/s3c2412-i2s.c38
-rw-r--r--sound/soc/s3c24xx/s3c2443-ac97.c30
-rw-r--r--sound/soc/s3c24xx/s3c24xx-i2s.c35
-rw-r--r--sound/soc/s3c24xx/s3c24xx-pcm.c12
-rw-r--r--sound/soc/s3c24xx/s3c24xx_uda134x.c373
-rw-r--r--sound/soc/s3c24xx/smdk2443_wm9710.c8
-rw-r--r--sound/soc/sh/dma-sh7760.c12
-rw-r--r--sound/soc/sh/hac.c19
-rw-r--r--sound/soc/sh/sh7760-ac97.c6
-rw-r--r--sound/soc/sh/ssi.c30
-rw-r--r--sound/soc/soc-core.c840
-rw-r--r--sound/soc/soc-dapm.c82
-rw-r--r--sound/sound_core.c7
-rw-r--r--sound/usb/caiaq/caiaq-control.c73
-rw-r--r--sound/usb/caiaq/caiaq-device.c2
-rw-r--r--sound/usb/usbmidi.c2
-rw-r--r--sound/usb/usx2y/usb_stream.c3
1336 files changed, 46151 insertions, 17671 deletions
diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX
index edef85ce119..2a39aeba146 100644
--- a/Documentation/00-INDEX
+++ b/Documentation/00-INDEX
@@ -42,14 +42,8 @@ IRQ.txt
- description of what an IRQ is.
ManagementStyle
- how to (attempt to) manage kernel hackers.
-MSI-HOWTO.txt
- - the Message Signaled Interrupts (MSI) Driver Guide HOWTO and FAQ.
RCU/
- directory with info on RCU (read-copy update).
-README.DAC960
- - info on Mylex DAC960/DAC1100 PCI RAID Controller Driver for Linux.
-README.cycladesZ
- - info on Cyclades-Z firmware loading.
SAK.txt
- info on Secure Attention Keys.
SM501.txt
@@ -86,20 +80,16 @@ blackfin/
- directory with documentation for the Blackfin arch.
block/
- info on the Block I/O (BIO) layer.
+blockdev/
+ - info on block devices & drivers
cachetlb.txt
- describes the cache/TLB flushing interfaces Linux uses.
-cciss.txt
- - info, major/minor #'s for Compaq's SMART Array Controllers.
cdrom/
- directory with information on the CD-ROM drivers that Linux has.
-computone.txt
- - info on Computone Intelliport II/Plus Multiport Serial Driver.
connector/
- docs on the netlink based userspace<->kernel space communication mod.
console/
- documentation on Linux console drivers.
-cpqarray.txt
- - info on using Compaq's SMART2 Intelligent Disk Array Controllers.
cpu-freq/
- info on CPU frequency and voltage scaling.
cpu-hotplug.txt
@@ -126,8 +116,6 @@ device-mapper/
- directory with info on Device Mapper.
devices.txt
- plain ASCII listing of all the nodes in /dev/ with major minor #'s.
-digiepca.txt
- - info on Digi Intl. {PC,PCI,EISA}Xx and Xem series cards.
dontdiff
- file containing a list of files that should never be diff'ed.
driver-model/
@@ -152,14 +140,10 @@ filesystems/
- info on the vfs and the various filesystems that Linux supports.
firmware_class/
- request_firmware() hotplug interface info.
-floppy.txt
- - notes and driver options for the floppy disk driver.
frv/
- Fujitsu FR-V Linux documentation.
gpio.txt
- overview of GPIO (General Purpose Input/Output) access conventions.
-hayes-esp.txt
- - info on using the Hayes ESP serial driver.
highuid.txt
- notes on the change from 16 bit to 32 bit user/group IDs.
timers/
@@ -186,8 +170,6 @@ io_ordering.txt
- info on ordering I/O writes to memory-mapped addresses.
ioctl/
- directory with documents describing various IOCTL calls.
-ioctl-number.txt
- - how to implement and register device/driver ioctl calls.
iostats.txt
- info on I/O statistics Linux kernel provides.
irqflags-tracing.txt
@@ -250,14 +232,10 @@ mips/
- directory with info about Linux on MIPS architecture.
mono.txt
- how to execute Mono-based .NET binaries with the help of BINFMT_MISC.
-moxa-smartio
- - file with info on installing/using Moxa multiport serial driver.
mutex-design.txt
- info on the generic mutex subsystem.
namespaces/
- directory with various information about namespaces
-nbd.txt
- - info on a TCP implementation of a network block device.
netlabel/
- directory with information on the NetLabel subsystem.
networking/
@@ -270,8 +248,6 @@ numastat.txt
- info on how to read Numa policy hit/miss statistics in sysfs.
oops-tracing.txt
- how to decode those nasty internal kernel error dump messages.
-paride.txt
- - information about the parallel port IDE subsystem.
parisc/
- directory with info on using Linux on PA-RISC architecture.
parport.txt
@@ -290,20 +266,16 @@ powerpc/
- directory with info on using Linux with the PowerPC.
preempt-locking.txt
- info on locking under a preemptive kernel.
+printk-formats.txt
+ - how to get printk format specifiers right
prio_tree.txt
- info on radix-priority-search-tree use for indexing vmas.
-ramdisk.txt
- - short guide on how to set up and use the RAM disk.
rbtree.txt
- info on what red-black trees are and what they are for.
-riscom8.txt
- - notes on using the RISCom/8 multi-port serial driver.
robust-futex-ABI.txt
- documentation of the robust futex ABI.
robust-futexes.txt
- a description of what robust futexes are.
-rocket.txt
- - info on the Comtrol RocketPort multiport serial driver.
rt-mutex-design.txt
- description of the RealTime mutex implementation design.
rt-mutex.txt
@@ -332,8 +304,6 @@ sparc/
- directory with info on using Linux on Sparc architecture.
sparse.txt
- info on how to obtain and use the sparse tool for typechecking.
-specialix.txt
- - info on hardware/driver for specialix IO8+ multiport serial card.
spi/
- overview of Linux kernel Serial Peripheral Interface (SPI) support.
spinlocks.txt
@@ -342,14 +312,10 @@ stable_api_nonsense.txt
- info on why the kernel does not have a stable in-kernel api or abi.
stable_kernel_rules.txt
- rules and procedures for the -stable kernel releases.
-stallion.txt
- - info on using the Stallion multiport serial driver.
svga.txt
- short guide on selecting video modes at boot via VGA BIOS.
sysfs-rules.txt
- How not to use sysfs.
-sx.txt
- - info on the Specialix SX/SI multiport serial driver.
sysctl/
- directory with info on the /proc/sys/* files.
sysrq.txt
@@ -358,8 +324,6 @@ telephony/
- directory with info on telephony (e.g. voice over IP) support.
time_interpolators.txt
- info on time interpolators.
-tty.txt
- - guide to the locking policies of the tty layer.
uml/
- directory with information about User Mode Linux.
unicode.txt
diff --git a/Documentation/ABI/testing/sysfs-c2port b/Documentation/ABI/testing/sysfs-c2port
new file mode 100644
index 00000000000..716cffc457e
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-c2port
@@ -0,0 +1,88 @@
+What: /sys/class/c2port/
+Date: October 2008
+Contact: Rodolfo Giometti <giometti@linux.it>
+Description:
+ The /sys/class/c2port/ directory will contain files and
+ directories that will provide a unified interface to
+ the C2 port interface.
+
+What: /sys/class/c2port/c2portX
+Date: October 2008
+Contact: Rodolfo Giometti <giometti@linux.it>
+Description:
+ The /sys/class/c2port/c2portX/ directory is related to X-th
+ C2 port into the system. Each directory will contain files to
+ manage and control its C2 port.
+
+What: /sys/class/c2port/c2portX/access
+Date: October 2008
+Contact: Rodolfo Giometti <giometti@linux.it>
+Description:
+ The /sys/class/c2port/c2portX/access file enable the access
+ to the C2 port from the system. No commands can be sent
+ till this entry is set to 0.
+
+What: /sys/class/c2port/c2portX/dev_id
+Date: October 2008
+Contact: Rodolfo Giometti <giometti@linux.it>
+Description:
+ The /sys/class/c2port/c2portX/dev_id file show the device ID
+ of the connected micro.
+
+What: /sys/class/c2port/c2portX/flash_access
+Date: October 2008
+Contact: Rodolfo Giometti <giometti@linux.it>
+Description:
+ The /sys/class/c2port/c2portX/flash_access file enable the
+ access to the on-board flash of the connected micro.
+ No commands can be sent till this entry is set to 0.
+
+What: /sys/class/c2port/c2portX/flash_block_size
+Date: October 2008
+Contact: Rodolfo Giometti <giometti@linux.it>
+Description:
+ The /sys/class/c2port/c2portX/flash_block_size file show
+ the on-board flash block size of the connected micro.
+
+What: /sys/class/c2port/c2portX/flash_blocks_num
+Date: October 2008
+Contact: Rodolfo Giometti <giometti@linux.it>
+Description:
+ The /sys/class/c2port/c2portX/flash_blocks_num file show
+ the on-board flash blocks number of the connected micro.
+
+What: /sys/class/c2port/c2portX/flash_data
+Date: October 2008
+Contact: Rodolfo Giometti <giometti@linux.it>
+Description:
+ The /sys/class/c2port/c2portX/flash_data file export
+ the content of the on-board flash of the connected micro.
+
+What: /sys/class/c2port/c2portX/flash_erase
+Date: October 2008
+Contact: Rodolfo Giometti <giometti@linux.it>
+Description:
+ The /sys/class/c2port/c2portX/flash_erase file execute
+ the "erase" command on the on-board flash of the connected
+ micro.
+
+What: /sys/class/c2port/c2portX/flash_erase
+Date: October 2008
+Contact: Rodolfo Giometti <giometti@linux.it>
+Description:
+ The /sys/class/c2port/c2portX/flash_erase file show the
+ on-board flash size of the connected micro.
+
+What: /sys/class/c2port/c2portX/reset
+Date: October 2008
+Contact: Rodolfo Giometti <giometti@linux.it>
+Description:
+ The /sys/class/c2port/c2portX/reset file execute a "reset"
+ command on the connected micro.
+
+What: /sys/class/c2port/c2portX/rev_id
+Date: October 2008
+Contact: Rodolfo Giometti <giometti@linux.it>
+Description:
+ The /sys/class/c2port/c2portX/rev_id file show the revision ID
+ of the connected micro.
diff --git a/Documentation/ABI/testing/sysfs-firmware-acpi b/Documentation/ABI/testing/sysfs-firmware-acpi
index f27be7d1a49..e8ffc70ffe1 100644
--- a/Documentation/ABI/testing/sysfs-firmware-acpi
+++ b/Documentation/ABI/testing/sysfs-firmware-acpi
@@ -89,7 +89,7 @@ Description:
error - an interrupt that can't be accounted for above.
- invalid: it's either a wakeup GPE or a GPE/Fixed Event that
+ invalid: it's either a GPE or a Fixed Event that
doesn't have an event handler.
disable: the GPE/Fixed Event is valid but disabled.
@@ -117,30 +117,30 @@ Description:
and other user space applications so that the machine won't shutdown
when pressing the power button.
# cat ff_pwr_btn
- 0
+ 0 enabled
# press the power button for 3 times;
# cat ff_pwr_btn
- 3
+ 3 enabled
# echo disable > ff_pwr_btn
# cat ff_pwr_btn
- disable
+ 3 disabled
# press the power button for 3 times;
# cat ff_pwr_btn
- disable
+ 3 disabled
# echo enable > ff_pwr_btn
# cat ff_pwr_btn
- 4
+ 4 enabled
/*
* this is because the status bit is set even if the enable bit is cleared,
* and it triggers an ACPI fixed event when the enable bit is set again
*/
# press the power button for 3 times;
# cat ff_pwr_btn
- 7
+ 7 enabled
# echo disable > ff_pwr_btn
# press the power button for 3 times;
# echo clear > ff_pwr_btn /* clear the status bit */
# echo disable > ff_pwr_btn
# cat ff_pwr_btn
- 7
+ 7 enabled
diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt
index b8e86460046..b462bb14954 100644
--- a/Documentation/DMA-API.txt
+++ b/Documentation/DMA-API.txt
@@ -316,12 +316,10 @@ reduce current DMA mapping usage or delay and try again later).
pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
int nents, int direction)
-Maps a scatter gather list from the block layer.
-
Returns: the number of physical segments mapped (this may be shorter
-than <nents> passed in if the block layer determines that some
-elements of the scatter/gather list are physically adjacent and thus
-may be mapped with a single entry).
+than <nents> passed in if some elements of the scatter/gather list are
+physically or virtually adjacent and an IOMMU maps them with a single
+entry).
Please note that the sg cannot be mapped again if it has been mapped once.
The mapping process is allowed to destroy information in the sg.
diff --git a/Documentation/PCI/00-INDEX b/Documentation/PCI/00-INDEX
index 49f43946c6b..812b17fe3ed 100644
--- a/Documentation/PCI/00-INDEX
+++ b/Documentation/PCI/00-INDEX
@@ -1,5 +1,7 @@
00-INDEX
- this file
+MSI-HOWTO.txt
+ - the Message Signaled Interrupts (MSI) Driver Guide HOWTO and FAQ.
PCI-DMA-mapping.txt
- info for PCI drivers using DMA portably across all platforms
PCIEBUS-HOWTO.txt
diff --git a/Documentation/MSI-HOWTO.txt b/Documentation/PCI/MSI-HOWTO.txt
index 256defd7e17..256defd7e17 100644
--- a/Documentation/MSI-HOWTO.txt
+++ b/Documentation/PCI/MSI-HOWTO.txt
diff --git a/Documentation/acpi/debug.txt b/Documentation/acpi/debug.txt
new file mode 100644
index 00000000000..65bf47c46b6
--- /dev/null
+++ b/Documentation/acpi/debug.txt
@@ -0,0 +1,148 @@
+ ACPI Debug Output
+
+
+The ACPI CA, the Linux ACPI core, and some ACPI drivers can generate debug
+output. This document describes how to use this facility.
+
+Compile-time configuration
+--------------------------
+
+ACPI debug output is globally enabled by CONFIG_ACPI_DEBUG. If this config
+option is turned off, the debug messages are not even built into the
+kernel.
+
+Boot- and run-time configuration
+--------------------------------
+
+When CONFIG_ACPI_DEBUG=y, you can select the component and level of messages
+you're interested in. At boot-time, use the acpi.debug_layer and
+acpi.debug_level kernel command line options. After boot, you can use the
+debug_layer and debug_level files in /sys/module/acpi/parameters/ to control
+the debug messages.
+
+debug_layer (component)
+-----------------------
+
+The "debug_layer" is a mask that selects components of interest, e.g., a
+specific driver or part of the ACPI interpreter. To build the debug_layer
+bitmask, look for the "#define _COMPONENT" in an ACPI source file.
+
+You can set the debug_layer mask at boot-time using the acpi.debug_layer
+command line argument, and you can change it after boot by writing values
+to /sys/module/acpi/parameters/debug_layer.
+
+The possible components are defined in include/acpi/acoutput.h and
+include/acpi/acpi_drivers.h. Reading /sys/module/acpi/parameters/debug_layer
+shows the supported mask values, currently these:
+
+ ACPI_UTILITIES 0x00000001
+ ACPI_HARDWARE 0x00000002
+ ACPI_EVENTS 0x00000004
+ ACPI_TABLES 0x00000008
+ ACPI_NAMESPACE 0x00000010
+ ACPI_PARSER 0x00000020
+ ACPI_DISPATCHER 0x00000040
+ ACPI_EXECUTER 0x00000080
+ ACPI_RESOURCES 0x00000100
+ ACPI_CA_DEBUGGER 0x00000200
+ ACPI_OS_SERVICES 0x00000400
+ ACPI_CA_DISASSEMBLER 0x00000800
+ ACPI_COMPILER 0x00001000
+ ACPI_TOOLS 0x00002000
+ ACPI_BUS_COMPONENT 0x00010000
+ ACPI_AC_COMPONENT 0x00020000
+ ACPI_BATTERY_COMPONENT 0x00040000
+ ACPI_BUTTON_COMPONENT 0x00080000
+ ACPI_SBS_COMPONENT 0x00100000
+ ACPI_FAN_COMPONENT 0x00200000
+ ACPI_PCI_COMPONENT 0x00400000
+ ACPI_POWER_COMPONENT 0x00800000
+ ACPI_CONTAINER_COMPONENT 0x01000000
+ ACPI_SYSTEM_COMPONENT 0x02000000
+ ACPI_THERMAL_COMPONENT 0x04000000
+ ACPI_MEMORY_DEVICE_COMPONENT 0x08000000
+ ACPI_VIDEO_COMPONENT 0x10000000
+ ACPI_PROCESSOR_COMPONENT 0x20000000
+
+debug_level
+-----------
+
+The "debug_level" is a mask that selects different types of messages, e.g.,
+those related to initialization, method execution, informational messages, etc.
+To build debug_level, look at the level specified in an ACPI_DEBUG_PRINT()
+statement.
+
+The ACPI interpreter uses several different levels, but the Linux
+ACPI core and ACPI drivers generally only use ACPI_LV_INFO.
+
+You can set the debug_level mask at boot-time using the acpi.debug_level
+command line argument, and you can change it after boot by writing values
+to /sys/module/acpi/parameters/debug_level.
+
+The possible levels are defined in include/acpi/acoutput.h. Reading
+/sys/module/acpi/parameters/debug_level shows the supported mask values,
+currently these:
+
+ ACPI_LV_INIT 0x00000001
+ ACPI_LV_DEBUG_OBJECT 0x00000002
+ ACPI_LV_INFO 0x00000004
+ ACPI_LV_INIT_NAMES 0x00000020
+ ACPI_LV_PARSE 0x00000040
+ ACPI_LV_LOAD 0x00000080
+ ACPI_LV_DISPATCH 0x00000100
+ ACPI_LV_EXEC 0x00000200
+ ACPI_LV_NAMES 0x00000400
+ ACPI_LV_OPREGION 0x00000800
+ ACPI_LV_BFIELD 0x00001000
+ ACPI_LV_TABLES 0x00002000
+ ACPI_LV_VALUES 0x00004000
+ ACPI_LV_OBJECTS 0x00008000
+ ACPI_LV_RESOURCES 0x00010000
+ ACPI_LV_USER_REQUESTS 0x00020000
+ ACPI_LV_PACKAGE 0x00040000
+ ACPI_LV_ALLOCATIONS 0x00100000
+ ACPI_LV_FUNCTIONS 0x00200000
+ ACPI_LV_OPTIMIZATIONS 0x00400000
+ ACPI_LV_MUTEX 0x01000000
+ ACPI_LV_THREADS 0x02000000
+ ACPI_LV_IO 0x04000000
+ ACPI_LV_INTERRUPTS 0x08000000
+ ACPI_LV_AML_DISASSEMBLE 0x10000000
+ ACPI_LV_VERBOSE_INFO 0x20000000
+ ACPI_LV_FULL_TABLES 0x40000000
+ ACPI_LV_EVENTS 0x80000000
+
+Examples
+--------
+
+For example, drivers/acpi/bus.c contains this:
+
+ #define _COMPONENT ACPI_BUS_COMPONENT
+ ...
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device insertion detected\n"));
+
+To turn on this message, set the ACPI_BUS_COMPONENT bit in acpi.debug_layer
+and the ACPI_LV_INFO bit in acpi.debug_level. (The ACPI_DEBUG_PRINT
+statement uses ACPI_DB_INFO, which is macro based on the ACPI_LV_INFO
+definition.)
+
+Enable all AML "Debug" output (stores to the Debug object while interpreting
+AML) during boot:
+
+ acpi.debug_layer=0xffffffff acpi.debug_level=0x2
+
+Enable PCI and PCI interrupt routing debug messages:
+
+ acpi.debug_layer=0x400000 acpi.debug_level=0x4
+
+Enable all ACPI hardware-related messages:
+
+ acpi.debug_layer=0x2 acpi.debug_level=0xffffffff
+
+Enable all ACPI_DB_INFO messages after boot:
+
+ # echo 0x4 > /sys/module/acpi/parameters/debug_level
+
+Show all valid component values:
+
+ # cat /sys/module/acpi/parameters/debug_layer
diff --git a/Documentation/arm/mem_alignment b/Documentation/arm/mem_alignment
index d145ccca169..c7c7a114c78 100644
--- a/Documentation/arm/mem_alignment
+++ b/Documentation/arm/mem_alignment
@@ -24,7 +24,7 @@ real bad - it changes the behaviour of all unaligned instructions in user
space, and might cause programs to fail unexpectedly.
To change the alignment trap behavior, simply echo a number into
-/proc/sys/debug/alignment. The number is made up from various bits:
+/proc/cpu/alignment. The number is made up from various bits:
bit behavior when set
--- -----------------
diff --git a/Documentation/blockdev/00-INDEX b/Documentation/blockdev/00-INDEX
new file mode 100644
index 00000000000..86f054c4701
--- /dev/null
+++ b/Documentation/blockdev/00-INDEX
@@ -0,0 +1,16 @@
+00-INDEX
+ - this file
+README.DAC960
+ - info on Mylex DAC960/DAC1100 PCI RAID Controller Driver for Linux.
+cciss.txt
+ - info, major/minor #'s for Compaq's SMART Array Controllers.
+cpqarray.txt
+ - info on using Compaq's SMART2 Intelligent Disk Array Controllers.
+floppy.txt
+ - notes and driver options for the floppy disk driver.
+nbd.txt
+ - info on a TCP implementation of a network block device.
+paride.txt
+ - information about the parallel port IDE subsystem.
+ramdisk.txt
+ - short guide on how to set up and use the RAM disk.
diff --git a/Documentation/README.DAC960 b/Documentation/blockdev/README.DAC960
index 0e8f618ab53..0e8f618ab53 100644
--- a/Documentation/README.DAC960
+++ b/Documentation/blockdev/README.DAC960
diff --git a/Documentation/cciss.txt b/Documentation/blockdev/cciss.txt
index 89698e8df7d..89698e8df7d 100644
--- a/Documentation/cciss.txt
+++ b/Documentation/blockdev/cciss.txt
diff --git a/Documentation/cpqarray.txt b/Documentation/blockdev/cpqarray.txt
index c7154e20ef5..c7154e20ef5 100644
--- a/Documentation/cpqarray.txt
+++ b/Documentation/blockdev/cpqarray.txt
diff --git a/Documentation/floppy.txt b/Documentation/blockdev/floppy.txt
index 6ccab88705c..6ccab88705c 100644
--- a/Documentation/floppy.txt
+++ b/Documentation/blockdev/floppy.txt
diff --git a/Documentation/nbd.txt b/Documentation/blockdev/nbd.txt
index aeb93ffe641..aeb93ffe641 100644
--- a/Documentation/nbd.txt
+++ b/Documentation/blockdev/nbd.txt
diff --git a/Documentation/paride.txt b/Documentation/blockdev/paride.txt
index e4312676bdd..e4312676bdd 100644
--- a/Documentation/paride.txt
+++ b/Documentation/blockdev/paride.txt
diff --git a/Documentation/ramdisk.txt b/Documentation/blockdev/ramdisk.txt
index 6c820baa19a..6c820baa19a 100644
--- a/Documentation/ramdisk.txt
+++ b/Documentation/blockdev/ramdisk.txt
diff --git a/Documentation/c2port.txt b/Documentation/c2port.txt
new file mode 100644
index 00000000000..d9bf93ea439
--- /dev/null
+++ b/Documentation/c2port.txt
@@ -0,0 +1,90 @@
+ C2 port support
+ ---------------
+
+(C) Copyright 2007 Rodolfo Giometti <giometti@enneenne.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+
+
+Overview
+--------
+
+This driver implements the support for Linux of Silicon Labs (Silabs)
+C2 Interface used for in-system programming of micro controllers.
+
+By using this driver you can reprogram the in-system flash without EC2
+or EC3 debug adapter. This solution is also useful in those systems
+where the micro controller is connected via special GPIOs pins.
+
+References
+----------
+
+The C2 Interface main references are at (http://www.silabs.com)
+Silicon Laboratories site], see:
+
+- AN127: FLASH Programming via the C2 Interface at
+http://www.silabs.com/public/documents/tpub_doc/anote/Microcontrollers/Small_Form_Factor/en/an127.pdf, and
+
+- C2 Specification at
+http://www.silabs.com/public/documents/tpub_doc/spec/Microcontrollers/en/C2spec.pdf,
+
+however it implements a two wire serial communication protocol (bit
+banging) designed to enable in-system programming, debugging, and
+boundary-scan testing on low pin-count Silicon Labs devices. Currently
+this code supports only flash programming but extensions are easy to
+add.
+
+Using the driver
+----------------
+
+Once the driver is loaded you can use sysfs support to get C2port's
+info or read/write in-system flash.
+
+# ls /sys/class/c2port/c2port0/
+access flash_block_size flash_erase rev_id
+dev_id flash_blocks_num flash_size subsystem/
+flash_access flash_data reset uevent
+
+Initially the C2port access is disabled since you hardware may have
+such lines multiplexed with other devices so, to get access to the
+C2port, you need the command:
+
+# echo 1 > /sys/class/c2port/c2port0/access
+
+after that you should read the device ID and revision ID of the
+connected micro controller:
+
+# cat /sys/class/c2port/c2port0/dev_id
+8
+# cat /sys/class/c2port/c2port0/rev_id
+1
+
+However, for security reasons, the in-system flash access in not
+enabled yet, to do so you need the command:
+
+# echo 1 > /sys/class/c2port/c2port0/flash_access
+
+After that you can read the whole flash:
+
+# cat /sys/class/c2port/c2port0/flash_data > image
+
+erase it:
+
+# echo 1 > /sys/class/c2port/c2port0/flash_erase
+
+and write it:
+
+# cat image > /sys/class/c2port/c2port0/flash_data
+
+after writing you have to reset the device to execute the new code:
+
+# echo 1 > /sys/class/c2port/c2port0/reset
diff --git a/Documentation/cgroups/freezer-subsystem.txt b/Documentation/cgroups/freezer-subsystem.txt
index c50ab58b72e..41f37fea127 100644
--- a/Documentation/cgroups/freezer-subsystem.txt
+++ b/Documentation/cgroups/freezer-subsystem.txt
@@ -1,4 +1,4 @@
- The cgroup freezer is useful to batch job management system which start
+The cgroup freezer is useful to batch job management system which start
and stop sets of tasks in order to schedule the resources of a machine
according to the desires of a system administrator. This sort of program
is often used on HPC clusters to schedule access to the cluster as a
@@ -6,7 +6,7 @@ whole. The cgroup freezer uses cgroups to describe the set of tasks to
be started/stopped by the batch job management system. It also provides
a means to start and stop the tasks composing the job.
- The cgroup freezer will also be useful for checkpointing running groups
+The cgroup freezer will also be useful for checkpointing running groups
of tasks. The freezer allows the checkpoint code to obtain a consistent
image of the tasks by attempting to force the tasks in a cgroup into a
quiescent state. Once the tasks are quiescent another task can
@@ -16,7 +16,7 @@ recoverable error occur. This also allows the checkpointed tasks to be
migrated between nodes in a cluster by copying the gathered information
to another node and restarting the tasks there.
- Sequences of SIGSTOP and SIGCONT are not always sufficient for stopping
+Sequences of SIGSTOP and SIGCONT are not always sufficient for stopping
and resuming tasks in userspace. Both of these signals are observable
from within the tasks we wish to freeze. While SIGSTOP cannot be caught,
blocked, or ignored it can be seen by waiting or ptracing parent tasks.
@@ -37,26 +37,29 @@ demonstrate this problem using nested bash shells:
<at this point 16990 exits and causes 16644 to exit too>
- This happens because bash can observe both signals and choose how it
+This happens because bash can observe both signals and choose how it
responds to them.
- Another example of a program which catches and responds to these
+Another example of a program which catches and responds to these
signals is gdb. In fact any program designed to use ptrace is likely to
have a problem with this method of stopping and resuming tasks.
- In contrast, the cgroup freezer uses the kernel freezer code to
+In contrast, the cgroup freezer uses the kernel freezer code to
prevent the freeze/unfreeze cycle from becoming visible to the tasks
being frozen. This allows the bash example above and gdb to run as
expected.
- The freezer subsystem in the container filesystem defines a file named
+The freezer subsystem in the container filesystem defines a file named
freezer.state. Writing "FROZEN" to the state file will freeze all tasks in the
cgroup. Subsequently writing "THAWED" will unfreeze the tasks in the cgroup.
Reading will return the current state.
+Note freezer.state doesn't exist in root cgroup, which means root cgroup
+is non-freezable.
+
* Examples of usage :
- # mkdir /containers/freezer
+ # mkdir /containers
# mount -t cgroup -ofreezer freezer /containers
# mkdir /containers/0
# echo $some_pid > /containers/0/tasks
@@ -94,6 +97,6 @@ things happens:
the freezer.state file
2) Userspace retries the freezing operation by writing "FROZEN" to
the freezer.state file (writing "FREEZING" is not legal
- and returns EIO)
+ and returns EINVAL)
3) The tasks that blocked the cgroup from entering the "FROZEN"
state disappear from the cgroup's set of tasks.
diff --git a/Documentation/cpu-freq/user-guide.txt b/Documentation/cpu-freq/user-guide.txt
index 6c442d8426b..4f3f3840320 100644
--- a/Documentation/cpu-freq/user-guide.txt
+++ b/Documentation/cpu-freq/user-guide.txt
@@ -23,6 +23,7 @@ Contents:
1.3 sparc64
1.4 ppc
1.5 SuperH
+1.6 Blackfin
2. "Policy" / "Governor"?
2.1 Policy
@@ -97,6 +98,17 @@ The following SuperH processors are supported by cpufreq:
SH-3
SH-4
+1.6 Blackfin
+------------
+
+The following Blackfin processors are supported by cpufreq:
+
+BF522, BF523, BF524, BF525, BF526, BF527, Rev 0.1 or higher
+BF531, BF532, BF533, Rev 0.3 or higher
+BF534, BF536, BF537, Rev 0.2 or higher
+BF561, Rev 0.3 or higher
+BF542, BF544, BF547, BF548, BF549, Rev 0.1 or higher
+
2. "Policy" / "Governor" ?
==========================
diff --git a/Documentation/filesystems/ocfs2.txt b/Documentation/filesystems/ocfs2.txt
index 4340cc82579..67310fbbb7d 100644
--- a/Documentation/filesystems/ocfs2.txt
+++ b/Documentation/filesystems/ocfs2.txt
@@ -28,10 +28,7 @@ Manish Singh <manish.singh@oracle.com>
Caveats
=======
Features which OCFS2 does not support yet:
- - extended attributes
- quotas
- - cluster aware flock
- - cluster aware lockf
- Directory change notification (F_NOTIFY)
- Distributed Caching (F_SETLEASE/F_GETLEASE/break_lease)
- POSIX ACLs
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index bcceb99b81d..bb1b0dd3bfc 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -44,6 +44,7 @@ Table of Contents
2.14 /proc/<pid>/io - Display the IO accounting fields
2.15 /proc/<pid>/coredump_filter - Core dump filtering settings
2.16 /proc/<pid>/mountinfo - Information about mounts
+ 2.17 /proc/sys/fs/epoll - Configuration options for the epoll interface
------------------------------------------------------------------------------
Preface
@@ -2483,4 +2484,30 @@ For more information on mount propagation see:
Documentation/filesystems/sharedsubtree.txt
+2.17 /proc/sys/fs/epoll - Configuration options for the epoll interface
+--------------------------------------------------------
+
+This directory contains configuration options for the epoll(7) interface.
+
+max_user_instances
+------------------
+
+This is the maximum number of epoll file descriptors that a single user can
+have open at a given time. The default value is 128, and should be enough
+for normal users.
+
+max_user_watches
+----------------
+
+Every epoll file descriptor can store a number of files to be monitored
+for event readiness. Each one of these monitored files constitutes a "watch".
+This configuration option sets the maximum number of "watches" that are
+allowed for each user.
+Each "watch" costs roughly 90 bytes on a 32bit kernel, and roughly 160 bytes
+on a 64bit one.
+The current default value for max_user_watches is the 1/32 of the available
+low memory, divided for the "watch" cost in bytes.
+
+
------------------------------------------------------------------------------
+
diff --git a/Documentation/filesystems/ramfs-rootfs-initramfs.txt b/Documentation/filesystems/ramfs-rootfs-initramfs.txt
index 62fe9b1e089..a8273d5fad2 100644
--- a/Documentation/filesystems/ramfs-rootfs-initramfs.txt
+++ b/Documentation/filesystems/ramfs-rootfs-initramfs.txt
@@ -130,12 +130,12 @@ The 2.6 kernel build process always creates a gzipped cpio format initramfs
archive and links it into the resulting kernel binary. By default, this
archive is empty (consuming 134 bytes on x86).
-The config option CONFIG_INITRAMFS_SOURCE (for some reason buried under
-devices->block devices in menuconfig, and living in usr/Kconfig) can be used
-to specify a source for the initramfs archive, which will automatically be
-incorporated into the resulting binary. This option can point to an existing
-gzipped cpio archive, a directory containing files to be archived, or a text
-file specification such as the following example:
+The config option CONFIG_INITRAMFS_SOURCE (in General Setup in menuconfig,
+and living in usr/Kconfig) can be used to specify a source for the
+initramfs archive, which will automatically be incorporated into the
+resulting binary. This option can point to an existing gzipped cpio
+archive, a directory containing files to be archived, or a text file
+specification such as the following example:
dir /dev 755 0 0
nod /dev/console 644 0 0 c 5 1
diff --git a/Documentation/filesystems/xip.txt b/Documentation/filesystems/xip.txt
index 3cc4010521a..0466ee56927 100644
--- a/Documentation/filesystems/xip.txt
+++ b/Documentation/filesystems/xip.txt
@@ -39,10 +39,11 @@ The block device operation is optional, these block devices support it as of
today:
- dcssblk: s390 dcss block device driver
-An address space operation named get_xip_page is used to retrieve reference
-to a struct page. To address the target page, a reference to an address_space,
-and a sector number is provided. A 3rd argument indicates whether the
-function should allocate blocks if needed.
+An address space operation named get_xip_mem is used to retrieve references
+to a page frame number and a kernel address. To obtain these values a reference
+to an address_space is provided. This function assigns values to the kmem and
+pfn parameters. The third argument indicates whether the function should allocate
+blocks if needed.
This address space operation is mutually exclusive with readpage&writepage that
do page cache read/write operations.
diff --git a/Documentation/hwmon/adt7462 b/Documentation/hwmon/adt7462
new file mode 100644
index 00000000000..ec660b32827
--- /dev/null
+++ b/Documentation/hwmon/adt7462
@@ -0,0 +1,67 @@
+Kernel driver adt7462
+======================
+
+Supported chips:
+ * Analog Devices ADT7462
+ Prefix: 'adt7462'
+ Addresses scanned: I2C 0x58, 0x5C
+ Datasheet: Publicly available at the Analog Devices website
+
+Author: Darrick J. Wong
+
+Description
+-----------
+
+This driver implements support for the Analog Devices ADT7462 chip family.
+
+This chip is a bit of a beast. It has 8 counters for measuring fan speed. It
+can also measure 13 voltages or 4 temperatures, or various combinations of the
+two. See the chip documentation for more details about the exact set of
+configurations. This driver does not allow one to configure the chip; that is
+left to the system designer.
+
+A sophisticated control system for the PWM outputs is designed into the ADT7462
+that allows fan speed to be adjusted automatically based on any of the three
+temperature sensors. Each PWM output is individually adjustable and
+programmable. Once configured, the ADT7462 will adjust the PWM outputs in
+response to the measured temperatures without further host intervention. This
+feature can also be disabled for manual control of the PWM's.
+
+Each of the measured inputs (voltage, temperature, fan speed) has
+corresponding high/low limit values. The ADT7462 will signal an ALARM if
+any measured value exceeds either limit.
+
+The ADT7462 samples all inputs continuously. The driver will not read
+the registers more often than once every other second. Further,
+configuration data is only read once per minute.
+
+Special Features
+----------------
+
+The ADT7462 have a 10-bit ADC and can therefore measure temperatures
+with 0.25 degC resolution.
+
+The Analog Devices datasheet is very detailed and describes a procedure for
+determining an optimal configuration for the automatic PWM control.
+
+The driver will report sensor labels when it is able to determine that
+information from the configuration registers.
+
+Configuration Notes
+-------------------
+
+Besides standard interfaces driver adds the following:
+
+* PWM Control
+
+* pwm#_auto_point1_pwm and temp#_auto_point1_temp and
+* pwm#_auto_point2_pwm and temp#_auto_point2_temp -
+
+point1: Set the pwm speed at a lower temperature bound.
+point2: Set the pwm speed at a higher temperature bound.
+
+The ADT7462 will scale the pwm between the lower and higher pwm speed when
+the temperature is between the two temperature boundaries. PWM values range
+from 0 (off) to 255 (full speed). Fan speed will be set to maximum when the
+temperature sensor associated with the PWM control exceeds temp#_max.
+
diff --git a/Documentation/hwmon/lis3lv02d b/Documentation/hwmon/lis3lv02d
new file mode 100644
index 00000000000..65dfb0c0fd6
--- /dev/null
+++ b/Documentation/hwmon/lis3lv02d
@@ -0,0 +1,49 @@
+Kernel driver lis3lv02d
+==================
+
+Supported chips:
+
+ * STMicroelectronics LIS3LV02DL and LIS3LV02DQ
+
+Author:
+ Yan Burman <burman.yan@gmail.com>
+ Eric Piel <eric.piel@tremplin-utc.net>
+
+
+Description
+-----------
+
+This driver provides support for the accelerometer found in various HP laptops
+sporting the feature officially called "HP Mobile Data Protection System 3D" or
+"HP 3D DriveGuard". It detect automatically laptops with this sensor. Known models
+(for now the HP 2133, nc6420, nc2510, nc8510, nc84x0, nw9440 and nx9420) will
+have their axis automatically oriented on standard way (eg: you can directly
+play neverball). The accelerometer data is readable via
+/sys/devices/platform/lis3lv02d.
+
+Sysfs attributes under /sys/devices/platform/lis3lv02d/:
+position - 3D position that the accelerometer reports. Format: "(x,y,z)"
+calibrate - read: values (x, y, z) that are used as the base for input class device operation.
+ write: forces the base to be recalibrated with the current position.
+rate - reports the sampling rate of the accelerometer device in HZ
+
+This driver also provides an absolute input class device, allowing
+the laptop to act as a pinball machine-esque joystick.
+
+Axes orientation
+----------------
+
+For better compatibility between the various laptops. The values reported by
+the accelerometer are converted into a "standard" organisation of the axes
+(aka "can play neverball out of the box"):
+ * When the laptop is horizontal the position reported is about 0 for X and Y
+and a positive value for Z
+ * If the left side is elevated, X increases (becomes positive)
+ * If the front side (where the touchpad is) is elevated, Y decreases (becomes negative)
+ * If the laptop is put upside-down, Z becomes negative
+
+If your laptop model is not recognized (cf "dmesg"), you can send an email to the
+authors to add it to the database. When reporting a new laptop, please include
+the output of "dmidecode" plus the value of /sys/devices/platform/lis3lv02d/position
+in these four cases.
+
diff --git a/Documentation/ics932s401 b/Documentation/ics932s401
new file mode 100644
index 00000000000..07a739f406d
--- /dev/null
+++ b/Documentation/ics932s401
@@ -0,0 +1,31 @@
+Kernel driver ics932s401
+======================
+
+Supported chips:
+ * IDT ICS932S401
+ Prefix: 'ics932s401'
+ Addresses scanned: I2C 0x69
+ Datasheet: Publically available at the IDT website
+
+Author: Darrick J. Wong
+
+Description
+-----------
+
+This driver implements support for the IDT ICS932S401 chip family.
+
+This chip has 4 clock outputs--a base clock for the CPU (which is likely
+multiplied to get the real CPU clock), a system clock, a PCI clock, a USB
+clock, and a reference clock. The driver reports selected and actual
+frequency. If spread spectrum mode is enabled, the driver also reports by what
+percent the clock signal is being spread, which should be between 0 and -0.5%.
+All frequencies are reported in KHz.
+
+The ICS932S401 monitors all inputs continuously. The driver will not read
+the registers more often than once every other second.
+
+Special Features
+----------------
+
+The clocks could be reprogrammed to increase system speed. I will not help you
+do this, as you risk damaging your system!
diff --git a/Documentation/input/input-programming.txt b/Documentation/input/input-programming.txt
index 81905e81585..7f8b9d97bc4 100644
--- a/Documentation/input/input-programming.txt
+++ b/Documentation/input/input-programming.txt
@@ -20,10 +20,11 @@ pressed or released a BUTTON_IRQ happens. The driver could look like:
static struct input_dev *button_dev;
-static void button_interrupt(int irq, void *dummy, struct pt_regs *fp)
+static irqreturn_t button_interrupt(int irq, void *dummy)
{
input_report_key(button_dev, BTN_0, inb(BUTTON_PORT) & 1);
input_sync(button_dev);
+ return IRQ_HANDLED;
}
static int __init button_init(void)
diff --git a/Documentation/ioctl/00-INDEX b/Documentation/ioctl/00-INDEX
new file mode 100644
index 00000000000..d2fe4d4729e
--- /dev/null
+++ b/Documentation/ioctl/00-INDEX
@@ -0,0 +1,10 @@
+00-INDEX
+ - this file
+cdrom.txt
+ - summary of CDROM ioctl calls
+hdio.txt
+ - summary of HDIO_ ioctl calls
+ioctl-decoding.txt
+ - how to decode the bits of an IOCTL code
+ioctl-number.txt
+ - how to implement and register device/driver ioctl calls
diff --git a/Documentation/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt
index b880ce5dbd3..b880ce5dbd3 100644
--- a/Documentation/ioctl-number.txt
+++ b/Documentation/ioctl/ioctl-number.txt
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index c86c0745971..c9115c1b672 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -198,59 +198,45 @@ and is between 256 and 4096 characters. It is defined in the file
that require a timer override, but don't have
HPET
- acpi.debug_layer= [HW,ACPI]
+ acpi_backlight= [HW,ACPI]
+ acpi_backlight=vendor
+ acpi_backlight=video
+ If set to vendor, prefer vendor specific driver
+ (e.g. thinkpad_acpi, sony_acpi, etc.) instead
+ of the ACPI video.ko driver.
+
+ acpi_display_output= [HW,ACPI]
+ acpi_display_output=vendor
+ acpi_display_output=video
+ See above.
+
+ acpi.debug_layer= [HW,ACPI,ACPI_DEBUG]
+ acpi.debug_level= [HW,ACPI,ACPI_DEBUG]
Format: <int>
- Each bit of the <int> indicates an ACPI debug layer,
- 1: enable, 0: disable. It is useful for boot time
- debugging. After system has booted up, it can be set
- via /sys/module/acpi/parameters/debug_layer.
- CONFIG_ACPI_DEBUG must be enabled for this to produce any output.
- Available bits (add the numbers together) to enable debug output
- for specific parts of the ACPI subsystem:
- 0x01 utilities 0x02 hardware 0x04 events 0x08 tables
- 0x10 namespace 0x20 parser 0x40 dispatcher
- 0x80 executer 0x100 resources 0x200 acpica debugger
- 0x400 os services 0x800 acpica disassembler.
- The number can be in decimal or prefixed with 0x in hex.
- Warning: Many of these options can produce a lot of
- output and make your system unusable. Be very careful.
-
- acpi.debug_level= [HW,ACPI]
- Format: <int>
- Each bit of the <int> indicates an ACPI debug level,
- which corresponds to the level in an ACPI_DEBUG_PRINT
- statement. After system has booted up, this mask
- can be set via /sys/module/acpi/parameters/debug_level.
-
- CONFIG_ACPI_DEBUG must be enabled for this to produce
- any output. The number can be in decimal or prefixed
- with 0x in hex. Some of these options produce so much
- output that the system is unusable.
-
- The following global components are defined by the
- ACPI CA:
- 0x01 error
- 0x02 warn
- 0x04 init
- 0x08 debug object
- 0x10 info
- 0x20 init names
- 0x40 parse
- 0x80 load
- 0x100 dispatch
- 0x200 execute
- 0x400 names
- 0x800 operation region
- 0x1000 bfield
- 0x2000 tables
- 0x4000 values
- 0x8000 objects
- 0x10000 resources
- 0x20000 user requests
- 0x40000 package
- The number can be in decimal or prefixed with 0x in hex.
- Warning: Many of these options can produce a lot of
- output and make your system unusable. Be very careful.
+ CONFIG_ACPI_DEBUG must be enabled to produce any ACPI
+ debug output. Bits in debug_layer correspond to a
+ _COMPONENT in an ACPI source file, e.g.,
+ #define _COMPONENT ACPI_PCI_COMPONENT
+ Bits in debug_level correspond to a level in
+ ACPI_DEBUG_PRINT statements, e.g.,
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, ...
+ The debug_level mask defaults to "info". See
+ Documentation/acpi/debug.txt for more information about
+ debug layers and levels.
+
+ Enable processor driver info messages:
+ acpi.debug_layer=0x20000000
+ Enable PCI/PCI interrupt routing info messages:
+ acpi.debug_layer=0x400000
+ Enable AML "Debug" output, i.e., stores to the Debug
+ object while interpreting AML:
+ acpi.debug_layer=0xffffffff acpi.debug_level=0x2
+ Enable all messages related to ACPI hardware:
+ acpi.debug_layer=0x2 acpi.debug_level=0xffffffff
+
+ Some values produce so much output that the system is
+ unusable. The "log_buf_len" parameter may be useful
+ if you need to capture more output.
acpi.power_nocheck= [HW,ACPI]
Format: 1/0 enable/disable the check of power state.
@@ -311,7 +297,9 @@ and is between 256 and 4096 characters. It is defined in the file
Possible values are:
isolate - enable device isolation (each device, as far
as possible, will get its own protection
- domain)
+ domain) [default]
+ share - put every device behind one IOMMU into the
+ same protection domain
fullflush - enable flushing of IO/TLB entries when
they are unmapped. Otherwise they are
flushed before they will be reused, which
@@ -646,7 +634,7 @@ and is between 256 and 4096 characters. It is defined in the file
digiepca= [HW,SERIAL]
See drivers/char/README.epca and
- Documentation/digiepca.txt.
+ Documentation/serial/digiepca.txt.
disable_mtrr_cleanup [X86]
enable_mtrr_cleanup [X86]
@@ -757,7 +745,7 @@ and is between 256 and 4096 characters. It is defined in the file
See header of drivers/scsi/fdomain.c.
floppy= [HW]
- See Documentation/floppy.txt.
+ See Documentation/blockdev/floppy.txt.
force_pal_cache_flush
[IA-64] Avoid check_sal_cache_flush which may hang on
@@ -1118,7 +1106,7 @@ and is between 256 and 4096 characters. It is defined in the file
the same attribute, the last one is used.
load_ramdisk= [RAM] List of ramdisks to load from floppy
- See Documentation/ramdisk.txt.
+ See Documentation/blockdev/ramdisk.txt.
lockd.nlm_grace_period=P [NFS] Assign grace period.
Format: <integer>
@@ -1210,8 +1198,8 @@ and is between 256 and 4096 characters. It is defined in the file
it is equivalent to "nosmp", which also disables
the IO APIC.
- max_addr=[KMG] [KNL,BOOT,ia64] All physical memory greater than or
- equal to this physical address is ignored.
+ max_addr=nn[KMG] [KNL,BOOT,ia64] All physical memory greater than
+ or equal to this physical address is ignored.
max_luns= [SCSI] Maximum number of LUNs to probe.
Should be between 1 and 2^32-1.
@@ -1311,6 +1299,9 @@ and is between 256 and 4096 characters. It is defined in the file
mga= [HW,DRM]
+ min_addr=nn[KMG] [KNL,BOOT,ia64] All physical memory below this
+ physical address is ignored.
+
mminit_loglevel=
[KNL] When CONFIG_DEBUG_MEMORY_INIT is set, this
parameter allows control of the logging verbosity for
@@ -1613,7 +1604,7 @@ and is between 256 and 4096 characters. It is defined in the file
pcd. [PARIDE]
See header of drivers/block/paride/pcd.c.
- See also Documentation/paride.txt.
+ See also Documentation/blockdev/paride.txt.
pci=option[,option...] [PCI] various PCI subsystem options:
off [X86] don't probe for the PCI bus
@@ -1714,7 +1705,7 @@ and is between 256 and 4096 characters. It is defined in the file
pcmv= [HW,PCMCIA] BadgePAD 4
pd. [PARIDE]
- See Documentation/paride.txt.
+ See Documentation/blockdev/paride.txt.
pdcchassis= [PARISC,HW] Disable/Enable PDC Chassis Status codes at
boot time.
@@ -1722,10 +1713,10 @@ and is between 256 and 4096 characters. It is defined in the file
See arch/parisc/kernel/pdc_chassis.c
pf. [PARIDE]
- See Documentation/paride.txt.
+ See Documentation/blockdev/paride.txt.
pg. [PARIDE]
- See Documentation/paride.txt.
+ See Documentation/blockdev/paride.txt.
pirq= [SMP,APIC] Manual mp-table setup
See Documentation/x86/i386/IO-APIC.txt.
@@ -1795,7 +1786,7 @@ and is between 256 and 4096 characters. It is defined in the file
prompt_ramdisk= [RAM] List of RAM disks to prompt for floppy disk
before loading.
- See Documentation/ramdisk.txt.
+ See Documentation/blockdev/ramdisk.txt.
psmouse.proto= [HW,MOUSE] Highest PS2 mouse protocol extension to
probe for; one of (bare|imps|exps|lifebook|any).
@@ -1815,7 +1806,7 @@ and is between 256 and 4096 characters. It is defined in the file
<io>,<mss_io>,<mss_irq>,<mss_dma>,<mpu_io>,<mpu_irq>
pt. [PARIDE]
- See Documentation/paride.txt.
+ See Documentation/blockdev/paride.txt.
pty.legacy_count=
[KNL] Number of legacy pty's. Overwrites compiled-in
@@ -1829,10 +1820,10 @@ and is between 256 and 4096 characters. It is defined in the file
See Documentation/md.txt.
ramdisk_blocksize= [RAM]
- See Documentation/ramdisk.txt.
+ See Documentation/blockdev/ramdisk.txt.
ramdisk_size= [RAM] Sizes of RAM disks in kilobytes
- See Documentation/ramdisk.txt.
+ See Documentation/blockdev/ramdisk.txt.
rcupdate.blimit= [KNL,BOOT]
Set maximum number of finished RCU callbacks to process
@@ -2164,7 +2155,7 @@ and is between 256 and 4096 characters. It is defined in the file
See Documentation/sonypi.txt
specialix= [HW,SERIAL] Specialix multi-serial port adapter
- See Documentation/specialix.txt.
+ See Documentation/serial/specialix.txt.
spia_io_base= [HW,MTD]
spia_fio_base=
diff --git a/Documentation/local_ops.txt b/Documentation/local_ops.txt
index f4f8b1c6c8b..23045b8b50f 100644
--- a/Documentation/local_ops.txt
+++ b/Documentation/local_ops.txt
@@ -149,7 +149,7 @@ static void do_test_timer(unsigned long data)
int cpu;
/* Increment the counters */
- on_each_cpu(test_each, NULL, 0, 1);
+ on_each_cpu(test_each, NULL, 1);
/* Read all the counters */
printk("Counters read from CPU %d\n", smp_processor_id());
for_each_online_cpu(cpu) {
diff --git a/Documentation/networking/phy.txt b/Documentation/networking/phy.txt
index 8df6a7b0e66..88bb71b46da 100644
--- a/Documentation/networking/phy.txt
+++ b/Documentation/networking/phy.txt
@@ -96,7 +96,7 @@ Letting the PHY Abstraction Layer do Everything
static void adjust_link(struct net_device *dev);
Next, you need to know the device name of the PHY connected to this device.
- The name will look something like, "phy0:0", where the first number is the
+ The name will look something like, "0:00", where the first number is the
bus id, and the second is the PHY's address on that bus. Typically,
the bus is responsible for making its ID unique.
diff --git a/Documentation/printk-formats.txt b/Documentation/printk-formats.txt
new file mode 100644
index 00000000000..1b5a5ddbc3e
--- /dev/null
+++ b/Documentation/printk-formats.txt
@@ -0,0 +1,35 @@
+If variable is of Type, use printk format specifier:
+---------------------------------------------------------
+ int %d or %x
+ unsigned int %u or %x
+ long %ld or %lx
+ unsigned long %lu or %lx
+ long long %lld or %llx
+ unsigned long long %llu or %llx
+ size_t %zu or %zx
+ ssize_t %zd or %zx
+
+Raw pointer value SHOULD be printed with %p.
+
+u64 SHOULD be printed with %llu/%llx, (unsigned long long):
+
+ printk("%llu", (unsigned long long)u64_var);
+
+s64 SHOULD be printed with %lld/%llx, (long long):
+
+ printk("%lld", (long long)s64_var);
+
+If <type> is dependent on a config option for its size (e.g., sector_t,
+blkcnt_t, phys_addr_t, resource_size_t) or is architecture-dependent
+for its size (e.g., tcflag_t), use a format specifier of its largest
+possible type and explicitly cast to it. Example:
+
+ printk("test: sector number/total blocks: %llu/%llu\n",
+ (unsigned long long)sector, (unsigned long long)blockcount);
+
+Reminder: sizeof() result is of type size_t.
+
+Thank you for your cooperation and attention.
+
+
+By Randy Dunlap <rdunlap@xenotime.net>
diff --git a/Documentation/serial/00-INDEX b/Documentation/serial/00-INDEX
new file mode 100644
index 00000000000..07dcdb0d2a3
--- /dev/null
+++ b/Documentation/serial/00-INDEX
@@ -0,0 +1,24 @@
+00-INDEX
+ - this file.
+README.cycladesZ
+ - info on Cyclades-Z firmware loading.
+computone.txt
+ - info on Computone Intelliport II/Plus Multiport Serial Driver.
+digiepca.txt
+ - info on Digi Intl. {PC,PCI,EISA}Xx and Xem series cards.
+hayes-esp.txt
+ - info on using the Hayes ESP serial driver.
+moxa-smartio
+ - file with info on installing/using Moxa multiport serial driver.
+riscom8.txt
+ - notes on using the RISCom/8 multi-port serial driver.
+rocket.txt
+ - info on the Comtrol RocketPort multiport serial driver.
+specialix.txt
+ - info on hardware/driver for specialix IO8+ multiport serial card.
+stallion.txt
+ - info on using the Stallion multiport serial driver.
+sx.txt
+ - info on the Specialix SX/SI multiport serial driver.
+tty.txt
+ - guide to the locking policies of the tty layer.
diff --git a/Documentation/README.cycladesZ b/Documentation/serial/README.cycladesZ
index 024a69443cc..024a69443cc 100644
--- a/Documentation/README.cycladesZ
+++ b/Documentation/serial/README.cycladesZ
diff --git a/Documentation/computone.txt b/Documentation/serial/computone.txt
index 5e2a0c76bfa..c57ea4781e5 100644
--- a/Documentation/computone.txt
+++ b/Documentation/serial/computone.txt
@@ -247,7 +247,7 @@ shar archive to make it easier to extract the script from the documentation.
To create the ip2mkdev shell script change to a convenient directory (/tmp
works just fine) and run the following command:
- unshar Documentation/computone.txt
+ unshar Documentation/serial/computone.txt
(This file)
You should now have a file ip2mkdev in your current working directory with
diff --git a/Documentation/digiepca.txt b/Documentation/serial/digiepca.txt
index f2560e22f2c..f2560e22f2c 100644
--- a/Documentation/digiepca.txt
+++ b/Documentation/serial/digiepca.txt
diff --git a/Documentation/hayes-esp.txt b/Documentation/serial/hayes-esp.txt
index 09b5d585675..09b5d585675 100644
--- a/Documentation/hayes-esp.txt
+++ b/Documentation/serial/hayes-esp.txt
diff --git a/Documentation/moxa-smartio b/Documentation/serial/moxa-smartio
index 5337e80a5b9..5337e80a5b9 100644
--- a/Documentation/moxa-smartio
+++ b/Documentation/serial/moxa-smartio
diff --git a/Documentation/riscom8.txt b/Documentation/serial/riscom8.txt
index 14f61fdad7c..14f61fdad7c 100644
--- a/Documentation/riscom8.txt
+++ b/Documentation/serial/riscom8.txt
diff --git a/Documentation/rocket.txt b/Documentation/serial/rocket.txt
index 1d858299043..1d858299043 100644
--- a/Documentation/rocket.txt
+++ b/Documentation/serial/rocket.txt
diff --git a/Documentation/specialix.txt b/Documentation/serial/specialix.txt
index 6eb6f3a3331..6eb6f3a3331 100644
--- a/Documentation/specialix.txt
+++ b/Documentation/serial/specialix.txt
diff --git a/Documentation/stallion.txt b/Documentation/serial/stallion.txt
index 5c4902d9a5b..5c4902d9a5b 100644
--- a/Documentation/stallion.txt
+++ b/Documentation/serial/stallion.txt
diff --git a/Documentation/sx.txt b/Documentation/serial/sx.txt
index cb4efa0fb5c..cb4efa0fb5c 100644
--- a/Documentation/sx.txt
+++ b/Documentation/serial/sx.txt
diff --git a/Documentation/tty.txt b/Documentation/serial/tty.txt
index 8e65c4498c5..8e65c4498c5 100644
--- a/Documentation/tty.txt
+++ b/Documentation/serial/tty.txt
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index e0e54a27fc1..841a9365d5f 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -757,6 +757,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
model - force the model name
position_fix - Fix DMA pointer (0 = auto, 1 = use LPIB, 2 = POSBUF)
probe_mask - Bitmask to probe codecs (default = -1, meaning all slots)
+ probe_only - Only probing and no codec initialization (default=off);
+ Useful to check the initial codec status for debugging
bdl_pos_adj - Specifies the DMA IRQ timing delay in samples.
Passing -1 will make the driver to choose the appropriate
value based on the controller chip.
@@ -772,322 +774,23 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
This module supports multiple cards and autoprobe.
+ See Documentation/sound/alsa/HD-Audio.txt for more details about
+ HD-audio driver.
+
Each codec may have a model table for different configurations.
If your machine isn't listed there, the default (usually minimal)
configuration is set up. You can pass "model=<name>" option to
specify a certain model in such a case. There are different
- models depending on the codec chip.
-
- Model name Description
- ---------- -----------
- ALC880
- 3stack 3-jack in back and a headphone out
- 3stack-digout 3-jack in back, a HP out and a SPDIF out
- 5stack 5-jack in back, 2-jack in front
- 5stack-digout 5-jack in back, 2-jack in front, a SPDIF out
- 6stack 6-jack in back, 2-jack in front
- 6stack-digout 6-jack with a SPDIF out
- w810 3-jack
- z71v 3-jack (HP shared SPDIF)
- asus 3-jack (ASUS Mobo)
- asus-w1v ASUS W1V
- asus-dig ASUS with SPDIF out
- asus-dig2 ASUS with SPDIF out (using GPIO2)
- uniwill 3-jack
- fujitsu Fujitsu Laptops (Pi1536)
- F1734 2-jack
- lg LG laptop (m1 express dual)
- lg-lw LG LW20/LW25 laptop
- tcl TCL S700
- clevo Clevo laptops (m520G, m665n)
- medion Medion Rim 2150
- test for testing/debugging purpose, almost all controls can be
- adjusted. Appearing only when compiled with
- $CONFIG_SND_DEBUG=y
- auto auto-config reading BIOS (default)
-
- ALC260
- hp HP machines
- hp-3013 HP machines (3013-variant)
- hp-dc7600 HP DC7600
- fujitsu Fujitsu S7020
- acer Acer TravelMate
- will Will laptops (PB V7900)
- replacer Replacer 672V
- basic fixed pin assignment (old default model)
- test for testing/debugging purpose, almost all controls can
- adjusted. Appearing only when compiled with
- $CONFIG_SND_DEBUG=y
- auto auto-config reading BIOS (default)
-
- ALC262
- fujitsu Fujitsu Laptop
- hp-bpc HP xw4400/6400/8400/9400 laptops
- hp-bpc-d7000 HP BPC D7000
- hp-tc-t5735 HP Thin Client T5735
- hp-rp5700 HP RP5700
- benq Benq ED8
- benq-t31 Benq T31
- hippo Hippo (ATI) with jack detection, Sony UX-90s
- hippo_1 Hippo (Benq) with jack detection
- sony-assamd Sony ASSAMD
- toshiba-s06 Toshiba S06
- toshiba-rx1 Toshiba RX1
- ultra Samsung Q1 Ultra Vista model
- lenovo-3000 Lenovo 3000 y410
- nec NEC Versa S9100
- basic fixed pin assignment w/o SPDIF
- auto auto-config reading BIOS (default)
-
- ALC267/268
- quanta-il1 Quanta IL1 mini-notebook
- 3stack 3-stack model
- toshiba Toshiba A205
- acer Acer laptops
- acer-aspire Acer Aspire One
- dell Dell OEM laptops (Vostro 1200)
- zepto Zepto laptops
- test for testing/debugging purpose, almost all controls can
- adjusted. Appearing only when compiled with
- $CONFIG_SND_DEBUG=y
- auto auto-config reading BIOS (default)
-
- ALC269
- basic Basic preset
- quanta Quanta FL1
- eeepc-p703 ASUS Eeepc P703 P900A
- eeepc-p901 ASUS Eeepc P901 S101
-
- ALC662/663
- 3stack-dig 3-stack (2-channel) with SPDIF
- 3stack-6ch 3-stack (6-channel)
- 3stack-6ch-dig 3-stack (6-channel) with SPDIF
- 6stack-dig 6-stack with SPDIF
- lenovo-101e Lenovo laptop
- eeepc-p701 ASUS Eeepc P701
- eeepc-ep20 ASUS Eeepc EP20
- ecs ECS/Foxconn mobo
- m51va ASUS M51VA
- g71v ASUS G71V
- h13 ASUS H13
- g50v ASUS G50V
- asus-mode1 ASUS
- asus-mode2 ASUS
- asus-mode3 ASUS
- asus-mode4 ASUS
- asus-mode5 ASUS
- asus-mode6 ASUS
- auto auto-config reading BIOS (default)
-
- ALC882/885
- 3stack-dig 3-jack with SPDIF I/O
- 6stack-dig 6-jack digital with SPDIF I/O
- arima Arima W820Di1
- targa Targa T8, MSI-1049 T8
- asus-a7j ASUS A7J
- asus-a7m ASUS A7M
- macpro MacPro support
- mbp3 Macbook Pro rev3
- imac24 iMac 24'' with jack detection
- w2jc ASUS W2JC
- auto auto-config reading BIOS (default)
-
- ALC883/888
- 3stack-dig 3-jack with SPDIF I/O
- 6stack-dig 6-jack digital with SPDIF I/O
- 3stack-6ch 3-jack 6-channel
- 3stack-6ch-dig 3-jack 6-channel with SPDIF I/O
- 6stack-dig-demo 6-jack digital for Intel demo board
- acer Acer laptops (Travelmate 3012WTMi, Aspire 5600, etc)
- acer-aspire Acer Aspire 9810
- medion Medion Laptops
- medion-md2 Medion MD2
- targa-dig Targa/MSI
- targa-2ch-dig Targs/MSI with 2-channel
- laptop-eapd 3-jack with SPDIF I/O and EAPD (Clevo M540JE, M550JE)
- lenovo-101e Lenovo 101E
- lenovo-nb0763 Lenovo NB0763
- lenovo-ms7195-dig Lenovo MS7195
- lenovo-sky Lenovo Sky
- haier-w66 Haier W66
- 3stack-hp HP machines with 3stack (Lucknow, Samba boards)
- 6stack-dell Dell machines with 6stack (Inspiron 530)
- mitac Mitac 8252D
- clevo-m720 Clevo M720 laptop series
- fujitsu-pi2515 Fujitsu AMILO Pi2515
- 3stack-6ch-intel Intel DG33* boards
- auto auto-config reading BIOS (default)
-
- ALC861/660
- 3stack 3-jack
- 3stack-dig 3-jack with SPDIF I/O
- 6stack-dig 6-jack with SPDIF I/O
- 3stack-660 3-jack (for ALC660)
- uniwill-m31 Uniwill M31 laptop
- toshiba Toshiba laptop support
- asus Asus laptop support
- asus-laptop ASUS F2/F3 laptops
- auto auto-config reading BIOS (default)
-
- ALC861VD/660VD
- 3stack 3-jack
- 3stack-dig 3-jack with SPDIF OUT
- 6stack-dig 6-jack with SPDIF OUT
- 3stack-660 3-jack (for ALC660VD)
- 3stack-660-digout 3-jack with SPDIF OUT (for ALC660VD)
- lenovo Lenovo 3000 C200
- dallas Dallas laptops
- hp HP TX1000
- auto auto-config reading BIOS (default)
-
- CMI9880
- minimal 3-jack in back
- min_fp 3-jack in back, 2-jack in front
- full 6-jack in back, 2-jack in front
- full_dig 6-jack in back, 2-jack in front, SPDIF I/O
- allout 5-jack in back, 2-jack in front, SPDIF out
- auto auto-config reading BIOS (default)
-
- AD1882 / AD1882A
- 3stack 3-stack mode (default)
- 6stack 6-stack mode
-
- AD1884A / AD1883 / AD1984A / AD1984B
- desktop 3-stack desktop (default)
- laptop laptop with HP jack sensing
- mobile mobile devices with HP jack sensing
- thinkpad Lenovo Thinkpad X300
-
- AD1884
- N/A
-
- AD1981
- basic 3-jack (default)
- hp HP nx6320
- thinkpad Lenovo Thinkpad T60/X60/Z60
- toshiba Toshiba U205
-
- AD1983
- N/A
-
- AD1984
- basic default configuration
- thinkpad Lenovo Thinkpad T61/X61
- dell Dell T3400
-
- AD1986A
- 6stack 6-jack, separate surrounds (default)
- 3stack 3-stack, shared surrounds
- laptop 2-channel only (FSC V2060, Samsung M50)
- laptop-eapd 2-channel with EAPD (Samsung R65, ASUS A6J)
- laptop-automute 2-channel with EAPD and HP-automute (Lenovo N100)
- ultra 2-channel with EAPD (Samsung Ultra tablet PC)
-
- AD1988/AD1988B/AD1989A/AD1989B
- 6stack 6-jack
- 6stack-dig ditto with SPDIF
- 3stack 3-jack
- 3stack-dig ditto with SPDIF
- laptop 3-jack with hp-jack automute
- laptop-dig ditto with SPDIF
- auto auto-config reading BIOS (default)
-
- Conexant 5045
- laptop-hpsense Laptop with HP sense (old model laptop)
- laptop-micsense Laptop with Mic sense (old model fujitsu)
- laptop-hpmicsense Laptop with HP and Mic senses
- benq Benq R55E
- test for testing/debugging purpose, almost all controls
- can be adjusted. Appearing only when compiled with
- $CONFIG_SND_DEBUG=y
-
- Conexant 5047
- laptop Basic Laptop config
- laptop-hp Laptop config for some HP models (subdevice 30A5)
- laptop-eapd Laptop config with EAPD support
- test for testing/debugging purpose, almost all controls
- can be adjusted. Appearing only when compiled with
- $CONFIG_SND_DEBUG=y
-
- Conexant 5051
- laptop Basic Laptop config (default)
- hp HP Spartan laptop
-
- STAC9200
- ref Reference board
- dell-d21 Dell (unknown)
- dell-d22 Dell (unknown)
- dell-d23 Dell (unknown)
- dell-m21 Dell Inspiron 630m, Dell Inspiron 640m
- dell-m22 Dell Latitude D620, Dell Latitude D820
- dell-m23 Dell XPS M1710, Dell Precision M90
- dell-m24 Dell Latitude 120L
- dell-m25 Dell Inspiron E1505n
- dell-m26 Dell Inspiron 1501
- dell-m27 Dell Inspiron E1705/9400
- gateway Gateway laptops with EAPD control
- panasonic Panasonic CF-74
-
- STAC9205/9254
- ref Reference board
- dell-m42 Dell (unknown)
- dell-m43 Dell Precision
- dell-m44 Dell Inspiron
-
- STAC9220/9221
- ref Reference board
- 3stack D945 3stack
- 5stack D945 5stack + SPDIF
- intel-mac-v1 Intel Mac Type 1
- intel-mac-v2 Intel Mac Type 2
- intel-mac-v3 Intel Mac Type 3
- intel-mac-v4 Intel Mac Type 4
- intel-mac-v5 Intel Mac Type 5
- intel-mac-auto Intel Mac (detect type according to subsystem id)
- macmini Intel Mac Mini (equivalent with type 3)
- macbook Intel Mac Book (eq. type 5)
- macbook-pro-v1 Intel Mac Book Pro 1st generation (eq. type 3)
- macbook-pro Intel Mac Book Pro 2nd generation (eq. type 3)
- imac-intel Intel iMac (eq. type 2)
- imac-intel-20 Intel iMac (newer version) (eq. type 3)
- dell-d81 Dell (unknown)
- dell-d82 Dell (unknown)
- dell-m81 Dell (unknown)
- dell-m82 Dell XPS M1210
-
- STAC9202/9250/9251
- ref Reference board, base config
- m2-2 Some Gateway MX series laptops
- m6 Some Gateway NX series laptops
- pa6 Gateway NX860 series
-
- STAC9227/9228/9229/927x
- ref Reference board
- 3stack D965 3stack
- 5stack D965 5stack + SPDIF
- dell-3stack Dell Dimension E520
- dell-bios Fixes with Dell BIOS setup
-
- STAC92HD71B*
- ref Reference board
- dell-m4-1 Dell desktops
- dell-m4-2 Dell desktops
-
- STAC92HD73*
- ref Reference board
- dell-m6 Dell desktops
-
- STAC9872
- vaio Setup for VAIO FE550G/SZ110
- vaio-ar Setup for VAIO AR
+ models depending on the codec chip. The list of available models
+ is found in HD-Audio-Models.txt
The model name "genric" is treated as a special case. When this
model is given, the driver uses the generic codec parser without
"codec-patch". It's sometimes good for testing and debugging.
If the default configuration doesn't work and one of the above
- matches with your device, report it together with the PCI
- subsystem ID (output of "lspci -nv") to ALSA BTS or alsa-devel
+ matches with your device, report it together with alsa-info.sh
+ output (with --no-upload option) to kernel bugzilla or alsa-devel
ML (see the section "Links and Addresses").
power_save and power_save_controller options are for power-saving
@@ -1647,7 +1350,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
* AuzenTech X-Meridian
* Bgears b-Enspirer
* Club3D Theatron DTS
- * HT-Omega Claro
+ * HT-Omega Claro (plus)
+ * HT-Omega Claro halo (XT)
* Razer Barracuda AC-1
* Sondigo Inferno
@@ -2404,8 +2108,11 @@ Links and Addresses
ALSA project homepage
http://www.alsa-project.org
- ALSA Bug Tracking System
- https://bugtrack.alsa-project.org/bugs/
+ Kernel Bugzilla
+ http://bugzilla.kernel.org/
ALSA Developers ML
mailto:alsa-devel@alsa-project.org
+
+ alsa-info.sh script
+ http://www.alsa-project.org/alsa-info.sh
diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt
new file mode 100644
index 00000000000..4b7ac21ea9e
--- /dev/null
+++ b/Documentation/sound/alsa/HD-Audio-Models.txt
@@ -0,0 +1,348 @@
+ Model name Description
+ ---------- -----------
+ALC880
+======
+ 3stack 3-jack in back and a headphone out
+ 3stack-digout 3-jack in back, a HP out and a SPDIF out
+ 5stack 5-jack in back, 2-jack in front
+ 5stack-digout 5-jack in back, 2-jack in front, a SPDIF out
+ 6stack 6-jack in back, 2-jack in front
+ 6stack-digout 6-jack with a SPDIF out
+ w810 3-jack
+ z71v 3-jack (HP shared SPDIF)
+ asus 3-jack (ASUS Mobo)
+ asus-w1v ASUS W1V
+ asus-dig ASUS with SPDIF out
+ asus-dig2 ASUS with SPDIF out (using GPIO2)
+ uniwill 3-jack
+ fujitsu Fujitsu Laptops (Pi1536)
+ F1734 2-jack
+ lg LG laptop (m1 express dual)
+ lg-lw LG LW20/LW25 laptop
+ tcl TCL S700
+ clevo Clevo laptops (m520G, m665n)
+ medion Medion Rim 2150
+ test for testing/debugging purpose, almost all controls can be
+ adjusted. Appearing only when compiled with
+ $CONFIG_SND_DEBUG=y
+ auto auto-config reading BIOS (default)
+
+ALC260
+======
+ hp HP machines
+ hp-3013 HP machines (3013-variant)
+ hp-dc7600 HP DC7600
+ fujitsu Fujitsu S7020
+ acer Acer TravelMate
+ will Will laptops (PB V7900)
+ replacer Replacer 672V
+ basic fixed pin assignment (old default model)
+ test for testing/debugging purpose, almost all controls can
+ adjusted. Appearing only when compiled with
+ $CONFIG_SND_DEBUG=y
+ auto auto-config reading BIOS (default)
+
+ALC262
+======
+ fujitsu Fujitsu Laptop
+ hp-bpc HP xw4400/6400/8400/9400 laptops
+ hp-bpc-d7000 HP BPC D7000
+ hp-tc-t5735 HP Thin Client T5735
+ hp-rp5700 HP RP5700
+ benq Benq ED8
+ benq-t31 Benq T31
+ hippo Hippo (ATI) with jack detection, Sony UX-90s
+ hippo_1 Hippo (Benq) with jack detection
+ sony-assamd Sony ASSAMD
+ toshiba-s06 Toshiba S06
+ toshiba-rx1 Toshiba RX1
+ ultra Samsung Q1 Ultra Vista model
+ lenovo-3000 Lenovo 3000 y410
+ nec NEC Versa S9100
+ basic fixed pin assignment w/o SPDIF
+ auto auto-config reading BIOS (default)
+
+ALC267/268
+==========
+ quanta-il1 Quanta IL1 mini-notebook
+ 3stack 3-stack model
+ toshiba Toshiba A205
+ acer Acer laptops
+ acer-dmic Acer laptops with digital-mic
+ acer-aspire Acer Aspire One
+ dell Dell OEM laptops (Vostro 1200)
+ zepto Zepto laptops
+ test for testing/debugging purpose, almost all controls can
+ adjusted. Appearing only when compiled with
+ $CONFIG_SND_DEBUG=y
+ auto auto-config reading BIOS (default)
+
+ALC269
+======
+ basic Basic preset
+ quanta Quanta FL1
+ eeepc-p703 ASUS Eeepc P703 P900A
+ eeepc-p901 ASUS Eeepc P901 S101
+ fujitsu FSC Amilo
+ auto auto-config reading BIOS (default)
+
+ALC662/663
+==========
+ 3stack-dig 3-stack (2-channel) with SPDIF
+ 3stack-6ch 3-stack (6-channel)
+ 3stack-6ch-dig 3-stack (6-channel) with SPDIF
+ 6stack-dig 6-stack with SPDIF
+ lenovo-101e Lenovo laptop
+ eeepc-p701 ASUS Eeepc P701
+ eeepc-ep20 ASUS Eeepc EP20
+ ecs ECS/Foxconn mobo
+ m51va ASUS M51VA
+ g71v ASUS G71V
+ h13 ASUS H13
+ g50v ASUS G50V
+ asus-mode1 ASUS
+ asus-mode2 ASUS
+ asus-mode3 ASUS
+ asus-mode4 ASUS
+ asus-mode5 ASUS
+ asus-mode6 ASUS
+ auto auto-config reading BIOS (default)
+
+ALC882/885
+==========
+ 3stack-dig 3-jack with SPDIF I/O
+ 6stack-dig 6-jack digital with SPDIF I/O
+ arima Arima W820Di1
+ targa Targa T8, MSI-1049 T8
+ asus-a7j ASUS A7J
+ asus-a7m ASUS A7M
+ macpro MacPro support
+ mbp3 Macbook Pro rev3
+ imac24 iMac 24'' with jack detection
+ w2jc ASUS W2JC
+ auto auto-config reading BIOS (default)
+
+ALC883/888
+==========
+ 3stack-dig 3-jack with SPDIF I/O
+ 6stack-dig 6-jack digital with SPDIF I/O
+ 3stack-6ch 3-jack 6-channel
+ 3stack-6ch-dig 3-jack 6-channel with SPDIF I/O
+ 6stack-dig-demo 6-jack digital for Intel demo board
+ acer Acer laptops (Travelmate 3012WTMi, Aspire 5600, etc)
+ acer-aspire Acer Aspire 9810
+ acer-aspire-4930g Acer Aspire 4930G
+ medion Medion Laptops
+ medion-md2 Medion MD2
+ targa-dig Targa/MSI
+ targa-2ch-dig Targs/MSI with 2-channel
+ laptop-eapd 3-jack with SPDIF I/O and EAPD (Clevo M540JE, M550JE)
+ lenovo-101e Lenovo 101E
+ lenovo-nb0763 Lenovo NB0763
+ lenovo-ms7195-dig Lenovo MS7195
+ lenovo-sky Lenovo Sky
+ haier-w66 Haier W66
+ 3stack-hp HP machines with 3stack (Lucknow, Samba boards)
+ 6stack-dell Dell machines with 6stack (Inspiron 530)
+ mitac Mitac 8252D
+ clevo-m720 Clevo M720 laptop series
+ fujitsu-pi2515 Fujitsu AMILO Pi2515
+ fujitsu-xa3530 Fujitsu AMILO XA3530
+ 3stack-6ch-intel Intel DG33* boards
+ auto auto-config reading BIOS (default)
+
+ALC861/660
+==========
+ 3stack 3-jack
+ 3stack-dig 3-jack with SPDIF I/O
+ 6stack-dig 6-jack with SPDIF I/O
+ 3stack-660 3-jack (for ALC660)
+ uniwill-m31 Uniwill M31 laptop
+ toshiba Toshiba laptop support
+ asus Asus laptop support
+ asus-laptop ASUS F2/F3 laptops
+ auto auto-config reading BIOS (default)
+
+ALC861VD/660VD
+==============
+ 3stack 3-jack
+ 3stack-dig 3-jack with SPDIF OUT
+ 6stack-dig 6-jack with SPDIF OUT
+ 3stack-660 3-jack (for ALC660VD)
+ 3stack-660-digout 3-jack with SPDIF OUT (for ALC660VD)
+ lenovo Lenovo 3000 C200
+ dallas Dallas laptops
+ hp HP TX1000
+ asus-v1s ASUS V1Sn
+ auto auto-config reading BIOS (default)
+
+CMI9880
+=======
+ minimal 3-jack in back
+ min_fp 3-jack in back, 2-jack in front
+ full 6-jack in back, 2-jack in front
+ full_dig 6-jack in back, 2-jack in front, SPDIF I/O
+ allout 5-jack in back, 2-jack in front, SPDIF out
+ auto auto-config reading BIOS (default)
+
+AD1882 / AD1882A
+================
+ 3stack 3-stack mode (default)
+ 6stack 6-stack mode
+
+AD1884A / AD1883 / AD1984A / AD1984B
+====================================
+ desktop 3-stack desktop (default)
+ laptop laptop with HP jack sensing
+ mobile mobile devices with HP jack sensing
+ thinkpad Lenovo Thinkpad X300
+
+AD1884
+======
+ N/A
+
+AD1981
+======
+ basic 3-jack (default)
+ hp HP nx6320
+ thinkpad Lenovo Thinkpad T60/X60/Z60
+ toshiba Toshiba U205
+
+AD1983
+======
+ N/A
+
+AD1984
+======
+ basic default configuration
+ thinkpad Lenovo Thinkpad T61/X61
+ dell Dell T3400
+
+AD1986A
+=======
+ 6stack 6-jack, separate surrounds (default)
+ 3stack 3-stack, shared surrounds
+ laptop 2-channel only (FSC V2060, Samsung M50)
+ laptop-eapd 2-channel with EAPD (ASUS A6J)
+ laptop-automute 2-channel with EAPD and HP-automute (Lenovo N100)
+ ultra 2-channel with EAPD (Samsung Ultra tablet PC)
+ samsung 2-channel with EAPD (Samsung R65)
+
+AD1988/AD1988B/AD1989A/AD1989B
+==============================
+ 6stack 6-jack
+ 6stack-dig ditto with SPDIF
+ 3stack 3-jack
+ 3stack-dig ditto with SPDIF
+ laptop 3-jack with hp-jack automute
+ laptop-dig ditto with SPDIF
+ auto auto-config reading BIOS (default)
+
+Conexant 5045
+=============
+ laptop-hpsense Laptop with HP sense (old model laptop)
+ laptop-micsense Laptop with Mic sense (old model fujitsu)
+ laptop-hpmicsense Laptop with HP and Mic senses
+ benq Benq R55E
+ test for testing/debugging purpose, almost all controls
+ can be adjusted. Appearing only when compiled with
+ $CONFIG_SND_DEBUG=y
+
+Conexant 5047
+=============
+ laptop Basic Laptop config
+ laptop-hp Laptop config for some HP models (subdevice 30A5)
+ laptop-eapd Laptop config with EAPD support
+ test for testing/debugging purpose, almost all controls
+ can be adjusted. Appearing only when compiled with
+ $CONFIG_SND_DEBUG=y
+
+Conexant 5051
+=============
+ laptop Basic Laptop config (default)
+ hp HP Spartan laptop
+
+STAC9200
+========
+ ref Reference board
+ dell-d21 Dell (unknown)
+ dell-d22 Dell (unknown)
+ dell-d23 Dell (unknown)
+ dell-m21 Dell Inspiron 630m, Dell Inspiron 640m
+ dell-m22 Dell Latitude D620, Dell Latitude D820
+ dell-m23 Dell XPS M1710, Dell Precision M90
+ dell-m24 Dell Latitude 120L
+ dell-m25 Dell Inspiron E1505n
+ dell-m26 Dell Inspiron 1501
+ dell-m27 Dell Inspiron E1705/9400
+ gateway Gateway laptops with EAPD control
+ panasonic Panasonic CF-74
+
+STAC9205/9254
+=============
+ ref Reference board
+ dell-m42 Dell (unknown)
+ dell-m43 Dell Precision
+ dell-m44 Dell Inspiron
+
+STAC9220/9221
+=============
+ ref Reference board
+ 3stack D945 3stack
+ 5stack D945 5stack + SPDIF
+ intel-mac-v1 Intel Mac Type 1
+ intel-mac-v2 Intel Mac Type 2
+ intel-mac-v3 Intel Mac Type 3
+ intel-mac-v4 Intel Mac Type 4
+ intel-mac-v5 Intel Mac Type 5
+ intel-mac-auto Intel Mac (detect type according to subsystem id)
+ macmini Intel Mac Mini (equivalent with type 3)
+ macbook Intel Mac Book (eq. type 5)
+ macbook-pro-v1 Intel Mac Book Pro 1st generation (eq. type 3)
+ macbook-pro Intel Mac Book Pro 2nd generation (eq. type 3)
+ imac-intel Intel iMac (eq. type 2)
+ imac-intel-20 Intel iMac (newer version) (eq. type 3)
+ dell-d81 Dell (unknown)
+ dell-d82 Dell (unknown)
+ dell-m81 Dell (unknown)
+ dell-m82 Dell XPS M1210
+
+STAC9202/9250/9251
+==================
+ ref Reference board, base config
+ m2-2 Some Gateway MX series laptops
+ m6 Some Gateway NX series laptops
+ pa6 Gateway NX860 series
+
+STAC9227/9228/9229/927x
+=======================
+ ref Reference board
+ ref-no-jd Reference board without HP/Mic jack detection
+ 3stack D965 3stack
+ 5stack D965 5stack + SPDIF
+ dell-3stack Dell Dimension E520
+ dell-bios Fixes with Dell BIOS setup
+
+STAC92HD71B*
+============
+ ref Reference board
+ dell-m4-1 Dell desktops
+ dell-m4-2 Dell desktops
+ dell-m4-3 Dell desktops
+
+STAC92HD73*
+===========
+ ref Reference board
+ no-jd BIOS setup but without jack-detection
+ dell-m6-amic Dell desktops/laptops with analog mics
+ dell-m6-dmic Dell desktops/laptops with digital mics
+ dell-m6 Dell desktops/laptops with both type of mics
+
+STAC92HD83*
+===========
+ ref Reference board
+
+STAC9872
+========
+ vaio Setup for VAIO FE550G/SZ110
+ vaio-ar Setup for VAIO AR
diff --git a/Documentation/sound/alsa/HD-Audio.txt b/Documentation/sound/alsa/HD-Audio.txt
new file mode 100644
index 00000000000..8d68fff7183
--- /dev/null
+++ b/Documentation/sound/alsa/HD-Audio.txt
@@ -0,0 +1,577 @@
+MORE NOTES ON HD-AUDIO DRIVER
+=============================
+ Takashi Iwai <tiwai@suse.de>
+
+
+GENERAL
+-------
+
+HD-audio is the new standard on-board audio component on modern PCs
+after AC97. Although Linux has been supporting HD-audio since long
+time ago, there are often problems with new machines. A part of the
+problem is broken BIOS, and the rest is the driver implementation.
+This document explains the brief trouble-shooting and debugging
+methods for the HD-audio hardware.
+
+The HD-audio component consists of two parts: the controller chip and
+the codec chips on the HD-audio bus. Linux provides a single driver
+for all controllers, snd-hda-intel. Although the driver name contains
+a word of a well-known harware vendor, it's not specific to it but for
+all controller chips by other companies. Since the HD-audio
+controllers are supposed to be compatible, the single snd-hda-driver
+should work in most cases. But, not surprisingly, there are known
+bugs and issues specific to each controller type. The snd-hda-intel
+driver has a bunch of workarounds for these as described below.
+
+A controller may have multiple codecs. Usually you have one audio
+codec and optionally one modem codec. In theory, there might be
+multiple audio codecs, e.g. for analog and digital outputs, and the
+driver might not work properly because of conflict of mixer elements.
+This should be fixed in future if such hardware really exists.
+
+The snd-hda-intel driver has several different codec parsers depending
+on the codec. It has a generic parser as a fallback, but this
+functionality is fairly limited until now. Instead of the generic
+parser, usually the codec-specific parser (coded in patch_*.c) is used
+for the codec-specific implementations. The details about the
+codec-specific problems are explained in the later sections.
+
+If you are interested in the deep debugging of HD-audio, read the
+HD-audio specification at first. The specification is found on
+Intel's web page, for example:
+
+- http://www.intel.com/standards/hdaudio/
+
+
+HD-AUDIO CONTROLLER
+-------------------
+
+DMA-Position Problem
+~~~~~~~~~~~~~~~~~~~~
+The most common problem of the controller is the inaccurate DMA
+pointer reporting. The DMA pointer for playback and capture can be
+read in two ways, either via a LPIB register or via a position-buffer
+map. As default the driver tries to read from the io-mapped
+position-buffer, and falls back to LPIB if the position-buffer appears
+dead. However, this detection isn't perfect on some devices. In such
+a case, you can change the default method via `position_fix` option.
+
+`position_fix=1` means to use LPIB method explicitly.
+`position_fix=2` means to use the position-buffer. 0 is the default
+value, the automatic check and fallback to LPIB as described in the
+above. If you get a problem of repeated sounds, this option might
+help.
+
+In addition to that, every controller is known to be broken regarding
+the wake-up timing. It wakes up a few samples before actually
+processing the data on the buffer. This caused a lot of problems, for
+example, with ALSA dmix or JACK. Since 2.6.27 kernel, the driver puts
+an artificial delay to the wake up timing. This delay is controlled
+via `bdl_pos_adj` option.
+
+When `bdl_pos_adj` is a negative value (as default), it's assigned to
+an appropriate value depending on the controller chip. For Intel
+chips, it'd be 1 while it'd be 32 for others. Usually this works.
+Only in case it doesn't work and you get warning messages, you should
+change this parameter to other values.
+
+
+Codec-Probing Problem
+~~~~~~~~~~~~~~~~~~~~~
+A less often but a more severe problem is the codec probing. When
+BIOS reports the available codec slots wrongly, the driver gets
+confused and tries to access the non-existing codec slot. This often
+results in the total screw-up, and destructs the further communication
+with the codec chips. The symptom appears usually as error messages
+like:
+------------------------------------------------------------------------
+ hda_intel: azx_get_response timeout, switching to polling mode:
+ last cmd=0x12345678
+ hda_intel: azx_get_response timeout, switching to single_cmd mode:
+ last cmd=0x12345678
+------------------------------------------------------------------------
+
+The first line is a warning, and this is usually relatively harmless.
+It means that the codec response isn't notified via an IRQ. The
+driver uses explicit polling method to read the response. It gives
+very slight CPU overhead, but you'd unlikely notice it.
+
+The second line is, however, a fatal error. If this happens, usually
+it means that something is really wrong. Most likely you are
+accessing a non-existing codec slot.
+
+Thus, if the second error message appears, try to narrow the probed
+codec slots via `probe_mask` option. It's a bitmask, and each bit
+corresponds to the codec slot. For example, to probe only the first
+slot, pass `probe_mask=1`. For the first and the third slots, pass
+`probe_mask=5` (where 5 = 1 | 4), and so on.
+
+Since 2.6.29 kernel, the driver has a more robust probing method, so
+this error might happen rarely, though.
+
+
+Interrupt Handling
+~~~~~~~~~~~~~~~~~~
+In rare but some cases, the interrupt isn't properly handled as
+default. You would notice this by the DMA transfer error reported by
+ALSA PCM core, for example. Using MSI might help in such a case.
+Pass `enable_msi=1` option for enabling MSI.
+
+
+HD-AUDIO CODEC
+--------------
+
+Model Option
+~~~~~~~~~~~~
+The most common problem regarding the HD-audio driver is the
+unsupported codec features or the mismatched device configuration.
+Most of codec-specific code has several preset models, either to
+override the BIOS setup or to provide more comprehensive features.
+
+The driver checks PCI SSID and looks through the static configuration
+table until any matching entry is found. If you have a new machine,
+you may see a message like below:
+------------------------------------------------------------------------
+ hda_codec: Unknown model for ALC880, trying auto-probe from BIOS...
+------------------------------------------------------------------------
+Even if you see such a message, DON'T PANIC. Take a deep breath and
+keep your towel. First of all, it's an informational message, no
+warning, no error. This means that the PCI SSID of your device isn't
+listed in the known preset model (white-)list. But, this doesn't mean
+that the driver is broken. Many codec-drivers provide the automatic
+configuration mechanism based on the BIOS setup.
+
+The HD-audio codec has usually "pin" widgets, and BIOS sets the default
+configuration of each pin, which indicates the location, the
+connection type, the jack color, etc. The HD-audio driver can guess
+the right connection judging from these default configuration values.
+However -- some codec-support codes, such as patch_analog.c, don't
+support the automatic probing (yet as of 2.6.28). And, BIOS is often,
+yes, pretty often broken. It sets up wrong values and screws up the
+driver.
+
+The preset model is provided basically to overcome such a situation.
+When the matching preset model is found in the white-list, the driver
+assumes the static configuration of that preset and builds the mixer
+elements and PCM streams based on the static information. Thus, if
+you have a newer machine with a slightly different PCI SSID from the
+existing one, you may have a good chance to re-use the same model.
+You can pass the `model` option to specify the preset model instead of
+PCI SSID look-up.
+
+What `model` option values are available depends on the codec chip.
+Check your codec chip from the codec proc file (see "Codec Proc-File"
+section below). It will show the vendor/product name of your codec
+chip. Then, see Documentation/sound/alsa/HD-Audio-Modelstxt file,
+the section of HD-audio driver. You can find a list of codecs
+and `model` options belonging to each codec. For example, for Realtek
+ALC262 codec chip, pass `model=ultra` for devices that are compatible
+with Samsung Q1 Ultra.
+
+Thus, the first thing you can do for any brand-new, unsupported and
+non-working HD-audio hardware is to check HD-audio codec and several
+different `model` option values. If you have a luck, some of them
+might suit with your device well.
+
+Some codecs such as ALC880 have a special model option `model=test`.
+This configures the driver to provide as many mixer controls as
+possible for every single pin feature except for the unsolicited
+events (and maybe some other specials). Adjust each mixer element and
+try the I/O in the way of trial-and-error until figuring out the whole
+I/O pin mappings.
+
+Note that `model=generic` has a special meaning. It means to use the
+generic parser regardless of the codec. Usually the codec-specific
+parser is much better than the generic parser (as now). Thus this
+option is more about the debugging purpose.
+
+
+Speaker and Headphone Output
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+One of the most frequent (and obvious) bugs with HD-audio is the
+silent output from either or both of a built-in speaker and a
+headphone jack. In general, you should try a headphone output at
+first. A speaker output often requires more additional controls like
+the external amplifier bits. Thus a headphone output has a slightly
+better chance.
+
+Before making a bug report, double-check whether the mixer is set up
+correctly. The recent version of snd-hda-intel driver provides mostly
+"Master" volume control as well as "Front" volume (where Front
+indicates the front-channels). In addition, there can be individual
+"Headphone" and "Speaker" controls.
+
+Ditto for the speaker output. There can be "External Amplifier"
+switch on some codecs. Turn on this if present.
+
+Another related problem is the automatic mute of speaker output by
+headphone plugging. This feature is implemented in most cases, but
+not on every preset model or codec-support code.
+
+In anyway, try a different model option if you have such a problem.
+Some other models may match better and give you more matching
+functionality. If none of the available models works, send a bug
+report. See the bug report section for details.
+
+If you are masochistic enough to debug the driver problem, note the
+following:
+
+- The speaker (and the headphone, too) output often requires the
+ external amplifier. This can be set usually via EAPD verb or a
+ certain GPIO. If the codec pin supports EAPD, you have a better
+ chance via SET_EAPD_BTL verb (0x70c). On others, GPIO pin (mostly
+ it's either GPIO0 or GPIO1) may turn on/off EAPD.
+- Some Realtek codecs require special vendor-specific coefficients to
+ turn on the amplifier. See patch_realtek.c.
+- IDT codecs may have extra power-enable/disable controls on each
+ analog pin. See patch_sigmatel.c.
+- Very rare but some devices don't accept the pin-detection verb until
+ triggered. Issuing GET_PIN_SENSE verb (0xf09) may result in the
+ codec-communication stall. Some examples are found in
+ patch_realtek.c.
+
+
+Capture Problems
+~~~~~~~~~~~~~~~~
+The capture problems are often because of missing setups of mixers.
+Thus, before submitting a bug report, make sure that you set up the
+mixer correctly. For example, both "Capture Volume" and "Capture
+Switch" have to be set properly in addition to the right "Capture
+Source" or "Input Source" selection. Some devices have "Mic Boost"
+volume or switch.
+
+When the PCM device is opened via "default" PCM (without pulse-audio
+plugin), you'll likely have "Digital Capture Volume" control as well.
+This is provided for the extra gain/attenuation of the signal in
+software, especially for the inputs without the hardware volume
+control such as digital microphones. Unless really needed, this
+should be set to exactly 50%, corresponding to 0dB -- neither extra
+gain nor attenuation. When you use "hw" PCM, i.e., a raw access PCM,
+this control will have no influence, though.
+
+It's known that some codecs / devices have fairly bad analog circuits,
+and the recorded sound contains a certain DC-offset. This is no bug
+of the driver.
+
+Most of modern laptops have no analog CD-input connection. Thus, the
+recording from CD input won't work in many cases although the driver
+provides it as the capture source. Use CDDA instead.
+
+The automatic switching of the built-in and external mic per plugging
+is implemented on some codec models but not on every model. Partly
+because of my laziness but mostly lack of testers. Feel free to
+submit the improvement patch to the author.
+
+
+Direct Debugging
+~~~~~~~~~~~~~~~~
+If no model option gives you a better result, and you are a tough guy
+to fight against evil, try debugging via hitting the raw HD-audio
+codec verbs to the device. Some tools are available: hda-emu and
+hda-analyzer. The detailed description is found in the sections
+below. You'd need to enable hwdep for using these tools. See "Kernel
+Configuration" section.
+
+
+OTHER ISSUES
+------------
+
+Kernel Configuration
+~~~~~~~~~~~~~~~~~~~~
+In general, I recommend you to enable the sound debug option,
+`CONFIG_SND_DEBUG=y`, no matter whether you are debugging or not.
+This enables snd_printd() macro and others, and you'll get additional
+kernel messages at probing.
+
+In addition, you can enable `CONFIG_SND_DEBUG_VERBOSE=y`. But this
+will give you far more messages. Thus turn this on only when you are
+sure to want it.
+
+Don't forget to turn on the appropriate `CONFIG_SND_HDA_CODEC_*`
+options. Note that each of them corresponds to the codec chip, not
+the controller chip. Thus, even if lspci shows the Nvidia controller,
+you may need to choose the option for other vendors. If you are
+unsure, just select all yes.
+
+`CONFIG_SND_HDA_HWDEP` is a useful option for debugging the driver.
+When this is enabled, the driver creates hardware-dependent devices
+(one per each codec), and you have a raw access to the device via
+these device files. For example, `hwC0D2` will be created for the
+codec slot #2 of the first card (#0). For debug-tools such as
+hda-verb and hda-analyzer, the hwdep device has to be enabled.
+Thus, it'd be better to turn this on always.
+
+`CONFIG_SND_HDA_RECONFIG` is a new option, and this depends on the
+hwdep option above. When enabled, you'll have some sysfs files under
+the corresponding hwdep directory. See "HD-audio reconfiguration"
+section below.
+
+`CONFIG_SND_HDA_POWER_SAVE` option enables the power-saving feature.
+See "Power-saving" section below.
+
+
+Codec Proc-File
+~~~~~~~~~~~~~~~
+The codec proc-file is a treasure-chest for debugging HD-audio.
+It shows most of useful information of each codec widget.
+
+The proc file is located in /proc/asound/card*/codec#*, one file per
+each codec slot. You can know the codec vendor, product id and
+names, the type of each widget, capabilities and so on.
+This file, however, doesn't show the jack sensing state, so far. This
+is because the jack-sensing might be depending on the trigger state.
+
+This file will be picked up by the debug tools, and also it can be fed
+to the emulator as the primary codec information. See the debug tools
+section below.
+
+This proc file can be also used to check whether the generic parser is
+used. When the generic parser is used, the vendor/product ID name
+will appear as "Realtek ID 0262", instead of "Realtek ALC262".
+
+
+HD-Audio Reconfiguration
+~~~~~~~~~~~~~~~~~~~~~~~~
+This is an experimental feature to allow you re-configure the HD-audio
+codec dynamically without reloading the driver. The following sysfs
+files are available under each codec-hwdep device directory (e.g.
+/sys/class/sound/hwC0D0):
+
+vendor_id::
+ Shows the 32bit codec vendor-id hex number. You can change the
+ vendor-id value by writing to this file.
+subsystem_id::
+ Shows the 32bit codec subsystem-id hex number. You can change the
+ subsystem-id value by writing to this file.
+revision_id::
+ Shows the 32bit codec revision-id hex number. You can change the
+ revision-id value by writing to this file.
+afg::
+ Shows the AFG ID. This is read-only.
+mfg::
+ Shows the MFG ID. This is read-only.
+name::
+ Shows the codec name string. Can be changed by writing to this
+ file.
+modelname::
+ Shows the currently set `model` option. Can be changed by writing
+ to this file.
+init_verbs::
+ The extra verbs to execute at initialization. You can add a verb by
+ writing to this file. Pass tree numbers, nid, verb and parameter.
+hints::
+ Shows hint strings for codec parsers for any use. Right now it's
+ not used.
+reconfig::
+ Triggers the codec re-configuration. When any value is written to
+ this file, the driver re-initialize and parses the codec tree
+ again. All the changes done by the sysfs entries above are taken
+ into account.
+clear::
+ Resets the codec, removes the mixer elements and PCM stuff of the
+ specified codec, and clear all init verbs and hints.
+
+
+Power-Saving
+~~~~~~~~~~~~
+The power-saving is a kind of auto-suspend of the device. When the
+device is inactive for a certain time, the device is automatically
+turned off to save the power. The time to go down is specified via
+`power_save` module option, and this option can be changed dynamically
+via sysfs.
+
+The power-saving won't work when the analog loopback is enabled on
+some codecs. Make sure that you mute all unneeded signal routes when
+you want the power-saving.
+
+The power-saving feature might cause audible click noises at each
+power-down/up depending on the device. Some of them might be
+solvable, but some are hard, I'm afraid. Some distros such as
+openSUSE enables the power-saving feature automatically when the power
+cable is unplugged. Thus, if you hear noises, suspect first the
+power-saving. See /sys/module/snd_hda_intel/parameters/power_save to
+check the current value. If it's non-zero, the feature is turned on.
+
+
+Development Tree
+~~~~~~~~~~~~~~~~
+The latest development codes for HD-audio are found on sound git tree:
+
+- git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6.git
+
+The master branch or for-next branches can be used as the main
+development branches in general while the HD-audio specific patches
+are committed in topic/hda branch.
+
+If you are using the latest Linus tree, it'd be better to pull the
+above GIT tree onto it. If you are using the older kernels, an easy
+way to try the latest ALSA code is to build from the snapshot
+tarball. There are daily tarballs and the latest snapshot tarball.
+All can be built just like normal alsa-driver release packages, that
+is, installed via the usual spells: configure, make and make
+install(-modules). See INSTALL in the package. The snapshot tarballs
+are found at:
+
+- ftp://ftp.kernel.org/pub/linux/kernel/people/tiwai/snapshot/
+
+
+Sending a Bug Report
+~~~~~~~~~~~~~~~~~~~~
+If any model or module options don't work for your device, it's time
+to send a bug report to the developers. Give the following in your
+bug report:
+
+- Hardware vendor, product and model names
+- Kernel version (and ALSA-driver version if you built externally)
+- `alsa-info.sh` output; run with `--no-upload` option. See the
+ section below about alsa-info
+
+If it's a regression, at best, send alsa-info outputs of both working
+and non-working kernels. This is really helpful because we can
+compare the codec registers directly.
+
+Send a bug report either the followings:
+
+kernel-bugzilla::
+ http://bugme.linux-foundation.org/
+alsa-devel ML::
+ alsa-devel@alsa-project.org
+
+
+DEBUG TOOLS
+-----------
+
+This section describes some tools available for debugging HD-audio
+problems.
+
+alsa-info
+~~~~~~~~~
+The script `alsa-info.sh` is a very useful tool to gather the audio
+device information. You can fetch the latest version from:
+
+- http://www.alsa-project.org/alsa-info.sh
+
+Run this script as root, and it will gather the important information
+such as the module lists, module parameters, proc file contents
+including the codec proc files, mixer outputs and the control
+elements. As default, it will store the information onto a web server
+on alsa-project.org. But, if you send a bug report, it'd be better to
+run with `--no-upload` option, and attach the generated file.
+
+There are some other useful options. See `--help` option output for
+details.
+
+
+hda-verb
+~~~~~~~~
+hda-verb is a tiny program that allows you to access the HD-audio
+codec directly. You can execute a raw HD-audio codec verb with this.
+This program accesses the hwdep device, thus you need to enable the
+kernel config `CONFIG_SND_HDA_HWDEP=y` beforehand.
+
+The hda-verb program takes four arguments: the hwdep device file, the
+widget NID, the verb and the parameter. When you access to the codec
+on the slot 2 of the card 0, pass /dev/snd/hwC0D2 to the first
+argument, typically. (However, the real path name depends on the
+system.)
+
+The second parameter is the widget number-id to access. The third
+parameter can be either a hex/digit number or a string corresponding
+to a verb. Similarly, the last parameter is the value to write, or
+can be a string for the parameter type.
+
+------------------------------------------------------------------------
+ % hda-verb /dev/snd/hwC0D0 0x12 0x701 2
+ nid = 0x12, verb = 0x701, param = 0x2
+ value = 0x0
+
+ % hda-verb /dev/snd/hwC0D0 0x0 PARAMETERS VENDOR_ID
+ nid = 0x0, verb = 0xf00, param = 0x0
+ value = 0x10ec0262
+
+ % hda-verb /dev/snd/hwC0D0 2 set_a 0xb080
+ nid = 0x2, verb = 0x300, param = 0xb080
+ value = 0x0
+------------------------------------------------------------------------
+
+Although you can issue any verbs with this program, the driver state
+won't be always updated. For example, the volume values are usually
+cached in the driver, and thus changing the widget amp value directly
+via hda-verb won't change the mixer value.
+
+The hda-verb program is found in the ftp directory:
+
+- ftp://ftp.kernel.org/pub/linux/kernel/people/tiwai/misc/
+
+Also a git repository is available:
+
+- git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/hda-verb.git
+
+See README file in the tarball for more details about hda-verb
+program.
+
+
+hda-analyzer
+~~~~~~~~~~~~
+hda-analyzer provides a graphical interface to access the raw HD-audio
+control, based on pyGTK2 binding. It's a more powerful version of
+hda-verb. The program gives you an easy-to-use GUI stuff for showing
+the widget information and adjusting the amp values, as well as the
+proc-compatible output.
+
+The hda-analyzer is a part of alsa.git repository in
+alsa-project.org:
+
+- http://git.alsa-project.org/?p=alsa.git;a=tree;f=hda-analyzer
+
+
+Codecgraph
+~~~~~~~~~~
+Codecgraph is a utility program to generate a graph and visualizes the
+codec-node connection of a codec chip. It's especially useful when
+you analyze or debug a codec without a proper datasheet. The program
+parses the given codec proc file and converts to SVG via graphiz
+program.
+
+The tarball and GIT trees are found in the web page at:
+
+- http://helllabs.org/codecgraph/
+
+
+hda-emu
+~~~~~~~
+hda-emu is an HD-audio emulator. The main purpose of this program is
+to debug an HD-audio codec without the real hardware. Thus, it
+doesn't emulate the behavior with the real audio I/O, but it just
+dumps the codec register changes and the ALSA-driver internal changes
+at probing and operating the HD-audio driver.
+
+The program requires a codec proc-file to simulate. Get a proc file
+for the target codec beforehand, or pick up an example codec from the
+codec proc collections in the tarball. Then, run the program with the
+proc file, and the hda-emu program will start parsing the codec file
+and simulates the HD-audio driver:
+
+------------------------------------------------------------------------
+ % hda-emu codecs/stac9200-dell-d820-laptop
+ # Parsing..
+ hda_codec: Unknown model for STAC9200, using BIOS defaults
+ hda_codec: pin nid 08 bios pin config 40c003fa
+ ....
+------------------------------------------------------------------------
+
+The program gives you only a very dumb command-line interface. You
+can get a proc-file dump at the current state, get a list of control
+(mixer) elements, set/get the control element value, simulate the PCM
+operation, the jack plugging simulation, etc.
+
+The package is found in:
+
+- ftp://ftp.kernel.org/pub/linux/kernel/people/tiwai/misc/
+
+A git repository is available:
+
+- git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/hda-emu.git
+
+See README file in the tarball for more details about hda-emu
+program.
diff --git a/Documentation/sound/alsa/Procfile.txt b/Documentation/sound/alsa/Procfile.txt
index f738b296440..bba2dbb79d8 100644
--- a/Documentation/sound/alsa/Procfile.txt
+++ b/Documentation/sound/alsa/Procfile.txt
@@ -153,6 +153,16 @@ card*/codec#*
Shows the general codec information and the attribute of each
widget node.
+card*/eld#*
+ Available for HDMI or DisplayPort interfaces.
+ Shows ELD(EDID Like Data) info retrieved from the attached HDMI sink,
+ and describes its audio capabilities and configurations.
+
+ Some ELD fields may be modified by doing `echo name hex_value > eld#*`.
+ Only do this if you are sure the HDMI sink provided value is wrong.
+ And if that makes your HDMI audio work, please report to us so that we
+ can fix it in future kernel releases.
+
Sequencer Information
---------------------
diff --git a/Documentation/sound/alsa/soc/machine.txt b/Documentation/sound/alsa/soc/machine.txt
index f370e7db86a..bab7711ce96 100644
--- a/Documentation/sound/alsa/soc/machine.txt
+++ b/Documentation/sound/alsa/soc/machine.txt
@@ -9,7 +9,7 @@ the audio subsystem with the kernel as a platform device and is represented by
the following struct:-
/* SoC machine */
-struct snd_soc_machine {
+struct snd_soc_card {
char *name;
int (*probe)(struct platform_device *pdev);
@@ -67,10 +67,10 @@ static struct snd_soc_dai_link corgi_dai = {
.ops = &corgi_ops,
};
-struct snd_soc_machine then sets up the machine with it's DAIs. e.g.
+struct snd_soc_card then sets up the machine with it's DAIs. e.g.
/* corgi audio machine driver */
-static struct snd_soc_machine snd_soc_machine_corgi = {
+static struct snd_soc_card snd_soc_corgi = {
.name = "Corgi",
.dai_link = &corgi_dai,
.num_links = 1,
@@ -90,7 +90,7 @@ static struct wm8731_setup_data corgi_wm8731_setup = {
/* corgi audio subsystem */
static struct snd_soc_device corgi_snd_devdata = {
- .machine = &snd_soc_machine_corgi,
+ .machine = &snd_soc_corgi,
.platform = &pxa2xx_soc_platform,
.codec_dev = &soc_codec_dev_wm8731,
.codec_data = &corgi_wm8731_setup,
diff --git a/Documentation/spi/spi-summary b/Documentation/spi/spi-summary
index 8bae2f018d3..0f5122eb282 100644
--- a/Documentation/spi/spi-summary
+++ b/Documentation/spi/spi-summary
@@ -215,7 +215,7 @@ So for example arch/.../mach-*/board-*.c files might have code like:
/* if your mach-* infrastructure doesn't support kernels that can
* run on multiple boards, pdata wouldn't benefit from "__init".
*/
- static struct mysoc_spi_data __init pdata = { ... };
+ static struct mysoc_spi_data __initdata pdata = { ... };
static __init board_init(void)
{
diff --git a/Documentation/tracers/mmiotrace.txt b/Documentation/tracers/mmiotrace.txt
index 5bbbe209622..cde23b4a12a 100644
--- a/Documentation/tracers/mmiotrace.txt
+++ b/Documentation/tracers/mmiotrace.txt
@@ -37,7 +37,7 @@ $ echo mmiotrace > /debug/tracing/current_tracer
$ cat /debug/tracing/trace_pipe > mydump.txt &
Start X or whatever.
$ echo "X is up" > /debug/tracing/trace_marker
-$ echo none > /debug/tracing/current_tracer
+$ echo nop > /debug/tracing/current_tracer
Check for lost events.
@@ -66,7 +66,7 @@ which action. It is recommended to place descriptive markers about what you
do.
Shut down mmiotrace (requires root privileges):
-$ echo none > /debug/tracing/current_tracer
+$ echo nop > /debug/tracing/current_tracer
The 'cat' process exits. If it does not, kill it by issuing 'fg' command and
pressing ctrl+c.
@@ -81,7 +81,9 @@ are:
$ cat /debug/tracing/trace_entries
gives you a number. Approximately double this number and write it back, for
instance:
+$ echo 0 > /debug/tracing/tracing_enabled
$ echo 128000 > /debug/tracing/trace_entries
+$ echo 1 > /debug/tracing/tracing_enabled
Then start again from the top.
If you are doing a trace for a driver project, e.g. Nouveau, you should also
diff --git a/Documentation/usb/gadget_serial.txt b/Documentation/usb/gadget_serial.txt
index 9b22bd14c34..eac7df94d8e 100644
--- a/Documentation/usb/gadget_serial.txt
+++ b/Documentation/usb/gadget_serial.txt
@@ -114,11 +114,11 @@ modules.
Then you must load the gadget serial driver. To load it as an
ACM device (recommended for interoperability), do this:
- modprobe g_serial use_acm=1
+ modprobe g_serial
To load it as a vendor specific bulk in/out device, do this:
- modprobe g_serial
+ modprobe g_serial use_acm=0
This will also automatically load the underlying gadget peripheral
controller driver. This must be done each time you reboot the gadget
diff --git a/Documentation/usb/proc_usb_info.txt b/Documentation/usb/proc_usb_info.txt
index 077e9032d0c..fafcd472326 100644
--- a/Documentation/usb/proc_usb_info.txt
+++ b/Documentation/usb/proc_usb_info.txt
@@ -49,8 +49,10 @@ it and 002/048 sometime later.
These files can be read as binary data. The binary data consists
of first the device descriptor, then the descriptors for each
-configuration of the device. That information is also shown in
-text form by the /proc/bus/usb/devices file, described later.
+configuration of the device. Multi-byte fields in the device and
+configuration descriptors, but not other descriptors, are converted
+to host endianness by the kernel. This information is also shown
+in text form by the /proc/bus/usb/devices file, described later.
These files may also be used to write user-level drivers for the USB
devices. You would open the /proc/bus/usb/BBB/DDD file read/write,
diff --git a/Documentation/usb/usbmon.txt b/Documentation/usb/usbmon.txt
index 2917ce4ffdc..270481906dc 100644
--- a/Documentation/usb/usbmon.txt
+++ b/Documentation/usb/usbmon.txt
@@ -34,11 +34,12 @@ if usbmon is built into the kernel.
Verify that bus sockets are present.
# ls /sys/kernel/debug/usbmon
-0s 0t 0u 1s 1t 1u 2s 2t 2u 3s 3t 3u 4s 4t 4u
+0s 0u 1s 1t 1u 2s 2t 2u 3s 3t 3u 4s 4t 4u
#
-Now you can choose to either use the sockets numbered '0' (to capture packets on
-all buses), and skip to step #3, or find the bus used by your device with step #2.
+Now you can choose to either use the socket '0u' (to capture packets on all
+buses), and skip to step #3, or find the bus used by your device with step #2.
+This allows to filter away annoying devices that talk continuously.
2. Find which bus connects to the desired device
@@ -99,8 +100,9 @@ on the event type, but there is a set of words, common for all types.
Here is the list of words, from left to right:
-- URB Tag. This is used to identify URBs is normally a kernel mode address
- of the URB structure in hexadecimal.
+- URB Tag. This is used to identify URBs, and is normally an in-kernel address
+ of the URB structure in hexadecimal, but can be a sequence number or any
+ other unique string, within reason.
- Timestamp in microseconds, a decimal number. The timestamp's resolution
depends on available clock, and so it can be much worse than a microsecond
diff --git a/Documentation/w1/masters/omap-hdq b/Documentation/w1/masters/omap-hdq
new file mode 100644
index 00000000000..ca722e09b6a
--- /dev/null
+++ b/Documentation/w1/masters/omap-hdq
@@ -0,0 +1,46 @@
+Kernel driver for omap HDQ/1-wire module.
+========================================
+
+Supported chips:
+================
+ HDQ/1-wire controller on the TI OMAP 2430/3430 platforms.
+
+A useful link about HDQ basics:
+===============================
+http://focus.ti.com/lit/an/slua408/slua408.pdf
+
+Description:
+============
+The HDQ/1-Wire module of TI OMAP2430/3430 platforms implement the hardware
+protocol of the master functions of the Benchmark HDQ and the Dallas
+Semiconductor 1-Wire protocols. These protocols use a single wire for
+communication between the master (HDQ/1-Wire controller) and the slave
+(HDQ/1-Wire external compliant device).
+
+A typical application of the HDQ/1-Wire module is the communication with battery
+monitor (gas gauge) integrated circuits.
+
+The controller supports operation in both HDQ and 1-wire mode. The essential
+difference between the HDQ and 1-wire mode is how the slave device responds to
+initialization pulse.In HDQ mode, the firmware does not require the host to
+create an initialization pulse to the slave.However, the slave can be reset by
+using an initialization pulse (also referred to as a break pulse).The slave
+does not respond with a presence pulse as it does in the 1-Wire protocol.
+
+Remarks:
+========
+The driver (drivers/w1/masters/omap_hdq.c) supports the HDQ mode of the
+controller. In this mode, as we can not read the ID which obeys the W1
+spec(family:id:crc), a module parameter can be passed to the driver which will
+be used to calculate the CRC and pass back an appropriate slave ID to the W1
+core.
+
+By default the master driver and the BQ slave i/f
+driver(drivers/w1/slaves/w1_bq27000.c) sets the ID to 1.
+Please note to load both the modules with a different ID if required, but note
+that the ID used should be same for both master and slave driver loading.
+
+e.g:
+insmod omap_hdq.ko W1_ID=2
+inamod w1_bq27000.ko F_ID=2
+
diff --git a/MAINTAINERS b/MAINTAINERS
index 53e78c83cc7..70102570151 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -779,6 +779,7 @@ ATM
P: Chas Williams
M: chas@cmf.nrl.navy.mil
L: linux-atm-general@lists.sourceforge.net (subscribers-only)
+L: netdev@vger.kernel.org
W: http://linux-atm.sourceforge.net
S: Maintained
@@ -1526,10 +1527,10 @@ W: http://ebtables.sourceforge.net/
S: Maintained
ECRYPT FILE SYSTEM
-P: Mike Halcrow, Phillip Hellewell
-M: mhalcrow@us.ibm.com, phillip@hellewell.homeip.net
-L: ecryptfs-devel@lists.sourceforge.net
-W: http://ecryptfs.sourceforge.net/
+P: Tyler Hicks, Dustin Kirkland
+M: tyhicks@linux.vnet.ibm.com, kirkland@canonical.com
+L: ecryptfs-devel@lists.launchpad.net
+W: https://launchpad.net/ecryptfs
S: Supported
EDAC-CORE
@@ -1809,7 +1810,7 @@ S: Maintained
FTRACE
P: Steven Rostedt
-M: srostedt@redhat.com
+M: rostedt@goodmis.org
S: Maintained
FUJITSU FR-V (FRV) PORT
@@ -2190,9 +2191,9 @@ S: Supported
INOTIFY
P: John McCutchan
-M: ttb@tentacle.dhs.org
+M: john@johnmccutchan.com
P: Robert Love
-M: rml@novell.com
+M: rlove@rlove.org
L: linux-kernel@vger.kernel.org
S: Maintained
@@ -2216,6 +2217,13 @@ M: adaplas@gmail.com
L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers)
S: Maintained
+INTEL MENLOW THERMAL DRIVER
+P: Sujith Thomas
+M: sujith.thomas@intel.com
+L: linux-acpi@vger.kernel.org
+W: http://www.lesswatts.org/projects/acpi/
+S: Supported
+
INTEL IA32 MICROCODE UPDATE SUPPORT
P: Tigran Aivazian
M: tigran@aivazian.fsnet.co.uk
@@ -2696,6 +2704,11 @@ P: Arnaldo Carvalho de Melo
M: acme@ghostprotocols.net
S: Maintained
+LIS3LV02D ACCELEROMETER DRIVER
+P: Eric Piel
+M: eric.piel@tremplin-utc.net
+S: Maintained
+
LM83 HARDWARE MONITOR DRIVER
P: Jean Delvare
M: khali@linux-fr.org
@@ -3377,7 +3390,9 @@ S: Maintained
PNP SUPPORT
P: Adam Belay
-M: ambx1@neo.rr.com
+M: abelay@mit.edu
+P: Bjorn Helgaas
+M: bjorn.helgaas@hp.com
S: Maintained
PNXxxxx I2C DRIVER
@@ -3744,6 +3759,15 @@ M: drzeus-sdhci@drzeus.cx
L: sdhci-devel@list.drzeus.cx
S: Maintained
+SECURITY SUBSYSTEM
+F: security/
+P: James Morris
+M: jmorris@namei.org
+L: linux-kernel@vger.kernel.org
+L: linux-security-module@vger.kernel.org (suggested Cc:)
+T: git kernel.org:pub/scm/linux/kernel/git/jmorris/security-testing-2.6.git
+S: Supported
+
SECURITY CONTACT
P: Security Officers
M: security@kernel.org
@@ -3914,8 +3938,6 @@ M: bootc@bootc.net
S: Maintained
SOFTWARE RAID (Multiple Disks) SUPPORT
-P: Ingo Molnar
-M: mingo@redhat.com
P: Neil Brown
M: neilb@suse.de
L: linux-raid@vger.kernel.org
@@ -3955,7 +3977,7 @@ M: tiwai@suse.de
L: alsa-devel@alsa-project.org (subscribers-only)
S: Maintained
-SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT
+SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT (ASoC)
P: Liam Girdwood
M: lrg@slimlogic.co.uk
P: Mark Brown
@@ -4223,7 +4245,7 @@ M: dedekind@infradead.org
P: Adrian Hunter
M: ext-adrian.hunter@nokia.com
L: linux-mtd@lists.infradead.org
-T: git git://git.infradead.org/~dedekind/ubifs-2.6.git
+T: git git://git.infradead.org/ubifs-2.6.git
W: http://www.linux-mtd.infradead.org/doc/ubifs.html
S: Maintained
@@ -4277,7 +4299,7 @@ P: Artem Bityutskiy
M: dedekind@infradead.org
W: http://www.linux-mtd.infradead.org/
L: linux-mtd@lists.infradead.org
-T: git git://git.infradead.org/~dedekind/ubi-2.6.git
+T: git git://git.infradead.org/ubi-2.6.git
S: Maintained
USB ACM DRIVER
@@ -4507,7 +4529,7 @@ S: Maintained
USB VIDEO CLASS
P: Laurent Pinchart
M: laurent.pinchart@skynet.be
-L: linux-uvc-devel@lists.berlios.de
+L: linux-uvc-devel@lists.berlios.de (subscribers-only)
L: video4linux-list@redhat.com
W: http://linux-uvc.berlios.de
S: Maintained
diff --git a/Makefile b/Makefile
index 7f9ff9bf154..71e98e9e6ac 100644
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 28
-EXTRAVERSION = -rc4
-NAME = Killer Bat of Doom
+EXTRAVERSION =
+NAME = Erotic Pickled Herring
# *DOCUMENTATION*
# To see a list of typical targets execute "make help"
diff --git a/arch/Kconfig b/arch/Kconfig
index 8977d99987c..471e72dbaf8 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -79,8 +79,6 @@ config HAVE_KRETPROBES
# task_pt_regs() in asm/processor.h or asm/ptrace.h
# arch_has_single_step() if there is hardware single-step support
# arch_has_block_step() if there is hardware block-step support
-# arch_ptrace() and not #define __ARCH_SYS_PTRACE
-# compat_arch_ptrace() and #define __ARCH_WANT_COMPAT_SYS_PTRACE
# asm/syscall.h supplying asm-generic/syscall.h interface
# linux/regset.h user_regset interfaces
# CORE_DUMP_USE_REGSET #define'd in linux/elf.h
diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c
index 5cf45fc5134..ff8cb638472 100644
--- a/arch/alpha/kernel/pci.c
+++ b/arch/alpha/kernel/pci.c
@@ -338,7 +338,7 @@ common_swizzle(struct pci_dev *dev, u8 *pinp)
return PCI_SLOT(dev->devfn);
}
-void __devinit
+void
pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
struct resource *res)
{
diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c
index e657c45d91d..cf7da10097b 100644
--- a/arch/alpha/kernel/smp.c
+++ b/arch/alpha/kernel/smp.c
@@ -121,7 +121,7 @@ wait_boot_cpu_to_stop(int cpuid)
/*
* Where secondaries begin a life of C.
*/
-void __init
+void __cpuinit
smp_callin(void)
{
int cpuid = hard_smp_processor_id();
@@ -198,7 +198,7 @@ wait_for_txrdy (unsigned long cpumask)
* Send a message to a secondary's console. "START" is one such
* interesting message. ;-)
*/
-static void __init
+static void __cpuinit
send_secondary_console_msg(char *str, int cpuid)
{
struct percpu_struct *cpu;
@@ -289,7 +289,7 @@ recv_secondary_console_msg(void)
/*
* Convince the console to have a secondary cpu begin execution.
*/
-static int __init
+static int __cpuinit
secondary_cpu_start(int cpuid, struct task_struct *idle)
{
struct percpu_struct *cpu;
diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c
index c778779007f..cefc5a355ef 100644
--- a/arch/alpha/kernel/traps.c
+++ b/arch/alpha/kernel/traps.c
@@ -31,7 +31,7 @@
static int opDEC_fix;
-static void __init
+static void __cpuinit
opDEC_check(void)
{
__asm__ __volatile__ (
@@ -1072,7 +1072,7 @@ give_sigbus:
return;
}
-void __init
+void __cpuinit
trap_init(void)
{
/* Tell PAL-code what global pointer we want in the kernel. */
diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c
index 47ccec95f3e..ef12794c3c6 100644
--- a/arch/arm/common/sa1111.c
+++ b/arch/arm/common/sa1111.c
@@ -630,7 +630,7 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq)
return -ENOMEM;
sachip->clk = clk_get(me, "SA1111_CLK");
- if (!sachip->clk) {
+ if (IS_ERR(sachip->clk)) {
ret = PTR_ERR(sachip->clk);
goto err_free;
}
diff --git a/arch/arm/configs/corgi_defconfig b/arch/arm/configs/corgi_defconfig
index f3af0b593eb..98765438048 100644
--- a/arch/arm/configs/corgi_defconfig
+++ b/arch/arm/configs/corgi_defconfig
@@ -179,7 +179,7 @@ CONFIG_MACH_HUSKY=y
# CONFIG_MACH_AKITA is not set
# CONFIG_MACH_SPITZ is not set
# CONFIG_MACH_BORZOI is not set
-CONFIG_MACH_TOSA=y
+# CONFIG_MACH_TOSA is not set
# CONFIG_ARCH_VIPER is not set
# CONFIG_ARCH_PXA_ESERIES is not set
# CONFIG_TRIZEPS_PXA is not set
diff --git a/arch/arm/include/asm/bitops.h b/arch/arm/include/asm/bitops.h
index 9a1db20e032..63a481fbbed 100644
--- a/arch/arm/include/asm/bitops.h
+++ b/arch/arm/include/asm/bitops.h
@@ -237,6 +237,7 @@ extern int _find_next_bit_be(const unsigned long *p, int size, int offset);
#if __LINUX_ARM_ARCH__ < 5
#include <asm-generic/bitops/ffz.h>
+#include <asm-generic/bitops/__fls.h>
#include <asm-generic/bitops/__ffs.h>
#include <asm-generic/bitops/fls.h>
#include <asm-generic/bitops/ffs.h>
@@ -277,16 +278,19 @@ static inline int constant_fls(int x)
* the clz instruction for much better code efficiency.
*/
-#define __fls(x) \
- ( __builtin_constant_p(x) ? constant_fls(x) : \
- ({ int __r; asm("clz\t%0, %1" : "=r"(__r) : "r"(x) : "cc"); 32-__r; }) )
-
-/* Implement fls() in C so that 64-bit args are suitably truncated */
static inline int fls(int x)
{
- return __fls(x);
+ int ret;
+
+ if (__builtin_constant_p(x))
+ return constant_fls(x);
+
+ asm("clz\t%0, %1" : "=r" (ret) : "r" (x) : "cc");
+ ret = 32 - ret;
+ return ret;
}
+#define __fls(x) (fls(x) - 1)
#define ffs(x) ({ unsigned long __t = (x); fls(__t & -__t); })
#define __ffs(x) (ffs(x) - 1)
#define ffz(x) __ffs( ~(x) )
diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h
index 1cb8602dd9d..4ed149cbb32 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -256,8 +256,17 @@ int dmabounce_sync_for_cpu(struct device *, dma_addr_t, unsigned long,
int dmabounce_sync_for_device(struct device *, dma_addr_t, unsigned long,
size_t, enum dma_data_direction);
#else
-#define dmabounce_sync_for_cpu(dev,dma,off,sz,dir) (1)
-#define dmabounce_sync_for_device(dev,dma,off,sz,dir) (1)
+static inline int dmabounce_sync_for_cpu(struct device *d, dma_addr_t addr,
+ unsigned long offset, size_t size, enum dma_data_direction dir)
+{
+ return 1;
+}
+
+static inline int dmabounce_sync_for_device(struct device *d, dma_addr_t addr,
+ unsigned long offset, size_t size, enum dma_data_direction dir)
+{
+ return 1;
+}
/**
diff --git a/arch/arm/include/asm/hardware/iop3xx-adma.h b/arch/arm/include/asm/hardware/iop3xx-adma.h
index 87bff09633a..83e6ba338e2 100644
--- a/arch/arm/include/asm/hardware/iop3xx-adma.h
+++ b/arch/arm/include/asm/hardware/iop3xx-adma.h
@@ -730,7 +730,8 @@ static inline void iop_desc_set_next_desc(struct iop_adma_desc_slot *desc,
{
/* hw_desc->next_desc is the same location for all channels */
union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
- BUG_ON(hw_desc.dma->next_desc);
+
+ iop_paranoia(hw_desc.dma->next_desc);
hw_desc.dma->next_desc = next_desc_addr;
}
@@ -760,7 +761,7 @@ static inline int iop_desc_get_zero_result(struct iop_adma_desc_slot *desc)
struct iop3xx_desc_aau *hw_desc = desc->hw_desc;
struct iop3xx_aau_desc_ctrl desc_ctrl = hw_desc->desc_ctrl_field;
- BUG_ON(!(desc_ctrl.tx_complete && desc_ctrl.zero_result_en));
+ iop_paranoia(!(desc_ctrl.tx_complete && desc_ctrl.zero_result_en));
return desc_ctrl.zero_result_err;
}
diff --git a/arch/arm/include/asm/hardware/iop_adma.h b/arch/arm/include/asm/hardware/iop_adma.h
index cb7e3611bcb..385c6e8cbbd 100644
--- a/arch/arm/include/asm/hardware/iop_adma.h
+++ b/arch/arm/include/asm/hardware/iop_adma.h
@@ -23,6 +23,12 @@
#define IOP_ADMA_SLOT_SIZE 32
#define IOP_ADMA_THRESHOLD 4
+#ifdef DEBUG
+#define IOP_PARANOIA 1
+#else
+#define IOP_PARANOIA 0
+#endif
+#define iop_paranoia(x) BUG_ON(IOP_PARANOIA && (x))
/**
* struct iop_adma_device - internal representation of an ADMA device
diff --git a/arch/arm/include/asm/mach/map.h b/arch/arm/include/asm/mach/map.h
index cb1139ac194..39d949b63e8 100644
--- a/arch/arm/include/asm/mach/map.h
+++ b/arch/arm/include/asm/mach/map.h
@@ -19,12 +19,13 @@ struct map_desc {
};
/* types 0-3 are defined in asm/io.h */
-#define MT_CACHECLEAN 4
-#define MT_MINICLEAN 5
-#define MT_LOW_VECTORS 6
-#define MT_HIGH_VECTORS 7
-#define MT_MEMORY 8
-#define MT_ROM 9
+#define MT_UNCACHED 4
+#define MT_CACHECLEAN 5
+#define MT_MINICLEAN 6
+#define MT_LOW_VECTORS 7
+#define MT_HIGH_VECTORS 8
+#define MT_MEMORY 9
+#define MT_ROM 10
#ifdef CONFIG_MMU
extern void iotable_init(struct map_desc *, int);
diff --git a/arch/arm/include/asm/processor.h b/arch/arm/include/asm/processor.h
index 517a4d6ffc7..6ff33790f47 100644
--- a/arch/arm/include/asm/processor.h
+++ b/arch/arm/include/asm/processor.h
@@ -23,7 +23,7 @@
#include <asm/types.h>
#ifdef __KERNEL__
-#define STACK_TOP ((current->personality == PER_LINUX_32BIT) ? \
+#define STACK_TOP ((current->personality & ADDR_LIMIT_32BIT) ? \
TASK_SIZE : TASK_SIZE_26)
#define STACK_TOP_MAX TASK_SIZE
#endif
diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c
index c74f766ffc1..23af3c972c9 100644
--- a/arch/arm/kernel/armksyms.c
+++ b/arch/arm/kernel/armksyms.c
@@ -115,6 +115,8 @@ EXPORT_SYMBOL(__strnlen_user);
EXPORT_SYMBOL(__strncpy_from_user);
#ifdef CONFIG_MMU
+EXPORT_SYMBOL(copy_page);
+
EXPORT_SYMBOL(__copy_from_user);
EXPORT_SYMBOL(__copy_to_user);
EXPORT_SYMBOL(__clear_user);
@@ -181,8 +183,6 @@ EXPORT_SYMBOL(_find_first_bit_be);
EXPORT_SYMBOL(_find_next_bit_be);
#endif
-EXPORT_SYMBOL(copy_page);
-
#ifdef CONFIG_FUNCTION_TRACER
EXPORT_SYMBOL(mcount);
#endif
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 57e6874d0b8..79abc4ddc0c 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -18,6 +18,7 @@
#include <linux/personality.h>
#include <linux/kallsyms.h>
#include <linux/delay.h>
+#include <linux/hardirq.h>
#include <linux/init.h>
#include <linux/uaccess.h>
diff --git a/arch/arm/mach-clps711x/include/mach/hardware.h b/arch/arm/mach-clps711x/include/mach/hardware.h
index 4c3e101b96c..b3ebe9e4871 100644
--- a/arch/arm/mach-clps711x/include/mach/hardware.h
+++ b/arch/arm/mach-clps711x/include/mach/hardware.h
@@ -94,20 +94,6 @@
#include <asm/hardware/ep7212.h>
#include <asm/hardware/cs89712.h>
-/* dynamic ioremap() areas */
-#define FLASH_START 0x00000000
-#define FLASH_SIZE 0x800000
-#define FLASH_WIDTH 4
-
-#define SRAM_START 0x60000000
-#define SRAM_SIZE 0xc000
-#define SRAM_WIDTH 4
-
-#define BOOTROM_START 0x70000000
-#define BOOTROM_SIZE 0x80
-#define BOOTROM_WIDTH 4
-
-
/* static cdb89712_map_io() areas */
#define REGISTER_START 0x80000000
#define REGISTER_SIZE 0x4000
@@ -198,14 +184,6 @@
#define CEIVA_FLASH_SIZE 0x100000
#define CEIVA_FLASH_WIDTH 2
-#define SRAM_START 0x60000000
-#define SRAM_SIZE 0xc000
-#define SRAM_WIDTH 4
-
-#define BOOTROM_START 0x70000000
-#define BOOTROM_SIZE 0x80
-#define BOOTROM_WIDTH 4
-
/*
* SED1355 LCD controller
*/
diff --git a/arch/arm/mach-clps7500/core.c b/arch/arm/mach-clps7500/core.c
index c3a33b8a5aa..7e247c04d41 100644
--- a/arch/arm/mach-clps7500/core.c
+++ b/arch/arm/mach-clps7500/core.c
@@ -275,9 +275,9 @@ static struct map_desc cl7500_io_desc[] __initdata = {
.length = ISA_SIZE,
.type = MT_DEVICE
}, { /* Flash */
- .virtual = FLASH_BASE,
- .pfn = __phys_to_pfn(FLASH_START),
- .length = FLASH_SIZE,
+ .virtual = CLPS7500_FLASH_BASE,
+ .pfn = __phys_to_pfn(CLPS7500_FLASH_START),
+ .length = CLPS7500_FLASH_SIZE,
.type = MT_DEVICE
}, { /* LED */
.virtual = LED_BASE,
diff --git a/arch/arm/mach-clps7500/include/mach/hardware.h b/arch/arm/mach-clps7500/include/mach/hardware.h
index d66578a3371..a6ad1d44bad 100644
--- a/arch/arm/mach-clps7500/include/mach/hardware.h
+++ b/arch/arm/mach-clps7500/include/mach/hardware.h
@@ -39,9 +39,9 @@
#define ISA_SIZE 0x00010000
#define ISA_BASE 0xe1000000
-#define FLASH_START 0x01000000 /* XXX */
-#define FLASH_SIZE 0x01000000
-#define FLASH_BASE 0xe2000000
+#define CLPS7500_FLASH_START 0x01000000 /* XXX */
+#define CLPS7500_FLASH_SIZE 0x01000000
+#define CLPS7500_FLASH_BASE 0xe2000000
#define LED_START 0x0302B000
#define LED_SIZE 0x00001000
diff --git a/arch/arm/mach-h720x/include/mach/boards.h b/arch/arm/mach-h720x/include/mach/boards.h
index 079b279e124..38b8e0d61fb 100644
--- a/arch/arm/mach-h720x/include/mach/boards.h
+++ b/arch/arm/mach-h720x/include/mach/boards.h
@@ -19,9 +19,9 @@
#ifdef CONFIG_ARCH_H7202
/* FLASH */
-#define FLASH_VIRT 0xd0000000
-#define FLASH_PHYS 0x00000000
-#define FLASH_SIZE 0x02000000
+#define H720X_FLASH_VIRT 0xd0000000
+#define H720X_FLASH_PHYS 0x00000000
+#define H720X_FLASH_SIZE 0x02000000
/* onboard LAN controller */
# define ETH0_PHYS 0x08000000
diff --git a/arch/arm/mach-integrator/include/mach/platform.h b/arch/arm/mach-integrator/include/mach/platform.h
index 028b87839c0..e00a2624f26 100644
--- a/arch/arm/mach-integrator/include/mach/platform.h
+++ b/arch/arm/mach-integrator/include/mach/platform.h
@@ -408,27 +408,10 @@
#define uHAL_MEMORY_SIZE INTEGRATOR_SSRAM_SIZE
/*
- * Application Flash
- *
- */
-#define FLASH_BASE INTEGRATOR_FLASH_BASE
-#define FLASH_SIZE INTEGRATOR_FLASH_SIZE
-#define FLASH_END (FLASH_BASE + FLASH_SIZE - 1)
-#define FLASH_BLOCK_SIZE SZ_128K
-
-/*
- * Boot Flash
- *
- */
-#define EPROM_BASE INTEGRATOR_BOOT_ROM_HI
-#define EPROM_SIZE INTEGRATOR_BOOT_ROM_SIZE
-#define EPROM_END (EPROM_BASE + EPROM_SIZE - 1)
-
-/*
* Clean base - dummy
*
*/
-#define CLEAN_BASE EPROM_BASE
+#define CLEAN_BASE INTEGRATOR_BOOT_ROM_HI
/*
* Timer definitions
diff --git a/arch/arm/mach-iop13xx/include/mach/adma.h b/arch/arm/mach-iop13xx/include/mach/adma.h
index 60019c8e646..5722e86f217 100644
--- a/arch/arm/mach-iop13xx/include/mach/adma.h
+++ b/arch/arm/mach-iop13xx/include/mach/adma.h
@@ -404,7 +404,8 @@ static inline void iop_desc_set_next_desc(struct iop_adma_desc_slot *desc,
u32 next_desc_addr)
{
struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
- BUG_ON(hw_desc->next_desc);
+
+ iop_paranoia(hw_desc->next_desc);
hw_desc->next_desc = next_desc_addr;
}
diff --git a/arch/arm/mach-omap1/io.c b/arch/arm/mach-omap1/io.c
index b3bd8ca8511..4c3e582f3d3 100644
--- a/arch/arm/mach-omap1/io.c
+++ b/arch/arm/mach-omap1/io.c
@@ -128,7 +128,7 @@ void __init omap1_map_common_io(void)
* Common low-level hardware init for omap1. This should only get called from
* board specific init.
*/
-void __init omap1_init_common_hw()
+void __init omap1_init_common_hw(void)
{
/* REVISIT: Refer to OMAP5910 Errata, Advisory SYS_1: "Timeout Abort
* on a Posted Write in the TIPB Bridge".
diff --git a/arch/arm/mach-pxa/include/mach/palmasoc.h b/arch/arm/mach-pxa/include/mach/palmasoc.h
new file mode 100644
index 00000000000..6c4b1f7de20
--- /dev/null
+++ b/arch/arm/mach-pxa/include/mach/palmasoc.h
@@ -0,0 +1,13 @@
+#ifndef _INCLUDE_PALMASOC_H_
+#define _INCLUDE_PALMASOC_H_
+struct palm27x_asoc_info {
+ int jack_gpio;
+};
+
+#ifdef CONFIG_SND_PXA2XX_SOC_PALM27X
+void __init palm27x_asoc_set_pdata(struct palm27x_asoc_info *data);
+#else
+static inline void palm27x_asoc_set_pdata(struct palm27x_asoc_info *data) {}
+#endif
+
+#endif
diff --git a/arch/arm/mach-pxa/include/mach/pxafb.h b/arch/arm/mach-pxa/include/mach/pxafb.h
index 8e591118371..cbda4d35c42 100644
--- a/arch/arm/mach-pxa/include/mach/pxafb.h
+++ b/arch/arm/mach-pxa/include/mach/pxafb.h
@@ -33,6 +33,7 @@
#define LCD_CONN_TYPE(_x) ((_x) & 0x0f)
#define LCD_CONN_WIDTH(_x) (((_x) >> 4) & 0x1f)
+#define LCD_TYPE_MASK 0xf
#define LCD_TYPE_UNKNOWN 0
#define LCD_TYPE_MONO_STN 1
#define LCD_TYPE_MONO_DSTN 2
diff --git a/arch/arm/mach-pxa/include/mach/reset.h b/arch/arm/mach-pxa/include/mach/reset.h
index 7b8842cfa5f..31e6a7b6ad8 100644
--- a/arch/arm/mach-pxa/include/mach/reset.h
+++ b/arch/arm/mach-pxa/include/mach/reset.h
@@ -12,9 +12,8 @@ extern void clear_reset_status(unsigned int mask);
/**
* init_gpio_reset() - register GPIO as reset generator
- *
- * @gpio - gpio nr
- * @output - set gpio as out/low instead of input during normal work
+ * @gpio: gpio nr
+ * @output: set gpio as out/low instead of input during normal work
*/
extern int init_gpio_reset(int gpio, int output);
diff --git a/arch/arm/mach-pxa/mioa701.c b/arch/arm/mach-pxa/mioa701.c
index 0842c531ee4..782903fe9c6 100644
--- a/arch/arm/mach-pxa/mioa701.c
+++ b/arch/arm/mach-pxa/mioa701.c
@@ -565,7 +565,7 @@ static int mioa701_sys_suspend(struct sys_device *sysdev, pm_message_t state)
u32 *mem_resume_unknown = phys_to_virt(RESUME_UNKNOWN_ADDR);
/* Devices prepare suspend */
- is_bt_on = gpio_get_value(GPIO83_BT_ON);
+ is_bt_on = !!gpio_get_value(GPIO83_BT_ON);
pxa2xx_mfp_set_lpm(GPIO83_BT_ON,
is_bt_on ? MFP_LPM_DRIVE_HIGH : MFP_LPM_DRIVE_LOW);
diff --git a/arch/arm/mach-pxa/mioa701_bootresume.S b/arch/arm/mach-pxa/mioa701_bootresume.S
index a647693d985..324d25a48c8 100644
--- a/arch/arm/mach-pxa/mioa701_bootresume.S
+++ b/arch/arm/mach-pxa/mioa701_bootresume.S
@@ -24,6 +24,7 @@ ENTRY(mioa701_jumpaddr)
1:
mov r0, #0xa0000000 @ Don't suppose memory access works
orr r0, r0, #0x00200000 @ even if it's supposed to
+ orr r0, r0, #0x0000b000
mov r1, #0
str r1, [r0] @ Early disable resume for next boot
ldr r0, mioa701_jumpaddr @ (Murphy's Law)
diff --git a/arch/arm/mach-pxa/palmtx.c b/arch/arm/mach-pxa/palmtx.c
index 4447711c9fc..a9d94f5dbec 100644
--- a/arch/arm/mach-pxa/palmtx.c
+++ b/arch/arm/mach-pxa/palmtx.c
@@ -56,6 +56,9 @@ static unsigned long palmtx_pin_config[] __initdata = {
GPIO110_MMC_DAT_2,
GPIO111_MMC_DAT_3,
GPIO112_MMC_CMD,
+ GPIO14_GPIO, /* SD detect */
+ GPIO114_GPIO, /* SD power */
+ GPIO115_GPIO, /* SD r/o switch */
/* AC97 */
GPIO28_AC97_BITCLK,
@@ -64,6 +67,7 @@ static unsigned long palmtx_pin_config[] __initdata = {
GPIO31_AC97_SYNC,
/* IrDA */
+ GPIO40_GPIO, /* ir disable */
GPIO46_FICP_RXD,
GPIO47_FICP_TXD,
@@ -71,7 +75,8 @@ static unsigned long palmtx_pin_config[] __initdata = {
GPIO16_PWM0_OUT,
/* USB */
- GPIO13_GPIO,
+ GPIO13_GPIO, /* usb detect */
+ GPIO95_GPIO, /* usb power */
/* PCMCIA */
GPIO48_nPOE,
@@ -84,6 +89,45 @@ static unsigned long palmtx_pin_config[] __initdata = {
GPIO55_nPREG,
GPIO56_nPWAIT,
GPIO57_nIOIS16,
+ GPIO94_GPIO, /* wifi power 1 */
+ GPIO108_GPIO, /* wifi power 2 */
+ GPIO116_GPIO, /* wifi ready */
+
+ /* MATRIX KEYPAD */
+ GPIO100_KP_MKIN_0,
+ GPIO101_KP_MKIN_1,
+ GPIO102_KP_MKIN_2,
+ GPIO97_KP_MKIN_3,
+ GPIO103_KP_MKOUT_0,
+ GPIO104_KP_MKOUT_1,
+ GPIO105_KP_MKOUT_2,
+
+ /* LCD */
+ GPIO58_LCD_LDD_0,
+ GPIO59_LCD_LDD_1,
+ GPIO60_LCD_LDD_2,
+ GPIO61_LCD_LDD_3,
+ GPIO62_LCD_LDD_4,
+ GPIO63_LCD_LDD_5,
+ GPIO64_LCD_LDD_6,
+ GPIO65_LCD_LDD_7,
+ GPIO66_LCD_LDD_8,
+ GPIO67_LCD_LDD_9,
+ GPIO68_LCD_LDD_10,
+ GPIO69_LCD_LDD_11,
+ GPIO70_LCD_LDD_12,
+ GPIO71_LCD_LDD_13,
+ GPIO72_LCD_LDD_14,
+ GPIO73_LCD_LDD_15,
+ GPIO74_LCD_FCLK,
+ GPIO75_LCD_LCLK,
+ GPIO76_LCD_PCLK,
+ GPIO77_LCD_BIAS,
+
+ /* MISC. */
+ GPIO10_GPIO, /* hotsync button */
+ GPIO12_GPIO, /* power detect */
+ GPIO107_GPIO, /* earphone detect */
};
/******************************************************************************
@@ -95,32 +139,49 @@ static int palmtx_mci_init(struct device *dev, irq_handler_t palmtx_detect_int,
int err = 0;
/* Setup an interrupt for detecting card insert/remove events */
- err = request_irq(IRQ_GPIO_PALMTX_SD_DETECT_N, palmtx_detect_int,
- IRQF_DISABLED | IRQF_SAMPLE_RANDOM |
+ err = gpio_request(GPIO_NR_PALMTX_SD_DETECT_N, "SD IRQ");
+ if (err)
+ goto err;
+ err = gpio_direction_input(GPIO_NR_PALMTX_SD_DETECT_N);
+ if (err)
+ goto err2;
+ err = request_irq(gpio_to_irq(GPIO_NR_PALMTX_SD_DETECT_N),
+ palmtx_detect_int, IRQF_DISABLED | IRQF_SAMPLE_RANDOM |
IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
"SD/MMC card detect", data);
if (err) {
printk(KERN_ERR "%s: cannot request SD/MMC card detect IRQ\n",
__func__);
- return err;
+ goto err2;
}
err = gpio_request(GPIO_NR_PALMTX_SD_POWER, "SD_POWER");
if (err)
- goto pwr_err;
+ goto err3;
+ err = gpio_direction_output(GPIO_NR_PALMTX_SD_POWER, 0);
+ if (err)
+ goto err4;
err = gpio_request(GPIO_NR_PALMTX_SD_READONLY, "SD_READONLY");
if (err)
- goto ro_err;
+ goto err4;
+ err = gpio_direction_input(GPIO_NR_PALMTX_SD_READONLY);
+ if (err)
+ goto err5;
printk(KERN_DEBUG "%s: irq registered\n", __func__);
return 0;
-ro_err:
+err5:
+ gpio_free(GPIO_NR_PALMTX_SD_READONLY);
+err4:
gpio_free(GPIO_NR_PALMTX_SD_POWER);
-pwr_err:
- free_irq(IRQ_GPIO_PALMTX_SD_DETECT_N, data);
+err3:
+ free_irq(gpio_to_irq(GPIO_NR_PALMTX_SD_DETECT_N), data);
+err2:
+ gpio_free(GPIO_NR_PALMTX_SD_DETECT_N);
+err:
return err;
}
@@ -128,7 +189,8 @@ static void palmtx_mci_exit(struct device *dev, void *data)
{
gpio_free(GPIO_NR_PALMTX_SD_READONLY);
gpio_free(GPIO_NR_PALMTX_SD_POWER);
- free_irq(IRQ_GPIO_PALMTX_SD_DETECT_N, data);
+ free_irq(gpio_to_irq(GPIO_NR_PALMTX_SD_DETECT_N), data);
+ gpio_free(GPIO_NR_PALMTX_SD_DETECT_N);
}
static void palmtx_mci_power(struct device *dev, unsigned int vdd)
@@ -167,7 +229,6 @@ static unsigned int palmtx_matrix_keys[] = {
KEY(3, 0, KEY_RIGHT),
KEY(3, 2, KEY_LEFT),
-
};
static struct pxa27x_keypad_platform_data palmtx_keypad_platform_data = {
@@ -209,11 +270,19 @@ static int palmtx_backlight_init(struct device *dev)
ret = gpio_request(GPIO_NR_PALMTX_BL_POWER, "BL POWER");
if (ret)
goto err;
+ ret = gpio_direction_output(GPIO_NR_PALMTX_BL_POWER, 0);
+ if (ret)
+ goto err2;
ret = gpio_request(GPIO_NR_PALMTX_LCD_POWER, "LCD POWER");
if (ret)
goto err2;
+ ret = gpio_direction_output(GPIO_NR_PALMTX_LCD_POWER, 0);
+ if (ret)
+ goto err3;
return 0;
+err3:
+ gpio_free(GPIO_NR_PALMTX_LCD_POWER);
err2:
gpio_free(GPIO_NR_PALMTX_BL_POWER);
err:
@@ -254,6 +323,24 @@ static struct platform_device palmtx_backlight = {
/******************************************************************************
* IrDA
******************************************************************************/
+static int palmtx_irda_startup(struct device *dev)
+{
+ int err;
+ err = gpio_request(GPIO_NR_PALMTX_IR_DISABLE, "IR DISABLE");
+ if (err)
+ goto err;
+ err = gpio_direction_output(GPIO_NR_PALMTX_IR_DISABLE, 1);
+ if (err)
+ gpio_free(GPIO_NR_PALMTX_IR_DISABLE);
+err:
+ return err;
+}
+
+static void palmtx_irda_shutdown(struct device *dev)
+{
+ gpio_free(GPIO_NR_PALMTX_IR_DISABLE);
+}
+
static void palmtx_irda_transceiver_mode(struct device *dev, int mode)
{
gpio_set_value(GPIO_NR_PALMTX_IR_DISABLE, mode & IR_OFF);
@@ -261,6 +348,8 @@ static void palmtx_irda_transceiver_mode(struct device *dev, int mode)
}
static struct pxaficp_platform_data palmtx_ficp_platform_data = {
+ .startup = palmtx_irda_startup,
+ .shutdown = palmtx_irda_shutdown,
.transceiver_cap = IR_SIRMODE | IR_FIRMODE | IR_OFF,
.transceiver_mode = palmtx_irda_transceiver_mode,
};
@@ -268,17 +357,11 @@ static struct pxaficp_platform_data palmtx_ficp_platform_data = {
/******************************************************************************
* UDC
******************************************************************************/
-static void palmtx_udc_command(int cmd)
-{
- gpio_set_value(GPIO_NR_PALMTX_USB_POWER, !cmd);
- udelay(50);
- gpio_set_value(GPIO_NR_PALMTX_USB_PULLUP, !cmd);
-}
-
static struct pxa2xx_udc_mach_info palmtx_udc_info __initdata = {
.gpio_vbus = GPIO_NR_PALMTX_USB_DETECT_N,
.gpio_vbus_inverted = 1,
- .udc_command = palmtx_udc_command,
+ .gpio_pullup = GPIO_NR_PALMTX_USB_POWER,
+ .gpio_pullup_inverted = 0,
};
/******************************************************************************
@@ -290,17 +373,16 @@ static int power_supply_init(struct device *dev)
ret = gpio_request(GPIO_NR_PALMTX_POWER_DETECT, "CABLE_STATE_AC");
if (ret)
- goto err_cs_ac;
-
- ret = gpio_request(GPIO_NR_PALMTX_USB_DETECT_N, "CABLE_STATE_USB");
+ goto err1;
+ ret = gpio_direction_input(GPIO_NR_PALMTX_POWER_DETECT);
if (ret)
- goto err_cs_usb;
+ goto err2;
return 0;
-err_cs_usb:
+err2:
gpio_free(GPIO_NR_PALMTX_POWER_DETECT);
-err_cs_ac:
+err1:
return ret;
}
@@ -309,14 +391,8 @@ static int palmtx_is_ac_online(void)
return gpio_get_value(GPIO_NR_PALMTX_POWER_DETECT);
}
-static int palmtx_is_usb_online(void)
-{
- return !gpio_get_value(GPIO_NR_PALMTX_USB_DETECT_N);
-}
-
static void power_supply_exit(struct device *dev)
{
- gpio_free(GPIO_NR_PALMTX_USB_DETECT_N);
gpio_free(GPIO_NR_PALMTX_POWER_DETECT);
}
@@ -327,7 +403,6 @@ static char *palmtx_supplicants[] = {
static struct pda_power_pdata power_supply_info = {
.init = power_supply_init,
.is_ac_online = palmtx_is_ac_online,
- .is_usb_online = palmtx_is_usb_online,
.exit = power_supply_exit,
.supplied_to = palmtx_supplicants,
.num_supplicants = ARRAY_SIZE(palmtx_supplicants),
@@ -410,12 +485,23 @@ static void __init palmtx_map_io(void)
iotable_init(palmtx_io_desc, ARRAY_SIZE(palmtx_io_desc));
}
+/* setup udc GPIOs initial state */
+static void __init palmtx_udc_init(void)
+{
+ if (!gpio_request(GPIO_NR_PALMTX_USB_POWER, "UDC Vbus")) {
+ gpio_direction_output(GPIO_NR_PALMTX_USB_POWER, 1);
+ gpio_free(GPIO_NR_PALMTX_USB_POWER);
+ }
+}
+
+
static void __init palmtx_init(void)
{
pxa2xx_mfp_config(ARRAY_AND_SIZE(palmtx_pin_config));
set_pxa_fb_info(&palmtx_lcd_screen);
pxa_set_mci_info(&palmtx_mci_platform_data);
+ palmtx_udc_init();
pxa_set_udc_info(&palmtx_udc_info);
pxa_set_ac97_info(NULL);
pxa_set_ficp_info(&palmtx_ficp_platform_data);
diff --git a/arch/arm/mach-pxa/pcm990-baseboard.c b/arch/arm/mach-pxa/pcm990-baseboard.c
index f601425f1b1..b36cec5c9ee 100644
--- a/arch/arm/mach-pxa/pcm990-baseboard.c
+++ b/arch/arm/mach-pxa/pcm990-baseboard.c
@@ -385,6 +385,7 @@ static struct soc_camera_link iclink[] = {
.gpio = NR_BUILTIN_GPIO + 1,
}, {
.bus_id = 0, /* Must match with the camera ID above */
+ .gpio = -ENXIO,
}
};
diff --git a/arch/arm/mach-pxa/reset.c b/arch/arm/mach-pxa/reset.c
index 1b2af575c40..00b2dc2a107 100644
--- a/arch/arm/mach-pxa/reset.c
+++ b/arch/arm/mach-pxa/reset.c
@@ -90,12 +90,13 @@ void arch_reset(char mode)
/* Jump into ROM at address 0 */
cpu_reset(0);
break;
- case 'h':
- do_hw_reset();
- break;
case 'g':
do_gpio_reset();
break;
+ case 'h':
+ default:
+ do_hw_reset();
+ break;
}
}
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
index f0a5bbae0b4..3be76ee2bdb 100644
--- a/arch/arm/mach-pxa/spitz.c
+++ b/arch/arm/mach-pxa/spitz.c
@@ -67,6 +67,7 @@
static unsigned long spitz_pin_config[] __initdata = {
/* Chip Selects */
GPIO78_nCS_2, /* SCOOP #2 */
+ GPIO79_nCS_3, /* NAND */
GPIO80_nCS_4, /* SCOOP #1 */
/* LCD - 16bpp Active TFT */
@@ -97,10 +98,10 @@ static unsigned long spitz_pin_config[] __initdata = {
GPIO51_nPIOW,
GPIO85_nPCE_1,
GPIO54_nPCE_2,
- GPIO79_PSKTSEL,
GPIO55_nPREG,
GPIO56_nPWAIT,
GPIO57_nIOIS16,
+ GPIO104_PSKTSEL,
/* MMC */
GPIO32_MMC_CLK,
@@ -686,7 +687,6 @@ static void __init akita_init(void)
spitz_pcmcia_config.num_devs = 1;
platform_scoop_config = &spitz_pcmcia_config;
- pxa_set_i2c_info(NULL);
i2c_register_board_info(0, ARRAY_AND_SIZE(akita_i2c_board_info));
common_init();
diff --git a/arch/arm/mach-realview/clock.c b/arch/arm/mach-realview/clock.c
index 3e706c57833..3347c4236a6 100644
--- a/arch/arm/mach-realview/clock.c
+++ b/arch/arm/mach-realview/clock.c
@@ -104,7 +104,7 @@ static struct clk uart_clk = {
static struct clk mmci_clk = {
.name = "MCLK",
- .rate = 33000000,
+ .rate = 24000000,
};
int clk_register(struct clk *clk)
diff --git a/arch/arm/mach-realview/include/mach/platform.h b/arch/arm/mach-realview/include/mach/platform.h
index 4034b54950c..793a3a33271 100644
--- a/arch/arm/mach-realview/include/mach/platform.h
+++ b/arch/arm/mach-realview/include/mach/platform.h
@@ -239,27 +239,10 @@
#define REALVIEW_DECODE_OFFSET 0xC /* Fitted logic modules */
/*
- * Application Flash
- *
- */
-#define FLASH_BASE REALVIEW_FLASH_BASE
-#define FLASH_SIZE REALVIEW_FLASH_SIZE
-#define FLASH_END (FLASH_BASE + FLASH_SIZE - 1)
-#define FLASH_BLOCK_SIZE SZ_128K
-
-/*
- * Boot Flash
- *
- */
-#define EPROM_BASE REALVIEW_BOOT_ROM_HI
-#define EPROM_SIZE REALVIEW_BOOT_ROM_SIZE
-#define EPROM_END (EPROM_BASE + EPROM_SIZE - 1)
-
-/*
* Clean base - dummy
*
*/
-#define CLEAN_BASE EPROM_BASE
+#define CLEAN_BASE REALVIEW_BOOT_ROM_HI
/*
* System controller bit assignment
diff --git a/arch/arm/mach-s3c2410/include/mach/spi-gpio.h b/arch/arm/mach-s3c2410/include/mach/spi-gpio.h
index 3fe8be9ca11..980a099e209 100644
--- a/arch/arm/mach-s3c2410/include/mach/spi-gpio.h
+++ b/arch/arm/mach-s3c2410/include/mach/spi-gpio.h
@@ -18,6 +18,7 @@ struct s3c2410_spigpio_info {
unsigned long pin_mosi;
unsigned long pin_miso;
+ int num_chipselect;
int bus_num;
void (*chip_select)(struct s3c2410_spigpio_info *spi, int cs);
diff --git a/arch/arm/mach-versatile/clock.c b/arch/arm/mach-versatile/clock.c
index 9336508ec0b..58937f1fb38 100644
--- a/arch/arm/mach-versatile/clock.c
+++ b/arch/arm/mach-versatile/clock.c
@@ -105,7 +105,7 @@ static struct clk uart_clk = {
static struct clk mmci_clk = {
.name = "MCLK",
- .rate = 33000000,
+ .rate = 24000000,
};
int clk_register(struct clk *clk)
diff --git a/arch/arm/mach-versatile/include/mach/platform.h b/arch/arm/mach-versatile/include/mach/platform.h
index 27cbe6a3f22..f91ba930ca8 100644
--- a/arch/arm/mach-versatile/include/mach/platform.h
+++ b/arch/arm/mach-versatile/include/mach/platform.h
@@ -436,28 +436,12 @@
#define SIC_INTMASK_PCI1 (1 << SIC_INT_PCI1)
#define SIC_INTMASK_PCI2 (1 << SIC_INT_PCI2)
#define SIC_INTMASK_PCI3 (1 << SIC_INT_PCI3)
-/*
- * Application Flash
- *
- */
-#define FLASH_BASE VERSATILE_FLASH_BASE
-#define FLASH_SIZE VERSATILE_FLASH_SIZE
-#define FLASH_END (FLASH_BASE + FLASH_SIZE - 1)
-#define FLASH_BLOCK_SIZE SZ_128K
-
-/*
- * Boot Flash
- *
- */
-#define EPROM_BASE VERSATILE_BOOT_ROM_HI
-#define EPROM_SIZE VERSATILE_BOOT_ROM_SIZE
-#define EPROM_END (EPROM_BASE + EPROM_SIZE - 1)
/*
* Clean base - dummy
*
*/
-#define CLEAN_BASE EPROM_BASE
+#define CLEAN_BASE VERSATILE_BOOT_ROM_HI
/*
* System controller bit assignment
diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c
index 133e65d166b..2d5884ce043 100644
--- a/arch/arm/mm/alignment.c
+++ b/arch/arm/mm/alignment.c
@@ -70,6 +70,10 @@ static unsigned long ai_dword;
static unsigned long ai_multi;
static int ai_usermode;
+#define UM_WARN (1 << 0)
+#define UM_FIXUP (1 << 1)
+#define UM_SIGNAL (1 << 2)
+
#ifdef CONFIG_PROC_FS
static const char *usermode_action[] = {
"ignored",
@@ -754,7 +758,7 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
user:
ai_user += 1;
- if (ai_usermode & 1)
+ if (ai_usermode & UM_WARN)
printk("Alignment trap: %s (%d) PC=0x%08lx Instr=0x%0*lx "
"Address=0x%08lx FSR 0x%03x\n", current->comm,
task_pid_nr(current), instrptr,
@@ -762,10 +766,10 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
thumb_mode(regs) ? tinstr : instr,
addr, fsr);
- if (ai_usermode & 2)
+ if (ai_usermode & UM_FIXUP)
goto fixup;
- if (ai_usermode & 4)
+ if (ai_usermode & UM_SIGNAL)
force_sig(SIGBUS, current);
else
set_cr(cr_no_alignment);
@@ -796,6 +800,22 @@ static int __init alignment_init(void)
res->write_proc = proc_alignment_write;
#endif
+ /*
+ * ARMv6 and later CPUs can perform unaligned accesses for
+ * most single load and store instructions up to word size.
+ * LDM, STM, LDRD and STRD still need to be handled.
+ *
+ * Ignoring the alignment fault is not an option on these
+ * CPUs since we spin re-faulting the instruction without
+ * making any progress.
+ */
+ if (cpu_architecture() >= CPU_ARCH_ARMv6 && (cr_alignment & CR_U)) {
+ cr_alignment &= ~CR_A;
+ cr_no_alignment &= ~CR_A;
+ set_cr(cr_alignment);
+ ai_usermode = UM_FIXUP;
+ }
+
hook_fault_code(1, do_alignment, SIGILL, "alignment exception");
hook_fault_code(3, do_alignment, SIGILL, "alignment exception");
diff --git a/arch/arm/mm/cache-feroceon-l2.c b/arch/arm/mm/cache-feroceon-l2.c
index 13cdae8b0d4..80cd207cbae 100644
--- a/arch/arm/mm/cache-feroceon-l2.c
+++ b/arch/arm/mm/cache-feroceon-l2.c
@@ -150,7 +150,7 @@ static void feroceon_l2_inv_range(unsigned long start, unsigned long end)
/*
* Clean and invalidate partial last cache line.
*/
- if (end & (CACHE_LINE_SIZE - 1)) {
+ if (start < end && end & (CACHE_LINE_SIZE - 1)) {
l2_clean_inv_pa(end & ~(CACHE_LINE_SIZE - 1));
end &= ~(CACHE_LINE_SIZE - 1);
}
@@ -158,7 +158,7 @@ static void feroceon_l2_inv_range(unsigned long start, unsigned long end)
/*
* Invalidate all full cache lines between 'start' and 'end'.
*/
- while (start != end) {
+ while (start < end) {
unsigned long range_end = calc_range_end(start, end);
l2_inv_pa_range(start, range_end - CACHE_LINE_SIZE);
start = range_end;
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
index 2df8d9facf5..22c9530e91e 100644
--- a/arch/arm/mm/fault.c
+++ b/arch/arm/mm/fault.c
@@ -11,6 +11,7 @@
#include <linux/module.h>
#include <linux/signal.h>
#include <linux/mm.h>
+#include <linux/hardirq.h>
#include <linux/init.h>
#include <linux/kprobes.h>
#include <linux/uaccess.h>
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index e63db11f16a..7f36c825718 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -208,6 +208,12 @@ static struct mem_type mem_types[] = {
.prot_sect = PROT_SECT_DEVICE,
.domain = DOMAIN_IO,
},
+ [MT_UNCACHED] = {
+ .prot_pte = PROT_PTE_DEVICE,
+ .prot_l1 = PMD_TYPE_TABLE,
+ .prot_sect = PMD_TYPE_SECT | PMD_SECT_XN,
+ .domain = DOMAIN_IO,
+ },
[MT_CACHECLEAN] = {
.prot_sect = PMD_TYPE_SECT | PMD_SECT_XN,
.domain = DOMAIN_KERNEL,
diff --git a/arch/arm/plat-iop/setup.c b/arch/arm/plat-iop/setup.c
index 4689db638e9..9e573e78176 100644
--- a/arch/arm/plat-iop/setup.c
+++ b/arch/arm/plat-iop/setup.c
@@ -16,14 +16,15 @@
#include <asm/hardware/iop3xx.h>
/*
- * Standard IO mapping for all IOP3xx based systems
+ * Standard IO mapping for all IOP3xx based systems. Note that
+ * the IOP3xx OCCDR must be mapped uncached and unbuffered.
*/
static struct map_desc iop3xx_std_desc[] __initdata = {
{ /* mem mapped registers */
.virtual = IOP3XX_PERIPHERAL_VIRT_BASE,
.pfn = __phys_to_pfn(IOP3XX_PERIPHERAL_PHYS_BASE),
.length = IOP3XX_PERIPHERAL_SIZE,
- .type = MT_DEVICE,
+ .type = MT_UNCACHED,
}, { /* PCI IO space */
.virtual = IOP3XX_PCI_LOWER_IO_VA,
.pfn = __phys_to_pfn(IOP3XX_PCI_LOWER_IO_PA),
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
index 8679fbca6bb..424049d83fb 100644
--- a/arch/arm/plat-omap/gpio.c
+++ b/arch/arm/plat-omap/gpio.c
@@ -101,6 +101,7 @@
#define OMAP24XX_GPIO_IRQSTATUS2 0x0028
#define OMAP24XX_GPIO_IRQENABLE2 0x002c
#define OMAP24XX_GPIO_IRQENABLE1 0x001c
+#define OMAP24XX_GPIO_WAKE_EN 0x0020
#define OMAP24XX_GPIO_CTRL 0x0030
#define OMAP24XX_GPIO_OE 0x0034
#define OMAP24XX_GPIO_DATAIN 0x0038
@@ -1551,7 +1552,7 @@ static int omap_gpio_suspend(struct sys_device *dev, pm_message_t mesg)
#endif
#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
case METHOD_GPIO_24XX:
- wake_status = bank->base + OMAP24XX_GPIO_SETWKUENA;
+ wake_status = bank->base + OMAP24XX_GPIO_WAKE_EN;
wake_clear = bank->base + OMAP24XX_GPIO_CLEARWKUENA;
wake_set = bank->base + OMAP24XX_GPIO_SETWKUENA;
break;
@@ -1574,7 +1575,7 @@ static int omap_gpio_resume(struct sys_device *dev)
{
int i;
- if (!cpu_is_omap24xx() && !cpu_is_omap16xx())
+ if (!cpu_class_is_omap2() && !cpu_is_omap16xx())
return 0;
for (i = 0; i < gpio_bank_count; i++) {
diff --git a/arch/arm/plat-omap/include/mach/omapfb.h b/arch/arm/plat-omap/include/mach/omapfb.h
index ec67fb42860..7b74d1255e0 100644
--- a/arch/arm/plat-omap/include/mach/omapfb.h
+++ b/arch/arm/plat-omap/include/mach/omapfb.h
@@ -353,8 +353,8 @@ struct omapfb_device {
u32 pseudo_palette[17];
struct lcd_panel *panel; /* LCD panel */
- struct lcd_ctrl *ctrl; /* LCD controller */
- struct lcd_ctrl *int_ctrl; /* internal LCD ctrl */
+ const struct lcd_ctrl *ctrl; /* LCD controller */
+ const struct lcd_ctrl *int_ctrl; /* internal LCD ctrl */
struct lcd_ctrl_extif *ext_if; /* LCD ctrl external
interface */
struct device *dev;
diff --git a/arch/arm/plat-omap/include/mach/pm.h b/arch/arm/plat-omap/include/mach/pm.h
index 768eb6e7abc..2a9c27ad4c3 100644
--- a/arch/arm/plat-omap/include/mach/pm.h
+++ b/arch/arm/plat-omap/include/mach/pm.h
@@ -128,7 +128,7 @@ void clk_deny_idle(struct clk *clk);
* clk_allow_idle - Counters previous clk_deny_idle
* @clk: clock signal handle
*/
-void clk_deny_idle(struct clk *clk);
+void clk_allow_idle(struct clk *clk);
extern void omap_pm_idle(void);
extern void omap_pm_suspend(void);
diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c
index 9f9a921829c..dcd9d16da2e 100644
--- a/arch/arm/plat-omap/sram.c
+++ b/arch/arm/plat-omap/sram.c
@@ -255,7 +255,7 @@ void omap_sram_reprogram_clock(u32 dpllctl, u32 ckctl)
if (!_omap_sram_reprogram_clock)
omap_sram_error();
- return _omap_sram_reprogram_clock(dpllctl, ckctl);
+ _omap_sram_reprogram_clock(dpllctl, ckctl);
}
int __init omap1_sram_init(void)
@@ -282,8 +282,8 @@ void omap2_sram_ddr_init(u32 *slow_dll_ctrl, u32 fast_dll_ctrl,
if (!_omap2_sram_ddr_init)
omap_sram_error();
- return _omap2_sram_ddr_init(slow_dll_ctrl, fast_dll_ctrl,
- base_cs, force_unlock);
+ _omap2_sram_ddr_init(slow_dll_ctrl, fast_dll_ctrl,
+ base_cs, force_unlock);
}
static void (*_omap2_sram_reprogram_sdrc)(u32 perf_level, u32 dll_val,
@@ -294,7 +294,7 @@ void omap2_sram_reprogram_sdrc(u32 perf_level, u32 dll_val, u32 mem_type)
if (!_omap2_sram_reprogram_sdrc)
omap_sram_error();
- return _omap2_sram_reprogram_sdrc(perf_level, dll_val, mem_type);
+ _omap2_sram_reprogram_sdrc(perf_level, dll_val, mem_type);
}
static u32 (*_omap2_set_prcm)(u32 dpll_ctrl_val, u32 sdrc_rfr_val, int bypass);
diff --git a/arch/arm/plat-orion/pcie.c b/arch/arm/plat-orion/pcie.c
index 883902fead8..d41d41d78ad 100644
--- a/arch/arm/plat-orion/pcie.c
+++ b/arch/arm/plat-orion/pcie.c
@@ -35,7 +35,7 @@
#define PCIE_CONF_REG(r) ((((r) & 0xf00) << 16) | ((r) & 0xfc))
#define PCIE_CONF_BUS(b) (((b) & 0xff) << 16)
#define PCIE_CONF_DEV(d) (((d) & 0x1f) << 11)
-#define PCIE_CONF_FUNC(f) (((f) & 0x3) << 8)
+#define PCIE_CONF_FUNC(f) (((f) & 0x7) << 8)
#define PCIE_CONF_DATA_OFF 0x18fc
#define PCIE_MASK_OFF 0x1910
#define PCIE_CTRL_OFF 0x1a00
diff --git a/arch/avr32/boards/favr-32/flash.c b/arch/avr32/boards/favr-32/flash.c
index 5f139b7cb5f..604bbd5e41d 100644
--- a/arch/avr32/boards/favr-32/flash.c
+++ b/arch/avr32/boards/favr-32/flash.c
@@ -13,7 +13,7 @@
#include <linux/mtd/partitions.h>
#include <linux/mtd/physmap.h>
-#include <asm/arch/smc.h>
+#include <mach/smc.h>
static struct smc_timing flash_timing __initdata = {
.ncs_read_setup = 0,
diff --git a/arch/avr32/boards/favr-32/setup.c b/arch/avr32/boards/favr-32/setup.c
index 7538f3d2b9e..1ee4faf0742 100644
--- a/arch/avr32/boards/favr-32/setup.c
+++ b/arch/avr32/boards/favr-32/setup.c
@@ -25,10 +25,10 @@
#include <asm/setup.h>
-#include <asm/arch/at32ap700x.h>
-#include <asm/arch/init.h>
-#include <asm/arch/board.h>
-#include <asm/arch/portmux.h>
+#include <mach/at32ap700x.h>
+#include <mach/init.h>
+#include <mach/board.h>
+#include <mach/portmux.h>
/* Oscillator frequencies. These are board-specific */
unsigned long at32_board_osc_rates[3] = {
diff --git a/arch/avr32/boot/images/Makefile b/arch/avr32/boot/images/Makefile
index 219720a47bf..1848bf0d7f6 100644
--- a/arch/avr32/boot/images/Makefile
+++ b/arch/avr32/boot/images/Makefile
@@ -10,7 +10,7 @@ MKIMAGE := $(srctree)/scripts/mkuboot.sh
extra-y := vmlinux.bin vmlinux.gz
-OBJCOPYFLAGS_vmlinux.bin := -O binary
+OBJCOPYFLAGS_vmlinux.bin := -O binary -R .note.gnu.build-id
$(obj)/vmlinux.bin: vmlinux FORCE
$(call if_changed,objcopy)
diff --git a/arch/avr32/configs/atstk1006_defconfig b/arch/avr32/configs/atstk1006_defconfig
index 8b6e54c9946..6c45a3b77aa 100644
--- a/arch/avr32/configs/atstk1006_defconfig
+++ b/arch/avr32/configs/atstk1006_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27-rc1
-# Tue Aug 5 15:40:26 2008
+# Linux kernel version: 2.6.28-rc8
+# Thu Dec 18 11:22:23 2008
#
CONFIG_AVR32=y
CONFIG_GENERIC_GPIO=y
@@ -67,6 +67,7 @@ CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLUB_DEBUG=y
# CONFIG_SLAB is not set
@@ -77,15 +78,8 @@ CONFIG_PROFILING=y
CONFIG_OPROFILE=m
CONFIG_HAVE_OPROFILE=y
CONFIG_KPROBES=y
-# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set
-# CONFIG_HAVE_IOREMAP_PROT is not set
CONFIG_HAVE_KPROBES=y
-# CONFIG_HAVE_KRETPROBES is not set
-# CONFIG_HAVE_ARCH_TRACEHOOK is not set
-# CONFIG_HAVE_DMA_ATTRS is not set
-# CONFIG_USE_GENERIC_SMP_HELPERS is not set
CONFIG_HAVE_CLK=y
-CONFIG_PROC_PAGE_MONITOR=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -118,6 +112,7 @@ CONFIG_DEFAULT_CFQ=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="cfq"
CONFIG_CLASSIC_RCU=y
+CONFIG_FREEZER=y
#
# System Type and features
@@ -134,6 +129,8 @@ CONFIG_CPU_AT32AP700X=y
CONFIG_CPU_AT32AP7000=y
CONFIG_BOARD_ATSTK1000=y
# CONFIG_BOARD_ATNGW100 is not set
+# CONFIG_BOARD_FAVR_32 is not set
+# CONFIG_BOARD_MIMC200 is not set
# CONFIG_BOARD_ATSTK1002 is not set
# CONFIG_BOARD_ATSTK1003 is not set
# CONFIG_BOARD_ATSTK1004 is not set
@@ -171,14 +168,14 @@ CONFIG_FLATMEM_MANUAL=y
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
CONFIG_NR_QUICK=2
CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
# CONFIG_OWNERSHIP_TRACE is not set
CONFIG_NMI_DEBUGGING=y
# CONFIG_HZ_100 is not set
@@ -186,7 +183,7 @@ CONFIG_HZ_250=y
# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
-# CONFIG_SCHED_HRTICK is not set
+CONFIG_SCHED_HRTICK=y
CONFIG_CMDLINE=""
#
@@ -228,6 +225,8 @@ CONFIG_CPU_FREQ_AT32AP=y
# Executable file formats
#
CONFIG_BINFMT_ELF=y
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
+# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
CONFIG_NET=y
@@ -299,6 +298,7 @@ CONFIG_IPV6_TUNNEL=m
# CONFIG_ATM is not set
CONFIG_STP=m
CONFIG_BRIDGE=m
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
CONFIG_LLC=m
@@ -321,14 +321,8 @@ CONFIG_LLC=m
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
-# CONFIG_CFG80211 is not set
-# CONFIG_WIRELESS_EXT is not set
-# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_PHONET is not set
+# CONFIG_WIRELESS is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -359,6 +353,7 @@ CONFIG_MTD_CMDLINE_PARTS=y
# User Modules And Translation Layers
#
CONFIG_MTD_CHAR=y
+CONFIG_HAVE_MTD_OTP=y
CONFIG_MTD_BLKDEVS=y
CONFIG_MTD_BLOCK=y
# CONFIG_FTL is not set
@@ -407,6 +402,8 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=2
# Self-contained MTD device drivers
#
CONFIG_MTD_DATAFLASH=m
+# CONFIG_MTD_DATAFLASH_WRITE_VERIFY is not set
+CONFIG_MTD_DATAFLASH_OTP=y
CONFIG_MTD_M25P80=m
CONFIG_M25PXX_USE_FAST_READ=y
# CONFIG_MTD_SLRAM is not set
@@ -464,9 +461,10 @@ CONFIG_ATMEL_TCLIB=y
CONFIG_ATMEL_TCB_CLKSRC=y
CONFIG_ATMEL_TCB_CLKSRC_BLOCK=0
# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_ICS932S401 is not set
CONFIG_ATMEL_SSC=m
# CONFIG_ENCLOSURE_SERVICES is not set
-# CONFIG_HAVE_IDE is not set
+# CONFIG_C2PORT is not set
#
# SCSI device support
@@ -548,6 +546,9 @@ CONFIG_MACB=y
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
# CONFIG_B44 is not set
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
@@ -653,6 +654,7 @@ CONFIG_UNIX98_PTYS=y
CONFIG_I2C=m
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=m
+CONFIG_I2C_HELPER_AUTO=y
CONFIG_I2C_ALGOBIT=m
#
@@ -717,6 +719,10 @@ CONFIG_GPIOLIB=y
CONFIG_GPIO_SYSFS=y
#
+# Memory mapped GPIO expanders:
+#
+
+#
# I2C GPIO expanders:
#
# CONFIG_GPIO_MAX732X is not set
@@ -745,11 +751,11 @@ CONFIG_WATCHDOG=y
#
# CONFIG_SOFT_WATCHDOG is not set
CONFIG_AT32AP700X_WDT=y
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -758,6 +764,10 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -783,6 +793,7 @@ CONFIG_SSB_POSSIBLE=y
CONFIG_FB=y
# CONFIG_FIRMWARE_EDID is not set
# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
@@ -804,10 +815,13 @@ CONFIG_FB_CFB_IMAGEBLIT=y
# CONFIG_FB_S1D13XXX is not set
CONFIG_FB_ATMEL=y
# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
CONFIG_BACKLIGHT_LCD_SUPPORT=y
CONFIG_LCD_CLASS_DEVICE=y
CONFIG_LCD_LTV350QV=y
# CONFIG_LCD_ILI9320 is not set
+# CONFIG_LCD_TDO24M is not set
# CONFIG_LCD_VGG2432A4 is not set
# CONFIG_LCD_PLATFORM is not set
# CONFIG_BACKLIGHT_CLASS_DEVICE is not set
@@ -818,6 +832,7 @@ CONFIG_LCD_LTV350QV=y
# CONFIG_DISPLAY_SUPPORT is not set
# CONFIG_LOGO is not set
CONFIG_SOUND=m
+CONFIG_SOUND_OSS_CORE=y
CONFIG_SND=m
CONFIG_SND_TIMER=m
CONFIG_SND_PCM=m
@@ -848,28 +863,32 @@ CONFIG_USB_SUPPORT=y
# CONFIG_USB_ARCH_HAS_EHCI is not set
# CONFIG_USB_OTG_WHITELIST is not set
# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_MUSB_HDRC is not set
+# CONFIG_USB_GADGET_MUSB_HDRC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
CONFIG_USB_GADGET=y
# CONFIG_USB_GADGET_DEBUG is not set
# CONFIG_USB_GADGET_DEBUG_FILES is not set
# CONFIG_USB_GADGET_DEBUG_FS is not set
+CONFIG_USB_GADGET_VBUS_DRAW=2
CONFIG_USB_GADGET_SELECTED=y
-# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_AT91 is not set
CONFIG_USB_GADGET_ATMEL_USBA=y
CONFIG_USB_ATMEL_USBA=y
# CONFIG_USB_GADGET_FSL_USB2 is not set
-# CONFIG_USB_GADGET_NET2280 is not set
-# CONFIG_USB_GADGET_PXA25X is not set
-# CONFIG_USB_GADGET_M66592 is not set
-# CONFIG_USB_GADGET_PXA27X is not set
-# CONFIG_USB_GADGET_GOKU is not set
# CONFIG_USB_GADGET_LH7A40X is not set
# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_PXA27X is not set
# CONFIG_USB_GADGET_S3C2410 is not set
-# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
# CONFIG_USB_GADGET_DUMMY_HCD is not set
CONFIG_USB_GADGET_DUALSPEED=y
CONFIG_USB_ZERO=m
@@ -887,7 +906,7 @@ CONFIG_MMC=y
# CONFIG_MMC_UNSAFE_RESUME is not set
#
-# MMC/SD Card Drivers
+# MMC/SD/SDIO Card Drivers
#
CONFIG_MMC_BLOCK=y
CONFIG_MMC_BLOCK_BOUNCE=y
@@ -895,10 +914,11 @@ CONFIG_MMC_BLOCK_BOUNCE=y
# CONFIG_MMC_TEST is not set
#
-# MMC/SD Host Controller Drivers
+# MMC/SD/SDIO Host Controller Drivers
#
# CONFIG_MMC_SDHCI is not set
CONFIG_MMC_ATMELMCI=y
+# CONFIG_MMC_ATMELMCI_DMA is not set
CONFIG_MMC_SPI=m
# CONFIG_MEMSTICK is not set
CONFIG_NEW_LEDS=y
@@ -918,6 +938,7 @@ CONFIG_LEDS_GPIO=m
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=m
CONFIG_LEDS_TRIGGER_HEARTBEAT=m
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
# CONFIG_ACCESSIBILITY is not set
CONFIG_RTC_LIB=y
@@ -950,25 +971,31 @@ CONFIG_RTC_INTF_DEV=y
# CONFIG_RTC_DRV_M41T80 is not set
# CONFIG_RTC_DRV_S35390A is not set
# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
#
# SPI RTC drivers
#
# CONFIG_RTC_DRV_M41T94 is not set
# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
# CONFIG_RTC_DRV_MAX6902 is not set
# CONFIG_RTC_DRV_R9701 is not set
# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
#
# Platform RTC drivers
#
+# CONFIG_RTC_DRV_DS1286 is not set
# CONFIG_RTC_DRV_DS1511 is not set
# CONFIG_RTC_DRV_DS1553 is not set
# CONFIG_RTC_DRV_DS1742 is not set
# CONFIG_RTC_DRV_STK17TA8 is not set
# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
# CONFIG_RTC_DRV_V3020 is not set
#
@@ -989,6 +1016,8 @@ CONFIG_DMA_ENGINE=y
# CONFIG_NET_DMA is not set
CONFIG_DMATEST=m
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+CONFIG_STAGING_EXCLUDE_BUILD=y
#
# File systems
@@ -998,12 +1027,17 @@ CONFIG_EXT2_FS=m
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=m
# CONFIG_EXT3_FS_XATTR is not set
-# CONFIG_EXT4DEV_FS is not set
+CONFIG_EXT4_FS=m
+CONFIG_EXT4DEV_COMPAT=y
+# CONFIG_EXT4_FS_XATTR is not set
CONFIG_JBD=m
# CONFIG_JBD_DEBUG is not set
+CONFIG_JBD2=m
+# CONFIG_JBD2_DEBUG is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
# CONFIG_XFS_FS is not set
# CONFIG_OCFS2_FS is not set
# CONFIG_DNOTIFY is not set
@@ -1036,6 +1070,7 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
@@ -1054,7 +1089,8 @@ CONFIG_TMPFS=y
# CONFIG_EFS_FS is not set
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
-# CONFIG_JFFS2_FS_WRITEBUFFER is not set
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
# CONFIG_JFFS2_SUMMARY is not set
# CONFIG_JFFS2_FS_XATTR is not set
# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
@@ -1088,6 +1124,7 @@ CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_REGISTER_V4 is not set
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -1185,10 +1222,21 @@ CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_FRAME_POINTER=y
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_KPROBES_SANITY_TEST is not set
# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
# CONFIG_LKDTM is not set
# CONFIG_FAULT_INJECTION is not set
+
+#
+# Tracers
+#
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
#
@@ -1196,17 +1244,26 @@ CONFIG_FRAME_POINTER=y
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_CRYPTO=y
#
# Crypto core or helper
#
+CONFIG_CRYPTO_FIPS=y
CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=m
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
@@ -1257,7 +1314,7 @@ CONFIG_CRYPTO_SHA1=m
#
# Ciphers
#
-# CONFIG_CRYPTO_AES is not set
+CONFIG_CRYPTO_AES=m
# CONFIG_CRYPTO_ANUBIS is not set
# CONFIG_CRYPTO_ARC4 is not set
# CONFIG_CRYPTO_BLOWFISH is not set
@@ -1278,14 +1335,17 @@ CONFIG_CRYPTO_DES=m
#
CONFIG_CRYPTO_DEFLATE=y
CONFIG_CRYPTO_LZO=y
+
+#
+# Random Number Generation
+#
+CONFIG_CRYPTO_ANSI_CPRNG=m
# CONFIG_CRYPTO_HW is not set
#
# Library routines
#
CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
-# CONFIG_GENERIC_FIND_NEXT_BIT is not set
CONFIG_CRC_CCITT=m
CONFIG_CRC16=y
CONFIG_CRC_T10DIF=m
diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c
index 0c6e02f80a3..066252eebf6 100644
--- a/arch/avr32/mach-at32ap/at32ap700x.c
+++ b/arch/avr32/mach-at32ap/at32ap700x.c
@@ -967,28 +967,28 @@ static inline void configure_usart0_pins(void)
{
u32 pin_mask = (1 << 8) | (1 << 9); /* RXD & TXD */
- select_peripheral(PIOA, pin_mask, PERIPH_B, 0);
+ select_peripheral(PIOA, pin_mask, PERIPH_B, AT32_GPIOF_PULLUP);
}
static inline void configure_usart1_pins(void)
{
u32 pin_mask = (1 << 17) | (1 << 18); /* RXD & TXD */
- select_peripheral(PIOA, pin_mask, PERIPH_A, 0);
+ select_peripheral(PIOA, pin_mask, PERIPH_A, AT32_GPIOF_PULLUP);
}
static inline void configure_usart2_pins(void)
{
u32 pin_mask = (1 << 26) | (1 << 27); /* RXD & TXD */
- select_peripheral(PIOB, pin_mask, PERIPH_B, 0);
+ select_peripheral(PIOB, pin_mask, PERIPH_B, AT32_GPIOF_PULLUP);
}
static inline void configure_usart3_pins(void)
{
u32 pin_mask = (1 << 18) | (1 << 17); /* RXD & TXD */
- select_peripheral(PIOB, pin_mask, PERIPH_B, 0);
+ select_peripheral(PIOB, pin_mask, PERIPH_B, AT32_GPIOF_PULLUP);
}
static struct platform_device *__initdata at32_usarts[4];
diff --git a/arch/blackfin/include/asm/bfin-global.h b/arch/blackfin/include/asm/bfin-global.h
index 56dcb0a2d24..77295666c34 100644
--- a/arch/blackfin/include/asm/bfin-global.h
+++ b/arch/blackfin/include/asm/bfin-global.h
@@ -101,7 +101,7 @@ extern u16 _bfin_swrst; /* shadow for Software Reset Register (SWRST) */
extern unsigned long _ramstart, _ramend, _rambase;
extern unsigned long memory_start, memory_end, physical_mem_end;
extern char _stext_l1[], _etext_l1[], _sdata_l1[], _edata_l1[], _sbss_l1[],
- _ebss_l1[], _l1_lma_start[], _sdata_b_l1[], _ebss_b_l1[],
+ _ebss_l1[], _l1_lma_start[], _sdata_b_l1[], _sbss_b_l1[], _ebss_b_l1[],
_stext_l2[], _etext_l2[], _sdata_l2[], _edata_l2[], _sbss_l2[],
_ebss_l2[], _l2_lma_start[];
diff --git a/arch/blackfin/include/asm/dma-mapping.h b/arch/blackfin/include/asm/dma-mapping.h
index ede748d67ef..d7d9148e433 100644
--- a/arch/blackfin/include/asm/dma-mapping.h
+++ b/arch/blackfin/include/asm/dma-mapping.h
@@ -15,7 +15,11 @@ void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
-#define dma_mapping_error
+static inline
+int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
+{
+ return 0;
+}
/*
* Map a single buffer of the indicated size for DMA in streaming mode.
diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c
index 6e08f425bb4..5c0800adb4d 100644
--- a/arch/blackfin/kernel/bfin_gpio.c
+++ b/arch/blackfin/kernel/bfin_gpio.c
@@ -218,7 +218,7 @@ inline int check_gpio(unsigned gpio)
if (gpio == GPIO_PB15 || gpio == GPIO_PC14 || gpio == GPIO_PC15
|| gpio == GPIO_PH14 || gpio == GPIO_PH15
|| gpio == GPIO_PJ14 || gpio == GPIO_PJ15
- || gpio > MAX_BLACKFIN_GPIOS)
+ || gpio >= MAX_BLACKFIN_GPIOS)
return -EINVAL;
return 0;
}
diff --git a/arch/blackfin/kernel/cplb-nompu/cplbinit.c b/arch/blackfin/kernel/cplb-nompu/cplbinit.c
index 512f8c92ead..2debc900e24 100644
--- a/arch/blackfin/kernel/cplb-nompu/cplbinit.c
+++ b/arch/blackfin/kernel/cplb-nompu/cplbinit.c
@@ -188,10 +188,11 @@ static struct cplb_desc cplb_data[] = {
static u16 __init lock_kernel_check(u32 start, u32 end)
{
- if ((end <= (u32) _end && end >= (u32)_stext) ||
- (start <= (u32) _end && start >= (u32)_stext))
- return IN_KERNEL;
- return 0;
+ if (start >= (u32)_end || end <= (u32)_stext)
+ return 0;
+
+ /* This cplb block overlapped with kernel area. */
+ return IN_KERNEL;
}
static unsigned short __init
diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c
index 77800dd83e5..0c3ea118b65 100644
--- a/arch/blackfin/kernel/process.c
+++ b/arch/blackfin/kernel/process.c
@@ -351,10 +351,15 @@ int _access_ok(unsigned long addr, unsigned long size)
return 1;
#endif
#if L1_DATA_B_LENGTH != 0
- if (addr >= L1_DATA_B_START
+ if (addr >= L1_DATA_B_START + (_ebss_b_l1 - _sdata_b_l1)
&& addr + size <= L1_DATA_B_START + L1_DATA_B_LENGTH)
return 1;
#endif
+#if L2_LENGTH != 0
+ if (addr >= L2_START + (_ebss_l2 - _stext_l2)
+ && addr + size <= L2_START + L2_LENGTH)
+ return 1;
+#endif
return 0;
}
EXPORT_SYMBOL(_access_ok);
diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c
index 7f35d1046cd..71a9a8c53ce 100644
--- a/arch/blackfin/kernel/setup.c
+++ b/arch/blackfin/kernel/setup.c
@@ -119,23 +119,23 @@ void __init bfin_relocate_l1_mem(void)
/* Copy _stext_l1 to _etext_l1 to L1 instruction SRAM */
dma_memcpy(_stext_l1, _l1_lma_start, l1_code_length);
- l1_data_a_length = _ebss_l1 - _sdata_l1;
+ l1_data_a_length = _sbss_l1 - _sdata_l1;
if (l1_data_a_length > L1_DATA_A_LENGTH)
panic("L1 Data SRAM Bank A Overflow\n");
- /* Copy _sdata_l1 to _ebss_l1 to L1 data bank A SRAM */
+ /* Copy _sdata_l1 to _sbss_l1 to L1 data bank A SRAM */
dma_memcpy(_sdata_l1, _l1_lma_start + l1_code_length, l1_data_a_length);
- l1_data_b_length = _ebss_b_l1 - _sdata_b_l1;
+ l1_data_b_length = _sbss_b_l1 - _sdata_b_l1;
if (l1_data_b_length > L1_DATA_B_LENGTH)
panic("L1 Data SRAM Bank B Overflow\n");
- /* Copy _sdata_b_l1 to _ebss_b_l1 to L1 data bank B SRAM */
+ /* Copy _sdata_b_l1 to _sbss_b_l1 to L1 data bank B SRAM */
dma_memcpy(_sdata_b_l1, _l1_lma_start + l1_code_length +
l1_data_a_length, l1_data_b_length);
if (L2_LENGTH != 0) {
- l2_length = _ebss_l2 - _stext_l2;
+ l2_length = _sbss_l2 - _stext_l2;
if (l2_length > L2_LENGTH)
panic("L2 SRAM Overflow\n");
@@ -827,7 +827,7 @@ void __init setup_arch(char **cmdline_p)
printk(KERN_ERR "Warning: Compiled for Rev %d, but running on Rev %d\n",
bfin_compiled_revid(), bfin_revid());
}
- if (bfin_revid() <= CONFIG_BF_REV_MIN || bfin_revid() > CONFIG_BF_REV_MAX)
+ if (bfin_revid() < CONFIG_BF_REV_MIN || bfin_revid() > CONFIG_BF_REV_MAX)
printk(KERN_ERR "Warning: Unsupported Chip Revision ADSP-%s Rev 0.%d detected\n",
CPU, bfin_revid());
}
diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c
index 1aa2c788e22..bef025b0744 100644
--- a/arch/blackfin/kernel/traps.c
+++ b/arch/blackfin/kernel/traps.c
@@ -59,7 +59,7 @@
#endif
-#ifdef CONFIG_VERBOSE_DEBUG
+#ifdef CONFIG_DEBUG_VERBOSE
#define verbose_printk(fmt, arg...) \
printk(fmt, ##arg)
#else
@@ -147,9 +147,12 @@ static void decode_address(char *buf, unsigned long address)
char *name = p->comm;
struct file *file = vma->vm_file;
- if (file)
- name = d_path(&file->f_path, _tmpbuf,
+ if (file) {
+ char *d_name = d_path(&file->f_path, _tmpbuf,
sizeof(_tmpbuf));
+ if (!IS_ERR(d_name))
+ name = d_name;
+ }
/* FLAT does not have its text aligned to the start of
* the map while FDPIC ELF does ...
@@ -571,7 +574,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
#endif
panic("Kernel exception");
} else {
-#ifdef CONFIG_VERBOSE_DEBUG
+#ifdef CONFIG_DEBUG_VERBOSE
unsigned long *stack;
/* Dump the user space stack */
stack = (unsigned long *)rdusp();
diff --git a/arch/blackfin/mach-common/cache.S b/arch/blackfin/mach-common/cache.S
index db532181fbd..a028e945041 100644
--- a/arch/blackfin/mach-common/cache.S
+++ b/arch/blackfin/mach-common/cache.S
@@ -25,9 +25,13 @@
*/
.macro do_flush flushins:req optflushins optnopins label
+ R2 = -L1_CACHE_BYTES;
+
+ /* start = (start & -L1_CACHE_BYTES) */
+ R0 = R0 & R2;
+
/* end = ((end - 1) & -L1_CACHE_BYTES) + L1_CACHE_BYTES; */
R1 += -1;
- R2 = -L1_CACHE_BYTES;
R1 = R1 & R2;
R1 += L1_CACHE_BYTES;
@@ -63,7 +67,7 @@ ENDPROC(_blackfin_icache_flush_range)
/* Flush all cache lines assocoiated with this area of memory. */
ENTRY(_blackfin_icache_dcache_flush_range)
- do_flush IFLUSH, FLUSH
+ do_flush FLUSH, IFLUSH
ENDPROC(_blackfin_icache_dcache_flush_range)
/* Throw away all D-cached data in specified region without any obligation to
diff --git a/arch/blackfin/mach-common/cpufreq.c b/arch/blackfin/mach-common/cpufreq.c
index c22c47b6012..dda5443b37e 100644
--- a/arch/blackfin/mach-common/cpufreq.c
+++ b/arch/blackfin/mach-common/cpufreq.c
@@ -72,13 +72,13 @@ unsigned int __bfin_cycles_mod;
/**************************************************************************/
-static unsigned int bfin_getfreq(unsigned int cpu)
+static unsigned int bfin_getfreq_khz(unsigned int cpu)
{
/* The driver only support single cpu */
if (cpu != 0)
return -1;
- return get_cclk();
+ return get_cclk() / 1000;
}
@@ -96,7 +96,7 @@ static int bfin_target(struct cpufreq_policy *policy,
cclk_hz = bfin_freq_table[index].frequency;
- freqs.old = bfin_getfreq(0);
+ freqs.old = bfin_getfreq_khz(0);
freqs.new = cclk_hz;
freqs.cpu = 0;
@@ -137,8 +137,8 @@ static int __init __bfin_cpu_init(struct cpufreq_policy *policy)
if (policy->cpu != 0)
return -EINVAL;
- cclk = get_cclk();
- sclk = get_sclk();
+ cclk = get_cclk() / 1000;
+ sclk = get_sclk() / 1000;
#if ANOMALY_05000273 || (!defined(CONFIG_BF54x) && defined(CONFIG_BFIN_DCACHE))
min_cclk = sclk * 2;
@@ -152,7 +152,7 @@ static int __init __bfin_cpu_init(struct cpufreq_policy *policy)
dpm_state_table[index].csel = csel << 4; /* Shift now into PLL_DIV bitpos */
dpm_state_table[index].tscale = (TIME_SCALE / (1 << csel)) - 1;
- pr_debug("cpufreq: freq:%d csel:%d tscale:%d\n",
+ pr_debug("cpufreq: freq:%d csel:0x%x tscale:%d\n",
bfin_freq_table[index].frequency,
dpm_state_table[index].csel,
dpm_state_table[index].tscale);
@@ -173,7 +173,7 @@ static struct freq_attr *bfin_freq_attr[] = {
static struct cpufreq_driver bfin_driver = {
.verify = bfin_verify_speed,
.target = bfin_target,
- .get = bfin_getfreq,
+ .get = bfin_getfreq_khz,
.init = __bfin_cpu_init,
.name = "bfin cpufreq",
.owner = THIS_MODULE,
diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S
index c13fa8da28c..bde6dc4e261 100644
--- a/arch/blackfin/mach-common/entry.S
+++ b/arch/blackfin/mach-common/entry.S
@@ -277,7 +277,7 @@ ENTRY(_bfin_return_from_exception)
p5.h = hi(ILAT);
r6 = [p5];
r7 = 0x20; /* Did I just cause anther HW error? */
- r7 = r7 & r1;
+ r6 = r7 & r6;
CC = R7 == R6;
if CC JUMP _double_fault;
#endif
diff --git a/arch/blackfin/mm/sram-alloc.c b/arch/blackfin/mm/sram-alloc.c
index 0f1ca6930c1..cc6f336e731 100644
--- a/arch/blackfin/mm/sram-alloc.c
+++ b/arch/blackfin/mm/sram-alloc.c
@@ -183,10 +183,10 @@ static void __init l2_sram_init(void)
return;
}
- free_l2_sram_head.next->paddr = (void *)L2_START +
- (_etext_l2 - _stext_l2) + (_edata_l2 - _sdata_l2);
- free_l2_sram_head.next->size = L2_LENGTH -
- (_etext_l2 - _stext_l2) + (_edata_l2 - _sdata_l2);
+ free_l2_sram_head.next->paddr =
+ (void *)L2_START + (_ebss_l2 - _stext_l2);
+ free_l2_sram_head.next->size =
+ L2_LENGTH - (_ebss_l2 - _stext_l2);
free_l2_sram_head.next->pid = 0;
free_l2_sram_head.next->next = NULL;
diff --git a/arch/frv/kernel/sys_frv.c b/arch/frv/kernel/sys_frv.c
index 49b2cf2c38f..baadc97f862 100644
--- a/arch/frv/kernel/sys_frv.c
+++ b/arch/frv/kernel/sys_frv.c
@@ -35,22 +35,21 @@ asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
int error = -EBADF;
struct file * file = NULL;
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
- if (!(flags & MAP_ANONYMOUS)) {
- file = fget(fd);
- if (!file)
- goto out;
- }
-
/* As with sparc32, make sure the shift for mmap2 is constant
(12), no matter what PAGE_SIZE we have.... */
/* But unlike sparc32, don't just silently break if we're
trying to map something we can't */
- if (pgoff & ((1<<(PAGE_SHIFT-12))-1))
+ if (pgoff & ((1 << (PAGE_SHIFT - 12)) - 1))
return -EINVAL;
+ pgoff >>= PAGE_SHIFT - 12;
- pgoff >>= (PAGE_SHIFT - 12);
+ flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ if (!(flags & MAP_ANONYMOUS)) {
+ file = fget(fd);
+ if (!file)
+ goto out;
+ }
down_write(&current->mm->mmap_sem);
error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
diff --git a/arch/ia64/configs/generic_defconfig b/arch/ia64/configs/generic_defconfig
index e05f9e1d3fa..27eb67604c5 100644
--- a/arch/ia64/configs/generic_defconfig
+++ b/arch/ia64/configs/generic_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27-rc1
-# Mon Aug 4 15:38:01 2008
+# Linux kernel version: 2.6.28-rc7
+# Mon Dec 8 08:12:07 2008
#
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -26,6 +26,7 @@ CONFIG_LOG_BUF_SHIFT=20
CONFIG_CGROUPS=y
# CONFIG_CGROUP_DEBUG is not set
# CONFIG_CGROUP_NS is not set
+# CONFIG_CGROUP_FREEZER is not set
# CONFIG_CGROUP_DEVICE is not set
CONFIG_CPUSETS=y
# CONFIG_GROUP_SCHED is not set
@@ -46,7 +47,6 @@ CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL=y
# CONFIG_EMBEDDED is not set
CONFIG_SYSCTL_SYSCALL=y
-CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -63,7 +63,9 @@ CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
CONFIG_SLUB_DEBUG=y
# CONFIG_SLAB is not set
CONFIG_SLUB=y
@@ -72,15 +74,11 @@ CONFIG_SLUB=y
# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
-# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set
-# CONFIG_HAVE_IOREMAP_PROT is not set
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
-# CONFIG_HAVE_ARCH_TRACEHOOK is not set
+CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_DMA_ATTRS=y
CONFIG_USE_GENERIC_SMP_HELPERS=y
-# CONFIG_HAVE_CLK is not set
-CONFIG_PROC_PAGE_MONITOR=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -113,6 +111,7 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_FREEZER is not set
#
# Processor type and features
@@ -125,8 +124,6 @@ CONFIG_MMU=y
CONFIG_SWIOTLB=y
CONFIG_IOMMU_HELPER=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-# CONFIG_ARCH_HAS_ILOG2_U32 is not set
-# CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_HUGETLB_PAGE_SIZE_VARIABLE=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
@@ -139,13 +136,16 @@ CONFIG_GENERIC_IOMAP=y
CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
CONFIG_IA64_UNCACHED_ALLOCATOR=y
CONFIG_AUDIT_ARCH=y
+# CONFIG_PARAVIRT_GUEST is not set
CONFIG_IA64_GENERIC=y
# CONFIG_IA64_DIG is not set
+# CONFIG_IA64_DIG_VTD is not set
# CONFIG_IA64_HP_ZX1 is not set
# CONFIG_IA64_HP_ZX1_SWIOTLB is not set
# CONFIG_IA64_SGI_SN2 is not set
# CONFIG_IA64_SGI_UV is not set
# CONFIG_IA64_HP_SIM is not set
+# CONFIG_IA64_XEN_GUEST is not set
# CONFIG_ITANIUM is not set
CONFIG_MCKINLEY=y
# CONFIG_IA64_PAGE_SIZE_4KB is not set
@@ -182,16 +182,17 @@ CONFIG_DISCONTIGMEM_MANUAL=y
CONFIG_DISCONTIGMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_NEED_MULTIPLE_NODES=y
-# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
CONFIG_RESOURCES_64BIT=y
+CONFIG_PHYS_ADDR_T_64BIT=y
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_NR_QUICK=1
CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
CONFIG_MMU_NOTIFIER=y
CONFIG_ARCH_SELECT_MEMORY_MODEL=y
CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
@@ -231,12 +232,12 @@ CONFIG_EFI_VARS=y
CONFIG_EFI_PCDP=y
CONFIG_DMIID=y
CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
CONFIG_BINFMT_MISC=m
-# CONFIG_DMAR is not set
-
#
-# Power management and ACPI
+# Power management and ACPI options
#
CONFIG_PM=y
# CONFIG_PM_DEBUG is not set
@@ -248,7 +249,6 @@ CONFIG_ACPI_PROC_EVENT=y
CONFIG_ACPI_BUTTON=m
CONFIG_ACPI_FAN=m
CONFIG_ACPI_DOCK=y
-# CONFIG_ACPI_BAY is not set
CONFIG_ACPI_PROCESSOR=m
CONFIG_ACPI_HOTPLUG_CPU=y
CONFIG_ACPI_THERMAL=m
@@ -256,9 +256,7 @@ CONFIG_ACPI_NUMA=y
# CONFIG_ACPI_CUSTOM_DSDT is not set
CONFIG_ACPI_BLACKLIST_YEAR=0
# CONFIG_ACPI_DEBUG is not set
-CONFIG_ACPI_EC=y
# CONFIG_ACPI_PCI_SLOT is not set
-CONFIG_ACPI_POWER=y
CONFIG_ACPI_SYSTEM=y
CONFIG_ACPI_CONTAINER=m
@@ -275,7 +273,7 @@ CONFIG_PCI_DOMAINS=y
CONFIG_PCI_SYSCALL=y
# CONFIG_PCIEPORTBUS is not set
CONFIG_ARCH_SUPPORTS_MSI=y
-# CONFIG_PCI_MSI is not set
+CONFIG_PCI_MSI=y
CONFIG_PCI_LEGACY=y
# CONFIG_PCI_DEBUG is not set
CONFIG_HOTPLUG_PCI=m
@@ -286,6 +284,7 @@ CONFIG_HOTPLUG_PCI_ACPI=m
# CONFIG_HOTPLUG_PCI_SHPC is not set
# CONFIG_HOTPLUG_PCI_SGI is not set
# CONFIG_PCCARD is not set
+CONFIG_DMAR=y
CONFIG_NET=y
#
@@ -333,6 +332,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
@@ -353,11 +353,10 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
+# CONFIG_PHONET is not set
+CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
@@ -385,7 +384,7 @@ CONFIG_PROC_EVENTS=y
# CONFIG_MTD is not set
# CONFIG_PARPORT is not set
CONFIG_PNP=y
-# CONFIG_PNP_DEBUG is not set
+# CONFIG_PNP_DEBUG_MESSAGES is not set
#
# Protocols
@@ -419,10 +418,9 @@ CONFIG_SGI_XP=m
# CONFIG_HP_ILO is not set
CONFIG_SGI_GRU=m
# CONFIG_SGI_GRU_DEBUG is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
CONFIG_IDE=y
-CONFIG_IDE_MAX_HWIFS=4
-CONFIG_BLK_DEV_IDE=y
#
# Please see Documentation/ide/ide.txt for help/info on IDE drives
@@ -430,12 +428,12 @@ CONFIG_BLK_DEV_IDE=y
CONFIG_IDE_TIMINGS=y
CONFIG_IDE_ATAPI=y
# CONFIG_BLK_DEV_IDE_SATA is not set
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_IDE_GD=y
+CONFIG_IDE_GD_ATA=y
+# CONFIG_IDE_GD_ATAPI is not set
CONFIG_BLK_DEV_IDECD=y
CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y
# CONFIG_BLK_DEV_IDETAPE is not set
-CONFIG_BLK_DEV_IDEFLOPPY=y
CONFIG_BLK_DEV_IDESCSI=m
# CONFIG_BLK_DEV_IDEACPI is not set
# CONFIG_IDE_TASK_IOCTL is not set
@@ -705,6 +703,9 @@ CONFIG_TULIP=m
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
CONFIG_NET_PCI=y
# CONFIG_PCNET32 is not set
# CONFIG_AMD8111_ETH is not set
@@ -725,11 +726,11 @@ CONFIG_E100=m
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
# CONFIG_SC92031 is not set
+# CONFIG_ATL2 is not set
CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
CONFIG_E1000=y
-# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
# CONFIG_E1000E is not set
# CONFIG_IP1000 is not set
CONFIG_IGB=y
@@ -747,18 +748,22 @@ CONFIG_TIGON3=y
# CONFIG_QLA3XXX is not set
# CONFIG_ATL1 is not set
# CONFIG_ATL1E is not set
+# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
# CONFIG_CHELSIO_T3 is not set
+# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
# CONFIG_NIU is not set
+# CONFIG_MLX4_EN is not set
# CONFIG_MLX4_CORE is not set
# CONFIG_TEHUTI is not set
# CONFIG_BNX2X is not set
+# CONFIG_QLGE is not set
# CONFIG_SFC is not set
# CONFIG_TR is not set
@@ -826,9 +831,11 @@ CONFIG_MOUSE_PS2_LOGIPS2PP=y
CONFIG_MOUSE_PS2_SYNAPTICS=y
CONFIG_MOUSE_PS2_LIFEBOOK=y
CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
# CONFIG_MOUSE_PS2_TOUCHKIT is not set
# CONFIG_MOUSE_SERIAL is not set
# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
# CONFIG_MOUSE_VSXXXAA is not set
# CONFIG_INPUT_JOYSTICK is not set
# CONFIG_INPUT_TABLET is not set
@@ -942,15 +949,16 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_VT8231 is not set
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_SENSORS_LIS3LV02D is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
CONFIG_THERMAL=m
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -959,6 +967,8 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -1009,6 +1019,7 @@ CONFIG_VGA_CONSOLE=y
# CONFIG_VGACON_SOFT_SCROLLBACK is not set
CONFIG_DUMMY_CONSOLE=y
CONFIG_SOUND=m
+CONFIG_SOUND_OSS_CORE=y
CONFIG_SND=m
CONFIG_SND_TIMER=m
CONFIG_SND_PCM=m
@@ -1113,8 +1124,7 @@ CONFIG_HID=y
# USB Input Devices
#
CONFIG_USB_HID=m
-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
-# CONFIG_HID_FF is not set
+# CONFIG_HID_PID is not set
# CONFIG_USB_HIDDEV is not set
#
@@ -1122,6 +1132,34 @@ CONFIG_USB_HID=m
#
# CONFIG_USB_KBD is not set
# CONFIG_USB_MOUSE is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
+CONFIG_HID_A4TECH=m
+CONFIG_HID_APPLE=m
+CONFIG_HID_BELKIN=m
+CONFIG_HID_BRIGHT=m
+CONFIG_HID_CHERRY=m
+CONFIG_HID_CHICONY=m
+CONFIG_HID_CYPRESS=m
+CONFIG_HID_DELL=m
+CONFIG_HID_EZKEY=m
+CONFIG_HID_GYRATION=m
+CONFIG_HID_LOGITECH=m
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=m
+CONFIG_HID_MONTEREY=m
+CONFIG_HID_PANTHERLORD=m
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_HID_PETALYNX=m
+CONFIG_HID_SAMSUNG=m
+CONFIG_HID_SONY=m
+CONFIG_HID_SUNPLUS=m
+# CONFIG_THRUSTMASTER_FF is not set
+# CONFIG_ZEROPLUS_FF is not set
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
@@ -1138,6 +1176,9 @@ CONFIG_USB_DEVICE_CLASS=y
# CONFIG_USB_DYNAMIC_MINORS is not set
# CONFIG_USB_SUSPEND is not set
# CONFIG_USB_OTG is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
#
# USB Host Controller Drivers
@@ -1155,6 +1196,12 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
CONFIG_USB_UHCI_HCD=m
# CONFIG_USB_SL811_HCD is not set
# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_WHCI_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+
+#
+# Enable Host or Gadget support to see Inventra options
+#
#
# USB Device Class drivers
@@ -1162,13 +1209,14 @@ CONFIG_USB_UHCI_HCD=m
# CONFIG_USB_ACM is not set
# CONFIG_USB_PRINTER is not set
# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
#
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
#
CONFIG_USB_STORAGE=m
# CONFIG_USB_STORAGE_DEBUG is not set
@@ -1191,7 +1239,6 @@ CONFIG_USB_STORAGE=m
#
# CONFIG_USB_MDC800 is not set
# CONFIG_USB_MICROTEK is not set
-CONFIG_USB_MON=y
#
# USB port drivers
@@ -1204,7 +1251,7 @@ CONFIG_USB_MON=y
# CONFIG_USB_EMI62 is not set
# CONFIG_USB_EMI26 is not set
# CONFIG_USB_ADUTUX is not set
-# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_SEVSEG is not set
# CONFIG_USB_RIO500 is not set
# CONFIG_USB_LEGOTOWER is not set
# CONFIG_USB_LCD is not set
@@ -1222,7 +1269,9 @@ CONFIG_USB_MON=y
# CONFIG_USB_IOWARRIOR is not set
# CONFIG_USB_TEST is not set
# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
+# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
@@ -1246,6 +1295,15 @@ CONFIG_INFINIBAND_IPOIB_DEBUG=y
# CONFIG_RTC_CLASS is not set
# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+CONFIG_STAGING_EXCLUDE_BUILD=y
+
+#
+# HP Simulator drivers
+#
+# CONFIG_HP_SIMETH is not set
+# CONFIG_HP_SIMSERIAL is not set
+# CONFIG_HP_SIMSCSI is not set
CONFIG_MSPEC=m
#
@@ -1260,7 +1318,7 @@ CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y
CONFIG_EXT3_FS_POSIX_ACL=y
CONFIG_EXT3_FS_SECURITY=y
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
CONFIG_JBD=y
CONFIG_FS_MBCACHE=y
CONFIG_REISERFS_FS=y
@@ -1271,6 +1329,7 @@ CONFIG_REISERFS_FS_POSIX_ACL=y
CONFIG_REISERFS_FS_SECURITY=y
# CONFIG_JFS_FS is not set
CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=y
CONFIG_XFS_FS=y
# CONFIG_XFS_QUOTA is not set
# CONFIG_XFS_POSIX_ACL is not set
@@ -1282,8 +1341,8 @@ CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
# CONFIG_QUOTA is not set
-CONFIG_AUTOFS_FS=y
-CONFIG_AUTOFS4_FS=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
# CONFIG_FUSE_FS is not set
#
@@ -1314,6 +1373,7 @@ CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_PROC_VMCORE=y
CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
@@ -1356,6 +1416,7 @@ CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=m
CONFIG_SUNRPC_GSS=m
CONFIG_SUNRPC_XPRT_RDMA=m
+# CONFIG_SUNRPC_REGISTER_V4 is not set
CONFIG_RPCSEC_GSS_KRB5=m
# CONFIG_RPCSEC_GSS_SPKM3 is not set
CONFIG_SMB_FS=m
@@ -1433,38 +1494,6 @@ CONFIG_NLS_KOI8_R=m
CONFIG_NLS_KOI8_U=m
CONFIG_NLS_UTF8=m
# CONFIG_DLM is not set
-CONFIG_HAVE_KVM=y
-CONFIG_VIRTUALIZATION=y
-# CONFIG_KVM is not set
-
-#
-# Library routines
-#
-CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
-# CONFIG_CRC_CCITT is not set
-# CONFIG_CRC16 is not set
-CONFIG_CRC_T10DIF=y
-CONFIG_CRC_ITU_T=m
-CONFIG_CRC32=y
-# CONFIG_CRC7 is not set
-# CONFIG_LIBCRC32C is not set
-CONFIG_GENERIC_ALLOCATOR=y
-CONFIG_PLIST=y
-CONFIG_HAS_IOMEM=y
-CONFIG_HAS_IOPORT=y
-CONFIG_HAS_DMA=y
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
-CONFIG_GENERIC_PENDING_IRQ=y
-CONFIG_IRQ_PER_CPU=y
-
-#
-# HP Simulator drivers
-#
-# CONFIG_HP_SIMETH is not set
-# CONFIG_HP_SIMSERIAL is not set
-# CONFIG_HP_SIMSCSI is not set
#
# Kernel hacking
@@ -1503,8 +1532,19 @@ CONFIG_DEBUG_MEMORY_INIT=y
# CONFIG_DEBUG_SG is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
# CONFIG_FAULT_INJECTION is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+
+#
+# Tracers
+#
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_IA64_GRANULE_16MB=y
# CONFIG_IA64_GRANULE_64MB is not set
@@ -1519,14 +1559,19 @@ CONFIG_SYSVIPC_COMPAT=y
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_CRYPTO=y
#
# Crypto core or helper
#
+# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_AEAD=m
CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=m
+CONFIG_CRYPTO_RNG=m
CONFIG_CRYPTO_MANAGER=m
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
@@ -1599,5 +1644,36 @@ CONFIG_CRYPTO_DES=m
#
# CONFIG_CRYPTO_DEFLATE is not set
# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+CONFIG_HAVE_KVM=y
+CONFIG_VIRTUALIZATION=y
+# CONFIG_KVM is not set
+# CONFIG_VIRTIO_PCI is not set
+# CONFIG_VIRTIO_BALLOON is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=m
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_PENDING_IRQ=y
+CONFIG_IRQ_PER_CPU=y
diff --git a/arch/ia64/hp/sim/Kconfig b/arch/ia64/hp/sim/Kconfig
index f92306bbedb..8d513a8c526 100644
--- a/arch/ia64/hp/sim/Kconfig
+++ b/arch/ia64/hp/sim/Kconfig
@@ -4,6 +4,7 @@ menu "HP Simulator drivers"
config HP_SIMETH
bool "Simulated Ethernet "
+ depends on NET
config HP_SIMSERIAL
bool "Simulated serial driver support"
diff --git a/arch/ia64/include/asm/intrinsics.h b/arch/ia64/include/asm/intrinsics.h
index 47d686dba1e..a3e44a5ed49 100644
--- a/arch/ia64/include/asm/intrinsics.h
+++ b/arch/ia64/include/asm/intrinsics.h
@@ -226,7 +226,7 @@ extern long ia64_cmpxchg_called_with_bad_pointer (void);
/************************************************/
#define ia64_ssm IA64_INTRINSIC_MACRO(ssm)
#define ia64_rsm IA64_INTRINSIC_MACRO(rsm)
-#define ia64_getreg IA64_INTRINSIC_API(getreg)
+#define ia64_getreg IA64_INTRINSIC_MACRO(getreg)
#define ia64_setreg IA64_INTRINSIC_API(setreg)
#define ia64_set_rr IA64_INTRINSIC_API(set_rr)
#define ia64_get_rr IA64_INTRINSIC_API(get_rr)
diff --git a/arch/ia64/include/asm/paravirt_privop.h b/arch/ia64/include/asm/paravirt_privop.h
index d577aac1183..33c8e55f577 100644
--- a/arch/ia64/include/asm/paravirt_privop.h
+++ b/arch/ia64/include/asm/paravirt_privop.h
@@ -78,6 +78,18 @@ extern unsigned long ia64_native_getreg_func(int regnum);
ia64_native_rsm(mask); \
} while (0)
+/* returned ip value should be the one in the caller,
+ * not in __paravirt_getreg() */
+#define paravirt_getreg(reg) \
+ ({ \
+ unsigned long res; \
+ if ((reg) == _IA64_REG_IP) \
+ res = ia64_native_getreg(_IA64_REG_IP); \
+ else \
+ res = pv_cpu_ops.getreg(reg); \
+ res; \
+ })
+
/******************************************************************************
* replacement of hand written assembly codes.
*/
diff --git a/arch/ia64/include/asm/ptrace.h b/arch/ia64/include/asm/ptrace.h
index 6417c1ecb44..14055c636ad 100644
--- a/arch/ia64/include/asm/ptrace.h
+++ b/arch/ia64/include/asm/ptrace.h
@@ -325,8 +325,6 @@ static inline unsigned long user_stack_pointer(struct pt_regs *regs)
#define arch_has_block_step() (1)
extern void user_enable_block_step(struct task_struct *);
-#define __ARCH_WANT_COMPAT_SYS_PTRACE
-
#endif /* !__KERNEL__ */
/* pt_all_user_regs is used for PTRACE_GETREGS PTRACE_SETREGS */
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index 7ef0c594f5e..d435f4a7a96 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -499,6 +499,7 @@ GLOBAL_ENTRY(prefetch_stack)
END(prefetch_stack)
GLOBAL_ENTRY(kernel_execve)
+ rum psr.ac
mov r15=__NR_execve // put syscall number in place
break __BREAK_SYSCALL
br.ret.sptk.many rp
diff --git a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S
index 66e491d8baa..59301c47280 100644
--- a/arch/ia64/kernel/head.S
+++ b/arch/ia64/kernel/head.S
@@ -260,7 +260,7 @@ start_ap:
* Switch into virtual mode:
*/
movl r16=(IA64_PSR_IT|IA64_PSR_IC|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_DFH|IA64_PSR_BN \
- |IA64_PSR_DI)
+ |IA64_PSR_DI|IA64_PSR_AC)
;;
mov cr.ipsr=r16
movl r17=1f
diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
index 7dd96c12717..bab1de2d2f6 100644
--- a/arch/ia64/kernel/mca.c
+++ b/arch/ia64/kernel/mca.c
@@ -1139,7 +1139,7 @@ ia64_mca_modify_original_stack(struct pt_regs *regs,
return previous_current;
no_mod:
- printk(KERN_INFO "cpu %d, %s %s, original stack not modified\n",
+ mprintk(KERN_INFO "cpu %d, %s %s, original stack not modified\n",
smp_processor_id(), type, msg);
return previous_current;
}
diff --git a/arch/ia64/kernel/paravirt.c b/arch/ia64/kernel/paravirt.c
index de35d8e8b7d..9f14c16f636 100644
--- a/arch/ia64/kernel/paravirt.c
+++ b/arch/ia64/kernel/paravirt.c
@@ -130,7 +130,7 @@ ia64_native_getreg_func(int regnum)
unsigned long res = -1;
switch (regnum) {
CASE_GET_REG(GP);
- CASE_GET_REG(IP);
+ /*CASE_GET_REG(IP);*/ /* returned ip value shouldn't be constant */
CASE_GET_REG(PSR);
CASE_GET_REG(TP);
CASE_GET_REG(SP);
diff --git a/arch/ia64/kernel/pci-dma.c b/arch/ia64/kernel/pci-dma.c
index dbdb778efa0..2a92f637431 100644
--- a/arch/ia64/kernel/pci-dma.c
+++ b/arch/ia64/kernel/pci-dma.c
@@ -19,7 +19,6 @@
#include <linux/kernel.h>
#include <asm/page.h>
-#include <asm/iommu.h>
dma_addr_t bad_dma_address __read_mostly;
EXPORT_SYMBOL(bad_dma_address);
diff --git a/arch/ia64/kernel/topology.c b/arch/ia64/kernel/topology.c
index 26228e2d01a..c75b914f2d6 100644
--- a/arch/ia64/kernel/topology.c
+++ b/arch/ia64/kernel/topology.c
@@ -53,10 +53,12 @@ int __ref arch_register_cpu(int num)
}
EXPORT_SYMBOL(arch_register_cpu);
-void arch_unregister_cpu(int num)
+void __ref arch_unregister_cpu(int num)
{
unregister_cpu(&sysfs_cpus[num].cpu);
+#ifdef CONFIG_ACPI
unmap_cpu_from_node(num, cpu_to_node(num));
+#endif
}
EXPORT_SYMBOL(arch_unregister_cpu);
#else
diff --git a/arch/ia64/kvm/Kconfig b/arch/ia64/kvm/Kconfig
index 8e99fed6b3f..f833a0b4188 100644
--- a/arch/ia64/kvm/Kconfig
+++ b/arch/ia64/kvm/Kconfig
@@ -20,6 +20,8 @@ if VIRTUALIZATION
config KVM
tristate "Kernel-based Virtual Machine (KVM) support"
depends on HAVE_KVM && EXPERIMENTAL
+ # for device assignment:
+ depends on PCI
select PREEMPT_NOTIFIERS
select ANON_INODES
---help---
diff --git a/arch/ia64/kvm/Makefile b/arch/ia64/kvm/Makefile
index 3ab4d6d5070..92cef66ca26 100644
--- a/arch/ia64/kvm/Makefile
+++ b/arch/ia64/kvm/Makefile
@@ -58,7 +58,7 @@ endif
kvm-objs := $(common-objs) kvm-ia64.o kvm_fw.o
obj-$(CONFIG_KVM) += kvm.o
-EXTRA_CFLAGS_vcpu.o += -mfixed-range=f2-f5,f12-f127
+CFLAGS_vcpu.o += -mfixed-range=f2-f5,f12-f127
kvm-intel-objs = vmm.o vmm_ivt.o trampoline.o vcpu.o optvfault.o mmio.o \
vtlb.o process.o
#Add link memcpy and memset to avoid possible structure assignment error
diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c
index 3caac477de9..af1464f7a6a 100644
--- a/arch/ia64/kvm/kvm-ia64.c
+++ b/arch/ia64/kvm/kvm-ia64.c
@@ -673,16 +673,16 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
vcpu_load(vcpu);
+ if (vcpu->sigset_active)
+ sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved);
+
if (unlikely(vcpu->arch.mp_state == KVM_MP_STATE_UNINITIALIZED)) {
kvm_vcpu_block(vcpu);
clear_bit(KVM_REQ_UNHALT, &vcpu->requests);
- vcpu_put(vcpu);
- return -EAGAIN;
+ r = -EAGAIN;
+ goto out;
}
- if (vcpu->sigset_active)
- sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved);
-
if (vcpu->mmio_needed) {
memcpy(vcpu->mmio_data, kvm_run->mmio.data, 8);
kvm_set_mmio_data(vcpu);
@@ -690,7 +690,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
vcpu->mmio_needed = 0;
}
r = __vcpu_run(vcpu, kvm_run);
-
+out:
if (vcpu->sigset_active)
sigprocmask(SIG_SETMASK, &sigsaved, NULL);
diff --git a/arch/ia64/kvm/optvfault.S b/arch/ia64/kvm/optvfault.S
index 634abad979b..32254ce9a1b 100644
--- a/arch/ia64/kvm/optvfault.S
+++ b/arch/ia64/kvm/optvfault.S
@@ -107,10 +107,10 @@ END(kvm_vps_resume_normal)
GLOBAL_ENTRY(kvm_vps_resume_handler)
movl r30 = PAL_VPS_RESUME_HANDLER
;;
- ld8 r27=[r25]
+ ld8 r26=[r25]
shr r17=r17,IA64_ISR_IR_BIT
;;
- dep r27=r17,r27,63,1 // bit 63 of r27 indicate whether enable CFLE
+ dep r26=r17,r26,63,1 // bit 63 of r26 indicate whether enable CFLE
mov pr=r23,-2
br.sptk.many kvm_vps_entry
END(kvm_vps_resume_handler)
@@ -894,12 +894,15 @@ ENTRY(kvm_resume_to_guest)
;;
ld8 r19=[r19]
mov b0=r29
- cmp.ne p6,p7 = r0,r0
+ mov r27=cr.isr
;;
- tbit.z p6,p7 = r19,IA64_PSR_IC_BIT // p1=vpsr.ic
+ tbit.z p6,p7 = r19,IA64_PSR_IC_BIT // p7=vpsr.ic
+ shr r27=r27,IA64_ISR_IR_BIT
;;
(p6) ld8 r26=[r25]
(p7) mov b0=r28
+ ;;
+ (p6) dep r26=r27,r26,63,1
mov pr=r31,-2
br.sptk.many b0 // call pal service
;;
diff --git a/arch/ia64/kvm/vcpu.h b/arch/ia64/kvm/vcpu.h
index 341e3fee280..e9b2a4e121c 100644
--- a/arch/ia64/kvm/vcpu.h
+++ b/arch/ia64/kvm/vcpu.h
@@ -384,6 +384,10 @@ static inline u64 __gpfn_is_io(u64 gpfn)
#define MODE_IND(psr) \
(((psr).it << 2) + ((psr).dt << 1) + (psr).rt)
+#ifndef CONFIG_SMP
+#define _vmm_raw_spin_lock(x) do {}while(0)
+#define _vmm_raw_spin_unlock(x) do {}while(0)
+#else
#define _vmm_raw_spin_lock(x) \
do { \
__u32 *ia64_spinlock_ptr = (__u32 *) (x); \
@@ -403,6 +407,7 @@ static inline u64 __gpfn_is_io(u64 gpfn)
do { barrier(); \
((spinlock_t *)x)->raw_lock.lock = 0; } \
while (0)
+#endif
void vmm_spin_lock(spinlock_t *lock);
void vmm_spin_unlock(spinlock_t *lock);
diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c
index c3aa851d1ca..4e1801bad83 100644
--- a/arch/ia64/sn/kernel/io_init.c
+++ b/arch/ia64/sn/kernel/io_init.c
@@ -292,7 +292,7 @@ EXPORT_SYMBOL(sn_io_slot_fixup);
* sn_pci_controller_fixup() - This routine sets up a bus's resources
* consistent with the Linux PCI abstraction layer.
*/
-static void
+static void __init
sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus)
{
s64 status = 0;
diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c
index 96c31b4180c..0c66dbdd1d7 100644
--- a/arch/ia64/sn/kernel/irq.c
+++ b/arch/ia64/sn/kernel/irq.c
@@ -5,7 +5,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (c) 2000-2007 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2000-2008 Silicon Graphics, Inc. All Rights Reserved.
*/
#include <linux/irq.h>
@@ -375,6 +375,7 @@ void sn_irq_fixup(struct pci_dev *pci_dev, struct sn_irq_info *sn_irq_info)
int cpu = nasid_slice_to_cpuid(nasid, slice);
#ifdef CONFIG_SMP
int cpuphys;
+ irq_desc_t *desc;
#endif
pci_dev_get(pci_dev);
@@ -391,6 +392,12 @@ void sn_irq_fixup(struct pci_dev *pci_dev, struct sn_irq_info *sn_irq_info)
#ifdef CONFIG_SMP
cpuphys = cpu_physical_id(cpu);
set_irq_affinity_info(sn_irq_info->irq_irq, cpuphys, 0);
+ desc = irq_to_desc(sn_irq_info->irq_irq);
+ /*
+ * Affinity was set by the PROM, prevent it from
+ * being reset by the request_irq() path.
+ */
+ desc->status |= IRQ_AFFINITY_SET;
#endif
}
diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c
index bb1d2492964..02c5b8a9fb6 100644
--- a/arch/ia64/sn/kernel/setup.c
+++ b/arch/ia64/sn/kernel/setup.c
@@ -200,7 +200,7 @@ static int __cpuinitdata shub_1_1_found;
* Set flag for enabling shub specific wars
*/
-static inline int __init is_shub_1_1(int nasid)
+static inline int __cpuinit is_shub_1_1(int nasid)
{
unsigned long id;
int rev;
@@ -212,7 +212,7 @@ static inline int __init is_shub_1_1(int nasid)
return rev <= 2;
}
-static void __init sn_check_for_wars(void)
+static void __cpuinit sn_check_for_wars(void)
{
int cnode;
@@ -512,7 +512,6 @@ static void __init sn_init_pdas(char **cmdline_p)
for_each_online_node(cnode) {
nodepdaindr[cnode] =
alloc_bootmem_node(NODE_DATA(cnode), sizeof(nodepda_t));
- memset(nodepdaindr[cnode], 0, sizeof(nodepda_t));
memset(nodepdaindr[cnode]->phys_cpuid, -1,
sizeof(nodepdaindr[cnode]->phys_cpuid));
spin_lock_init(&nodepdaindr[cnode]->ptc_lock);
@@ -521,11 +520,9 @@ static void __init sn_init_pdas(char **cmdline_p)
/*
* Allocate & initialize nodepda for TIOs. For now, put them on node 0.
*/
- for (cnode = num_online_nodes(); cnode < num_cnodes; cnode++) {
+ for (cnode = num_online_nodes(); cnode < num_cnodes; cnode++)
nodepdaindr[cnode] =
alloc_bootmem_node(NODE_DATA(0), sizeof(nodepda_t));
- memset(nodepdaindr[cnode], 0, sizeof(nodepda_t));
- }
/*
* Now copy the array of nodepda pointers to each nodepda.
diff --git a/arch/ia64/xen/hypercall.S b/arch/ia64/xen/hypercall.S
index d4ff0b9e79f..45e02bb64a9 100644
--- a/arch/ia64/xen/hypercall.S
+++ b/arch/ia64/xen/hypercall.S
@@ -58,7 +58,7 @@ __HCALL2(xen_set_rr, HYPERPRIVOP_SET_RR)
__HCALL2(xen_set_kr, HYPERPRIVOP_SET_KR)
#ifdef CONFIG_IA32_SUPPORT
-__HCALL1(xen_get_eflag, HYPERPRIVOP_GET_EFLAG)
+__HCALL0(xen_get_eflag, HYPERPRIVOP_GET_EFLAG)
__HCALL1(xen_set_eflag, HYPERPRIVOP_SET_EFLAG) // refer SDM vol1 3.1.8
#endif /* CONFIG_IA32_SUPPORT */
diff --git a/arch/m32r/kernel/head.S b/arch/m32r/kernel/head.S
index 40180778a5c..90916067b9c 100644
--- a/arch/m32r/kernel/head.S
+++ b/arch/m32r/kernel/head.S
@@ -23,7 +23,7 @@ __INITDATA
/*
* References to members of the boot_cpu_data structure.
*/
- .text
+.section .text.head, "ax"
.global start_kernel
.global __bss_start
.global _end
@@ -133,7 +133,6 @@ loop1:
/*
* AP startup routine
*/
- .text
.global eit_vector
ENTRY(startup_AP)
;; setup EVB
@@ -230,6 +229,7 @@ ENTRY(startup_AP)
nop
#endif /* CONFIG_SMP */
+ .text
ENTRY(stack_start)
.long init_thread_union+8192
.long __KERNEL_DS
diff --git a/arch/m32r/kernel/vmlinux.lds.S b/arch/m32r/kernel/vmlinux.lds.S
index 15a6f36c06d..9db05df20c0 100644
--- a/arch/m32r/kernel/vmlinux.lds.S
+++ b/arch/m32r/kernel/vmlinux.lds.S
@@ -27,6 +27,7 @@ SECTIONS
_text = .; /* Text and read-only data */
.boot : { *(.boot) } = 0
.text : {
+ *(.text.head)
TEXT_TEXT
SCHED_TEXT
LOCK_TEXT
diff --git a/arch/m68k/configs/amiga_defconfig b/arch/m68k/configs/amiga_defconfig
index 8bd61a640fc..23597beb66c 100644
--- a/arch/m68k/configs/amiga_defconfig
+++ b/arch/m68k/configs/amiga_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27-rc6
-# Wed Sep 10 09:02:00 2008
+# Linux kernel version: 2.6.28-rc7
+# Tue Dec 2 20:27:42 2008
#
CONFIG_M68K=y
CONFIG_MMU=y
@@ -14,7 +14,6 @@ CONFIG_TIME_LOW_RES=y
CONFIG_GENERIC_IOMAP=y
CONFIG_NO_IOPORT=y
# CONFIG_NO_DMA is not set
-CONFIG_ARCH_SUPPORTS_AOUT=y
CONFIG_HZ=100
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -67,22 +66,13 @@ CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
# CONFIG_MARKERS is not set
-# CONFIG_HAVE_OPROFILE is not set
-# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set
-# CONFIG_HAVE_IOREMAP_PROT is not set
-# CONFIG_HAVE_KPROBES is not set
-# CONFIG_HAVE_KRETPROBES is not set
-# CONFIG_HAVE_ARCH_TRACEHOOK is not set
-# CONFIG_HAVE_DMA_ATTRS is not set
-# CONFIG_USE_GENERIC_SMP_HELPERS is not set
-# CONFIG_HAVE_CLK is not set
-CONFIG_PROC_PAGE_MONITOR=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -115,11 +105,11 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_FREEZER is not set
#
# Platform dependent setup
#
-# CONFIG_SUN3 is not set
CONFIG_AMIGA=y
# CONFIG_ATARI is not set
# CONFIG_MAC is not set
@@ -148,19 +138,21 @@ CONFIG_DISCONTIGMEM_MANUAL=y
CONFIG_DISCONTIGMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_NEED_MULTIPLE_NODES=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
#
# General setup
#
CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
CONFIG_BINFMT_AOUT=m
CONFIG_BINFMT_MISC=m
CONFIG_ZORRO=y
@@ -212,7 +204,6 @@ CONFIG_INET_TCP_DIAG=m
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
-# CONFIG_IP_VS is not set
CONFIG_IPV6=m
CONFIG_IPV6_PRIVACY=y
CONFIG_IPV6_ROUTER_PREF=y
@@ -262,13 +253,14 @@ CONFIG_NF_CONNTRACK_SANE=m
CONFIG_NF_CONNTRACK_SIP=m
CONFIG_NF_CONNTRACK_TFTP=m
# CONFIG_NF_CT_NETLINK is not set
+# CONFIG_NETFILTER_TPROXY is not set
CONFIG_NETFILTER_XTABLES=m
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
CONFIG_NETFILTER_XT_TARGET_DSCP=m
CONFIG_NETFILTER_XT_TARGET_MARK=m
-CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
CONFIG_NETFILTER_XT_TARGET_RATEEST=m
CONFIG_NETFILTER_XT_TARGET_TRACE=m
@@ -282,19 +274,22 @@ CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
CONFIG_NETFILTER_XT_MATCH_DCCP=m
CONFIG_NETFILTER_XT_MATCH_DSCP=m
CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
CONFIG_NETFILTER_XT_MATCH_HELPER=m
CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
CONFIG_NETFILTER_XT_MATCH_MAC=m
CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_OWNER=m
CONFIG_NETFILTER_XT_MATCH_POLICY=m
-CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_QUOTA=m
CONFIG_NETFILTER_XT_MATCH_RATEEST=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_RECENT=m
+# CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT is not set
CONFIG_NETFILTER_XT_MATCH_SCTP=m
CONFIG_NETFILTER_XT_MATCH_STATE=m
CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
@@ -302,20 +297,20 @@ CONFIG_NETFILTER_XT_MATCH_STRING=m
CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
CONFIG_NETFILTER_XT_MATCH_TIME=m
CONFIG_NETFILTER_XT_MATCH_U32=m
-CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+# CONFIG_IP_VS is not set
#
# IP: Netfilter Configuration
#
+CONFIG_NF_DEFRAG_IPV4=m
CONFIG_NF_CONNTRACK_IPV4=m
CONFIG_NF_CONNTRACK_PROC_COMPAT=y
CONFIG_IP_NF_QUEUE=m
CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_RECENT=m
-CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IP_NF_TARGET_LOG=m
@@ -323,8 +318,8 @@ CONFIG_IP_NF_TARGET_ULOG=m
CONFIG_NF_NAT=m
CONFIG_NF_NAT_NEEDED=y
CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
CONFIG_NF_NAT_SNMP_BASIC=m
CONFIG_NF_NAT_PROTO_GRE=m
CONFIG_NF_NAT_PROTO_UDPLITE=m
@@ -337,9 +332,9 @@ CONFIG_NF_NAT_PPTP=m
CONFIG_NF_NAT_H323=m
CONFIG_NF_NAT_SIP=m
CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
CONFIG_IP_NF_TARGET_ECN=m
CONFIG_IP_NF_TARGET_TTL=m
-CONFIG_IP_NF_TARGET_CLUSTERIP=m
CONFIG_IP_NF_RAW=m
CONFIG_IP_NF_ARPTABLES=m
CONFIG_IP_NF_ARPFILTER=m
@@ -351,16 +346,16 @@ CONFIG_IP_NF_ARP_MANGLE=m
CONFIG_NF_CONNTRACK_IPV6=m
CONFIG_IP6_NF_QUEUE=m
CONFIG_IP6_NF_IPTABLES=m
-CONFIG_IP6_NF_MATCH_RT=m
-CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
CONFIG_IP6_NF_MATCH_HL=m
CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-CONFIG_IP6_NF_MATCH_AH=m
CONFIG_IP6_NF_MATCH_MH=m
-CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_MATCH_RT=m
CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_FILTER=m
CONFIG_IP6_NF_TARGET_REJECT=m
CONFIG_IP6_NF_MANGLE=m
CONFIG_IP6_NF_TARGET_HL=m
@@ -387,6 +382,7 @@ CONFIG_SCTP_HMAC_MD5=y
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
CONFIG_LLC=m
@@ -410,19 +406,8 @@ CONFIG_NET_CLS_ROUTE=y
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
-# CONFIG_CFG80211 is not set
-CONFIG_WIRELESS_EXT=y
-# CONFIG_WIRELESS_EXT_SYSFS is not set
-# CONFIG_MAC80211 is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
-CONFIG_IEEE80211_CRYPT_TKIP=m
+# CONFIG_PHONET is not set
+# CONFIG_WIRELESS is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -470,21 +455,20 @@ CONFIG_ATA_OVER_ETH=m
CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
CONFIG_IDE=y
-CONFIG_BLK_DEV_IDE=y
#
# Please see Documentation/ide/ide.txt for help/info on IDE drives
#
-CONFIG_IDE_ATAPI=y
# CONFIG_BLK_DEV_IDE_SATA is not set
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_IDE_GD=y
+CONFIG_IDE_GD_ATA=y
+# CONFIG_IDE_GD_ATAPI is not set
CONFIG_BLK_DEV_IDECD=y
CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y
# CONFIG_BLK_DEV_IDETAPE is not set
-CONFIG_BLK_DEV_IDEFLOPPY=m
# CONFIG_BLK_DEV_IDESCSI is not set
# CONFIG_IDE_TASK_IOCTL is not set
CONFIG_IDE_PROC_FS=y
@@ -609,8 +593,12 @@ CONFIG_APNE=m
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
# CONFIG_NET_PCI is not set
# CONFIG_B44 is not set
+# CONFIG_CS89x0 is not set
# CONFIG_NET_POCKET is not set
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
@@ -763,11 +751,11 @@ CONFIG_GEN_RTC_X=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -777,6 +765,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -802,6 +791,7 @@ CONFIG_SSB_POSSIBLE=y
CONFIG_FB=y
# CONFIG_FIRMWARE_EDID is not set
# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
@@ -829,6 +819,8 @@ CONFIG_FB_FM2=y
# CONFIG_FB_UVESA is not set
# CONFIG_FB_S1D13XXX is not set
# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
@@ -852,12 +844,19 @@ CONFIG_LOGO_LINUX_MONO=y
CONFIG_LOGO_LINUX_VGA16=y
CONFIG_LOGO_LINUX_CLUT224=y
CONFIG_SOUND=m
+CONFIG_SOUND_OSS_CORE=y
CONFIG_DMASOUND_PAULA=m
CONFIG_DMASOUND=m
CONFIG_HID_SUPPORT=y
CONFIG_HID=m
# CONFIG_HID_DEBUG is not set
CONFIG_HIDRAW=y
+# CONFIG_HID_PID is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
# CONFIG_USB_SUPPORT is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -867,6 +866,8 @@ CONFIG_HIDRAW=y
# CONFIG_DMADEVICES is not set
# CONFIG_AUXDISPLAY is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+CONFIG_STAGING_EXCLUDE_BUILD=y
#
# Character devices
@@ -883,8 +884,9 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
# CONFIG_EXT3_FS_XATTR is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
CONFIG_JBD=y
+CONFIG_JBD2=m
CONFIG_REISERFS_FS=m
# CONFIG_REISERFS_CHECK is not set
# CONFIG_REISERFS_PROC_INFO is not set
@@ -895,6 +897,7 @@ CONFIG_JFS_FS=m
# CONFIG_JFS_DEBUG is not set
# CONFIG_JFS_STATISTICS is not set
# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
CONFIG_XFS_FS=m
# CONFIG_XFS_QUOTA is not set
# CONFIG_XFS_POSIX_ACL is not set
@@ -906,6 +909,7 @@ CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
# CONFIG_OCFS2_FS_STATS is not set
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
# CONFIG_OCFS2_DEBUG_FS is not set
+# CONFIG_OCFS2_COMPAT_JBD is not set
CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
@@ -944,6 +948,7 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
@@ -986,6 +991,7 @@ CONFIG_EXPORTFS=m
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=m
CONFIG_SUNRPC_GSS=m
+# CONFIG_SUNRPC_REGISTER_V4 is not set
CONFIG_RPCSEC_GSS_KRB5=m
# CONFIG_RPCSEC_GSS_SPKM3 is not set
CONFIG_SMB_FS=m
@@ -1059,7 +1065,13 @@ CONFIG_MAGIC_SYSRQ=y
# CONFIG_DEBUG_KERNEL is not set
CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
+
+#
+# Tracers
+#
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
#
@@ -1067,6 +1079,7 @@ CONFIG_SYSCTL_SYSCALL_CHECK=y
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_XOR_BLOCKS=m
CONFIG_ASYNC_CORE=m
@@ -1077,10 +1090,12 @@ CONFIG_CRYPTO=y
#
# Crypto core or helper
#
+# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=m
-CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_BLKCIPHER=y
CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_RNG=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_GF128MUL=m
CONFIG_CRYPTO_NULL=m
@@ -1154,14 +1169,17 @@ CONFIG_CRYPTO_TWOFISH_COMMON=m
#
CONFIG_CRYPTO_DEFLATE=m
CONFIG_CRYPTO_LZO=m
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
# CONFIG_CRYPTO_HW is not set
#
# Library routines
#
CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
-# CONFIG_GENERIC_FIND_NEXT_BIT is not set
CONFIG_CRC_CCITT=m
CONFIG_CRC16=m
CONFIG_CRC_T10DIF=y
diff --git a/arch/m68k/configs/apollo_defconfig b/arch/m68k/configs/apollo_defconfig
index c41b854c028..935108d115a 100644
--- a/arch/m68k/configs/apollo_defconfig
+++ b/arch/m68k/configs/apollo_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27-rc6
-# Wed Sep 10 09:02:01 2008
+# Linux kernel version: 2.6.28-rc7
+# Tue Dec 2 20:27:43 2008
#
CONFIG_M68K=y
CONFIG_MMU=y
@@ -14,7 +14,6 @@ CONFIG_TIME_LOW_RES=y
CONFIG_GENERIC_IOMAP=y
CONFIG_NO_IOPORT=y
# CONFIG_NO_DMA is not set
-CONFIG_ARCH_SUPPORTS_AOUT=y
CONFIG_HZ=100
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -67,22 +66,13 @@ CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
# CONFIG_MARKERS is not set
-# CONFIG_HAVE_OPROFILE is not set
-# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set
-# CONFIG_HAVE_IOREMAP_PROT is not set
-# CONFIG_HAVE_KPROBES is not set
-# CONFIG_HAVE_KRETPROBES is not set
-# CONFIG_HAVE_ARCH_TRACEHOOK is not set
-# CONFIG_HAVE_DMA_ATTRS is not set
-# CONFIG_USE_GENERIC_SMP_HELPERS is not set
-# CONFIG_HAVE_CLK is not set
-CONFIG_PROC_PAGE_MONITOR=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -115,11 +105,11 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_FREEZER is not set
#
# Platform dependent setup
#
-# CONFIG_SUN3 is not set
# CONFIG_AMIGA is not set
# CONFIG_ATARI is not set
# CONFIG_MAC is not set
@@ -148,19 +138,21 @@ CONFIG_DISCONTIGMEM_MANUAL=y
CONFIG_DISCONTIGMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_NEED_MULTIPLE_NODES=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
#
# General setup
#
CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
CONFIG_BINFMT_AOUT=m
CONFIG_BINFMT_MISC=m
CONFIG_HEARTBEAT=y
@@ -210,7 +202,6 @@ CONFIG_INET_TCP_DIAG=m
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
-# CONFIG_IP_VS is not set
CONFIG_IPV6=m
CONFIG_IPV6_PRIVACY=y
CONFIG_IPV6_ROUTER_PREF=y
@@ -260,13 +251,14 @@ CONFIG_NF_CONNTRACK_SANE=m
CONFIG_NF_CONNTRACK_SIP=m
CONFIG_NF_CONNTRACK_TFTP=m
# CONFIG_NF_CT_NETLINK is not set
+# CONFIG_NETFILTER_TPROXY is not set
CONFIG_NETFILTER_XTABLES=m
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
CONFIG_NETFILTER_XT_TARGET_DSCP=m
CONFIG_NETFILTER_XT_TARGET_MARK=m
-CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
CONFIG_NETFILTER_XT_TARGET_RATEEST=m
CONFIG_NETFILTER_XT_TARGET_TRACE=m
@@ -280,19 +272,22 @@ CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
CONFIG_NETFILTER_XT_MATCH_DCCP=m
CONFIG_NETFILTER_XT_MATCH_DSCP=m
CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
CONFIG_NETFILTER_XT_MATCH_HELPER=m
CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
CONFIG_NETFILTER_XT_MATCH_MAC=m
CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_OWNER=m
CONFIG_NETFILTER_XT_MATCH_POLICY=m
-CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_QUOTA=m
CONFIG_NETFILTER_XT_MATCH_RATEEST=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_RECENT=m
+# CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT is not set
CONFIG_NETFILTER_XT_MATCH_SCTP=m
CONFIG_NETFILTER_XT_MATCH_STATE=m
CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
@@ -300,20 +295,20 @@ CONFIG_NETFILTER_XT_MATCH_STRING=m
CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
CONFIG_NETFILTER_XT_MATCH_TIME=m
CONFIG_NETFILTER_XT_MATCH_U32=m
-CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+# CONFIG_IP_VS is not set
#
# IP: Netfilter Configuration
#
+CONFIG_NF_DEFRAG_IPV4=m
CONFIG_NF_CONNTRACK_IPV4=m
CONFIG_NF_CONNTRACK_PROC_COMPAT=y
CONFIG_IP_NF_QUEUE=m
CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_RECENT=m
-CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IP_NF_TARGET_LOG=m
@@ -321,8 +316,8 @@ CONFIG_IP_NF_TARGET_ULOG=m
CONFIG_NF_NAT=m
CONFIG_NF_NAT_NEEDED=y
CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
CONFIG_NF_NAT_SNMP_BASIC=m
CONFIG_NF_NAT_PROTO_GRE=m
CONFIG_NF_NAT_PROTO_UDPLITE=m
@@ -335,9 +330,9 @@ CONFIG_NF_NAT_PPTP=m
CONFIG_NF_NAT_H323=m
CONFIG_NF_NAT_SIP=m
CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
CONFIG_IP_NF_TARGET_ECN=m
CONFIG_IP_NF_TARGET_TTL=m
-CONFIG_IP_NF_TARGET_CLUSTERIP=m
CONFIG_IP_NF_RAW=m
CONFIG_IP_NF_ARPTABLES=m
CONFIG_IP_NF_ARPFILTER=m
@@ -349,16 +344,16 @@ CONFIG_IP_NF_ARP_MANGLE=m
CONFIG_NF_CONNTRACK_IPV6=m
CONFIG_IP6_NF_QUEUE=m
CONFIG_IP6_NF_IPTABLES=m
-CONFIG_IP6_NF_MATCH_RT=m
-CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
CONFIG_IP6_NF_MATCH_HL=m
CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-CONFIG_IP6_NF_MATCH_AH=m
CONFIG_IP6_NF_MATCH_MH=m
-CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_MATCH_RT=m
CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_FILTER=m
CONFIG_IP6_NF_TARGET_REJECT=m
CONFIG_IP6_NF_MANGLE=m
CONFIG_IP6_NF_TARGET_HL=m
@@ -385,6 +380,7 @@ CONFIG_SCTP_HMAC_MD5=y
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
CONFIG_LLC=m
@@ -408,19 +404,8 @@ CONFIG_NET_CLS_ROUTE=y
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
-# CONFIG_CFG80211 is not set
-CONFIG_WIRELESS_EXT=y
-# CONFIG_WIRELESS_EXT_SYSFS is not set
-# CONFIG_MAC80211 is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
-CONFIG_IEEE80211_CRYPT_TKIP=m
+# CONFIG_PHONET is not set
+# CONFIG_WIRELESS is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -458,6 +443,7 @@ CONFIG_ATA_OVER_ETH=m
CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -540,6 +526,9 @@ CONFIG_NET_ETHERNET=y
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
# CONFIG_B44 is not set
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
@@ -609,6 +598,7 @@ CONFIG_MOUSE_PS2_LOGIPS2PP=y
CONFIG_MOUSE_PS2_SYNAPTICS=y
CONFIG_MOUSE_PS2_LIFEBOOK=y
CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
# CONFIG_MOUSE_PS2_TOUCHKIT is not set
CONFIG_MOUSE_SERIAL=m
# CONFIG_MOUSE_VSXXXAA is not set
@@ -663,11 +653,11 @@ CONFIG_GEN_RTC_X=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -677,6 +667,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -702,6 +693,7 @@ CONFIG_SSB_POSSIBLE=y
CONFIG_FB=y
# CONFIG_FIRMWARE_EDID is not set
# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
CONFIG_FB_CFB_FILLRECT=y
# CONFIG_FB_CFB_COPYAREA is not set
CONFIG_FB_CFB_IMAGEBLIT=y
@@ -724,6 +716,8 @@ CONFIG_FB_APOLLO=y
# CONFIG_FB_UVESA is not set
# CONFIG_FB_S1D13XXX is not set
# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
@@ -750,6 +744,12 @@ CONFIG_HID_SUPPORT=y
CONFIG_HID=m
# CONFIG_HID_DEBUG is not set
CONFIG_HIDRAW=y
+# CONFIG_HID_PID is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
# CONFIG_USB_SUPPORT is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -758,6 +758,8 @@ CONFIG_HIDRAW=y
# CONFIG_RTC_CLASS is not set
# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+CONFIG_STAGING_EXCLUDE_BUILD=y
#
# Character devices
@@ -773,8 +775,9 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
# CONFIG_EXT3_FS_XATTR is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
CONFIG_JBD=y
+CONFIG_JBD2=m
CONFIG_REISERFS_FS=m
# CONFIG_REISERFS_CHECK is not set
# CONFIG_REISERFS_PROC_INFO is not set
@@ -785,6 +788,7 @@ CONFIG_JFS_FS=m
# CONFIG_JFS_DEBUG is not set
# CONFIG_JFS_STATISTICS is not set
# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
CONFIG_XFS_FS=m
# CONFIG_XFS_QUOTA is not set
# CONFIG_XFS_POSIX_ACL is not set
@@ -796,6 +800,7 @@ CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
# CONFIG_OCFS2_FS_STATS is not set
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
# CONFIG_OCFS2_DEBUG_FS is not set
+# CONFIG_OCFS2_COMPAT_JBD is not set
CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
@@ -834,6 +839,7 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
@@ -877,6 +883,7 @@ CONFIG_EXPORTFS=m
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_REGISTER_V4 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
CONFIG_SMB_FS=m
@@ -949,7 +956,13 @@ CONFIG_MAGIC_SYSRQ=y
# CONFIG_DEBUG_KERNEL is not set
CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
+
+#
+# Tracers
+#
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
#
@@ -957,6 +970,7 @@ CONFIG_SYSCTL_SYSCALL_CHECK=y
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_XOR_BLOCKS=m
CONFIG_ASYNC_CORE=m
@@ -967,10 +981,12 @@ CONFIG_CRYPTO=y
#
# Crypto core or helper
#
+# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD=y
CONFIG_CRYPTO_BLKCIPHER=y
CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_RNG=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_GF128MUL=m
CONFIG_CRYPTO_NULL=m
@@ -1044,14 +1060,17 @@ CONFIG_CRYPTO_TWOFISH_COMMON=m
#
CONFIG_CRYPTO_DEFLATE=m
CONFIG_CRYPTO_LZO=m
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
# CONFIG_CRYPTO_HW is not set
#
# Library routines
#
CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
-# CONFIG_GENERIC_FIND_NEXT_BIT is not set
CONFIG_CRC_CCITT=m
CONFIG_CRC16=m
CONFIG_CRC_T10DIF=y
diff --git a/arch/m68k/configs/atari_defconfig b/arch/m68k/configs/atari_defconfig
index 654c5acb9e8..a594a1d47b6 100644
--- a/arch/m68k/configs/atari_defconfig
+++ b/arch/m68k/configs/atari_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27-rc6
-# Wed Sep 10 09:02:02 2008
+# Linux kernel version: 2.6.28-rc7
+# Tue Dec 2 20:27:44 2008
#
CONFIG_M68K=y
CONFIG_MMU=y
@@ -14,7 +14,6 @@ CONFIG_TIME_LOW_RES=y
CONFIG_GENERIC_IOMAP=y
CONFIG_NO_IOPORT=y
# CONFIG_NO_DMA is not set
-CONFIG_ARCH_SUPPORTS_AOUT=y
CONFIG_HZ=100
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -67,22 +66,13 @@ CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
# CONFIG_MARKERS is not set
-# CONFIG_HAVE_OPROFILE is not set
-# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set
-# CONFIG_HAVE_IOREMAP_PROT is not set
-# CONFIG_HAVE_KPROBES is not set
-# CONFIG_HAVE_KRETPROBES is not set
-# CONFIG_HAVE_ARCH_TRACEHOOK is not set
-# CONFIG_HAVE_DMA_ATTRS is not set
-# CONFIG_USE_GENERIC_SMP_HELPERS is not set
-# CONFIG_HAVE_CLK is not set
-CONFIG_PROC_PAGE_MONITOR=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -115,11 +105,11 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_FREEZER is not set
#
# Platform dependent setup
#
-# CONFIG_SUN3 is not set
# CONFIG_AMIGA is not set
CONFIG_ATARI=y
# CONFIG_MAC is not set
@@ -148,19 +138,21 @@ CONFIG_DISCONTIGMEM_MANUAL=y
CONFIG_DISCONTIGMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_NEED_MULTIPLE_NODES=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
#
# General setup
#
CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
CONFIG_BINFMT_AOUT=m
CONFIG_BINFMT_MISC=m
CONFIG_STRAM_PROC=y
@@ -208,7 +200,6 @@ CONFIG_INET_TCP_DIAG=m
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
-# CONFIG_IP_VS is not set
CONFIG_IPV6=m
CONFIG_IPV6_PRIVACY=y
CONFIG_IPV6_ROUTER_PREF=y
@@ -258,13 +249,14 @@ CONFIG_NF_CONNTRACK_SANE=m
CONFIG_NF_CONNTRACK_SIP=m
CONFIG_NF_CONNTRACK_TFTP=m
# CONFIG_NF_CT_NETLINK is not set
+# CONFIG_NETFILTER_TPROXY is not set
CONFIG_NETFILTER_XTABLES=m
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
CONFIG_NETFILTER_XT_TARGET_DSCP=m
CONFIG_NETFILTER_XT_TARGET_MARK=m
-CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
CONFIG_NETFILTER_XT_TARGET_RATEEST=m
CONFIG_NETFILTER_XT_TARGET_TRACE=m
@@ -278,19 +270,22 @@ CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
CONFIG_NETFILTER_XT_MATCH_DCCP=m
CONFIG_NETFILTER_XT_MATCH_DSCP=m
CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
CONFIG_NETFILTER_XT_MATCH_HELPER=m
CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
CONFIG_NETFILTER_XT_MATCH_MAC=m
CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_OWNER=m
CONFIG_NETFILTER_XT_MATCH_POLICY=m
-CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_QUOTA=m
CONFIG_NETFILTER_XT_MATCH_RATEEST=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_RECENT=m
+# CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT is not set
CONFIG_NETFILTER_XT_MATCH_SCTP=m
CONFIG_NETFILTER_XT_MATCH_STATE=m
CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
@@ -298,20 +293,20 @@ CONFIG_NETFILTER_XT_MATCH_STRING=m
CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
CONFIG_NETFILTER_XT_MATCH_TIME=m
CONFIG_NETFILTER_XT_MATCH_U32=m
-CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+# CONFIG_IP_VS is not set
#
# IP: Netfilter Configuration
#
+CONFIG_NF_DEFRAG_IPV4=m
CONFIG_NF_CONNTRACK_IPV4=m
CONFIG_NF_CONNTRACK_PROC_COMPAT=y
CONFIG_IP_NF_QUEUE=m
CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_RECENT=m
-CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IP_NF_TARGET_LOG=m
@@ -319,8 +314,8 @@ CONFIG_IP_NF_TARGET_ULOG=m
CONFIG_NF_NAT=m
CONFIG_NF_NAT_NEEDED=y
CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
CONFIG_NF_NAT_SNMP_BASIC=m
CONFIG_NF_NAT_PROTO_GRE=m
CONFIG_NF_NAT_PROTO_UDPLITE=m
@@ -333,9 +328,9 @@ CONFIG_NF_NAT_PPTP=m
CONFIG_NF_NAT_H323=m
CONFIG_NF_NAT_SIP=m
CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
CONFIG_IP_NF_TARGET_ECN=m
CONFIG_IP_NF_TARGET_TTL=m
-CONFIG_IP_NF_TARGET_CLUSTERIP=m
CONFIG_IP_NF_RAW=m
CONFIG_IP_NF_ARPTABLES=m
CONFIG_IP_NF_ARPFILTER=m
@@ -347,16 +342,16 @@ CONFIG_IP_NF_ARP_MANGLE=m
CONFIG_NF_CONNTRACK_IPV6=m
CONFIG_IP6_NF_QUEUE=m
CONFIG_IP6_NF_IPTABLES=m
-CONFIG_IP6_NF_MATCH_RT=m
-CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
CONFIG_IP6_NF_MATCH_HL=m
CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-CONFIG_IP6_NF_MATCH_AH=m
CONFIG_IP6_NF_MATCH_MH=m
-CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_MATCH_RT=m
CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_FILTER=m
CONFIG_IP6_NF_TARGET_REJECT=m
CONFIG_IP6_NF_MANGLE=m
CONFIG_IP6_NF_TARGET_HL=m
@@ -383,6 +378,7 @@ CONFIG_SCTP_HMAC_MD5=y
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
CONFIG_LLC=m
@@ -406,19 +402,8 @@ CONFIG_NET_CLS_ROUTE=y
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
-# CONFIG_CFG80211 is not set
-CONFIG_WIRELESS_EXT=y
-# CONFIG_WIRELESS_EXT_SYSFS is not set
-# CONFIG_MAC80211 is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
-CONFIG_IEEE80211_CRYPT_TKIP=m
+# CONFIG_PHONET is not set
+# CONFIG_WIRELESS is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -462,21 +447,20 @@ CONFIG_ATA_OVER_ETH=m
CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
CONFIG_IDE=y
-CONFIG_BLK_DEV_IDE=y
#
# Please see Documentation/ide/ide.txt for help/info on IDE drives
#
-CONFIG_IDE_ATAPI=y
# CONFIG_BLK_DEV_IDE_SATA is not set
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_IDE_GD=y
+CONFIG_IDE_GD_ATA=y
+# CONFIG_IDE_GD_ATAPI is not set
CONFIG_BLK_DEV_IDECD=y
CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y
# CONFIG_BLK_DEV_IDETAPE is not set
-CONFIG_BLK_DEV_IDEFLOPPY=m
# CONFIG_BLK_DEV_IDESCSI is not set
# CONFIG_IDE_TASK_IOCTL is not set
CONFIG_IDE_PROC_FS=y
@@ -565,12 +549,15 @@ CONFIG_EQUALIZER=m
CONFIG_VETH=m
# CONFIG_PHYLIB is not set
CONFIG_NET_ETHERNET=y
-CONFIG_MII=m
+CONFIG_MII=y
CONFIG_ATARILANCE=m
# CONFIG_IBM_NEW_EMAC_ZMII is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
# CONFIG_B44 is not set
# CONFIG_NET_POCKET is not set
# CONFIG_NETDEV_1000 is not set
@@ -644,6 +631,7 @@ CONFIG_MOUSE_PS2_LOGIPS2PP=y
CONFIG_MOUSE_PS2_SYNAPTICS=y
CONFIG_MOUSE_PS2_LIFEBOOK=y
CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
# CONFIG_MOUSE_PS2_TOUCHKIT is not set
# CONFIG_MOUSE_SERIAL is not set
CONFIG_MOUSE_ATARI=m
@@ -706,11 +694,11 @@ CONFIG_GEN_RTC_X=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -720,6 +708,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -745,6 +734,7 @@ CONFIG_SSB_POSSIBLE=y
CONFIG_FB=y
# CONFIG_FIRMWARE_EDID is not set
# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
@@ -768,6 +758,8 @@ CONFIG_FB_ATARI=y
# CONFIG_FB_S1D13XXX is not set
# CONFIG_FB_ATY is not set
# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
@@ -790,12 +782,19 @@ CONFIG_LOGO_LINUX_MONO=y
CONFIG_LOGO_LINUX_VGA16=y
CONFIG_LOGO_LINUX_CLUT224=y
CONFIG_SOUND=m
+CONFIG_SOUND_OSS_CORE=y
CONFIG_DMASOUND_ATARI=m
CONFIG_DMASOUND=m
CONFIG_HID_SUPPORT=y
CONFIG_HID=m
# CONFIG_HID_DEBUG is not set
CONFIG_HIDRAW=y
+# CONFIG_HID_PID is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
# CONFIG_USB_SUPPORT is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -805,6 +804,8 @@ CONFIG_HIDRAW=y
# CONFIG_DMADEVICES is not set
# CONFIG_AUXDISPLAY is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+CONFIG_STAGING_EXCLUDE_BUILD=y
#
# Character devices
@@ -821,10 +822,9 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
# CONFIG_EXT3_FS_XATTR is not set
-CONFIG_EXT4DEV_FS=y
-# CONFIG_EXT4DEV_FS_XATTR is not set
+# CONFIG_EXT4_FS is not set
CONFIG_JBD=y
-CONFIG_JBD2=y
+CONFIG_JBD2=m
CONFIG_REISERFS_FS=m
# CONFIG_REISERFS_CHECK is not set
# CONFIG_REISERFS_PROC_INFO is not set
@@ -835,6 +835,7 @@ CONFIG_JFS_FS=m
# CONFIG_JFS_DEBUG is not set
# CONFIG_JFS_STATISTICS is not set
# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
CONFIG_XFS_FS=m
# CONFIG_XFS_QUOTA is not set
# CONFIG_XFS_POSIX_ACL is not set
@@ -846,6 +847,7 @@ CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
# CONFIG_OCFS2_FS_STATS is not set
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
# CONFIG_OCFS2_DEBUG_FS is not set
+# CONFIG_OCFS2_COMPAT_JBD is not set
CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
@@ -884,6 +886,7 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
@@ -925,6 +928,7 @@ CONFIG_LOCKD_V4=y
CONFIG_EXPORTFS=m
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=m
+# CONFIG_SUNRPC_REGISTER_V4 is not set
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
CONFIG_SMB_FS=m
@@ -998,7 +1002,13 @@ CONFIG_MAGIC_SYSRQ=y
# CONFIG_DEBUG_KERNEL is not set
CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
+
+#
+# Tracers
+#
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
#
@@ -1006,6 +1016,7 @@ CONFIG_SYSCTL_SYSCALL_CHECK=y
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_XOR_BLOCKS=m
CONFIG_ASYNC_CORE=m
@@ -1016,10 +1027,12 @@ CONFIG_CRYPTO=y
#
# Crypto core or helper
#
+# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=m
-CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_BLKCIPHER=y
CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_RNG=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_GF128MUL=m
CONFIG_CRYPTO_NULL=m
@@ -1093,14 +1106,17 @@ CONFIG_CRYPTO_TWOFISH_COMMON=m
#
CONFIG_CRYPTO_DEFLATE=m
CONFIG_CRYPTO_LZO=m
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
# CONFIG_CRYPTO_HW is not set
#
# Library routines
#
CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
-# CONFIG_GENERIC_FIND_NEXT_BIT is not set
CONFIG_CRC_CCITT=m
CONFIG_CRC16=y
CONFIG_CRC_T10DIF=y
diff --git a/arch/m68k/configs/bvme6000_defconfig b/arch/m68k/configs/bvme6000_defconfig
index 2e44af0fe54..d3d9814a91d 100644
--- a/arch/m68k/configs/bvme6000_defconfig
+++ b/arch/m68k/configs/bvme6000_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27-rc6
-# Wed Sep 10 09:02:03 2008
+# Linux kernel version: 2.6.28-rc7
+# Tue Dec 2 20:27:45 2008
#
CONFIG_M68K=y
CONFIG_MMU=y
@@ -14,7 +14,6 @@ CONFIG_TIME_LOW_RES=y
CONFIG_GENERIC_IOMAP=y
CONFIG_NO_IOPORT=y
# CONFIG_NO_DMA is not set
-CONFIG_ARCH_SUPPORTS_AOUT=y
CONFIG_HZ=100
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -67,22 +66,13 @@ CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
# CONFIG_MARKERS is not set
-# CONFIG_HAVE_OPROFILE is not set
-# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set
-# CONFIG_HAVE_IOREMAP_PROT is not set
-# CONFIG_HAVE_KPROBES is not set
-# CONFIG_HAVE_KRETPROBES is not set
-# CONFIG_HAVE_ARCH_TRACEHOOK is not set
-# CONFIG_HAVE_DMA_ATTRS is not set
-# CONFIG_USE_GENERIC_SMP_HELPERS is not set
-# CONFIG_HAVE_CLK is not set
-CONFIG_PROC_PAGE_MONITOR=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -115,11 +105,11 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_FREEZER is not set
#
# Platform dependent setup
#
-# CONFIG_SUN3 is not set
# CONFIG_AMIGA is not set
# CONFIG_ATARI is not set
# CONFIG_MAC is not set
@@ -151,19 +141,21 @@ CONFIG_DISCONTIGMEM_MANUAL=y
CONFIG_DISCONTIGMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_NEED_MULTIPLE_NODES=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
#
# General setup
#
CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
CONFIG_BINFMT_AOUT=m
CONFIG_BINFMT_MISC=m
CONFIG_PROC_HARDWARE=y
@@ -212,7 +204,6 @@ CONFIG_INET_TCP_DIAG=m
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
-# CONFIG_IP_VS is not set
CONFIG_IPV6=m
CONFIG_IPV6_PRIVACY=y
CONFIG_IPV6_ROUTER_PREF=y
@@ -262,13 +253,14 @@ CONFIG_NF_CONNTRACK_SANE=m
CONFIG_NF_CONNTRACK_SIP=m
CONFIG_NF_CONNTRACK_TFTP=m
# CONFIG_NF_CT_NETLINK is not set
+# CONFIG_NETFILTER_TPROXY is not set
CONFIG_NETFILTER_XTABLES=m
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
CONFIG_NETFILTER_XT_TARGET_DSCP=m
CONFIG_NETFILTER_XT_TARGET_MARK=m
-CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
CONFIG_NETFILTER_XT_TARGET_RATEEST=m
CONFIG_NETFILTER_XT_TARGET_TRACE=m
@@ -282,19 +274,22 @@ CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
CONFIG_NETFILTER_XT_MATCH_DCCP=m
CONFIG_NETFILTER_XT_MATCH_DSCP=m
CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
CONFIG_NETFILTER_XT_MATCH_HELPER=m
CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
CONFIG_NETFILTER_XT_MATCH_MAC=m
CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_OWNER=m
CONFIG_NETFILTER_XT_MATCH_POLICY=m
-CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_QUOTA=m
CONFIG_NETFILTER_XT_MATCH_RATEEST=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_RECENT=m
+# CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT is not set
CONFIG_NETFILTER_XT_MATCH_SCTP=m
CONFIG_NETFILTER_XT_MATCH_STATE=m
CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
@@ -302,20 +297,20 @@ CONFIG_NETFILTER_XT_MATCH_STRING=m
CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
CONFIG_NETFILTER_XT_MATCH_TIME=m
CONFIG_NETFILTER_XT_MATCH_U32=m
-CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+# CONFIG_IP_VS is not set
#
# IP: Netfilter Configuration
#
+CONFIG_NF_DEFRAG_IPV4=m
CONFIG_NF_CONNTRACK_IPV4=m
CONFIG_NF_CONNTRACK_PROC_COMPAT=y
CONFIG_IP_NF_QUEUE=m
CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_RECENT=m
-CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IP_NF_TARGET_LOG=m
@@ -323,8 +318,8 @@ CONFIG_IP_NF_TARGET_ULOG=m
CONFIG_NF_NAT=m
CONFIG_NF_NAT_NEEDED=y
CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
CONFIG_NF_NAT_SNMP_BASIC=m
CONFIG_NF_NAT_PROTO_GRE=m
CONFIG_NF_NAT_PROTO_UDPLITE=m
@@ -337,9 +332,9 @@ CONFIG_NF_NAT_PPTP=m
CONFIG_NF_NAT_H323=m
CONFIG_NF_NAT_SIP=m
CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
CONFIG_IP_NF_TARGET_ECN=m
CONFIG_IP_NF_TARGET_TTL=m
-CONFIG_IP_NF_TARGET_CLUSTERIP=m
CONFIG_IP_NF_RAW=m
CONFIG_IP_NF_ARPTABLES=m
CONFIG_IP_NF_ARPFILTER=m
@@ -351,16 +346,16 @@ CONFIG_IP_NF_ARP_MANGLE=m
CONFIG_NF_CONNTRACK_IPV6=m
CONFIG_IP6_NF_QUEUE=m
CONFIG_IP6_NF_IPTABLES=m
-CONFIG_IP6_NF_MATCH_RT=m
-CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
CONFIG_IP6_NF_MATCH_HL=m
CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-CONFIG_IP6_NF_MATCH_AH=m
CONFIG_IP6_NF_MATCH_MH=m
-CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_MATCH_RT=m
CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_FILTER=m
CONFIG_IP6_NF_TARGET_REJECT=m
CONFIG_IP6_NF_MANGLE=m
CONFIG_IP6_NF_TARGET_HL=m
@@ -387,6 +382,7 @@ CONFIG_SCTP_HMAC_MD5=y
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
CONFIG_LLC=m
@@ -410,19 +406,8 @@ CONFIG_NET_CLS_ROUTE=y
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
-# CONFIG_CFG80211 is not set
-CONFIG_WIRELESS_EXT=y
-# CONFIG_WIRELESS_EXT_SYSFS is not set
-# CONFIG_MAC80211 is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
-CONFIG_IEEE80211_CRYPT_TKIP=m
+# CONFIG_PHONET is not set
+# CONFIG_WIRELESS is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -460,6 +445,7 @@ CONFIG_ATA_OVER_ETH=m
CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -545,6 +531,9 @@ CONFIG_BVME6000_NET=y
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
# CONFIG_B44 is not set
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
@@ -614,6 +603,7 @@ CONFIG_MOUSE_PS2_LOGIPS2PP=y
CONFIG_MOUSE_PS2_SYNAPTICS=y
CONFIG_MOUSE_PS2_LIFEBOOK=y
CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
# CONFIG_MOUSE_PS2_TOUCHKIT is not set
CONFIG_MOUSE_SERIAL=m
# CONFIG_MOUSE_VSXXXAA is not set
@@ -668,11 +658,11 @@ CONFIG_GEN_RTC_X=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -682,6 +672,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -721,6 +712,12 @@ CONFIG_HID_SUPPORT=y
CONFIG_HID=m
# CONFIG_HID_DEBUG is not set
CONFIG_HIDRAW=y
+# CONFIG_HID_PID is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
# CONFIG_USB_SUPPORT is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -729,6 +726,8 @@ CONFIG_HIDRAW=y
# CONFIG_RTC_CLASS is not set
# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+CONFIG_STAGING_EXCLUDE_BUILD=y
#
# Character devices
@@ -744,8 +743,9 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
# CONFIG_EXT3_FS_XATTR is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
CONFIG_JBD=y
+CONFIG_JBD2=m
CONFIG_REISERFS_FS=m
# CONFIG_REISERFS_CHECK is not set
# CONFIG_REISERFS_PROC_INFO is not set
@@ -756,6 +756,7 @@ CONFIG_JFS_FS=m
# CONFIG_JFS_DEBUG is not set
# CONFIG_JFS_STATISTICS is not set
# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
CONFIG_XFS_FS=m
# CONFIG_XFS_QUOTA is not set
# CONFIG_XFS_POSIX_ACL is not set
@@ -767,6 +768,7 @@ CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
# CONFIG_OCFS2_FS_STATS is not set
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
# CONFIG_OCFS2_DEBUG_FS is not set
+# CONFIG_OCFS2_COMPAT_JBD is not set
CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
@@ -805,6 +807,7 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
@@ -848,6 +851,7 @@ CONFIG_EXPORTFS=m
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_REGISTER_V4 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
CONFIG_SMB_FS=m
@@ -921,7 +925,13 @@ CONFIG_MAGIC_SYSRQ=y
# CONFIG_DEBUG_KERNEL is not set
CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
+
+#
+# Tracers
+#
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
#
@@ -929,6 +939,7 @@ CONFIG_SYSCTL_SYSCALL_CHECK=y
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_XOR_BLOCKS=m
CONFIG_ASYNC_CORE=m
@@ -939,10 +950,12 @@ CONFIG_CRYPTO=y
#
# Crypto core or helper
#
+# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD=y
CONFIG_CRYPTO_BLKCIPHER=y
CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_RNG=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_GF128MUL=m
CONFIG_CRYPTO_NULL=m
@@ -1016,14 +1029,17 @@ CONFIG_CRYPTO_TWOFISH_COMMON=m
#
CONFIG_CRYPTO_DEFLATE=m
CONFIG_CRYPTO_LZO=m
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
# CONFIG_CRYPTO_HW is not set
#
# Library routines
#
CONFIG_BITREVERSE=m
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
-# CONFIG_GENERIC_FIND_NEXT_BIT is not set
CONFIG_CRC_CCITT=m
CONFIG_CRC16=m
CONFIG_CRC_T10DIF=y
diff --git a/arch/m68k/configs/hp300_defconfig b/arch/m68k/configs/hp300_defconfig
index 3570fc89b08..5556ef088d0 100644
--- a/arch/m68k/configs/hp300_defconfig
+++ b/arch/m68k/configs/hp300_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27-rc6
-# Wed Sep 10 09:02:04 2008
+# Linux kernel version: 2.6.28-rc7
+# Tue Dec 2 20:27:46 2008
#
CONFIG_M68K=y
CONFIG_MMU=y
@@ -14,7 +14,6 @@ CONFIG_TIME_LOW_RES=y
CONFIG_GENERIC_IOMAP=y
CONFIG_NO_IOPORT=y
# CONFIG_NO_DMA is not set
-CONFIG_ARCH_SUPPORTS_AOUT=y
CONFIG_HZ=100
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -67,22 +66,13 @@ CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
# CONFIG_MARKERS is not set
-# CONFIG_HAVE_OPROFILE is not set
-# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set
-# CONFIG_HAVE_IOREMAP_PROT is not set
-# CONFIG_HAVE_KPROBES is not set
-# CONFIG_HAVE_KRETPROBES is not set
-# CONFIG_HAVE_ARCH_TRACEHOOK is not set
-# CONFIG_HAVE_DMA_ATTRS is not set
-# CONFIG_USE_GENERIC_SMP_HELPERS is not set
-# CONFIG_HAVE_CLK is not set
-CONFIG_PROC_PAGE_MONITOR=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -115,11 +105,11 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_FREEZER is not set
#
# Platform dependent setup
#
-# CONFIG_SUN3 is not set
# CONFIG_AMIGA is not set
# CONFIG_ATARI is not set
# CONFIG_MAC is not set
@@ -149,19 +139,21 @@ CONFIG_DISCONTIGMEM_MANUAL=y
CONFIG_DISCONTIGMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_NEED_MULTIPLE_NODES=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
#
# General setup
#
CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
CONFIG_BINFMT_AOUT=m
CONFIG_BINFMT_MISC=m
CONFIG_HEARTBEAT=y
@@ -211,7 +203,6 @@ CONFIG_INET_TCP_DIAG=m
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
-# CONFIG_IP_VS is not set
CONFIG_IPV6=m
CONFIG_IPV6_PRIVACY=y
CONFIG_IPV6_ROUTER_PREF=y
@@ -261,13 +252,14 @@ CONFIG_NF_CONNTRACK_SANE=m
CONFIG_NF_CONNTRACK_SIP=m
CONFIG_NF_CONNTRACK_TFTP=m
# CONFIG_NF_CT_NETLINK is not set
+# CONFIG_NETFILTER_TPROXY is not set
CONFIG_NETFILTER_XTABLES=m
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
CONFIG_NETFILTER_XT_TARGET_DSCP=m
CONFIG_NETFILTER_XT_TARGET_MARK=m
-CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
CONFIG_NETFILTER_XT_TARGET_RATEEST=m
CONFIG_NETFILTER_XT_TARGET_TRACE=m
@@ -281,19 +273,22 @@ CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
CONFIG_NETFILTER_XT_MATCH_DCCP=m
CONFIG_NETFILTER_XT_MATCH_DSCP=m
CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
CONFIG_NETFILTER_XT_MATCH_HELPER=m
CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
CONFIG_NETFILTER_XT_MATCH_MAC=m
CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_OWNER=m
CONFIG_NETFILTER_XT_MATCH_POLICY=m
-CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_QUOTA=m
CONFIG_NETFILTER_XT_MATCH_RATEEST=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_RECENT=m
+# CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT is not set
CONFIG_NETFILTER_XT_MATCH_SCTP=m
CONFIG_NETFILTER_XT_MATCH_STATE=m
CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
@@ -301,20 +296,20 @@ CONFIG_NETFILTER_XT_MATCH_STRING=m
CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
CONFIG_NETFILTER_XT_MATCH_TIME=m
CONFIG_NETFILTER_XT_MATCH_U32=m
-CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+# CONFIG_IP_VS is not set
#
# IP: Netfilter Configuration
#
+CONFIG_NF_DEFRAG_IPV4=m
CONFIG_NF_CONNTRACK_IPV4=m
CONFIG_NF_CONNTRACK_PROC_COMPAT=y
CONFIG_IP_NF_QUEUE=m
CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_RECENT=m
-CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IP_NF_TARGET_LOG=m
@@ -322,8 +317,8 @@ CONFIG_IP_NF_TARGET_ULOG=m
CONFIG_NF_NAT=m
CONFIG_NF_NAT_NEEDED=y
CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
CONFIG_NF_NAT_SNMP_BASIC=m
CONFIG_NF_NAT_PROTO_GRE=m
CONFIG_NF_NAT_PROTO_UDPLITE=m
@@ -336,9 +331,9 @@ CONFIG_NF_NAT_PPTP=m
CONFIG_NF_NAT_H323=m
CONFIG_NF_NAT_SIP=m
CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
CONFIG_IP_NF_TARGET_ECN=m
CONFIG_IP_NF_TARGET_TTL=m
-CONFIG_IP_NF_TARGET_CLUSTERIP=m
CONFIG_IP_NF_RAW=m
CONFIG_IP_NF_ARPTABLES=m
CONFIG_IP_NF_ARPFILTER=m
@@ -350,16 +345,16 @@ CONFIG_IP_NF_ARP_MANGLE=m
CONFIG_NF_CONNTRACK_IPV6=m
CONFIG_IP6_NF_QUEUE=m
CONFIG_IP6_NF_IPTABLES=m
-CONFIG_IP6_NF_MATCH_RT=m
-CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
CONFIG_IP6_NF_MATCH_HL=m
CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-CONFIG_IP6_NF_MATCH_AH=m
CONFIG_IP6_NF_MATCH_MH=m
-CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_MATCH_RT=m
CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_FILTER=m
CONFIG_IP6_NF_TARGET_REJECT=m
CONFIG_IP6_NF_MANGLE=m
CONFIG_IP6_NF_TARGET_HL=m
@@ -386,6 +381,7 @@ CONFIG_SCTP_HMAC_MD5=y
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
CONFIG_LLC=m
@@ -409,19 +405,8 @@ CONFIG_NET_CLS_ROUTE=y
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
-# CONFIG_CFG80211 is not set
-CONFIG_WIRELESS_EXT=y
-# CONFIG_WIRELESS_EXT_SYSFS is not set
-# CONFIG_MAC80211 is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
-CONFIG_IEEE80211_CRYPT_TKIP=m
+# CONFIG_PHONET is not set
+# CONFIG_WIRELESS is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -459,6 +444,7 @@ CONFIG_ATA_OVER_ETH=m
CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -542,6 +528,9 @@ CONFIG_HPLANCE=y
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
# CONFIG_B44 is not set
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
@@ -613,6 +602,7 @@ CONFIG_MOUSE_PS2_LOGIPS2PP=y
CONFIG_MOUSE_PS2_SYNAPTICS=y
CONFIG_MOUSE_PS2_LIFEBOOK=y
CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
# CONFIG_MOUSE_PS2_TOUCHKIT is not set
CONFIG_MOUSE_SERIAL=m
# CONFIG_MOUSE_VSXXXAA is not set
@@ -673,11 +663,11 @@ CONFIG_GEN_RTC_X=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -687,6 +677,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -712,6 +703,7 @@ CONFIG_SSB_POSSIBLE=y
CONFIG_FB=y
# CONFIG_FIRMWARE_EDID is not set
# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
# CONFIG_FB_CFB_FILLRECT is not set
# CONFIG_FB_CFB_COPYAREA is not set
CONFIG_FB_CFB_IMAGEBLIT=y
@@ -734,6 +726,8 @@ CONFIG_FB_HP300=y
# CONFIG_FB_UVESA is not set
# CONFIG_FB_S1D13XXX is not set
# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
@@ -760,6 +754,12 @@ CONFIG_HID_SUPPORT=y
CONFIG_HID=m
# CONFIG_HID_DEBUG is not set
CONFIG_HIDRAW=y
+# CONFIG_HID_PID is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
# CONFIG_USB_SUPPORT is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -768,6 +768,8 @@ CONFIG_HIDRAW=y
# CONFIG_RTC_CLASS is not set
# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+CONFIG_STAGING_EXCLUDE_BUILD=y
#
# Character devices
@@ -781,8 +783,9 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
# CONFIG_EXT3_FS_XATTR is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
CONFIG_JBD=y
+CONFIG_JBD2=m
CONFIG_REISERFS_FS=m
# CONFIG_REISERFS_CHECK is not set
# CONFIG_REISERFS_PROC_INFO is not set
@@ -793,6 +796,7 @@ CONFIG_JFS_FS=m
# CONFIG_JFS_DEBUG is not set
# CONFIG_JFS_STATISTICS is not set
# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
CONFIG_XFS_FS=m
# CONFIG_XFS_QUOTA is not set
# CONFIG_XFS_POSIX_ACL is not set
@@ -804,6 +808,7 @@ CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
# CONFIG_OCFS2_FS_STATS is not set
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
# CONFIG_OCFS2_DEBUG_FS is not set
+# CONFIG_OCFS2_COMPAT_JBD is not set
CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
@@ -842,6 +847,7 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
@@ -885,6 +891,7 @@ CONFIG_EXPORTFS=m
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_REGISTER_V4 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
CONFIG_SMB_FS=m
@@ -957,7 +964,13 @@ CONFIG_MAGIC_SYSRQ=y
# CONFIG_DEBUG_KERNEL is not set
CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
+
+#
+# Tracers
+#
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
#
@@ -965,6 +978,7 @@ CONFIG_SYSCTL_SYSCALL_CHECK=y
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_XOR_BLOCKS=m
CONFIG_ASYNC_CORE=m
@@ -975,10 +989,12 @@ CONFIG_CRYPTO=y
#
# Crypto core or helper
#
+# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD=y
CONFIG_CRYPTO_BLKCIPHER=y
CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_RNG=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_GF128MUL=m
CONFIG_CRYPTO_NULL=m
@@ -1052,14 +1068,17 @@ CONFIG_CRYPTO_TWOFISH_COMMON=m
#
CONFIG_CRYPTO_DEFLATE=m
CONFIG_CRYPTO_LZO=m
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
# CONFIG_CRYPTO_HW is not set
#
# Library routines
#
CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
-# CONFIG_GENERIC_FIND_NEXT_BIT is not set
CONFIG_CRC_CCITT=m
CONFIG_CRC16=m
CONFIG_CRC_T10DIF=y
diff --git a/arch/m68k/configs/mac_defconfig b/arch/m68k/configs/mac_defconfig
index db6e8822594..c6de25724a2 100644
--- a/arch/m68k/configs/mac_defconfig
+++ b/arch/m68k/configs/mac_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27-rc6
-# Wed Sep 10 09:02:06 2008
+# Linux kernel version: 2.6.28-rc7
+# Tue Dec 2 20:27:47 2008
#
CONFIG_M68K=y
CONFIG_MMU=y
@@ -14,7 +14,6 @@ CONFIG_TIME_LOW_RES=y
CONFIG_GENERIC_IOMAP=y
CONFIG_NO_IOPORT=y
# CONFIG_NO_DMA is not set
-CONFIG_ARCH_SUPPORTS_AOUT=y
CONFIG_HZ=100
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -67,22 +66,13 @@ CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
# CONFIG_MARKERS is not set
-# CONFIG_HAVE_OPROFILE is not set
-# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set
-# CONFIG_HAVE_IOREMAP_PROT is not set
-# CONFIG_HAVE_KPROBES is not set
-# CONFIG_HAVE_KRETPROBES is not set
-# CONFIG_HAVE_ARCH_TRACEHOOK is not set
-# CONFIG_HAVE_DMA_ATTRS is not set
-# CONFIG_USE_GENERIC_SMP_HELPERS is not set
-# CONFIG_HAVE_CLK is not set
-CONFIG_PROC_PAGE_MONITOR=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -115,11 +105,11 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_FREEZER is not set
#
# Platform dependent setup
#
-# CONFIG_SUN3 is not set
# CONFIG_AMIGA is not set
# CONFIG_ATARI is not set
CONFIG_MAC=y
@@ -150,19 +140,21 @@ CONFIG_DISCONTIGMEM_MANUAL=y
CONFIG_DISCONTIGMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_NEED_MULTIPLE_NODES=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
#
# General setup
#
CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
CONFIG_BINFMT_AOUT=m
CONFIG_BINFMT_MISC=m
# CONFIG_HEARTBEAT is not set
@@ -209,7 +201,6 @@ CONFIG_INET_TCP_DIAG=m
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
-# CONFIG_IP_VS is not set
CONFIG_IPV6=m
CONFIG_IPV6_PRIVACY=y
CONFIG_IPV6_ROUTER_PREF=y
@@ -259,13 +250,14 @@ CONFIG_NF_CONNTRACK_SANE=m
CONFIG_NF_CONNTRACK_SIP=m
CONFIG_NF_CONNTRACK_TFTP=m
# CONFIG_NF_CT_NETLINK is not set
+# CONFIG_NETFILTER_TPROXY is not set
CONFIG_NETFILTER_XTABLES=m
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
CONFIG_NETFILTER_XT_TARGET_DSCP=m
CONFIG_NETFILTER_XT_TARGET_MARK=m
-CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
CONFIG_NETFILTER_XT_TARGET_RATEEST=m
CONFIG_NETFILTER_XT_TARGET_TRACE=m
@@ -279,19 +271,22 @@ CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
CONFIG_NETFILTER_XT_MATCH_DCCP=m
CONFIG_NETFILTER_XT_MATCH_DSCP=m
CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
CONFIG_NETFILTER_XT_MATCH_HELPER=m
CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
CONFIG_NETFILTER_XT_MATCH_MAC=m
CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_OWNER=m
CONFIG_NETFILTER_XT_MATCH_POLICY=m
-CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_QUOTA=m
CONFIG_NETFILTER_XT_MATCH_RATEEST=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_RECENT=m
+# CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT is not set
CONFIG_NETFILTER_XT_MATCH_SCTP=m
CONFIG_NETFILTER_XT_MATCH_STATE=m
CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
@@ -299,20 +294,20 @@ CONFIG_NETFILTER_XT_MATCH_STRING=m
CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
CONFIG_NETFILTER_XT_MATCH_TIME=m
CONFIG_NETFILTER_XT_MATCH_U32=m
-CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+# CONFIG_IP_VS is not set
#
# IP: Netfilter Configuration
#
+CONFIG_NF_DEFRAG_IPV4=m
CONFIG_NF_CONNTRACK_IPV4=m
CONFIG_NF_CONNTRACK_PROC_COMPAT=y
CONFIG_IP_NF_QUEUE=m
CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_RECENT=m
-CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IP_NF_TARGET_LOG=m
@@ -320,8 +315,8 @@ CONFIG_IP_NF_TARGET_ULOG=m
CONFIG_NF_NAT=m
CONFIG_NF_NAT_NEEDED=y
CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
CONFIG_NF_NAT_SNMP_BASIC=m
CONFIG_NF_NAT_PROTO_GRE=m
CONFIG_NF_NAT_PROTO_UDPLITE=m
@@ -334,9 +329,9 @@ CONFIG_NF_NAT_PPTP=m
CONFIG_NF_NAT_H323=m
CONFIG_NF_NAT_SIP=m
CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
CONFIG_IP_NF_TARGET_ECN=m
CONFIG_IP_NF_TARGET_TTL=m
-CONFIG_IP_NF_TARGET_CLUSTERIP=m
CONFIG_IP_NF_RAW=m
CONFIG_IP_NF_ARPTABLES=m
CONFIG_IP_NF_ARPFILTER=m
@@ -348,16 +343,16 @@ CONFIG_IP_NF_ARP_MANGLE=m
CONFIG_NF_CONNTRACK_IPV6=m
CONFIG_IP6_NF_QUEUE=m
CONFIG_IP6_NF_IPTABLES=m
-CONFIG_IP6_NF_MATCH_RT=m
-CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
CONFIG_IP6_NF_MATCH_HL=m
CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-CONFIG_IP6_NF_MATCH_AH=m
CONFIG_IP6_NF_MATCH_MH=m
-CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_MATCH_RT=m
CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_FILTER=m
CONFIG_IP6_NF_TARGET_REJECT=m
CONFIG_IP6_NF_MANGLE=m
CONFIG_IP6_NF_TARGET_HL=m
@@ -384,6 +379,7 @@ CONFIG_SCTP_HMAC_MD5=y
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
CONFIG_LLC=m
@@ -410,19 +406,8 @@ CONFIG_NET_CLS_ROUTE=y
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
-# CONFIG_CFG80211 is not set
-CONFIG_WIRELESS_EXT=y
-# CONFIG_WIRELESS_EXT_SYSFS is not set
-# CONFIG_MAC80211 is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
-CONFIG_IEEE80211_CRYPT_TKIP=m
+# CONFIG_PHONET is not set
+# CONFIG_WIRELESS is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -460,21 +445,20 @@ CONFIG_ATA_OVER_ETH=m
CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
CONFIG_IDE=y
-CONFIG_BLK_DEV_IDE=y
#
# Please see Documentation/ide/ide.txt for help/info on IDE drives
#
-CONFIG_IDE_ATAPI=y
# CONFIG_BLK_DEV_IDE_SATA is not set
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_IDE_GD=y
+CONFIG_IDE_GD_ATA=y
+# CONFIG_IDE_GD_ATAPI is not set
CONFIG_BLK_DEV_IDECD=y
CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y
# CONFIG_BLK_DEV_IDETAPE is not set
-CONFIG_BLK_DEV_IDEFLOPPY=m
# CONFIG_BLK_DEV_IDESCSI is not set
# CONFIG_IDE_TASK_IOCTL is not set
CONFIG_IDE_PROC_FS=y
@@ -581,6 +565,9 @@ CONFIG_MACMACE=y
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
# CONFIG_B44 is not set
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
@@ -650,6 +637,7 @@ CONFIG_MOUSE_PS2_LOGIPS2PP=y
CONFIG_MOUSE_PS2_SYNAPTICS=y
CONFIG_MOUSE_PS2_LIFEBOOK=y
CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
# CONFIG_MOUSE_PS2_TOUCHKIT is not set
CONFIG_MOUSE_SERIAL=m
# CONFIG_MOUSE_VSXXXAA is not set
@@ -706,11 +694,11 @@ CONFIG_GEN_RTC_X=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -720,6 +708,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -745,6 +734,7 @@ CONFIG_SSB_POSSIBLE=y
CONFIG_FB=y
# CONFIG_FIRMWARE_EDID is not set
# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
@@ -768,6 +758,8 @@ CONFIG_FB_MAC=y
# CONFIG_FB_UVESA is not set
# CONFIG_FB_S1D13XXX is not set
# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
@@ -796,6 +788,12 @@ CONFIG_HID_SUPPORT=y
CONFIG_HID=m
# CONFIG_HID_DEBUG is not set
CONFIG_HIDRAW=y
+# CONFIG_HID_PID is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
# CONFIG_USB_SUPPORT is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -804,6 +802,8 @@ CONFIG_HIDRAW=y
# CONFIG_RTC_CLASS is not set
# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+CONFIG_STAGING_EXCLUDE_BUILD=y
#
# Character devices
@@ -820,8 +820,9 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
# CONFIG_EXT3_FS_XATTR is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
CONFIG_JBD=y
+CONFIG_JBD2=m
CONFIG_REISERFS_FS=m
# CONFIG_REISERFS_CHECK is not set
# CONFIG_REISERFS_PROC_INFO is not set
@@ -832,6 +833,7 @@ CONFIG_JFS_FS=m
# CONFIG_JFS_DEBUG is not set
# CONFIG_JFS_STATISTICS is not set
# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
CONFIG_XFS_FS=m
# CONFIG_XFS_QUOTA is not set
# CONFIG_XFS_POSIX_ACL is not set
@@ -843,6 +845,7 @@ CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
# CONFIG_OCFS2_FS_STATS is not set
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
# CONFIG_OCFS2_DEBUG_FS is not set
+# CONFIG_OCFS2_COMPAT_JBD is not set
CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
@@ -881,6 +884,7 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
@@ -923,6 +927,7 @@ CONFIG_EXPORTFS=m
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=m
CONFIG_SUNRPC_GSS=m
+# CONFIG_SUNRPC_REGISTER_V4 is not set
CONFIG_RPCSEC_GSS_KRB5=m
# CONFIG_RPCSEC_GSS_SPKM3 is not set
CONFIG_SMB_FS=m
@@ -996,7 +1001,13 @@ CONFIG_MAGIC_SYSRQ=y
# CONFIG_DEBUG_KERNEL is not set
CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
+
+#
+# Tracers
+#
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
#
@@ -1004,6 +1015,7 @@ CONFIG_SYSCTL_SYSCALL_CHECK=y
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_XOR_BLOCKS=m
CONFIG_ASYNC_CORE=m
@@ -1014,10 +1026,12 @@ CONFIG_CRYPTO=y
#
# Crypto core or helper
#
+# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=m
-CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_BLKCIPHER=y
CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_RNG=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_GF128MUL=m
CONFIG_CRYPTO_NULL=m
@@ -1091,14 +1105,17 @@ CONFIG_CRYPTO_TWOFISH_COMMON=m
#
CONFIG_CRYPTO_DEFLATE=m
CONFIG_CRYPTO_LZO=m
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
# CONFIG_CRYPTO_HW is not set
#
# Library routines
#
CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
-# CONFIG_GENERIC_FIND_NEXT_BIT is not set
CONFIG_CRC_CCITT=m
CONFIG_CRC16=m
CONFIG_CRC_T10DIF=y
diff --git a/arch/m68k/configs/multi_defconfig b/arch/m68k/configs/multi_defconfig
index 1a806102b99..70693588031 100644
--- a/arch/m68k/configs/multi_defconfig
+++ b/arch/m68k/configs/multi_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27-rc6
-# Wed Sep 10 09:02:07 2008
+# Linux kernel version: 2.6.28-rc7
+# Tue Dec 2 20:27:48 2008
#
CONFIG_M68K=y
CONFIG_MMU=y
@@ -14,7 +14,6 @@ CONFIG_TIME_LOW_RES=y
CONFIG_GENERIC_IOMAP=y
CONFIG_NO_IOPORT=y
# CONFIG_NO_DMA is not set
-CONFIG_ARCH_SUPPORTS_AOUT=y
CONFIG_HZ=100
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -67,22 +66,13 @@ CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
# CONFIG_MARKERS is not set
-# CONFIG_HAVE_OPROFILE is not set
-# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set
-# CONFIG_HAVE_IOREMAP_PROT is not set
-# CONFIG_HAVE_KPROBES is not set
-# CONFIG_HAVE_KRETPROBES is not set
-# CONFIG_HAVE_ARCH_TRACEHOOK is not set
-# CONFIG_HAVE_DMA_ATTRS is not set
-# CONFIG_USE_GENERIC_SMP_HELPERS is not set
-# CONFIG_HAVE_CLK is not set
-CONFIG_PROC_PAGE_MONITOR=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -115,11 +105,11 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_FREEZER is not set
#
# Platform dependent setup
#
-# CONFIG_SUN3 is not set
CONFIG_AMIGA=y
CONFIG_ATARI=y
CONFIG_MAC=y
@@ -154,19 +144,21 @@ CONFIG_DISCONTIGMEM_MANUAL=y
CONFIG_DISCONTIGMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_NEED_MULTIPLE_NODES=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
#
# General setup
#
CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
CONFIG_BINFMT_AOUT=m
CONFIG_BINFMT_MISC=m
CONFIG_ZORRO=y
@@ -222,7 +214,6 @@ CONFIG_INET_TCP_DIAG=m
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
-# CONFIG_IP_VS is not set
CONFIG_IPV6=m
CONFIG_IPV6_PRIVACY=y
CONFIG_IPV6_ROUTER_PREF=y
@@ -272,13 +263,14 @@ CONFIG_NF_CONNTRACK_SANE=m
CONFIG_NF_CONNTRACK_SIP=m
CONFIG_NF_CONNTRACK_TFTP=m
# CONFIG_NF_CT_NETLINK is not set
+# CONFIG_NETFILTER_TPROXY is not set
CONFIG_NETFILTER_XTABLES=m
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
CONFIG_NETFILTER_XT_TARGET_DSCP=m
CONFIG_NETFILTER_XT_TARGET_MARK=m
-CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
CONFIG_NETFILTER_XT_TARGET_RATEEST=m
CONFIG_NETFILTER_XT_TARGET_TRACE=m
@@ -292,19 +284,22 @@ CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
CONFIG_NETFILTER_XT_MATCH_DCCP=m
CONFIG_NETFILTER_XT_MATCH_DSCP=m
CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
CONFIG_NETFILTER_XT_MATCH_HELPER=m
CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
CONFIG_NETFILTER_XT_MATCH_MAC=m
CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_OWNER=m
CONFIG_NETFILTER_XT_MATCH_POLICY=m
-CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_QUOTA=m
CONFIG_NETFILTER_XT_MATCH_RATEEST=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_RECENT=m
+# CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT is not set
CONFIG_NETFILTER_XT_MATCH_SCTP=m
CONFIG_NETFILTER_XT_MATCH_STATE=m
CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
@@ -312,20 +307,20 @@ CONFIG_NETFILTER_XT_MATCH_STRING=m
CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
CONFIG_NETFILTER_XT_MATCH_TIME=m
CONFIG_NETFILTER_XT_MATCH_U32=m
-CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+# CONFIG_IP_VS is not set
#
# IP: Netfilter Configuration
#
+CONFIG_NF_DEFRAG_IPV4=m
CONFIG_NF_CONNTRACK_IPV4=m
CONFIG_NF_CONNTRACK_PROC_COMPAT=y
CONFIG_IP_NF_QUEUE=m
CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_RECENT=m
-CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IP_NF_TARGET_LOG=m
@@ -333,8 +328,8 @@ CONFIG_IP_NF_TARGET_ULOG=m
CONFIG_NF_NAT=m
CONFIG_NF_NAT_NEEDED=y
CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
CONFIG_NF_NAT_SNMP_BASIC=m
CONFIG_NF_NAT_PROTO_GRE=m
CONFIG_NF_NAT_PROTO_UDPLITE=m
@@ -347,9 +342,9 @@ CONFIG_NF_NAT_PPTP=m
CONFIG_NF_NAT_H323=m
CONFIG_NF_NAT_SIP=m
CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
CONFIG_IP_NF_TARGET_ECN=m
CONFIG_IP_NF_TARGET_TTL=m
-CONFIG_IP_NF_TARGET_CLUSTERIP=m
CONFIG_IP_NF_RAW=m
CONFIG_IP_NF_ARPTABLES=m
CONFIG_IP_NF_ARPFILTER=m
@@ -361,16 +356,16 @@ CONFIG_IP_NF_ARP_MANGLE=m
CONFIG_NF_CONNTRACK_IPV6=m
CONFIG_IP6_NF_QUEUE=m
CONFIG_IP6_NF_IPTABLES=m
-CONFIG_IP6_NF_MATCH_RT=m
-CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
CONFIG_IP6_NF_MATCH_HL=m
CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-CONFIG_IP6_NF_MATCH_AH=m
CONFIG_IP6_NF_MATCH_MH=m
-CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_MATCH_RT=m
CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_FILTER=m
CONFIG_IP6_NF_TARGET_REJECT=m
CONFIG_IP6_NF_MANGLE=m
CONFIG_IP6_NF_TARGET_HL=m
@@ -397,6 +392,7 @@ CONFIG_SCTP_HMAC_MD5=y
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
CONFIG_LLC=m
@@ -424,19 +420,8 @@ CONFIG_NET_CLS_ROUTE=y
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
-# CONFIG_CFG80211 is not set
-CONFIG_WIRELESS_EXT=y
-# CONFIG_WIRELESS_EXT_SYSFS is not set
-# CONFIG_MAC80211 is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
-CONFIG_IEEE80211_CRYPT_TKIP=m
+# CONFIG_PHONET is not set
+# CONFIG_WIRELESS is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -486,21 +471,20 @@ CONFIG_ATA_OVER_ETH=m
CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
CONFIG_IDE=y
-CONFIG_BLK_DEV_IDE=y
#
# Please see Documentation/ide/ide.txt for help/info on IDE drives
#
-CONFIG_IDE_ATAPI=y
# CONFIG_BLK_DEV_IDE_SATA is not set
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_IDE_GD=y
+CONFIG_IDE_GD_ATA=y
+# CONFIG_IDE_GD_ATAPI is not set
CONFIG_BLK_DEV_IDECD=y
CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y
# CONFIG_BLK_DEV_IDETAPE is not set
-CONFIG_BLK_DEV_IDEFLOPPY=m
# CONFIG_BLK_DEV_IDESCSI is not set
# CONFIG_IDE_TASK_IOCTL is not set
CONFIG_IDE_PROC_FS=y
@@ -629,7 +613,7 @@ CONFIG_VETH=m
# CONFIG_ARCNET is not set
# CONFIG_PHYLIB is not set
CONFIG_NET_ETHERNET=y
-CONFIG_MII=m
+CONFIG_MII=y
CONFIG_ARIADNE=m
CONFIG_A2065=m
CONFIG_HYDRA=m
@@ -657,8 +641,12 @@ CONFIG_NE2000=m
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
# CONFIG_NET_PCI is not set
# CONFIG_B44 is not set
+# CONFIG_CS89x0 is not set
# CONFIG_NET_POCKET is not set
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
@@ -735,6 +723,7 @@ CONFIG_MOUSE_PS2_LOGIPS2PP=y
CONFIG_MOUSE_PS2_SYNAPTICS=y
CONFIG_MOUSE_PS2_LIFEBOOK=y
CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
# CONFIG_MOUSE_PS2_TOUCHKIT is not set
CONFIG_MOUSE_SERIAL=m
# CONFIG_MOUSE_INPORT is not set
@@ -832,11 +821,11 @@ CONFIG_GEN_RTC_X=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -846,6 +835,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -871,6 +861,7 @@ CONFIG_SSB_POSSIBLE=y
CONFIG_FB=y
# CONFIG_FIRMWARE_EDID is not set
# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
@@ -905,6 +896,8 @@ CONFIG_FB_HP300=y
# CONFIG_FB_S1D13XXX is not set
# CONFIG_FB_ATY is not set
# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
@@ -930,6 +923,7 @@ CONFIG_LOGO_LINUX_VGA16=y
CONFIG_LOGO_LINUX_CLUT224=y
CONFIG_LOGO_MAC_CLUT224=y
CONFIG_SOUND=m
+CONFIG_SOUND_OSS_CORE=y
CONFIG_DMASOUND_ATARI=m
CONFIG_DMASOUND_PAULA=m
CONFIG_DMASOUND_Q40=m
@@ -938,6 +932,12 @@ CONFIG_HID_SUPPORT=y
CONFIG_HID=m
# CONFIG_HID_DEBUG is not set
CONFIG_HIDRAW=y
+# CONFIG_HID_PID is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
# CONFIG_USB_SUPPORT is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -947,6 +947,8 @@ CONFIG_HIDRAW=y
# CONFIG_DMADEVICES is not set
# CONFIG_AUXDISPLAY is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+CONFIG_STAGING_EXCLUDE_BUILD=y
#
# Character devices
@@ -973,10 +975,9 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
# CONFIG_EXT3_FS_XATTR is not set
-CONFIG_EXT4DEV_FS=y
-# CONFIG_EXT4DEV_FS_XATTR is not set
+# CONFIG_EXT4_FS is not set
CONFIG_JBD=y
-CONFIG_JBD2=y
+CONFIG_JBD2=m
CONFIG_REISERFS_FS=m
# CONFIG_REISERFS_CHECK is not set
# CONFIG_REISERFS_PROC_INFO is not set
@@ -987,6 +988,7 @@ CONFIG_JFS_FS=m
# CONFIG_JFS_DEBUG is not set
# CONFIG_JFS_STATISTICS is not set
# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
CONFIG_XFS_FS=m
# CONFIG_XFS_QUOTA is not set
# CONFIG_XFS_POSIX_ACL is not set
@@ -998,6 +1000,7 @@ CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
# CONFIG_OCFS2_FS_STATS is not set
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
# CONFIG_OCFS2_DEBUG_FS is not set
+# CONFIG_OCFS2_COMPAT_JBD is not set
CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
@@ -1036,6 +1039,7 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
@@ -1079,6 +1083,7 @@ CONFIG_EXPORTFS=m
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_REGISTER_V4 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
CONFIG_SMB_FS=m
@@ -1156,7 +1161,13 @@ CONFIG_MAGIC_SYSRQ=y
# CONFIG_DEBUG_KERNEL is not set
CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
+
+#
+# Tracers
+#
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
#
@@ -1164,6 +1175,7 @@ CONFIG_SYSCTL_SYSCALL_CHECK=y
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_XOR_BLOCKS=m
CONFIG_ASYNC_CORE=m
@@ -1174,10 +1186,12 @@ CONFIG_CRYPTO=y
#
# Crypto core or helper
#
+# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD=y
CONFIG_CRYPTO_BLKCIPHER=y
CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_RNG=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_GF128MUL=m
CONFIG_CRYPTO_NULL=m
@@ -1251,14 +1265,17 @@ CONFIG_CRYPTO_TWOFISH_COMMON=m
#
CONFIG_CRYPTO_DEFLATE=m
CONFIG_CRYPTO_LZO=m
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
# CONFIG_CRYPTO_HW is not set
#
# Library routines
#
CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
-# CONFIG_GENERIC_FIND_NEXT_BIT is not set
CONFIG_CRC_CCITT=m
CONFIG_CRC16=y
CONFIG_CRC_T10DIF=y
diff --git a/arch/m68k/configs/mvme147_defconfig b/arch/m68k/configs/mvme147_defconfig
index cacb5aef6a3..52d42715bd0 100644
--- a/arch/m68k/configs/mvme147_defconfig
+++ b/arch/m68k/configs/mvme147_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27-rc6
-# Wed Sep 10 09:02:08 2008
+# Linux kernel version: 2.6.28-rc7
+# Tue Dec 2 20:27:50 2008
#
CONFIG_M68K=y
CONFIG_MMU=y
@@ -14,7 +14,6 @@ CONFIG_TIME_LOW_RES=y
CONFIG_GENERIC_IOMAP=y
CONFIG_NO_IOPORT=y
# CONFIG_NO_DMA is not set
-CONFIG_ARCH_SUPPORTS_AOUT=y
CONFIG_HZ=100
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -67,22 +66,13 @@ CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
# CONFIG_MARKERS is not set
-# CONFIG_HAVE_OPROFILE is not set
-# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set
-# CONFIG_HAVE_IOREMAP_PROT is not set
-# CONFIG_HAVE_KPROBES is not set
-# CONFIG_HAVE_KRETPROBES is not set
-# CONFIG_HAVE_ARCH_TRACEHOOK is not set
-# CONFIG_HAVE_DMA_ATTRS is not set
-# CONFIG_USE_GENERIC_SMP_HELPERS is not set
-# CONFIG_HAVE_CLK is not set
-CONFIG_PROC_PAGE_MONITOR=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -115,11 +105,11 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_FREEZER is not set
#
# Platform dependent setup
#
-# CONFIG_SUN3 is not set
# CONFIG_AMIGA is not set
# CONFIG_ATARI is not set
# CONFIG_MAC is not set
@@ -151,19 +141,21 @@ CONFIG_DISCONTIGMEM_MANUAL=y
CONFIG_DISCONTIGMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_NEED_MULTIPLE_NODES=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
#
# General setup
#
CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
CONFIG_BINFMT_AOUT=m
CONFIG_BINFMT_MISC=m
CONFIG_PROC_HARDWARE=y
@@ -212,7 +204,6 @@ CONFIG_INET_TCP_DIAG=m
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
-# CONFIG_IP_VS is not set
CONFIG_IPV6=m
CONFIG_IPV6_PRIVACY=y
CONFIG_IPV6_ROUTER_PREF=y
@@ -262,13 +253,14 @@ CONFIG_NF_CONNTRACK_SANE=m
CONFIG_NF_CONNTRACK_SIP=m
CONFIG_NF_CONNTRACK_TFTP=m
# CONFIG_NF_CT_NETLINK is not set
+# CONFIG_NETFILTER_TPROXY is not set
CONFIG_NETFILTER_XTABLES=m
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
CONFIG_NETFILTER_XT_TARGET_DSCP=m
CONFIG_NETFILTER_XT_TARGET_MARK=m
-CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
CONFIG_NETFILTER_XT_TARGET_RATEEST=m
CONFIG_NETFILTER_XT_TARGET_TRACE=m
@@ -282,19 +274,22 @@ CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
CONFIG_NETFILTER_XT_MATCH_DCCP=m
CONFIG_NETFILTER_XT_MATCH_DSCP=m
CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
CONFIG_NETFILTER_XT_MATCH_HELPER=m
CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
CONFIG_NETFILTER_XT_MATCH_MAC=m
CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_OWNER=m
CONFIG_NETFILTER_XT_MATCH_POLICY=m
-CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_QUOTA=m
CONFIG_NETFILTER_XT_MATCH_RATEEST=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_RECENT=m
+# CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT is not set
CONFIG_NETFILTER_XT_MATCH_SCTP=m
CONFIG_NETFILTER_XT_MATCH_STATE=m
CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
@@ -302,20 +297,20 @@ CONFIG_NETFILTER_XT_MATCH_STRING=m
CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
CONFIG_NETFILTER_XT_MATCH_TIME=m
CONFIG_NETFILTER_XT_MATCH_U32=m
-CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+# CONFIG_IP_VS is not set
#
# IP: Netfilter Configuration
#
+CONFIG_NF_DEFRAG_IPV4=m
CONFIG_NF_CONNTRACK_IPV4=m
CONFIG_NF_CONNTRACK_PROC_COMPAT=y
CONFIG_IP_NF_QUEUE=m
CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_RECENT=m
-CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IP_NF_TARGET_LOG=m
@@ -323,8 +318,8 @@ CONFIG_IP_NF_TARGET_ULOG=m
CONFIG_NF_NAT=m
CONFIG_NF_NAT_NEEDED=y
CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
CONFIG_NF_NAT_SNMP_BASIC=m
CONFIG_NF_NAT_PROTO_GRE=m
CONFIG_NF_NAT_PROTO_UDPLITE=m
@@ -337,9 +332,9 @@ CONFIG_NF_NAT_PPTP=m
CONFIG_NF_NAT_H323=m
CONFIG_NF_NAT_SIP=m
CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
CONFIG_IP_NF_TARGET_ECN=m
CONFIG_IP_NF_TARGET_TTL=m
-CONFIG_IP_NF_TARGET_CLUSTERIP=m
CONFIG_IP_NF_RAW=m
CONFIG_IP_NF_ARPTABLES=m
CONFIG_IP_NF_ARPFILTER=m
@@ -351,16 +346,16 @@ CONFIG_IP_NF_ARP_MANGLE=m
CONFIG_NF_CONNTRACK_IPV6=m
CONFIG_IP6_NF_QUEUE=m
CONFIG_IP6_NF_IPTABLES=m
-CONFIG_IP6_NF_MATCH_RT=m
-CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
CONFIG_IP6_NF_MATCH_HL=m
CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-CONFIG_IP6_NF_MATCH_AH=m
CONFIG_IP6_NF_MATCH_MH=m
-CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_MATCH_RT=m
CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_FILTER=m
CONFIG_IP6_NF_TARGET_REJECT=m
CONFIG_IP6_NF_MANGLE=m
CONFIG_IP6_NF_TARGET_HL=m
@@ -387,6 +382,7 @@ CONFIG_SCTP_HMAC_MD5=y
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
CONFIG_LLC=m
@@ -410,19 +406,8 @@ CONFIG_NET_CLS_ROUTE=y
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
-# CONFIG_CFG80211 is not set
-CONFIG_WIRELESS_EXT=y
-# CONFIG_WIRELESS_EXT_SYSFS is not set
-# CONFIG_MAC80211 is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
-CONFIG_IEEE80211_CRYPT_TKIP=m
+# CONFIG_PHONET is not set
+# CONFIG_WIRELESS is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -460,6 +445,7 @@ CONFIG_ATA_OVER_ETH=m
CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -544,6 +530,9 @@ CONFIG_MVME147_NET=y
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
# CONFIG_B44 is not set
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
@@ -613,6 +602,7 @@ CONFIG_MOUSE_PS2_LOGIPS2PP=y
CONFIG_MOUSE_PS2_SYNAPTICS=y
CONFIG_MOUSE_PS2_LIFEBOOK=y
CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
# CONFIG_MOUSE_PS2_TOUCHKIT is not set
CONFIG_MOUSE_SERIAL=m
# CONFIG_MOUSE_VSXXXAA is not set
@@ -667,11 +657,11 @@ CONFIG_GEN_RTC_X=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -681,6 +671,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -720,6 +711,12 @@ CONFIG_HID_SUPPORT=y
CONFIG_HID=m
# CONFIG_HID_DEBUG is not set
CONFIG_HIDRAW=y
+# CONFIG_HID_PID is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
# CONFIG_USB_SUPPORT is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -728,6 +725,8 @@ CONFIG_HIDRAW=y
# CONFIG_RTC_CLASS is not set
# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+CONFIG_STAGING_EXCLUDE_BUILD=y
#
# Character devices
@@ -743,8 +742,9 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
# CONFIG_EXT3_FS_XATTR is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
CONFIG_JBD=y
+CONFIG_JBD2=m
CONFIG_REISERFS_FS=m
# CONFIG_REISERFS_CHECK is not set
# CONFIG_REISERFS_PROC_INFO is not set
@@ -755,6 +755,7 @@ CONFIG_JFS_FS=m
# CONFIG_JFS_DEBUG is not set
# CONFIG_JFS_STATISTICS is not set
# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
CONFIG_XFS_FS=m
# CONFIG_XFS_QUOTA is not set
# CONFIG_XFS_POSIX_ACL is not set
@@ -766,6 +767,7 @@ CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
# CONFIG_OCFS2_FS_STATS is not set
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
# CONFIG_OCFS2_DEBUG_FS is not set
+# CONFIG_OCFS2_COMPAT_JBD is not set
CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
@@ -804,6 +806,7 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
@@ -847,6 +850,7 @@ CONFIG_EXPORTFS=m
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_REGISTER_V4 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
CONFIG_SMB_FS=m
@@ -920,7 +924,13 @@ CONFIG_MAGIC_SYSRQ=y
# CONFIG_DEBUG_KERNEL is not set
CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
+
+#
+# Tracers
+#
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
#
@@ -928,6 +938,7 @@ CONFIG_SYSCTL_SYSCALL_CHECK=y
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_XOR_BLOCKS=m
CONFIG_ASYNC_CORE=m
@@ -938,10 +949,12 @@ CONFIG_CRYPTO=y
#
# Crypto core or helper
#
+# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD=y
CONFIG_CRYPTO_BLKCIPHER=y
CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_RNG=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_GF128MUL=m
CONFIG_CRYPTO_NULL=m
@@ -1015,14 +1028,17 @@ CONFIG_CRYPTO_TWOFISH_COMMON=m
#
CONFIG_CRYPTO_DEFLATE=m
CONFIG_CRYPTO_LZO=m
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
# CONFIG_CRYPTO_HW is not set
#
# Library routines
#
CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
-# CONFIG_GENERIC_FIND_NEXT_BIT is not set
CONFIG_CRC_CCITT=m
CONFIG_CRC16=m
CONFIG_CRC_T10DIF=y
diff --git a/arch/m68k/configs/mvme16x_defconfig b/arch/m68k/configs/mvme16x_defconfig
index a183e25e348..3403ed2eda7 100644
--- a/arch/m68k/configs/mvme16x_defconfig
+++ b/arch/m68k/configs/mvme16x_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27-rc6
-# Wed Sep 10 09:02:09 2008
+# Linux kernel version: 2.6.28-rc7
+# Tue Dec 2 20:27:51 2008
#
CONFIG_M68K=y
CONFIG_MMU=y
@@ -14,7 +14,6 @@ CONFIG_TIME_LOW_RES=y
CONFIG_GENERIC_IOMAP=y
CONFIG_NO_IOPORT=y
# CONFIG_NO_DMA is not set
-CONFIG_ARCH_SUPPORTS_AOUT=y
CONFIG_HZ=100
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -67,22 +66,13 @@ CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
# CONFIG_MARKERS is not set
-# CONFIG_HAVE_OPROFILE is not set
-# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set
-# CONFIG_HAVE_IOREMAP_PROT is not set
-# CONFIG_HAVE_KPROBES is not set
-# CONFIG_HAVE_KRETPROBES is not set
-# CONFIG_HAVE_ARCH_TRACEHOOK is not set
-# CONFIG_HAVE_DMA_ATTRS is not set
-# CONFIG_USE_GENERIC_SMP_HELPERS is not set
-# CONFIG_HAVE_CLK is not set
-CONFIG_PROC_PAGE_MONITOR=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -115,11 +105,11 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_FREEZER is not set
#
# Platform dependent setup
#
-# CONFIG_SUN3 is not set
# CONFIG_AMIGA is not set
# CONFIG_ATARI is not set
# CONFIG_MAC is not set
@@ -151,19 +141,21 @@ CONFIG_DISCONTIGMEM_MANUAL=y
CONFIG_DISCONTIGMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_NEED_MULTIPLE_NODES=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
#
# General setup
#
CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
CONFIG_BINFMT_AOUT=m
CONFIG_BINFMT_MISC=m
CONFIG_PROC_HARDWARE=y
@@ -212,7 +204,6 @@ CONFIG_INET_TCP_DIAG=m
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
-# CONFIG_IP_VS is not set
CONFIG_IPV6=m
CONFIG_IPV6_PRIVACY=y
CONFIG_IPV6_ROUTER_PREF=y
@@ -262,13 +253,14 @@ CONFIG_NF_CONNTRACK_SANE=m
CONFIG_NF_CONNTRACK_SIP=m
CONFIG_NF_CONNTRACK_TFTP=m
# CONFIG_NF_CT_NETLINK is not set
+# CONFIG_NETFILTER_TPROXY is not set
CONFIG_NETFILTER_XTABLES=m
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
CONFIG_NETFILTER_XT_TARGET_DSCP=m
CONFIG_NETFILTER_XT_TARGET_MARK=m
-CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
CONFIG_NETFILTER_XT_TARGET_RATEEST=m
CONFIG_NETFILTER_XT_TARGET_TRACE=m
@@ -282,19 +274,22 @@ CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
CONFIG_NETFILTER_XT_MATCH_DCCP=m
CONFIG_NETFILTER_XT_MATCH_DSCP=m
CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
CONFIG_NETFILTER_XT_MATCH_HELPER=m
CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
CONFIG_NETFILTER_XT_MATCH_MAC=m
CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_OWNER=m
CONFIG_NETFILTER_XT_MATCH_POLICY=m
-CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_QUOTA=m
CONFIG_NETFILTER_XT_MATCH_RATEEST=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_RECENT=m
+# CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT is not set
CONFIG_NETFILTER_XT_MATCH_SCTP=m
CONFIG_NETFILTER_XT_MATCH_STATE=m
CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
@@ -302,20 +297,20 @@ CONFIG_NETFILTER_XT_MATCH_STRING=m
CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
CONFIG_NETFILTER_XT_MATCH_TIME=m
CONFIG_NETFILTER_XT_MATCH_U32=m
-CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+# CONFIG_IP_VS is not set
#
# IP: Netfilter Configuration
#
+CONFIG_NF_DEFRAG_IPV4=m
CONFIG_NF_CONNTRACK_IPV4=m
CONFIG_NF_CONNTRACK_PROC_COMPAT=y
CONFIG_IP_NF_QUEUE=m
CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_RECENT=m
-CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IP_NF_TARGET_LOG=m
@@ -323,8 +318,8 @@ CONFIG_IP_NF_TARGET_ULOG=m
CONFIG_NF_NAT=m
CONFIG_NF_NAT_NEEDED=y
CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
CONFIG_NF_NAT_SNMP_BASIC=m
CONFIG_NF_NAT_PROTO_GRE=m
CONFIG_NF_NAT_PROTO_UDPLITE=m
@@ -337,9 +332,9 @@ CONFIG_NF_NAT_PPTP=m
CONFIG_NF_NAT_H323=m
CONFIG_NF_NAT_SIP=m
CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
CONFIG_IP_NF_TARGET_ECN=m
CONFIG_IP_NF_TARGET_TTL=m
-CONFIG_IP_NF_TARGET_CLUSTERIP=m
CONFIG_IP_NF_RAW=m
CONFIG_IP_NF_ARPTABLES=m
CONFIG_IP_NF_ARPFILTER=m
@@ -351,16 +346,16 @@ CONFIG_IP_NF_ARP_MANGLE=m
CONFIG_NF_CONNTRACK_IPV6=m
CONFIG_IP6_NF_QUEUE=m
CONFIG_IP6_NF_IPTABLES=m
-CONFIG_IP6_NF_MATCH_RT=m
-CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
CONFIG_IP6_NF_MATCH_HL=m
CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-CONFIG_IP6_NF_MATCH_AH=m
CONFIG_IP6_NF_MATCH_MH=m
-CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_MATCH_RT=m
CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_FILTER=m
CONFIG_IP6_NF_TARGET_REJECT=m
CONFIG_IP6_NF_MANGLE=m
CONFIG_IP6_NF_TARGET_HL=m
@@ -387,6 +382,7 @@ CONFIG_SCTP_HMAC_MD5=y
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
CONFIG_LLC=m
@@ -410,19 +406,8 @@ CONFIG_NET_CLS_ROUTE=y
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
-# CONFIG_CFG80211 is not set
-CONFIG_WIRELESS_EXT=y
-# CONFIG_WIRELESS_EXT_SYSFS is not set
-# CONFIG_MAC80211 is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
-CONFIG_IEEE80211_CRYPT_TKIP=m
+# CONFIG_PHONET is not set
+# CONFIG_WIRELESS is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -460,6 +445,7 @@ CONFIG_ATA_OVER_ETH=m
CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -545,6 +531,9 @@ CONFIG_MVME16x_NET=y
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
# CONFIG_B44 is not set
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
@@ -614,6 +603,7 @@ CONFIG_MOUSE_PS2_LOGIPS2PP=y
CONFIG_MOUSE_PS2_SYNAPTICS=y
CONFIG_MOUSE_PS2_LIFEBOOK=y
CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
# CONFIG_MOUSE_PS2_TOUCHKIT is not set
CONFIG_MOUSE_SERIAL=m
# CONFIG_MOUSE_VSXXXAA is not set
@@ -668,11 +658,11 @@ CONFIG_GEN_RTC_X=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -682,6 +672,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -721,6 +712,12 @@ CONFIG_HID_SUPPORT=y
CONFIG_HID=m
# CONFIG_HID_DEBUG is not set
CONFIG_HIDRAW=y
+# CONFIG_HID_PID is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
# CONFIG_USB_SUPPORT is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -729,6 +726,8 @@ CONFIG_HIDRAW=y
# CONFIG_RTC_CLASS is not set
# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+CONFIG_STAGING_EXCLUDE_BUILD=y
#
# Character devices
@@ -745,8 +744,9 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
# CONFIG_EXT3_FS_XATTR is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
CONFIG_JBD=y
+CONFIG_JBD2=m
CONFIG_REISERFS_FS=m
# CONFIG_REISERFS_CHECK is not set
# CONFIG_REISERFS_PROC_INFO is not set
@@ -757,6 +757,7 @@ CONFIG_JFS_FS=m
# CONFIG_JFS_DEBUG is not set
# CONFIG_JFS_STATISTICS is not set
# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
CONFIG_XFS_FS=m
# CONFIG_XFS_QUOTA is not set
# CONFIG_XFS_POSIX_ACL is not set
@@ -768,6 +769,7 @@ CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
# CONFIG_OCFS2_FS_STATS is not set
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
# CONFIG_OCFS2_DEBUG_FS is not set
+# CONFIG_OCFS2_COMPAT_JBD is not set
CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
@@ -806,6 +808,7 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
@@ -849,6 +852,7 @@ CONFIG_EXPORTFS=m
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_REGISTER_V4 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
CONFIG_SMB_FS=m
@@ -922,7 +926,13 @@ CONFIG_MAGIC_SYSRQ=y
# CONFIG_DEBUG_KERNEL is not set
CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
+
+#
+# Tracers
+#
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
#
@@ -930,6 +940,7 @@ CONFIG_SYSCTL_SYSCALL_CHECK=y
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_XOR_BLOCKS=m
CONFIG_ASYNC_CORE=m
@@ -940,10 +951,12 @@ CONFIG_CRYPTO=y
#
# Crypto core or helper
#
+# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD=y
CONFIG_CRYPTO_BLKCIPHER=y
CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_RNG=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_GF128MUL=m
CONFIG_CRYPTO_NULL=m
@@ -1017,14 +1030,17 @@ CONFIG_CRYPTO_TWOFISH_COMMON=m
#
CONFIG_CRYPTO_DEFLATE=m
CONFIG_CRYPTO_LZO=m
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
# CONFIG_CRYPTO_HW is not set
#
# Library routines
#
CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
-# CONFIG_GENERIC_FIND_NEXT_BIT is not set
CONFIG_CRC_CCITT=m
CONFIG_CRC16=m
CONFIG_CRC_T10DIF=y
diff --git a/arch/m68k/configs/q40_defconfig b/arch/m68k/configs/q40_defconfig
index 72eaff0776b..3459c594194 100644
--- a/arch/m68k/configs/q40_defconfig
+++ b/arch/m68k/configs/q40_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27-rc6
-# Wed Sep 10 09:02:10 2008
+# Linux kernel version: 2.6.28-rc7
+# Tue Dec 2 20:27:52 2008
#
CONFIG_M68K=y
CONFIG_MMU=y
@@ -14,7 +14,6 @@ CONFIG_TIME_LOW_RES=y
CONFIG_GENERIC_IOMAP=y
CONFIG_NO_IOPORT=y
# CONFIG_NO_DMA is not set
-CONFIG_ARCH_SUPPORTS_AOUT=y
CONFIG_HZ=100
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -67,22 +66,13 @@ CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
# CONFIG_MARKERS is not set
-# CONFIG_HAVE_OPROFILE is not set
-# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set
-# CONFIG_HAVE_IOREMAP_PROT is not set
-# CONFIG_HAVE_KPROBES is not set
-# CONFIG_HAVE_KRETPROBES is not set
-# CONFIG_HAVE_ARCH_TRACEHOOK is not set
-# CONFIG_HAVE_DMA_ATTRS is not set
-# CONFIG_USE_GENERIC_SMP_HELPERS is not set
-# CONFIG_HAVE_CLK is not set
-CONFIG_PROC_PAGE_MONITOR=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -115,11 +105,11 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_FREEZER is not set
#
# Platform dependent setup
#
-# CONFIG_SUN3 is not set
# CONFIG_AMIGA is not set
# CONFIG_ATARI is not set
# CONFIG_MAC is not set
@@ -148,19 +138,21 @@ CONFIG_DISCONTIGMEM_MANUAL=y
CONFIG_DISCONTIGMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_NEED_MULTIPLE_NODES=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
#
# General setup
#
CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
CONFIG_BINFMT_AOUT=m
CONFIG_BINFMT_MISC=m
CONFIG_HEARTBEAT=y
@@ -209,7 +201,6 @@ CONFIG_INET_TCP_DIAG=m
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
-# CONFIG_IP_VS is not set
CONFIG_IPV6=m
CONFIG_IPV6_PRIVACY=y
CONFIG_IPV6_ROUTER_PREF=y
@@ -259,13 +250,14 @@ CONFIG_NF_CONNTRACK_SANE=m
CONFIG_NF_CONNTRACK_SIP=m
CONFIG_NF_CONNTRACK_TFTP=m
# CONFIG_NF_CT_NETLINK is not set
+# CONFIG_NETFILTER_TPROXY is not set
CONFIG_NETFILTER_XTABLES=m
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
CONFIG_NETFILTER_XT_TARGET_DSCP=m
CONFIG_NETFILTER_XT_TARGET_MARK=m
-CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
CONFIG_NETFILTER_XT_TARGET_RATEEST=m
CONFIG_NETFILTER_XT_TARGET_TRACE=m
@@ -279,19 +271,22 @@ CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
CONFIG_NETFILTER_XT_MATCH_DCCP=m
CONFIG_NETFILTER_XT_MATCH_DSCP=m
CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
CONFIG_NETFILTER_XT_MATCH_HELPER=m
CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
CONFIG_NETFILTER_XT_MATCH_MAC=m
CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_OWNER=m
CONFIG_NETFILTER_XT_MATCH_POLICY=m
-CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_QUOTA=m
CONFIG_NETFILTER_XT_MATCH_RATEEST=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_RECENT=m
+# CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT is not set
CONFIG_NETFILTER_XT_MATCH_SCTP=m
CONFIG_NETFILTER_XT_MATCH_STATE=m
CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
@@ -299,20 +294,20 @@ CONFIG_NETFILTER_XT_MATCH_STRING=m
CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
CONFIG_NETFILTER_XT_MATCH_TIME=m
CONFIG_NETFILTER_XT_MATCH_U32=m
-CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+# CONFIG_IP_VS is not set
#
# IP: Netfilter Configuration
#
+CONFIG_NF_DEFRAG_IPV4=m
CONFIG_NF_CONNTRACK_IPV4=m
CONFIG_NF_CONNTRACK_PROC_COMPAT=y
CONFIG_IP_NF_QUEUE=m
CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_RECENT=m
-CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IP_NF_TARGET_LOG=m
@@ -320,8 +315,8 @@ CONFIG_IP_NF_TARGET_ULOG=m
CONFIG_NF_NAT=m
CONFIG_NF_NAT_NEEDED=y
CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
CONFIG_NF_NAT_SNMP_BASIC=m
CONFIG_NF_NAT_PROTO_GRE=m
CONFIG_NF_NAT_PROTO_UDPLITE=m
@@ -334,9 +329,9 @@ CONFIG_NF_NAT_PPTP=m
CONFIG_NF_NAT_H323=m
CONFIG_NF_NAT_SIP=m
CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
CONFIG_IP_NF_TARGET_ECN=m
CONFIG_IP_NF_TARGET_TTL=m
-CONFIG_IP_NF_TARGET_CLUSTERIP=m
CONFIG_IP_NF_RAW=m
CONFIG_IP_NF_ARPTABLES=m
CONFIG_IP_NF_ARPFILTER=m
@@ -348,16 +343,16 @@ CONFIG_IP_NF_ARP_MANGLE=m
CONFIG_NF_CONNTRACK_IPV6=m
CONFIG_IP6_NF_QUEUE=m
CONFIG_IP6_NF_IPTABLES=m
-CONFIG_IP6_NF_MATCH_RT=m
-CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
CONFIG_IP6_NF_MATCH_HL=m
CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-CONFIG_IP6_NF_MATCH_AH=m
CONFIG_IP6_NF_MATCH_MH=m
-CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_MATCH_RT=m
CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_FILTER=m
CONFIG_IP6_NF_TARGET_REJECT=m
CONFIG_IP6_NF_MANGLE=m
CONFIG_IP6_NF_TARGET_HL=m
@@ -384,6 +379,7 @@ CONFIG_SCTP_HMAC_MD5=y
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
CONFIG_LLC=m
@@ -407,19 +403,8 @@ CONFIG_NET_CLS_ROUTE=y
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
-# CONFIG_CFG80211 is not set
-CONFIG_WIRELESS_EXT=y
-# CONFIG_WIRELESS_EXT_SYSFS is not set
-# CONFIG_MAC80211 is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
-CONFIG_IEEE80211_CRYPT_TKIP=m
+# CONFIG_PHONET is not set
+# CONFIG_WIRELESS is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -458,21 +443,20 @@ CONFIG_ATA_OVER_ETH=m
CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
CONFIG_IDE=y
-CONFIG_BLK_DEV_IDE=y
#
# Please see Documentation/ide/ide.txt for help/info on IDE drives
#
-CONFIG_IDE_ATAPI=y
# CONFIG_BLK_DEV_IDE_SATA is not set
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_IDE_GD=y
+CONFIG_IDE_GD_ATA=y
+# CONFIG_IDE_GD_ATAPI is not set
CONFIG_BLK_DEV_IDECD=y
CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y
# CONFIG_BLK_DEV_IDETAPE is not set
-CONFIG_BLK_DEV_IDEFLOPPY=m
# CONFIG_BLK_DEV_IDESCSI is not set
# CONFIG_IDE_TASK_IOCTL is not set
CONFIG_IDE_PROC_FS=y
@@ -585,8 +569,12 @@ CONFIG_NE2000=m
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
# CONFIG_NET_PCI is not set
# CONFIG_B44 is not set
+# CONFIG_CS89x0 is not set
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
# CONFIG_TR is not set
@@ -656,6 +644,7 @@ CONFIG_MOUSE_PS2_LOGIPS2PP=y
CONFIG_MOUSE_PS2_SYNAPTICS=y
CONFIG_MOUSE_PS2_LIFEBOOK=y
CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
# CONFIG_MOUSE_PS2_TOUCHKIT is not set
CONFIG_MOUSE_SERIAL=m
# CONFIG_MOUSE_INPORT is not set
@@ -717,11 +706,11 @@ CONFIG_GEN_RTC_X=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -731,6 +720,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -756,6 +746,7 @@ CONFIG_SSB_POSSIBLE=y
CONFIG_FB=y
# CONFIG_FIRMWARE_EDID is not set
# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
@@ -778,6 +769,8 @@ CONFIG_FB_Q40=y
# CONFIG_FB_UVESA is not set
# CONFIG_FB_S1D13XXX is not set
# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
@@ -800,12 +793,19 @@ CONFIG_LOGO_LINUX_MONO=y
CONFIG_LOGO_LINUX_VGA16=y
CONFIG_LOGO_LINUX_CLUT224=y
CONFIG_SOUND=m
+CONFIG_SOUND_OSS_CORE=y
CONFIG_DMASOUND_Q40=m
CONFIG_DMASOUND=m
CONFIG_HID_SUPPORT=y
CONFIG_HID=m
# CONFIG_HID_DEBUG is not set
CONFIG_HIDRAW=y
+# CONFIG_HID_PID is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
# CONFIG_USB_SUPPORT is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -814,6 +814,8 @@ CONFIG_HIDRAW=y
# CONFIG_RTC_CLASS is not set
# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+CONFIG_STAGING_EXCLUDE_BUILD=y
#
# Character devices
@@ -827,8 +829,9 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
# CONFIG_EXT3_FS_XATTR is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
CONFIG_JBD=y
+CONFIG_JBD2=m
CONFIG_REISERFS_FS=m
# CONFIG_REISERFS_CHECK is not set
# CONFIG_REISERFS_PROC_INFO is not set
@@ -839,6 +842,7 @@ CONFIG_JFS_FS=m
# CONFIG_JFS_DEBUG is not set
# CONFIG_JFS_STATISTICS is not set
# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
CONFIG_XFS_FS=m
# CONFIG_XFS_QUOTA is not set
# CONFIG_XFS_POSIX_ACL is not set
@@ -850,6 +854,7 @@ CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
# CONFIG_OCFS2_FS_STATS is not set
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
# CONFIG_OCFS2_DEBUG_FS is not set
+# CONFIG_OCFS2_COMPAT_JBD is not set
CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
@@ -888,6 +893,7 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
@@ -930,6 +936,7 @@ CONFIG_EXPORTFS=m
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_REGISTER_V4 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
CONFIG_SMB_FS=m
@@ -1002,7 +1009,13 @@ CONFIG_MAGIC_SYSRQ=y
# CONFIG_DEBUG_KERNEL is not set
CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
+
+#
+# Tracers
+#
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
#
@@ -1010,6 +1023,7 @@ CONFIG_SYSCTL_SYSCALL_CHECK=y
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_XOR_BLOCKS=m
CONFIG_ASYNC_CORE=m
@@ -1020,10 +1034,12 @@ CONFIG_CRYPTO=y
#
# Crypto core or helper
#
+# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD=y
CONFIG_CRYPTO_BLKCIPHER=y
CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_RNG=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_GF128MUL=m
CONFIG_CRYPTO_NULL=m
@@ -1097,14 +1113,17 @@ CONFIG_CRYPTO_TWOFISH_COMMON=m
#
CONFIG_CRYPTO_DEFLATE=m
CONFIG_CRYPTO_LZO=m
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
# CONFIG_CRYPTO_HW is not set
#
# Library routines
#
CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
-# CONFIG_GENERIC_FIND_NEXT_BIT is not set
CONFIG_CRC_CCITT=m
CONFIG_CRC16=m
CONFIG_CRC_T10DIF=y
diff --git a/arch/m68k/configs/sun3_defconfig b/arch/m68k/configs/sun3_defconfig
index cb62b96d766..f404917429f 100644
--- a/arch/m68k/configs/sun3_defconfig
+++ b/arch/m68k/configs/sun3_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27-rc6
-# Wed Sep 10 09:02:11 2008
+# Linux kernel version: 2.6.28-rc7
+# Tue Dec 2 20:27:53 2008
#
CONFIG_M68K=y
CONFIG_MMU=y
@@ -14,7 +14,6 @@ CONFIG_TIME_LOW_RES=y
CONFIG_GENERIC_IOMAP=y
CONFIG_NO_IOPORT=y
CONFIG_NO_DMA=y
-CONFIG_ARCH_SUPPORTS_AOUT=y
CONFIG_HZ=100
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -67,22 +66,13 @@ CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
# CONFIG_MARKERS is not set
-# CONFIG_HAVE_OPROFILE is not set
-# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set
-# CONFIG_HAVE_IOREMAP_PROT is not set
-# CONFIG_HAVE_KPROBES is not set
-# CONFIG_HAVE_KRETPROBES is not set
-# CONFIG_HAVE_ARCH_TRACEHOOK is not set
-# CONFIG_HAVE_DMA_ATTRS is not set
-# CONFIG_USE_GENERIC_SMP_HELPERS is not set
-# CONFIG_HAVE_CLK is not set
-CONFIG_PROC_PAGE_MONITOR=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -115,10 +105,19 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_FREEZER is not set
#
# Platform dependent setup
#
+# CONFIG_AMIGA is not set
+# CONFIG_ATARI is not set
+# CONFIG_MAC is not set
+# CONFIG_APOLLO is not set
+# CONFIG_VME is not set
+# CONFIG_HP300 is not set
+# CONFIG_SUN3X is not set
+# CONFIG_Q40 is not set
CONFIG_SUN3=y
#
@@ -137,19 +136,21 @@ CONFIG_FLATMEM_MANUAL=y
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_NEED_MULTIPLE_NODES=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
#
# General setup
#
CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
CONFIG_BINFMT_AOUT=m
CONFIG_BINFMT_MISC=m
CONFIG_PROC_HARDWARE=y
@@ -198,7 +199,6 @@ CONFIG_INET_TCP_DIAG=m
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
-# CONFIG_IP_VS is not set
CONFIG_IPV6=m
CONFIG_IPV6_PRIVACY=y
CONFIG_IPV6_ROUTER_PREF=y
@@ -248,13 +248,14 @@ CONFIG_NF_CONNTRACK_SANE=m
CONFIG_NF_CONNTRACK_SIP=m
CONFIG_NF_CONNTRACK_TFTP=m
# CONFIG_NF_CT_NETLINK is not set
+# CONFIG_NETFILTER_TPROXY is not set
CONFIG_NETFILTER_XTABLES=m
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
CONFIG_NETFILTER_XT_TARGET_DSCP=m
CONFIG_NETFILTER_XT_TARGET_MARK=m
-CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
CONFIG_NETFILTER_XT_TARGET_RATEEST=m
CONFIG_NETFILTER_XT_TARGET_TRACE=m
@@ -268,19 +269,22 @@ CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
CONFIG_NETFILTER_XT_MATCH_DCCP=m
CONFIG_NETFILTER_XT_MATCH_DSCP=m
CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
CONFIG_NETFILTER_XT_MATCH_HELPER=m
CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
CONFIG_NETFILTER_XT_MATCH_MAC=m
CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_OWNER=m
CONFIG_NETFILTER_XT_MATCH_POLICY=m
-CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_QUOTA=m
CONFIG_NETFILTER_XT_MATCH_RATEEST=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_RECENT=m
+# CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT is not set
CONFIG_NETFILTER_XT_MATCH_SCTP=m
CONFIG_NETFILTER_XT_MATCH_STATE=m
CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
@@ -288,20 +292,20 @@ CONFIG_NETFILTER_XT_MATCH_STRING=m
CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
CONFIG_NETFILTER_XT_MATCH_TIME=m
CONFIG_NETFILTER_XT_MATCH_U32=m
-CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+# CONFIG_IP_VS is not set
#
# IP: Netfilter Configuration
#
+CONFIG_NF_DEFRAG_IPV4=m
CONFIG_NF_CONNTRACK_IPV4=m
CONFIG_NF_CONNTRACK_PROC_COMPAT=y
CONFIG_IP_NF_QUEUE=m
CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_RECENT=m
-CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IP_NF_TARGET_LOG=m
@@ -309,8 +313,8 @@ CONFIG_IP_NF_TARGET_ULOG=m
CONFIG_NF_NAT=m
CONFIG_NF_NAT_NEEDED=y
CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
CONFIG_NF_NAT_SNMP_BASIC=m
CONFIG_NF_NAT_PROTO_GRE=m
CONFIG_NF_NAT_PROTO_UDPLITE=m
@@ -323,9 +327,9 @@ CONFIG_NF_NAT_PPTP=m
CONFIG_NF_NAT_H323=m
CONFIG_NF_NAT_SIP=m
CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
CONFIG_IP_NF_TARGET_ECN=m
CONFIG_IP_NF_TARGET_TTL=m
-CONFIG_IP_NF_TARGET_CLUSTERIP=m
CONFIG_IP_NF_RAW=m
CONFIG_IP_NF_ARPTABLES=m
CONFIG_IP_NF_ARPFILTER=m
@@ -337,16 +341,16 @@ CONFIG_IP_NF_ARP_MANGLE=m
CONFIG_NF_CONNTRACK_IPV6=m
CONFIG_IP6_NF_QUEUE=m
CONFIG_IP6_NF_IPTABLES=m
-CONFIG_IP6_NF_MATCH_RT=m
-CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
CONFIG_IP6_NF_MATCH_HL=m
CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-CONFIG_IP6_NF_MATCH_AH=m
CONFIG_IP6_NF_MATCH_MH=m
-CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_MATCH_RT=m
CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_FILTER=m
CONFIG_IP6_NF_TARGET_REJECT=m
CONFIG_IP6_NF_MANGLE=m
CONFIG_IP6_NF_TARGET_HL=m
@@ -373,6 +377,7 @@ CONFIG_SCTP_HMAC_MD5=y
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
CONFIG_LLC=m
@@ -396,19 +401,8 @@ CONFIG_NET_CLS_ROUTE=y
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
-# CONFIG_CFG80211 is not set
-CONFIG_WIRELESS_EXT=y
-# CONFIG_WIRELESS_EXT_SYSFS is not set
-# CONFIG_MAC80211 is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
-CONFIG_IEEE80211_CRYPT_TKIP=m
+# CONFIG_PHONET is not set
+# CONFIG_WIRELESS is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -446,6 +440,7 @@ CONFIG_ATA_OVER_ETH=m
CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -531,6 +526,9 @@ CONFIG_SUN3_82586=y
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
@@ -599,6 +597,7 @@ CONFIG_MOUSE_PS2_LOGIPS2PP=y
CONFIG_MOUSE_PS2_SYNAPTICS=y
CONFIG_MOUSE_PS2_LIFEBOOK=y
CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
# CONFIG_MOUSE_PS2_TOUCHKIT is not set
CONFIG_MOUSE_SERIAL=m
# CONFIG_MOUSE_VSXXXAA is not set
@@ -655,16 +654,13 @@ CONFIG_GEN_RTC_X=y
# CONFIG_WATCHDOG is not set
#
-# Sonics Silicon Backplane
-#
-
-#
# Multifunction device drivers
#
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -690,6 +686,7 @@ CONFIG_GEN_RTC_X=y
CONFIG_FB=y
# CONFIG_FIRMWARE_EDID is not set
# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
# CONFIG_FB_CFB_FILLRECT is not set
# CONFIG_FB_CFB_COPYAREA is not set
# CONFIG_FB_CFB_IMAGEBLIT is not set
@@ -711,6 +708,8 @@ CONFIG_FB=y
# CONFIG_FB_UVESA is not set
# CONFIG_FB_S1D13XXX is not set
# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
@@ -737,6 +736,12 @@ CONFIG_HID_SUPPORT=y
CONFIG_HID=m
# CONFIG_HID_DEBUG is not set
CONFIG_HIDRAW=y
+# CONFIG_HID_PID is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
# CONFIG_USB_SUPPORT is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -744,6 +749,8 @@ CONFIG_HIDRAW=y
# CONFIG_ACCESSIBILITY is not set
# CONFIG_RTC_CLASS is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+CONFIG_STAGING_EXCLUDE_BUILD=y
#
# Character devices
@@ -757,8 +764,9 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
# CONFIG_EXT3_FS_XATTR is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
CONFIG_JBD=y
+CONFIG_JBD2=m
CONFIG_REISERFS_FS=m
# CONFIG_REISERFS_CHECK is not set
# CONFIG_REISERFS_PROC_INFO is not set
@@ -769,6 +777,7 @@ CONFIG_JFS_FS=m
# CONFIG_JFS_DEBUG is not set
# CONFIG_JFS_STATISTICS is not set
# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
CONFIG_XFS_FS=m
# CONFIG_XFS_QUOTA is not set
# CONFIG_XFS_POSIX_ACL is not set
@@ -780,6 +789,7 @@ CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
# CONFIG_OCFS2_FS_STATS is not set
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
# CONFIG_OCFS2_DEBUG_FS is not set
+# CONFIG_OCFS2_COMPAT_JBD is not set
CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
@@ -818,6 +828,7 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
@@ -861,6 +872,7 @@ CONFIG_EXPORTFS=m
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_REGISTER_V4 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
CONFIG_SMB_FS=m
@@ -934,7 +946,13 @@ CONFIG_MAGIC_SYSRQ=y
# CONFIG_DEBUG_KERNEL is not set
CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
+
+#
+# Tracers
+#
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
#
@@ -942,6 +960,7 @@ CONFIG_SYSCTL_SYSCALL_CHECK=y
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_XOR_BLOCKS=m
CONFIG_ASYNC_CORE=m
@@ -952,10 +971,12 @@ CONFIG_CRYPTO=y
#
# Crypto core or helper
#
+# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD=y
CONFIG_CRYPTO_BLKCIPHER=y
CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_RNG=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_GF128MUL=m
CONFIG_CRYPTO_NULL=m
@@ -1029,14 +1050,17 @@ CONFIG_CRYPTO_TWOFISH_COMMON=m
#
CONFIG_CRYPTO_DEFLATE=m
CONFIG_CRYPTO_LZO=m
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
# CONFIG_CRYPTO_HW is not set
#
# Library routines
#
CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
-# CONFIG_GENERIC_FIND_NEXT_BIT is not set
CONFIG_CRC_CCITT=m
CONFIG_CRC16=m
CONFIG_CRC_T10DIF=y
diff --git a/arch/m68k/configs/sun3x_defconfig b/arch/m68k/configs/sun3x_defconfig
index 04b4363a705..4d8a1e84e39 100644
--- a/arch/m68k/configs/sun3x_defconfig
+++ b/arch/m68k/configs/sun3x_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27-rc6
-# Wed Sep 10 09:02:12 2008
+# Linux kernel version: 2.6.28-rc7
+# Tue Dec 2 20:27:54 2008
#
CONFIG_M68K=y
CONFIG_MMU=y
@@ -14,7 +14,6 @@ CONFIG_TIME_LOW_RES=y
CONFIG_GENERIC_IOMAP=y
CONFIG_NO_IOPORT=y
# CONFIG_NO_DMA is not set
-CONFIG_ARCH_SUPPORTS_AOUT=y
CONFIG_HZ=100
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -67,22 +66,13 @@ CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
# CONFIG_MARKERS is not set
-# CONFIG_HAVE_OPROFILE is not set
-# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set
-# CONFIG_HAVE_IOREMAP_PROT is not set
-# CONFIG_HAVE_KPROBES is not set
-# CONFIG_HAVE_KRETPROBES is not set
-# CONFIG_HAVE_ARCH_TRACEHOOK is not set
-# CONFIG_HAVE_DMA_ATTRS is not set
-# CONFIG_USE_GENERIC_SMP_HELPERS is not set
-# CONFIG_HAVE_CLK is not set
-CONFIG_PROC_PAGE_MONITOR=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -115,11 +105,11 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_FREEZER is not set
#
# Platform dependent setup
#
-# CONFIG_SUN3 is not set
# CONFIG_AMIGA is not set
# CONFIG_ATARI is not set
# CONFIG_MAC is not set
@@ -148,19 +138,21 @@ CONFIG_DISCONTIGMEM_MANUAL=y
CONFIG_DISCONTIGMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_NEED_MULTIPLE_NODES=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
#
# General setup
#
CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
CONFIG_BINFMT_AOUT=m
CONFIG_BINFMT_MISC=m
CONFIG_PROC_HARDWARE=y
@@ -209,7 +201,6 @@ CONFIG_INET_TCP_DIAG=m
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
-# CONFIG_IP_VS is not set
CONFIG_IPV6=m
CONFIG_IPV6_PRIVACY=y
CONFIG_IPV6_ROUTER_PREF=y
@@ -259,13 +250,14 @@ CONFIG_NF_CONNTRACK_SANE=m
CONFIG_NF_CONNTRACK_SIP=m
CONFIG_NF_CONNTRACK_TFTP=m
# CONFIG_NF_CT_NETLINK is not set
+# CONFIG_NETFILTER_TPROXY is not set
CONFIG_NETFILTER_XTABLES=m
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
CONFIG_NETFILTER_XT_TARGET_DSCP=m
CONFIG_NETFILTER_XT_TARGET_MARK=m
-CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
CONFIG_NETFILTER_XT_TARGET_RATEEST=m
CONFIG_NETFILTER_XT_TARGET_TRACE=m
@@ -279,19 +271,22 @@ CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
CONFIG_NETFILTER_XT_MATCH_DCCP=m
CONFIG_NETFILTER_XT_MATCH_DSCP=m
CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
CONFIG_NETFILTER_XT_MATCH_HELPER=m
CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
CONFIG_NETFILTER_XT_MATCH_MAC=m
CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_OWNER=m
CONFIG_NETFILTER_XT_MATCH_POLICY=m
-CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_QUOTA=m
CONFIG_NETFILTER_XT_MATCH_RATEEST=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_RECENT=m
+# CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT is not set
CONFIG_NETFILTER_XT_MATCH_SCTP=m
CONFIG_NETFILTER_XT_MATCH_STATE=m
CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
@@ -299,20 +294,20 @@ CONFIG_NETFILTER_XT_MATCH_STRING=m
CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
CONFIG_NETFILTER_XT_MATCH_TIME=m
CONFIG_NETFILTER_XT_MATCH_U32=m
-CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+# CONFIG_IP_VS is not set
#
# IP: Netfilter Configuration
#
+CONFIG_NF_DEFRAG_IPV4=m
CONFIG_NF_CONNTRACK_IPV4=m
CONFIG_NF_CONNTRACK_PROC_COMPAT=y
CONFIG_IP_NF_QUEUE=m
CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_RECENT=m
-CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IP_NF_TARGET_LOG=m
@@ -320,8 +315,8 @@ CONFIG_IP_NF_TARGET_ULOG=m
CONFIG_NF_NAT=m
CONFIG_NF_NAT_NEEDED=y
CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
CONFIG_NF_NAT_SNMP_BASIC=m
CONFIG_NF_NAT_PROTO_GRE=m
CONFIG_NF_NAT_PROTO_UDPLITE=m
@@ -334,9 +329,9 @@ CONFIG_NF_NAT_PPTP=m
CONFIG_NF_NAT_H323=m
CONFIG_NF_NAT_SIP=m
CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
CONFIG_IP_NF_TARGET_ECN=m
CONFIG_IP_NF_TARGET_TTL=m
-CONFIG_IP_NF_TARGET_CLUSTERIP=m
CONFIG_IP_NF_RAW=m
CONFIG_IP_NF_ARPTABLES=m
CONFIG_IP_NF_ARPFILTER=m
@@ -348,16 +343,16 @@ CONFIG_IP_NF_ARP_MANGLE=m
CONFIG_NF_CONNTRACK_IPV6=m
CONFIG_IP6_NF_QUEUE=m
CONFIG_IP6_NF_IPTABLES=m
-CONFIG_IP6_NF_MATCH_RT=m
-CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
CONFIG_IP6_NF_MATCH_HL=m
CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-CONFIG_IP6_NF_MATCH_AH=m
CONFIG_IP6_NF_MATCH_MH=m
-CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_MATCH_RT=m
CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_FILTER=m
CONFIG_IP6_NF_TARGET_REJECT=m
CONFIG_IP6_NF_MANGLE=m
CONFIG_IP6_NF_TARGET_HL=m
@@ -384,6 +379,7 @@ CONFIG_SCTP_HMAC_MD5=y
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
CONFIG_LLC=m
@@ -407,19 +403,8 @@ CONFIG_NET_CLS_ROUTE=y
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
-# CONFIG_CFG80211 is not set
-CONFIG_WIRELESS_EXT=y
-# CONFIG_WIRELESS_EXT_SYSFS is not set
-# CONFIG_MAC80211 is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
-CONFIG_IEEE80211_CRYPT_TKIP=m
+# CONFIG_PHONET is not set
+# CONFIG_WIRELESS is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -457,6 +442,7 @@ CONFIG_ATA_OVER_ETH=m
CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -541,6 +527,9 @@ CONFIG_SUN3LANCE=y
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
# CONFIG_B44 is not set
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
@@ -610,6 +599,7 @@ CONFIG_MOUSE_PS2_LOGIPS2PP=y
CONFIG_MOUSE_PS2_SYNAPTICS=y
CONFIG_MOUSE_PS2_LIFEBOOK=y
CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
# CONFIG_MOUSE_PS2_TOUCHKIT is not set
CONFIG_MOUSE_SERIAL=m
# CONFIG_MOUSE_VSXXXAA is not set
@@ -664,11 +654,11 @@ CONFIG_GEN_RTC_X=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -678,6 +668,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -703,6 +694,7 @@ CONFIG_SSB_POSSIBLE=y
CONFIG_FB=y
# CONFIG_FIRMWARE_EDID is not set
# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
# CONFIG_FB_CFB_FILLRECT is not set
# CONFIG_FB_CFB_COPYAREA is not set
# CONFIG_FB_CFB_IMAGEBLIT is not set
@@ -724,6 +716,8 @@ CONFIG_FB=y
# CONFIG_FB_UVESA is not set
# CONFIG_FB_S1D13XXX is not set
# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
@@ -750,6 +744,12 @@ CONFIG_HID_SUPPORT=y
CONFIG_HID=m
# CONFIG_HID_DEBUG is not set
CONFIG_HIDRAW=y
+# CONFIG_HID_PID is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
# CONFIG_USB_SUPPORT is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -758,6 +758,8 @@ CONFIG_HIDRAW=y
# CONFIG_RTC_CLASS is not set
# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+CONFIG_STAGING_EXCLUDE_BUILD=y
#
# Character devices
@@ -771,8 +773,9 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
# CONFIG_EXT3_FS_XATTR is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
CONFIG_JBD=y
+CONFIG_JBD2=m
CONFIG_REISERFS_FS=m
# CONFIG_REISERFS_CHECK is not set
# CONFIG_REISERFS_PROC_INFO is not set
@@ -783,6 +786,7 @@ CONFIG_JFS_FS=m
# CONFIG_JFS_DEBUG is not set
# CONFIG_JFS_STATISTICS is not set
# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
CONFIG_XFS_FS=m
# CONFIG_XFS_QUOTA is not set
# CONFIG_XFS_POSIX_ACL is not set
@@ -794,6 +798,7 @@ CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
# CONFIG_OCFS2_FS_STATS is not set
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
# CONFIG_OCFS2_DEBUG_FS is not set
+# CONFIG_OCFS2_COMPAT_JBD is not set
CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
@@ -832,6 +837,7 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
@@ -875,6 +881,7 @@ CONFIG_EXPORTFS=m
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_REGISTER_V4 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
CONFIG_SMB_FS=m
@@ -948,7 +955,13 @@ CONFIG_MAGIC_SYSRQ=y
# CONFIG_DEBUG_KERNEL is not set
CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
+
+#
+# Tracers
+#
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
#
@@ -956,6 +969,7 @@ CONFIG_SYSCTL_SYSCALL_CHECK=y
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_XOR_BLOCKS=m
CONFIG_ASYNC_CORE=m
@@ -966,10 +980,12 @@ CONFIG_CRYPTO=y
#
# Crypto core or helper
#
+# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD=y
CONFIG_CRYPTO_BLKCIPHER=y
CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_RNG=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_GF128MUL=m
CONFIG_CRYPTO_NULL=m
@@ -1043,14 +1059,17 @@ CONFIG_CRYPTO_TWOFISH_COMMON=m
#
CONFIG_CRYPTO_DEFLATE=m
CONFIG_CRYPTO_LZO=m
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
# CONFIG_CRYPTO_HW is not set
#
# Library routines
#
CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
-# CONFIG_GENERIC_FIND_NEXT_BIT is not set
CONFIG_CRC_CCITT=m
CONFIG_CRC16=m
CONFIG_CRC_T10DIF=y
diff --git a/arch/m68k/kernel/ints.c b/arch/m68k/kernel/ints.c
index 7e8a0d394e6..761ee0440c9 100644
--- a/arch/m68k/kernel/ints.c
+++ b/arch/m68k/kernel/ints.c
@@ -133,7 +133,7 @@ void __init m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt,
{
int i;
- BUG_ON(IRQ_USER + cnt >= NR_IRQS);
+ BUG_ON(IRQ_USER + cnt > NR_IRQS);
m68k_first_user_vec = vec;
for (i = 0; i < cnt; i++)
irq_controller[IRQ_USER + i] = &user_irq_controller;
diff --git a/arch/mips/Kconfig.debug b/arch/mips/Kconfig.debug
index 765c8e287d2..364ca893880 100644
--- a/arch/mips/Kconfig.debug
+++ b/arch/mips/Kconfig.debug
@@ -48,7 +48,7 @@ config RUNTIME_DEBUG
help
If you say Y here, some debugging macros will do run-time checking.
If you say N here, those macros will mostly turn to no-ops. See
- include/asm-mips/debug.h for debuging macros.
+ arch/mips/include/asm/debug.h for debugging macros.
If unsure, say N.
endmenu
diff --git a/arch/mips/configs/fulong_defconfig b/arch/mips/configs/fulong_defconfig
index 620980081a3..b6698a232ae 100644
--- a/arch/mips/configs/fulong_defconfig
+++ b/arch/mips/configs/fulong_defconfig
@@ -1,63 +1,78 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.22-rc4
-# Mon Jun 11 00:23:51 2007
+# Linux kernel version: 2.6.28-rc6
+# Fri Nov 28 17:53:48 2008
#
CONFIG_MIPS=y
#
# Machine selection
#
-CONFIG_LEMOTE_FULONG=y
# CONFIG_MACH_ALCHEMY is not set
# CONFIG_BASLER_EXCITE is not set
+# CONFIG_BCM47XX is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
+CONFIG_LEMOTE_FULONG=y
# CONFIG_MIPS_MALTA is not set
-# CONFIG_WR_PPMC is not set
# CONFIG_MIPS_SIM is not set
+# CONFIG_MACH_EMMA is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_NXP_STB220 is not set
+# CONFIG_NXP_STB225 is not set
# CONFIG_PNX8550_JBS is not set
# CONFIG_PNX8550_STB810 is not set
-# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_MSP is not set
# CONFIG_PMC_YOSEMITE is not set
-# CONFIG_MARKEINS is not set
# CONFIG_SGI_IP22 is not set
# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP28 is not set
# CONFIG_SGI_IP32 is not set
-# CONFIG_SIBYTE_BIGSUR is not set
-# CONFIG_SIBYTE_SWARM is not set
-# CONFIG_SIBYTE_SENTOSA is not set
-# CONFIG_SIBYTE_RHONE is not set
-# CONFIG_SIBYTE_CARMEL is not set
-# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CARMEL is not set
# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_BIGSUR is not set
# CONFIG_SNI_RM is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_TOSHIBA_RBTX4938 is not set
+# CONFIG_MACH_TX39XX is not set
+# CONFIG_MACH_TX49XX is not set
+# CONFIG_MIKROTIK_RB532 is not set
+# CONFIG_WR_PPMC is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
# CONFIG_ARCH_HAS_ILOG2_U32 is not set
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_ARCH_SUPPORTS_OPROFILE=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_CEVT_R4K=y
+CONFIG_CSRC_R4K=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
CONFIG_EARLY_PRINTK=y
CONFIG_SYS_HAS_EARLY_PRINTK=y
+# CONFIG_HOTPLUG_CPU is not set
CONFIG_I8259=y
# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_ISA_DMA_SUPPORT_BROKEN=y
# CONFIG_CPU_BIG_ENDIAN is not set
CONFIG_CPU_LITTLE_ENDIAN=y
CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
CONFIG_IRQ_CPU=y
CONFIG_BOOT_ELF32=y
CONFIG_MIPS_L1_CACHE_SHIFT=5
+CONFIG_HAVE_STD_PC_SERIAL_PORT=y
#
# CPU selection
@@ -75,6 +90,7 @@ CONFIG_CPU_LOONGSON2=y
# CONFIG_CPU_TX49XX is not set
# CONFIG_CPU_R5000 is not set
# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R5500 is not set
# CONFIG_CPU_R6000 is not set
# CONFIG_CPU_NEVADA is not set
# CONFIG_CPU_R8000 is not set
@@ -101,7 +117,6 @@ CONFIG_BOARD_SCACHE=y
CONFIG_MIPS_MT_DISABLED=y
# CONFIG_MIPS_MT_SMP is not set
# CONFIG_MIPS_MT_SMTC is not set
-# CONFIG_MIPS_VPE_LOADER is not set
CONFIG_CPU_HAS_WB=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
@@ -109,6 +124,7 @@ CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_CPU_SUPPORTS_HIGHMEM=y
CONFIG_SYS_SUPPORTS_HIGHMEM=y
CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_ARCH_SPARSEMEM_ENABLE=y
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
@@ -117,9 +133,17 @@ CONFIG_FLATMEM_MANUAL=y
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_SPARSEMEM_STATIC=y
+CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_RESOURCES_64BIT=y
+CONFIG_PHYS_ADDR_T_64BIT=y
CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
# CONFIG_HZ_48 is not set
# CONFIG_HZ_100 is not set
# CONFIG_HZ_128 is not set
@@ -133,37 +157,40 @@ CONFIG_HZ=250
CONFIG_PREEMPT_VOLUNTARY=y
# CONFIG_PREEMPT is not set
# CONFIG_KEXEC is not set
+CONFIG_SECCOMP=y
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
-# Code maturity level options
+# General setup
#
CONFIG_EXPERIMENTAL=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
CONFIG_LOCALVERSION="lm32"
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
-# CONFIG_IPC_NS is not set
CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
# CONFIG_TASKSTATS is not set
-# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+# CONFIG_GROUP_SCHED is not set
CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+CONFIG_USER_NS=y
+CONFIG_PID_NS=y
# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
@@ -175,6 +202,8 @@ CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
+# CONFIG_PCSPKR_PLATFORM is not set
+# CONFIG_COMPAT_BRK is not set
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_ANON_INODES=y
@@ -183,29 +212,33 @@ CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+# CONFIG_MARKERS is not set
+CONFIG_OPROFILE=m
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-
-#
-# Loadable module support
-#
CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
-
-#
-# Block layer
-#
CONFIG_BLOCK=y
# CONFIG_BLK_DEV_IO_TRACE is not set
+CONFIG_BLK_DEV_BSG=y
+# CONFIG_BLK_DEV_INTEGRITY is not set
+CONFIG_BLOCK_COMPAT=y
#
# IO Schedulers
@@ -219,19 +252,19 @@ CONFIG_IOSCHED_CFQ=y
CONFIG_DEFAULT_CFQ=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_CLASSIC_RCU=y
+CONFIG_FREEZER=y
#
# Bus options (PCI, PCMCIA, EISA, ISA, TC)
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
# CONFIG_ARCH_SUPPORTS_MSI is not set
+CONFIG_PCI_LEGACY=y
CONFIG_ISA=y
CONFIG_MMU=y
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
@@ -239,8 +272,9 @@ CONFIG_MMU=y
# Executable file formats
#
CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
CONFIG_BINFMT_MISC=y
-# CONFIG_BUILD_ELF64 is not set
CONFIG_MIPS32_COMPAT=y
CONFIG_COMPAT=y
CONFIG_SYSVIPC_COMPAT=y
@@ -251,14 +285,12 @@ CONFIG_BINFMT_ELF32=y
#
# Power management options
#
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
# CONFIG_PM_DEBUG is not set
-# CONFIG_PM_SYSFS_DEPRECATED is not set
-
-#
-# Networking
-#
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
CONFIG_NET=y
#
@@ -271,6 +303,7 @@ CONFIG_XFRM=y
# CONFIG_XFRM_USER is not set
# CONFIG_XFRM_SUB_POLICY is not set
# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
@@ -294,18 +327,17 @@ CONFIG_INET_TUNNEL=m
# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
# CONFIG_INET_XFRM_MODE_TUNNEL is not set
CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
# CONFIG_INET_DIAG is not set
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
-# CONFIG_IP_VS is not set
# CONFIG_IPV6 is not set
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETWORK_SECMARK is not set
CONFIG_NETFILTER=y
# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
#
# Core Netfilter Configuration
@@ -313,53 +345,59 @@ CONFIG_NETFILTER=y
CONFIG_NETFILTER_NETLINK=m
CONFIG_NETFILTER_NETLINK_QUEUE=m
CONFIG_NETFILTER_NETLINK_LOG=m
-# CONFIG_NF_CONNTRACK_ENABLED is not set
# CONFIG_NF_CONNTRACK is not set
CONFIG_NETFILTER_XTABLES=m
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
CONFIG_NETFILTER_XT_TARGET_MARK=m
-CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_RATEEST=m
+CONFIG_NETFILTER_XT_TARGET_TRACE=m
# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
CONFIG_NETFILTER_XT_MATCH_DCCP=m
# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
CONFIG_NETFILTER_XT_MATCH_ESP=m
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
CONFIG_NETFILTER_XT_MATCH_MAC=m
CONFIG_NETFILTER_XT_MATCH_MARK=m
-# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_OWNER=m
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_RATEEST=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_RECENT=m
+# CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT is not set
CONFIG_NETFILTER_XT_MATCH_SCTP=m
CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
CONFIG_NETFILTER_XT_MATCH_STRING=m
CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
-# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+CONFIG_NETFILTER_XT_MATCH_TIME=m
+CONFIG_NETFILTER_XT_MATCH_U32=m
+# CONFIG_IP_VS is not set
#
# IP: Netfilter Configuration
#
+# CONFIG_NF_DEFRAG_IPV4 is not set
CONFIG_IP_NF_QUEUE=m
CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_TOS=m
-CONFIG_IP_NF_MATCH_RECENT=m
-CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_OWNER=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IP_NF_TARGET_LOG=m
CONFIG_IP_NF_TARGET_ULOG=m
CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_TOS=m
CONFIG_IP_NF_TARGET_ECN=m
CONFIG_IP_NF_TARGET_TTL=m
CONFIG_IP_NF_RAW=m
@@ -371,6 +409,7 @@ CONFIG_IP_NF_ARP_MANGLE=m
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
@@ -380,10 +419,6 @@ CONFIG_IP_NF_ARP_MANGLE=m
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
# CONFIG_NET_SCHED is not set
CONFIG_NET_CLS_ROUTE=y
@@ -392,23 +427,25 @@ CONFIG_NET_CLS_ROUTE=y
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
+CONFIG_PHONET=m
+CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_OLD_REGULATORY=y
CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
# CONFIG_MAC80211 is not set
CONFIG_IEEE80211=m
# CONFIG_IEEE80211_DEBUG is not set
CONFIG_IEEE80211_CRYPT_WEP=m
# CONFIG_IEEE80211_CRYPT_CCMP is not set
# CONFIG_IEEE80211_CRYPT_TKIP is not set
-# CONFIG_IEEE80211_SOFTMAC is not set
# CONFIG_RFKILL is not set
+CONFIG_NET_9P=m
+# CONFIG_NET_9P_DEBUG is not set
#
# Device Drivers
@@ -417,14 +454,13 @@ CONFIG_IEEE80211_CRYPT_WEP=m
#
# Generic Driver Options
#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
CONFIG_FW_LOADER=m
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
# CONFIG_SYS_HYPERVISOR is not set
-
-#
-# Connector - unified userspace <-> kernelspace linker
-#
# CONFIG_CONNECTOR is not set
CONFIG_MTD=m
# CONFIG_MTD_DEBUG is not set
@@ -443,6 +479,7 @@ CONFIG_MTD_BLOCK=m
# CONFIG_INFTL is not set
# CONFIG_RFD_FTL is not set
# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
#
# RAM/ROM/Flash chip drivers
@@ -482,6 +519,7 @@ CONFIG_MTD_PHYSMAP=m
CONFIG_MTD_PHYSMAP_START=0x1fc00000
CONFIG_MTD_PHYSMAP_LEN=0x80000
CONFIG_MTD_PHYSMAP_BANKWIDTH=1
+# CONFIG_MTD_INTEL_VR_NOR is not set
# CONFIG_MTD_PLATRAM is not set
#
@@ -506,21 +544,9 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=1
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
-
-#
-# Parallel port support
-#
# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
# CONFIG_PNP is not set
-# CONFIG_PNPACPI is not set
-
-#
-# Block devices
-#
+CONFIG_BLK_DEV=y
# CONFIG_BLK_CPQ_DA is not set
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
@@ -534,32 +560,28 @@ CONFIG_BLK_DEV_CRYPTOLOOP=m
CONFIG_BLK_DEV_RAM=m
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_BLK_DEV_XIP is not set
CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
CONFIG_ATA_OVER_ETH=m
-
-#
-# Misc devices
-#
-# CONFIG_PHANTOM is not set
-# CONFIG_SGI_IOC4 is not set
-# CONFIG_TIFM_CORE is not set
-# CONFIG_BLINK is not set
+# CONFIG_BLK_DEV_HD is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
CONFIG_IDE=y
-CONFIG_IDE_MAX_HWIFS=4
-CONFIG_BLK_DEV_IDE=y
#
-# Please see Documentation/ide.txt for help/info on IDE drives
+# Please see Documentation/ide/ide.txt for help/info on IDE drives
#
+CONFIG_IDE_TIMINGS=y
+CONFIG_IDE_ATAPI=y
# CONFIG_BLK_DEV_IDE_SATA is not set
-CONFIG_BLK_DEV_IDEDISK=y
-CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_IDE_GD=y
+CONFIG_IDE_GD_ATA=y
+# CONFIG_IDE_GD_ATAPI is not set
CONFIG_BLK_DEV_IDECD=y
+CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y
# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
CONFIG_BLK_DEV_IDESCSI=y
CONFIG_IDE_TASK_IOCTL=y
CONFIG_IDE_PROC_FS=y
@@ -568,24 +590,25 @@ CONFIG_IDE_PROC_FS=y
# IDE chipset support/bugfixes
#
CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_PLATFORM is not set
+CONFIG_BLK_DEV_IDEDMA_SFF=y
+
+#
+# PCI IDE chipsets support
+#
CONFIG_BLK_DEV_IDEPCI=y
-CONFIG_IDEPCI_SHARE_IRQ=y
CONFIG_IDEPCI_PCIBUS_ORDER=y
# CONFIG_BLK_DEV_OFFBOARD is not set
CONFIG_BLK_DEV_GENERIC=y
# CONFIG_BLK_DEV_OPTI621 is not set
CONFIG_BLK_DEV_IDEDMA_PCI=y
-# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-# CONFIG_IDEDMA_ONLYDISK is not set
# CONFIG_BLK_DEV_AEC62XX is not set
# CONFIG_BLK_DEV_ALI15X3 is not set
# CONFIG_BLK_DEV_AMD74XX is not set
# CONFIG_BLK_DEV_CMD64X is not set
# CONFIG_BLK_DEV_TRIFLEX is not set
-# CONFIG_BLK_DEV_CY82C693 is not set
# CONFIG_BLK_DEV_CS5520 is not set
# CONFIG_BLK_DEV_CS5530 is not set
-# CONFIG_BLK_DEV_HPT34X is not set
# CONFIG_BLK_DEV_HPT366 is not set
# CONFIG_BLK_DEV_JMICRON is not set
# CONFIG_BLK_DEV_SC1200 is not set
@@ -601,17 +624,28 @@ CONFIG_BLK_DEV_IDEDMA_PCI=y
# CONFIG_BLK_DEV_TRM290 is not set
CONFIG_BLK_DEV_VIA82CXXX=y
# CONFIG_BLK_DEV_TC86C001 is not set
-# CONFIG_IDE_ARM is not set
-# CONFIG_IDE_CHIPSETS is not set
+
+#
+# Other IDE chipsets support
+#
+
+#
+# Note: most of these also require special kernel boot parameters
+#
+# CONFIG_BLK_DEV_4DRIVES is not set
+# CONFIG_BLK_DEV_ALI14XX is not set
+# CONFIG_BLK_DEV_DTC2278 is not set
+# CONFIG_BLK_DEV_HT6560B is not set
+# CONFIG_BLK_DEV_QD65XX is not set
+# CONFIG_BLK_DEV_UMC8672 is not set
CONFIG_BLK_DEV_IDEDMA=y
-# CONFIG_IDEDMA_IVB is not set
-# CONFIG_BLK_DEV_HD is not set
#
# SCSI device support
#
# CONFIG_RAID_ATTRS is not set
CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
# CONFIG_SCSI_TGT is not set
# CONFIG_SCSI_NETLINK is not set
CONFIG_SCSI_PROC_FS=y
@@ -644,88 +678,30 @@ CONFIG_SCSI_WAIT_SCAN=m
# CONFIG_SCSI_ISCSI_ATTRS is not set
# CONFIG_SCSI_SAS_ATTRS is not set
# CONFIG_SCSI_SAS_LIBSAS is not set
-
-#
-# SCSI low-level drivers
-#
-# CONFIG_ISCSI_TCP is not set
-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
-# CONFIG_SCSI_3W_9XXX is not set
-# CONFIG_SCSI_ACARD is not set
-# CONFIG_SCSI_AACRAID is not set
-# CONFIG_SCSI_AIC7XXX is not set
-# CONFIG_SCSI_AIC7XXX_OLD is not set
-# CONFIG_SCSI_AIC79XX is not set
-# CONFIG_SCSI_AIC94XX is not set
-# CONFIG_SCSI_IN2000 is not set
-# CONFIG_SCSI_ARCMSR is not set
-# CONFIG_MEGARAID_NEWGEN is not set
-# CONFIG_MEGARAID_LEGACY is not set
-# CONFIG_MEGARAID_SAS is not set
-# CONFIG_SCSI_HPTIOP is not set
-# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_DTC3280 is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GENERIC_NCR5380 is not set
-# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
-# CONFIG_SCSI_IPS is not set
-# CONFIG_SCSI_INITIO is not set
-# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_NCR53C406A is not set
-# CONFIG_SCSI_STEX is not set
-# CONFIG_SCSI_SYM53C8XX_2 is not set
-# CONFIG_SCSI_PAS16 is not set
-# CONFIG_SCSI_PSI240I is not set
-# CONFIG_SCSI_QLOGIC_FAS is not set
-# CONFIG_SCSI_QLOGIC_1280 is not set
-# CONFIG_SCSI_QLA_FC is not set
-# CONFIG_SCSI_QLA_ISCSI is not set
-# CONFIG_SCSI_LPFC is not set
-# CONFIG_SCSI_SYM53C416 is not set
-# CONFIG_SCSI_DC395x is not set
-# CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_T128 is not set
-# CONFIG_SCSI_DEBUG is not set
-# CONFIG_SCSI_SRP is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_SCSI_DH is not set
# CONFIG_ATA is not set
-
-#
-# Old CD-ROM drivers (not SCSI, not IDE)
-#
-# CONFIG_CD_NO_IDESCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
# CONFIG_FUSION is not set
-# CONFIG_FUSION_SPI is not set
-# CONFIG_FUSION_FC is not set
-# CONFIG_FUSION_SAS is not set
#
# IEEE 1394 (FireWire) support
#
-# CONFIG_FIREWIRE is not set
-# CONFIG_IEEE1394 is not set
#
-# I2O device support
+# Enable only one of the two stacks, unless you know what you are doing
#
+# CONFIG_FIREWIRE is not set
+# CONFIG_IEEE1394 is not set
# CONFIG_I2O is not set
-
-#
-# Network device support
-#
CONFIG_NETDEVICES=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
+CONFIG_MACVLAN=m
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
+CONFIG_VETH=m
# CONFIG_ARCNET is not set
CONFIG_PHYLIB=m
@@ -740,29 +716,32 @@ CONFIG_CICADA_PHY=m
# CONFIG_VITESSE_PHY is not set
# CONFIG_SMSC_PHY is not set
# CONFIG_BROADCOM_PHY is not set
-# CONFIG_FIXED_PHY is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
+# CONFIG_AX88796 is not set
# CONFIG_HAPPYMEAL is not set
# CONFIG_SUNGEM is not set
# CONFIG_CASSINI is not set
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_SMC91X is not set
# CONFIG_DM9000 is not set
# CONFIG_NET_VENDOR_RACAL is not set
-
-#
-# Tulip family network device support
-#
# CONFIG_NET_TULIP is not set
# CONFIG_AT1700 is not set
# CONFIG_DEPCA is not set
# CONFIG_HP100 is not set
# CONFIG_NET_ISA is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
CONFIG_NET_PCI=y
# CONFIG_PCNET32 is not set
# CONFIG_AMD8111_ETH is not set
@@ -773,7 +752,6 @@ CONFIG_NET_PCI=y
# CONFIG_FORCEDETH is not set
# CONFIG_CS89x0 is not set
# CONFIG_TC35815 is not set
-# CONFIG_DGRS is not set
# CONFIG_EEPRO100 is not set
# CONFIG_E100 is not set
# CONFIG_FEALNX is not set
@@ -785,15 +763,21 @@ CONFIG_8139TOO=y
# CONFIG_8139TOO_TUNE_TWISTER is not set
# CONFIG_8139TOO_8129 is not set
# CONFIG_8139_OLD_RX_RESET is not set
+# CONFIG_R6040 is not set
# CONFIG_SIS900 is not set
# CONFIG_EPIC100 is not set
# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
# CONFIG_SC92031 is not set
+# CONFIG_ATL2 is not set
CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
# CONFIG_E1000 is not set
+# CONFIG_E1000E is not set
+# CONFIG_IP1000 is not set
+# CONFIG_IGB is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
@@ -801,20 +785,29 @@ CONFIG_NETDEV_1000=y
# CONFIG_SIS190 is not set
# CONFIG_SKGE is not set
# CONFIG_SKY2 is not set
-# CONFIG_SK98LIN is not set
# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
# CONFIG_BNX2 is not set
# CONFIG_QLA3XXX is not set
# CONFIG_ATL1 is not set
+# CONFIG_ATL1E is not set
+# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
# CONFIG_CHELSIO_T3 is not set
+# CONFIG_ENIC is not set
+# CONFIG_IXGBE is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
+# CONFIG_NIU is not set
+# CONFIG_MLX4_EN is not set
# CONFIG_MLX4_CORE is not set
+# CONFIG_TEHUTI is not set
+# CONFIG_BNX2X is not set
+# CONFIG_QLGE is not set
+# CONFIG_SFC is not set
# CONFIG_TR is not set
#
@@ -822,6 +815,7 @@ CONFIG_NETDEV_10000=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
#
# USB Network Adapters
@@ -830,7 +824,6 @@ CONFIG_NETDEV_10000=y
# CONFIG_USB_KAWETH is not set
# CONFIG_USB_PEGASUS is not set
# CONFIG_USB_RTL8150 is not set
-# CONFIG_USB_USBNET_MII is not set
# CONFIG_USB_USBNET is not set
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
@@ -844,25 +837,17 @@ CONFIG_PPP_DEFLATE=m
CONFIG_PPP_BSDCOMP=m
CONFIG_PPP_MPPE=m
CONFIG_PPPOE=m
+CONFIG_PPPOL2TP=m
CONFIG_SLIP=m
CONFIG_SLIP_COMPRESSED=y
CONFIG_SLHC=m
CONFIG_SLIP_SMART=y
CONFIG_SLIP_MODE_SLIP6=y
CONFIG_NET_FC=y
-# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
-
-#
-# ISDN subsystem
-#
# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
# CONFIG_PHONE is not set
#
@@ -870,6 +855,7 @@ CONFIG_NET_FC=y
#
CONFIG_INPUT=y
CONFIG_INPUT_FF_MEMLESS=y
+# CONFIG_INPUT_POLLDEV is not set
#
# Userland interfaces
@@ -879,7 +865,6 @@ CONFIG_INPUT_MOUSEDEV_PSAUX=y
CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
# CONFIG_INPUT_EVDEV is not set
# CONFIG_INPUT_EVBUG is not set
@@ -900,9 +885,11 @@ CONFIG_MOUSE_PS2_LOGIPS2PP=y
CONFIG_MOUSE_PS2_SYNAPTICS=y
CONFIG_MOUSE_PS2_LIFEBOOK=y
CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
# CONFIG_MOUSE_PS2_TOUCHKIT is not set
CONFIG_MOUSE_SERIAL=y
# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
# CONFIG_MOUSE_INPORT is not set
# CONFIG_MOUSE_LOGIBM is not set
# CONFIG_MOUSE_PC110PAD is not set
@@ -927,10 +914,13 @@ CONFIG_SERIO_LIBPS2=y
# Character devices
#
CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
CONFIG_VT_CONSOLE=y
CONFIG_HW_CONSOLE=y
# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
#
# Serial drivers
@@ -951,105 +941,152 @@ CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
-
-#
-# IPMI
-#
# CONFIG_IPMI_HANDLER is not set
-# CONFIG_WATCHDOG is not set
CONFIG_HW_RANDOM=y
-CONFIG_RTC=y
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
-# CONFIG_DRM is not set
# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
# CONFIG_TCG_TPM is not set
CONFIG_DEVPORT=y
CONFIG_I2C=m
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=m
+CONFIG_I2C_HELPER_AUTO=y
#
-# I2C Algorithms
+# I2C Hardware Bus support
#
-# CONFIG_I2C_ALGOBIT is not set
-# CONFIG_I2C_ALGOPCF is not set
-# CONFIG_I2C_ALGOPCA is not set
#
-# I2C Hardware Bus support
+# PC SMBus host controller drivers
#
# CONFIG_I2C_ALI1535 is not set
# CONFIG_I2C_ALI1563 is not set
# CONFIG_I2C_ALI15X3 is not set
# CONFIG_I2C_AMD756 is not set
# CONFIG_I2C_AMD8111 is not set
-# CONFIG_I2C_ELEKTOR is not set
# CONFIG_I2C_I801 is not set
-# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_ISCH is not set
# CONFIG_I2C_PIIX4 is not set
# CONFIG_I2C_NFORCE2 is not set
-# CONFIG_I2C_OCORES is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PROSAVAGE is not set
-# CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_I2C_SIMTEC is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
-# CONFIG_I2C_STUB is not set
-# CONFIG_I2C_TINY_USB is not set
# CONFIG_I2C_VIA is not set
CONFIG_I2C_VIAPRO=m
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Graphics adapter I2C/DDC channel drivers
+#
# CONFIG_I2C_VOODOO3 is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_ELEKTOR is not set
# CONFIG_I2C_PCA_ISA is not set
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
#
# Miscellaneous I2C Chip support
#
-# CONFIG_SENSORS_DS1337 is not set
-# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_AT24 is not set
# CONFIG_SENSORS_EEPROM is not set
# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
# CONFIG_I2C_DEBUG_CHIP is not set
-
-#
-# SPI support
-#
# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
-# Dallas's 1-wire bus
+# Sonics Silicon Backplane
#
-# CONFIG_W1 is not set
-# CONFIG_HWMON is not set
+# CONFIG_SSB is not set
#
# Multifunction device drivers
#
+# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
#
+
+#
+# Multimedia core support
+#
CONFIG_VIDEO_DEV=m
-CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_V4L2_COMMON=m
+CONFIG_VIDEO_ALLOW_V4L1=y
CONFIG_VIDEO_V4L1_COMPAT=y
-CONFIG_VIDEO_V4L2=y
+# CONFIG_DVB_CORE is not set
+CONFIG_VIDEO_MEDIA=m
+
+#
+# Multimedia drivers
+#
+CONFIG_MEDIA_ATTACH=y
+CONFIG_MEDIA_TUNER=m
+CONFIG_MEDIA_TUNER_CUSTOMIZE=y
+CONFIG_MEDIA_TUNER_SIMPLE=m
+CONFIG_MEDIA_TUNER_TDA8290=m
+CONFIG_MEDIA_TUNER_TDA827X=m
+CONFIG_MEDIA_TUNER_TDA18271=m
+CONFIG_MEDIA_TUNER_TDA9887=m
+CONFIG_MEDIA_TUNER_TEA5761=m
+CONFIG_MEDIA_TUNER_TEA5767=m
+CONFIG_MEDIA_TUNER_MT20XX=m
+CONFIG_MEDIA_TUNER_MT2060=m
+CONFIG_MEDIA_TUNER_MT2266=m
+CONFIG_MEDIA_TUNER_MT2131=m
+CONFIG_MEDIA_TUNER_QT1010=m
+CONFIG_MEDIA_TUNER_XC2028=m
+CONFIG_MEDIA_TUNER_XC5000=m
+CONFIG_MEDIA_TUNER_MXL5005S=m
+CONFIG_MEDIA_TUNER_MXL5007T=m
+CONFIG_VIDEO_V4L2=m
+CONFIG_VIDEO_V4L1=m
+CONFIG_VIDEOBUF_GEN=m
+CONFIG_VIDEOBUF_VMALLOC=m
+CONFIG_VIDEOBUF_DMA_CONTIG=m
CONFIG_VIDEO_CAPTURE_DRIVERS=y
# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
# CONFIG_VIDEO_VIVI is not set
# CONFIG_VIDEO_BT848 is not set
@@ -1058,17 +1095,46 @@ CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
# CONFIG_VIDEO_CPIA2 is not set
# CONFIG_VIDEO_SAA5246A is not set
# CONFIG_VIDEO_SAA5249 is not set
-# CONFIG_TUNER_3036 is not set
# CONFIG_VIDEO_STRADIS is not set
# CONFIG_VIDEO_SAA7134 is not set
# CONFIG_VIDEO_MXB is not set
-# CONFIG_VIDEO_DPC is not set
# CONFIG_VIDEO_HEXIUM_ORION is not set
# CONFIG_VIDEO_HEXIUM_GEMINI is not set
# CONFIG_VIDEO_CX88 is not set
# CONFIG_VIDEO_IVTV is not set
# CONFIG_VIDEO_CAFE_CCIC is not set
+CONFIG_SOC_CAMERA=m
+CONFIG_SOC_CAMERA_MT9M001=m
+CONFIG_SOC_CAMERA_MT9M111=m
+CONFIG_SOC_CAMERA_MT9V022=m
+CONFIG_SOC_CAMERA_PLATFORM=m
+CONFIG_VIDEO_SH_MOBILE_CEU=m
CONFIG_V4L_USB_DRIVERS=y
+CONFIG_USB_VIDEO_CLASS=m
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
+CONFIG_USB_GSPCA=m
+CONFIG_USB_M5602=m
+CONFIG_USB_GSPCA_CONEX=m
+CONFIG_USB_GSPCA_ETOMS=m
+CONFIG_USB_GSPCA_FINEPIX=m
+CONFIG_USB_GSPCA_MARS=m
+CONFIG_USB_GSPCA_OV519=m
+CONFIG_USB_GSPCA_PAC207=m
+CONFIG_USB_GSPCA_PAC7311=m
+CONFIG_USB_GSPCA_SONIXB=m
+CONFIG_USB_GSPCA_SONIXJ=m
+CONFIG_USB_GSPCA_SPCA500=m
+CONFIG_USB_GSPCA_SPCA501=m
+CONFIG_USB_GSPCA_SPCA505=m
+CONFIG_USB_GSPCA_SPCA506=m
+CONFIG_USB_GSPCA_SPCA508=m
+CONFIG_USB_GSPCA_SPCA561=m
+CONFIG_USB_GSPCA_STK014=m
+CONFIG_USB_GSPCA_SUNPLUS=m
+CONFIG_USB_GSPCA_T613=m
+CONFIG_USB_GSPCA_TV8532=m
+CONFIG_USB_GSPCA_VC032X=m
+CONFIG_USB_GSPCA_ZC3XX=m
# CONFIG_VIDEO_PVRUSB2 is not set
# CONFIG_VIDEO_EM28XX is not set
# CONFIG_VIDEO_USBVISION is not set
@@ -1079,7 +1145,6 @@ CONFIG_USB_KONICAWC=m
CONFIG_USB_QUICKCAM_MESSENGER=m
CONFIG_USB_ET61X251=m
# CONFIG_VIDEO_OVCAMCHIP is not set
-# CONFIG_USB_W9968CF is not set
CONFIG_USB_OV511=m
CONFIG_USB_SE401=m
CONFIG_USB_SN9C102=m
@@ -1088,6 +1153,8 @@ CONFIG_USB_ZC0301=m
CONFIG_USB_PWC=m
# CONFIG_USB_PWC_DEBUG is not set
# CONFIG_USB_ZR364XX is not set
+CONFIG_USB_STKWEBCAM=m
+CONFIG_USB_S2255=m
CONFIG_RADIO_ADAPTERS=y
# CONFIG_RADIO_CADET is not set
# CONFIG_RADIO_RTRACK is not set
@@ -1104,33 +1171,30 @@ CONFIG_RADIO_ADAPTERS=y
# CONFIG_RADIO_TYPHOON is not set
# CONFIG_RADIO_ZOLTRIX is not set
# CONFIG_USB_DSBR is not set
-# CONFIG_DVB_CORE is not set
+CONFIG_USB_SI470X=m
+CONFIG_USB_MR800=m
CONFIG_DAB=y
# CONFIG_USB_DABUSB is not set
#
# Graphics support
#
-CONFIG_BACKLIGHT_LCD_SUPPORT=y
-CONFIG_BACKLIGHT_CLASS_DEVICE=y
-CONFIG_LCD_CLASS_DEVICE=m
-
-#
-# Display device support
-#
-# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_DRM is not set
# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=m
CONFIG_FB=y
# CONFIG_FIRMWARE_EDID is not set
# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
# CONFIG_FB_SYS_FILLRECT is not set
# CONFIG_FB_SYS_COPYAREA is not set
# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
# CONFIG_FB_SYS_FOPS is not set
-CONFIG_FB_DEFERRED_IO=y
# CONFIG_FB_SVGALIB is not set
# CONFIG_FB_MACMODES is not set
CONFIG_FB_BACKLIGHT=y
@@ -1158,16 +1222,30 @@ CONFIG_FB_RADEON_BACKLIGHT=y
# CONFIG_FB_S3 is not set
# CONFIG_FB_SAVAGE is not set
# CONFIG_FB_SIS is not set
+# CONFIG_FB_VIA is not set
# CONFIG_FB_NEOMAGIC is not set
# CONFIG_FB_KYRO is not set
# CONFIG_FB_3DFX is not set
# CONFIG_FB_VOODOO1 is not set
-# CONFIG_FB_SMIVGX is not set
# CONFIG_FB_VT8623 is not set
# CONFIG_FB_TRIDENT is not set
# CONFIG_FB_ARK is not set
# CONFIG_FB_PM3 is not set
+# CONFIG_FB_CARMINE is not set
# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=m
+# CONFIG_LCD_ILI9320 is not set
+# CONFIG_LCD_PLATFORM is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+# CONFIG_BACKLIGHT_CORGI is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
#
# Console display driver support
@@ -1176,20 +1254,14 @@ CONFIG_FB_RADEON_BACKLIGHT=y
# CONFIG_MDA_CONSOLE is not set
CONFIG_DUMMY_CONSOLE=y
CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
# CONFIG_FONTS is not set
CONFIG_FONT_8x8=y
CONFIG_FONT_8x16=y
# CONFIG_LOGO is not set
-
-#
-# Sound
-#
CONFIG_SOUND=y
-
-#
-# Advanced Linux Sound Architecture
-#
+CONFIG_SOUND_OSS_CORE=y
CONFIG_SND=m
CONFIG_SND_TIMER=m
CONFIG_SND_PCM=m
@@ -1201,28 +1273,22 @@ CONFIG_SND_MIXER_OSS=m
CONFIG_SND_PCM_OSS=m
CONFIG_SND_PCM_OSS_PLUGINS=y
CONFIG_SND_SEQUENCER_OSS=y
-CONFIG_SND_RTCTIMER=m
-CONFIG_SND_SEQ_RTCTIMER_DEFAULT=y
# CONFIG_SND_DYNAMIC_MINORS is not set
CONFIG_SND_SUPPORT_OLD_API=y
CONFIG_SND_VERBOSE_PROCFS=y
# CONFIG_SND_VERBOSE_PRINTK is not set
# CONFIG_SND_DEBUG is not set
-
-#
-# Generic devices
-#
+CONFIG_SND_VMASTER=y
CONFIG_SND_MPU401_UART=m
CONFIG_SND_AC97_CODEC=m
+CONFIG_SND_DRIVERS=y
# CONFIG_SND_DUMMY is not set
# CONFIG_SND_VIRMIDI is not set
# CONFIG_SND_MTPAV is not set
# CONFIG_SND_SERIAL_U16550 is not set
# CONFIG_SND_MPU401 is not set
-
-#
-# PCI devices
-#
+# CONFIG_SND_AC97_POWER_SAVE is not set
+CONFIG_SND_PCI=y
# CONFIG_SND_AD1889 is not set
# CONFIG_SND_ALS300 is not set
# CONFIG_SND_ALI5451 is not set
@@ -1231,10 +1297,12 @@ CONFIG_SND_AC97_CODEC=m
# CONFIG_SND_AU8810 is not set
# CONFIG_SND_AU8820 is not set
# CONFIG_SND_AU8830 is not set
+# CONFIG_SND_AW2 is not set
# CONFIG_SND_AZT3328 is not set
# CONFIG_SND_BT87X is not set
# CONFIG_SND_CA0106 is not set
# CONFIG_SND_CMIPCI is not set
+# CONFIG_SND_OXYGEN is not set
# CONFIG_SND_CS4281 is not set
# CONFIG_SND_CS46XX is not set
# CONFIG_SND_DARLA20 is not set
@@ -1259,6 +1327,7 @@ CONFIG_SND_AC97_CODEC=m
# CONFIG_SND_HDA_INTEL is not set
# CONFIG_SND_HDSP is not set
# CONFIG_SND_HDSPM is not set
+# CONFIG_SND_HIFIER is not set
# CONFIG_SND_ICE1712 is not set
# CONFIG_SND_ICE1724 is not set
# CONFIG_SND_INTEL8X0 is not set
@@ -1276,43 +1345,26 @@ CONFIG_SND_AC97_CODEC=m
# CONFIG_SND_TRIDENT is not set
CONFIG_SND_VIA82XX=m
# CONFIG_SND_VIA82XX_MODEM is not set
+# CONFIG_SND_VIRTUOSO is not set
# CONFIG_SND_VX222 is not set
# CONFIG_SND_YMFPCI is not set
-# CONFIG_SND_AC97_POWER_SAVE is not set
-
-#
-# ALSA MIPS devices
-#
-
-#
-# USB devices
-#
+CONFIG_SND_MIPS=y
+CONFIG_SND_USB=y
# CONFIG_SND_USB_AUDIO is not set
# CONFIG_SND_USB_CAIAQ is not set
-
-#
-# System on Chip audio support
-#
# CONFIG_SND_SOC is not set
-
-#
-# Open Sound System
-#
# CONFIG_SOUND_PRIME is not set
CONFIG_AC97_BUS=m
-
-#
-# HID Devices
-#
+CONFIG_HID_SUPPORT=y
CONFIG_HID=y
# CONFIG_HID_DEBUG is not set
+CONFIG_HIDRAW=y
#
# USB Input Devices
#
CONFIG_USB_HID=m
-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
-# CONFIG_HID_FF is not set
+CONFIG_HID_PID=y
CONFIG_USB_HIDDEV=y
#
@@ -1322,13 +1374,39 @@ CONFIG_USB_HIDDEV=y
# CONFIG_USB_MOUSE is not set
#
-# USB support
-#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
+CONFIG_HID_A4TECH=m
+CONFIG_HID_APPLE=m
+CONFIG_HID_BELKIN=m
+CONFIG_HID_BRIGHT=m
+CONFIG_HID_CHERRY=m
+CONFIG_HID_CHICONY=m
+CONFIG_HID_CYPRESS=m
+CONFIG_HID_DELL=m
+CONFIG_HID_EZKEY=m
+CONFIG_HID_GYRATION=m
+CONFIG_HID_LOGITECH=m
+CONFIG_LOGITECH_FF=y
+CONFIG_LOGIRUMBLEPAD2_FF=y
+CONFIG_HID_MICROSOFT=m
+CONFIG_HID_MONTEREY=m
+CONFIG_HID_PANTHERLORD=m
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_HID_PETALYNX=m
+CONFIG_HID_SAMSUNG=m
+CONFIG_HID_SONY=m
+CONFIG_HID_SUNPLUS=m
+# CONFIG_THRUSTMASTER_FF is not set
+CONFIG_ZEROPLUS_FF=m
+CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
CONFIG_USB_ARCH_HAS_EHCI=y
CONFIG_USB=y
# CONFIG_USB_DEBUG is not set
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
#
# Miscellaneous USB options
@@ -1338,35 +1416,46 @@ CONFIG_USB_DEVICEFS=y
# CONFIG_USB_DYNAMIC_MINORS is not set
# CONFIG_USB_SUSPEND is not set
# CONFIG_USB_OTG is not set
+CONFIG_USB_OTG_WHITELIST=y
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB is not set
+CONFIG_USB_WUSB_CBAF=m
+# CONFIG_USB_WUSB_CBAF_DEBUG is not set
#
# USB Host Controller Drivers
#
+CONFIG_USB_C67X00_HCD=m
CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_EHCI_SPLIT_ISO=y
CONFIG_USB_EHCI_ROOT_HUB_TT=y
CONFIG_USB_EHCI_TT_NEWSCHED=y
-# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO is not set
# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_ISP1760_HCD=m
CONFIG_USB_OHCI_HCD=y
# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
CONFIG_USB_OHCI_LITTLE_ENDIAN=y
CONFIG_USB_UHCI_HCD=m
# CONFIG_USB_SL811_HCD is not set
+CONFIG_USB_R8A66597_HCD=m
+# CONFIG_USB_WHCI_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
#
# USB Device Class drivers
#
CONFIG_USB_ACM=y
CONFIG_USB_PRINTER=y
+CONFIG_USB_WDM=m
+CONFIG_USB_TMC=m
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
#
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
#
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
@@ -1379,7 +1468,9 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_SDDR55 is not set
# CONFIG_USB_STORAGE_JUMPSHOT is not set
# CONFIG_USB_STORAGE_ALAUDA is not set
+CONFIG_USB_STORAGE_ONETOUCH=y
# CONFIG_USB_STORAGE_KARMA is not set
+CONFIG_USB_STORAGE_CYPRESS_ATACB=y
CONFIG_USB_LIBUSUAL=y
#
@@ -1387,15 +1478,10 @@ CONFIG_USB_LIBUSUAL=y
#
# CONFIG_USB_MDC800 is not set
# CONFIG_USB_MICROTEK is not set
-# CONFIG_USB_MON is not set
#
# USB port drivers
#
-
-#
-# USB Serial Converter support
-#
# CONFIG_USB_SERIAL is not set
#
@@ -1404,7 +1490,7 @@ CONFIG_USB_LIBUSUAL=y
# CONFIG_USB_EMI62 is not set
# CONFIG_USB_EMI26 is not set
# CONFIG_USB_ADUTUX is not set
-# CONFIG_USB_AUERSWALD is not set
+CONFIG_USB_SEVSEG=m
# CONFIG_USB_RIO500 is not set
# CONFIG_USB_LEGOTOWER is not set
# CONFIG_USB_LCD is not set
@@ -1421,56 +1507,75 @@ CONFIG_USB_LIBUSUAL=y
# CONFIG_USB_TRANCEVIBRATOR is not set
# CONFIG_USB_IOWARRIOR is not set
# CONFIG_USB_TEST is not set
-
-#
-# USB DSL modem support
-#
-
-#
-# USB Gadget Support
-#
+CONFIG_USB_ISIGHTFW=m
+CONFIG_USB_VST=m
# CONFIG_USB_GADGET is not set
+# CONFIG_UWB is not set
# CONFIG_MMC is not set
-
-#
-# LED devices
-#
+# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
-
-#
-# LED drivers
-#
-
-#
-# LED Triggers
-#
-
-#
-# InfiniBand support
-#
+# CONFIG_ACCESSIBILITY is not set
# CONFIG_INFINIBAND is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=m
#
-# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+# RTC interfaces
#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+# CONFIG_RTC_DRV_TEST is not set
#
-# Real Time Clock
+# I2C RTC drivers
#
-# CONFIG_RTC_CLASS is not set
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
#
-# DMA Engine support
+# SPI RTC drivers
#
-# CONFIG_DMA_ENGINE is not set
#
-# DMA Clients
+# Platform RTC drivers
#
+CONFIG_RTC_DRV_CMOS=m
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
#
-# DMA Devices
+# on-CPU RTC drivers
#
+# CONFIG_DMADEVICES is not set
+CONFIG_UIO=m
+CONFIG_UIO_CIF=m
+# CONFIG_UIO_PDRV is not set
+# CONFIG_UIO_PDRV_GENIRQ is not set
+# CONFIG_UIO_SMX is not set
+# CONFIG_UIO_SERCOS3 is not set
+# CONFIG_STAGING is not set
+CONFIG_STAGING_EXCLUDE_BUILD=y
#
# File systems
@@ -1478,27 +1583,31 @@ CONFIG_USB_LIBUSUAL=y
CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
CONFIG_EXT2_FS_XIP=y
-CONFIG_FS_XIP=y
CONFIG_EXT3_FS=y
# CONFIG_EXT3_FS_XATTR is not set
-# CONFIG_EXT4DEV_FS is not set
+CONFIG_EXT4_FS=m
+CONFIG_EXT4DEV_COMPAT=y
+CONFIG_EXT4_FS_XATTR=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_FS_XIP=y
CONFIG_JBD=y
-# CONFIG_JBD_DEBUG is not set
+CONFIG_JBD2=m
+CONFIG_FS_MBCACHE=m
CONFIG_REISERFS_FS=m
# CONFIG_REISERFS_CHECK is not set
# CONFIG_REISERFS_PROC_INFO is not set
# CONFIG_REISERFS_FS_XATTR is not set
# CONFIG_JFS_FS is not set
CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=y
# CONFIG_XFS_FS is not set
# CONFIG_GFS2_FS is not set
# CONFIG_OCFS2_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
+CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
CONFIG_AUTOFS_FS=y
CONFIG_AUTOFS4_FS=y
CONFIG_FUSE_FS=y
@@ -1530,11 +1639,11 @@ CONFIG_NTFS_RW=y
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
#
@@ -1550,25 +1659,23 @@ CONFIG_RAMFS=y
# CONFIG_JFFS2_FS is not set
# CONFIG_CRAMFS is not set
# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+CONFIG_OMFS_FS=m
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
+CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=m
CONFIG_NFS_V3=y
CONFIG_NFS_V3_ACL=y
CONFIG_NFS_V4=y
-CONFIG_NFS_DIRECTIO=y
CONFIG_NFSD=m
CONFIG_NFSD_V2_ACL=y
CONFIG_NFSD_V3=y
CONFIG_NFSD_V3_ACL=y
CONFIG_NFSD_V4=y
-CONFIG_NFSD_TCP=y
CONFIG_LOCKD=m
CONFIG_LOCKD_V4=y
CONFIG_EXPORTFS=m
@@ -1576,7 +1683,7 @@ CONFIG_NFS_ACL_SUPPORT=m
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=m
CONFIG_SUNRPC_GSS=m
-# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_SUNRPC_REGISTER_V4 is not set
CONFIG_RPCSEC_GSS_KRB5=m
# CONFIG_RPCSEC_GSS_SPKM3 is not set
CONFIG_SMB_FS=m
@@ -1616,10 +1723,6 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_KARMA_PARTITION is not set
# CONFIG_EFI_PARTITION is not set
# CONFIG_SYSV68_PARTITION is not set
-
-#
-# Native Language Support
-#
CONFIG_NLS=y
CONFIG_NLS_DEFAULT="utf8"
# CONFIG_NLS_CODEPAGE_437 is not set
@@ -1660,30 +1763,31 @@ CONFIG_NLS_ISO8859_1=y
# CONFIG_NLS_KOI8_R is not set
# CONFIG_NLS_KOI8_U is not set
CONFIG_NLS_UTF8=y
-
-#
-# Distributed Lock Manager
-#
# CONFIG_DLM is not set
#
-# Profiling support
-#
-CONFIG_PROFILING=y
-CONFIG_OPROFILE=m
-
-#
# Kernel hacking
#
CONFIG_TRACE_IRQFLAGS_SUPPORT=y
# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=2048
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
# CONFIG_DEBUG_FS is not set
# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
-CONFIG_CROSSCOMPILE=y
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+
+#
+# Tracers
+#
+CONFIG_DYNAMIC_PRINTK_DEBUG=y
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
CONFIG_CMDLINE=""
#
@@ -1691,64 +1795,113 @@ CONFIG_CMDLINE=""
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+CONFIG_SECURITY_FILE_CAPABILITIES=y
+CONFIG_CRYPTO=y
#
-# Cryptographic options
+# Crypto core or helper
#
-CONFIG_CRYPTO=y
+CONFIG_CRYPTO_FIPS=y
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_BLKCIPHER=y
CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_RNG=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_GF128MUL=m
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+CONFIG_CRYPTO_AUTHENC=m
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_SEQIV=m
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_CTR=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_ECB=m
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+
+#
+# Hash modes
+#
CONFIG_CRYPTO_HMAC=y
# CONFIG_CRYPTO_XCBC is not set
-# CONFIG_CRYPTO_NULL is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
# CONFIG_CRYPTO_MD4 is not set
CONFIG_CRYPTO_MD5=m
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+CONFIG_CRYPTO_RMD128=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_RMD256=m
+CONFIG_CRYPTO_RMD320=m
CONFIG_CRYPTO_SHA1=m
# CONFIG_CRYPTO_SHA256 is not set
# CONFIG_CRYPTO_SHA512 is not set
-# CONFIG_CRYPTO_WP512 is not set
# CONFIG_CRYPTO_TGR192 is not set
-# CONFIG_CRYPTO_GF128MUL is not set
-CONFIG_CRYPTO_ECB=m
-CONFIG_CRYPTO_CBC=m
-CONFIG_CRYPTO_PCBC=m
-# CONFIG_CRYPTO_LRW is not set
-# CONFIG_CRYPTO_CRYPTD is not set
-CONFIG_CRYPTO_DES=m
-# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=m
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=m
# CONFIG_CRYPTO_BLOWFISH is not set
-# CONFIG_CRYPTO_TWOFISH is not set
-# CONFIG_CRYPTO_SERPENT is not set
-# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
# CONFIG_CRYPTO_CAST5 is not set
# CONFIG_CRYPTO_CAST6 is not set
-# CONFIG_CRYPTO_TEA is not set
-CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_DES=m
+# CONFIG_CRYPTO_FCRYPT is not set
# CONFIG_CRYPTO_KHAZAD is not set
-# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_SALSA20=m
+CONFIG_CRYPTO_SEED=m
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
CONFIG_CRYPTO_DEFLATE=m
-# CONFIG_CRYPTO_MICHAEL_MIC is not set
-# CONFIG_CRYPTO_CRC32C is not set
-# CONFIG_CRYPTO_CAMELLIA is not set
-# CONFIG_CRYPTO_TEST is not set
+CONFIG_CRYPTO_LZO=m
#
-# Hardware crypto devices
+# Random Number Generation
#
+CONFIG_CRYPTO_ANSI_CPRNG=m
+# CONFIG_CRYPTO_HW is not set
#
# Library routines
#
CONFIG_BITREVERSE=y
CONFIG_CRC_CCITT=y
-# CONFIG_CRC16 is not set
-# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC16=m
+# CONFIG_CRC_T10DIF is not set
+CONFIG_CRC_ITU_T=m
CONFIG_CRC32=y
+CONFIG_CRC7=m
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=m
CONFIG_ZLIB_DEFLATE=m
+CONFIG_LZO_COMPRESS=m
+CONFIG_LZO_DECOMPRESS=m
CONFIG_TEXTSEARCH=y
CONFIG_TEXTSEARCH_KMP=m
CONFIG_TEXTSEARCH_BM=m
diff --git a/arch/mips/configs/ip22_defconfig b/arch/mips/configs/ip22_defconfig
index f719bf5e01a..11582287641 100644
--- a/arch/mips/configs/ip22_defconfig
+++ b/arch/mips/configs/ip22_defconfig
@@ -1,30 +1,34 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.23-rc2
-# Tue Aug 7 12:39:49 2007
+# Linux kernel version: 2.6.28-rc6
+# Fri Nov 28 15:41:33 2008
#
CONFIG_MIPS=y
#
# Machine selection
#
-CONFIG_ZONE_DMA=y
# CONFIG_MACH_ALCHEMY is not set
# CONFIG_BASLER_EXCITE is not set
+# CONFIG_BCM47XX is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
# CONFIG_LEMOTE_FULONG is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SIM is not set
-# CONFIG_MARKEINS is not set
+# CONFIG_MACH_EMMA is not set
# CONFIG_MACH_VR41XX is not set
+# CONFIG_NXP_STB220 is not set
+# CONFIG_NXP_STB225 is not set
# CONFIG_PNX8550_JBS is not set
# CONFIG_PNX8550_STB810 is not set
# CONFIG_PMC_MSP is not set
# CONFIG_PMC_YOSEMITE is not set
CONFIG_SGI_IP22=y
# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP28 is not set
# CONFIG_SGI_IP32 is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CARMEL is not set
@@ -35,34 +39,49 @@ CONFIG_SGI_IP22=y
# CONFIG_SIBYTE_SENTOSA is not set
# CONFIG_SIBYTE_BIGSUR is not set
# CONFIG_SNI_RM is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_TOSHIBA_RBTX4938 is not set
+# CONFIG_MACH_TX39XX is not set
+# CONFIG_MACH_TX49XX is not set
+# CONFIG_MIKROTIK_RB532 is not set
# CONFIG_WR_PPMC is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
# CONFIG_ARCH_HAS_ILOG2_U32 is not set
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_ARCH_SUPPORTS_OPROFILE=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
CONFIG_ARC=y
+CONFIG_CEVT_R4K=y
+CONFIG_CSRC_R4K=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
CONFIG_EARLY_PRINTK=y
CONFIG_SYS_HAS_EARLY_PRINTK=y
+# CONFIG_HOTPLUG_CPU is not set
+CONFIG_I8259=y
# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_ISA_DMA=y
CONFIG_GENERIC_ISA_DMA_SUPPORT_BROKEN=y
CONFIG_CPU_BIG_ENDIAN=y
# CONFIG_CPU_LITTLE_ENDIAN is not set
CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
CONFIG_IRQ_CPU=y
CONFIG_SWAP_IO_SPACE=y
+CONFIG_SGI_HAS_INDYDOG=y
+CONFIG_SGI_HAS_HAL2=y
+CONFIG_SGI_HAS_SEEQ=y
+CONFIG_SGI_HAS_WD93=y
+CONFIG_SGI_HAS_ZILOG=y
+CONFIG_SGI_HAS_I8042=y
+CONFIG_DEFAULT_SGI_PARTITION=y
CONFIG_ARC32=y
CONFIG_BOOT_ELF32=y
-CONFIG_MIPS_L1_CACHE_SHIFT=5
+CONFIG_MIPS_L1_CACHE_SHIFT=7
CONFIG_ARC_CONSOLE=y
CONFIG_ARC_PROMLIB=y
@@ -82,6 +101,7 @@ CONFIG_ARC_PROMLIB=y
# CONFIG_CPU_TX49XX is not set
CONFIG_CPU_R5000=y
# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R5500 is not set
# CONFIG_CPU_R6000 is not set
# CONFIG_CPU_NEVADA is not set
# CONFIG_CPU_R8000 is not set
@@ -115,18 +135,24 @@ CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
# CONFIG_DISCONTIGMEM_MANUAL is not set
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
-CONFIG_ZONE_DMA_FLAG=1
-CONFIG_BOUNCE=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
# CONFIG_HZ_48 is not set
# CONFIG_HZ_100 is not set
# CONFIG_HZ_128 is not set
@@ -159,13 +185,20 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
-# CONFIG_USER_NS is not set
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+# CONFIG_GROUP_SCHED is not set
CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_RELAY=y
+CONFIG_NAMESPACES=y
+CONFIG_UTS_NS=y
+CONFIG_IPC_NS=y
+CONFIG_USER_NS=y
+CONFIG_PID_NS=y
# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
@@ -177,6 +210,8 @@ CONFIG_KALLSYMS=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
+# CONFIG_PCSPKR_PLATFORM is not set
+# CONFIG_COMPAT_BRK is not set
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_ANON_INODES=y
@@ -185,14 +220,21 @@ CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
CONFIG_MODVERSIONS=y
@@ -203,6 +245,7 @@ CONFIG_BLOCK=y
# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
#
# IO Schedulers
@@ -216,6 +259,8 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_CLASSIC_RCU=y
+# CONFIG_FREEZER is not set
#
# Bus options (PCI, PCMCIA, EISA, ISA, TC)
@@ -224,29 +269,24 @@ CONFIG_HW_HAS_EISA=y
# CONFIG_ARCH_SUPPORTS_MSI is not set
# CONFIG_EISA is not set
CONFIG_MMU=y
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
+CONFIG_I8253=y
#
# Executable file formats
#
CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
CONFIG_BINFMT_MISC=m
CONFIG_TRAD_SIGNALS=y
#
# Power management options
#
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
# CONFIG_PM_DEBUG is not set
# CONFIG_SUSPEND is not set
-
-#
-# Networking
-#
CONFIG_NET=y
#
@@ -259,6 +299,8 @@ CONFIG_XFRM=y
CONFIG_XFRM_USER=m
# CONFIG_XFRM_SUB_POLICY is not set
CONFIG_XFRM_MIGRATE=y
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_XFRM_IPCOMP=m
CONFIG_NET_KEY=y
CONFIG_NET_KEY_MIGRATE=y
CONFIG_INET=y
@@ -282,42 +324,13 @@ CONFIG_INET_TUNNEL=m
CONFIG_INET_XFRM_MODE_TRANSPORT=m
CONFIG_INET_XFRM_MODE_TUNNEL=m
CONFIG_INET_XFRM_MODE_BEET=m
+# CONFIG_INET_LRO is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
CONFIG_TCP_MD5SIG=y
-CONFIG_IP_VS=m
-# CONFIG_IP_VS_DEBUG is not set
-CONFIG_IP_VS_TAB_BITS=12
-
-#
-# IPVS transport protocol load balancing support
-#
-CONFIG_IP_VS_PROTO_TCP=y
-CONFIG_IP_VS_PROTO_UDP=y
-CONFIG_IP_VS_PROTO_ESP=y
-CONFIG_IP_VS_PROTO_AH=y
-
-#
-# IPVS scheduler
-#
-CONFIG_IP_VS_RR=m
-CONFIG_IP_VS_WRR=m
-CONFIG_IP_VS_LC=m
-CONFIG_IP_VS_WLC=m
-CONFIG_IP_VS_LBLC=m
-CONFIG_IP_VS_LBLCR=m
-CONFIG_IP_VS_DH=m
-CONFIG_IP_VS_SH=m
-CONFIG_IP_VS_SED=m
-CONFIG_IP_VS_NQ=m
-
-#
-# IPVS application helper
-#
-CONFIG_IP_VS_FTP=m
CONFIG_IPV6=m
CONFIG_IPV6_PRIVACY=y
CONFIG_IPV6_ROUTER_PREF=y
@@ -334,12 +347,16 @@ CONFIG_INET6_XFRM_MODE_TUNNEL=m
CONFIG_INET6_XFRM_MODE_BEET=m
CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
CONFIG_IPV6_SIT=m
+CONFIG_IPV6_NDISC_NODETYPE=y
CONFIG_IPV6_TUNNEL=m
CONFIG_IPV6_MULTIPLE_TABLES=y
CONFIG_IPV6_SUBTREES=y
+CONFIG_IPV6_MROUTE=y
+CONFIG_IPV6_PIMSM_V2=y
CONFIG_NETWORK_SECMARK=y
CONFIG_NETFILTER=y
# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
#
# Core Netfilter Configuration
@@ -347,12 +364,12 @@ CONFIG_NETFILTER=y
CONFIG_NETFILTER_NETLINK=m
CONFIG_NETFILTER_NETLINK_QUEUE=m
CONFIG_NETFILTER_NETLINK_LOG=m
-CONFIG_NF_CONNTRACK_ENABLED=m
CONFIG_NF_CONNTRACK=m
CONFIG_NF_CT_ACCT=y
CONFIG_NF_CONNTRACK_MARK=y
CONFIG_NF_CONNTRACK_SECMARK=y
CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=m
CONFIG_NF_CT_PROTO_GRE=m
CONFIG_NF_CT_PROTO_SCTP=m
CONFIG_NF_CT_PROTO_UDPLITE=m
@@ -366,18 +383,22 @@ CONFIG_NF_CONNTRACK_SANE=m
CONFIG_NF_CONNTRACK_SIP=m
CONFIG_NF_CONNTRACK_TFTP=m
CONFIG_NF_CT_NETLINK=m
+CONFIG_NETFILTER_TPROXY=m
CONFIG_NETFILTER_XTABLES=m
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
CONFIG_NETFILTER_XT_TARGET_DSCP=m
CONFIG_NETFILTER_XT_TARGET_MARK=m
-CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_RATEEST=m
+CONFIG_NETFILTER_XT_TARGET_TPROXY=m
CONFIG_NETFILTER_XT_TARGET_TRACE=m
CONFIG_NETFILTER_XT_TARGET_SECMARK=m
-CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
@@ -386,39 +407,75 @@ CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
CONFIG_NETFILTER_XT_MATCH_DCCP=m
CONFIG_NETFILTER_XT_MATCH_DSCP=m
CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
CONFIG_NETFILTER_XT_MATCH_MAC=m
CONFIG_NETFILTER_XT_MATCH_MARK=m
-CONFIG_NETFILTER_XT_MATCH_POLICY=m
CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_OWNER=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_RATEEST=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_RECENT=m
+CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT=y
CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_SOCKET=m
CONFIG_NETFILTER_XT_MATCH_STATE=m
CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
CONFIG_NETFILTER_XT_MATCH_STRING=m
CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_TIME=m
CONFIG_NETFILTER_XT_MATCH_U32=m
-CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+CONFIG_IP_VS=m
+CONFIG_IP_VS_IPV6=y
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_AH_ESP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
#
# IP: Netfilter Configuration
#
+CONFIG_NF_DEFRAG_IPV4=m
CONFIG_NF_CONNTRACK_IPV4=m
CONFIG_NF_CONNTRACK_PROC_COMPAT=y
CONFIG_IP_NF_QUEUE=m
CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_TOS=m
-CONFIG_IP_NF_MATCH_RECENT=m
-CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_OWNER=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IP_NF_TARGET_LOG=m
@@ -426,11 +483,13 @@ CONFIG_IP_NF_TARGET_ULOG=m
CONFIG_NF_NAT=m
CONFIG_NF_NAT_NEEDED=y
CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
CONFIG_IP_NF_TARGET_NETMAP=m
-CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
CONFIG_NF_NAT_SNMP_BASIC=m
+CONFIG_NF_NAT_PROTO_DCCP=m
CONFIG_NF_NAT_PROTO_GRE=m
+CONFIG_NF_NAT_PROTO_UDPLITE=m
+CONFIG_NF_NAT_PROTO_SCTP=m
CONFIG_NF_NAT_FTP=m
CONFIG_NF_NAT_IRC=m
CONFIG_NF_NAT_TFTP=m
@@ -439,32 +498,30 @@ CONFIG_NF_NAT_PPTP=m
CONFIG_NF_NAT_H323=m
CONFIG_NF_NAT_SIP=m
CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
CONFIG_IP_NF_TARGET_ECN=m
CONFIG_IP_NF_TARGET_TTL=m
-CONFIG_IP_NF_TARGET_CLUSTERIP=m
CONFIG_IP_NF_RAW=m
CONFIG_IP_NF_ARPTABLES=m
CONFIG_IP_NF_ARPFILTER=m
CONFIG_IP_NF_ARP_MANGLE=m
#
-# IPv6: Netfilter Configuration (EXPERIMENTAL)
+# IPv6: Netfilter Configuration
#
CONFIG_NF_CONNTRACK_IPV6=m
CONFIG_IP6_NF_QUEUE=m
CONFIG_IP6_NF_IPTABLES=m
-CONFIG_IP6_NF_MATCH_RT=m
-CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
CONFIG_IP6_NF_MATCH_HL=m
-CONFIG_IP6_NF_MATCH_OWNER=m
CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-CONFIG_IP6_NF_MATCH_AH=m
CONFIG_IP6_NF_MATCH_MH=m
-CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_MATCH_RT=m
CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_FILTER=m
CONFIG_IP6_NF_TARGET_REJECT=m
CONFIG_IP6_NF_MANGLE=m
CONFIG_IP6_NF_TARGET_HL=m
@@ -479,6 +536,7 @@ CONFIG_SCTP_HMAC_MD5=y
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
@@ -488,12 +546,7 @@ CONFIG_SCTP_HMAC_MD5=y
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
CONFIG_NET_SCHED=y
-CONFIG_NET_SCH_FIFO=y
#
# Queueing/Scheduling
@@ -502,7 +555,7 @@ CONFIG_NET_SCH_CBQ=m
CONFIG_NET_SCH_HTB=m
CONFIG_NET_SCH_HFSC=m
CONFIG_NET_SCH_PRIO=m
-CONFIG_NET_SCH_RR=m
+# CONFIG_NET_SCH_MULTIQ is not set
CONFIG_NET_SCH_RED=m
CONFIG_NET_SCH_SFQ=m
CONFIG_NET_SCH_TEQL=m
@@ -526,6 +579,7 @@ CONFIG_NET_CLS_U32=m
# CONFIG_CLS_U32_MARK is not set
CONFIG_NET_CLS_RSVP=m
CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_FLOW=m
# CONFIG_NET_EMATCH is not set
CONFIG_NET_CLS_ACT=y
CONFIG_NET_ACT_POLICE=y
@@ -533,35 +587,28 @@ CONFIG_NET_ACT_GACT=m
CONFIG_GACT_PROB=y
CONFIG_NET_ACT_MIRRED=m
CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_NAT=m
CONFIG_NET_ACT_PEDIT=m
CONFIG_NET_ACT_SIMP=m
-CONFIG_NET_CLS_POLICE=y
+CONFIG_NET_ACT_SKBEDIT=m
# CONFIG_NET_CLS_IND is not set
+CONFIG_NET_SCH_FIFO=y
#
# Network testing
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
+CONFIG_PHONET=m
CONFIG_FIB_RULES=y
-
-#
-# Wireless
-#
-CONFIG_CFG80211=m
+# CONFIG_WIRELESS is not set
CONFIG_WIRELESS_EXT=y
-CONFIG_MAC80211=m
-# CONFIG_MAC80211_DEBUG is not set
CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
-CONFIG_IEEE80211_CRYPT_TKIP=m
-CONFIG_IEEE80211_SOFTMAC=m
-# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
CONFIG_RFKILL=m
CONFIG_RFKILL_INPUT=m
# CONFIG_NET_9P is not set
@@ -588,7 +635,9 @@ CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
CONFIG_ATA_OVER_ETH=m
+# CONFIG_BLK_DEV_HD is not set
# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
#
@@ -628,20 +677,22 @@ CONFIG_SCSI_SPI_ATTRS=m
# CONFIG_SCSI_FC_ATTRS is not set
CONFIG_SCSI_ISCSI_ATTRS=m
# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
CONFIG_ISCSI_TCP=m
CONFIG_SGIWD93_SCSI=y
# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
# CONFIG_ATA is not set
# CONFIG_MD is not set
CONFIG_NETDEVICES=y
-# CONFIG_NETDEVICES_MULTIQUEUE is not set
# CONFIG_IFB is not set
CONFIG_DUMMY=m
CONFIG_BONDING=m
CONFIG_MACVLAN=m
CONFIG_EQUALIZER=m
CONFIG_TUN=m
+CONFIG_VETH=m
CONFIG_PHYLIB=m
#
@@ -656,11 +707,21 @@ CONFIG_CICADA_PHY=m
# CONFIG_SMSC_PHY is not set
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
-# CONFIG_FIXED_PHY is not set
+CONFIG_REALTEK_PHY=m
+CONFIG_MDIO_BITBANG=m
CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
+CONFIG_MII=m
# CONFIG_AX88796 is not set
+CONFIG_SMC91X=m
# CONFIG_DM9000 is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
CONFIG_SGISEEQ=y
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
@@ -672,12 +733,12 @@ CONFIG_WLAN_PRE80211=y
CONFIG_STRIP=m
CONFIG_WLAN_80211=y
# CONFIG_LIBERTAS is not set
+# CONFIG_IWLWIFI_LEDS is not set
CONFIG_HOSTAP=m
# CONFIG_HOSTAP_FIRMWARE is not set
# CONFIG_WAN is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
-# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
@@ -699,7 +760,6 @@ CONFIG_INPUT_MOUSEDEV_PSAUX=y
CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
# CONFIG_INPUT_EVDEV is not set
# CONFIG_INPUT_EVBUG is not set
@@ -720,6 +780,7 @@ CONFIG_MOUSE_PS2_LOGIPS2PP=y
# CONFIG_MOUSE_PS2_SYNAPTICS is not set
# CONFIG_MOUSE_PS2_LIFEBOOK is not set
CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
# CONFIG_MOUSE_PS2_TOUCHKIT is not set
CONFIG_MOUSE_SERIAL=m
# CONFIG_MOUSE_VSXXXAA is not set
@@ -742,9 +803,11 @@ CONFIG_SERIO_RAW=m
# Character devices
#
CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
CONFIG_VT_CONSOLE=y
CONFIG_HW_CONSOLE=y
CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_DEVKMEM=y
# CONFIG_SERIAL_NONSTANDARD is not set
#
@@ -761,6 +824,17 @@ CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+CONFIG_RAW_DRIVER=m
+CONFIG_MAX_RAW_DEVS=256
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+CONFIG_THERMAL=m
CONFIG_WATCHDOG=y
# CONFIG_WATCHDOG_NOWAYOUT is not set
@@ -769,47 +843,50 @@ CONFIG_WATCHDOG=y
#
# CONFIG_SOFT_WATCHDOG is not set
CONFIG_INDYDOG=m
-# CONFIG_HW_RANDOM is not set
-# CONFIG_RTC is not set
-# CONFIG_R3964 is not set
-CONFIG_RAW_DRIVER=m
-CONFIG_MAX_RAW_DEVS=256
-# CONFIG_TCG_TPM is not set
-# CONFIG_I2C is not set
+CONFIG_SSB_POSSIBLE=y
#
-# SPI support
+# Sonics Silicon Backplane
#
-# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
-# CONFIG_W1 is not set
-# CONFIG_POWER_SUPPLY is not set
-# CONFIG_HWMON is not set
+# CONFIG_SSB is not set
#
# Multifunction device drivers
#
+# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
#
+
+#
+# Multimedia core support
+#
# CONFIG_VIDEO_DEV is not set
# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
# CONFIG_DAB is not set
#
# Graphics support
#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Display device support
#
# CONFIG_DISPLAY_SUPPORT is not set
-# CONFIG_VGASTATE is not set
-# CONFIG_VIDEO_OUTPUT_CONTROL is not set
-# CONFIG_FB is not set
#
# Console display driver support
@@ -823,48 +900,77 @@ CONFIG_LOGO=y
# CONFIG_LOGO_LINUX_VGA16 is not set
# CONFIG_LOGO_LINUX_CLUT224 is not set
CONFIG_LOGO_SGI_CLUT224=y
-
-#
-# Sound
-#
# CONFIG_SOUND is not set
CONFIG_HID_SUPPORT=y
CONFIG_HID=y
# CONFIG_HID_DEBUG is not set
+CONFIG_HIDRAW=y
+CONFIG_HID_PID=y
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
CONFIG_USB_SUPPORT=y
# CONFIG_USB_ARCH_HAS_HCD is not set
# CONFIG_USB_ARCH_HAS_OHCI is not set
# CONFIG_USB_ARCH_HAS_EHCI is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# Enable Host or Gadget support to see Inventra options
#
#
-# USB Gadget Support
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
# CONFIG_USB_GADGET is not set
# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
-# CONFIG_RTC_CLASS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
#
-# DMA Engine support
+# RTC interfaces
#
-# CONFIG_DMA_ENGINE is not set
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+# CONFIG_RTC_DRV_TEST is not set
#
-# DMA Clients
+# SPI RTC drivers
#
#
-# DMA Devices
+# Platform RTC drivers
#
+# CONFIG_RTC_DRV_CMOS is not set
+CONFIG_RTC_DRV_DS1286=y
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
#
-# Userspace I/O
+# on-CPU RTC drivers
#
+# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+CONFIG_STAGING_EXCLUDE_BUILD=y
#
# File systems
@@ -876,29 +982,33 @@ CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y
CONFIG_EXT3_FS_POSIX_ACL=y
CONFIG_EXT3_FS_SECURITY=y
-# CONFIG_EXT4DEV_FS is not set
+CONFIG_EXT4_FS=m
+CONFIG_EXT4DEV_COMPAT=y
+CONFIG_EXT4_FS_XATTR=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
CONFIG_JBD=y
-# CONFIG_JBD_DEBUG is not set
+CONFIG_JBD2=m
CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=y
CONFIG_XFS_FS=m
CONFIG_XFS_QUOTA=y
-CONFIG_XFS_SECURITY=y
# CONFIG_XFS_POSIX_ACL is not set
# CONFIG_XFS_RT is not set
-# CONFIG_GFS2_FS is not set
+# CONFIG_XFS_DEBUG is not set
# CONFIG_OCFS2_FS is not set
-CONFIG_MINIX_FS=m
-# CONFIG_ROMFS_FS is not set
+CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+# CONFIG_PRINT_QUOTA_WARNING is not set
# CONFIG_QFMT_V1 is not set
CONFIG_QFMT_V2=m
CONFIG_QUOTACTL=y
-CONFIG_DNOTIFY=y
CONFIG_AUTOFS_FS=m
CONFIG_AUTOFS4_FS=m
CONFIG_FUSE_FS=m
@@ -929,11 +1039,11 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
CONFIG_TMPFS_POSIX_ACL=y
# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
CONFIG_CONFIGFS_FS=m
#
@@ -949,27 +1059,25 @@ CONFIG_CONFIGFS_FS=m
CONFIG_EFS_FS=m
# CONFIG_CRAMFS is not set
# CONFIG_VXFS_FS is not set
+CONFIG_MINIX_FS=m
+CONFIG_OMFS_FS=m
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
CONFIG_UFS_FS=m
# CONFIG_UFS_FS_WRITE is not set
# CONFIG_UFS_DEBUG is not set
-
-#
-# Network File Systems
-#
+CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=m
CONFIG_NFS_V3=y
CONFIG_NFS_V3_ACL=y
# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
CONFIG_NFSD=m
CONFIG_NFSD_V2_ACL=y
CONFIG_NFSD_V3=y
CONFIG_NFSD_V3_ACL=y
# CONFIG_NFSD_V4 is not set
-CONFIG_NFSD_TCP=y
CONFIG_LOCKD=m
CONFIG_LOCKD_V4=y
CONFIG_EXPORTFS=m
@@ -977,7 +1085,7 @@ CONFIG_NFS_ACL_SUPPORT=m
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=m
CONFIG_SUNRPC_GSS=m
-# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_SUNRPC_REGISTER_V4 is not set
CONFIG_RPCSEC_GSS_KRB5=m
# CONFIG_RPCSEC_GSS_SPKM3 is not set
CONFIG_SMB_FS=m
@@ -986,12 +1094,12 @@ CONFIG_SMB_NLS_REMOTE="cp437"
CONFIG_CIFS=m
# CONFIG_CIFS_STATS is not set
# CONFIG_CIFS_WEAK_PW_HASH is not set
+CONFIG_CIFS_UPCALL=y
# CONFIG_CIFS_XATTR is not set
# CONFIG_CIFS_DEBUG2 is not set
# CONFIG_CIFS_EXPERIMENTAL is not set
# CONFIG_NCP_FS is not set
CONFIG_CODA_FS=m
-# CONFIG_CODA_FS_OLD_API is not set
# CONFIG_AFS_FS is not set
#
@@ -1015,10 +1123,6 @@ CONFIG_SGI_PARTITION=y
# CONFIG_KARMA_PARTITION is not set
# CONFIG_EFI_PARTITION is not set
# CONFIG_SYSV68_PARTITION is not set
-
-#
-# Native Language Support
-#
CONFIG_NLS=m
CONFIG_NLS_DEFAULT="iso8859-1"
CONFIG_NLS_CODEPAGE_437=m
@@ -1059,30 +1163,32 @@ CONFIG_NLS_ISO8859_15=m
CONFIG_NLS_KOI8_R=m
CONFIG_NLS_KOI8_U=m
CONFIG_NLS_UTF8=m
-
-#
-# Distributed Lock Manager
-#
CONFIG_DLM=m
# CONFIG_DLM_DEBUG is not set
#
-# Profiling support
-#
-# CONFIG_PROFILING is not set
-
-#
# Kernel hacking
#
CONFIG_TRACE_IRQFLAGS_SUPPORT=y
# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
# CONFIG_DEBUG_FS is not set
# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
-CONFIG_CROSSCOMPILE=y
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+
+#
+# Tracers
+#
+CONFIG_DYNAMIC_PRINTK_DEBUG=y
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
CONFIG_CMDLINE=""
#
@@ -1091,46 +1197,97 @@ CONFIG_CMDLINE=""
CONFIG_KEYS=y
CONFIG_KEYS_DEBUG_PROC_KEYS=y
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+CONFIG_SECURITY_FILE_CAPABILITIES=y
CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_FIPS=y
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_ABLKCIPHER=m
-CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_BLKCIPHER=y
CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_RNG=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_CRYPTD=m
+CONFIG_CRYPTO_AUTHENC=m
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_SEQIV=m
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_CTR=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+
+#
+# Hash modes
+#
CONFIG_CRYPTO_HMAC=y
CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_NULL=m
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=m
CONFIG_CRYPTO_MD4=m
CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_RMD128=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_RMD256=m
+CONFIG_CRYPTO_RMD320=m
CONFIG_CRYPTO_SHA1=m
CONFIG_CRYPTO_SHA256=m
CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_GF128MUL=m
-CONFIG_CRYPTO_ECB=m
-CONFIG_CRYPTO_CBC=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_LRW=m
-CONFIG_CRYPTO_CRYPTD=m
-CONFIG_CRYPTO_DES=m
-CONFIG_CRYPTO_FCRYPT=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_TWOFISH_COMMON=m
-CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_WP512=m
+
+#
+# Ciphers
+#
CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAMELLIA=m
CONFIG_CRYPTO_CAST5=m
CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_FCRYPT=m
CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_SALSA20=m
+CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+
+#
+# Compression
+#
CONFIG_CRYPTO_DEFLATE=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_CRC32C=m
-CONFIG_CRYPTO_CAMELLIA=m
-# CONFIG_CRYPTO_TEST is not set
+CONFIG_CRYPTO_LZO=m
+
+#
+# Random Number Generation
+#
+CONFIG_CRYPTO_ANSI_CPRNG=m
# CONFIG_CRYPTO_HW is not set
#
@@ -1139,12 +1296,15 @@ CONFIG_CRYPTO_CAMELLIA=m
CONFIG_BITREVERSE=m
# CONFIG_CRC_CCITT is not set
CONFIG_CRC16=m
-# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC_T10DIF=m
+CONFIG_CRC_ITU_T=m
CONFIG_CRC32=m
# CONFIG_CRC7 is not set
CONFIG_LIBCRC32C=m
CONFIG_ZLIB_INFLATE=m
CONFIG_ZLIB_DEFLATE=m
+CONFIG_LZO_COMPRESS=m
+CONFIG_LZO_DECOMPRESS=m
CONFIG_TEXTSEARCH=y
CONFIG_TEXTSEARCH_KMP=m
CONFIG_TEXTSEARCH_BM=m
diff --git a/arch/mips/configs/ip32_defconfig b/arch/mips/configs/ip32_defconfig
index fe4699df962..de4c7a0a96d 100644
--- a/arch/mips/configs/ip32_defconfig
+++ b/arch/mips/configs/ip32_defconfig
@@ -1,71 +1,71 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20
-# Tue Feb 20 21:47:33 2007
+# Linux kernel version: 2.6.28-rc7
+# Wed Dec 10 14:39:08 2008
#
CONFIG_MIPS=y
#
# Machine selection
#
-CONFIG_ZONE_DMA=y
-# CONFIG_MIPS_MTX1 is not set
-# CONFIG_MIPS_BOSPORUS is not set
-# CONFIG_MIPS_PB1000 is not set
-# CONFIG_MIPS_PB1100 is not set
-# CONFIG_MIPS_PB1500 is not set
-# CONFIG_MIPS_PB1550 is not set
-# CONFIG_MIPS_PB1200 is not set
-# CONFIG_MIPS_DB1000 is not set
-# CONFIG_MIPS_DB1100 is not set
-# CONFIG_MIPS_DB1500 is not set
-# CONFIG_MIPS_DB1550 is not set
-# CONFIG_MIPS_DB1200 is not set
-# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_MACH_ALCHEMY is not set
# CONFIG_BASLER_EXCITE is not set
+# CONFIG_BCM47XX is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
+# CONFIG_LEMOTE_FULONG is not set
# CONFIG_MIPS_MALTA is not set
-# CONFIG_WR_PPMC is not set
# CONFIG_MIPS_SIM is not set
-# CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_MACH_EMMA is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_NXP_STB220 is not set
+# CONFIG_NXP_STB225 is not set
# CONFIG_PNX8550_JBS is not set
# CONFIG_PNX8550_STB810 is not set
-# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_MSP is not set
# CONFIG_PMC_YOSEMITE is not set
-# CONFIG_MARKEINS is not set
# CONFIG_SGI_IP22 is not set
# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP28 is not set
CONFIG_SGI_IP32=y
-# CONFIG_SIBYTE_BIGSUR is not set
-# CONFIG_SIBYTE_SWARM is not set
-# CONFIG_SIBYTE_SENTOSA is not set
-# CONFIG_SIBYTE_RHONE is not set
-# CONFIG_SIBYTE_CARMEL is not set
-# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CARMEL is not set
# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_BIGSUR is not set
# CONFIG_SNI_RM is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_TOSHIBA_RBTX4938 is not set
+# CONFIG_MACH_TX39XX is not set
+# CONFIG_MACH_TX49XX is not set
+# CONFIG_MIKROTIK_RB532 is not set
+# CONFIG_WR_PPMC is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
# CONFIG_ARCH_HAS_ILOG2_U32 is not set
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_ARCH_SUPPORTS_OPROFILE=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
CONFIG_ARC=y
+CONFIG_CEVT_R4K=y
+CONFIG_CSRC_R4K=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
+# CONFIG_HOTPLUG_CPU is not set
+# CONFIG_NO_IOPORT is not set
CONFIG_CPU_BIG_ENDIAN=y
# CONFIG_CPU_LITTLE_ENDIAN is not set
CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
+CONFIG_IRQ_CPU=y
CONFIG_ARC32=y
CONFIG_BOOT_ELF32=y
CONFIG_MIPS_L1_CACHE_SHIFT=5
@@ -75,6 +75,7 @@ CONFIG_ARC_PROMLIB=y
#
# CPU selection
#
+# CONFIG_CPU_LOONGSON2 is not set
# CONFIG_CPU_MIPS32_R1 is not set
# CONFIG_CPU_MIPS32_R2 is not set
# CONFIG_CPU_MIPS64_R1 is not set
@@ -87,6 +88,7 @@ CONFIG_ARC_PROMLIB=y
# CONFIG_CPU_TX49XX is not set
CONFIG_CPU_R5000=y
# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R5500 is not set
# CONFIG_CPU_R6000 is not set
# CONFIG_CPU_NEVADA is not set
# CONFIG_CPU_R8000 is not set
@@ -116,65 +118,73 @@ CONFIG_RM7000_CPU_SCACHE=y
CONFIG_MIPS_MT_DISABLED=y
# CONFIG_MIPS_MT_SMP is not set
# CONFIG_MIPS_MT_SMTC is not set
-# CONFIG_MIPS_VPE_LOADER is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
# CONFIG_DISCONTIGMEM_MANUAL is not set
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_RESOURCES_64BIT=y
-CONFIG_ZONE_DMA_FLAG=1
+CONFIG_PHYS_ADDR_T_64BIT=y
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
# CONFIG_HZ_48 is not set
# CONFIG_HZ_100 is not set
# CONFIG_HZ_128 is not set
-# CONFIG_HZ_250 is not set
+CONFIG_HZ_250=y
# CONFIG_HZ_256 is not set
-CONFIG_HZ_1000=y
+# CONFIG_HZ_1000 is not set
# CONFIG_HZ_1024 is not set
CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
-CONFIG_HZ=1000
-# CONFIG_PREEMPT_NONE is not set
-CONFIG_PREEMPT_VOLUNTARY=y
+CONFIG_HZ=250
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not set
# CONFIG_KEXEC is not set
+# CONFIG_SECCOMP is not set
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
-# Code maturity level options
+# General setup
#
CONFIG_EXPERIMENTAL=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
CONFIG_LOCALVERSION=""
CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
-# CONFIG_IPC_NS is not set
CONFIG_SYSVIPC_SYSCTL=y
-# CONFIG_POSIX_MQUEUE is not set
+CONFIG_POSIX_MQUEUE=y
CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
# CONFIG_TASKSTATS is not set
-# CONFIG_UTS_NS is not set
-# CONFIG_AUDIT is not set
-# CONFIG_IKCONFIG is not set
+CONFIG_AUDIT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+# CONFIG_GROUP_SCHED is not set
CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_RELAY=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL=y
CONFIG_EMBEDDED=y
CONFIG_SYSCTL_SYSCALL=y
@@ -184,27 +194,43 @@ CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
+CONFIG_PCSPKR_PLATFORM=y
+CONFIG_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
-CONFIG_SLAB=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+# CONFIG_MARKERS is not set
+CONFIG_OPROFILE=m
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
-
-#
-# Loadable module support
-#
-# CONFIG_MODULES is not set
-
-#
-# Block layer
-#
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+CONFIG_BLOCK_COMPAT=y
#
# IO Schedulers
@@ -213,59 +239,50 @@ CONFIG_IOSCHED_NOOP=y
CONFIG_IOSCHED_AS=y
CONFIG_IOSCHED_DEADLINE=y
CONFIG_IOSCHED_CFQ=y
-CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_AS is not set
# CONFIG_DEFAULT_DEADLINE is not set
-# CONFIG_DEFAULT_CFQ is not set
+CONFIG_DEFAULT_CFQ=y
# CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_CLASSIC_RCU=y
+# CONFIG_FREEZER is not set
#
# Bus options (PCI, PCMCIA, EISA, ISA, TC)
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCI_LEGACY is not set
CONFIG_MMU=y
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
# CONFIG_HOTPLUG_PCI is not set
#
# Executable file formats
#
CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
CONFIG_BINFMT_MISC=y
-# CONFIG_BUILD_ELF64 is not set
CONFIG_MIPS32_COMPAT=y
CONFIG_COMPAT=y
CONFIG_SYSVIPC_COMPAT=y
CONFIG_MIPS32_O32=y
-# CONFIG_MIPS32_N32 is not set
+CONFIG_MIPS32_N32=y
CONFIG_BINFMT_ELF32=y
#
# Power management options
#
-CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
-# CONFIG_PM_DEBUG is not set
-# CONFIG_PM_SYSFS_DEPRECATED is not set
-
-#
-# Networking
-#
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_PM is not set
CONFIG_NET=y
#
# Networking options
#
-# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -273,56 +290,83 @@ CONFIG_XFRM=y
CONFIG_XFRM_USER=y
# CONFIG_XFRM_SUB_POLICY is not set
CONFIG_XFRM_MIGRATE=y
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_XFRM_IPCOMP=m
CONFIG_NET_KEY=y
CONFIG_NET_KEY_MIGRATE=y
CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
+CONFIG_IP_MULTICAST=y
# CONFIG_IP_ADVANCED_ROUTER is not set
CONFIG_IP_FIB_HASH=y
CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_DHCP=y
CONFIG_IP_PNP_BOOTP=y
# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+# CONFIG_NET_IPGRE_BROADCAST is not set
+# CONFIG_IP_MROUTE is not set
# CONFIG_ARPD is not set
# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_XFRM_TUNNEL is not set
-# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
+CONFIG_INET_TUNNEL=m
CONFIG_INET_XFRM_MODE_TRANSPORT=y
CONFIG_INET_XFRM_MODE_TUNNEL=y
CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
-# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_BIC=m
CONFIG_TCP_CONG_CUBIC=y
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+# CONFIG_TCP_CONG_HSTCP is not set
+# CONFIG_TCP_CONG_HYBLA is not set
+# CONFIG_TCP_CONG_VEGAS is not set
+# CONFIG_TCP_CONG_SCALABLE is not set
+# CONFIG_TCP_CONG_LP is not set
+# CONFIG_TCP_CONG_VENO is not set
+# CONFIG_TCP_CONG_YEAH is not set
+# CONFIG_TCP_CONG_ILLINOIS is not set
+# CONFIG_DEFAULT_BIC is not set
+CONFIG_DEFAULT_CUBIC=y
+# CONFIG_DEFAULT_HTCP is not set
+# CONFIG_DEFAULT_VEGAS is not set
+# CONFIG_DEFAULT_WESTWOOD is not set
+# CONFIG_DEFAULT_RENO is not set
CONFIG_DEFAULT_TCP_CONG="cubic"
CONFIG_TCP_MD5SIG=y
-# CONFIG_IPV6 is not set
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+# CONFIG_IPV6_MIP6 is not set
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_NDISC_NODETYPE=y
+CONFIG_IPV6_TUNNEL=m
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
CONFIG_NETWORK_SECMARK=y
# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
@@ -332,10 +376,6 @@ CONFIG_NETWORK_SECMARK=y
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
# CONFIG_NET_SCHED is not set
#
@@ -343,15 +383,14 @@ CONFIG_NETWORK_SECMARK=y
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
-CONFIG_IEEE80211=y
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=y
-CONFIG_IEEE80211_CRYPT_CCMP=y
-CONFIG_IEEE80211_SOFTMAC=y
-# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
-CONFIG_WIRELESS_EXT=y
+# CONFIG_AF_RXRPC is not set
+# CONFIG_PHONET is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
#
# Device Drivers
@@ -360,60 +399,40 @@ CONFIG_WIRELESS_EXT=y
#
# Generic Driver Options
#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
# CONFIG_SYS_HYPERVISOR is not set
-
-#
-# Connector - unified userspace <-> kernelspace linker
-#
CONFIG_CONNECTOR=y
CONFIG_PROC_EVENTS=y
-
-#
-# Memory Technology Devices (MTD)
-#
# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNPACPI is not set
-
-#
-# Block devices
-#
+CONFIG_BLK_DEV=y
# CONFIG_BLK_CPQ_DA is not set
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
# CONFIG_BLK_DEV_UMEM is not set
# CONFIG_BLK_DEV_COW_COMMON is not set
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-CONFIG_CDROM_PKTCDVD=y
-CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
-CONFIG_ATA_OVER_ETH=y
-
-#
-# Misc devices
-#
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_PHANTOM is not set
+# CONFIG_EEPROM_93CX6 is not set
CONFIG_SGI_IOC4=y
# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
+CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
#
@@ -421,19 +440,20 @@ CONFIG_SGI_IOC4=y
#
CONFIG_RAID_ATTRS=y
CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
CONFIG_SCSI_TGT=y
-CONFIG_SCSI_NETLINK=y
+# CONFIG_SCSI_NETLINK is not set
CONFIG_SCSI_PROC_FS=y
#
# SCSI support type (disk, tape, CD-ROM)
#
CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=y
-CONFIG_CHR_DEV_OSST=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
CONFIG_BLK_DEV_SR=y
CONFIG_BLK_DEV_SR_VENDOR=y
-CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SG=m
# CONFIG_CHR_DEV_SCH is not set
#
@@ -443,35 +463,36 @@ CONFIG_SCSI_MULTI_LUN=y
CONFIG_SCSI_CONSTANTS=y
CONFIG_SCSI_LOGGING=y
CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_SCSI_WAIT_SCAN=m
#
# SCSI Transports
#
CONFIG_SCSI_SPI_ATTRS=y
-CONFIG_SCSI_FC_ATTRS=y
+# CONFIG_SCSI_FC_ATTRS is not set
# CONFIG_SCSI_ISCSI_ATTRS is not set
CONFIG_SCSI_SAS_ATTRS=y
CONFIG_SCSI_SAS_LIBSAS=y
+CONFIG_SCSI_SAS_HOST_SMP=y
# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set
-
-#
-# SCSI low-level drivers
-#
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_ACARD is not set
# CONFIG_SCSI_AACRAID is not set
CONFIG_SCSI_AIC7XXX=y
-CONFIG_AIC7XXX_CMDS_PER_DEVICE=8
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=32
CONFIG_AIC7XXX_RESET_DELAY_MS=15000
CONFIG_AIC7XXX_DEBUG_ENABLE=y
CONFIG_AIC7XXX_DEBUG_MASK=0
CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
# CONFIG_SCSI_AIC7XXX_OLD is not set
# CONFIG_SCSI_AIC79XX is not set
-CONFIG_SCSI_AIC94XX=y
-# CONFIG_AIC94XX_DEBUG is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ADVANSYS is not set
# CONFIG_SCSI_ARCMSR is not set
# CONFIG_MEGARAID_NEWGEN is not set
# CONFIG_MEGARAID_LEGACY is not set
@@ -482,6 +503,7 @@ CONFIG_SCSI_AIC94XX=y
# CONFIG_SCSI_IPS is not set
# CONFIG_SCSI_INITIO is not set
# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_MVSAS is not set
# CONFIG_SCSI_STEX is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
@@ -492,147 +514,81 @@ CONFIG_SCSI_AIC94XX=y
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_SRP is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
+# CONFIG_SCSI_DH is not set
# CONFIG_ATA is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
# CONFIG_FUSION is not set
-# CONFIG_FUSION_SPI is not set
-# CONFIG_FUSION_FC is not set
-# CONFIG_FUSION_SAS is not set
#
# IEEE 1394 (FireWire) support
#
-# CONFIG_IEEE1394 is not set
#
-# I2O device support
+# Enable only one of the two stacks, unless you know what you are doing
#
+# CONFIG_FIREWIRE is not set
+# CONFIG_IEEE1394 is not set
# CONFIG_I2O is not set
-
-#
-# Network device support
-#
CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+# CONFIG_MACVLAN is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
+# CONFIG_VETH is not set
# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
-CONFIG_PHYLIB=y
-
-#
-# MII PHY device drivers
-#
-CONFIG_MARVELL_PHY=y
-CONFIG_DAVICOM_PHY=y
-CONFIG_QSEMI_PHY=y
-CONFIG_LXT_PHY=y
-CONFIG_CICADA_PHY=y
-CONFIG_VITESSE_PHY=y
-CONFIG_SMSC_PHY=y
-# CONFIG_BROADCOM_PHY is not set
-# CONFIG_FIXED_PHY is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
+# CONFIG_PHYLIB is not set
CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
CONFIG_SGI_O2MACE_ETH=y
# CONFIG_HAPPYMEAL is not set
# CONFIG_SUNGEM is not set
# CONFIG_CASSINI is not set
# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_SMC91X is not set
# CONFIG_DM9000 is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
+CONFIG_NET_TULIP=y
+CONFIG_DE2104X=m
+CONFIG_TULIP=m
+# CONFIG_TULIP_MWI is not set
+CONFIG_TULIP_MMIO=y
+# CONFIG_TULIP_NAPI is not set
+# CONFIG_DE4X5 is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_DM9102 is not set
+# CONFIG_ULI526X is not set
# CONFIG_HP100 is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
# CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
-# CONFIG_SKGE is not set
-# CONFIG_SKY2 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-# CONFIG_BNX2 is not set
-CONFIG_QLA3XXX=y
-# CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_CHELSIO_T1 is not set
-CONFIG_CHELSIO_T3=y
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-# CONFIG_MYRI10GE is not set
-CONFIG_NETXEN_NIC=y
-
-#
-# Token Ring devices
-#
+# CONFIG_B44 is not set
+# CONFIG_ATL2 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
# CONFIG_TR is not set
#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
+# Wireless LAN
#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
# CONFIG_NET_FC is not set
-# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
-
-#
-# ISDN subsystem
-#
# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
# CONFIG_PHONE is not set
#
@@ -640,6 +596,7 @@ CONFIG_NETXEN_NIC=y
#
CONFIG_INPUT=y
# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
#
# Userland interfaces
@@ -649,16 +606,32 @@ CONFIG_INPUT_MOUSEDEV_PSAUX=y
CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
+CONFIG_INPUT_EVDEV=m
# CONFIG_INPUT_EVBUG is not set
#
# Input Device Drivers
#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_VSXXXAA is not set
# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
# CONFIG_INPUT_MISC is not set
@@ -669,8 +642,8 @@ CONFIG_SERIO=y
# CONFIG_SERIO_I8042 is not set
CONFIG_SERIO_SERPORT=y
# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_MACEPS2 is not set
-# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_MACEPS2=y
+CONFIG_SERIO_LIBPS2=y
CONFIG_SERIO_RAW=y
# CONFIG_GAMEPORT is not set
@@ -678,10 +651,13 @@ CONFIG_SERIO_RAW=y
# Character devices
#
CONFIG_VT=y
+# CONFIG_CONSOLE_TRANSLATIONS is not set
CONFIG_VT_CONSOLE=y
CONFIG_HW_CONSOLE=y
-CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
#
# Serial drivers
@@ -702,192 +678,304 @@ CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
-
-#
-# IPMI
-#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_HW_RANDOM is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
+CONFIG_HW_RANDOM=y
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
-# CONFIG_DRM is not set
# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_I5K_AMB is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
#
-# I2C support
+# Watchdog Device Drivers
#
-# CONFIG_I2C is not set
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_ALIM7101_WDT is not set
#
-# SPI support
+# PCI-based Watchdog Cards
#
-# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+CONFIG_SSB_POSSIBLE=y
#
-# Dallas's 1-wire bus
+# Sonics Silicon Backplane
#
-# CONFIG_W1 is not set
+# CONFIG_SSB is not set
#
-# Hardware Monitoring support
+# Multifunction device drivers
#
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
#
-# CONFIG_VIDEO_DEV is not set
#
-# Digital Video Broadcasting Devices
+# Multimedia core support
#
-# CONFIG_DVB is not set
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L2_COMMON=m
+CONFIG_VIDEO_ALLOW_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+# CONFIG_DVB_CORE is not set
+CONFIG_VIDEO_MEDIA=m
#
-# Graphics support
+# Multimedia drivers
#
-# CONFIG_FIRMWARE_EDID is not set
-# CONFIG_FB is not set
+# CONFIG_MEDIA_ATTACH is not set
+CONFIG_VIDEO_V4L2=m
+CONFIG_VIDEO_V4L1=m
+CONFIG_VIDEOBUF_GEN=m
+CONFIG_VIDEOBUF_VMALLOC=m
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+CONFIG_VIDEO_VIVI=m
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_STRADIS is not set
+# CONFIG_SOC_CAMERA is not set
+CONFIG_RADIO_ADAPTERS=y
+# CONFIG_RADIO_GEMTEK_PCI is not set
+# CONFIG_RADIO_MAXIRADIO is not set
+# CONFIG_RADIO_MAESTRO is not set
+CONFIG_DAB=y
#
-# Console display driver support
+# Graphics support
#
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=y
+CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_UVESA is not set
+CONFIG_FB_GBE=y
+CONFIG_FB_GBE_MEM=4
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_VIA is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
+# CONFIG_FB_CARMINE is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
-# Sound
+# Display device support
#
-# CONFIG_SOUND is not set
+# CONFIG_DISPLAY_SUPPORT is not set
#
-# HID Devices
+# Console display driver support
#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_7x14 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FONT_MINI_4x6 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+CONFIG_LOGO_SGI_CLUT224=y
+# CONFIG_SOUND is not set
+CONFIG_HID_SUPPORT=y
CONFIG_HID=y
# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+# CONFIG_HID_PID is not set
#
-# USB support
-#
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-CONFIG_USB_ARCH_HAS_EHCI=y
-# CONFIG_USB is not set
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
+# Special HID drivers
#
+CONFIG_HID_COMPAT=y
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_UWB is not set
# CONFIG_MMC is not set
-
-#
-# LED devices
-#
+# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
-
-#
-# LED drivers
-#
-
-#
-# LED Triggers
-#
-
-#
-# InfiniBand support
-#
+# CONFIG_ACCESSIBILITY is not set
# CONFIG_INFINIBAND is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+# CONFIG_RTC_HCTOSYS is not set
+# CONFIG_RTC_DEBUG is not set
#
-# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+# RTC interfaces
#
+# CONFIG_RTC_INTF_SYSFS is not set
+# CONFIG_RTC_INTF_PROC is not set
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
#
-# Real Time Clock
+# SPI RTC drivers
#
-# CONFIG_RTC_CLASS is not set
#
-# DMA Engine support
+# Platform RTC drivers
#
-# CONFIG_DMA_ENGINE is not set
+CONFIG_RTC_DRV_CMOS=y
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
#
-# DMA Clients
-#
-
-#
-# DMA Devices
-#
-
-#
-# Auxiliary Display support
-#
-
-#
-# Virtualization
+# on-CPU RTC drivers
#
+# CONFIG_DMADEVICES is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+CONFIG_STAGING_EXCLUDE_BUILD=y
#
# File systems
#
CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
# CONFIG_EXT2_FS_XIP is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_EXT4DEV_FS is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=y
# CONFIG_XFS_FS is not set
# CONFIG_GFS2_FS is not set
# CONFIG_OCFS2_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
+CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
-# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-CONFIG_FUSE_FS=y
+CONFIG_QUOTA=y
+# CONFIG_QUOTA_NETLINK_INTERFACE is not set
+CONFIG_PRINT_QUOTA_WARNING=y
+CONFIG_QFMT_V1=m
+CONFIG_QFMT_V2=m
+CONFIG_QUOTACTL=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
CONFIG_GENERIC_ACL=y
#
# CD-ROM/DVD Filesystems
#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
#
# DOS/FAT/NT Filesystems
#
-# CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
# CONFIG_NTFS_FS is not set
#
@@ -896,11 +984,11 @@ CONFIG_GENERIC_ACL=y
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
CONFIG_TMPFS_POSIX_ACL=y
# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
CONFIG_CONFIGFS_FS=y
#
@@ -916,33 +1004,42 @@ CONFIG_CONFIGFS_FS=y
# CONFIG_EFS_FS is not set
# CONFIG_CRAMFS is not set
# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
+CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
-# CONFIG_NFSD is not set
CONFIG_ROOT_NFS=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+# CONFIG_NFSD_V4 is not set
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_REGISTER_V4 is not set
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_WEAK_PW_HASH is not set
+# CONFIG_CIFS_UPCALL is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set
-# CONFIG_9P_FS is not set
#
# Partition Types
@@ -953,45 +1050,83 @@ CONFIG_PARTITION_ADVANCED=y
# CONFIG_AMIGA_PARTITION is not set
# CONFIG_ATARI_PARTITION is not set
# CONFIG_MAC_PARTITION is not set
-# CONFIG_MSDOS_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
# CONFIG_LDM_PARTITION is not set
CONFIG_SGI_PARTITION=y
# CONFIG_ULTRIX_PARTITION is not set
# CONFIG_SUN_PARTITION is not set
# CONFIG_KARMA_PARTITION is not set
# CONFIG_EFI_PARTITION is not set
-
-#
-# Native Language Support
-#
-# CONFIG_NLS is not set
-
-#
-# Distributed Lock Manager
-#
-CONFIG_DLM=y
-CONFIG_DLM_TCP=y
-# CONFIG_DLM_SCTP is not set
-# CONFIG_DLM_DEBUG is not set
-
-#
-# Profiling support
-#
-# CONFIG_PROFILING is not set
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+# CONFIG_DLM is not set
#
# Kernel hacking
#
CONFIG_TRACE_IRQFLAGS_SUPPORT=y
# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
CONFIG_ENABLE_MUST_CHECK=y
-# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_FRAME_WARN=2048
+CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
# CONFIG_DEBUG_FS is not set
# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_CROSSCOMPILE=y
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+
+#
+# Tracers
+#
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
CONFIG_CMDLINE=""
#
@@ -1000,51 +1135,99 @@ CONFIG_CMDLINE=""
CONFIG_KEYS=y
CONFIG_KEYS_DEBUG_PROC_KEYS=y
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
#
-# Cryptographic options
+# Crypto core or helper
#
-CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_AEAD=y
CONFIG_CRYPTO_BLKCIPHER=y
CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_RNG=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_GF128MUL=y
+CONFIG_CRYPTO_NULL=y
+# CONFIG_CRYPTO_CRYPTD is not set
+CONFIG_CRYPTO_AUTHENC=m
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_LRW=y
+CONFIG_CRYPTO_PCBC=y
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
CONFIG_CRYPTO_HMAC=y
CONFIG_CRYPTO_XCBC=y
-CONFIG_CRYPTO_NULL=y
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
CONFIG_CRYPTO_MD4=y
CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
CONFIG_CRYPTO_SHA1=y
CONFIG_CRYPTO_SHA256=y
CONFIG_CRYPTO_SHA512=y
-CONFIG_CRYPTO_WP512=y
CONFIG_CRYPTO_TGR192=y
-CONFIG_CRYPTO_GF128MUL=y
-CONFIG_CRYPTO_ECB=y
-CONFIG_CRYPTO_CBC=y
-CONFIG_CRYPTO_PCBC=y
-CONFIG_CRYPTO_LRW=y
-CONFIG_CRYPTO_DES=y
-CONFIG_CRYPTO_FCRYPT=y
-CONFIG_CRYPTO_BLOWFISH=y
-CONFIG_CRYPTO_TWOFISH=y
-CONFIG_CRYPTO_TWOFISH_COMMON=y
-CONFIG_CRYPTO_SERPENT=y
+CONFIG_CRYPTO_WP512=y
+
+#
+# Ciphers
+#
CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_ANUBIS=y
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_BLOWFISH=y
+CONFIG_CRYPTO_CAMELLIA=y
CONFIG_CRYPTO_CAST5=y
CONFIG_CRYPTO_CAST6=y
-CONFIG_CRYPTO_TEA=y
-CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_FCRYPT=y
CONFIG_CRYPTO_KHAZAD=y
-CONFIG_CRYPTO_ANUBIS=y
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+CONFIG_CRYPTO_SERPENT=y
+CONFIG_CRYPTO_TEA=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_TWOFISH_COMMON=y
+
+#
+# Compression
+#
CONFIG_CRYPTO_DEFLATE=y
-CONFIG_CRYPTO_MICHAEL_MIC=y
-CONFIG_CRYPTO_CRC32C=y
-CONFIG_CRYPTO_CAMELLIA=y
+# CONFIG_CRYPTO_LZO is not set
#
-# Hardware crypto devices
+# Random Number Generation
#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_HIFN_795X is not set
#
# Library routines
@@ -1052,10 +1235,15 @@ CONFIG_CRYPTO_CAMELLIA=y
CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
CONFIG_CRC16=y
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=m
CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
CONFIG_LIBCRC32C=y
+CONFIG_AUDIT_GENERIC=y
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
CONFIG_PLIST=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/mips/configs/malta_defconfig b/arch/mips/configs/malta_defconfig
index 74daa0cf87e..1ecdd3b65dc 100644
--- a/arch/mips/configs/malta_defconfig
+++ b/arch/mips/configs/malta_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.23-rc2
-# Tue Aug 7 12:59:29 2007
+# Linux kernel version: 2.6.28-rc6
+# Mon Dec 1 08:08:19 2008
#
CONFIG_MIPS=y
@@ -11,20 +11,25 @@ CONFIG_MIPS=y
CONFIG_ZONE_DMA=y
# CONFIG_MACH_ALCHEMY is not set
# CONFIG_BASLER_EXCITE is not set
+# CONFIG_BCM47XX is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
# CONFIG_LEMOTE_FULONG is not set
CONFIG_MIPS_MALTA=y
# CONFIG_MIPS_SIM is not set
-# CONFIG_MARKEINS is not set
+# CONFIG_MACH_EMMA is not set
# CONFIG_MACH_VR41XX is not set
+# CONFIG_NXP_STB220 is not set
+# CONFIG_NXP_STB225 is not set
# CONFIG_PNX8550_JBS is not set
# CONFIG_PNX8550_STB810 is not set
# CONFIG_PMC_MSP is not set
# CONFIG_PMC_YOSEMITE is not set
# CONFIG_SGI_IP22 is not set
# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP28 is not set
# CONFIG_SGI_IP32 is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CARMEL is not set
@@ -35,13 +40,14 @@ CONFIG_MIPS_MALTA=y
# CONFIG_SIBYTE_SENTOSA is not set
# CONFIG_SIBYTE_BIGSUR is not set
# CONFIG_SNI_RM is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_TOSHIBA_RBTX4938 is not set
+# CONFIG_MACH_TX39XX is not set
+# CONFIG_MACH_TX49XX is not set
+# CONFIG_MIKROTIK_RB532 is not set
# CONFIG_WR_PPMC is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
# CONFIG_ARCH_HAS_ILOG2_U32 is not set
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_ARCH_SUPPORTS_OPROFILE=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
@@ -51,21 +57,26 @@ CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_BOOT_RAW=y
CONFIG_CEVT_R4K=y
+CONFIG_CSRC_R4K=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
CONFIG_EARLY_PRINTK=y
CONFIG_SYS_HAS_EARLY_PRINTK=y
-CONFIG_GENERIC_ISA_DMA=y
+# CONFIG_HOTPLUG_CPU is not set
CONFIG_I8259=y
CONFIG_MIPS_BONITO64=y
CONFIG_MIPS_MSC=y
# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_ISA_DMA=y
# CONFIG_CPU_BIG_ENDIAN is not set
CONFIG_CPU_LITTLE_ENDIAN=y
CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
CONFIG_IRQ_CPU=y
+CONFIG_IRQ_GIC=y
+CONFIG_MIPS_BOARDS_GEN=y
CONFIG_PCI_GT64XXX_PCI0=y
CONFIG_SWAP_IO_SPACE=y
CONFIG_BOOT_ELF32=y
@@ -74,10 +85,6 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5
#
# CPU selection
#
-CONFIG_TICK_ONESHOT=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
# CONFIG_CPU_LOONGSON2 is not set
# CONFIG_CPU_MIPS32_R1 is not set
CONFIG_CPU_MIPS32_R2=y
@@ -91,6 +98,7 @@ CONFIG_CPU_MIPS32_R2=y
# CONFIG_CPU_TX49XX is not set
# CONFIG_CPU_R5000 is not set
# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R5500 is not set
# CONFIG_CPU_R6000 is not set
# CONFIG_CPU_NEVADA is not set
# CONFIG_CPU_R8000 is not set
@@ -108,6 +116,7 @@ CONFIG_CPU_MIPSR2=y
CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_HARDWARE_WATCHPOINTS=y
#
# Kernel type
@@ -125,6 +134,8 @@ CONFIG_CPU_HAS_PREFETCH=y
CONFIG_MIPS_MT_SMP=y
# CONFIG_MIPS_MT_SMTC is not set
CONFIG_MIPS_MT=y
+# CONFIG_SCHED_SMT is not set
+CONFIG_SYS_SUPPORTS_SCHED_SMT=y
CONFIG_SYS_SUPPORTS_MULTITHREADING=y
CONFIG_MIPS_MT_FPAFF=y
# CONFIG_MIPS_VPE_LOADER is not set
@@ -132,7 +143,6 @@ CONFIG_CPU_HAS_LLSC=y
# CONFIG_CPU_HAS_SMARTMIPS is not set
CONFIG_CPU_MIPSR2_IRQ_VI=y
CONFIG_CPU_MIPSR2_IRQ_EI=y
-CONFIG_CPU_MIPSR2_SRS=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
@@ -140,22 +150,30 @@ CONFIG_IRQ_PER_CPU=y
CONFIG_CPU_SUPPORTS_HIGHMEM=y
CONFIG_SYS_SUPPORTS_SMARTMIPS=y
CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
# CONFIG_DISCONTIGMEM_MANUAL is not set
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
CONFIG_SMP=y
+CONFIG_SMP_UP=y
CONFIG_SYS_SUPPORTS_SMP=y
CONFIG_NR_CPUS_DEFAULT_2=y
CONFIG_NR_CPUS=2
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
# CONFIG_HZ_48 is not set
CONFIG_HZ_100=y
# CONFIG_HZ_128 is not set
@@ -168,7 +186,6 @@ CONFIG_HZ=100
CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not set
-CONFIG_PREEMPT_BKL=y
# CONFIG_KEXEC is not set
CONFIG_SECCOMP=y
CONFIG_LOCKDEP_SUPPORT=y
@@ -189,13 +206,19 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
-# CONFIG_USER_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=15
-# CONFIG_CPUSETS is not set
+# CONFIG_CGROUPS is not set
+# CONFIG_GROUP_SCHED is not set
CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_RELAY=y
+CONFIG_NAMESPACES=y
+CONFIG_UTS_NS=y
+CONFIG_IPC_NS=y
+# CONFIG_USER_NS is not set
+CONFIG_PID_NS=y
# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
@@ -207,6 +230,8 @@ CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
+CONFIG_PCSPKR_PLATFORM=y
+# CONFIG_COMPAT_BRK is not set
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_ANON_INODES=y
@@ -215,14 +240,23 @@ CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+CONFIG_USE_GENERIC_SMP_HELPERS=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
CONFIG_MODVERSIONS=y
@@ -234,6 +268,7 @@ CONFIG_BLOCK=y
# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
#
# IO Schedulers
@@ -247,19 +282,19 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_CLASSIC_RCU=y
+# CONFIG_FREEZER is not set
#
# Bus options (PCI, PCMCIA, EISA, ISA, TC)
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
# CONFIG_ARCH_SUPPORTS_MSI is not set
+CONFIG_PCI_LEGACY=y
CONFIG_MMU=y
CONFIG_I8253=y
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
@@ -267,6 +302,8 @@ CONFIG_I8253=y
# Executable file formats
#
CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
CONFIG_TRAD_SIGNALS=y
@@ -274,12 +311,7 @@ CONFIG_TRAD_SIGNALS=y
# Power management options
#
CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
# CONFIG_PM_DEBUG is not set
-
-#
-# Networking
-#
CONFIG_NET=y
#
@@ -292,6 +324,8 @@ CONFIG_XFRM=y
CONFIG_XFRM_USER=m
# CONFIG_XFRM_SUB_POLICY is not set
CONFIG_XFRM_MIGRATE=y
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_XFRM_IPCOMP=m
CONFIG_NET_KEY=y
CONFIG_NET_KEY_MIGRATE=y
CONFIG_INET=y
@@ -323,42 +357,13 @@ CONFIG_INET_TUNNEL=m
CONFIG_INET_XFRM_MODE_TRANSPORT=m
CONFIG_INET_XFRM_MODE_TUNNEL=m
CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_LRO=m
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
CONFIG_TCP_MD5SIG=y
-CONFIG_IP_VS=m
-# CONFIG_IP_VS_DEBUG is not set
-CONFIG_IP_VS_TAB_BITS=12
-
-#
-# IPVS transport protocol load balancing support
-#
-CONFIG_IP_VS_PROTO_TCP=y
-CONFIG_IP_VS_PROTO_UDP=y
-CONFIG_IP_VS_PROTO_ESP=y
-CONFIG_IP_VS_PROTO_AH=y
-
-#
-# IPVS scheduler
-#
-CONFIG_IP_VS_RR=m
-CONFIG_IP_VS_WRR=m
-CONFIG_IP_VS_LC=m
-CONFIG_IP_VS_WLC=m
-CONFIG_IP_VS_LBLC=m
-CONFIG_IP_VS_LBLCR=m
-CONFIG_IP_VS_DH=m
-CONFIG_IP_VS_SH=m
-CONFIG_IP_VS_SED=m
-CONFIG_IP_VS_NQ=m
-
-#
-# IPVS application helper
-#
-CONFIG_IP_VS_FTP=m
CONFIG_IPV6=m
CONFIG_IPV6_PRIVACY=y
CONFIG_IPV6_ROUTER_PREF=y
@@ -375,11 +380,15 @@ CONFIG_INET6_XFRM_MODE_TUNNEL=m
CONFIG_INET6_XFRM_MODE_BEET=m
# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
CONFIG_IPV6_SIT=m
+CONFIG_IPV6_NDISC_NODETYPE=y
CONFIG_IPV6_TUNNEL=m
# CONFIG_IPV6_MULTIPLE_TABLES is not set
+CONFIG_IPV6_MROUTE=y
+CONFIG_IPV6_PIMSM_V2=y
CONFIG_NETWORK_SECMARK=y
CONFIG_NETFILTER=y
# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
CONFIG_BRIDGE_NETFILTER=y
#
@@ -388,12 +397,12 @@ CONFIG_BRIDGE_NETFILTER=y
CONFIG_NETFILTER_NETLINK=m
CONFIG_NETFILTER_NETLINK_QUEUE=m
CONFIG_NETFILTER_NETLINK_LOG=m
-CONFIG_NF_CONNTRACK_ENABLED=m
CONFIG_NF_CONNTRACK=m
CONFIG_NF_CT_ACCT=y
CONFIG_NF_CONNTRACK_MARK=y
CONFIG_NF_CONNTRACK_SECMARK=y
CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=m
CONFIG_NF_CT_PROTO_GRE=m
CONFIG_NF_CT_PROTO_SCTP=m
CONFIG_NF_CT_PROTO_UDPLITE=m
@@ -407,18 +416,22 @@ CONFIG_NF_CONNTRACK_SANE=m
CONFIG_NF_CONNTRACK_SIP=m
CONFIG_NF_CONNTRACK_TFTP=m
CONFIG_NF_CT_NETLINK=m
+CONFIG_NETFILTER_TPROXY=m
CONFIG_NETFILTER_XTABLES=m
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+# CONFIG_NETFILTER_XT_TARGET_CONNSECMARK is not set
# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
CONFIG_NETFILTER_XT_TARGET_MARK=m
-CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_RATEEST=m
+CONFIG_NETFILTER_XT_TARGET_TPROXY=m
CONFIG_NETFILTER_XT_TARGET_TRACE=m
CONFIG_NETFILTER_XT_TARGET_SECMARK=m
-# CONFIG_NETFILTER_XT_TARGET_CONNSECMARK is not set
CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
@@ -427,40 +440,76 @@ CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
CONFIG_NETFILTER_XT_MATCH_DCCP=m
# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
CONFIG_NETFILTER_XT_MATCH_MAC=m
CONFIG_NETFILTER_XT_MATCH_MARK=m
-CONFIG_NETFILTER_XT_MATCH_POLICY=m
CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_OWNER=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_RATEEST=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_RECENT=m
+# CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT is not set
CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_SOCKET=m
CONFIG_NETFILTER_XT_MATCH_STATE=m
CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
CONFIG_NETFILTER_XT_MATCH_STRING=m
CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_TIME=m
CONFIG_NETFILTER_XT_MATCH_U32=m
-CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+CONFIG_IP_VS=m
+CONFIG_IP_VS_IPV6=y
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_AH_ESP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
#
# IP: Netfilter Configuration
#
+CONFIG_NF_DEFRAG_IPV4=m
CONFIG_NF_CONNTRACK_IPV4=m
CONFIG_NF_CONNTRACK_PROC_COMPAT=y
CONFIG_IP_NF_QUEUE=m
CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_TOS=m
-CONFIG_IP_NF_MATCH_RECENT=m
-CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_OWNER=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IP_NF_TARGET_LOG=m
@@ -468,11 +517,13 @@ CONFIG_IP_NF_TARGET_ULOG=m
CONFIG_NF_NAT=m
CONFIG_NF_NAT_NEEDED=y
CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
CONFIG_IP_NF_TARGET_NETMAP=m
-CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
CONFIG_NF_NAT_SNMP_BASIC=m
+CONFIG_NF_NAT_PROTO_DCCP=m
CONFIG_NF_NAT_PROTO_GRE=m
+CONFIG_NF_NAT_PROTO_UDPLITE=m
+CONFIG_NF_NAT_PROTO_SCTP=m
CONFIG_NF_NAT_FTP=m
CONFIG_NF_NAT_IRC=m
CONFIG_NF_NAT_TFTP=m
@@ -481,40 +532,34 @@ CONFIG_NF_NAT_PPTP=m
CONFIG_NF_NAT_H323=m
CONFIG_NF_NAT_SIP=m
CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
CONFIG_IP_NF_TARGET_ECN=m
CONFIG_IP_NF_TARGET_TTL=m
-CONFIG_IP_NF_TARGET_CLUSTERIP=m
CONFIG_IP_NF_RAW=m
CONFIG_IP_NF_ARPTABLES=m
CONFIG_IP_NF_ARPFILTER=m
CONFIG_IP_NF_ARP_MANGLE=m
#
-# IPv6: Netfilter Configuration (EXPERIMENTAL)
+# IPv6: Netfilter Configuration
#
CONFIG_NF_CONNTRACK_IPV6=m
CONFIG_IP6_NF_QUEUE=m
CONFIG_IP6_NF_IPTABLES=m
-CONFIG_IP6_NF_MATCH_RT=m
-CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
CONFIG_IP6_NF_MATCH_HL=m
-CONFIG_IP6_NF_MATCH_OWNER=m
CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-CONFIG_IP6_NF_MATCH_AH=m
CONFIG_IP6_NF_MATCH_MH=m
-CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_MATCH_RT=m
CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_FILTER=m
CONFIG_IP6_NF_TARGET_REJECT=m
CONFIG_IP6_NF_MANGLE=m
CONFIG_IP6_NF_TARGET_HL=m
CONFIG_IP6_NF_RAW=m
-
-#
-# Bridge: Netfilter Configuration
-#
CONFIG_BRIDGE_NF_EBTABLES=m
CONFIG_BRIDGE_EBT_BROUTE=m
CONFIG_BRIDGE_EBT_T_FILTER=m
@@ -523,6 +568,7 @@ CONFIG_BRIDGE_EBT_802_3=m
CONFIG_BRIDGE_EBT_AMONG=m
CONFIG_BRIDGE_EBT_ARP=m
CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_IP6=m
CONFIG_BRIDGE_EBT_LIMIT=m
CONFIG_BRIDGE_EBT_MARK=m
CONFIG_BRIDGE_EBT_PKTTYPE=m
@@ -535,6 +581,7 @@ CONFIG_BRIDGE_EBT_REDIRECT=m
CONFIG_BRIDGE_EBT_SNAT=m
CONFIG_BRIDGE_EBT_LOG=m
CONFIG_BRIDGE_EBT_ULOG=m
+CONFIG_BRIDGE_EBT_NFLOG=m
# CONFIG_IP_DCCP is not set
CONFIG_IP_SCTP=m
# CONFIG_SCTP_DBG_MSG is not set
@@ -544,8 +591,12 @@ CONFIG_IP_SCTP=m
CONFIG_SCTP_HMAC_MD5=y
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
+CONFIG_STP=m
+CONFIG_GARP=m
CONFIG_BRIDGE=m
+# CONFIG_NET_DSA is not set
CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
# CONFIG_DECNET is not set
CONFIG_LLC=m
# CONFIG_LLC2 is not set
@@ -559,12 +610,7 @@ CONFIG_IPDDP_DECAP=y
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
CONFIG_NET_SCHED=y
-CONFIG_NET_SCH_FIFO=y
#
# Queueing/Scheduling
@@ -573,7 +619,7 @@ CONFIG_NET_SCH_CBQ=m
CONFIG_NET_SCH_HTB=m
CONFIG_NET_SCH_HFSC=m
CONFIG_NET_SCH_PRIO=m
-CONFIG_NET_SCH_RR=m
+# CONFIG_NET_SCH_MULTIQ is not set
CONFIG_NET_SCH_RED=m
CONFIG_NET_SCH_SFQ=m
CONFIG_NET_SCH_TEQL=m
@@ -597,6 +643,7 @@ CONFIG_NET_CLS_U32=m
# CONFIG_CLS_U32_MARK is not set
CONFIG_NET_CLS_RSVP=m
CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_FLOW=m
# CONFIG_NET_EMATCH is not set
CONFIG_NET_CLS_ACT=y
CONFIG_NET_ACT_POLICE=y
@@ -604,37 +651,51 @@ CONFIG_NET_ACT_GACT=m
CONFIG_GACT_PROB=y
CONFIG_NET_ACT_MIRRED=m
CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_NAT=m
CONFIG_NET_ACT_PEDIT=m
CONFIG_NET_ACT_SIMP=m
-CONFIG_NET_CLS_POLICE=y
+CONFIG_NET_ACT_SKBEDIT=m
CONFIG_NET_CLS_IND=y
+CONFIG_NET_SCH_FIFO=y
#
# Network testing
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
+CONFIG_PHONET=m
CONFIG_FIB_RULES=y
-
-#
-# Wireless
-#
+CONFIG_WIRELESS=y
CONFIG_CFG80211=m
+CONFIG_NL80211=y
+CONFIG_WIRELESS_OLD_REGULATORY=y
CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
CONFIG_MAC80211=m
-# CONFIG_MAC80211_DEBUG is not set
+
+#
+# Rate control algorithm selection
+#
+CONFIG_MAC80211_RC_PID=y
+CONFIG_MAC80211_RC_MINSTREL=y
+CONFIG_MAC80211_RC_DEFAULT_PID=y
+# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT="pid"
+CONFIG_MAC80211_MESH=y
+CONFIG_MAC80211_LEDS=y
+# CONFIG_MAC80211_DEBUG_MENU is not set
CONFIG_IEEE80211=m
# CONFIG_IEEE80211_DEBUG is not set
CONFIG_IEEE80211_CRYPT_WEP=m
CONFIG_IEEE80211_CRYPT_CCMP=m
CONFIG_IEEE80211_CRYPT_TKIP=m
-CONFIG_IEEE80211_SOFTMAC=m
-# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
CONFIG_RFKILL=m
CONFIG_RFKILL_INPUT=m
+CONFIG_RFKILL_LEDS=y
# CONFIG_NET_9P is not set
#
@@ -644,9 +705,12 @@ CONFIG_RFKILL_INPUT=m
#
# Generic Driver Options
#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
# CONFIG_SYS_HYPERVISOR is not set
CONFIG_CONNECTOR=m
CONFIG_MTD=y
@@ -655,6 +719,7 @@ CONFIG_MTD=y
CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_REDBOOT_PARTS is not set
# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
#
# User Modules And Translation Layers
@@ -667,6 +732,7 @@ CONFIG_MTD_BLOCK=y
# CONFIG_INFTL is not set
# CONFIG_RFD_FTL is not set
# CONFIG_SSFDC is not set
+CONFIG_MTD_OOPS=m
#
# RAM/ROM/Flash chip drivers
@@ -701,6 +767,7 @@ CONFIG_MTD_PHYSMAP=y
CONFIG_MTD_PHYSMAP_START=0x0
CONFIG_MTD_PHYSMAP_LEN=0x0
CONFIG_MTD_PHYSMAP_BANKWIDTH=0
+# CONFIG_MTD_INTEL_VR_NOR is not set
# CONFIG_MTD_PLATRAM is not set
#
@@ -748,25 +815,26 @@ CONFIG_BLK_DEV_NBD=m
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_BLK_DEV_XIP is not set
CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
CONFIG_ATA_OVER_ETH=m
+# CONFIG_BLK_DEV_HD is not set
# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
CONFIG_IDE=y
-CONFIG_IDE_MAX_HWIFS=4
-CONFIG_BLK_DEV_IDE=y
#
-# Please see Documentation/ide.txt for help/info on IDE drives
+# Please see Documentation/ide/ide.txt for help/info on IDE drives
#
# CONFIG_BLK_DEV_IDE_SATA is not set
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_IDE_GD=y
+CONFIG_IDE_GD_ATA=y
+# CONFIG_IDE_GD_ATAPI is not set
CONFIG_BLK_DEV_IDECD=y
+CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y
# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
# CONFIG_BLK_DEV_IDESCSI is not set
# CONFIG_IDE_TASK_IOCTL is not set
CONFIG_IDE_PROC_FS=y
@@ -775,24 +843,25 @@ CONFIG_IDE_PROC_FS=y
# IDE chipset support/bugfixes
#
CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_PLATFORM is not set
+CONFIG_BLK_DEV_IDEDMA_SFF=y
+
+#
+# PCI IDE chipsets support
+#
CONFIG_BLK_DEV_IDEPCI=y
-# CONFIG_IDEPCI_SHARE_IRQ is not set
CONFIG_IDEPCI_PCIBUS_ORDER=y
# CONFIG_BLK_DEV_OFFBOARD is not set
CONFIG_BLK_DEV_GENERIC=y
# CONFIG_BLK_DEV_OPTI621 is not set
CONFIG_BLK_DEV_IDEDMA_PCI=y
-# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-# CONFIG_IDEDMA_ONLYDISK is not set
# CONFIG_BLK_DEV_AEC62XX is not set
# CONFIG_BLK_DEV_ALI15X3 is not set
# CONFIG_BLK_DEV_AMD74XX is not set
# CONFIG_BLK_DEV_CMD64X is not set
# CONFIG_BLK_DEV_TRIFLEX is not set
-# CONFIG_BLK_DEV_CY82C693 is not set
# CONFIG_BLK_DEV_CS5520 is not set
# CONFIG_BLK_DEV_CS5530 is not set
-# CONFIG_BLK_DEV_HPT34X is not set
# CONFIG_BLK_DEV_HPT366 is not set
# CONFIG_BLK_DEV_JMICRON is not set
# CONFIG_BLK_DEV_SC1200 is not set
@@ -808,10 +877,7 @@ CONFIG_BLK_DEV_IT8213=m
# CONFIG_BLK_DEV_TRM290 is not set
# CONFIG_BLK_DEV_VIA82CXXX is not set
CONFIG_BLK_DEV_TC86C001=m
-# CONFIG_IDE_ARM is not set
CONFIG_BLK_DEV_IDEDMA=y
-# CONFIG_IDEDMA_IVB is not set
-# CONFIG_BLK_DEV_HD is not set
#
# SCSI device support
@@ -848,8 +914,10 @@ CONFIG_SCSI_WAIT_SCAN=m
#
CONFIG_SCSI_SPI_ATTRS=m
CONFIG_SCSI_FC_ATTRS=m
+# CONFIG_SCSI_FC_TGT_ATTRS is not set
CONFIG_SCSI_ISCSI_ATTRS=m
# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
CONFIG_ISCSI_TCP=m
CONFIG_BLK_DEV_3W_XXXX_RAID=m
@@ -866,6 +934,7 @@ CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
# CONFIG_SCSI_AIC79XX is not set
# CONFIG_SCSI_AIC94XX is not set
# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ADVANSYS is not set
# CONFIG_SCSI_ARCMSR is not set
# CONFIG_MEGARAID_NEWGEN is not set
# CONFIG_MEGARAID_LEGACY is not set
@@ -876,6 +945,7 @@ CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
# CONFIG_SCSI_IPS is not set
# CONFIG_SCSI_INITIO is not set
# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_MVSAS is not set
# CONFIG_SCSI_STEX is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
@@ -887,6 +957,7 @@ CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
# CONFIG_SCSI_NSP32 is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_SRP is not set
+# CONFIG_SCSI_DH is not set
# CONFIG_ATA is not set
CONFIG_MD=y
CONFIG_BLK_DEV_MD=m
@@ -905,32 +976,28 @@ CONFIG_DM_SNAPSHOT=m
CONFIG_DM_MIRROR=m
CONFIG_DM_ZERO=m
CONFIG_DM_MULTIPATH=m
-CONFIG_DM_MULTIPATH_EMC=m
-CONFIG_DM_MULTIPATH_RDAC=m
# CONFIG_DM_DELAY is not set
+# CONFIG_DM_UEVENT is not set
+# CONFIG_FUSION is not set
#
-# Fusion MPT device support
+# IEEE 1394 (FireWire) support
#
-# CONFIG_FUSION is not set
-# CONFIG_FUSION_SPI is not set
-# CONFIG_FUSION_FC is not set
-# CONFIG_FUSION_SAS is not set
#
-# IEEE 1394 (FireWire) support
+# Enable only one of the two stacks, unless you know what you are doing
#
# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
# CONFIG_I2O is not set
CONFIG_NETDEVICES=y
-CONFIG_NETDEVICES_MULTIQUEUE=y
CONFIG_IFB=m
CONFIG_DUMMY=m
CONFIG_BONDING=m
CONFIG_MACVLAN=m
CONFIG_EQUALIZER=m
CONFIG_TUN=m
+CONFIG_VETH=m
# CONFIG_ARCNET is not set
CONFIG_PHYLIB=m
@@ -946,26 +1013,34 @@ CONFIG_VITESSE_PHY=m
CONFIG_SMSC_PHY=m
CONFIG_BROADCOM_PHY=m
CONFIG_ICPLUS_PHY=m
-# CONFIG_FIXED_PHY is not set
+CONFIG_REALTEK_PHY=m
+CONFIG_MDIO_BITBANG=m
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
CONFIG_AX88796=m
+# CONFIG_AX88796_93CX6 is not set
# CONFIG_HAPPYMEAL is not set
# CONFIG_SUNGEM is not set
# CONFIG_CASSINI is not set
# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_SMC91X is not set
# CONFIG_DM9000 is not set
# CONFIG_NET_TULIP is not set
# CONFIG_HP100 is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
CONFIG_NET_PCI=y
CONFIG_PCNET32=y
-# CONFIG_PCNET32_NAPI is not set
# CONFIG_AMD8111_ETH is not set
# CONFIG_ADAPTEC_STARFIRE is not set
# CONFIG_B44 is not set
# CONFIG_FORCEDETH is not set
CONFIG_TC35815=m
-# CONFIG_DGRS is not set
# CONFIG_EEPRO100 is not set
# CONFIG_E100 is not set
# CONFIG_FEALNX is not set
@@ -973,16 +1048,21 @@ CONFIG_TC35815=m
# CONFIG_NE2K_PCI is not set
# CONFIG_8139CP is not set
# CONFIG_8139TOO is not set
+# CONFIG_R6040 is not set
# CONFIG_SIS900 is not set
# CONFIG_EPIC100 is not set
# CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
# CONFIG_SC92031 is not set
+# CONFIG_ATL2 is not set
CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
# CONFIG_E1000 is not set
+# CONFIG_E1000E is not set
+# CONFIG_IP1000 is not set
+# CONFIG_IGB is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
@@ -995,14 +1075,24 @@ CONFIG_NETDEV_1000=y
# CONFIG_BNX2 is not set
# CONFIG_QLA3XXX is not set
# CONFIG_ATL1 is not set
+# CONFIG_ATL1E is not set
+# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
CONFIG_CHELSIO_T3=m
+# CONFIG_ENIC is not set
+# CONFIG_IXGBE is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
CONFIG_NETXEN_NIC=m
+# CONFIG_NIU is not set
+# CONFIG_MLX4_EN is not set
# CONFIG_MLX4_CORE is not set
+# CONFIG_TEHUTI is not set
+# CONFIG_BNX2X is not set
+# CONFIG_QLGE is not set
+# CONFIG_SFC is not set
# CONFIG_TR is not set
#
@@ -1022,6 +1112,7 @@ CONFIG_IPW2200_QOS=y
# CONFIG_IPW2200_DEBUG is not set
CONFIG_LIBERTAS=m
# CONFIG_LIBERTAS_DEBUG is not set
+# CONFIG_LIBERTAS_THINFIRM is not set
CONFIG_HERMES=m
CONFIG_PLX_HERMES=m
CONFIG_TMD_HERMES=m
@@ -1030,25 +1121,30 @@ CONFIG_PCI_HERMES=m
CONFIG_ATMEL=m
CONFIG_PCI_ATMEL=m
CONFIG_PRISM54=m
+# CONFIG_RTL8180 is not set
+# CONFIG_ADM8211 is not set
+# CONFIG_MAC80211_HWSIM is not set
+# CONFIG_P54_COMMON is not set
+# CONFIG_ATH5K is not set
+# CONFIG_ATH9K is not set
+# CONFIG_IWLCORE is not set
+# CONFIG_IWLWIFI_LEDS is not set
+# CONFIG_IWLAGN is not set
+# CONFIG_IWL3945 is not set
CONFIG_HOSTAP=m
CONFIG_HOSTAP_FIRMWARE=y
CONFIG_HOSTAP_FIRMWARE_NVRAM=y
CONFIG_HOSTAP_PLX=m
CONFIG_HOSTAP_PCI=m
-CONFIG_BCM43XX=m
-CONFIG_BCM43XX_DEBUG=y
-CONFIG_BCM43XX_DMA=y
-CONFIG_BCM43XX_PIO=y
-CONFIG_BCM43XX_DMA_AND_PIO_MODE=y
-# CONFIG_BCM43XX_DMA_MODE is not set
-# CONFIG_BCM43XX_PIO_MODE is not set
+# CONFIG_B43 is not set
+# CONFIG_B43LEGACY is not set
+# CONFIG_RT2X00 is not set
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
# CONFIG_NET_FC is not set
-# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
@@ -1070,7 +1166,6 @@ CONFIG_INPUT_MOUSEDEV_PSAUX=y
CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
# CONFIG_INPUT_EVDEV is not set
# CONFIG_INPUT_EVBUG is not set
@@ -1099,10 +1194,13 @@ CONFIG_SERIO_SERPORT=y
# Character devices
#
CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
CONFIG_VT_CONSOLE=y
CONFIG_HW_CONSOLE=y
CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_DEVKMEM=y
# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
#
# Serial drivers
@@ -1124,101 +1222,165 @@ CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
-# CONFIG_WATCHDOG is not set
CONFIG_HW_RANDOM=m
-CONFIG_RTC=y
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
-# CONFIG_DRM is not set
# CONFIG_RAW_DRIVER is not set
# CONFIG_TCG_TPM is not set
CONFIG_DEVPORT=y
# CONFIG_I2C is not set
-
-#
-# SPI support
-#
# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
#
# Multifunction device drivers
#
+# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
#
+
+#
+# Multimedia core support
+#
# CONFIG_VIDEO_DEV is not set
# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
# CONFIG_DAB is not set
#
# Graphics support
#
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Display device support
#
# CONFIG_DISPLAY_SUPPORT is not set
-# CONFIG_VGASTATE is not set
-# CONFIG_VIDEO_OUTPUT_CONTROL is not set
-# CONFIG_FB is not set
#
# Console display driver support
#
# CONFIG_VGA_CONSOLE is not set
CONFIG_DUMMY_CONSOLE=y
-
-#
-# Sound
-#
# CONFIG_SOUND is not set
CONFIG_HID_SUPPORT=y
CONFIG_HID=m
# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+# CONFIG_HID_PID is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# Enable Host or Gadget support to see Inventra options
#
#
-# USB Gadget Support
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
# CONFIG_USB_GADGET is not set
+# CONFIG_UWB is not set
# CONFIG_MMC is not set
-# CONFIG_NEW_LEDS is not set
+# CONFIG_MEMSTICK is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=m
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=m
+CONFIG_LEDS_TRIGGER_BACKLIGHT=m
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
+# CONFIG_ACCESSIBILITY is not set
# CONFIG_INFINIBAND is not set
-# CONFIG_RTC_CLASS is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
#
-# DMA Engine support
+# RTC interfaces
#
-# CONFIG_DMA_ENGINE is not set
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
#
-# DMA Clients
+# SPI RTC drivers
#
#
-# DMA Devices
+# Platform RTC drivers
#
+CONFIG_RTC_DRV_CMOS=y
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
#
-# Userspace I/O
+# on-CPU RTC drivers
#
+# CONFIG_DMADEVICES is not set
CONFIG_UIO=m
CONFIG_UIO_CIF=m
+# CONFIG_UIO_PDRV is not set
+# CONFIG_UIO_PDRV_GENIRQ is not set
+# CONFIG_UIO_SMX is not set
+# CONFIG_UIO_SERCOS3 is not set
+# CONFIG_STAGING is not set
+CONFIG_STAGING_EXCLUDE_BUILD=y
#
# File systems
@@ -1230,9 +1392,8 @@ CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
CONFIG_JBD=y
-# CONFIG_JBD_DEBUG is not set
CONFIG_FS_MBCACHE=y
CONFIG_REISERFS_FS=m
# CONFIG_REISERFS_CHECK is not set
@@ -1246,22 +1407,22 @@ CONFIG_JFS_SECURITY=y
# CONFIG_JFS_DEBUG is not set
# CONFIG_JFS_STATISTICS is not set
CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=y
CONFIG_XFS_FS=m
CONFIG_XFS_QUOTA=y
-CONFIG_XFS_SECURITY=y
CONFIG_XFS_POSIX_ACL=y
# CONFIG_XFS_RT is not set
-# CONFIG_GFS2_FS is not set
+# CONFIG_XFS_DEBUG is not set
# CONFIG_OCFS2_FS is not set
-CONFIG_MINIX_FS=m
-CONFIG_ROMFS_FS=m
+CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
CONFIG_QUOTA=y
+# CONFIG_QUOTA_NETLINK_INTERFACE is not set
+CONFIG_PRINT_QUOTA_WARNING=y
# CONFIG_QFMT_V1 is not set
CONFIG_QFMT_V2=y
CONFIG_QUOTACTL=y
-CONFIG_DNOTIFY=y
CONFIG_AUTOFS_FS=y
# CONFIG_AUTOFS4_FS is not set
CONFIG_FUSE_FS=m
@@ -1291,11 +1452,11 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
#
@@ -1312,46 +1473,48 @@ CONFIG_EFS_FS=m
CONFIG_JFFS2_FS=m
CONFIG_JFFS2_FS_DEBUG=0
CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
# CONFIG_JFFS2_SUMMARY is not set
CONFIG_JFFS2_FS_XATTR=y
CONFIG_JFFS2_FS_POSIX_ACL=y
CONFIG_JFFS2_FS_SECURITY=y
CONFIG_JFFS2_COMPRESSION_OPTIONS=y
CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
CONFIG_JFFS2_RTIME=y
CONFIG_JFFS2_RUBIN=y
# CONFIG_JFFS2_CMODE_NONE is not set
CONFIG_JFFS2_CMODE_PRIORITY=y
# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
+# CONFIG_UBIFS_FS is not set
CONFIG_CRAMFS=m
CONFIG_VXFS_FS=m
+CONFIG_MINIX_FS=m
+# CONFIG_OMFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
+CONFIG_ROMFS_FS=m
CONFIG_SYSV_FS=m
CONFIG_UFS_FS=m
# CONFIG_UFS_FS_WRITE is not set
# CONFIG_UFS_DEBUG is not set
-
-#
-# Network File Systems
-#
+CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
+CONFIG_ROOT_NFS=y
CONFIG_NFSD=y
CONFIG_NFSD_V3=y
# CONFIG_NFSD_V3_ACL is not set
# CONFIG_NFSD_V4 is not set
-# CONFIG_NFSD_TCP is not set
-CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
CONFIG_EXPORTFS=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_SUNRPC_REGISTER_V4 is not set
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -1365,10 +1528,6 @@ CONFIG_SUNRPC=y
#
# CONFIG_PARTITION_ADVANCED is not set
CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
CONFIG_NLS=m
CONFIG_NLS_DEFAULT="iso8859-1"
CONFIG_NLS_CODEPAGE_437=m
@@ -1409,29 +1568,30 @@ CONFIG_NLS_ISO8859_15=m
CONFIG_NLS_KOI8_R=m
CONFIG_NLS_KOI8_U=m
CONFIG_NLS_UTF8=m
-
-#
-# Distributed Lock Manager
-#
# CONFIG_DLM is not set
#
-# Profiling support
-#
-# CONFIG_PROFILING is not set
-
-#
# Kernel hacking
#
CONFIG_TRACE_IRQFLAGS_SUPPORT=y
# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
# CONFIG_DEBUG_FS is not set
# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
-CONFIG_CROSSCOMPILE=y
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+
+#
+# Tracers
+#
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
CONFIG_CMDLINE=""
#
@@ -1439,51 +1599,103 @@ CONFIG_CMDLINE=""
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_XOR_BLOCKS=m
CONFIG_ASYNC_CORE=m
CONFIG_ASYNC_MEMCPY=m
CONFIG_ASYNC_XOR=m
CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_ABLKCIPHER=m
-CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_BLKCIPHER=y
CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_RNG=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_CRYPTD=m
+CONFIG_CRYPTO_AUTHENC=m
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=m
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
CONFIG_CRYPTO_HMAC=y
CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_NULL=m
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=m
CONFIG_CRYPTO_MD4=m
CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
CONFIG_CRYPTO_SHA1=m
CONFIG_CRYPTO_SHA256=m
CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_GF128MUL=m
-CONFIG_CRYPTO_ECB=m
-CONFIG_CRYPTO_CBC=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_LRW=m
-CONFIG_CRYPTO_CRYPTD=m
-CONFIG_CRYPTO_DES=m
-CONFIG_CRYPTO_FCRYPT=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_TWOFISH_COMMON=m
-CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_WP512=m
+
+#
+# Ciphers
+#
CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAMELLIA=m
CONFIG_CRYPTO_CAST5=m
CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_FCRYPT=m
CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_ANUBIS=m
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+
+#
+# Compression
+#
CONFIG_CRYPTO_DEFLATE=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_CRC32C=m
-CONFIG_CRYPTO_CAMELLIA=m
-# CONFIG_CRYPTO_TEST is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_HIFN_795X is not set
#
# Library routines
@@ -1491,7 +1703,8 @@ CONFIG_CRYPTO_HW=y
CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
CONFIG_CRC16=m
-# CONFIG_CRC_ITU_T is not set
+# CONFIG_CRC_T10DIF is not set
+CONFIG_CRC_ITU_T=m
CONFIG_CRC32=y
# CONFIG_CRC7 is not set
CONFIG_LIBCRC32C=m
diff --git a/arch/mips/include/asm/asmmacro.h b/arch/mips/include/asm/asmmacro.h
index 7a881755800..6c8342ae74d 100644
--- a/arch/mips/include/asm/asmmacro.h
+++ b/arch/mips/include/asm/asmmacro.h
@@ -35,6 +35,16 @@
mtc0 \reg, CP0_TCSTATUS
_ehb
.endm
+#elif defined(CONFIG_CPU_MIPSR2)
+ .macro local_irq_enable reg=t0
+ ei
+ irq_enable_hazard
+ .endm
+
+ .macro local_irq_disable reg=t0
+ di
+ irq_disable_hazard
+ .endm
#else
.macro local_irq_enable reg=t0
mfc0 \reg, CP0_STATUS
diff --git a/arch/mips/include/asm/bug.h b/arch/mips/include/asm/bug.h
index 7eb63de808b..08ea46863fe 100644
--- a/arch/mips/include/asm/bug.h
+++ b/arch/mips/include/asm/bug.h
@@ -7,20 +7,31 @@
#include <asm/break.h>
-#define BUG() \
-do { \
- __asm__ __volatile__("break %0" : : "i" (BRK_BUG)); \
-} while (0)
+static inline void __noreturn BUG(void)
+{
+ __asm__ __volatile__("break %0" : : "i" (BRK_BUG));
+ /* Fool GCC into thinking the function doesn't return. */
+ while (1)
+ ;
+}
#define HAVE_ARCH_BUG
#if (_MIPS_ISA > _MIPS_ISA_MIPS1)
-#define BUG_ON(condition) \
-do { \
- __asm__ __volatile__("tne $0, %0, %1" \
- : : "r" (condition), "i" (BRK_BUG)); \
-} while (0)
+static inline void __BUG_ON(unsigned long condition)
+{
+ if (__builtin_constant_p(condition)) {
+ if (condition)
+ BUG();
+ else
+ return;
+ }
+ __asm__ __volatile__("tne $0, %0, %1"
+ : : "r" (condition), "i" (BRK_BUG));
+}
+
+#define BUG_ON(C) __BUG_ON((unsigned long)(C))
#define HAVE_ARCH_BUG_ON
diff --git a/arch/mips/include/asm/byteorder.h b/arch/mips/include/asm/byteorder.h
index 2988d29a086..33790b9e0cc 100644
--- a/arch/mips/include/asm/byteorder.h
+++ b/arch/mips/include/asm/byteorder.h
@@ -50,9 +50,8 @@ static inline __attribute_const__ __u32 __arch_swab32(__u32 x)
static inline __attribute_const__ __u64 __arch_swab64(__u64 x)
{
__asm__(
- " dsbh %0, %1 \n"
- " dshd %0, %0 \n"
- " drotr %0, %0, 32 \n"
+ " dsbh %0, %1\n"
+ " dshd %0, %0"
: "=r" (x)
: "r" (x));
diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h
index a8eac1697b3..d58f128aa74 100644
--- a/arch/mips/include/asm/elf.h
+++ b/arch/mips/include/asm/elf.h
@@ -232,7 +232,7 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
*/
#ifdef __MIPSEB__
#define ELF_DATA ELFDATA2MSB
-#elif __MIPSEL__
+#elif defined(__MIPSEL__)
#define ELF_DATA ELFDATA2LSB
#endif
#define ELF_ARCH EM_MIPS
diff --git a/arch/mips/include/asm/mach-rc32434/gpio.h b/arch/mips/include/asm/mach-rc32434/gpio.h
index c8e554eafce..b5cf6457305 100644
--- a/arch/mips/include/asm/mach-rc32434/gpio.h
+++ b/arch/mips/include/asm/mach-rc32434/gpio.h
@@ -84,5 +84,7 @@ extern void set_434_reg(unsigned reg_offs, unsigned bit, unsigned len, unsigned
extern unsigned get_434_reg(unsigned reg_offs);
extern void set_latch_u5(unsigned char or_mask, unsigned char nand_mask);
extern unsigned char get_latch_u5(void);
+extern void rb532_gpio_set_ilevel(int bit, unsigned gpio);
+extern void rb532_gpio_set_istat(int bit, unsigned gpio);
#endif /* _RC32434_GPIO_H_ */
diff --git a/arch/mips/include/asm/mach-rc32434/rb.h b/arch/mips/include/asm/mach-rc32434/rb.h
index 79e8ef67d0d..f25a8491670 100644
--- a/arch/mips/include/asm/mach-rc32434/rb.h
+++ b/arch/mips/include/asm/mach-rc32434/rb.h
@@ -40,12 +40,14 @@
#define BTCS 0x010040
#define BTCOMPARE 0x010044
#define GPIOBASE 0x050000
-#define GPIOCFG 0x050004
-#define GPIOD 0x050008
-#define GPIOILEVEL 0x05000C
-#define GPIOISTAT 0x050010
-#define GPIONMIEN 0x050014
-#define IMASK6 0x038038
+/* Offsets relative to GPIOBASE */
+#define GPIOFUNC 0x00
+#define GPIOCFG 0x04
+#define GPIOD 0x08
+#define GPIOILEVEL 0x0C
+#define GPIOISTAT 0x10
+#define GPIONMIEN 0x14
+#define IMASK6 0x38
#define LO_WPX (1 << 0)
#define LO_ALE (1 << 1)
#define LO_CLE (1 << 2)
diff --git a/arch/mips/include/asm/pci.h b/arch/mips/include/asm/pci.h
index 5510c53b7fe..053e4634ace 100644
--- a/arch/mips/include/asm/pci.h
+++ b/arch/mips/include/asm/pci.h
@@ -79,6 +79,11 @@ static inline void pcibios_penalize_isa_irq(int irq, int active)
/* We don't do dynamic PCI IRQ allocation */
}
+#define HAVE_PCI_MMAP
+
+extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+ enum pci_mmap_state mmap_state, int write_combine);
+
/*
* Dynamic DMA mapping stuff.
* MIPS has everything mapped statically.
diff --git a/arch/mips/include/asm/ptrace.h b/arch/mips/include/asm/ptrace.h
index 813abd16255..c2c8bac4330 100644
--- a/arch/mips/include/asm/ptrace.h
+++ b/arch/mips/include/asm/ptrace.h
@@ -9,10 +9,6 @@
#ifndef _ASM_PTRACE_H
#define _ASM_PTRACE_H
-#ifdef CONFIG_64BIT
-#define __ARCH_WANT_COMPAT_SYS_PTRACE
-#endif
-
/* 0 - 31 are integer registers, 32 - 63 are fp registers. */
#define FPR_BASE 32
#define PC 64
diff --git a/arch/mips/include/asm/time.h b/arch/mips/include/asm/time.h
index d3bd5c5aa2e..9601ea95054 100644
--- a/arch/mips/include/asm/time.h
+++ b/arch/mips/include/asm/time.h
@@ -63,7 +63,7 @@ static inline int mips_clockevent_init(void)
/*
* Initialize the count register as a clocksource
*/
-#ifdef CONFIG_CEVT_R4K
+#ifdef CONFIG_CSRC_R4K
extern int init_mips_clocksource(void);
#else
static inline int init_mips_clocksource(void)
diff --git a/arch/mips/kernel/csrc-r4k.c b/arch/mips/kernel/csrc-r4k.c
index 86e026f067b..74fb74583b4 100644
--- a/arch/mips/kernel/csrc-r4k.c
+++ b/arch/mips/kernel/csrc-r4k.c
@@ -27,7 +27,7 @@ int __init init_mips_clocksource(void)
if (!cpu_has_counter || !mips_hpt_frequency)
return -ENXIO;
- /* Calclate a somewhat reasonable rating value */
+ /* Calculate a somewhat reasonable rating value */
clocksource_mips.rating = 200 + mips_hpt_frequency / 10000000;
clocksource_set_clock(&clocksource_mips, mips_hpt_frequency);
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index 759f68066b5..d0916a55cd7 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -262,14 +262,11 @@ bad_alignment:
LEAF(sys_syscall)
subu t0, a0, __NR_O32_Linux # check syscall number
sltiu v0, t0, __NR_O32_Linux_syscalls + 1
+ beqz t0, einval # do not recurse
sll t1, t0, 3
beqz v0, einval
-
lw t2, sys_call_table(t1) # syscall routine
- li v1, 4000 - __NR_O32_Linux # index of sys_syscall
- beq t0, v1, einval # do not recurse
-
/* Some syscalls like execve get their arguments from struct pt_regs
and claim zero arguments in the syscall table. Thus we have to
assume the worst case and shuffle around all potential arguments.
@@ -627,7 +624,7 @@ einval: li v0, -ENOSYS
sys sys_pselect6 6
sys sys_ppoll 5
sys sys_unshare 1
- sys sys_splice 4
+ sys sys_splice 6
sys sys_sync_file_range 7 /* 4305 */
sys sys_tee 4
sys sys_vmsplice 4
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index e266b3aa656..30f3b6317a8 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -390,7 +390,7 @@ EXPORT(sysn32_call_table)
PTR sys_splice
PTR sys_sync_file_range
PTR sys_tee
- PTR sys_vmsplice /* 6270 */
+ PTR compat_sys_vmsplice /* 6270 */
PTR sys_move_pages
PTR compat_sys_set_robust_list
PTR compat_sys_get_robust_list
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index 6c7ef8313eb..fefef4af859 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -174,14 +174,12 @@ not_o32_scall:
END(handle_sys)
LEAF(sys32_syscall)
- sltu v0, a0, __NR_O32_Linux + __NR_O32_Linux_syscalls + 1
+ subu t0, a0, __NR_O32_Linux # check syscall number
+ sltiu v0, t0, __NR_O32_Linux_syscalls + 1
+ beqz t0, einval # do not recurse
+ dsll t1, t0, 3
beqz v0, einval
-
- dsll v0, a0, 3
- ld t2, (sys_call_table - (__NR_O32_Linux * 8))(v0)
-
- li v1, 4000 # indirect syscall number
- beq a0, v1, einval # do not recurse
+ ld t2, sys_call_table(t1) # syscall routine
move a0, a1 # shift argument registers
move a1, a2
@@ -198,7 +196,7 @@ LEAF(sys32_syscall)
jr t2
/* Unreached */
-einval: li v0, -EINVAL
+einval: li v0, -ENOSYS
jr ra
END(sys32_syscall)
@@ -512,7 +510,7 @@ sys_call_table:
PTR sys_splice
PTR sys32_sync_file_range /* 4305 */
PTR sys_tee
- PTR sys_vmsplice
+ PTR compat_sys_vmsplice
PTR compat_sys_move_pages
PTR compat_sys_set_robust_list
PTR compat_sys_get_robust_list /* 4310 */
diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c
index 972b2d2b840..a1b3da6bad5 100644
--- a/arch/mips/kernel/vpe.c
+++ b/arch/mips/kernel/vpe.c
@@ -1134,7 +1134,7 @@ static int vpe_release(struct inode *inode, struct file *filp)
/* It's good to be able to run the SP and if it chokes have a look at
the /dev/rt?. But if we reset the pointer to the shared struct we
- loose what has happened. So perhaps if garbage is sent to the vpe
+ lose what has happened. So perhaps if garbage is sent to the vpe
device, use it as a trigger for the reset. Hopefully a nice
executable will be along shortly. */
if (ret < 0)
diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c
index 5b98d0e731c..e6708b3ad34 100644
--- a/arch/mips/mm/dma-default.c
+++ b/arch/mips/mm/dma-default.c
@@ -111,6 +111,7 @@ EXPORT_SYMBOL(dma_alloc_coherent);
void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr,
dma_addr_t dma_handle)
{
+ plat_unmap_dma_mem(dma_handle);
free_pages((unsigned long) vaddr, get_order(size));
}
@@ -121,6 +122,8 @@ void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
{
unsigned long addr = (unsigned long) vaddr;
+ plat_unmap_dma_mem(dma_handle);
+
if (!plat_device_is_coherent(dev))
addr = CAC_ADDR(addr);
diff --git a/arch/mips/mm/sc-ip22.c b/arch/mips/mm/sc-ip22.c
index 1f602a110e1..13adb578211 100644
--- a/arch/mips/mm/sc-ip22.c
+++ b/arch/mips/mm/sc-ip22.c
@@ -161,7 +161,7 @@ static inline int __init indy_sc_probe(void)
/* XXX Check with wje if the Indy caches can differenciate between
writeback + invalidate and just invalidate. */
-struct bcache_ops indy_sc_ops = {
+static struct bcache_ops indy_sc_ops = {
.bc_enable = indy_sc_enable,
.bc_disable = indy_sc_disable,
.bc_wback_inv = indy_sc_wback_invalidate,
diff --git a/arch/mips/mti-malta/Makefile b/arch/mips/mti-malta/Makefile
index cef2db8d222..32e847808df 100644
--- a/arch/mips/mti-malta/Makefile
+++ b/arch/mips/mti-malta/Makefile
@@ -7,9 +7,8 @@
#
obj-y := malta-amon.o malta-cmdline.o \
malta-display.o malta-init.o malta-int.o \
- malta-memory.o malta-mtd.o \
- malta-platform.o malta-reset.o \
- malta-setup.o malta-time.o
+ malta-memory.o malta-platform.o \
+ malta-reset.o malta-setup.o malta-time.o
obj-$(CONFIG_EARLY_PRINTK) += malta-console.o
obj-$(CONFIG_PCI) += malta-pci.o
diff --git a/arch/mips/mti-malta/malta-amon.c b/arch/mips/mti-malta/malta-amon.c
index 96236bf3383..df9e526312a 100644
--- a/arch/mips/mti-malta/malta-amon.c
+++ b/arch/mips/mti-malta/malta-amon.c
@@ -22,9 +22,9 @@
#include <linux/init.h>
#include <linux/smp.h>
-#include <asm-mips/addrspace.h>
-#include <asm-mips/mips-boards/launch.h>
-#include <asm-mips/mipsmtregs.h>
+#include <asm/addrspace.h>
+#include <asm/mips-boards/launch.h>
+#include <asm/mipsmtregs.h>
int amon_cpu_avail(int cpu)
{
diff --git a/arch/mips/mti-malta/malta-mtd.c b/arch/mips/mti-malta/malta-mtd.c
deleted file mode 100644
index 8ad9bdf25dc..00000000000
--- a/arch/mips/mti-malta/malta-mtd.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2006 MIPS Technologies, Inc.
- * written by Ralf Baechle <ralf@linux-mips.org>
- */
-
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/mtd/partitions.h>
-#include <linux/mtd/physmap.h>
-#include <mtd/mtd-abi.h>
-
-static struct mtd_partition malta_mtd_partitions[] = {
- {
- .name = "YAMON",
- .offset = 0x0,
- .size = 0x100000,
- .mask_flags = MTD_WRITEABLE
- }, {
- .name = "User FS",
- .offset = 0x100000,
- .size = 0x2e0000
- }, {
- .name = "Board Config",
- .offset = 0x3e0000,
- .size = 0x020000,
- .mask_flags = MTD_WRITEABLE
- }
-};
-
-static struct physmap_flash_data malta_flash_data = {
- .width = 4,
- .nr_parts = ARRAY_SIZE(malta_mtd_partitions),
- .parts = malta_mtd_partitions
-};
-
-static struct resource malta_flash_resource = {
- .start = 0x1e000000,
- .end = 0x1e3fffff,
- .flags = IORESOURCE_MEM
-};
-
-static struct platform_device malta_flash = {
- .name = "physmap-flash",
- .id = 0,
- .dev = {
- .platform_data = &malta_flash_data,
- },
- .num_resources = 1,
- .resource = &malta_flash_resource,
-};
-
-static int __init malta_mtd_init(void)
-{
- platform_device_register(&malta_flash);
-
- return 0;
-}
-
-module_init(malta_mtd_init)
diff --git a/arch/mips/mti-malta/malta-platform.c b/arch/mips/mti-malta/malta-platform.c
index 83b9bab3cd3..72e32a7715b 100644
--- a/arch/mips/mti-malta/malta-platform.c
+++ b/arch/mips/mti-malta/malta-platform.c
@@ -3,10 +3,14 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 2007 MIPS Technologies, Inc.
+ * Copyright (C) 2006, 07 MIPS Technologies, Inc.
* written by Ralf Baechle (ralf@linux-mips.org)
+ * written by Ralf Baechle <ralf@linux-mips.org>
*
- * Probe driver for the Malta's UART ports:
+ * Copyright (C) 2008 Wind River Systems, Inc.
+ * updated by Tiejun Chen <tiejun.chen@windriver.com>
+ *
+ * 1. Probe driver for the Malta's UART ports:
*
* o 2 ports in the SMC SuperIO
* o 1 port in the CBUS UART, a discrete 16550 which normally is only used
@@ -14,10 +18,17 @@
*
* We don't use 8250_platform.c on Malta as it would result in the CBUS
* UART becoming ttyS0.
+ *
+ * 2. Register RTC-CMOS platform device on Malta.
*/
-#include <linux/module.h>
#include <linux/init.h>
#include <linux/serial_8250.h>
+#include <linux/mc146818rtc.h>
+#include <linux/module.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
+#include <mtd/mtd-abi.h>
#define SMC_PORT(base, int) \
{ \
@@ -45,21 +56,93 @@ static struct plat_serial8250_port uart8250_data[] = {
{ },
};
-static struct platform_device uart8250_device = {
+static struct platform_device malta_uart8250_device = {
.name = "serial8250",
- .id = PLAT8250_DEV_PLATFORM2,
+ .id = PLAT8250_DEV_PLATFORM,
.dev = {
.platform_data = uart8250_data,
},
};
-static int __init uart8250_init(void)
+struct resource malta_rtc_resources[] = {
+ {
+ .start = RTC_PORT(0),
+ .end = RTC_PORT(7),
+ .flags = IORESOURCE_IO,
+ }, {
+ .start = RTC_IRQ,
+ .end = RTC_IRQ,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct platform_device malta_rtc_device = {
+ .name = "rtc_cmos",
+ .id = -1,
+ .resource = malta_rtc_resources,
+ .num_resources = ARRAY_SIZE(malta_rtc_resources),
+};
+
+static struct mtd_partition malta_mtd_partitions[] = {
+ {
+ .name = "YAMON",
+ .offset = 0x0,
+ .size = 0x100000,
+ .mask_flags = MTD_WRITEABLE
+ }, {
+ .name = "User FS",
+ .offset = 0x100000,
+ .size = 0x2e0000
+ }, {
+ .name = "Board Config",
+ .offset = 0x3e0000,
+ .size = 0x020000,
+ .mask_flags = MTD_WRITEABLE
+ }
+};
+
+static struct physmap_flash_data malta_flash_data = {
+ .width = 4,
+ .nr_parts = ARRAY_SIZE(malta_mtd_partitions),
+ .parts = malta_mtd_partitions
+};
+
+static struct resource malta_flash_resource = {
+ .start = 0x1e000000,
+ .end = 0x1e3fffff,
+ .flags = IORESOURCE_MEM
+};
+
+static struct platform_device malta_flash_device = {
+ .name = "physmap-flash",
+ .id = 0,
+ .dev = {
+ .platform_data = &malta_flash_data,
+ },
+ .num_resources = 1,
+ .resource = &malta_flash_resource,
+};
+
+static struct platform_device *malta_devices[] __initdata = {
+ &malta_uart8250_device,
+ &malta_rtc_device,
+ &malta_flash_device,
+};
+
+static int __init malta_add_devices(void)
{
- return platform_device_register(&uart8250_device);
-}
+ int err;
-module_init(uart8250_init);
+ err = platform_add_devices(malta_devices, ARRAY_SIZE(malta_devices));
+ if (err)
+ return err;
+
+ /*
+ * Set RTC to BCD mode to support current alarm code.
+ */
+ CMOS_WRITE(CMOS_READ(RTC_CONTROL) & ~RTC_DM_BINARY, RTC_CONTROL);
+
+ return 0;
+}
-MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("8250 UART probe driver for the Malta CBUS UART");
+device_initcall(malta_add_devices);
diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c
index a377e9d2d02..62cae740e25 100644
--- a/arch/mips/pci/pci.c
+++ b/arch/mips/pci/pci.c
@@ -354,6 +354,30 @@ EXPORT_SYMBOL(PCIBIOS_MIN_IO);
EXPORT_SYMBOL(PCIBIOS_MIN_MEM);
#endif
+int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+ enum pci_mmap_state mmap_state, int write_combine)
+{
+ unsigned long prot;
+
+ /*
+ * I/O space can be accessed via normal processor loads and stores on
+ * this platform but for now we elect not to do this and portable
+ * drivers should not do this anyway.
+ */
+ if (mmap_state == pci_mmap_io)
+ return -EINVAL;
+
+ /*
+ * Ignore write-combine; for now only return uncached mappings.
+ */
+ prot = pgprot_val(vma->vm_page_prot);
+ prot = (prot & ~_CACHE_MASK) | _CACHE_UNCACHED;
+ vma->vm_page_prot = __pgprot(prot);
+
+ return remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+ vma->vm_end - vma->vm_start, vma->vm_page_prot);
+}
+
char * (*pcibios_plat_setup)(char *str) __devinitdata;
char *__devinit pcibios_setup(char *str)
diff --git a/arch/mips/rb532/devices.c b/arch/mips/rb532/devices.c
index 2f22d714d5b..c1c29181bd4 100644
--- a/arch/mips/rb532/devices.c
+++ b/arch/mips/rb532/devices.c
@@ -118,7 +118,7 @@ static struct platform_device cf_slot0 = {
/* Resources and device for NAND */
static int rb532_dev_ready(struct mtd_info *mtd)
{
- return readl(IDT434_REG_BASE + GPIOD) & GPIO_RDY;
+ return gpio_get_value(GPIO_RDY);
}
static void rb532_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
diff --git a/arch/mips/rb532/gpio.c b/arch/mips/rb532/gpio.c
index 70c4a672637..0e84c8ab6a3 100644
--- a/arch/mips/rb532/gpio.c
+++ b/arch/mips/rb532/gpio.c
@@ -39,10 +39,6 @@
struct rb532_gpio_chip {
struct gpio_chip chip;
void __iomem *regbase;
- void (*set_int_level)(struct gpio_chip *chip, unsigned offset, int value);
- int (*get_int_level)(struct gpio_chip *chip, unsigned offset);
- void (*set_int_status)(struct gpio_chip *chip, unsigned offset, int value);
- int (*get_int_status)(struct gpio_chip *chip, unsigned offset);
};
struct mpmc_device dev3;
@@ -111,15 +107,47 @@ unsigned char get_latch_u5(void)
}
EXPORT_SYMBOL(get_latch_u5);
+/* rb532_set_bit - sanely set a bit
+ *
+ * bitval: new value for the bit
+ * offset: bit index in the 4 byte address range
+ * ioaddr: 4 byte aligned address being altered
+ */
+static inline void rb532_set_bit(unsigned bitval,
+ unsigned offset, void __iomem *ioaddr)
+{
+ unsigned long flags;
+ u32 val;
+
+ bitval = !!bitval; /* map parameter to {0,1} */
+
+ local_irq_save(flags);
+
+ val = readl(ioaddr);
+ val &= ~( ~bitval << offset ); /* unset bit if bitval == 0 */
+ val |= ( bitval << offset ); /* set bit if bitval == 1 */
+ writel(val, ioaddr);
+
+ local_irq_restore(flags);
+}
+
+/* rb532_get_bit - read a bit
+ *
+ * returns the boolean state of the bit, which may be > 1
+ */
+static inline int rb532_get_bit(unsigned offset, void __iomem *ioaddr)
+{
+ return (readl(ioaddr) & (1 << offset));
+}
+
/*
* Return GPIO level */
static int rb532_gpio_get(struct gpio_chip *chip, unsigned offset)
{
- u32 mask = 1 << offset;
struct rb532_gpio_chip *gpch;
gpch = container_of(chip, struct rb532_gpio_chip, chip);
- return readl(gpch->regbase + GPIOD) & mask;
+ return rb532_get_bit(offset, gpch->regbase + GPIOD);
}
/*
@@ -128,23 +156,10 @@ static int rb532_gpio_get(struct gpio_chip *chip, unsigned offset)
static void rb532_gpio_set(struct gpio_chip *chip,
unsigned offset, int value)
{
- unsigned long flags;
- u32 mask = 1 << offset;
- u32 tmp;
struct rb532_gpio_chip *gpch;
- void __iomem *gpvr;
gpch = container_of(chip, struct rb532_gpio_chip, chip);
- gpvr = gpch->regbase + GPIOD;
-
- local_irq_save(flags);
- tmp = readl(gpvr);
- if (value)
- tmp |= mask;
- else
- tmp &= ~mask;
- writel(tmp, gpvr);
- local_irq_restore(flags);
+ rb532_set_bit(value, offset, gpch->regbase + GPIOD);
}
/*
@@ -152,21 +167,14 @@ static void rb532_gpio_set(struct gpio_chip *chip,
*/
static int rb532_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
{
- unsigned long flags;
- u32 mask = 1 << offset;
- u32 value;
struct rb532_gpio_chip *gpch;
- void __iomem *gpdr;
gpch = container_of(chip, struct rb532_gpio_chip, chip);
- gpdr = gpch->regbase + GPIOCFG;
- local_irq_save(flags);
- value = readl(gpdr);
- value &= ~mask;
- writel(value, gpdr);
- local_irq_restore(flags);
+ if (rb532_get_bit(offset, gpch->regbase + GPIOFUNC))
+ return 1; /* alternate function, GPIOCFG is ignored */
+ rb532_set_bit(0, offset, gpch->regbase + GPIOCFG);
return 0;
}
@@ -176,117 +184,60 @@ static int rb532_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
static int rb532_gpio_direction_output(struct gpio_chip *chip,
unsigned offset, int value)
{
- unsigned long flags;
- u32 mask = 1 << offset;
- u32 tmp;
struct rb532_gpio_chip *gpch;
- void __iomem *gpdr;
gpch = container_of(chip, struct rb532_gpio_chip, chip);
- writel(mask, gpch->regbase + GPIOD);
- gpdr = gpch->regbase + GPIOCFG;
- local_irq_save(flags);
- tmp = readl(gpdr);
- tmp |= mask;
- writel(tmp, gpdr);
- local_irq_restore(flags);
+ if (rb532_get_bit(offset, gpch->regbase + GPIOFUNC))
+ return 1; /* alternate function, GPIOCFG is ignored */
+ /* set the initial output value */
+ rb532_set_bit(value, offset, gpch->regbase + GPIOD);
+
+ rb532_set_bit(1, offset, gpch->regbase + GPIOCFG);
return 0;
}
-/*
- * Set the GPIO interrupt level
- */
-static void rb532_gpio_set_int_level(struct gpio_chip *chip,
- unsigned offset, int value)
-{
- unsigned long flags;
- u32 mask = 1 << offset;
- u32 tmp;
- struct rb532_gpio_chip *gpch;
- void __iomem *gpil;
-
- gpch = container_of(chip, struct rb532_gpio_chip, chip);
- gpil = gpch->regbase + GPIOILEVEL;
-
- local_irq_save(flags);
- tmp = readl(gpil);
- if (value)
- tmp |= mask;
- else
- tmp &= ~mask;
- writel(tmp, gpil);
- local_irq_restore(flags);
-}
+static struct rb532_gpio_chip rb532_gpio_chip[] = {
+ [0] = {
+ .chip = {
+ .label = "gpio0",
+ .direction_input = rb532_gpio_direction_input,
+ .direction_output = rb532_gpio_direction_output,
+ .get = rb532_gpio_get,
+ .set = rb532_gpio_set,
+ .base = 0,
+ .ngpio = 32,
+ },
+ },
+};
/*
- * Get the GPIO interrupt level
+ * Set GPIO interrupt level
*/
-static int rb532_gpio_get_int_level(struct gpio_chip *chip, unsigned offset)
+void rb532_gpio_set_ilevel(int bit, unsigned gpio)
{
- u32 mask = 1 << offset;
- struct rb532_gpio_chip *gpch;
-
- gpch = container_of(chip, struct rb532_gpio_chip, chip);
- return readl(gpch->regbase + GPIOILEVEL) & mask;
+ rb532_set_bit(bit, gpio, rb532_gpio_chip->regbase + GPIOILEVEL);
}
+EXPORT_SYMBOL(rb532_gpio_set_ilevel);
/*
- * Set the GPIO interrupt status
+ * Set GPIO interrupt status
*/
-static void rb532_gpio_set_int_status(struct gpio_chip *chip,
- unsigned offset, int value)
+void rb532_gpio_set_istat(int bit, unsigned gpio)
{
- unsigned long flags;
- u32 mask = 1 << offset;
- u32 tmp;
- struct rb532_gpio_chip *gpch;
- void __iomem *gpis;
-
- gpch = container_of(chip, struct rb532_gpio_chip, chip);
- gpis = gpch->regbase + GPIOISTAT;
-
- local_irq_save(flags);
- tmp = readl(gpis);
- if (value)
- tmp |= mask;
- else
- tmp &= ~mask;
- writel(tmp, gpis);
- local_irq_restore(flags);
+ rb532_set_bit(bit, gpio, rb532_gpio_chip->regbase + GPIOISTAT);
}
+EXPORT_SYMBOL(rb532_gpio_set_istat);
/*
- * Get the GPIO interrupt status
+ * Configure GPIO alternate function
*/
-static int rb532_gpio_get_int_status(struct gpio_chip *chip, unsigned offset)
+static void rb532_gpio_set_func(int bit, unsigned gpio)
{
- u32 mask = 1 << offset;
- struct rb532_gpio_chip *gpch;
-
- gpch = container_of(chip, struct rb532_gpio_chip, chip);
- return readl(gpch->regbase + GPIOISTAT) & mask;
+ rb532_set_bit(bit, gpio, rb532_gpio_chip->regbase + GPIOFUNC);
}
-static struct rb532_gpio_chip rb532_gpio_chip[] = {
- [0] = {
- .chip = {
- .label = "gpio0",
- .direction_input = rb532_gpio_direction_input,
- .direction_output = rb532_gpio_direction_output,
- .get = rb532_gpio_get,
- .set = rb532_gpio_set,
- .base = 0,
- .ngpio = 32,
- },
- .get_int_level = rb532_gpio_get_int_level,
- .set_int_level = rb532_gpio_set_int_level,
- .get_int_status = rb532_gpio_get_int_status,
- .set_int_status = rb532_gpio_set_int_status,
- },
-};
-
int __init rb532_gpio_init(void)
{
struct resource *r;
@@ -310,9 +261,11 @@ int __init rb532_gpio_init(void)
return -ENXIO;
}
- /* Set the interrupt status and level for the CF pin */
- rb532_gpio_set_int_level(&rb532_gpio_chip->chip, CF_GPIO_NUM, 1);
- rb532_gpio_set_int_status(&rb532_gpio_chip->chip, CF_GPIO_NUM, 0);
+ /* configure CF_GPIO_NUM as CFRDY IRQ source */
+ rb532_gpio_set_func(0, CF_GPIO_NUM);
+ rb532_gpio_direction_input(&rb532_gpio_chip->chip, CF_GPIO_NUM);
+ rb532_gpio_set_ilevel(1, CF_GPIO_NUM);
+ rb532_gpio_set_istat(0, CF_GPIO_NUM);
return 0;
}
diff --git a/arch/mn10300/Kconfig.debug b/arch/mn10300/Kconfig.debug
index 524e33819f3..ff80e86b9bd 100644
--- a/arch/mn10300/Kconfig.debug
+++ b/arch/mn10300/Kconfig.debug
@@ -15,6 +15,15 @@ config DEBUG_DECOMPRESS_KERNEL
decompressing Linux seeing "Uncompressing Linux... " and
"Ok, booting the kernel.\n" on console.
+config TEST_MISALIGNMENT_HANDLER
+ bool "Run tests on the misalignment handler"
+ depends on DEBUG_KERNEL
+ default n
+ help
+ If you say Y here the kernel will execute a list of misaligned memory
+ accesses to make sure the misalignment handler deals them with
+ correctly. If it does not, the kernel will throw a BUG.
+
config KPROBES
bool "Kprobes"
depends on DEBUG_KERNEL
diff --git a/arch/mn10300/kernel/entry.S b/arch/mn10300/kernel/entry.S
index b7cbb1487af..62fba8aa9b6 100644
--- a/arch/mn10300/kernel/entry.S
+++ b/arch/mn10300/kernel/entry.S
@@ -180,6 +180,7 @@ ENTRY(resume_userspace)
#ifdef CONFIG_PREEMPT
ENTRY(resume_kernel)
+ __cli
mov (TI_preempt_count,a2),d0 # non-zero preempt_count ?
cmp 0,d0
bne restore_all
@@ -190,7 +191,7 @@ need_resched:
mov (REG_EPSW,fp),d0
and EPSW_IM,d0
cmp EPSW_IM_7,d0 # interrupts off (exception path) ?
- beq restore_all
+ bne restore_all
call preempt_schedule_irq[],0
jmp need_resched
#endif
diff --git a/arch/mn10300/kernel/gdb-io-serial.c b/arch/mn10300/kernel/gdb-io-serial.c
index 9a6d4e8ebe7..11584c51acd 100644
--- a/arch/mn10300/kernel/gdb-io-serial.c
+++ b/arch/mn10300/kernel/gdb-io-serial.c
@@ -99,6 +99,7 @@ int gdbstub_io_rx_char(unsigned char *_ch, int nonblock)
try_again:
/* pull chars out of the buffer */
ix = gdbstub_rx_outp;
+ barrier();
if (ix == gdbstub_rx_inp) {
if (nonblock)
return -EAGAIN;
@@ -110,6 +111,7 @@ int gdbstub_io_rx_char(unsigned char *_ch, int nonblock)
ch = gdbstub_rx_buffer[ix++];
st = gdbstub_rx_buffer[ix++];
+ barrier();
gdbstub_rx_outp = ix & 0x00000fff;
if (st & UART_LSR_BI) {
diff --git a/arch/mn10300/kernel/gdb-stub.c b/arch/mn10300/kernel/gdb-stub.c
index 54be6afb555..0ea7482c152 100644
--- a/arch/mn10300/kernel/gdb-stub.c
+++ b/arch/mn10300/kernel/gdb-stub.c
@@ -522,17 +522,7 @@ static int gdbstub_single_step(struct pt_regs *regs)
} else {
switch (cur) {
/* Bxx (d8,PC) */
- case 0xc0:
- case 0xc1:
- case 0xc2:
- case 0xc3:
- case 0xc4:
- case 0xc5:
- case 0xc6:
- case 0xc7:
- case 0xc8:
- case 0xc9:
- case 0xca:
+ case 0xc0 ... 0xca:
if (gdbstub_read_byte(pc + 1, (u8 *) &x) < 0)
goto fault;
if (!__gdbstub_mark_bp(pc + 2, 0))
@@ -543,17 +533,7 @@ static int gdbstub_single_step(struct pt_regs *regs)
break;
/* LXX (d8,PC) */
- case 0xd0:
- case 0xd1:
- case 0xd2:
- case 0xd3:
- case 0xd4:
- case 0xd5:
- case 0xd6:
- case 0xd7:
- case 0xd8:
- case 0xd9:
- case 0xda:
+ case 0xd0 ... 0xda:
if (!__gdbstub_mark_bp(pc + 1, 0))
goto fault;
if (regs->pc != regs->lar &&
diff --git a/arch/mn10300/kernel/mn10300-serial.c b/arch/mn10300/kernel/mn10300-serial.c
index aa07d0cd190..59b9c4bf958 100644
--- a/arch/mn10300/kernel/mn10300-serial.c
+++ b/arch/mn10300/kernel/mn10300-serial.c
@@ -566,6 +566,11 @@ static void mn10300_serial_transmit_interrupt(struct mn10300_serial_port *port)
{
_enter("%s", port->name);
+ if (!port->uart.info || !port->uart.info->port.tty) {
+ mn10300_serial_dis_tx_intr(port);
+ return;
+ }
+
if (uart_tx_stopped(&port->uart) ||
uart_circ_empty(&port->uart.info->xmit))
mn10300_serial_dis_tx_intr(port);
diff --git a/arch/mn10300/kernel/module.c b/arch/mn10300/kernel/module.c
index 8fa36893df7..6b287f2e8e8 100644
--- a/arch/mn10300/kernel/module.c
+++ b/arch/mn10300/kernel/module.c
@@ -1,6 +1,6 @@
/* MN10300 Kernel module helper routines
*
- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Copyright (C) 2007, 2008 Red Hat, Inc. All Rights Reserved.
* Written by Mark Salter (msalter@redhat.com)
* - Derived from arch/i386/kernel/module.c
*
@@ -64,21 +64,6 @@ int module_frob_arch_sections(Elf_Ehdr *hdr,
return 0;
}
-static uint32_t reloc_get16(uint8_t *p)
-{
- return p[0] | (p[1] << 8);
-}
-
-static uint32_t reloc_get24(uint8_t *p)
-{
- return reloc_get16(p) | (p[2] << 16);
-}
-
-static uint32_t reloc_get32(uint8_t *p)
-{
- return reloc_get16(p) | (reloc_get16(p+2) << 16);
-}
-
static void reloc_put16(uint8_t *p, uint32_t val)
{
p[0] = val & 0xff;
@@ -144,25 +129,19 @@ int apply_relocate_add(Elf32_Shdr *sechdrs,
relocation = sym->st_value + rel[i].r_addend;
switch (ELF32_R_TYPE(rel[i].r_info)) {
- /* for the first four relocation types, we add the
- * adjustment into the value at the location given */
+ /* for the first four relocation types, we simply
+ * store the adjustment at the location given */
case R_MN10300_32:
- value = reloc_get32(location);
- value += relocation;
- reloc_put32(location, value);
+ reloc_put32(location, relocation);
break;
case R_MN10300_24:
- value = reloc_get24(location);
- value += relocation;
- reloc_put24(location, value);
+ reloc_put24(location, relocation);
break;
case R_MN10300_16:
- value = reloc_get16(location);
- value += relocation;
- reloc_put16(location, value);
+ reloc_put16(location, relocation);
break;
case R_MN10300_8:
- *location += relocation;
+ *location = relocation;
break;
/* for the next three relocation types, we write the
diff --git a/arch/mn10300/kernel/setup.c b/arch/mn10300/kernel/setup.c
index 017121ce896..e1d88ab5100 100644
--- a/arch/mn10300/kernel/setup.c
+++ b/arch/mn10300/kernel/setup.c
@@ -161,7 +161,7 @@ void __init setup_arch(char **cmdline_p)
reserve the page it is occupying. */
if (CONFIG_INTERRUPT_VECTOR_BASE >= CONFIG_KERNEL_RAM_BASE_ADDRESS &&
CONFIG_INTERRUPT_VECTOR_BASE < memory_end)
- reserve_bootmem(CONFIG_INTERRUPT_VECTOR_BASE, 1,
+ reserve_bootmem(CONFIG_INTERRUPT_VECTOR_BASE, PAGE_SIZE,
BOOTMEM_DEFAULT);
reserve_bootmem(PAGE_ALIGN(PFN_PHYS(free_pfn)), bootmap_size,
diff --git a/arch/mn10300/kernel/vmlinux.lds.S b/arch/mn10300/kernel/vmlinux.lds.S
index a3e80f444f5..b8259668f7d 100644
--- a/arch/mn10300/kernel/vmlinux.lds.S
+++ b/arch/mn10300/kernel/vmlinux.lds.S
@@ -11,6 +11,7 @@
#define __VMLINUX_LDS__
#include <asm-generic/vmlinux.lds.h>
#include <asm/thread_info.h>
+#include <asm/page.h>
OUTPUT_FORMAT("elf32-am33lin", "elf32-am33lin", "elf32-am33lin")
OUTPUT_ARCH(mn10300)
@@ -55,13 +56,13 @@ SECTIONS
CONSTRUCTORS
}
- . = ALIGN(4096);
+ . = ALIGN(PAGE_SIZE);
__nosave_begin = .;
.data_nosave : { *(.data.nosave) }
- . = ALIGN(4096);
+ . = ALIGN(PAGE_SIZE);
__nosave_end = .;
- . = ALIGN(4096);
+ . = ALIGN(PAGE_SIZE);
.data.page_aligned : { *(.data.idt) }
. = ALIGN(32);
@@ -78,7 +79,7 @@ SECTIONS
.data.init_task : { *(.data.init_task) }
/* might get freed after init */
- . = ALIGN(4096);
+ . = ALIGN(PAGE_SIZE);
.smp_locks : AT(ADDR(.smp_locks) - LOAD_OFFSET) {
__smp_locks = .;
*(.smp_locks)
@@ -86,7 +87,7 @@ SECTIONS
}
/* will be freed after init */
- . = ALIGN(4096); /* Init code and data */
+ . = ALIGN(PAGE_SIZE); /* Init code and data */
__init_begin = .;
.init.text : {
_sinittext = .;
@@ -120,17 +121,14 @@ SECTIONS
.exit.data : { *(.exit.data) }
#ifdef CONFIG_BLK_DEV_INITRD
- . = ALIGN(4096);
+ . = ALIGN(PAGE_SIZE);
__initramfs_start = .;
.init.ramfs : { *(.init.ramfs) }
__initramfs_end = .;
#endif
- . = ALIGN(32);
- __per_cpu_start = .;
- .data.percpu : { *(.data.percpu) }
- __per_cpu_end = .;
- . = ALIGN(4096);
+ PERCPU(32)
+ . = ALIGN(PAGE_SIZE);
__init_end = .;
/* freed after init ends here */
@@ -145,7 +143,7 @@ SECTIONS
_end = . ;
/* This is where the kernel creates the early boot page tables */
- . = ALIGN(4096);
+ . = ALIGN(PAGE_SIZE);
pg0 = .;
/* Sections to be discarded */
diff --git a/arch/mn10300/mm/misalignment.c b/arch/mn10300/mm/misalignment.c
index 32aa89dc384..94c4a435806 100644
--- a/arch/mn10300/mm/misalignment.c
+++ b/arch/mn10300/mm/misalignment.c
@@ -37,26 +37,22 @@
#include <asm/asm-offsets.h>
#if 0
-#define kdebug(FMT, ...) printk(KERN_DEBUG FMT, ##__VA_ARGS__)
+#define kdebug(FMT, ...) printk(KERN_DEBUG "MISALIGN: "FMT"\n", ##__VA_ARGS__)
#else
#define kdebug(FMT, ...) do {} while (0)
#endif
-static int misalignment_addr(unsigned long *registers, unsigned params,
- unsigned opcode, unsigned disp,
- void **_address, unsigned long **_postinc);
+static int misalignment_addr(unsigned long *registers, unsigned long sp,
+ unsigned params, unsigned opcode,
+ unsigned long disp,
+ void **_address, unsigned long **_postinc,
+ unsigned long *_inc);
static int misalignment_reg(unsigned long *registers, unsigned params,
- unsigned opcode, unsigned disp,
+ unsigned opcode, unsigned long disp,
unsigned long **_register);
-static inline unsigned int_log2(unsigned x)
-{
- unsigned y;
- asm("bsch %1,%0" : "=r"(y) : "r"(x), "0"(0));
- return y;
-}
-#define log2(x) int_log2(x)
+static void misalignment_MOV_Lcc(struct pt_regs *regs, uint32_t opcode);
static const unsigned Dreg_index[] = {
REG_D0 >> 2, REG_D1 >> 2, REG_D2 >> 2, REG_D3 >> 2
@@ -86,9 +82,10 @@ enum format_id {
FMT_D7,
FMT_D8,
FMT_D9,
+ FMT_D10,
};
-struct {
+static const struct {
u_int8_t opsz, dispsz;
} format_tbl[16] = {
[FMT_S0] = { 8, 0 },
@@ -103,6 +100,7 @@ struct {
[FMT_D7] = { 24, 8 },
[FMT_D8] = { 24, 24 },
[FMT_D9] = { 24, 32 },
+ [FMT_D10] = { 32, 0 },
};
enum value_id {
@@ -128,9 +126,14 @@ enum value_id {
SD24, /* 24-bit signed displacement */
SIMM4_2, /* 4-bit signed displacement in opcode bits 4-7 */
SIMM8, /* 8-bit signed immediate */
+ IMM8, /* 8-bit unsigned immediate */
+ IMM16, /* 16-bit unsigned immediate */
IMM24, /* 24-bit unsigned immediate */
IMM32, /* 32-bit unsigned immediate */
- IMM32_HIGH8, /* 32-bit unsigned immediate, high 8-bits in opcode */
+ IMM32_HIGH8, /* 32-bit unsigned immediate, LSB in opcode */
+
+ IMM32_MEM, /* 32-bit unsigned displacement */
+ IMM32_HIGH8_MEM, /* 32-bit unsigned displacement, LSB in opcode */
DN0 = DM0,
DN1 = DM1,
@@ -149,7 +152,7 @@ enum value_id {
};
struct mn10300_opcode {
- const char *name;
+ const char name[8];
u_int32_t opcode;
u_int32_t opmask;
unsigned exclusion;
@@ -185,6 +188,10 @@ struct mn10300_opcode {
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
static const struct mn10300_opcode mn10300_opcodes[] = {
+{ "mov", 0x4200, 0xf300, 0, FMT_S1, 0, {DM1, MEM2(IMM8, SP)}},
+{ "mov", 0x4300, 0xf300, 0, FMT_S1, 0, {AM1, MEM2(IMM8, SP)}},
+{ "mov", 0x5800, 0xfc00, 0, FMT_S1, 0, {MEM2(IMM8, SP), DN0}},
+{ "mov", 0x5c00, 0xfc00, 0, FMT_S1, 0, {MEM2(IMM8, SP), AN0}},
{ "mov", 0x60, 0xf0, 0, FMT_S0, 0, {DM1, MEM(AN0)}},
{ "mov", 0x70, 0xf0, 0, FMT_S0, 0, {MEM(AM0), DN1}},
{ "mov", 0xf000, 0xfff0, 0, FMT_D0, 0, {MEM(AM0), AN1}},
@@ -197,8 +204,6 @@ static const struct mn10300_opcode mn10300_opcodes[] = {
{ "mov", 0xf81000, 0xfff000, 0, FMT_D1, 0, {DM1, MEM2(SD8, AN0)}},
{ "mov", 0xf82000, 0xfff000, 0, FMT_D1, 0, {MEM2(SD8,AM0), AN1}},
{ "mov", 0xf83000, 0xfff000, 0, FMT_D1, 0, {AM1, MEM2(SD8, AN0)}},
-{ "mov", 0xf8f000, 0xfffc00, 0, FMT_D1, AM33, {MEM2(SD8, AM0), SP}},
-{ "mov", 0xf8f400, 0xfffc00, 0, FMT_D1, AM33, {SP, MEM2(SD8, AN0)}},
{ "mov", 0xf90a00, 0xffff00, 0, FMT_D6, AM33, {MEM(RM0), RN2}},
{ "mov", 0xf91a00, 0xffff00, 0, FMT_D6, AM33, {RM2, MEM(RN0)}},
{ "mov", 0xf96a00, 0xffff00, 0x12, FMT_D6, AM33, {MEMINC(RM0), RN2}},
@@ -207,24 +212,46 @@ static const struct mn10300_opcode mn10300_opcodes[] = {
{ "mov", 0xfa100000, 0xfff00000, 0, FMT_D2, 0, {DM1, MEM2(SD16, AN0)}},
{ "mov", 0xfa200000, 0xfff00000, 0, FMT_D2, 0, {MEM2(SD16, AM0), AN1}},
{ "mov", 0xfa300000, 0xfff00000, 0, FMT_D2, 0, {AM1, MEM2(SD16, AN0)}},
+{ "mov", 0xfa900000, 0xfff30000, 0, FMT_D2, 0, {AM1, MEM2(IMM16, SP)}},
+{ "mov", 0xfa910000, 0xfff30000, 0, FMT_D2, 0, {DM1, MEM2(IMM16, SP)}},
+{ "mov", 0xfab00000, 0xfffc0000, 0, FMT_D2, 0, {MEM2(IMM16, SP), AN0}},
+{ "mov", 0xfab40000, 0xfffc0000, 0, FMT_D2, 0, {MEM2(IMM16, SP), DN0}},
{ "mov", 0xfb0a0000, 0xffff0000, 0, FMT_D7, AM33, {MEM2(SD8, RM0), RN2}},
{ "mov", 0xfb1a0000, 0xffff0000, 0, FMT_D7, AM33, {RM2, MEM2(SD8, RN0)}},
{ "mov", 0xfb6a0000, 0xffff0000, 0x22, FMT_D7, AM33, {MEMINC2 (RM0, SIMM8), RN2}},
{ "mov", 0xfb7a0000, 0xffff0000, 0, FMT_D7, AM33, {RM2, MEMINC2 (RN0, SIMM8)}},
+{ "mov", 0xfb8a0000, 0xffff0f00, 0, FMT_D7, AM33, {MEM2(IMM8, SP), RN2}},
{ "mov", 0xfb8e0000, 0xffff000f, 0, FMT_D7, AM33, {MEM2(RI, RM0), RD2}},
+{ "mov", 0xfb9a0000, 0xffff0f00, 0, FMT_D7, AM33, {RM2, MEM2(IMM8, SP)}},
{ "mov", 0xfb9e0000, 0xffff000f, 0, FMT_D7, AM33, {RD2, MEM2(RI, RN0)}},
{ "mov", 0xfc000000, 0xfff00000, 0, FMT_D4, 0, {MEM2(IMM32,AM0), DN1}},
{ "mov", 0xfc100000, 0xfff00000, 0, FMT_D4, 0, {DM1, MEM2(IMM32,AN0)}},
{ "mov", 0xfc200000, 0xfff00000, 0, FMT_D4, 0, {MEM2(IMM32,AM0), AN1}},
{ "mov", 0xfc300000, 0xfff00000, 0, FMT_D4, 0, {AM1, MEM2(IMM32,AN0)}},
+{ "mov", 0xfc800000, 0xfff30000, 0, FMT_D4, 0, {AM1, MEM(IMM32_MEM)}},
+{ "mov", 0xfc810000, 0xfff30000, 0, FMT_D4, 0, {DM1, MEM(IMM32_MEM)}},
+{ "mov", 0xfc900000, 0xfff30000, 0, FMT_D4, 0, {AM1, MEM2(IMM32, SP)}},
+{ "mov", 0xfc910000, 0xfff30000, 0, FMT_D4, 0, {DM1, MEM2(IMM32, SP)}},
+{ "mov", 0xfca00000, 0xfffc0000, 0, FMT_D4, 0, {MEM(IMM32_MEM), AN0}},
+{ "mov", 0xfca40000, 0xfffc0000, 0, FMT_D4, 0, {MEM(IMM32_MEM), DN0}},
+{ "mov", 0xfcb00000, 0xfffc0000, 0, FMT_D4, 0, {MEM2(IMM32, SP), AN0}},
+{ "mov", 0xfcb40000, 0xfffc0000, 0, FMT_D4, 0, {MEM2(IMM32, SP), DN0}},
{ "mov", 0xfd0a0000, 0xffff0000, 0, FMT_D8, AM33, {MEM2(SD24, RM0), RN2}},
{ "mov", 0xfd1a0000, 0xffff0000, 0, FMT_D8, AM33, {RM2, MEM2(SD24, RN0)}},
{ "mov", 0xfd6a0000, 0xffff0000, 0x22, FMT_D8, AM33, {MEMINC2 (RM0, IMM24), RN2}},
{ "mov", 0xfd7a0000, 0xffff0000, 0, FMT_D8, AM33, {RM2, MEMINC2 (RN0, IMM24)}},
+{ "mov", 0xfd8a0000, 0xffff0f00, 0, FMT_D8, AM33, {MEM2(IMM24, SP), RN2}},
+{ "mov", 0xfd9a0000, 0xffff0f00, 0, FMT_D8, AM33, {RM2, MEM2(IMM24, SP)}},
{ "mov", 0xfe0a0000, 0xffff0000, 0, FMT_D9, AM33, {MEM2(IMM32_HIGH8,RM0), RN2}},
+{ "mov", 0xfe0a0000, 0xffff0000, 0, FMT_D9, AM33, {MEM2(IMM32_HIGH8,RM0), RN2}},
+{ "mov", 0xfe0e0000, 0xffff0f00, 0, FMT_D9, AM33, {MEM(IMM32_HIGH8_MEM), RN2}},
+{ "mov", 0xfe1a0000, 0xffff0000, 0, FMT_D9, AM33, {RM2, MEM2(IMM32_HIGH8, RN0)}},
{ "mov", 0xfe1a0000, 0xffff0000, 0, FMT_D9, AM33, {RM2, MEM2(IMM32_HIGH8, RN0)}},
+{ "mov", 0xfe1e0000, 0xffff0f00, 0, FMT_D9, AM33, {RM2, MEM(IMM32_HIGH8_MEM)}},
{ "mov", 0xfe6a0000, 0xffff0000, 0x22, FMT_D9, AM33, {MEMINC2 (RM0, IMM32_HIGH8), RN2}},
{ "mov", 0xfe7a0000, 0xffff0000, 0, FMT_D9, AM33, {RN2, MEMINC2 (RM0, IMM32_HIGH8)}},
+{ "mov", 0xfe8a0000, 0xffff0f00, 0, FMT_D9, AM33, {MEM2(IMM32_HIGH8, SP), RN2}},
+{ "mov", 0xfe9a0000, 0xffff0f00, 0, FMT_D9, AM33, {RM2, MEM2(IMM32_HIGH8, SP)}},
{ "movhu", 0xf060, 0xfff0, 0, FMT_D0, 0, {MEM(AM0), DN1}},
{ "movhu", 0xf070, 0xfff0, 0, FMT_D0, 0, {DM1, MEM(AN0)}},
@@ -232,29 +259,58 @@ static const struct mn10300_opcode mn10300_opcodes[] = {
{ "movhu", 0xf4c0, 0xffc0, 0, FMT_D0, 0, {DM2, MEM2(DI, AN0)}},
{ "movhu", 0xf86000, 0xfff000, 0, FMT_D1, 0, {MEM2(SD8, AM0), DN1}},
{ "movhu", 0xf87000, 0xfff000, 0, FMT_D1, 0, {DM1, MEM2(SD8, AN0)}},
+{ "movhu", 0xf89300, 0xfff300, 0, FMT_D1, 0, {DM1, MEM2(IMM8, SP)}},
+{ "movhu", 0xf8bc00, 0xfffc00, 0, FMT_D1, 0, {MEM2(IMM8, SP), DN0}},
{ "movhu", 0xf94a00, 0xffff00, 0, FMT_D6, AM33, {MEM(RM0), RN2}},
{ "movhu", 0xf95a00, 0xffff00, 0, FMT_D6, AM33, {RM2, MEM(RN0)}},
{ "movhu", 0xf9ea00, 0xffff00, 0x12, FMT_D6, AM33, {MEMINC(RM0), RN2}},
{ "movhu", 0xf9fa00, 0xffff00, 0, FMT_D6, AM33, {RM2, MEMINC(RN0)}},
{ "movhu", 0xfa600000, 0xfff00000, 0, FMT_D2, 0, {MEM2(SD16, AM0), DN1}},
{ "movhu", 0xfa700000, 0xfff00000, 0, FMT_D2, 0, {DM1, MEM2(SD16, AN0)}},
+{ "movhu", 0xfa930000, 0xfff30000, 0, FMT_D2, 0, {DM1, MEM2(IMM16, SP)}},
+{ "movhu", 0xfabc0000, 0xfffc0000, 0, FMT_D2, 0, {MEM2(IMM16, SP), DN0}},
{ "movhu", 0xfb4a0000, 0xffff0000, 0, FMT_D7, AM33, {MEM2(SD8, RM0), RN2}},
{ "movhu", 0xfb5a0000, 0xffff0000, 0, FMT_D7, AM33, {RM2, MEM2(SD8, RN0)}},
+{ "movhu", 0xfbca0000, 0xffff0f00, 0, FMT_D7, AM33, {MEM2(IMM8, SP), RN2}},
{ "movhu", 0xfbce0000, 0xffff000f, 0, FMT_D7, AM33, {MEM2(RI, RM0), RD2}},
+{ "movhu", 0xfbda0000, 0xffff0f00, 0, FMT_D7, AM33, {RM2, MEM2(IMM8, SP)}},
{ "movhu", 0xfbde0000, 0xffff000f, 0, FMT_D7, AM33, {RD2, MEM2(RI, RN0)}},
{ "movhu", 0xfbea0000, 0xffff0000, 0x22, FMT_D7, AM33, {MEMINC2 (RM0, SIMM8), RN2}},
{ "movhu", 0xfbfa0000, 0xffff0000, 0, FMT_D7, AM33, {RM2, MEMINC2 (RN0, SIMM8)}},
{ "movhu", 0xfc600000, 0xfff00000, 0, FMT_D4, 0, {MEM2(IMM32,AM0), DN1}},
{ "movhu", 0xfc700000, 0xfff00000, 0, FMT_D4, 0, {DM1, MEM2(IMM32,AN0)}},
+{ "movhu", 0xfc830000, 0xfff30000, 0, FMT_D4, 0, {DM1, MEM(IMM32_MEM)}},
+{ "movhu", 0xfc930000, 0xfff30000, 0, FMT_D4, 0, {DM1, MEM2(IMM32, SP)}},
+{ "movhu", 0xfcac0000, 0xfffc0000, 0, FMT_D4, 0, {MEM(IMM32_MEM), DN0}},
+{ "movhu", 0xfcbc0000, 0xfffc0000, 0, FMT_D4, 0, {MEM2(IMM32, SP), DN0}},
{ "movhu", 0xfd4a0000, 0xffff0000, 0, FMT_D8, AM33, {MEM2(SD24, RM0), RN2}},
{ "movhu", 0xfd5a0000, 0xffff0000, 0, FMT_D8, AM33, {RM2, MEM2(SD24, RN0)}},
+{ "movhu", 0xfdca0000, 0xffff0f00, 0, FMT_D8, AM33, {MEM2(IMM24, SP), RN2}},
+{ "movhu", 0xfdda0000, 0xffff0f00, 0, FMT_D8, AM33, {RM2, MEM2(IMM24, SP)}},
{ "movhu", 0xfdea0000, 0xffff0000, 0x22, FMT_D8, AM33, {MEMINC2 (RM0, IMM24), RN2}},
{ "movhu", 0xfdfa0000, 0xffff0000, 0, FMT_D8, AM33, {RM2, MEMINC2 (RN0, IMM24)}},
{ "movhu", 0xfe4a0000, 0xffff0000, 0, FMT_D9, AM33, {MEM2(IMM32_HIGH8,RM0), RN2}},
+{ "movhu", 0xfe4e0000, 0xffff0f00, 0, FMT_D9, AM33, {MEM(IMM32_HIGH8_MEM), RN2}},
{ "movhu", 0xfe5a0000, 0xffff0000, 0, FMT_D9, AM33, {RM2, MEM2(IMM32_HIGH8, RN0)}},
+{ "movhu", 0xfe5e0000, 0xffff0f00, 0, FMT_D9, AM33, {RM2, MEM(IMM32_HIGH8_MEM)}},
+{ "movhu", 0xfeca0000, 0xffff0f00, 0, FMT_D9, AM33, {MEM2(IMM32_HIGH8, SP), RN2}},
+{ "movhu", 0xfeda0000, 0xffff0f00, 0, FMT_D9, AM33, {RM2, MEM2(IMM32_HIGH8, SP)}},
{ "movhu", 0xfeea0000, 0xffff0000, 0x22, FMT_D9, AM33, {MEMINC2 (RM0, IMM32_HIGH8), RN2}},
{ "movhu", 0xfefa0000, 0xffff0000, 0, FMT_D9, AM33, {RN2, MEMINC2 (RM0, IMM32_HIGH8)}},
-{ 0, 0, 0, 0, 0, 0, {0}},
+
+{ "mov_llt", 0xf7e00000, 0xffff000f, 0x22, FMT_D10, AM33, {MEMINC2 (RN4,SIMM4_2), RM6}},
+{ "mov_lgt", 0xf7e00001, 0xffff000f, 0x22, FMT_D10, AM33, {MEMINC2 (RN4,SIMM4_2), RM6}},
+{ "mov_lge", 0xf7e00002, 0xffff000f, 0x22, FMT_D10, AM33, {MEMINC2 (RN4,SIMM4_2), RM6}},
+{ "mov_lle", 0xf7e00003, 0xffff000f, 0x22, FMT_D10, AM33, {MEMINC2 (RN4,SIMM4_2), RM6}},
+{ "mov_lcs", 0xf7e00004, 0xffff000f, 0x22, FMT_D10, AM33, {MEMINC2 (RN4,SIMM4_2), RM6}},
+{ "mov_lhi", 0xf7e00005, 0xffff000f, 0x22, FMT_D10, AM33, {MEMINC2 (RN4,SIMM4_2), RM6}},
+{ "mov_lcc", 0xf7e00006, 0xffff000f, 0x22, FMT_D10, AM33, {MEMINC2 (RN4,SIMM4_2), RM6}},
+{ "mov_lls", 0xf7e00007, 0xffff000f, 0x22, FMT_D10, AM33, {MEMINC2 (RN4,SIMM4_2), RM6}},
+{ "mov_leq", 0xf7e00008, 0xffff000f, 0x22, FMT_D10, AM33, {MEMINC2 (RN4,SIMM4_2), RM6}},
+{ "mov_lne", 0xf7e00009, 0xffff000f, 0x22, FMT_D10, AM33, {MEMINC2 (RN4,SIMM4_2), RM6}},
+{ "mov_lra", 0xf7e0000a, 0xffff000f, 0x22, FMT_D10, AM33, {MEMINC2 (RN4,SIMM4_2), RM6}},
+
+{ "", 0, 0, 0, 0, 0, {0}},
};
/*
@@ -265,18 +321,21 @@ asmlinkage void misalignment(struct pt_regs *regs, enum exception_code code)
const struct exception_table_entry *fixup;
const struct mn10300_opcode *pop;
unsigned long *registers = (unsigned long *) regs;
- unsigned long data, *store, *postinc;
+ unsigned long data, *store, *postinc, disp, inc, sp;
mm_segment_t seg;
siginfo_t info;
- uint32_t opcode, disp, noc, xo, xm;
- uint8_t *pc, byte;
+ uint32_t opcode, noc, xo, xm;
+ uint8_t *pc, byte, datasz;
void *address;
- unsigned tmp, npop;
+ unsigned tmp, npop, dispsz, loop;
+
+ /* we don't fix up userspace misalignment faults */
+ if (user_mode(regs))
+ goto bus_error;
- kdebug("MISALIGN at %lx\n", regs->pc);
+ sp = (unsigned long) regs + sizeof(*regs);
- if (in_interrupt())
- die("Misalignment trap in interrupt context", regs, code);
+ kdebug("==>misalignment({pc=%lx,sp=%lx})", regs->pc, sp);
if (regs->epsw & EPSW_IE)
asm volatile("or %0,epsw" : : "i"(EPSW_IE));
@@ -294,8 +353,8 @@ asmlinkage void misalignment(struct pt_regs *regs, enum exception_code code)
opcode = byte;
noc = 8;
- for (pop = mn10300_opcodes; pop->name; pop++) {
- npop = log2(pop->opcode | pop->opmask);
+ for (pop = mn10300_opcodes; pop->name[0]; pop++) {
+ npop = ilog2(pop->opcode | pop->opmask);
if (npop <= 0 || npop > 31)
continue;
npop = (npop + 8) & ~7;
@@ -328,15 +387,15 @@ asmlinkage void misalignment(struct pt_regs *regs, enum exception_code code)
}
/* didn't manage to find a fixup */
- if (!user_mode(regs))
- printk(KERN_CRIT "MISALIGN: %lx: unsupported instruction %x\n",
- regs->pc, opcode);
+ printk(KERN_CRIT "MISALIGN: %lx: unsupported instruction %x\n",
+ regs->pc, opcode);
failed:
set_fs(seg);
if (die_if_no_fixup("misalignment error", regs, code))
return;
+bus_error:
info.si_signo = SIGBUS;
info.si_errno = 0;
info.si_code = BUS_ADRALN;
@@ -346,31 +405,27 @@ failed:
/* error reading opcodes */
fetch_error:
- if (!user_mode(regs))
- printk(KERN_CRIT
- "MISALIGN: %p: fault whilst reading instruction data\n",
- pc);
+ printk(KERN_CRIT
+ "MISALIGN: %p: fault whilst reading instruction data\n",
+ pc);
goto failed;
bad_addr_mode:
- if (!user_mode(regs))
- printk(KERN_CRIT
- "MISALIGN: %lx: unsupported addressing mode %x\n",
- regs->pc, opcode);
+ printk(KERN_CRIT
+ "MISALIGN: %lx: unsupported addressing mode %x\n",
+ regs->pc, opcode);
goto failed;
bad_reg_mode:
- if (!user_mode(regs))
- printk(KERN_CRIT
- "MISALIGN: %lx: unsupported register mode %x\n",
- regs->pc, opcode);
+ printk(KERN_CRIT
+ "MISALIGN: %lx: unsupported register mode %x\n",
+ regs->pc, opcode);
goto failed;
unsupported_instruction:
- if (!user_mode(regs))
- printk(KERN_CRIT
- "MISALIGN: %lx: unsupported instruction %x (%s)\n",
- regs->pc, opcode, pop->name);
+ printk(KERN_CRIT
+ "MISALIGN: %lx: unsupported instruction %x (%s)\n",
+ regs->pc, opcode, pop->name);
goto failed;
transfer_failed:
@@ -391,7 +446,7 @@ transfer_failed:
/* we matched the opcode */
found_opcode:
- kdebug("MISALIGN: %lx: %x==%x { %x, %x }\n",
+ kdebug("%lx: %x==%x { %x, %x }",
regs->pc, opcode, pop->opcode, pop->params[0], pop->params[1]);
tmp = format_tbl[pop->format].opsz;
@@ -406,106 +461,108 @@ found_opcode:
/* grab the extra displacement (note it's LSB first) */
disp = 0;
- tmp = format_tbl[pop->format].dispsz >> 3;
- while (tmp > 0) {
- tmp--;
- disp <<= 8;
-
+ dispsz = format_tbl[pop->format].dispsz;
+ for (loop = 0; loop < dispsz; loop += 8) {
pc++;
if (__get_user(byte, pc) != 0)
goto fetch_error;
- disp |= byte;
+ disp |= byte << loop;
+ kdebug("{%p} disp[%02x]=%02x", pc, loop, byte);
}
+ kdebug("disp=%lx", disp);
+
set_fs(KERNEL_XDS);
- if (fixup || regs->epsw & EPSW_nSL)
+ if (fixup)
set_fs(seg);
tmp = (pop->params[0] ^ pop->params[1]) & 0x80000000;
if (!tmp) {
- if (!user_mode(regs))
- printk(KERN_CRIT
- "MISALIGN: %lx:"
- " insn not move to/from memory %x\n",
- regs->pc, opcode);
+ printk(KERN_CRIT
+ "MISALIGN: %lx: insn not move to/from memory %x\n",
+ regs->pc, opcode);
goto failed;
}
+ /* determine the data transfer size of the move */
+ if (pop->name[3] == 0 || /* "mov" */
+ pop->name[4] == 'l') /* mov_lcc */
+ inc = datasz = 4;
+ else if (pop->name[3] == 'h') /* movhu */
+ inc = datasz = 2;
+ else
+ goto unsupported_instruction;
+
if (pop->params[0] & 0x80000000) {
/* move memory to register */
- if (!misalignment_addr(registers, pop->params[0], opcode, disp,
- &address, &postinc))
+ if (!misalignment_addr(registers, sp,
+ pop->params[0], opcode, disp,
+ &address, &postinc, &inc))
goto bad_addr_mode;
if (!misalignment_reg(registers, pop->params[1], opcode, disp,
&store))
goto bad_reg_mode;
- if (strcmp(pop->name, "mov") == 0) {
- kdebug("FIXUP: mov (%p),DARn\n", address);
- if (copy_from_user(&data, (void *) address, 4) != 0)
- goto transfer_failed;
- if (pop->params[0] & 0x1000000)
- *postinc += 4;
- } else if (strcmp(pop->name, "movhu") == 0) {
- kdebug("FIXUP: movhu (%p),DARn\n", address);
- data = 0;
- if (copy_from_user(&data, (void *) address, 2) != 0)
- goto transfer_failed;
- if (pop->params[0] & 0x1000000)
- *postinc += 2;
- } else {
- goto unsupported_instruction;
+ kdebug("mov%u (%p),DARn", datasz, address);
+ if (copy_from_user(&data, (void *) address, datasz) != 0)
+ goto transfer_failed;
+ if (pop->params[0] & 0x1000000) {
+ kdebug("inc=%lx", inc);
+ *postinc += inc;
}
*store = data;
+ kdebug("loaded %lx", data);
} else {
/* move register to memory */
if (!misalignment_reg(registers, pop->params[0], opcode, disp,
&store))
goto bad_reg_mode;
- if (!misalignment_addr(registers, pop->params[1], opcode, disp,
- &address, &postinc))
+ if (!misalignment_addr(registers, sp,
+ pop->params[1], opcode, disp,
+ &address, &postinc, &inc))
goto bad_addr_mode;
data = *store;
- if (strcmp(pop->name, "mov") == 0) {
- kdebug("FIXUP: mov %lx,(%p)\n", data, address);
- if (copy_to_user((void *) address, &data, 4) != 0)
- goto transfer_failed;
- if (pop->params[1] & 0x1000000)
- *postinc += 4;
- } else if (strcmp(pop->name, "movhu") == 0) {
- kdebug("FIXUP: movhu %hx,(%p)\n",
- (uint16_t) data, address);
- if (copy_to_user((void *) address, &data, 2) != 0)
- goto transfer_failed;
- if (pop->params[1] & 0x1000000)
- *postinc += 2;
- } else {
- goto unsupported_instruction;
- }
+ kdebug("mov%u %lx,(%p)", datasz, data, address);
+ if (copy_to_user((void *) address, &data, datasz) != 0)
+ goto transfer_failed;
+ if (pop->params[1] & 0x1000000)
+ *postinc += inc;
}
tmp = format_tbl[pop->format].opsz + format_tbl[pop->format].dispsz;
regs->pc += tmp >> 3;
+ /* handle MOV_Lcc, which are currently the only FMT_D10 insns that
+ * access memory */
+ if (pop->format == FMT_D10)
+ misalignment_MOV_Lcc(regs, opcode);
+
set_fs(seg);
- return;
}
/*
* determine the address that was being accessed
*/
-static int misalignment_addr(unsigned long *registers, unsigned params,
- unsigned opcode, unsigned disp,
- void **_address, unsigned long **_postinc)
+static int misalignment_addr(unsigned long *registers, unsigned long sp,
+ unsigned params, unsigned opcode,
+ unsigned long disp,
+ void **_address, unsigned long **_postinc,
+ unsigned long *_inc)
{
unsigned long *postinc = NULL, address = 0, tmp;
- params &= 0x7fffffff;
+ if (!(params & 0x1000000)) {
+ kdebug("noinc");
+ *_inc = 0;
+ _inc = NULL;
+ }
+
+ params &= 0x00ffffff;
do {
switch (params & 0xff) {
@@ -514,11 +571,11 @@ static int misalignment_addr(unsigned long *registers, unsigned params,
address += *postinc;
break;
case DM1:
- postinc = &registers[Dreg_index[opcode >> 2 & 0x0c]];
+ postinc = &registers[Dreg_index[opcode >> 2 & 0x03]];
address += *postinc;
break;
case DM2:
- postinc = &registers[Dreg_index[opcode >> 4 & 0x30]];
+ postinc = &registers[Dreg_index[opcode >> 4 & 0x03]];
address += *postinc;
break;
case AM0:
@@ -526,11 +583,11 @@ static int misalignment_addr(unsigned long *registers, unsigned params,
address += *postinc;
break;
case AM1:
- postinc = &registers[Areg_index[opcode >> 2 & 0x0c]];
+ postinc = &registers[Areg_index[opcode >> 2 & 0x03]];
address += *postinc;
break;
case AM2:
- postinc = &registers[Areg_index[opcode >> 4 & 0x30]];
+ postinc = &registers[Areg_index[opcode >> 4 & 0x03]];
address += *postinc;
break;
case RM0:
@@ -561,33 +618,53 @@ static int misalignment_addr(unsigned long *registers, unsigned params,
postinc = &registers[Rreg_index[disp >> 4 & 0x0f]];
address += *postinc;
break;
+ case SP:
+ address += sp;
+ break;
+ /* displacements are either to be added to the address
+ * before use, or, in the case of post-inc addressing,
+ * to be added into the base register after use */
case SD8:
case SIMM8:
- address += (int32_t) (int8_t) (disp & 0xff);
- break;
+ disp = (long) (int8_t) (disp & 0xff);
+ goto displace_or_inc;
case SD16:
- address += (int32_t) (int16_t) (disp & 0xffff);
- break;
+ disp = (long) (int16_t) (disp & 0xffff);
+ goto displace_or_inc;
case SD24:
tmp = disp << 8;
asm("asr 8,%0" : "=r"(tmp) : "0"(tmp));
- address += tmp;
- break;
+ disp = (long) tmp;
+ goto displace_or_inc;
case SIMM4_2:
tmp = opcode >> 4 & 0x0f;
tmp <<= 28;
asm("asr 28,%0" : "=r"(tmp) : "0"(tmp));
- address += tmp;
- break;
+ disp = (long) tmp;
+ goto displace_or_inc;
+ case IMM8:
+ disp &= 0x000000ff;
+ goto displace_or_inc;
+ case IMM16:
+ disp &= 0x0000ffff;
+ goto displace_or_inc;
case IMM24:
- address += disp & 0x00ffffff;
- break;
+ disp &= 0x00ffffff;
+ goto displace_or_inc;
case IMM32:
+ case IMM32_MEM:
case IMM32_HIGH8:
- address += disp;
+ case IMM32_HIGH8_MEM:
+ displace_or_inc:
+ kdebug("%s %lx", _inc ? "incr" : "disp", disp);
+ if (!_inc)
+ address += disp;
+ else
+ *_inc = disp;
break;
default:
+ BUG();
return 0;
}
} while ((params >>= 8));
@@ -601,7 +678,7 @@ static int misalignment_addr(unsigned long *registers, unsigned params,
* determine the register that is acting as source/dest
*/
static int misalignment_reg(unsigned long *registers, unsigned params,
- unsigned opcode, unsigned disp,
+ unsigned opcode, unsigned long disp,
unsigned long **_register)
{
params &= 0x7fffffff;
@@ -654,8 +731,239 @@ static int misalignment_reg(unsigned long *registers, unsigned params,
break;
default:
+ BUG();
return 0;
}
return 1;
}
+
+/*
+ * handle the conditional loop part of the move-and-loop instructions
+ */
+static void misalignment_MOV_Lcc(struct pt_regs *regs, uint32_t opcode)
+{
+ unsigned long epsw = regs->epsw;
+ unsigned long NxorV;
+
+ kdebug("MOV_Lcc %x [flags=%lx]", opcode, epsw & 0xf);
+
+ /* calculate N^V and shift onto the same bit position as Z */
+ NxorV = ((epsw >> 3) ^ epsw >> 1) & 1;
+
+ switch (opcode & 0xf) {
+ case 0x0: /* MOV_LLT: N^V */
+ if (NxorV)
+ goto take_the_loop;
+ return;
+ case 0x1: /* MOV_LGT: ~(Z or (N^V))*/
+ if (!((epsw & EPSW_FLAG_Z) | NxorV))
+ goto take_the_loop;
+ return;
+ case 0x2: /* MOV_LGE: ~(N^V) */
+ if (!NxorV)
+ goto take_the_loop;
+ return;
+ case 0x3: /* MOV_LLE: Z or (N^V) */
+ if ((epsw & EPSW_FLAG_Z) | NxorV)
+ goto take_the_loop;
+ return;
+
+ case 0x4: /* MOV_LCS: C */
+ if (epsw & EPSW_FLAG_C)
+ goto take_the_loop;
+ return;
+ case 0x5: /* MOV_LHI: ~(C or Z) */
+ if (!(epsw & (EPSW_FLAG_C | EPSW_FLAG_Z)))
+ goto take_the_loop;
+ return;
+ case 0x6: /* MOV_LCC: ~C */
+ if (!(epsw & EPSW_FLAG_C))
+ goto take_the_loop;
+ return;
+ case 0x7: /* MOV_LLS: C or Z */
+ if (epsw & (EPSW_FLAG_C | EPSW_FLAG_Z))
+ goto take_the_loop;
+ return;
+
+ case 0x8: /* MOV_LEQ: Z */
+ if (epsw & EPSW_FLAG_Z)
+ goto take_the_loop;
+ return;
+ case 0x9: /* MOV_LNE: ~Z */
+ if (!(epsw & EPSW_FLAG_Z))
+ goto take_the_loop;
+ return;
+ case 0xa: /* MOV_LRA: always */
+ goto take_the_loop;
+
+ default:
+ BUG();
+ }
+
+take_the_loop:
+ /* wind the PC back to just after the SETLB insn */
+ kdebug("loop LAR=%lx", regs->lar);
+ regs->pc = regs->lar - 4;
+}
+
+/*
+ * misalignment handler tests
+ */
+#ifdef CONFIG_TEST_MISALIGNMENT_HANDLER
+static u8 __initdata testbuf[512] __attribute__((aligned(16))) = {
+ [257] = 0x11,
+ [258] = 0x22,
+ [259] = 0x33,
+ [260] = 0x44,
+};
+
+#define ASSERTCMP(X, OP, Y) \
+do { \
+ if (unlikely(!((X) OP (Y)))) { \
+ printk(KERN_ERR "\n"); \
+ printk(KERN_ERR "MISALIGN: Assertion failed at line %u\n", \
+ __LINE__); \
+ printk(KERN_ERR "0x%lx " #OP " 0x%lx is false\n", \
+ (unsigned long)(X), (unsigned long)(Y)); \
+ BUG(); \
+ } \
+} while(0)
+
+static int __init test_misalignment(void)
+{
+ register void *r asm("e0");
+ register u32 y asm("e1");
+ void *p = testbuf, *q;
+ u32 tmp, tmp2, x;
+
+ printk(KERN_NOTICE "==>test_misalignment() [testbuf=%p]\n", p);
+ p++;
+
+ printk(KERN_NOTICE "___ MOV (Am),Dn ___\n");
+ q = p + 256;
+ asm volatile("mov (%0),%1" : "+a"(q), "=d"(x));
+ ASSERTCMP(q, ==, p + 256);
+ ASSERTCMP(x, ==, 0x44332211);
+
+ printk(KERN_NOTICE "___ MOV (256,Am),Dn ___\n");
+ q = p;
+ asm volatile("mov (256,%0),%1" : "+a"(q), "=d"(x));
+ ASSERTCMP(q, ==, p);
+ ASSERTCMP(x, ==, 0x44332211);
+
+ printk(KERN_NOTICE "___ MOV (Di,Am),Dn ___\n");
+ tmp = 256;
+ q = p;
+ asm volatile("mov (%2,%0),%1" : "+a"(q), "=d"(x), "+d"(tmp));
+ ASSERTCMP(q, ==, p);
+ ASSERTCMP(x, ==, 0x44332211);
+ ASSERTCMP(tmp, ==, 256);
+
+ printk(KERN_NOTICE "___ MOV (256,Rm),Rn ___\n");
+ r = p;
+ asm volatile("mov (256,%0),%1" : "+r"(r), "=r"(y));
+ ASSERTCMP(r, ==, p);
+ ASSERTCMP(y, ==, 0x44332211);
+
+ printk(KERN_NOTICE "___ MOV (Rm+),Rn ___\n");
+ r = p + 256;
+ asm volatile("mov (%0+),%1" : "+r"(r), "=r"(y));
+ ASSERTCMP(r, ==, p + 256 + 4);
+ ASSERTCMP(y, ==, 0x44332211);
+
+ printk(KERN_NOTICE "___ MOV (Rm+,8),Rn ___\n");
+ r = p + 256;
+ asm volatile("mov (%0+,8),%1" : "+r"(r), "=r"(y));
+ ASSERTCMP(r, ==, p + 256 + 8);
+ ASSERTCMP(y, ==, 0x44332211);
+
+ printk(KERN_NOTICE "___ MOV (7,SP),Rn ___\n");
+ asm volatile(
+ "add -16,sp \n"
+ "mov +0x11,%0 \n"
+ "movbu %0,(7,sp) \n"
+ "mov +0x22,%0 \n"
+ "movbu %0,(8,sp) \n"
+ "mov +0x33,%0 \n"
+ "movbu %0,(9,sp) \n"
+ "mov +0x44,%0 \n"
+ "movbu %0,(10,sp) \n"
+ "mov (7,sp),%1 \n"
+ "add +16,sp \n"
+ : "+a"(q), "=d"(x));
+ ASSERTCMP(x, ==, 0x44332211);
+
+ printk(KERN_NOTICE "___ MOV (259,SP),Rn ___\n");
+ asm volatile(
+ "add -264,sp \n"
+ "mov +0x11,%0 \n"
+ "movbu %0,(259,sp) \n"
+ "mov +0x22,%0 \n"
+ "movbu %0,(260,sp) \n"
+ "mov +0x33,%0 \n"
+ "movbu %0,(261,sp) \n"
+ "mov +0x55,%0 \n"
+ "movbu %0,(262,sp) \n"
+ "mov (259,sp),%1 \n"
+ "add +264,sp \n"
+ : "+d"(tmp), "=d"(x));
+ ASSERTCMP(x, ==, 0x55332211);
+
+ printk(KERN_NOTICE "___ MOV (260,SP),Rn ___\n");
+ asm volatile(
+ "add -264,sp \n"
+ "mov +0x11,%0 \n"
+ "movbu %0,(260,sp) \n"
+ "mov +0x22,%0 \n"
+ "movbu %0,(261,sp) \n"
+ "mov +0x33,%0 \n"
+ "movbu %0,(262,sp) \n"
+ "mov +0x55,%0 \n"
+ "movbu %0,(263,sp) \n"
+ "mov (260,sp),%1 \n"
+ "add +264,sp \n"
+ : "+d"(tmp), "=d"(x));
+ ASSERTCMP(x, ==, 0x55332211);
+
+
+ printk(KERN_NOTICE "___ MOV_LNE ___\n");
+ tmp = 1;
+ tmp2 = 2;
+ q = p + 256;
+ asm volatile(
+ "setlb \n"
+ "mov %2,%3 \n"
+ "mov %1,%2 \n"
+ "cmp +0,%1 \n"
+ "mov_lne (%0+,4),%1"
+ : "+r"(q), "+d"(tmp), "+d"(tmp2), "=d"(x)
+ :
+ : "cc");
+ ASSERTCMP(q, ==, p + 256 + 12);
+ ASSERTCMP(x, ==, 0x44332211);
+
+ printk(KERN_NOTICE "___ MOV in SETLB ___\n");
+ tmp = 1;
+ tmp2 = 2;
+ q = p + 256;
+ asm volatile(
+ "setlb \n"
+ "mov %1,%3 \n"
+ "mov (%0+),%1 \n"
+ "cmp +0,%1 \n"
+ "lne "
+ : "+a"(q), "+d"(tmp), "+d"(tmp2), "=d"(x)
+ :
+ : "cc");
+
+ ASSERTCMP(q, ==, p + 256 + 8);
+ ASSERTCMP(x, ==, 0x44332211);
+
+ printk(KERN_NOTICE "<==test_misalignment()\n");
+ return 0;
+}
+
+arch_initcall(test_misalignment);
+
+#endif /* CONFIG_TEST_MISALIGNMENT_HANDLER */
diff --git a/arch/parisc/include/asm/parisc-device.h b/arch/parisc/include/asm/parisc-device.h
index 7aa13f2add7..9afdad6c2ff 100644
--- a/arch/parisc/include/asm/parisc-device.h
+++ b/arch/parisc/include/asm/parisc-device.h
@@ -42,9 +42,9 @@ struct parisc_driver {
#define to_parisc_driver(d) container_of(d, struct parisc_driver, drv)
#define parisc_parent(d) to_parisc_device(d->dev.parent)
-static inline char *parisc_pathname(struct parisc_device *d)
+static inline const char *parisc_pathname(struct parisc_device *d)
{
- return d->dev.bus_id;
+ return dev_name(&d->dev);
}
static inline void
diff --git a/arch/parisc/include/asm/posix_types.h b/arch/parisc/include/asm/posix_types.h
index bb725a6630b..00da29a340b 100644
--- a/arch/parisc/include/asm/posix_types.h
+++ b/arch/parisc/include/asm/posix_types.h
@@ -24,13 +24,12 @@ typedef int __kernel_daddr_t;
typedef unsigned long __kernel_size_t;
typedef long __kernel_ssize_t;
typedef long __kernel_ptrdiff_t;
-typedef long __kernel_time_t;
#else
typedef unsigned int __kernel_size_t;
typedef int __kernel_ssize_t;
typedef int __kernel_ptrdiff_t;
-typedef long __kernel_time_t;
#endif
+typedef long __kernel_time_t;
typedef char * __kernel_caddr_t;
typedef unsigned short __kernel_uid16_t;
diff --git a/arch/parisc/include/asm/ptrace.h b/arch/parisc/include/asm/ptrace.h
index afa5333187b..302f68dc889 100644
--- a/arch/parisc/include/asm/ptrace.h
+++ b/arch/parisc/include/asm/ptrace.h
@@ -47,8 +47,6 @@ struct pt_regs {
#define task_regs(task) ((struct pt_regs *) ((char *)(task) + TASK_REGS))
-#define __ARCH_WANT_COMPAT_SYS_PTRACE
-
struct task_struct;
#define arch_has_single_step() 1
void user_disable_single_step(struct task_struct *task);
diff --git a/arch/parisc/include/asm/smp.h b/arch/parisc/include/asm/smp.h
index 398cdbaf4e5..409e698f436 100644
--- a/arch/parisc/include/asm/smp.h
+++ b/arch/parisc/include/asm/smp.h
@@ -44,8 +44,6 @@ extern void arch_send_call_function_ipi(cpumask_t mask);
#define PROC_CHANGE_PENALTY 15 /* Schedule penalty */
-extern unsigned long cpu_present_mask;
-
#define raw_smp_processor_id() (current_thread_info()->cpu)
#else /* CONFIG_SMP */
diff --git a/arch/parisc/include/asm/tlbflush.h b/arch/parisc/include/asm/tlbflush.h
index b72ec66db69..1f6fd4fc05b 100644
--- a/arch/parisc/include/asm/tlbflush.h
+++ b/arch/parisc/include/asm/tlbflush.h
@@ -44,9 +44,12 @@ static inline void flush_tlb_mm(struct mm_struct *mm)
{
BUG_ON(mm == &init_mm); /* Should never happen */
-#ifdef CONFIG_SMP
+#if 1 || defined(CONFIG_SMP)
flush_tlb_all();
#else
+ /* FIXME: currently broken, causing space id and protection ids
+ * to go out of sync, resulting in faults on userspace accesses.
+ */
if (mm) {
if (mm->context != 0)
free_sid(mm->context);
diff --git a/arch/parisc/kernel/drivers.c b/arch/parisc/kernel/drivers.c
index 2ca654bd632..884b7ce16a3 100644
--- a/arch/parisc/kernel/drivers.c
+++ b/arch/parisc/kernel/drivers.c
@@ -43,7 +43,7 @@ struct hppa_dma_ops *hppa_dma_ops __read_mostly;
EXPORT_SYMBOL(hppa_dma_ops);
static struct device root = {
- .bus_id = "parisc",
+ .init_name = "parisc",
};
static inline int check_dev(struct device *dev)
@@ -393,7 +393,8 @@ EXPORT_SYMBOL(print_pci_hwpath);
static void setup_bus_id(struct parisc_device *padev)
{
struct hardware_path path;
- char *output = padev->dev.bus_id;
+ char name[20];
+ char *output = name;
int i;
get_node_path(padev->dev.parent, &path);
@@ -404,6 +405,7 @@ static void setup_bus_id(struct parisc_device *padev)
output += sprintf(output, "%u:", (unsigned char) path.bc[i]);
}
sprintf(output, "%u", (unsigned char) padev->hw_path);
+ dev_set_name(&padev->dev, name);
}
struct parisc_device * create_tree_node(char id, struct device *parent)
diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c
index 90904f9dfc5..927db3668b6 100644
--- a/arch/parisc/kernel/ptrace.c
+++ b/arch/parisc/kernel/ptrace.c
@@ -183,10 +183,10 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
* being 64 bit in both cases.
*/
-static long translate_usr_offset(long offset)
+static compat_ulong_t translate_usr_offset(compat_ulong_t offset)
{
if (offset < 0)
- return -1;
+ return sizeof(struct pt_regs);
else if (offset <= 32*4) /* gr[0..31] */
return offset * 2 + 4;
else if (offset <= 32*4+32*8) /* gr[0..31] + fr[0..31] */
@@ -194,7 +194,7 @@ static long translate_usr_offset(long offset)
else if (offset < sizeof(struct pt_regs)/2 + 32*4)
return offset * 2 + 4 - 32*8;
else
- return -1;
+ return sizeof(struct pt_regs);
}
long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
@@ -209,7 +209,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
if (addr & (sizeof(compat_uint_t)-1))
break;
addr = translate_usr_offset(addr);
- if (addr < 0)
+ if (addr >= sizeof(struct pt_regs))
break;
tmp = *(compat_uint_t *) ((char *) task_regs(child) + addr);
@@ -236,7 +236,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
if (addr & (sizeof(compat_uint_t)-1))
break;
addr = translate_usr_offset(addr);
- if (addr < 0)
+ if (addr >= sizeof(struct pt_regs))
break;
if (addr >= PT_FR0 && addr <= PT_FR31 + 4) {
/* Special case, fp regs are 64 bits anyway */
diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c
index 675f1d098f0..4c771cd580e 100644
--- a/arch/parisc/kernel/traps.c
+++ b/arch/parisc/kernel/traps.c
@@ -24,7 +24,6 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/console.h>
-#include <linux/kallsyms.h>
#include <linux/bug.h>
#include <asm/assembly.h>
@@ -51,7 +50,7 @@
DEFINE_SPINLOCK(pa_dbit_lock);
#endif
-void parisc_show_stack(struct task_struct *t, unsigned long *sp,
+static void parisc_show_stack(struct task_struct *task, unsigned long *sp,
struct pt_regs *regs);
static int printbinary(char *buf, unsigned long x, int nbits)
@@ -121,18 +120,19 @@ static void print_fr(char *level, struct pt_regs *regs)
void show_regs(struct pt_regs *regs)
{
- int i;
+ int i, user;
char *level;
unsigned long cr30, cr31;
- level = user_mode(regs) ? KERN_DEBUG : KERN_CRIT;
+ user = user_mode(regs);
+ level = user ? KERN_DEBUG : KERN_CRIT;
print_gr(level, regs);
for (i = 0; i < 8; i += 4)
PRINTREGS(level, regs->sr, "sr", RFMT, i);
- if (user_mode(regs))
+ if (user)
print_fr(level, regs);
cr30 = mfctl(30);
@@ -145,14 +145,18 @@ void show_regs(struct pt_regs *regs)
printk("%s CPU: %8d CR30: " RFMT " CR31: " RFMT "\n",
level, current_thread_info()->cpu, cr30, cr31);
printk("%s ORIG_R28: " RFMT "\n", level, regs->orig_r28);
- printk(level);
- print_symbol(" IAOQ[0]: %s\n", regs->iaoq[0]);
- printk(level);
- print_symbol(" IAOQ[1]: %s\n", regs->iaoq[1]);
- printk(level);
- print_symbol(" RP(r2): %s\n", regs->gr[2]);
-
- parisc_show_stack(current, NULL, regs);
+
+ if (user) {
+ printk("%s IAOQ[0]: " RFMT "\n", level, regs->iaoq[0]);
+ printk("%s IAOQ[1]: " RFMT "\n", level, regs->iaoq[1]);
+ printk("%s RP(r2): " RFMT "\n", level, regs->gr[2]);
+ } else {
+ printk("%s IAOQ[0]: %pS\n", level, (void *) regs->iaoq[0]);
+ printk("%s IAOQ[1]: %pS\n", level, (void *) regs->iaoq[1]);
+ printk("%s RP(r2): %pS\n", level, (void *) regs->gr[2]);
+
+ parisc_show_stack(current, NULL, regs);
+ }
}
@@ -173,20 +177,15 @@ static void do_show_stack(struct unwind_frame_info *info)
break;
if (__kernel_text_address(info->ip)) {
- printk("%s [<" RFMT ">] ", (i&0x3)==1 ? KERN_CRIT : "", info->ip);
-#ifdef CONFIG_KALLSYMS
- print_symbol("%s\n", info->ip);
-#else
- if ((i & 0x03) == 0)
- printk("\n");
-#endif
+ printk(KERN_CRIT " [<" RFMT ">] %pS\n",
+ info->ip, (void *) info->ip);
i++;
}
}
- printk("\n");
+ printk(KERN_CRIT "\n");
}
-void parisc_show_stack(struct task_struct *task, unsigned long *sp,
+static void parisc_show_stack(struct task_struct *task, unsigned long *sp,
struct pt_regs *regs)
{
struct unwind_frame_info info;
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index 8fc6d72849a..3d3daa67429 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -41,6 +41,7 @@ $(obj)/4xx.o: BOOTCFLAGS += -mcpu=405
$(obj)/ebony.o: BOOTCFLAGS += -mcpu=405
$(obj)/cuboot-taishan.o: BOOTCFLAGS += -mcpu=405
$(obj)/cuboot-katmai.o: BOOTCFLAGS += -mcpu=405
+$(obj)/cuboot-acadia.o: BOOTCFLAGS += -mcpu=405
$(obj)/treeboot-walnut.o: BOOTCFLAGS += -mcpu=405
$(obj)/virtex405-head.o: BOOTAFLAGS += -mcpu=405
diff --git a/arch/powerpc/boot/dts/mpc832x_rdb.dts b/arch/powerpc/boot/dts/mpc832x_rdb.dts
index 226ff066652..dea30910c13 100644
--- a/arch/powerpc/boot/dts/mpc832x_rdb.dts
+++ b/arch/powerpc/boot/dts/mpc832x_rdb.dts
@@ -18,8 +18,8 @@
#size-cells = <1>;
aliases {
- ethernet0 = &enet0;
- ethernet1 = &enet1;
+ ethernet0 = &enet1;
+ ethernet1 = &enet0;
serial0 = &serial0;
serial1 = &serial1;
pci0 = &pci0;
diff --git a/arch/powerpc/boot/dts/mpc8349emitx.dts b/arch/powerpc/boot/dts/mpc8349emitx.dts
index 2c9d54a35bc..4bdbaf4993a 100644
--- a/arch/powerpc/boot/dts/mpc8349emitx.dts
+++ b/arch/powerpc/boot/dts/mpc8349emitx.dts
@@ -91,6 +91,14 @@
interrupts = <18 0x8>;
interrupt-parent = <&ipic>;
};
+
+ mcu_pio: mcu@a {
+ #gpio-cells = <2>;
+ compatible = "fsl,mc9s08qg8-mpc8349emitx",
+ "fsl,mcu-mpc8349emitx";
+ reg = <0x0a>;
+ gpio-controller;
+ };
};
spi@7000 {
@@ -139,14 +147,6 @@
interrupt-parent = <&ipic>;
interrupts = <71 8>;
};
-
- mcu_pio: mcu@a {
- #gpio-cells = <2>;
- compatible = "fsl,mc9s08qg8-mpc8349emitx",
- "fsl,mcu-mpc8349emitx";
- reg = <0x0a>;
- gpio-controller;
- };
};
usb@22000 {
diff --git a/arch/powerpc/boot/dts/mpc8572ds.dts b/arch/powerpc/boot/dts/mpc8572ds.dts
index cadd4652a69..5c69b2fafd3 100644
--- a/arch/powerpc/boot/dts/mpc8572ds.dts
+++ b/arch/powerpc/boot/dts/mpc8572ds.dts
@@ -90,7 +90,7 @@
compatible = "fsl,mpc8572-l2-cache-controller";
reg = <0x20000 0x1000>;
cache-line-size = <32>; // 32 bytes
- cache-size = <0x80000>; // L2, 512K
+ cache-size = <0x100000>; // L2, 1M
interrupt-parent = <&mpic>;
interrupts = <16 2>;
};
diff --git a/arch/powerpc/configs/40x/virtex_defconfig b/arch/powerpc/configs/40x/virtex_defconfig
new file mode 100644
index 00000000000..9a9350ded29
--- /dev/null
+++ b/arch/powerpc/configs/40x/virtex_defconfig
@@ -0,0 +1,1176 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.28-rc4
+# Fri Nov 14 10:49:16 2008
+#
+# CONFIG_PPC64 is not set
+
+#
+# Processor support
+#
+# CONFIG_6xx is not set
+# CONFIG_PPC_85xx is not set
+# CONFIG_PPC_8xx is not set
+CONFIG_40x=y
+# CONFIG_44x is not set
+# CONFIG_E200 is not set
+CONFIG_4xx=y
+# CONFIG_PPC_MM_SLICES is not set
+CONFIG_NOT_COHERENT_CACHE=y
+CONFIG_PPC32=y
+CONFIG_WORD_SIZE=32
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+CONFIG_MMU=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_HARDIRQS=y
+# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+CONFIG_IRQ_PER_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_GPIO=y
+# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+CONFIG_PPC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_OF=y
+CONFIG_PPC_UDBG_16550=y
+# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
+# CONFIG_DEFAULT_UIMAGE is not set
+CONFIG_PPC_DCR_NATIVE=y
+# CONFIG_PPC_DCR_MMIO is not set
+CONFIG_PPC_DCR=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+# CONFIG_GROUP_SCHED is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+# CONFIG_EMBEDDED is not set
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_COMPAT_BRK=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_CLASSIC_RCU=y
+# CONFIG_FREEZER is not set
+# CONFIG_PPC4xx_PCI_EXPRESS is not set
+
+#
+# Platform support
+#
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
+# CONFIG_PPC4xx_GPIO is not set
+CONFIG_XILINX_VIRTEX=y
+# CONFIG_ACADIA is not set
+# CONFIG_EP405 is not set
+# CONFIG_HCU4 is not set
+# CONFIG_KILAUEA is not set
+# CONFIG_MAKALU is not set
+# CONFIG_WALNUT is not set
+CONFIG_XILINX_VIRTEX_GENERIC_BOARD=y
+# CONFIG_PPC40x_SIMPLE is not set
+CONFIG_XILINX_VIRTEX_II_PRO=y
+CONFIG_XILINX_VIRTEX_4_FX=y
+CONFIG_IBM405_ERR77=y
+CONFIG_IBM405_ERR51=y
+# CONFIG_IPIC is not set
+# CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_FSL_ULI1575 is not set
+
+#
+# Kernel options
+#
+# CONFIG_HIGHMEM is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+# CONFIG_SCHED_HRTICK is not set
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+# CONFIG_PREEMPT_RCU is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_MATH_EMULATION=y
+# CONFIG_IOMMU_HELPER is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_HAS_WALK_MEMORY=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
+CONFIG_RESOURCES_64BIT=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_PROC_DEVICETREE=y
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE=""
+CONFIG_EXTRA_TARGETS=""
+# CONFIG_PM is not set
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_ZONE_DMA=y
+CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_4xx_SOC=y
+CONFIG_PPC_PCI_CHOICE=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_SYSCALL=y
+# CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
+CONFIG_PCI_LEGACY=y
+# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCCARD is not set
+# CONFIG_HOTPLUG_PCI is not set
+# CONFIG_HAS_RAPIDIO is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_PAGE_OFFSET=0xc0000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_PHYSICAL_START=0x00000000
+CONFIG_TASK_SIZE=0xc0000000
+CONFIG_CONSISTENT_START=0xff100000
+CONFIG_CONSISTENT_SIZE=0x00200000
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK_QUEUE is not set
+# CONFIG_NETFILTER_NETLINK_LOG is not set
+# CONFIG_NF_CONNTRACK is not set
+CONFIG_NETFILTER_XTABLES=m
+# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+# CONFIG_NETFILTER_XT_TARGET_MARK is not set
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set
+# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
+# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_MAC is not set
+# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
+# CONFIG_NETFILTER_XT_MATCH_OWNER is not set
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
+# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_RECENT is not set
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
+# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_TIME is not set
+# CONFIG_NETFILTER_XT_MATCH_U32 is not set
+# CONFIG_IP_VS is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_NF_DEFRAG_IPV4 is not set
+# CONFIG_IP_NF_QUEUE is not set
+CONFIG_IP_NF_IPTABLES=m
+# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+# CONFIG_IP_NF_MATCH_AH is not set
+# CONFIG_IP_NF_MATCH_ECN is not set
+# CONFIG_IP_NF_MATCH_TTL is not set
+CONFIG_IP_NF_FILTER=m
+# CONFIG_IP_NF_TARGET_REJECT is not set
+# CONFIG_IP_NF_TARGET_LOG is not set
+# CONFIG_IP_NF_TARGET_ULOG is not set
+CONFIG_IP_NF_MANGLE=m
+# CONFIG_IP_NF_TARGET_ECN is not set
+# CONFIG_IP_NF_TARGET_TTL is not set
+# CONFIG_IP_NF_RAW is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+
+#
+# IPv6: Netfilter Configuration
+#
+# CONFIG_IP6_NF_QUEUE is not set
+# CONFIG_IP6_NF_IPTABLES is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_PHONET is not set
+CONFIG_WIRELESS=y
+# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_OLD_REGULATORY=y
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+# CONFIG_MTD is not set
+CONFIG_OF_DEVICE=y
+CONFIG_OF_GPIO=y
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=8192
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_XILINX_SYSACE=y
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_PHANTOM is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# Enable only one of the two stacks, unless you know what you are doing
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_IEEE1394 is not set
+# CONFIG_I2O is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_ARCNET is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_IBM_NEW_EMAC is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_B44 is not set
+# CONFIG_ATL2 is not set
+CONFIG_NETDEV_1000=y
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_E1000E is not set
+# CONFIG_IP1000 is not set
+# CONFIG_IGB is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+# CONFIG_ATL1E is not set
+# CONFIG_JME is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_TR is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_GPIO is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_GPIO is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+CONFIG_SERIO_XILINX_XPS_PS2=y
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_UARTLITE=y
+CONFIG_SERIAL_UARTLITE_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_OF_PLATFORM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=m
+# CONFIG_NVRAM is not set
+# CONFIG_GEN_RTC is not set
+CONFIG_XILINX_HWICAP=y
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+CONFIG_GPIO_XILINX=y
+
+#
+# I2C GPIO expanders:
+#
+
+#
+# PCI GPIO expanders:
+#
+# CONFIG_GPIO_BT8XX is not set
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_OF is not set
+# CONFIG_FB_CT65550 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_VGA16 is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_VIA is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
+# CONFIG_FB_CARMINE is not set
+# CONFIG_FB_IBM_GXT4500 is not set
+CONFIG_FB_XILINX=y
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_7x14 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FONT_MINI_4x6 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_SOUND is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_UWB is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_INFINIBAND is not set
+# CONFIG_EDAC is not set
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+CONFIG_STAGING_EXCLUDE_BUILD=y
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_CRAMFS=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+CONFIG_ROMFS_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_REGISTER_V4 is not set
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=m
+# CONFIG_DLM is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_HAVE_LMB=y
+
+#
+# Kernel hacking
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_CODE_PATCHING_SELFTEST is not set
+# CONFIG_FTR_FIXUP_SELFTEST is not set
+# CONFIG_MSI_BITMAP_SELFTEST is not set
+# CONFIG_XMON is not set
+# CONFIG_IRQSTACKS is not set
+# CONFIG_BDI_SWITCH is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+# CONFIG_PPC_CLOCK is not set
+# CONFIG_VIRTUALIZATION is not set
diff --git a/arch/powerpc/configs/44x/virtex5_defconfig b/arch/powerpc/configs/44x/virtex5_defconfig
index 663ec512b33..7513d360e0b 100644
--- a/arch/powerpc/configs/44x/virtex5_defconfig
+++ b/arch/powerpc/configs/44x/virtex5_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27-rc1
-# Tue Aug 5 09:20:16 2008
+# Linux kernel version: 2.6.28-rc4
+# Fri Nov 14 10:31:16 2008
#
# CONFIG_PPC64 is not set
@@ -22,14 +22,13 @@ CONFIG_PHYS_64BIT=y
CONFIG_NOT_COHERENT_CACHE=y
CONFIG_PPC32=y
CONFIG_WORD_SIZE=32
-CONFIG_PPC_MERGE=y
+CONFIG_ARCH_PHYS_ADDR_T_64BIT=y
CONFIG_MMU=y
CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_TIME_VSYSCALL=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_HARDIRQS=y
-# CONFIG_HAVE_GET_USER_PAGES_FAST is not set
# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
CONFIG_IRQ_PER_CPU=y
CONFIG_STACKTRACE_SUPPORT=y
@@ -40,6 +39,7 @@ CONFIG_ARCH_HAS_ILOG2_U32=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_GPIO=y
# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
@@ -93,8 +93,8 @@ CONFIG_INITRAMFS_SOURCE=""
CONFIG_SYSCTL=y
# CONFIG_EMBEDDED is not set
CONFIG_SYSCTL_SYSCALL=y
-CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
@@ -109,7 +109,9 @@ CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
@@ -122,10 +124,6 @@ CONFIG_HAVE_IOREMAP_PROT=y
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
-# CONFIG_HAVE_DMA_ATTRS is not set
-# CONFIG_USE_GENERIC_SMP_HELPERS is not set
-# CONFIG_HAVE_CLK is not set
-CONFIG_PROC_PAGE_MONITOR=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -158,6 +156,7 @@ CONFIG_DEFAULT_CFQ=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="cfq"
CONFIG_CLASSIC_RCU=y
+# CONFIG_FREEZER is not set
# CONFIG_PPC4xx_PCI_EXPRESS is not set
#
@@ -174,9 +173,13 @@ CONFIG_CLASSIC_RCU=y
# CONFIG_KATMAI is not set
# CONFIG_RAINIER is not set
# CONFIG_WARP is not set
+# CONFIG_ARCHES is not set
# CONFIG_CANYONLANDS is not set
+# CONFIG_GLACIER is not set
# CONFIG_YOSEMITE is not set
CONFIG_XILINX_VIRTEX440_GENERIC_BOARD=y
+# CONFIG_PPC44x_SIMPLE is not set
+# CONFIG_PPC4xx_GPIO is not set
CONFIG_XILINX_VIRTEX=y
CONFIG_XILINX_VIRTEX_5_FXT=y
# CONFIG_IPIC is not set
@@ -196,7 +199,6 @@ CONFIG_XILINX_VIRTEX_5_FXT=y
# Kernel options
#
# CONFIG_HIGHMEM is not set
-# CONFIG_TICK_ONESHOT is not set
# CONFIG_NO_HZ is not set
# CONFIG_HIGH_RES_TIMERS is not set
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
@@ -211,6 +213,8 @@ CONFIG_HZ=250
CONFIG_PREEMPT=y
# CONFIG_PREEMPT_RCU is not set
CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
CONFIG_MATH_EMULATION=y
# CONFIG_IOMMU_HELPER is not set
@@ -225,15 +229,15 @@ CONFIG_FLATMEM_MANUAL=y
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
CONFIG_RESOURCES_64BIT=y
+CONFIG_PHYS_ADDR_T_64BIT=y
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
CONFIG_CMDLINE_BOOL=y
@@ -256,6 +260,7 @@ CONFIG_PCI_SYSCALL=y
CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
CONFIG_PCI_LEGACY=y
+# CONFIG_PCI_DEBUG is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -317,7 +322,6 @@ CONFIG_INET_TCP_DIAG=y
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
-# CONFIG_IP_VS is not set
CONFIG_IPV6=m
# CONFIG_IPV6_PRIVACY is not set
# CONFIG_IPV6_ROUTER_PREF is not set
@@ -352,8 +356,8 @@ CONFIG_NETFILTER_XTABLES=m
# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
# CONFIG_NETFILTER_XT_TARGET_MARK is not set
-# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set
# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
@@ -361,36 +365,38 @@ CONFIG_NETFILTER_XTABLES=m
# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set
# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
# CONFIG_NETFILTER_XT_MATCH_MAC is not set
# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
# CONFIG_NETFILTER_XT_MATCH_OWNER is not set
# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
-# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set
# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_RECENT is not set
# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
# CONFIG_NETFILTER_XT_MATCH_STRING is not set
# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
# CONFIG_NETFILTER_XT_MATCH_TIME is not set
# CONFIG_NETFILTER_XT_MATCH_U32 is not set
-# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+# CONFIG_IP_VS is not set
#
# IP: Netfilter Configuration
#
+# CONFIG_NF_DEFRAG_IPV4 is not set
# CONFIG_IP_NF_QUEUE is not set
CONFIG_IP_NF_IPTABLES=m
-# CONFIG_IP_NF_MATCH_RECENT is not set
-# CONFIG_IP_NF_MATCH_ECN is not set
+# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
# CONFIG_IP_NF_MATCH_AH is not set
+# CONFIG_IP_NF_MATCH_ECN is not set
# CONFIG_IP_NF_MATCH_TTL is not set
-# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
CONFIG_IP_NF_FILTER=m
# CONFIG_IP_NF_TARGET_REJECT is not set
# CONFIG_IP_NF_TARGET_LOG is not set
@@ -411,6 +417,7 @@ CONFIG_IP_NF_MANGLE=m
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
@@ -431,11 +438,10 @@ CONFIG_IP_NF_MANGLE=m
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
+# CONFIG_PHONET is not set
+CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
@@ -455,11 +461,13 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
CONFIG_FW_LOADER=y
CONFIG_FIRMWARE_IN_KERNEL=y
CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
# CONFIG_SYS_HYPERVISOR is not set
# CONFIG_CONNECTOR is not set
# CONFIG_MTD is not set
CONFIG_OF_DEVICE=y
-CONFIG_OF_I2C=y
+CONFIG_OF_GPIO=y
# CONFIG_PARPORT is not set
CONFIG_BLK_DEV=y
# CONFIG_BLK_DEV_FD is not set
@@ -478,7 +486,7 @@ CONFIG_BLK_DEV_RAM_SIZE=8192
# CONFIG_BLK_DEV_XIP is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
-# CONFIG_XILINX_SYSACE is not set
+CONFIG_XILINX_SYSACE=y
# CONFIG_BLK_DEV_HD is not set
CONFIG_MISC_DEVICES=y
# CONFIG_PHANTOM is not set
@@ -487,6 +495,7 @@ CONFIG_MISC_DEVICES=y
# CONFIG_TIFM_CORE is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -534,8 +543,12 @@ CONFIG_MII=y
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
# CONFIG_NET_PCI is not set
# CONFIG_B44 is not set
+# CONFIG_ATL2 is not set
CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
@@ -556,6 +569,7 @@ CONFIG_NETDEV_1000=y
# CONFIG_QLA3XXX is not set
# CONFIG_ATL1 is not set
# CONFIG_ATL1E is not set
+# CONFIG_JME is not set
# CONFIG_NETDEV_10000 is not set
# CONFIG_TR is not set
@@ -604,6 +618,7 @@ CONFIG_KEYBOARD_ATKBD=y
# CONFIG_KEYBOARD_XTKBD is not set
# CONFIG_KEYBOARD_NEWTON is not set
# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_GPIO is not set
CONFIG_INPUT_MOUSE=y
CONFIG_MOUSE_PS2=y
CONFIG_MOUSE_PS2_ALPS=y
@@ -611,9 +626,11 @@ CONFIG_MOUSE_PS2_LOGIPS2PP=y
CONFIG_MOUSE_PS2_SYNAPTICS=y
CONFIG_MOUSE_PS2_LIFEBOOK=y
CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
# CONFIG_MOUSE_PS2_TOUCHKIT is not set
# CONFIG_MOUSE_SERIAL is not set
# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_GPIO is not set
# CONFIG_INPUT_JOYSTICK is not set
# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
@@ -624,11 +641,11 @@ CONFIG_MOUSE_PS2_TRACKPOINT=y
#
CONFIG_SERIO=y
# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_SERPORT is not set
# CONFIG_SERIO_PCIPS2 is not set
CONFIG_SERIO_LIBPS2=y
# CONFIG_SERIO_RAW is not set
-# CONFIG_SERIO_XILINX_XPS_PS2 is not set
+CONFIG_SERIO_XILINX_XPS_PS2=y
# CONFIG_GAMEPORT is not set
#
@@ -656,11 +673,12 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
#
# Non-8250 serial port support
#
-# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_UARTLITE=y
+CONFIG_SERIAL_UARTLITE_CONSOLE=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
-CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -674,87 +692,41 @@ CONFIG_XILINX_HWICAP=y
# CONFIG_RAW_DRIVER is not set
# CONFIG_TCG_TPM is not set
CONFIG_DEVPORT=y
-CONFIG_I2C=y
-CONFIG_I2C_BOARDINFO=y
-CONFIG_I2C_CHARDEV=y
-
-#
-# I2C Hardware Bus support
-#
-
-#
-# PC SMBus host controller drivers
-#
-# CONFIG_I2C_ALI1535 is not set
-# CONFIG_I2C_ALI1563 is not set
-# CONFIG_I2C_ALI15X3 is not set
-# CONFIG_I2C_AMD756 is not set
-# CONFIG_I2C_AMD8111 is not set
-# CONFIG_I2C_I801 is not set
-# CONFIG_I2C_ISCH is not set
-# CONFIG_I2C_PIIX4 is not set
-# CONFIG_I2C_NFORCE2 is not set
-# CONFIG_I2C_SIS5595 is not set
-# CONFIG_I2C_SIS630 is not set
-# CONFIG_I2C_SIS96X is not set
-# CONFIG_I2C_VIA is not set
-# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
#
-# I2C system bus drivers (mostly embedded / system-on-chip)
+# Memory mapped GPIO expanders:
#
-# CONFIG_I2C_IBM_IIC is not set
-# CONFIG_I2C_MPC is not set
-# CONFIG_I2C_OCORES is not set
-# CONFIG_I2C_SIMTEC is not set
+CONFIG_GPIO_XILINX=y
#
-# External I2C/SMBus adapter drivers
+# I2C GPIO expanders:
#
-# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_TAOS_EVM is not set
#
-# Graphics adapter I2C/DDC channel drivers
+# PCI GPIO expanders:
#
-# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_GPIO_BT8XX is not set
#
-# Other I2C/SMBus bus drivers
+# SPI GPIO expanders:
#
-# CONFIG_I2C_PCA_PLATFORM is not set
-# CONFIG_I2C_STUB is not set
-
-#
-# Miscellaneous I2C Chip support
-#
-# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_PCF8575 is not set
-# CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_SENSORS_TSL2550 is not set
-CONFIG_I2C_DEBUG_CORE=y
-CONFIG_I2C_DEBUG_ALGO=y
-# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_I2C_DEBUG_CHIP is not set
-# CONFIG_SPI is not set
-CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
-# CONFIG_GPIOLIB is not set
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
# CONFIG_HWMON is not set
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -763,6 +735,8 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -790,6 +764,7 @@ CONFIG_SSB_POSSIBLE=y
CONFIG_FB=y
# CONFIG_FIRMWARE_EDID is not set
# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
@@ -826,6 +801,7 @@ CONFIG_FB_CFB_IMAGEBLIT=y
# CONFIG_FB_S3 is not set
# CONFIG_FB_SAVAGE is not set
# CONFIG_FB_SIS is not set
+# CONFIG_FB_VIA is not set
# CONFIG_FB_NEOMAGIC is not set
# CONFIG_FB_KYRO is not set
# CONFIG_FB_3DFX is not set
@@ -838,6 +814,8 @@ CONFIG_FB_CFB_IMAGEBLIT=y
# CONFIG_FB_IBM_GXT4500 is not set
CONFIG_FB_XILINX=y
# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
@@ -870,6 +848,7 @@ CONFIG_LOGO_LINUX_CLUT224=y
# CONFIG_SOUND is not set
# CONFIG_HID_SUPPORT is not set
# CONFIG_USB_SUPPORT is not set
+# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
@@ -879,6 +858,8 @@ CONFIG_LOGO_LINUX_CLUT224=y
# CONFIG_RTC_CLASS is not set
# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+CONFIG_STAGING_EXCLUDE_BUILD=y
#
# File systems
@@ -887,10 +868,11 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
# CONFIG_EXT3_FS is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
# CONFIG_XFS_FS is not set
# CONFIG_OCFS2_FS is not set
CONFIG_DNOTIFY=y
@@ -899,7 +881,7 @@ CONFIG_INOTIFY_USER=y
# CONFIG_QUOTA is not set
CONFIG_AUTOFS_FS=y
CONFIG_AUTOFS4_FS=y
-CONFIG_FUSE_FS=m
+# CONFIG_FUSE_FS is not set
#
# CD-ROM/DVD Filesystems
@@ -923,6 +905,7 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
CONFIG_PROC_FS=y
# CONFIG_PROC_KCORE is not set
CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
@@ -954,19 +937,15 @@ CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
# CONFIG_NFS_V4 is not set
CONFIG_ROOT_NFS=y
-CONFIG_NFSD=y
-CONFIG_NFSD_V3=y
-# CONFIG_NFSD_V3_ACL is not set
-# CONFIG_NFSD_V4 is not set
+# CONFIG_NFSD is not set
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_REGISTER_V4 is not set
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
-CONFIG_SMB_FS=y
-# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
@@ -1023,7 +1002,6 @@ CONFIG_NLS_UTF8=m
# Library routines
#
CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
CONFIG_CRC_CCITT=y
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -1041,7 +1019,7 @@ CONFIG_HAVE_LMB=y
#
# Kernel hacking
#
-# CONFIG_PRINTK_TIME is not set
+CONFIG_PRINTK_TIME=y
CONFIG_ENABLE_WARN_DEPRECATED=y
CONFIG_ENABLE_MUST_CHECK=y
CONFIG_FRAME_WARN=1024
@@ -1049,19 +1027,62 @@ CONFIG_FRAME_WARN=1024
# CONFIG_UNUSED_SYMBOLS is not set
# CONFIG_DEBUG_FS is not set
# CONFIG_HEADERS_CHECK is not set
-# CONFIG_DEBUG_KERNEL is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
-CONFIG_HAVE_FTRACE=y
-CONFIG_HAVE_DYNAMIC_FTRACE=y
-# CONFIG_FTRACE is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
# CONFIG_PREEMPT_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_CODE_PATCHING_SELFTEST is not set
+# CONFIG_FTR_FIXUP_SELFTEST is not set
+# CONFIG_MSI_BITMAP_SELFTEST is not set
+# CONFIG_XMON is not set
# CONFIG_IRQSTACKS is not set
+# CONFIG_BDI_SWITCH is not set
# CONFIG_PPC_EARLY_DEBUG is not set
#
@@ -1069,12 +1090,14 @@ CONFIG_HAVE_ARCH_KGDB=y
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_CRYPTO=y
#
# Crypto core or helper
#
+# CONFIG_CRYPTO_FIPS is not set
# CONFIG_CRYPTO_MANAGER is not set
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
@@ -1147,6 +1170,11 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_DEFLATE is not set
# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
# CONFIG_CRYPTO_DEV_HIFN_795X is not set
# CONFIG_PPC_CLOCK is not set
diff --git a/arch/powerpc/configs/52xx/cm5200_defconfig b/arch/powerpc/configs/52xx/cm5200_defconfig
index c10f7395aa1..3df627494b6 100644
--- a/arch/powerpc/configs/52xx/cm5200_defconfig
+++ b/arch/powerpc/configs/52xx/cm5200_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.25
-# Tue Apr 29 07:11:37 2008
+# Linux kernel version: 2.6.28-rc4
+# Thu Nov 13 02:12:40 2008
#
# CONFIG_PPC64 is not set
@@ -22,7 +22,7 @@ CONFIG_PPC_STD_MMU_32=y
# CONFIG_SMP is not set
CONFIG_PPC32=y
CONFIG_WORD_SIZE=32
-CONFIG_PPC_MERGE=y
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
CONFIG_MMU=y
CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_GENERIC_TIME=y
@@ -32,6 +32,7 @@ CONFIG_GENERIC_HARDIRQS=y
# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
CONFIG_IRQ_PER_CPU=y
CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
CONFIG_ARCH_HAS_ILOG2_U32=y
@@ -102,6 +103,7 @@ CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLUB_DEBUG=y
# CONFIG_SLAB is not set
@@ -110,9 +112,13 @@ CONFIG_SLUB=y
# CONFIG_PROFILING is not set
# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_HAVE_IOREMAP_PROT=y
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
-CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_CLK=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
@@ -123,6 +129,7 @@ CONFIG_BLOCK=y
# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
#
# IO Schedulers
@@ -137,19 +144,16 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_FREEZER is not set
#
# Platform support
#
CONFIG_PPC_MULTIPLATFORM=y
-# CONFIG_PPC_82xx is not set
-# CONFIG_PPC_83xx is not set
-# CONFIG_PPC_86xx is not set
CONFIG_CLASSIC32=y
# CONFIG_PPC_CHRP is not set
-# CONFIG_PPC_MPC512x is not set
-# CONFIG_PPC_MPC5121 is not set
# CONFIG_MPC5121_ADS is not set
+# CONFIG_MPC5121_GENERIC is not set
CONFIG_PPC_MPC52xx=y
CONFIG_PPC_MPC5200_SIMPLE=y
# CONFIG_PPC_EFIKA is not set
@@ -159,7 +163,10 @@ CONFIG_PPC_MPC5200_SIMPLE=y
# CONFIG_PPC_PMAC is not set
# CONFIG_PPC_CELL is not set
# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PPC_82xx is not set
# CONFIG_PQ2ADS is not set
+# CONFIG_PPC_83xx is not set
+# CONFIG_PPC_86xx is not set
# CONFIG_EMBEDDED6xx is not set
# CONFIG_IPIC is not set
# CONFIG_MPIC is not set
@@ -183,7 +190,6 @@ CONFIG_PPC_BESTCOMM_FEC=y
# Kernel options
#
# CONFIG_HIGHMEM is not set
-# CONFIG_TICK_ONESHOT is not set
# CONFIG_NO_HZ is not set
# CONFIG_HIGH_RES_TIMERS is not set
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
@@ -197,6 +203,8 @@ CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not set
CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
# CONFIG_IOMMU_HELPER is not set
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
@@ -211,19 +219,20 @@ CONFIG_FLATMEM_MANUAL=y
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
+CONFIG_EXTRA_TARGETS=""
CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
# CONFIG_PM_DEBUG is not set
CONFIG_SECCOMP=y
CONFIG_ISA_DMA_API=y
@@ -233,7 +242,7 @@ CONFIG_ISA_DMA_API=y
#
CONFIG_ZONE_DMA=y
CONFIG_GENERIC_ISA_DMA=y
-CONFIG_FSL_SOC=y
+CONFIG_PPC_PCI_CHOICE=y
# CONFIG_PCI is not set
# CONFIG_PCI_DOMAINS is not set
# CONFIG_PCI_SYSCALL is not set
@@ -254,10 +263,6 @@ CONFIG_PAGE_OFFSET=0xc0000000
CONFIG_KERNEL_START=0xc0000000
CONFIG_PHYSICAL_START=0x00000000
CONFIG_TASK_SIZE=0xc0000000
-
-#
-# Networking
-#
CONFIG_NET=y
#
@@ -308,6 +313,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
@@ -328,14 +334,8 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
-# CONFIG_CFG80211 is not set
-# CONFIG_WIRELESS_EXT is not set
-# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_PHONET is not set
+# CONFIG_WIRELESS is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -446,6 +446,7 @@ CONFIG_BLK_DEV_RAM_SIZE=32768
# CONFIG_BLK_DEV_XIP is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
# CONFIG_MISC_DEVICES is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -487,11 +488,11 @@ CONFIG_CHR_DEV_SG=y
# CONFIG_SCSI_SAS_LIBSAS is not set
# CONFIG_SCSI_SRP_ATTRS is not set
# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_SCSI_DH is not set
# CONFIG_ATA is not set
# CONFIG_MD is not set
# CONFIG_MACINTOSH_DRIVERS is not set
CONFIG_NETDEVICES=y
-# CONFIG_NETDEVICES_MULTIQUEUE is not set
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
@@ -521,6 +522,9 @@ CONFIG_NET_ETHERNET=y
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
# CONFIG_B44 is not set
CONFIG_FEC_MPC52xx=y
CONFIG_FEC_MPC52xx_MDIO=y
@@ -532,7 +536,6 @@ CONFIG_FEC_MPC52xx_MDIO=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI is not set
# CONFIG_IWLWIFI_LEDS is not set
#
@@ -567,6 +570,7 @@ CONFIG_FEC_MPC52xx_MDIO=y
# Character devices
#
# CONFIG_VT is not set
+CONFIG_DEVKMEM=y
# CONFIG_SERIAL_NONSTANDARD is not set
#
@@ -596,25 +600,40 @@ CONFIG_LEGACY_PTY_COUNT=256
CONFIG_I2C=y
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
#
# I2C Hardware Bus support
#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
CONFIG_I2C_MPC=y
# CONFIG_I2C_OCORES is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_TAOS_EVM is not set
# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
# CONFIG_I2C_PCA_PLATFORM is not set
#
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
+# CONFIG_AT24 is not set
# CONFIG_SENSORS_EEPROM is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
@@ -623,10 +642,13 @@ CONFIG_I2C_MPC=y
# CONFIG_I2C_DEBUG_BUS is not set
# CONFIG_I2C_DEBUG_CHIP is not set
# CONFIG_SPI is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+# CONFIG_GPIOLIB is not set
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
# CONFIG_HWMON is not set
# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
CONFIG_WATCHDOG=y
# CONFIG_WATCHDOG_NOWAYOUT is not set
@@ -640,24 +662,39 @@ CONFIG_WATCHDOG=y
# USB-based Watchdog Cards
#
# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
# Multifunction device drivers
#
+# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
#
+
+#
+# Multimedia core support
+#
# CONFIG_VIDEO_DEV is not set
# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
# CONFIG_DAB is not set
#
@@ -672,10 +709,6 @@ CONFIG_SSB_POSSIBLE=y
# Display device support
#
# CONFIG_DISPLAY_SUPPORT is not set
-
-#
-# Sound
-#
# CONFIG_SOUND is not set
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
@@ -695,11 +728,16 @@ CONFIG_USB_DEVICEFS=y
# CONFIG_USB_OTG is not set
# CONFIG_USB_OTG_WHITELIST is not set
# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
#
# USB Host Controller Drivers
#
+# CONFIG_USB_C67X00_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_OHCI_HCD_PPC_SOC=y
CONFIG_USB_OHCI_HCD_PPC_OF=y
@@ -710,12 +748,16 @@ CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
# CONFIG_USB_OHCI_LITTLE_ENDIAN is not set
# CONFIG_USB_SL811_HCD is not set
# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+# CONFIG_USB_MUSB_HDRC is not set
#
# USB Device Class drivers
#
# CONFIG_USB_ACM is not set
# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -744,7 +786,6 @@ CONFIG_USB_STORAGE=y
#
# CONFIG_USB_MDC800 is not set
# CONFIG_USB_MICROTEK is not set
-# CONFIG_USB_MON is not set
#
# USB port drivers
@@ -757,7 +798,7 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_EMI62 is not set
# CONFIG_USB_EMI26 is not set
# CONFIG_USB_ADUTUX is not set
-# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_SEVSEG is not set
# CONFIG_USB_RIO500 is not set
# CONFIG_USB_LEGOTOWER is not set
# CONFIG_USB_LCD is not set
@@ -773,14 +814,19 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_TRANCEVIBRATOR is not set
# CONFIG_USB_IOWARRIOR is not set
# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
# CONFIG_EDAC is not set
# CONFIG_RTC_CLASS is not set
# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+CONFIG_STAGING_EXCLUDE_BUILD=y
#
# File systems
@@ -792,12 +838,13 @@ CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
CONFIG_JBD=y
CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
# CONFIG_XFS_FS is not set
# CONFIG_OCFS2_FS is not set
CONFIG_DNOTIFY=y
@@ -830,6 +877,7 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
@@ -860,6 +908,7 @@ CONFIG_JFFS2_RTIME=y
CONFIG_CRAMFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
# CONFIG_ROMFS_FS is not set
@@ -870,14 +919,14 @@ CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
CONFIG_NFS_V4=y
-# CONFIG_NFSD is not set
CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
-# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_SUNRPC_REGISTER_V4 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -953,9 +1002,9 @@ CONFIG_NLS_ISO8859_1=y
# Library routines
#
CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_CRC7 is not set
@@ -982,9 +1031,12 @@ CONFIG_FRAME_WARN=1024
CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_SHIRQ is not set
CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
# CONFIG_SLUB_DEBUG_ON is not set
# CONFIG_SLUB_STATS is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
@@ -998,16 +1050,37 @@ CONFIG_SCHED_DEBUG=y
# CONFIG_DEBUG_INFO is not set
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
-# CONFIG_DEBUGGER is not set
+# CONFIG_CODE_PATCHING_SELFTEST is not set
+# CONFIG_FTR_FIXUP_SELFTEST is not set
+# CONFIG_MSI_BITMAP_SELFTEST is not set
+# CONFIG_XMON is not set
# CONFIG_IRQSTACKS is not set
# CONFIG_BDI_SWITCH is not set
# CONFIG_BOOTX_TEXT is not set
@@ -1018,14 +1091,19 @@ CONFIG_SCHED_DEBUG=y
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_CRYPTO=y
#
# Crypto core or helper
#
+# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_AEAD=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_RNG=y
CONFIG_CRYPTO_MANAGER=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
@@ -1063,6 +1141,10 @@ CONFIG_CRYPTO_PCBC=y
# CONFIG_CRYPTO_MD4 is not set
CONFIG_CRYPTO_MD5=y
# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
# CONFIG_CRYPTO_SHA1 is not set
# CONFIG_CRYPTO_SHA256 is not set
# CONFIG_CRYPTO_SHA512 is not set
@@ -1093,6 +1175,11 @@ CONFIG_CRYPTO_DES=y
#
# CONFIG_CRYPTO_DEFLATE is not set
# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
CONFIG_PPC_CLOCK=y
CONFIG_PPC_LIB_RHEAP=y
diff --git a/arch/powerpc/configs/52xx/lite5200b_defconfig b/arch/powerpc/configs/52xx/lite5200b_defconfig
index 1a8a250fa11..5b969f9c925 100644
--- a/arch/powerpc/configs/52xx/lite5200b_defconfig
+++ b/arch/powerpc/configs/52xx/lite5200b_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.25
-# Tue Apr 29 07:12:56 2008
+# Linux kernel version: 2.6.28-rc4
+# Thu Nov 13 02:10:16 2008
#
# CONFIG_PPC64 is not set
@@ -22,7 +22,7 @@ CONFIG_PPC_STD_MMU_32=y
# CONFIG_SMP is not set
CONFIG_PPC32=y
CONFIG_WORD_SIZE=32
-CONFIG_PPC_MERGE=y
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
CONFIG_MMU=y
CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_GENERIC_TIME=y
@@ -32,6 +32,7 @@ CONFIG_GENERIC_HARDIRQS=y
# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
CONFIG_IRQ_PER_CPU=y
CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
CONFIG_ARCH_HAS_ILOG2_U32=y
@@ -103,7 +104,9 @@ CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
CONFIG_SLUB_DEBUG=y
# CONFIG_SLAB is not set
CONFIG_SLUB=y
@@ -111,24 +114,30 @@ CONFIG_SLUB=y
# CONFIG_PROFILING is not set
# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_HAVE_IOREMAP_PROT=y
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
-CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_CLK=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-# CONFIG_KMOD is not set
+CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
#
# IO Schedulers
@@ -143,19 +152,16 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+CONFIG_FREEZER=y
#
# Platform support
#
CONFIG_PPC_MULTIPLATFORM=y
-# CONFIG_PPC_82xx is not set
-# CONFIG_PPC_83xx is not set
-# CONFIG_PPC_86xx is not set
CONFIG_CLASSIC32=y
# CONFIG_PPC_CHRP is not set
-# CONFIG_PPC_MPC512x is not set
-# CONFIG_PPC_MPC5121 is not set
# CONFIG_MPC5121_ADS is not set
+# CONFIG_MPC5121_GENERIC is not set
CONFIG_PPC_MPC52xx=y
CONFIG_PPC_MPC5200_SIMPLE=y
# CONFIG_PPC_EFIKA is not set
@@ -165,7 +171,10 @@ CONFIG_PPC_LITE5200=y
# CONFIG_PPC_PMAC is not set
# CONFIG_PPC_CELL is not set
# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PPC_82xx is not set
# CONFIG_PQ2ADS is not set
+# CONFIG_PPC_83xx is not set
+# CONFIG_PPC_86xx is not set
# CONFIG_EMBEDDED6xx is not set
# CONFIG_IPIC is not set
# CONFIG_MPIC is not set
@@ -198,11 +207,13 @@ CONFIG_HZ_250=y
# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
-# CONFIG_SCHED_HRTICK is not set
+CONFIG_SCHED_HRTICK=y
CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not set
CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
# CONFIG_IOMMU_HELPER is not set
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
@@ -217,19 +228,20 @@ CONFIG_FLATMEM_MANUAL=y
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
+CONFIG_EXTRA_TARGETS=""
CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
# CONFIG_PM_DEBUG is not set
CONFIG_PM_SLEEP=y
CONFIG_SUSPEND=y
@@ -243,7 +255,7 @@ CONFIG_ISA_DMA_API=y
CONFIG_ZONE_DMA=y
CONFIG_GENERIC_ISA_DMA=y
# CONFIG_PPC_INDIRECT_PCI is not set
-CONFIG_FSL_SOC=y
+CONFIG_PPC_PCI_CHOICE=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
CONFIG_PCI_SYSCALL=y
@@ -269,10 +281,6 @@ CONFIG_PAGE_OFFSET=0xc0000000
CONFIG_KERNEL_START=0xc0000000
CONFIG_PHYSICAL_START=0x00000000
CONFIG_TASK_SIZE=0xc0000000
-
-#
-# Networking
-#
CONFIG_NET=y
#
@@ -323,6 +331,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
@@ -343,14 +352,8 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
-# CONFIG_CFG80211 is not set
-# CONFIG_WIRELESS_EXT is not set
-# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_PHONET is not set
+# CONFIG_WIRELESS is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -390,12 +393,16 @@ CONFIG_BLK_DEV_RAM_SIZE=32768
# CONFIG_BLK_DEV_XIP is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
CONFIG_MISC_DEVICES=y
# CONFIG_PHANTOM is not set
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -412,7 +419,7 @@ CONFIG_SCSI_DMA=y
#
# SCSI support type (disk, tape, CD-ROM)
#
-# CONFIG_BLK_DEV_SD is not set
+CONFIG_BLK_DEV_SD=y
# CONFIG_CHR_DEV_ST is not set
# CONFIG_CHR_DEV_OSST is not set
# CONFIG_BLK_DEV_SR is not set
@@ -474,12 +481,12 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_SCSI_NSP32 is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_SRP is not set
+# CONFIG_SCSI_DH is not set
CONFIG_ATA=y
# CONFIG_ATA_NONSTANDARD is not set
CONFIG_SATA_PMP=y
# CONFIG_SATA_AHCI is not set
# CONFIG_SATA_SIL24 is not set
-# CONFIG_SATA_FSL is not set
CONFIG_ATA_SFF=y
# CONFIG_SATA_SVW is not set
# CONFIG_ATA_PIIX is not set
@@ -535,18 +542,22 @@ CONFIG_PATA_MPC52xx=y
# CONFIG_PATA_VIA is not set
# CONFIG_PATA_WINBOND is not set
# CONFIG_PATA_PLATFORM is not set
+# CONFIG_PATA_SCH is not set
# CONFIG_MD is not set
# CONFIG_FUSION is not set
#
# IEEE 1394 (FireWire) support
#
+
+#
+# Enable only one of the two stacks, unless you know what you are doing
+#
# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
# CONFIG_I2O is not set
# CONFIG_MACINTOSH_DRIVERS is not set
CONFIG_NETDEVICES=y
-# CONFIG_NETDEVICES_MULTIQUEUE is not set
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
@@ -583,16 +594,19 @@ CONFIG_NET_ETHERNET=y
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
# CONFIG_NET_PCI is not set
# CONFIG_B44 is not set
CONFIG_FEC_MPC52xx=y
CONFIG_FEC_MPC52xx_MDIO=y
+# CONFIG_ATL2 is not set
CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
# CONFIG_E1000 is not set
# CONFIG_E1000E is not set
-# CONFIG_E1000E_ENABLED is not set
# CONFIG_IP1000 is not set
# CONFIG_IGB is not set
# CONFIG_NS83820 is not set
@@ -605,22 +619,27 @@ CONFIG_NETDEV_1000=y
# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
# CONFIG_BNX2 is not set
-# CONFIG_GIANFAR is not set
# CONFIG_MV643XX_ETH is not set
# CONFIG_QLA3XXX is not set
# CONFIG_ATL1 is not set
+# CONFIG_ATL1E is not set
+# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
# CONFIG_CHELSIO_T3 is not set
+# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
# CONFIG_NIU is not set
+# CONFIG_MLX4_EN is not set
# CONFIG_MLX4_CORE is not set
# CONFIG_TEHUTI is not set
# CONFIG_BNX2X is not set
+# CONFIG_QLGE is not set
+# CONFIG_SFC is not set
# CONFIG_TR is not set
#
@@ -628,7 +647,6 @@ CONFIG_NETDEV_10000=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI is not set
# CONFIG_IWLWIFI_LEDS is not set
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
@@ -657,6 +675,7 @@ CONFIG_NETDEV_10000=y
# Character devices
#
# CONFIG_VT is not set
+CONFIG_DEVKMEM=y
# CONFIG_SERIAL_NONSTANDARD is not set
# CONFIG_NOZOMI is not set
@@ -691,42 +710,63 @@ CONFIG_DEVPORT=y
CONFIG_I2C=y
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
#
# I2C Hardware Bus support
#
+
+#
+# PC SMBus host controller drivers
+#
# CONFIG_I2C_ALI1535 is not set
# CONFIG_I2C_ALI1563 is not set
# CONFIG_I2C_ALI15X3 is not set
# CONFIG_I2C_AMD756 is not set
# CONFIG_I2C_AMD8111 is not set
# CONFIG_I2C_I801 is not set
-# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_ISCH is not set
# CONFIG_I2C_PIIX4 is not set
-CONFIG_I2C_MPC=y
# CONFIG_I2C_NFORCE2 is not set
-# CONFIG_I2C_OCORES is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PROSAVAGE is not set
-# CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_I2C_SIMTEC is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
-# CONFIG_I2C_TAOS_EVM is not set
-# CONFIG_I2C_STUB is not set
# CONFIG_I2C_VIA is not set
# CONFIG_I2C_VIAPRO is not set
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+CONFIG_I2C_MPC=y
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+
+#
+# Graphics adapter I2C/DDC channel drivers
+#
# CONFIG_I2C_VOODOO3 is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
#
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
+# CONFIG_AT24 is not set
# CONFIG_SENSORS_EEPROM is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
@@ -735,29 +775,47 @@ CONFIG_I2C_MPC=y
# CONFIG_I2C_DEBUG_BUS is not set
# CONFIG_I2C_DEBUG_CHIP is not set
# CONFIG_SPI is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+# CONFIG_GPIOLIB is not set
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
# CONFIG_HWMON is not set
# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
# Multifunction device drivers
#
+# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
#
+
+#
+# Multimedia core support
+#
# CONFIG_VIDEO_DEV is not set
# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
# CONFIG_DAB is not set
#
@@ -774,10 +832,6 @@ CONFIG_VIDEO_OUTPUT_CONTROL=m
# Display device support
#
# CONFIG_DISPLAY_SUPPORT is not set
-
-#
-# Sound
-#
# CONFIG_SOUND is not set
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
@@ -788,17 +842,25 @@ CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB_OTG_BLACKLIST_HUB is not set
#
+# Enable Host or Gadget support to see Inventra options
+#
+
+#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
#
# CONFIG_USB_GADGET is not set
+# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
# CONFIG_INFINIBAND is not set
# CONFIG_EDAC is not set
# CONFIG_RTC_CLASS is not set
# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+CONFIG_STAGING_EXCLUDE_BUILD=y
#
# File systems
@@ -810,12 +872,13 @@ CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
CONFIG_JBD=y
CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
# CONFIG_XFS_FS is not set
# CONFIG_OCFS2_FS is not set
CONFIG_DNOTIFY=y
@@ -845,6 +908,7 @@ CONFIG_INOTIFY_USER=y
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
@@ -864,6 +928,7 @@ CONFIG_TMPFS=y
# CONFIG_CRAMFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
# CONFIG_ROMFS_FS is not set
@@ -874,14 +939,14 @@ CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
CONFIG_NFS_V4=y
-# CONFIG_NFSD is not set
CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
-# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_SUNRPC_REGISTER_V4 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -902,9 +967,9 @@ CONFIG_MSDOS_PARTITION=y
# Library routines
#
CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_CRC7 is not set
@@ -929,9 +994,12 @@ CONFIG_FRAME_WARN=1024
CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_SHIRQ is not set
CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
# CONFIG_SLUB_DEBUG_ON is not set
# CONFIG_SLUB_STATS is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
@@ -945,17 +1013,37 @@ CONFIG_SCHED_DEBUG=y
CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
-# CONFIG_DEBUGGER is not set
+# CONFIG_CODE_PATCHING_SELFTEST is not set
+# CONFIG_FTR_FIXUP_SELFTEST is not set
+# CONFIG_MSI_BITMAP_SELFTEST is not set
+# CONFIG_XMON is not set
# CONFIG_IRQSTACKS is not set
# CONFIG_BDI_SWITCH is not set
# CONFIG_BOOTX_TEXT is not set
@@ -966,14 +1054,19 @@ CONFIG_DEBUG_INFO=y
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_CRYPTO=y
#
# Crypto core or helper
#
+# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_AEAD=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_RNG=y
CONFIG_CRYPTO_MANAGER=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
@@ -1012,6 +1105,10 @@ CONFIG_CRYPTO_CBC=y
# CONFIG_CRYPTO_MD4 is not set
CONFIG_CRYPTO_MD5=y
# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
# CONFIG_CRYPTO_SHA1 is not set
# CONFIG_CRYPTO_SHA256 is not set
# CONFIG_CRYPTO_SHA512 is not set
@@ -1042,6 +1139,11 @@ CONFIG_CRYPTO_DES=y
#
# CONFIG_CRYPTO_DEFLATE is not set
# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
# CONFIG_CRYPTO_DEV_HIFN_795X is not set
CONFIG_PPC_CLOCK=y
diff --git a/arch/powerpc/configs/52xx/motionpro_defconfig b/arch/powerpc/configs/52xx/motionpro_defconfig
index 8c7ba7c6ba4..3c0d4e56172 100644
--- a/arch/powerpc/configs/52xx/motionpro_defconfig
+++ b/arch/powerpc/configs/52xx/motionpro_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.25
-# Tue Apr 29 07:12:22 2008
+# Linux kernel version: 2.6.28-rc4
+# Thu Nov 13 02:11:02 2008
#
# CONFIG_PPC64 is not set
@@ -22,7 +22,7 @@ CONFIG_PPC_STD_MMU_32=y
# CONFIG_SMP is not set
CONFIG_PPC32=y
CONFIG_WORD_SIZE=32
-CONFIG_PPC_MERGE=y
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
CONFIG_MMU=y
CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_GENERIC_TIME=y
@@ -32,6 +32,7 @@ CONFIG_GENERIC_HARDIRQS=y
# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
CONFIG_IRQ_PER_CPU=y
CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
CONFIG_ARCH_HAS_ILOG2_U32=y
@@ -102,6 +103,7 @@ CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLUB_DEBUG=y
# CONFIG_SLAB is not set
@@ -110,9 +112,13 @@ CONFIG_SLUB=y
# CONFIG_PROFILING is not set
# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_HAVE_IOREMAP_PROT=y
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
-CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_CLK=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
@@ -123,6 +129,7 @@ CONFIG_BLOCK=y
# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
#
# IO Schedulers
@@ -137,19 +144,16 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_FREEZER is not set
#
# Platform support
#
CONFIG_PPC_MULTIPLATFORM=y
-# CONFIG_PPC_82xx is not set
-# CONFIG_PPC_83xx is not set
-# CONFIG_PPC_86xx is not set
CONFIG_CLASSIC32=y
# CONFIG_PPC_CHRP is not set
-# CONFIG_PPC_MPC512x is not set
-# CONFIG_PPC_MPC5121 is not set
# CONFIG_MPC5121_ADS is not set
+# CONFIG_MPC5121_GENERIC is not set
CONFIG_PPC_MPC52xx=y
CONFIG_PPC_MPC5200_SIMPLE=y
# CONFIG_PPC_EFIKA is not set
@@ -159,7 +163,10 @@ CONFIG_PPC_MPC5200_SIMPLE=y
# CONFIG_PPC_PMAC is not set
# CONFIG_PPC_CELL is not set
# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PPC_82xx is not set
# CONFIG_PQ2ADS is not set
+# CONFIG_PPC_83xx is not set
+# CONFIG_PPC_86xx is not set
# CONFIG_EMBEDDED6xx is not set
# CONFIG_IPIC is not set
# CONFIG_MPIC is not set
@@ -183,7 +190,6 @@ CONFIG_PPC_BESTCOMM_FEC=y
# Kernel options
#
# CONFIG_HIGHMEM is not set
-# CONFIG_TICK_ONESHOT is not set
# CONFIG_NO_HZ is not set
# CONFIG_HIGH_RES_TIMERS is not set
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
@@ -197,6 +203,8 @@ CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not set
CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
# CONFIG_IOMMU_HELPER is not set
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
@@ -211,19 +219,20 @@ CONFIG_FLATMEM_MANUAL=y
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
+CONFIG_EXTRA_TARGETS=""
CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
# CONFIG_PM_DEBUG is not set
CONFIG_SECCOMP=y
CONFIG_ISA_DMA_API=y
@@ -233,7 +242,7 @@ CONFIG_ISA_DMA_API=y
#
CONFIG_ZONE_DMA=y
CONFIG_GENERIC_ISA_DMA=y
-CONFIG_FSL_SOC=y
+CONFIG_PPC_PCI_CHOICE=y
# CONFIG_PCI is not set
# CONFIG_PCI_DOMAINS is not set
# CONFIG_PCI_SYSCALL is not set
@@ -254,10 +263,6 @@ CONFIG_PAGE_OFFSET=0xc0000000
CONFIG_KERNEL_START=0xc0000000
CONFIG_PHYSICAL_START=0x00000000
CONFIG_TASK_SIZE=0xc0000000
-
-#
-# Networking
-#
CONFIG_NET=y
#
@@ -308,6 +313,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
@@ -328,14 +334,8 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
-# CONFIG_CFG80211 is not set
-# CONFIG_WIRELESS_EXT is not set
-# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_PHONET is not set
+# CONFIG_WIRELESS is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -445,9 +445,12 @@ CONFIG_BLK_DEV_RAM_SIZE=32768
# CONFIG_BLK_DEV_XIP is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -490,10 +493,10 @@ CONFIG_CHR_DEV_SG=y
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
CONFIG_ATA=y
# CONFIG_ATA_NONSTANDARD is not set
CONFIG_SATA_PMP=y
-# CONFIG_SATA_FSL is not set
CONFIG_ATA_SFF=y
# CONFIG_SATA_MV is not set
CONFIG_PATA_MPC52xx=y
@@ -501,7 +504,6 @@ CONFIG_PATA_MPC52xx=y
# CONFIG_MD is not set
# CONFIG_MACINTOSH_DRIVERS is not set
CONFIG_NETDEVICES=y
-# CONFIG_NETDEVICES_MULTIQUEUE is not set
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
@@ -531,6 +533,9 @@ CONFIG_MII=y
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
# CONFIG_B44 is not set
CONFIG_FEC_MPC52xx=y
CONFIG_FEC_MPC52xx_MDIO=y
@@ -542,7 +547,6 @@ CONFIG_FEC_MPC52xx_MDIO=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI is not set
# CONFIG_IWLWIFI_LEDS is not set
# CONFIG_WAN is not set
# CONFIG_PPP is not set
@@ -568,6 +572,7 @@ CONFIG_FEC_MPC52xx_MDIO=y
# Character devices
#
# CONFIG_VT is not set
+CONFIG_DEVKMEM=y
# CONFIG_SERIAL_NONSTANDARD is not set
#
@@ -596,24 +601,39 @@ CONFIG_LEGACY_PTY_COUNT=256
CONFIG_I2C=y
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
#
# I2C Hardware Bus support
#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
CONFIG_I2C_MPC=y
# CONFIG_I2C_OCORES is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_TAOS_EVM is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
# CONFIG_I2C_PCA_PLATFORM is not set
#
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
+# CONFIG_AT24 is not set
CONFIG_SENSORS_EEPROM=y
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
@@ -622,10 +642,13 @@ CONFIG_SENSORS_EEPROM=y
# CONFIG_I2C_DEBUG_BUS is not set
# CONFIG_I2C_DEBUG_CHIP is not set
# CONFIG_SPI is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+# CONFIG_GPIOLIB is not set
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7414 is not set
# CONFIG_SENSORS_AD7418 is not set
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
@@ -633,6 +656,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ADT7473 is not set
# CONFIG_SENSORS_ATXP1 is not set
@@ -675,6 +699,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_W83627EHF is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
CONFIG_WATCHDOG=y
# CONFIG_WATCHDOG_NOWAYOUT is not set
@@ -683,24 +708,39 @@ CONFIG_WATCHDOG=y
#
# CONFIG_SOFT_WATCHDOG is not set
# CONFIG_MPC5200_WDT is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
# Multifunction device drivers
#
+# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
#
+
+#
+# Multimedia core support
+#
# CONFIG_VIDEO_DEV is not set
# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
CONFIG_DAB=y
#
@@ -715,10 +755,6 @@ CONFIG_DAB=y
# Display device support
#
# CONFIG_DISPLAY_SUPPORT is not set
-
-#
-# Sound
-#
# CONFIG_SOUND is not set
# CONFIG_USB_SUPPORT is not set
# CONFIG_MMC is not set
@@ -729,6 +765,7 @@ CONFIG_LEDS_CLASS=y
#
# LED drivers
#
+# CONFIG_LEDS_PCA955X is not set
#
# LED Triggers
@@ -736,7 +773,9 @@ CONFIG_LEDS_CLASS=y
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=y
# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
+# CONFIG_ACCESSIBILITY is not set
# CONFIG_EDAC is not set
CONFIG_RTC_LIB=y
CONFIG_RTC_CLASS=y
@@ -767,6 +806,8 @@ CONFIG_RTC_DRV_DS1307=y
# CONFIG_RTC_DRV_PCF8583 is not set
# CONFIG_RTC_DRV_M41T80 is not set
# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
#
# SPI RTC drivers
@@ -776,19 +817,25 @@ CONFIG_RTC_DRV_DS1307=y
# Platform RTC drivers
#
# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
# CONFIG_RTC_DRV_DS1511 is not set
# CONFIG_RTC_DRV_DS1553 is not set
# CONFIG_RTC_DRV_DS1742 is not set
# CONFIG_RTC_DRV_STK17TA8 is not set
# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
# CONFIG_RTC_DRV_V3020 is not set
#
# on-CPU RTC drivers
#
+# CONFIG_RTC_DRV_PPC is not set
# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+CONFIG_STAGING_EXCLUDE_BUILD=y
#
# File systems
@@ -800,12 +847,13 @@ CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
CONFIG_JBD=y
CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
# CONFIG_XFS_FS is not set
# CONFIG_OCFS2_FS is not set
CONFIG_DNOTIFY=y
@@ -838,6 +886,7 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
@@ -868,6 +917,7 @@ CONFIG_JFFS2_RTIME=y
CONFIG_CRAMFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
# CONFIG_ROMFS_FS is not set
@@ -878,14 +928,14 @@ CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
CONFIG_NFS_V4=y
-# CONFIG_NFSD is not set
CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
-# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_SUNRPC_REGISTER_V4 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -961,9 +1011,9 @@ CONFIG_NLS_ISO8859_1=y
# Library routines
#
CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_CRC7 is not set
@@ -990,9 +1040,12 @@ CONFIG_FRAME_WARN=1024
CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_SHIRQ is not set
CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
# CONFIG_SLUB_DEBUG_ON is not set
# CONFIG_SLUB_STATS is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
@@ -1006,16 +1059,37 @@ CONFIG_SCHED_DEBUG=y
CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
-# CONFIG_DEBUGGER is not set
+# CONFIG_CODE_PATCHING_SELFTEST is not set
+# CONFIG_FTR_FIXUP_SELFTEST is not set
+# CONFIG_MSI_BITMAP_SELFTEST is not set
+# CONFIG_XMON is not set
# CONFIG_IRQSTACKS is not set
# CONFIG_BDI_SWITCH is not set
# CONFIG_BOOTX_TEXT is not set
@@ -1026,14 +1100,19 @@ CONFIG_DEBUG_INFO=y
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_CRYPTO=y
#
# Crypto core or helper
#
+# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_AEAD=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_RNG=y
CONFIG_CRYPTO_MANAGER=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
@@ -1071,6 +1150,10 @@ CONFIG_CRYPTO_PCBC=y
# CONFIG_CRYPTO_MD4 is not set
CONFIG_CRYPTO_MD5=y
# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
# CONFIG_CRYPTO_SHA1 is not set
# CONFIG_CRYPTO_SHA256 is not set
# CONFIG_CRYPTO_SHA512 is not set
@@ -1101,6 +1184,11 @@ CONFIG_CRYPTO_DES=y
#
# CONFIG_CRYPTO_DEFLATE is not set
# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
CONFIG_PPC_CLOCK=y
CONFIG_PPC_LIB_RHEAP=y
diff --git a/arch/powerpc/configs/52xx/pcm030_defconfig b/arch/powerpc/configs/52xx/pcm030_defconfig
index 9c0caa488b2..9d0207783d6 100644
--- a/arch/powerpc/configs/52xx/pcm030_defconfig
+++ b/arch/powerpc/configs/52xx/pcm030_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.25
-# Tue Apr 29 07:13:19 2008
+# Linux kernel version: 2.6.28-rc4
+# Thu Nov 13 02:13:16 2008
#
# CONFIG_PPC64 is not set
@@ -22,7 +22,7 @@ CONFIG_PPC_STD_MMU_32=y
# CONFIG_SMP is not set
CONFIG_PPC32=y
CONFIG_WORD_SIZE=32
-CONFIG_PPC_MERGE=y
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
CONFIG_MMU=y
CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_GENERIC_TIME=y
@@ -32,6 +32,7 @@ CONFIG_GENERIC_HARDIRQS=y
# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
CONFIG_IRQ_PER_CPU=y
CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
CONFIG_ARCH_HAS_ILOG2_U32=y
@@ -104,7 +105,9 @@ CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
+CONFIG_AIO=y
# CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_PCI_QUIRKS=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
@@ -112,24 +115,30 @@ CONFIG_SLAB=y
# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_HAVE_IOREMAP_PROT=y
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
-CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_CLK=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-# CONFIG_KMOD is not set
+CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
#
# IO Schedulers
@@ -144,19 +153,16 @@ CONFIG_IOSCHED_NOOP=y
CONFIG_DEFAULT_NOOP=y
CONFIG_DEFAULT_IOSCHED="noop"
CONFIG_CLASSIC_RCU=y
+# CONFIG_FREEZER is not set
#
# Platform support
#
CONFIG_PPC_MULTIPLATFORM=y
-# CONFIG_PPC_82xx is not set
-# CONFIG_PPC_83xx is not set
-# CONFIG_PPC_86xx is not set
CONFIG_CLASSIC32=y
# CONFIG_PPC_CHRP is not set
-# CONFIG_PPC_MPC512x is not set
-# CONFIG_PPC_MPC5121 is not set
# CONFIG_MPC5121_ADS is not set
+# CONFIG_MPC5121_GENERIC is not set
CONFIG_PPC_MPC52xx=y
CONFIG_PPC_MPC5200_SIMPLE=y
# CONFIG_PPC_EFIKA is not set
@@ -166,7 +172,10 @@ CONFIG_PPC_MPC5200_SIMPLE=y
# CONFIG_PPC_PMAC is not set
# CONFIG_PPC_CELL is not set
# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PPC_82xx is not set
# CONFIG_PQ2ADS is not set
+# CONFIG_PPC_83xx is not set
+# CONFIG_PPC_86xx is not set
# CONFIG_EMBEDDED6xx is not set
# CONFIG_IPIC is not set
# CONFIG_MPIC is not set
@@ -199,12 +208,14 @@ CONFIG_HZ_100=y
# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=100
-# CONFIG_SCHED_HRTICK is not set
+CONFIG_SCHED_HRTICK=y
# CONFIG_PREEMPT_NONE is not set
# CONFIG_PREEMPT_VOLUNTARY is not set
CONFIG_PREEMPT=y
# CONFIG_PREEMPT_RCU is not set
CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
# CONFIG_IOMMU_HELPER is not set
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
@@ -219,17 +230,19 @@ CONFIG_FLATMEM_MANUAL=y
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
+CONFIG_EXTRA_TARGETS=""
# CONFIG_PM is not set
# CONFIG_SECCOMP is not set
CONFIG_ISA_DMA_API=y
@@ -240,7 +253,7 @@ CONFIG_ISA_DMA_API=y
CONFIG_ZONE_DMA=y
CONFIG_GENERIC_ISA_DMA=y
# CONFIG_PPC_INDIRECT_PCI is not set
-CONFIG_FSL_SOC=y
+CONFIG_PPC_PCI_CHOICE=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
CONFIG_PCI_SYSCALL=y
@@ -265,10 +278,6 @@ CONFIG_PAGE_OFFSET=0xc0000000
CONFIG_KERNEL_START=0xc0000000
CONFIG_PHYSICAL_START=0x00000000
CONFIG_TASK_SIZE=0xc0000000
-
-#
-# Networking
-#
CONFIG_NET=y
#
@@ -313,6 +322,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
@@ -333,14 +343,8 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
-# CONFIG_CFG80211 is not set
-# CONFIG_WIRELESS_EXT is not set
-# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_PHONET is not set
+# CONFIG_WIRELESS is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -484,12 +488,12 @@ CONFIG_SCSI_WAIT_SCAN=m
# CONFIG_SCSI_SAS_LIBSAS is not set
# CONFIG_SCSI_SRP_ATTRS is not set
# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_SCSI_DH is not set
CONFIG_ATA=m
# CONFIG_ATA_NONSTANDARD is not set
CONFIG_SATA_PMP=y
# CONFIG_SATA_AHCI is not set
# CONFIG_SATA_SIL24 is not set
-# CONFIG_SATA_FSL is not set
CONFIG_ATA_SFF=y
# CONFIG_SATA_SVW is not set
# CONFIG_ATA_PIIX is not set
@@ -545,18 +549,22 @@ CONFIG_PATA_MPC52xx=m
# CONFIG_PATA_VIA is not set
# CONFIG_PATA_WINBOND is not set
# CONFIG_PATA_PLATFORM is not set
+# CONFIG_PATA_SCH is not set
# CONFIG_MD is not set
# CONFIG_FUSION is not set
#
# IEEE 1394 (FireWire) support
#
+
+#
+# Enable only one of the two stacks, unless you know what you are doing
+#
# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
# CONFIG_I2O is not set
# CONFIG_MACINTOSH_DRIVERS is not set
CONFIG_NETDEVICES=y
-# CONFIG_NETDEVICES_MULTIQUEUE is not set
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
@@ -593,10 +601,14 @@ CONFIG_MII=y
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
# CONFIG_NET_PCI is not set
# CONFIG_B44 is not set
CONFIG_FEC_MPC52xx=y
CONFIG_FEC_MPC52xx_MDIO=y
+# CONFIG_ATL2 is not set
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
# CONFIG_TR is not set
@@ -606,7 +618,6 @@ CONFIG_FEC_MPC52xx_MDIO=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI is not set
# CONFIG_IWLWIFI_LEDS is not set
#
@@ -644,6 +655,7 @@ CONFIG_FEC_MPC52xx_MDIO=y
# Character devices
#
# CONFIG_VT is not set
+CONFIG_DEVKMEM=y
# CONFIG_SERIAL_NONSTANDARD is not set
# CONFIG_NOZOMI is not set
@@ -675,43 +687,64 @@ CONFIG_DEVPORT=y
CONFIG_I2C=y
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
#
# I2C Hardware Bus support
#
+
+#
+# PC SMBus host controller drivers
+#
# CONFIG_I2C_ALI1535 is not set
# CONFIG_I2C_ALI1563 is not set
# CONFIG_I2C_ALI15X3 is not set
# CONFIG_I2C_AMD756 is not set
# CONFIG_I2C_AMD8111 is not set
# CONFIG_I2C_I801 is not set
-# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_ISCH is not set
# CONFIG_I2C_PIIX4 is not set
-CONFIG_I2C_MPC=y
# CONFIG_I2C_NFORCE2 is not set
-# CONFIG_I2C_OCORES is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PROSAVAGE is not set
-# CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_I2C_SIMTEC is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
-# CONFIG_I2C_TAOS_EVM is not set
-# CONFIG_I2C_STUB is not set
-# CONFIG_I2C_TINY_USB is not set
# CONFIG_I2C_VIA is not set
# CONFIG_I2C_VIAPRO is not set
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+CONFIG_I2C_MPC=y
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Graphics adapter I2C/DDC channel drivers
+#
# CONFIG_I2C_VOODOO3 is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
#
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
+# CONFIG_AT24 is not set
CONFIG_SENSORS_EEPROM=m
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
@@ -720,29 +753,47 @@ CONFIG_SENSORS_EEPROM=m
# CONFIG_I2C_DEBUG_BUS is not set
# CONFIG_I2C_DEBUG_CHIP is not set
# CONFIG_SPI is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+# CONFIG_GPIOLIB is not set
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
# CONFIG_HWMON is not set
# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
# Multifunction device drivers
#
+# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
#
+
+#
+# Multimedia core support
+#
# CONFIG_VIDEO_DEV is not set
# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
# CONFIG_DAB is not set
#
@@ -759,10 +810,6 @@ CONFIG_SSB_POSSIBLE=y
# Display device support
#
# CONFIG_DISPLAY_SUPPORT is not set
-
-#
-# Sound
-#
# CONFIG_SOUND is not set
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
@@ -781,12 +828,17 @@ CONFIG_USB_DEVICEFS=y
# CONFIG_USB_OTG is not set
# CONFIG_USB_OTG_WHITELIST is not set
# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
#
# USB Host Controller Drivers
#
+# CONFIG_USB_C67X00_HCD is not set
# CONFIG_USB_EHCI_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
CONFIG_USB_OHCI_HCD=m
# CONFIG_USB_OHCI_HCD_PPC_SOC is not set
CONFIG_USB_OHCI_HCD_PPC_OF=y
@@ -799,12 +851,17 @@ CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
# CONFIG_USB_UHCI_HCD is not set
# CONFIG_USB_SL811_HCD is not set
# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_WHCI_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+# CONFIG_USB_MUSB_HDRC is not set
#
# USB Device Class drivers
#
# CONFIG_USB_ACM is not set
# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -833,7 +890,6 @@ CONFIG_USB_STORAGE=m
#
# CONFIG_USB_MDC800 is not set
# CONFIG_USB_MICROTEK is not set
-# CONFIG_USB_MON is not set
#
# USB port drivers
@@ -846,7 +902,7 @@ CONFIG_USB_STORAGE=m
# CONFIG_USB_EMI62 is not set
# CONFIG_USB_EMI26 is not set
# CONFIG_USB_ADUTUX is not set
-# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_SEVSEG is not set
# CONFIG_USB_RIO500 is not set
# CONFIG_USB_LEGOTOWER is not set
# CONFIG_USB_LCD is not set
@@ -862,10 +918,14 @@ CONFIG_USB_STORAGE=m
# CONFIG_USB_TRANCEVIBRATOR is not set
# CONFIG_USB_IOWARRIOR is not set
# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
+# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
# CONFIG_INFINIBAND is not set
# CONFIG_EDAC is not set
CONFIG_RTC_LIB=m
@@ -894,6 +954,8 @@ CONFIG_RTC_DRV_PCF8563=m
# CONFIG_RTC_DRV_PCF8583 is not set
# CONFIG_RTC_DRV_M41T80 is not set
# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
#
# SPI RTC drivers
@@ -903,19 +965,25 @@ CONFIG_RTC_DRV_PCF8563=m
# Platform RTC drivers
#
# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
# CONFIG_RTC_DRV_DS1511 is not set
# CONFIG_RTC_DRV_DS1553 is not set
# CONFIG_RTC_DRV_DS1742 is not set
# CONFIG_RTC_DRV_STK17TA8 is not set
# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
# CONFIG_RTC_DRV_V3020 is not set
#
# on-CPU RTC drivers
#
+# CONFIG_RTC_DRV_PPC is not set
# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+CONFIG_STAGING_EXCLUDE_BUILD=y
#
# File systems
@@ -927,12 +995,13 @@ CONFIG_EXT3_FS=m
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
CONFIG_JBD=m
CONFIG_FS_MBCACHE=m
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
# CONFIG_XFS_FS is not set
# CONFIG_OCFS2_FS is not set
# CONFIG_DNOTIFY is not set
@@ -964,6 +1033,7 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
CONFIG_PROC_FS=y
# CONFIG_PROC_KCORE is not set
CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
@@ -994,6 +1064,7 @@ CONFIG_JFFS2_RTIME=y
# CONFIG_CRAMFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
# CONFIG_ROMFS_FS is not set
@@ -1004,13 +1075,13 @@ CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
# CONFIG_NFS_V4 is not set
-# CONFIG_NFSD is not set
CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_SUNRPC_REGISTER_V4 is not set
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -1070,9 +1141,9 @@ CONFIG_NLS_ISO8859_1=y
# Library routines
#
CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_CRC7 is not set
@@ -1098,7 +1169,17 @@ CONFIG_FRAME_WARN=1024
# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+
+#
+# Tracers
+#
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_IRQSTACKS is not set
# CONFIG_BOOTX_TEXT is not set
# CONFIG_PPC_EARLY_DEBUG is not set
@@ -1108,6 +1189,7 @@ CONFIG_FRAME_WARN=1024
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
# CONFIG_CRYPTO is not set
CONFIG_PPC_CLOCK=y
diff --git a/arch/powerpc/configs/52xx/tqm5200_defconfig b/arch/powerpc/configs/52xx/tqm5200_defconfig
index 7672bfba356..bc190051e8d 100644
--- a/arch/powerpc/configs/52xx/tqm5200_defconfig
+++ b/arch/powerpc/configs/52xx/tqm5200_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.25
-# Tue Apr 29 07:12:39 2008
+# Linux kernel version: 2.6.28-rc4
+# Thu Nov 13 02:09:30 2008
#
# CONFIG_PPC64 is not set
@@ -22,7 +22,7 @@ CONFIG_PPC_STD_MMU_32=y
# CONFIG_SMP is not set
CONFIG_PPC32=y
CONFIG_WORD_SIZE=32
-CONFIG_PPC_MERGE=y
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
CONFIG_MMU=y
CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_GENERIC_TIME=y
@@ -32,6 +32,7 @@ CONFIG_GENERIC_HARDIRQS=y
# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
CONFIG_IRQ_PER_CPU=y
CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
CONFIG_ARCH_HAS_ILOG2_U32=y
@@ -102,6 +103,7 @@ CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLUB_DEBUG=y
# CONFIG_SLAB is not set
@@ -110,14 +112,19 @@ CONFIG_SLUB=y
# CONFIG_PROFILING is not set
# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_HAVE_IOREMAP_PROT=y
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
-CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_CLK=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
CONFIG_MODVERSIONS=y
@@ -128,6 +135,7 @@ CONFIG_BLOCK=y
# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
#
# IO Schedulers
@@ -142,19 +150,16 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_FREEZER is not set
#
# Platform support
#
CONFIG_PPC_MULTIPLATFORM=y
-# CONFIG_PPC_82xx is not set
-# CONFIG_PPC_83xx is not set
-# CONFIG_PPC_86xx is not set
CONFIG_CLASSIC32=y
# CONFIG_PPC_CHRP is not set
-# CONFIG_PPC_MPC512x is not set
-# CONFIG_PPC_MPC5121 is not set
# CONFIG_MPC5121_ADS is not set
+# CONFIG_MPC5121_GENERIC is not set
CONFIG_PPC_MPC52xx=y
CONFIG_PPC_MPC5200_SIMPLE=y
# CONFIG_PPC_EFIKA is not set
@@ -164,7 +169,10 @@ CONFIG_PPC_MPC5200_BUGFIX=y
# CONFIG_PPC_PMAC is not set
# CONFIG_PPC_CELL is not set
# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PPC_82xx is not set
# CONFIG_PQ2ADS is not set
+# CONFIG_PPC_83xx is not set
+# CONFIG_PPC_86xx is not set
# CONFIG_EMBEDDED6xx is not set
# CONFIG_IPIC is not set
# CONFIG_MPIC is not set
@@ -188,7 +196,6 @@ CONFIG_PPC_BESTCOMM_FEC=y
# Kernel options
#
# CONFIG_HIGHMEM is not set
-# CONFIG_TICK_ONESHOT is not set
# CONFIG_NO_HZ is not set
# CONFIG_HIGH_RES_TIMERS is not set
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
@@ -202,6 +209,8 @@ CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not set
CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
# CONFIG_IOMMU_HELPER is not set
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
@@ -216,19 +225,20 @@ CONFIG_FLATMEM_MANUAL=y
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
+CONFIG_EXTRA_TARGETS=""
CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
# CONFIG_PM_DEBUG is not set
CONFIG_SECCOMP=y
CONFIG_ISA_DMA_API=y
@@ -238,7 +248,7 @@ CONFIG_ISA_DMA_API=y
#
CONFIG_ZONE_DMA=y
CONFIG_GENERIC_ISA_DMA=y
-CONFIG_FSL_SOC=y
+CONFIG_PPC_PCI_CHOICE=y
# CONFIG_PCI is not set
# CONFIG_PCI_DOMAINS is not set
# CONFIG_PCI_SYSCALL is not set
@@ -259,10 +269,6 @@ CONFIG_PAGE_OFFSET=0xc0000000
CONFIG_KERNEL_START=0xc0000000
CONFIG_PHYSICAL_START=0x00000000
CONFIG_TASK_SIZE=0xc0000000
-
-#
-# Networking
-#
CONFIG_NET=y
#
@@ -313,6 +319,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
@@ -333,14 +340,8 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
-# CONFIG_CFG80211 is not set
-# CONFIG_WIRELESS_EXT is not set
-# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_PHONET is not set
+# CONFIG_WIRELESS is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -451,6 +452,7 @@ CONFIG_BLK_DEV_RAM_SIZE=32768
# CONFIG_BLK_DEV_XIP is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
# CONFIG_MISC_DEVICES is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -495,10 +497,10 @@ CONFIG_SCSI_WAIT_SCAN=m
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
CONFIG_ATA=y
# CONFIG_ATA_NONSTANDARD is not set
CONFIG_SATA_PMP=y
-# CONFIG_SATA_FSL is not set
CONFIG_ATA_SFF=y
# CONFIG_SATA_MV is not set
CONFIG_PATA_MPC52xx=y
@@ -507,7 +509,6 @@ CONFIG_PATA_PLATFORM=y
# CONFIG_MD is not set
# CONFIG_MACINTOSH_DRIVERS is not set
CONFIG_NETDEVICES=y
-# CONFIG_NETDEVICES_MULTIQUEUE is not set
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
@@ -537,6 +538,9 @@ CONFIG_NET_ETHERNET=y
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
# CONFIG_B44 is not set
CONFIG_FEC_MPC52xx=y
CONFIG_FEC_MPC52xx_MDIO=y
@@ -548,7 +552,6 @@ CONFIG_FEC_MPC52xx_MDIO=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI is not set
# CONFIG_IWLWIFI_LEDS is not set
#
@@ -583,6 +586,7 @@ CONFIG_FEC_MPC52xx_MDIO=y
# Character devices
#
# CONFIG_VT is not set
+CONFIG_DEVKMEM=y
# CONFIG_SERIAL_NONSTANDARD is not set
#
@@ -611,26 +615,41 @@ CONFIG_LEGACY_PTY_COUNT=256
CONFIG_I2C=y
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
#
# I2C Hardware Bus support
#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
CONFIG_I2C_MPC=y
# CONFIG_I2C_OCORES is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_TAOS_EVM is not set
-# CONFIG_I2C_STUB is not set
# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
#
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
+# CONFIG_AT24 is not set
# CONFIG_SENSORS_EEPROM is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
@@ -639,10 +658,13 @@ CONFIG_I2C_MPC=y
# CONFIG_I2C_DEBUG_BUS is not set
# CONFIG_I2C_DEBUG_CHIP is not set
# CONFIG_SPI is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+# CONFIG_GPIOLIB is not set
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7414 is not set
# CONFIG_SENSORS_AD7418 is not set
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
@@ -650,6 +672,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ADT7473 is not set
# CONFIG_SENSORS_ATXP1 is not set
@@ -692,6 +715,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_W83627EHF is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
CONFIG_WATCHDOG=y
# CONFIG_WATCHDOG_NOWAYOUT is not set
@@ -705,24 +729,39 @@ CONFIG_WATCHDOG=y
# USB-based Watchdog Cards
#
# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
# Multifunction device drivers
#
+# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
#
+
+#
+# Multimedia core support
+#
# CONFIG_VIDEO_DEV is not set
# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
# CONFIG_DAB is not set
#
@@ -737,10 +776,6 @@ CONFIG_SSB_POSSIBLE=y
# Display device support
#
# CONFIG_DISPLAY_SUPPORT is not set
-
-#
-# Sound
-#
# CONFIG_SOUND is not set
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
@@ -760,11 +795,16 @@ CONFIG_USB_DEVICEFS=y
# CONFIG_USB_OTG is not set
# CONFIG_USB_OTG_WHITELIST is not set
# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
#
# USB Host Controller Drivers
#
+# CONFIG_USB_C67X00_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_OHCI_HCD_PPC_SOC=y
CONFIG_USB_OHCI_HCD_PPC_OF=y
@@ -775,12 +815,16 @@ CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
# CONFIG_USB_OHCI_LITTLE_ENDIAN is not set
# CONFIG_USB_SL811_HCD is not set
# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+# CONFIG_USB_MUSB_HDRC is not set
#
# USB Device Class drivers
#
# CONFIG_USB_ACM is not set
# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -809,7 +853,6 @@ CONFIG_USB_STORAGE=y
#
# CONFIG_USB_MDC800 is not set
# CONFIG_USB_MICROTEK is not set
-CONFIG_USB_MON=y
#
# USB port drivers
@@ -822,7 +865,7 @@ CONFIG_USB_MON=y
# CONFIG_USB_EMI62 is not set
# CONFIG_USB_EMI26 is not set
# CONFIG_USB_ADUTUX is not set
-# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_SEVSEG is not set
# CONFIG_USB_RIO500 is not set
# CONFIG_USB_LEGOTOWER is not set
# CONFIG_USB_LCD is not set
@@ -838,10 +881,13 @@ CONFIG_USB_MON=y
# CONFIG_USB_TRANCEVIBRATOR is not set
# CONFIG_USB_IOWARRIOR is not set
# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
# CONFIG_EDAC is not set
CONFIG_RTC_LIB=y
CONFIG_RTC_CLASS=y
@@ -872,6 +918,8 @@ CONFIG_RTC_DRV_DS1307=y
# CONFIG_RTC_DRV_PCF8583 is not set
# CONFIG_RTC_DRV_M41T80 is not set
# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
#
# SPI RTC drivers
@@ -881,19 +929,25 @@ CONFIG_RTC_DRV_DS1307=y
# Platform RTC drivers
#
# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
# CONFIG_RTC_DRV_DS1511 is not set
# CONFIG_RTC_DRV_DS1553 is not set
# CONFIG_RTC_DRV_DS1742 is not set
# CONFIG_RTC_DRV_STK17TA8 is not set
# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
# CONFIG_RTC_DRV_V3020 is not set
#
# on-CPU RTC drivers
#
+# CONFIG_RTC_DRV_PPC is not set
# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+CONFIG_STAGING_EXCLUDE_BUILD=y
#
# File systems
@@ -905,12 +959,13 @@ CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
CONFIG_JBD=y
CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
# CONFIG_XFS_FS is not set
# CONFIG_OCFS2_FS is not set
CONFIG_DNOTIFY=y
@@ -943,6 +998,7 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
@@ -973,6 +1029,7 @@ CONFIG_JFFS2_RTIME=y
CONFIG_CRAMFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
# CONFIG_ROMFS_FS is not set
@@ -983,14 +1040,14 @@ CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
CONFIG_NFS_V4=y
-# CONFIG_NFSD is not set
CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
-# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_SUNRPC_REGISTER_V4 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -1066,9 +1123,9 @@ CONFIG_NLS_ISO8859_1=y
# Library routines
#
CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_CRC7 is not set
@@ -1095,9 +1152,12 @@ CONFIG_FRAME_WARN=1024
CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_SHIRQ is not set
CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
# CONFIG_SLUB_DEBUG_ON is not set
# CONFIG_SLUB_STATS is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
@@ -1111,17 +1171,37 @@ CONFIG_SCHED_DEBUG=y
CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
-# CONFIG_DEBUGGER is not set
+# CONFIG_CODE_PATCHING_SELFTEST is not set
+# CONFIG_FTR_FIXUP_SELFTEST is not set
+# CONFIG_MSI_BITMAP_SELFTEST is not set
+# CONFIG_XMON is not set
# CONFIG_IRQSTACKS is not set
# CONFIG_BDI_SWITCH is not set
# CONFIG_BOOTX_TEXT is not set
@@ -1132,14 +1212,19 @@ CONFIG_DEBUG_INFO=y
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_CRYPTO=y
#
# Crypto core or helper
#
+# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_AEAD=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_RNG=y
CONFIG_CRYPTO_MANAGER=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
@@ -1178,6 +1263,10 @@ CONFIG_CRYPTO_PCBC=y
# CONFIG_CRYPTO_MD4 is not set
CONFIG_CRYPTO_MD5=y
# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
# CONFIG_CRYPTO_SHA1 is not set
# CONFIG_CRYPTO_SHA256 is not set
# CONFIG_CRYPTO_SHA512 is not set
@@ -1208,6 +1297,11 @@ CONFIG_CRYPTO_DES=y
#
# CONFIG_CRYPTO_DEFLATE is not set
# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
CONFIG_PPC_CLOCK=y
CONFIG_PPC_LIB_RHEAP=y
diff --git a/arch/powerpc/configs/83xx/mpc834x_itx_defconfig b/arch/powerpc/configs/83xx/mpc834x_itx_defconfig
index e55ff7c47a3..07a674f5344 100644
--- a/arch/powerpc/configs/83xx/mpc834x_itx_defconfig
+++ b/arch/powerpc/configs/83xx/mpc834x_itx_defconfig
@@ -723,7 +723,7 @@ CONFIG_CICADA_PHY=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
-# CONFIG_FIXED_PHY is not set
+CONFIG_FIXED_PHY=y
# CONFIG_MDIO_BITBANG is not set
# CONFIG_NET_ETHERNET is not set
CONFIG_NETDEV_1000=y
diff --git a/arch/powerpc/configs/86xx/gef_sbc610_defconfig b/arch/powerpc/configs/86xx/gef_sbc610_defconfig
index 2da13e00a80..07ccaf89f37 100644
--- a/arch/powerpc/configs/86xx/gef_sbc610_defconfig
+++ b/arch/powerpc/configs/86xx/gef_sbc610_defconfig
@@ -838,7 +838,7 @@ CONFIG_PHYLIB=y
#
# MII PHY device drivers
#
-CONFIG_MARVELL_PHY=y
+# CONFIG_MARVELL_PHY is not set
# CONFIG_DAVICOM_PHY is not set
# CONFIG_QSEMI_PHY is not set
# CONFIG_LXT_PHY is not set
diff --git a/arch/powerpc/configs/mpc5200_defconfig b/arch/powerpc/configs/mpc5200_defconfig
index 740c9f2b7de..15c5604d0b2 100644
--- a/arch/powerpc/configs/mpc5200_defconfig
+++ b/arch/powerpc/configs/mpc5200_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.24-rc6
-# Fri Jan 18 14:19:54 2008
+# Linux kernel version: 2.6.28-rc4
+# Thu Nov 13 02:09:07 2008
#
# CONFIG_PPC64 is not set
@@ -22,14 +22,18 @@ CONFIG_PPC_STD_MMU_32=y
# CONFIG_SMP is not set
CONFIG_PPC32=y
CONFIG_WORD_SIZE=32
-CONFIG_PPC_MERGE=y
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
CONFIG_MMU=y
CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_TIME_VSYSCALL=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_HARDIRQS=y
+# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
CONFIG_IRQ_PER_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
CONFIG_ARCH_HAS_ILOG2_U32=y
CONFIG_GENERIC_HWEIGHT=y
@@ -47,7 +51,8 @@ CONFIG_OF=y
# CONFIG_GENERIC_TBSYNC is not set
CONFIG_AUDIT_ARCH=y
CONFIG_GENERIC_BUG=y
-# CONFIG_DEFAULT_UIMAGE is not set
+CONFIG_DEFAULT_UIMAGE=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
# CONFIG_PPC_DCR_NATIVE is not set
# CONFIG_PPC_DCR_MMIO is not set
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -66,17 +71,15 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
-# CONFIG_USER_NS is not set
-# CONFIG_PID_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_CGROUPS is not set
-CONFIG_FAIR_GROUP_SCHED=y
-CONFIG_FAIR_USER_SCHED=y
-# CONFIG_FAIR_CGROUP_SCHED is not set
+# CONFIG_GROUP_SCHED is not set
CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -88,32 +91,49 @@ CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
+CONFIG_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_ANON_INODES=y
# CONFIG_EPOLL is not set
CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
CONFIG_SLUB_DEBUG=y
# CONFIG_SLAB is not set
CONFIG_SLUB=y
# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_CLK=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-# CONFIG_KMOD is not set
+CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
#
# IO Schedulers
@@ -127,29 +147,34 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_CLASSIC_RCU=y
+CONFIG_FREEZER=y
#
# Platform support
#
CONFIG_PPC_MULTIPLATFORM=y
-# CONFIG_PPC_82xx is not set
-# CONFIG_PPC_83xx is not set
-# CONFIG_PPC_86xx is not set
CONFIG_CLASSIC32=y
# CONFIG_PPC_CHRP is not set
+# CONFIG_MPC5121_ADS is not set
+# CONFIG_MPC5121_GENERIC is not set
CONFIG_PPC_MPC52xx=y
-CONFIG_PPC_MPC5200=y
-CONFIG_PPC_MPC5200_BUGFIX=y
CONFIG_PPC_MPC5200_SIMPLE=y
CONFIG_PPC_EFIKA=y
CONFIG_PPC_LITE5200=y
+CONFIG_PPC_MPC5200_BUGFIX=y
+# CONFIG_PPC_MPC5200_GPIO is not set
# CONFIG_PPC_PMAC is not set
# CONFIG_PPC_CELL is not set
# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PPC_82xx is not set
# CONFIG_PQ2ADS is not set
+# CONFIG_PPC_83xx is not set
+# CONFIG_PPC_86xx is not set
# CONFIG_EMBEDDED6xx is not set
CONFIG_PPC_NATIVE=y
# CONFIG_UDBG_RTAS_CONSOLE is not set
+# CONFIG_IPIC is not set
# CONFIG_MPIC is not set
# CONFIG_MPIC_WEIRD is not set
# CONFIG_PPC_I8259 is not set
@@ -163,7 +188,6 @@ CONFIG_RTAS_PROC=y
# CONFIG_GENERIC_IOMAP is not set
# CONFIG_CPU_FREQ is not set
# CONFIG_TAU is not set
-# CONFIG_CPM2 is not set
# CONFIG_FSL_ULI1575 is not set
CONFIG_PPC_BESTCOMM=y
CONFIG_PPC_BESTCOMM_ATA=y
@@ -183,12 +207,18 @@ CONFIG_HZ_250=y
# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
+CONFIG_SCHED_HRTICK=y
CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not set
CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
+# CONFIG_IOMMU_HELPER is not set
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_HAS_WALK_MEMORY=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
# CONFIG_KEXEC is not set
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
@@ -198,26 +228,25 @@ CONFIG_FLATMEM_MANUAL=y
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
+CONFIG_EXTRA_TARGETS=""
CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
# CONFIG_PM_DEBUG is not set
CONFIG_PM_SLEEP=y
-CONFIG_SUSPEND_UP_POSSIBLE=y
CONFIG_SUSPEND=y
-CONFIG_HIBERNATION_UP_POSSIBLE=y
-# CONFIG_HIBERNATION is not set
+CONFIG_SUSPEND_FREEZER=y
CONFIG_SECCOMP=y
-CONFIG_WANT_DEVICE_TREE=y
-CONFIG_DEVICE_TREE=""
CONFIG_ISA_DMA_API=y
#
@@ -226,7 +255,7 @@ CONFIG_ISA_DMA_API=y
CONFIG_ZONE_DMA=y
CONFIG_GENERIC_ISA_DMA=y
# CONFIG_PPC_INDIRECT_PCI is not set
-CONFIG_FSL_SOC=y
+CONFIG_PPC_PCI_CHOICE=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
CONFIG_PCI_SYSCALL=y
@@ -237,6 +266,7 @@ CONFIG_PCI_LEGACY=y
# CONFIG_PCI_DEBUG is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
+# CONFIG_HAS_RAPIDIO is not set
#
# Advanced setup
@@ -246,15 +276,11 @@ CONFIG_PCI_LEGACY=y
#
# Default settings for advanced configuration options are used
#
-CONFIG_HIGHMEM_START=0xfe000000
CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_PAGE_OFFSET=0xc0000000
CONFIG_KERNEL_START=0xc0000000
+CONFIG_PHYSICAL_START=0x00000000
CONFIG_TASK_SIZE=0xc0000000
-CONFIG_BOOT_LOAD=0x00800000
-
-#
-# Networking
-#
CONFIG_NET=y
#
@@ -267,6 +293,7 @@ CONFIG_XFRM=y
CONFIG_XFRM_USER=m
# CONFIG_XFRM_SUB_POLICY is not set
# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
@@ -297,8 +324,6 @@ CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
# CONFIG_IPV6 is not set
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
# CONFIG_IP_DCCP is not set
@@ -306,6 +331,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
@@ -322,17 +348,12 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
-# CONFIG_CFG80211 is not set
-# CONFIG_WIRELESS_EXT is not set
-# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_PHONET is not set
+# CONFIG_WIRELESS is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -357,6 +378,8 @@ CONFIG_MTD_CONCAT=y
CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_REDBOOT_PARTS is not set
CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_OF_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
#
# User Modules And Translation Layers
@@ -428,6 +451,7 @@ CONFIG_MTD_PHYSMAP_OF=y
#
# CONFIG_MTD_UBI is not set
CONFIG_OF_DEVICE=y
+CONFIG_OF_I2C=y
# CONFIG_PARPORT is not set
CONFIG_BLK_DEV=y
# CONFIG_BLK_DEV_FD is not set
@@ -444,14 +468,20 @@ CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=32768
-CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_BLK_DEV_XIP is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
CONFIG_MISC_DEVICES=y
# CONFIG_PHANTOM is not set
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
+CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
#
@@ -516,6 +546,7 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_SCSI_IPS is not set
# CONFIG_SCSI_INITIO is not set
# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_MVSAS is not set
# CONFIG_SCSI_STEX is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
# CONFIG_SCSI_IPR is not set
@@ -528,9 +559,13 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_SCSI_NSP32 is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_SRP is not set
+# CONFIG_SCSI_DH is not set
CONFIG_ATA=y
# CONFIG_ATA_NONSTANDARD is not set
+CONFIG_SATA_PMP=y
# CONFIG_SATA_AHCI is not set
+# CONFIG_SATA_SIL24 is not set
+CONFIG_ATA_SFF=y
# CONFIG_SATA_SVW is not set
# CONFIG_ATA_PIIX is not set
# CONFIG_SATA_MV is not set
@@ -540,7 +575,6 @@ CONFIG_ATA=y
# CONFIG_SATA_PROMISE is not set
# CONFIG_SATA_SX4 is not set
# CONFIG_SATA_SIL is not set
-# CONFIG_SATA_SIL24 is not set
# CONFIG_SATA_SIS is not set
# CONFIG_SATA_ULI is not set
# CONFIG_SATA_VIA is not set
@@ -570,6 +604,7 @@ CONFIG_PATA_MPC52xx=y
# CONFIG_PATA_MPIIX is not set
# CONFIG_PATA_OLDPIIX is not set
# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NINJA32 is not set
# CONFIG_PATA_NS87410 is not set
# CONFIG_PATA_NS87415 is not set
# CONFIG_PATA_OPTI is not set
@@ -586,25 +621,28 @@ CONFIG_PATA_MPC52xx=y
# CONFIG_PATA_WINBOND is not set
CONFIG_PATA_PLATFORM=y
# CONFIG_PATA_OF_PLATFORM is not set
+# CONFIG_PATA_SCH is not set
# CONFIG_MD is not set
# CONFIG_FUSION is not set
#
# IEEE 1394 (FireWire) support
#
+
+#
+# Enable only one of the two stacks, unless you know what you are doing
+#
# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
# CONFIG_I2O is not set
# CONFIG_MACINTOSH_DRIVERS is not set
CONFIG_NETDEVICES=y
-# CONFIG_NETDEVICES_MULTIQUEUE is not set
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
# CONFIG_VETH is not set
-# CONFIG_IP1000 is not set
# CONFIG_ARCNET is not set
CONFIG_PHYLIB=y
@@ -620,6 +658,7 @@ CONFIG_PHYLIB=y
# CONFIG_SMSC_PHY is not set
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -634,10 +673,14 @@ CONFIG_NET_ETHERNET=y
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
# CONFIG_NET_PCI is not set
# CONFIG_B44 is not set
CONFIG_FEC_MPC52xx=y
CONFIG_FEC_MPC52xx_MDIO=y
+# CONFIG_ATL2 is not set
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
# CONFIG_TR is not set
@@ -647,6 +690,7 @@ CONFIG_FEC_MPC52xx_MDIO=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
#
# USB Network Adapters
@@ -662,7 +706,6 @@ CONFIG_FEC_MPC52xx_MDIO=y
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
# CONFIG_NET_FC is not set
-# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
@@ -672,7 +715,30 @@ CONFIG_FEC_MPC52xx_MDIO=y
#
# Input device support
#
-# CONFIG_INPUT is not set
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
#
# Hardware I/O ports
@@ -683,8 +749,14 @@ CONFIG_FEC_MPC52xx_MDIO=y
#
# Character devices
#
-# CONFIG_VT is not set
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
#
# Serial drivers
@@ -718,16 +790,15 @@ CONFIG_DEVPORT=y
CONFIG_I2C=y
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+CONFIG_I2C_ALGOBIT=y
#
-# I2C Algorithms
+# I2C Hardware Bus support
#
-# CONFIG_I2C_ALGOBIT is not set
-# CONFIG_I2C_ALGOPCF is not set
-# CONFIG_I2C_ALGOPCA is not set
#
-# I2C Hardware Bus support
+# PC SMBus host controller drivers
#
# CONFIG_I2C_ALI1535 is not set
# CONFIG_I2C_ALI1563 is not set
@@ -735,52 +806,64 @@ CONFIG_I2C_CHARDEV=y
# CONFIG_I2C_AMD756 is not set
# CONFIG_I2C_AMD8111 is not set
# CONFIG_I2C_I801 is not set
-# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_ISCH is not set
# CONFIG_I2C_PIIX4 is not set
-CONFIG_I2C_MPC=y
# CONFIG_I2C_NFORCE2 is not set
-# CONFIG_I2C_OCORES is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PROSAVAGE is not set
-# CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_I2C_SIMTEC is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
-# CONFIG_I2C_TAOS_EVM is not set
-# CONFIG_I2C_STUB is not set
-# CONFIG_I2C_TINY_USB is not set
# CONFIG_I2C_VIA is not set
# CONFIG_I2C_VIAPRO is not set
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+CONFIG_I2C_MPC=y
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Graphics adapter I2C/DDC channel drivers
+#
# CONFIG_I2C_VOODOO3 is not set
#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
# Miscellaneous I2C Chip support
#
-# CONFIG_SENSORS_DS1337 is not set
-# CONFIG_SENSORS_DS1374 is not set
# CONFIG_DS1682 is not set
+# CONFIG_AT24 is not set
# CONFIG_SENSORS_EEPROM is not set
# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_M41T00 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
# CONFIG_I2C_DEBUG_CHIP is not set
-
-#
-# SPI support
-#
# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+# CONFIG_GPIOLIB is not set
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7414 is not set
# CONFIG_SENSORS_AD7418 is not set
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
@@ -788,7 +871,9 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_I5K_AMB is not set
@@ -818,6 +903,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_SMSC47M192 is not set
# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
# CONFIG_SENSORS_THMC50 is not set
# CONFIG_SENSORS_VIA686A is not set
# CONFIG_SENSORS_VT1211 is not set
@@ -827,9 +913,12 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_W83792D is not set
# CONFIG_SENSORS_W83793 is not set
# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
CONFIG_WATCHDOG=y
# CONFIG_WATCHDOG_NOWAYOUT is not set
@@ -837,6 +926,7 @@ CONFIG_WATCHDOG=y
# Watchdog Device Drivers
#
# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_ALIM7101_WDT is not set
# CONFIG_MPC5200_WDT is not set
# CONFIG_WATCHDOG_RTAS is not set
@@ -850,23 +940,39 @@ CONFIG_WATCHDOG=y
# USB-based Watchdog Cards
#
# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
# Multifunction device drivers
#
+# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
#
+
+#
+# Multimedia core support
+#
# CONFIG_VIDEO_DEV is not set
# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
CONFIG_DAB=y
# CONFIG_USB_DABUSB is not set
@@ -874,11 +980,78 @@ CONFIG_DAB=y
# Graphics support
#
# CONFIG_AGP is not set
-# CONFIG_DRM is not set
+CONFIG_DRM=y
+# CONFIG_DRM_TDFX is not set
+# CONFIG_DRM_R128 is not set
+# CONFIG_DRM_RADEON is not set
+# CONFIG_DRM_MGA is not set
+# CONFIG_DRM_VIA is not set
+# CONFIG_DRM_SAVAGE is not set
# CONFIG_VGASTATE is not set
-CONFIG_VIDEO_OUTPUT_CONTROL=m
-# CONFIG_FB is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=y
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FB_DDC=y
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+CONFIG_FB_MACMODES=y
+CONFIG_FB_BACKLIGHT=y
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_OF is not set
+# CONFIG_FB_CT65550 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_VGA16 is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+CONFIG_FB_RADEON=y
+CONFIG_FB_RADEON_I2C=y
+CONFIG_FB_RADEON_BACKLIGHT=y
+# CONFIG_FB_RADEON_DEBUG is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_VIA is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
+# CONFIG_FB_CARMINE is not set
+# CONFIG_FB_IBM_GXT4500 is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=m
+# CONFIG_LCD_ILI9320 is not set
+# CONFIG_LCD_PLATFORM is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+# CONFIG_BACKLIGHT_CORGI is not set
#
# Display device support
@@ -886,15 +1059,64 @@ CONFIG_VIDEO_OUTPUT_CONTROL=m
# CONFIG_DISPLAY_SUPPORT is not set
#
-# Sound
-#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
# CONFIG_SOUND is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
+CONFIG_HID_A4TECH=y
+# CONFIG_HID_APPLE is not set
+CONFIG_HID_BELKIN=y
+CONFIG_HID_BRIGHT=y
+CONFIG_HID_CHERRY=y
+# CONFIG_HID_CHICONY is not set
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_DELL=y
+CONFIG_HID_EZKEY=y
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_LOGITECH is not set
+# CONFIG_HID_MICROSOFT is not set
+# CONFIG_HID_MONTEREY is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SONY is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_THRUSTMASTER_FF is not set
+# CONFIG_ZEROPLUS_FF is not set
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
CONFIG_USB_ARCH_HAS_EHCI=y
CONFIG_USB=y
# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
#
# Miscellaneous USB options
@@ -903,14 +1125,20 @@ CONFIG_USB_DEVICEFS=y
# CONFIG_USB_DEVICE_CLASS is not set
# CONFIG_USB_DYNAMIC_MINORS is not set
# CONFIG_USB_SUSPEND is not set
-# CONFIG_USB_PERSIST is not set
# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
#
# USB Host Controller Drivers
#
+# CONFIG_USB_C67X00_HCD is not set
# CONFIG_USB_EHCI_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_OHCI_HCD_PPC_SOC=y
CONFIG_USB_OHCI_HCD_PPC_OF=y
@@ -923,12 +1151,17 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_UHCI_HCD is not set
# CONFIG_USB_SL811_HCD is not set
# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_WHCI_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+# CONFIG_USB_MUSB_HDRC is not set
#
# USB Device Class drivers
#
# CONFIG_USB_ACM is not set
# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -948,7 +1181,9 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_SDDR55 is not set
# CONFIG_USB_STORAGE_JUMPSHOT is not set
# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
# CONFIG_USB_LIBUSUAL is not set
#
@@ -956,15 +1191,10 @@ CONFIG_USB_STORAGE=y
#
# CONFIG_USB_MDC800 is not set
# CONFIG_USB_MICROTEK is not set
-CONFIG_USB_MON=y
#
# USB port drivers
#
-
-#
-# USB Serial Converter support
-#
# CONFIG_USB_SERIAL is not set
#
@@ -973,7 +1203,7 @@ CONFIG_USB_MON=y
# CONFIG_USB_EMI62 is not set
# CONFIG_USB_EMI26 is not set
# CONFIG_USB_ADUTUX is not set
-# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_SEVSEG is not set
# CONFIG_USB_RIO500 is not set
# CONFIG_USB_LEGOTOWER is not set
# CONFIG_USB_LCD is not set
@@ -989,18 +1219,14 @@ CONFIG_USB_MON=y
# CONFIG_USB_TRANCEVIBRATOR is not set
# CONFIG_USB_IOWARRIOR is not set
# CONFIG_USB_TEST is not set
-
-#
-# USB DSL modem support
-#
-
-#
-# USB Gadget Support
-#
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
+# CONFIG_UWB is not set
# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
+# CONFIG_LEDS_CLASS is not set
#
# LED drivers
@@ -1009,17 +1235,15 @@ CONFIG_LEDS_CLASS=y
#
# LED Triggers
#
-CONFIG_LEDS_TRIGGERS=y
-CONFIG_LEDS_TRIGGER_TIMER=y
-# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set
+# CONFIG_LEDS_TRIGGERS is not set
+# CONFIG_ACCESSIBILITY is not set
# CONFIG_INFINIBAND is not set
# CONFIG_EDAC is not set
# CONFIG_RTC_CLASS is not set
-
-#
-# Userspace I/O
-#
+# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+CONFIG_STAGING_EXCLUDE_BUILD=y
#
# File systems
@@ -1031,21 +1255,19 @@ CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
CONFIG_JBD=y
CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
# CONFIG_XFS_FS is not set
-# CONFIG_GFS2_FS is not set
# CONFIG_OCFS2_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
+CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
# CONFIG_FUSE_FS is not set
@@ -1072,6 +1294,7 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
@@ -1101,8 +1324,11 @@ CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
CONFIG_CRAMFS=y
# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
@@ -1110,15 +1336,14 @@ CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
CONFIG_NFS_V4=y
-# CONFIG_NFS_DIRECTIO is not set
-# CONFIG_NFSD is not set
CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
-# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_SUNRPC_REGISTER_V4 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -1173,7 +1398,6 @@ CONFIG_NLS_ISO8859_1=y
# CONFIG_NLS_KOI8_U is not set
# CONFIG_NLS_UTF8 is not set
# CONFIG_DLM is not set
-# CONFIG_UCC_SLOW is not set
#
# Library routines
@@ -1181,6 +1405,7 @@ CONFIG_NLS_ISO8859_1=y
CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_CRC7 is not set
@@ -1191,7 +1416,7 @@ CONFIG_PLIST=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
CONFIG_HAS_DMA=y
-# CONFIG_INSTRUMENTATION is not set
+CONFIG_HAVE_LMB=y
#
# Kernel hacking
@@ -1199,6 +1424,7 @@ CONFIG_HAS_DMA=y
CONFIG_PRINTK_TIME=y
CONFIG_ENABLE_WARN_DEPRECATED=y
CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
# CONFIG_DEBUG_FS is not set
@@ -1206,10 +1432,14 @@ CONFIG_ENABLE_MUST_CHECK=y
CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_SHIRQ is not set
CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
@@ -1220,17 +1450,39 @@ CONFIG_SCHED_DEBUG=y
# CONFIG_DEBUG_BUGVERBOSE is not set
CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
-CONFIG_FORCED_INLINING=y
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
-# CONFIG_DEBUGGER is not set
+# CONFIG_CODE_PATCHING_SELFTEST is not set
+# CONFIG_FTR_FIXUP_SELFTEST is not set
+# CONFIG_MSI_BITMAP_SELFTEST is not set
+# CONFIG_XMON is not set
+# CONFIG_IRQSTACKS is not set
# CONFIG_BDI_SWITCH is not set
# CONFIG_BOOTX_TEXT is not set
# CONFIG_PPC_EARLY_DEBUG is not set
@@ -1240,47 +1492,98 @@ CONFIG_FORCED_INLINING=y
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_AEAD=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_RNG=y
CONFIG_CRYPTO_MANAGER=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
# CONFIG_CRYPTO_HMAC is not set
# CONFIG_CRYPTO_XCBC is not set
-# CONFIG_CRYPTO_NULL is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
# CONFIG_CRYPTO_MD4 is not set
CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
# CONFIG_CRYPTO_SHA1 is not set
# CONFIG_CRYPTO_SHA256 is not set
# CONFIG_CRYPTO_SHA512 is not set
-# CONFIG_CRYPTO_WP512 is not set
# CONFIG_CRYPTO_TGR192 is not set
-# CONFIG_CRYPTO_GF128MUL is not set
-# CONFIG_CRYPTO_ECB is not set
-CONFIG_CRYPTO_CBC=y
-# CONFIG_CRYPTO_PCBC is not set
-# CONFIG_CRYPTO_LRW is not set
-# CONFIG_CRYPTO_XTS is not set
-# CONFIG_CRYPTO_CRYPTD is not set
-CONFIG_CRYPTO_DES=y
-# CONFIG_CRYPTO_FCRYPT is not set
-# CONFIG_CRYPTO_BLOWFISH is not set
-# CONFIG_CRYPTO_TWOFISH is not set
-# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
# CONFIG_CRYPTO_CAST5 is not set
# CONFIG_CRYPTO_CAST6 is not set
-# CONFIG_CRYPTO_TEA is not set
-# CONFIG_CRYPTO_ARC4 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
# CONFIG_CRYPTO_KHAZAD is not set
-# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_SALSA20 is not set
# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
# CONFIG_CRYPTO_DEFLATE is not set
-# CONFIG_CRYPTO_MICHAEL_MIC is not set
-# CONFIG_CRYPTO_CRC32C is not set
-# CONFIG_CRYPTO_CAMELLIA is not set
-# CONFIG_CRYPTO_TEST is not set
-# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_HIFN_795X is not set
CONFIG_PPC_CLOCK=y
CONFIG_PPC_LIB_RHEAP=y
+# CONFIG_VIRTUALIZATION is not set
diff --git a/arch/powerpc/configs/mpc83xx_defconfig b/arch/powerpc/configs/mpc83xx_defconfig
index 15eb30c9b3f..d582014b0a3 100644
--- a/arch/powerpc/configs/mpc83xx_defconfig
+++ b/arch/powerpc/configs/mpc83xx_defconfig
@@ -682,7 +682,7 @@ CONFIG_VITESSE_PHY=y
# CONFIG_BROADCOM_PHY is not set
CONFIG_ICPLUS_PHY=y
# CONFIG_REALTEK_PHY is not set
-# CONFIG_FIXED_PHY is not set
+CONFIG_FIXED_PHY=y
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
diff --git a/arch/powerpc/configs/ppc40x_defconfig b/arch/powerpc/configs/ppc40x_defconfig
index c15c91deb2a..4256e2c4534 100644
--- a/arch/powerpc/configs/ppc40x_defconfig
+++ b/arch/powerpc/configs/ppc40x_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc2
-# Tue Oct 28 08:56:44 2008
+# Linux kernel version: 2.6.28-rc4
+# Fri Nov 14 09:54:44 2008
#
# CONFIG_PPC64 is not set
@@ -500,15 +500,17 @@ CONFIG_BLK_DEV_RAM_SIZE=35000
# CONFIG_BLK_DEV_XIP is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
-# CONFIG_XILINX_SYSACE is not set
+CONFIG_XILINX_SYSACE=m
# CONFIG_BLK_DEV_HD is not set
CONFIG_MISC_DEVICES=y
# CONFIG_PHANTOM is not set
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -632,7 +634,13 @@ CONFIG_NETDEV_10000=y
#
# Hardware I/O ports
#
-# CONFIG_SERIO is not set
+CONFIG_SERIO=m
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+CONFIG_SERIO_XILINX_XPS_PS2=m
# CONFIG_GAMEPORT is not set
#
@@ -660,7 +668,8 @@ CONFIG_SERIAL_8250_SHARE_IRQ=y
#
# Non-8250 serial port support
#
-# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_UARTLITE=y
+CONFIG_SERIAL_UARTLITE_CONSOLE=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
@@ -757,6 +766,11 @@ CONFIG_GPIOLIB=y
# CONFIG_GPIO_SYSFS is not set
#
+# Memory mapped GPIO expanders:
+#
+CONFIG_GPIO_XILINX=y
+
+#
# I2C GPIO expanders:
#
# CONFIG_GPIO_MAX732X is not set
@@ -776,11 +790,11 @@ CONFIG_GPIOLIB=y
# CONFIG_HWMON is not set
CONFIG_THERMAL=y
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -792,6 +806,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_TMIO is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -816,13 +831,65 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_DRM is not set
# CONFIG_VGASTATE is not set
CONFIG_VIDEO_OUTPUT_CONTROL=m
-# CONFIG_FB is not set
+CONFIG_FB=m
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=m
+CONFIG_FB_CFB_COPYAREA=m
+CONFIG_FB_CFB_IMAGEBLIT=m
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_VGA16 is not set
+# CONFIG_FB_UVESA is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_VIA is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
+# CONFIG_FB_CARMINE is not set
+# CONFIG_FB_IBM_GXT4500 is not set
+CONFIG_FB_XILINX=m
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Display device support
#
# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_LOGO is not set
# CONFIG_SOUND is not set
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
@@ -851,6 +918,7 @@ CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
# CONFIG_STAGING is not set
+CONFIG_STAGING_EXCLUDE_BUILD=y
#
# File systems
@@ -1077,10 +1145,12 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
-CONFIG_HAVE_DYNAMIC_FTRACE=y
-# CONFIG_FTRACE is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
diff --git a/arch/powerpc/configs/ppc44x_defconfig b/arch/powerpc/configs/ppc44x_defconfig
index 55edbd545b6..cfc94cfcf4c 100644
--- a/arch/powerpc/configs/ppc44x_defconfig
+++ b/arch/powerpc/configs/ppc44x_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc2
-# Tue Oct 28 09:28:58 2008
+# Linux kernel version: 2.6.28-rc4
+# Fri Nov 14 10:06:19 2008
#
# CONFIG_PPC64 is not set
@@ -506,15 +506,17 @@ CONFIG_BLK_DEV_RAM_SIZE=35000
# CONFIG_BLK_DEV_XIP is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
-# CONFIG_XILINX_SYSACE is not set
+CONFIG_XILINX_SYSACE=m
# CONFIG_BLK_DEV_HD is not set
CONFIG_MISC_DEVICES=y
# CONFIG_PHANTOM is not set
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -680,7 +682,13 @@ CONFIG_NETDEV_10000=y
#
# Hardware I/O ports
#
-# CONFIG_SERIO is not set
+CONFIG_SERIO=m
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+CONFIG_SERIO_XILINX_XPS_PS2=m
# CONFIG_GAMEPORT is not set
#
@@ -708,7 +716,8 @@ CONFIG_SERIAL_8250_SHARE_IRQ=y
#
# Non-8250 serial port support
#
-# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_UARTLITE=y
+CONFIG_SERIAL_UARTLITE_CONSOLE=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
@@ -806,6 +815,11 @@ CONFIG_GPIOLIB=y
# CONFIG_GPIO_SYSFS is not set
#
+# Memory mapped GPIO expanders:
+#
+CONFIG_GPIO_XILINX=y
+
+#
# I2C GPIO expanders:
#
# CONFIG_GPIO_MAX732X is not set
@@ -826,11 +840,11 @@ CONFIG_GPIOLIB=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -842,6 +856,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_TMIO is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -866,13 +881,65 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_DRM is not set
# CONFIG_VGASTATE is not set
# CONFIG_VIDEO_OUTPUT_CONTROL is not set
-# CONFIG_FB is not set
+CONFIG_FB=m
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=m
+CONFIG_FB_CFB_COPYAREA=m
+CONFIG_FB_CFB_IMAGEBLIT=m
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_VGA16 is not set
+# CONFIG_FB_UVESA is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_VIA is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
+# CONFIG_FB_CARMINE is not set
+# CONFIG_FB_IBM_GXT4500 is not set
+CONFIG_FB_XILINX=m
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Display device support
#
# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_LOGO is not set
# CONFIG_SOUND is not set
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
@@ -1002,6 +1069,7 @@ CONFIG_USB_STORAGE=m
# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
# CONFIG_STAGING is not set
+CONFIG_STAGING_EXCLUDE_BUILD=y
#
# File systems
@@ -1227,10 +1295,12 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
-CONFIG_HAVE_DYNAMIC_FTRACE=y
-# CONFIG_FTRACE is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
index 8931ba729d2..bb62ad876de 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -104,4 +104,6 @@ static inline void kvmppc_set_pid(struct kvm_vcpu *vcpu, u32 new_pid)
}
}
+extern void kvmppc_core_destroy_mmu(struct kvm_vcpu *vcpu);
+
#endif /* __POWERPC_KVM_PPC_H__ */
diff --git a/arch/powerpc/include/asm/mmu-hash64.h b/arch/powerpc/include/asm/mmu-hash64.h
index 5a441742ffb..68b75262680 100644
--- a/arch/powerpc/include/asm/mmu-hash64.h
+++ b/arch/powerpc/include/asm/mmu-hash64.h
@@ -280,7 +280,6 @@ extern int hash_huge_page(struct mm_struct *mm, unsigned long access,
extern int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
unsigned long pstart, unsigned long prot,
int psize, int ssize);
-extern void set_huge_psize(int psize);
extern void add_gpage(unsigned long addr, unsigned long page_size,
unsigned long number_of_pages);
extern void demote_segment_4k(struct mm_struct *mm, unsigned long addr);
diff --git a/arch/powerpc/include/asm/ptrace.h b/arch/powerpc/include/asm/ptrace.h
index 280a90cc989..c9c678fb253 100644
--- a/arch/powerpc/include/asm/ptrace.h
+++ b/arch/powerpc/include/asm/ptrace.h
@@ -55,8 +55,6 @@ struct pt_regs {
#ifdef __powerpc64__
-#define __ARCH_WANT_COMPAT_SYS_PTRACE
-
#define STACK_FRAME_OVERHEAD 112 /* size of minimum stack frame */
#define STACK_FRAME_LR_SAVE 2 /* Location of LR in stack frame */
#define STACK_FRAME_REGS_MARKER ASM_CONST(0x7265677368657265)
diff --git a/arch/powerpc/kernel/cpu_setup_44x.S b/arch/powerpc/kernel/cpu_setup_44x.S
index 80cac984d85..10b4ab1008a 100644
--- a/arch/powerpc/kernel/cpu_setup_44x.S
+++ b/arch/powerpc/kernel/cpu_setup_44x.S
@@ -34,7 +34,13 @@ _GLOBAL(__setup_cpu_440grx)
blr
_GLOBAL(__setup_cpu_460ex)
_GLOBAL(__setup_cpu_460gt)
- b __init_fpu_44x
+ mflr r4
+ bl __init_fpu_44x
+ bl __fixup_440A_mcheck
+ mtlr r4
+ blr
+
+_GLOBAL(__setup_cpu_440x5)
_GLOBAL(__setup_cpu_440gx)
_GLOBAL(__setup_cpu_440spe)
b __fixup_440A_mcheck
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index b1eb834bc0f..7e8719504f3 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -39,6 +39,7 @@ extern void __setup_cpu_440epx(unsigned long offset, struct cpu_spec* spec);
extern void __setup_cpu_440gx(unsigned long offset, struct cpu_spec* spec);
extern void __setup_cpu_440grx(unsigned long offset, struct cpu_spec* spec);
extern void __setup_cpu_440spe(unsigned long offset, struct cpu_spec* spec);
+extern void __setup_cpu_440x5(unsigned long offset, struct cpu_spec* spec);
extern void __setup_cpu_460ex(unsigned long offset, struct cpu_spec* spec);
extern void __setup_cpu_460gt(unsigned long offset, struct cpu_spec* spec);
extern void __setup_cpu_603(unsigned long offset, struct cpu_spec* spec);
@@ -1500,6 +1501,8 @@ static struct cpu_spec __initdata cpu_specs[] = {
.cpu_user_features = COMMON_USER_BOOKE,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .cpu_setup = __setup_cpu_440x5,
+ .machine_check = machine_check_440A,
.platform = "ppc440",
},
{ /* 460EX */
diff --git a/arch/powerpc/kernel/dma.c b/arch/powerpc/kernel/dma.c
index 1562daf8839..3a6eaa876ee 100644
--- a/arch/powerpc/kernel/dma.c
+++ b/arch/powerpc/kernel/dma.c
@@ -75,6 +75,7 @@ static int dma_direct_map_sg(struct device *dev, struct scatterlist *sgl,
for_each_sg(sgl, sg, nents, i) {
sg->dma_address = sg_phys(sg) + get_dma_direct_offset(dev);
sg->dma_length = sg->length;
+ __dma_sync_page(sg_page(sg), sg->offset, sg->length, direction);
}
return nents;
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index e6d52845854..e0bcf935428 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -57,12 +57,18 @@ system_call_common:
beq- 1f
ld r1,PACAKSAVE(r13)
1: std r10,0(r1)
- crclr so
std r11,_NIP(r1)
std r12,_MSR(r1)
std r0,GPR0(r1)
std r10,GPR1(r1)
ACCOUNT_CPU_USER_ENTRY(r10, r11)
+ /*
+ * This "crclr so" clears CR0.SO, which is the error indication on
+ * return from this system call. There must be no cmp instruction
+ * between it and the "mfcr r9" below, otherwise if XER.SO is set,
+ * CR0.SO will get set, causing all system calls to appear to fail.
+ */
+ crclr so
std r2,GPR2(r1)
std r3,GPR3(r1)
std r4,GPR4(r1)
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S
index bdc8b0e860e..5c33bc14bd9 100644
--- a/arch/powerpc/kernel/misc_32.S
+++ b/arch/powerpc/kernel/misc_32.S
@@ -479,17 +479,20 @@ _GLOBAL(_tlbil_pid)
* (no broadcast)
*/
_GLOBAL(_tlbil_va)
+ mfmsr r10
+ wrteei 0
slwi r4,r4,16
mtspr SPRN_MAS6,r4 /* assume AS=0 for now */
tlbsx 0,r3
mfspr r4,SPRN_MAS1 /* check valid */
andis. r3,r4,MAS1_VALID@h
- beqlr
+ beq 1f
rlwinm r4,r4,0,1,31
mtspr SPRN_MAS1,r4
tlbwe
msync
isync
+1: wrtee r10
blr
#endif /* CONFIG_FSL_BOOKE */
diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c
index bc1fb27368a..a11d68976dc 100644
--- a/arch/powerpc/kernel/prom_parse.c
+++ b/arch/powerpc/kernel/prom_parse.c
@@ -250,8 +250,11 @@ int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
* parsing
*/
dn = pci_device_to_OF_node(pdev);
- if (dn)
- return of_irq_map_one(dn, 0, out_irq);
+ if (dn) {
+ rc = of_irq_map_one(dn, 0, out_irq);
+ if (!rc)
+ return rc;
+ }
/* Ok, we don't, time to have fun. Let's start by building up an
* interrupt spec. we assume #interrupt-cells is 1, which is standard
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c
index 86a2ffccef2..20885a38237 100644
--- a/arch/powerpc/kernel/sysfs.c
+++ b/arch/powerpc/kernel/sysfs.c
@@ -717,9 +717,11 @@ static void unregister_cpu_online(unsigned int cpu)
BUG_ON(!c->hotpluggable);
+#ifdef CONFIG_PPC64
if (!firmware_has_feature(FW_FEATURE_ISERIES) &&
cpu_has_feature(CPU_FTR_SMT))
sysdev_remove_file(s, &attr_smt_snooze_delay);
+#endif
/* PMC stuff */
switch (cur_cpu_spec->pmc_type) {
diff --git a/arch/powerpc/kvm/44x_tlb.c b/arch/powerpc/kvm/44x_tlb.c
index 2e227a412bc..ad72c6f9811 100644
--- a/arch/powerpc/kvm/44x_tlb.c
+++ b/arch/powerpc/kvm/44x_tlb.c
@@ -124,6 +124,14 @@ static void kvmppc_44x_shadow_release(struct kvm_vcpu *vcpu,
}
}
+void kvmppc_core_destroy_mmu(struct kvm_vcpu *vcpu)
+{
+ int i;
+
+ for (i = 0; i <= tlb_44x_hwater; i++)
+ kvmppc_44x_shadow_release(vcpu, i);
+}
+
void kvmppc_tlbe_set_modified(struct kvm_vcpu *vcpu, unsigned int i)
{
vcpu->arch.shadow_tlb_mod[i] = 1;
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 90a6fc422b2..fda9baada13 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -238,6 +238,7 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu)
{
+ kvmppc_core_destroy_mmu(vcpu);
}
/* Note: clearing MSR[DE] just means that the debug interrupt will not be
diff --git a/arch/powerpc/lib/rheap.c b/arch/powerpc/lib/rheap.c
index 29b2941cada..45907c1dae6 100644
--- a/arch/powerpc/lib/rheap.c
+++ b/arch/powerpc/lib/rheap.c
@@ -556,6 +556,7 @@ unsigned long rh_alloc_fixed(rh_info_t * info, unsigned long start, int size, co
be = blk->start + blk->size;
if (s >= bs && e <= be)
break;
+ blk = NULL;
}
if (blk == NULL)
diff --git a/arch/powerpc/mm/40x_mmu.c b/arch/powerpc/mm/40x_mmu.c
index cecbbc76f62..29954dc2894 100644
--- a/arch/powerpc/mm/40x_mmu.c
+++ b/arch/powerpc/mm/40x_mmu.c
@@ -93,7 +93,7 @@ void __init MMU_init_hw(void)
unsigned long __init mmu_mapin_ram(void)
{
- unsigned long v, s;
+ unsigned long v, s, mapped;
phys_addr_t p;
v = KERNELBASE;
@@ -130,5 +130,17 @@ unsigned long __init mmu_mapin_ram(void)
s -= LARGE_PAGE_SIZE_4M;
}
- return total_lowmem - s;
+ mapped = total_lowmem - s;
+
+ /* If the size of RAM is not an exact power of two, we may not
+ * have covered RAM in its entirety with 16 and 4 MiB
+ * pages. Consequently, restrict the top end of RAM currently
+ * allocable so that calls to the LMB to allocate PTEs for "tail"
+ * coverage with normal-sized pages (or other reasons) do not
+ * attempt to allocate outside the allowed range.
+ */
+
+ __initial_memory_limit_addr = memstart_addr + mapped;
+
+ return mapped;
}
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c
index a117024ab8c..f0c3b88d50f 100644
--- a/arch/powerpc/mm/hugetlbpage.c
+++ b/arch/powerpc/mm/hugetlbpage.c
@@ -507,6 +507,9 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
{
struct hstate *hstate = hstate_file(file);
int mmu_psize = shift_to_mmu_psize(huge_page_shift(hstate));
+
+ if (!mmu_huge_psizes[mmu_psize])
+ return -EINVAL;
return slice_get_unmapped_area(addr, len, flags, mmu_psize, 1, 0);
}
@@ -677,7 +680,7 @@ repeat:
return err;
}
-void set_huge_psize(int psize)
+static void __init set_huge_psize(int psize)
{
/* Check that it is a page size supported by the hardware and
* that it fits within pagetable limits. */
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index eb505ad34a8..cf81049e1e5 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -865,10 +865,77 @@ static struct notifier_block __cpuinitdata ppc64_numa_nb = {
.priority = 1 /* Must run before sched domains notifier. */
};
+static void mark_reserved_regions_for_nid(int nid)
+{
+ struct pglist_data *node = NODE_DATA(nid);
+ int i;
+
+ for (i = 0; i < lmb.reserved.cnt; i++) {
+ unsigned long physbase = lmb.reserved.region[i].base;
+ unsigned long size = lmb.reserved.region[i].size;
+ unsigned long start_pfn = physbase >> PAGE_SHIFT;
+ unsigned long end_pfn = ((physbase + size) >> PAGE_SHIFT);
+ struct node_active_region node_ar;
+ unsigned long node_end_pfn = node->node_start_pfn +
+ node->node_spanned_pages;
+
+ /*
+ * Check to make sure that this lmb.reserved area is
+ * within the bounds of the node that we care about.
+ * Checking the nid of the start and end points is not
+ * sufficient because the reserved area could span the
+ * entire node.
+ */
+ if (end_pfn <= node->node_start_pfn ||
+ start_pfn >= node_end_pfn)
+ continue;
+
+ get_node_active_region(start_pfn, &node_ar);
+ while (start_pfn < end_pfn &&
+ node_ar.start_pfn < node_ar.end_pfn) {
+ unsigned long reserve_size = size;
+ /*
+ * if reserved region extends past active region
+ * then trim size to active region
+ */
+ if (end_pfn > node_ar.end_pfn)
+ reserve_size = (node_ar.end_pfn << PAGE_SHIFT)
+ - (start_pfn << PAGE_SHIFT);
+ /*
+ * Only worry about *this* node, others may not
+ * yet have valid NODE_DATA().
+ */
+ if (node_ar.nid == nid) {
+ dbg("reserve_bootmem %lx %lx nid=%d\n",
+ physbase, reserve_size, node_ar.nid);
+ reserve_bootmem_node(NODE_DATA(node_ar.nid),
+ physbase, reserve_size,
+ BOOTMEM_DEFAULT);
+ }
+ /*
+ * if reserved region is contained in the active region
+ * then done.
+ */
+ if (end_pfn <= node_ar.end_pfn)
+ break;
+
+ /*
+ * reserved region extends past the active region
+ * get next active region that contains this
+ * reserved region
+ */
+ start_pfn = node_ar.end_pfn;
+ physbase = start_pfn << PAGE_SHIFT;
+ size = size - reserve_size;
+ get_node_active_region(start_pfn, &node_ar);
+ }
+ }
+}
+
+
void __init do_init_bootmem(void)
{
int nid;
- unsigned int i;
min_low_pfn = 0;
max_low_pfn = lmb_end_of_DRAM() >> PAGE_SHIFT;
@@ -890,7 +957,13 @@ void __init do_init_bootmem(void)
get_pfn_range_for_nid(nid, &start_pfn, &end_pfn);
- /* Allocate the node structure node local if possible */
+ /*
+ * Allocate the node structure node local if possible
+ *
+ * Be careful moving this around, as it relies on all
+ * previous nodes' bootmem to be initialized and have
+ * all reserved areas marked.
+ */
NODE_DATA(nid) = careful_allocation(nid,
sizeof(struct pglist_data),
SMP_CACHE_BYTES, end_pfn);
@@ -922,53 +995,14 @@ void __init do_init_bootmem(void)
start_pfn, end_pfn);
free_bootmem_with_active_regions(nid, end_pfn);
- }
-
- /* Mark reserved regions */
- for (i = 0; i < lmb.reserved.cnt; i++) {
- unsigned long physbase = lmb.reserved.region[i].base;
- unsigned long size = lmb.reserved.region[i].size;
- unsigned long start_pfn = physbase >> PAGE_SHIFT;
- unsigned long end_pfn = ((physbase + size) >> PAGE_SHIFT);
- struct node_active_region node_ar;
-
- get_node_active_region(start_pfn, &node_ar);
- while (start_pfn < end_pfn &&
- node_ar.start_pfn < node_ar.end_pfn) {
- unsigned long reserve_size = size;
- /*
- * if reserved region extends past active region
- * then trim size to active region
- */
- if (end_pfn > node_ar.end_pfn)
- reserve_size = (node_ar.end_pfn << PAGE_SHIFT)
- - (start_pfn << PAGE_SHIFT);
- dbg("reserve_bootmem %lx %lx nid=%d\n", physbase,
- reserve_size, node_ar.nid);
- reserve_bootmem_node(NODE_DATA(node_ar.nid), physbase,
- reserve_size, BOOTMEM_DEFAULT);
- /*
- * if reserved region is contained in the active region
- * then done.
- */
- if (end_pfn <= node_ar.end_pfn)
- break;
-
- /*
- * reserved region extends past the active region
- * get next active region that contains this
- * reserved region
- */
- start_pfn = node_ar.end_pfn;
- physbase = start_pfn << PAGE_SHIFT;
- size = size - reserve_size;
- get_node_active_region(start_pfn, &node_ar);
- }
-
- }
-
- for_each_online_node(nid)
+ /*
+ * Be very careful about moving this around. Future
+ * calls to careful_allocation() depend on this getting
+ * done correctly.
+ */
+ mark_reserved_regions_for_nid(nid);
sparse_memory_present_with_active_regions(nid);
+ }
}
void __init paging_init(void)
diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c
index 896548ba1ca..0ce45c2b42f 100644
--- a/arch/powerpc/platforms/cell/axon_msi.c
+++ b/arch/powerpc/platforms/cell/axon_msi.c
@@ -95,6 +95,7 @@ static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc)
struct axon_msic *msic = get_irq_data(irq);
u32 write_offset, msi;
int idx;
+ int retry = 0;
write_offset = dcr_read(msic->dcr_host, MSIC_WRITE_OFFSET_REG);
pr_debug("axon_msi: original write_offset 0x%x\n", write_offset);
@@ -102,7 +103,7 @@ static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc)
/* write_offset doesn't wrap properly, so we have to mask it */
write_offset &= MSIC_FIFO_SIZE_MASK;
- while (msic->read_offset != write_offset) {
+ while (msic->read_offset != write_offset && retry < 100) {
idx = msic->read_offset / sizeof(__le32);
msi = le32_to_cpu(msic->fifo_virt[idx]);
msi &= 0xFFFF;
@@ -110,13 +111,37 @@ static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc)
pr_debug("axon_msi: woff %x roff %x msi %x\n",
write_offset, msic->read_offset, msi);
+ if (msi < NR_IRQS && irq_map[msi].host == msic->irq_host) {
+ generic_handle_irq(msi);
+ msic->fifo_virt[idx] = cpu_to_le32(0xffffffff);
+ } else {
+ /*
+ * Reading the MSIC_WRITE_OFFSET_REG does not
+ * reliably flush the outstanding DMA to the
+ * FIFO buffer. Here we were reading stale
+ * data, so we need to retry.
+ */
+ udelay(1);
+ retry++;
+ pr_debug("axon_msi: invalid irq 0x%x!\n", msi);
+ continue;
+ }
+
+ if (retry) {
+ pr_debug("axon_msi: late irq 0x%x, retry %d\n",
+ msi, retry);
+ retry = 0;
+ }
+
msic->read_offset += MSIC_FIFO_ENTRY_SIZE;
msic->read_offset &= MSIC_FIFO_SIZE_MASK;
+ }
- if (msi < NR_IRQS && irq_map[msi].host == msic->irq_host)
- generic_handle_irq(msi);
- else
- pr_debug("axon_msi: invalid irq 0x%x!\n", msi);
+ if (retry) {
+ printk(KERN_WARNING "axon_msi: irq timed out\n");
+
+ msic->read_offset += MSIC_FIFO_ENTRY_SIZE;
+ msic->read_offset &= MSIC_FIFO_SIZE_MASK;
}
desc->chip->eoi(irq);
@@ -364,6 +389,7 @@ static int axon_msi_probe(struct of_device *device,
dn->full_name);
goto out_free_fifo;
}
+ memset(msic->fifo_virt, 0xff, MSIC_FIFO_SIZE_BYTES);
msic->irq_host = irq_alloc_host(dn, IRQ_HOST_MAP_NOMAP,
NR_IRQS, &msic_host_ops, 0);
@@ -387,6 +413,9 @@ static int axon_msi_probe(struct of_device *device,
MSIC_CTRL_IRQ_ENABLE | MSIC_CTRL_ENABLE |
MSIC_CTRL_FIFO_SIZE);
+ msic->read_offset = dcr_read(msic->dcr_host, MSIC_WRITE_OFFSET_REG)
+ & MSIC_FIFO_SIZE_MASK;
+
device->dev.platform_data = msic;
ppc_md.setup_msi_irqs = axon_msi_setup_msi_irqs;
diff --git a/arch/powerpc/platforms/cell/smp.c b/arch/powerpc/platforms/cell/smp.c
index c0d86e1f56e..9046803c827 100644
--- a/arch/powerpc/platforms/cell/smp.c
+++ b/arch/powerpc/platforms/cell/smp.c
@@ -129,10 +129,15 @@ static int __init smp_iic_probe(void)
return cpus_weight(cpu_possible_map);
}
-static void __devinit smp_iic_setup_cpu(int cpu)
+static void __devinit smp_cell_setup_cpu(int cpu)
{
if (cpu != boot_cpuid)
iic_setup_cpu();
+
+ /*
+ * change default DABRX to allow user watchpoints
+ */
+ mtspr(SPRN_DABRX, DABRX_KERNEL | DABRX_USER);
}
static DEFINE_SPINLOCK(timebase_lock);
@@ -192,7 +197,7 @@ static struct smp_ops_t bpa_iic_smp_ops = {
.message_pass = smp_iic_message_pass,
.probe = smp_iic_probe,
.kick_cpu = smp_cell_kick_cpu,
- .setup_cpu = smp_iic_setup_cpu,
+ .setup_cpu = smp_cell_setup_cpu,
.cpu_bootable = smp_cell_cpu_bootable,
};
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index b73c369cc6f..1b26071a86c 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -390,6 +390,9 @@ static int spufs_ps_fault(struct vm_area_struct *vma,
if (offset >= ps_size)
return VM_FAULT_SIGBUS;
+ if (fatal_signal_pending(current))
+ return VM_FAULT_SIGBUS;
+
/*
* Because we release the mmap_sem, the context may be destroyed while
* we're in spu_wait. Grab an extra reference so it isn't destroyed
diff --git a/arch/powerpc/sysdev/bestcomm/Kconfig b/arch/powerpc/sysdev/bestcomm/Kconfig
index 57cc5656256..0b192a1c429 100644
--- a/arch/powerpc/sysdev/bestcomm/Kconfig
+++ b/arch/powerpc/sysdev/bestcomm/Kconfig
@@ -17,23 +17,20 @@ config PPC_BESTCOMM
answer Y or M. Otherwise say N.
config PPC_BESTCOMM_ATA
- tristate "Bestcomm ATA task support"
+ tristate
depends on PPC_BESTCOMM
- default n
help
This option enables the support for the ATA task.
config PPC_BESTCOMM_FEC
- tristate "Bestcomm FEC tasks support"
+ tristate
depends on PPC_BESTCOMM
- default n
help
This option enables the support for the FEC tasks.
config PPC_BESTCOMM_GEN_BD
- tristate "Bestcomm GenBD tasks support"
+ tristate
depends on PPC_BESTCOMM
- default n
help
This option enables the support for the GenBD tasks.
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index f6299cca781..1890fb085cd 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -600,7 +600,7 @@ static int irq_choose_cpu(unsigned int virt_irq)
cpuid = first_cpu(tmp);
}
- return cpuid;
+ return get_hard_smp_processor_id(cpuid);
}
#else
static int irq_choose_cpu(unsigned int virt_irq)
@@ -1271,6 +1271,7 @@ void __init mpic_set_default_senses(struct mpic *mpic, u8 *senses, int count)
void __init mpic_init(struct mpic *mpic)
{
int i;
+ int cpu;
BUG_ON(mpic->num_sources == 0);
@@ -1313,6 +1314,11 @@ void __init mpic_init(struct mpic *mpic)
mpic_pasemi_msi_init(mpic);
+ if (mpic->flags & MPIC_PRIMARY)
+ cpu = hard_smp_processor_id();
+ else
+ cpu = 0;
+
for (i = 0; i < mpic->num_sources; i++) {
/* start with vector = source number, and masked */
u32 vecpri = MPIC_VECPRI_MASK | i |
@@ -1323,8 +1329,7 @@ void __init mpic_init(struct mpic *mpic)
continue;
/* init hw */
mpic_irq_write(i, MPIC_INFO(IRQ_VECTOR_PRI), vecpri);
- mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION),
- 1 << hard_smp_processor_id());
+ mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION), 1 << cpu);
}
/* Init spurious vector */
diff --git a/arch/powerpc/sysdev/xilinx_intc.c b/arch/powerpc/sysdev/xilinx_intc.c
index b7aefd0d45c..a22e1a2df1a 100644
--- a/arch/powerpc/sysdev/xilinx_intc.c
+++ b/arch/powerpc/sysdev/xilinx_intc.c
@@ -107,8 +107,8 @@ xilinx_intc_init(struct device_node *np)
}
regs = ioremap(res.start, 32);
- printk(KERN_INFO "Xilinx intc at 0x%08LX mapped to 0x%p\n",
- res.start, regs);
+ printk(KERN_INFO "Xilinx intc at 0x%08llx mapped to 0x%p\n",
+ (unsigned long long) res.start, regs);
/* Setup interrupt controller */
out_be32(regs + XINTC_IER, 0); /* disable all irqs */
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index 9b0bc2c9fba..a0e748da990 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27-rc4
-# Thu Aug 21 19:43:29 2008
+# Linux kernel version: 2.6.28-rc6
+# Thu Nov 27 11:00:49 2008
#
CONFIG_SCHED_MC=y
CONFIG_MMU=y
@@ -45,6 +45,7 @@ CONFIG_LOG_BUF_SHIFT=17
CONFIG_CGROUPS=y
# CONFIG_CGROUP_DEBUG is not set
CONFIG_CGROUP_NS=y
+# CONFIG_CGROUP_FREEZER is not set
# CONFIG_CGROUP_DEVICE is not set
# CONFIG_CPUSETS is not set
CONFIG_GROUP_SCHED=y
@@ -84,6 +85,7 @@ CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
@@ -92,16 +94,10 @@ CONFIG_SLAB=y
# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_KPROBES=y
-# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set
CONFIG_KRETPROBES=y
-# CONFIG_HAVE_IOREMAP_PROT is not set
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
-# CONFIG_HAVE_ARCH_TRACEHOOK is not set
-# CONFIG_HAVE_DMA_ATTRS is not set
-# CONFIG_USE_GENERIC_SMP_HELPERS is not set
-# CONFIG_HAVE_CLK is not set
-CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -135,6 +131,7 @@ CONFIG_DEFAULT_DEADLINE=y
CONFIG_DEFAULT_IOSCHED="deadline"
CONFIG_PREEMPT_NOTIFIERS=y
CONFIG_CLASSIC_RCU=y
+# CONFIG_FREEZER is not set
#
# Base setup
@@ -189,7 +186,6 @@ CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_SPARSEMEM_MANUAL=y
CONFIG_SPARSEMEM=y
CONFIG_HAVE_MEMORY_PRESENT=y
-# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPARSEMEM_EXTREME=y
CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
CONFIG_SPARSEMEM_VMEMMAP=y
@@ -200,9 +196,11 @@ CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
CONFIG_RESOURCES_64BIT=y
+CONFIG_PHYS_ADDR_T_64BIT=y
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
#
# I/O subsystem configuration
@@ -220,6 +218,8 @@ CONFIG_IPL=y
CONFIG_IPL_VM=y
CONFIG_BINFMT_ELF=y
CONFIG_COMPAT_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
CONFIG_BINFMT_MISC=m
CONFIG_FORCE_MAX_ZONEORDER=9
# CONFIG_PROCESS_DEBUG is not set
@@ -255,7 +255,7 @@ CONFIG_XFRM=y
# CONFIG_XFRM_STATISTICS is not set
CONFIG_NET_KEY=y
# CONFIG_NET_KEY_MIGRATE is not set
-CONFIG_IUCV=m
+CONFIG_IUCV=y
CONFIG_AFIUCV=m
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
@@ -282,7 +282,6 @@ CONFIG_INET_TCP_DIAG=y
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
-# CONFIG_IP_VS is not set
CONFIG_IPV6=y
# CONFIG_IPV6_PRIVACY is not set
# CONFIG_IPV6_ROUTER_PREF is not set
@@ -331,10 +330,12 @@ CONFIG_NF_CONNTRACK=m
# CONFIG_NF_CONNTRACK_TFTP is not set
# CONFIG_NF_CT_NETLINK is not set
# CONFIG_NETFILTER_XTABLES is not set
+# CONFIG_IP_VS is not set
#
# IP: Netfilter Configuration
#
+# CONFIG_NF_DEFRAG_IPV4 is not set
# CONFIG_NF_CONNTRACK_IPV4 is not set
# CONFIG_IP_NF_QUEUE is not set
# CONFIG_IP_NF_IPTABLES is not set
@@ -374,6 +375,7 @@ CONFIG_NET_SCH_CBQ=m
# CONFIG_NET_SCH_HTB is not set
# CONFIG_NET_SCH_HFSC is not set
CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_MULTIQ=y
CONFIG_NET_SCH_RED=m
CONFIG_NET_SCH_SFQ=m
CONFIG_NET_SCH_TEQL=m
@@ -406,6 +408,7 @@ CONFIG_NET_ACT_POLICE=y
CONFIG_NET_ACT_NAT=m
# CONFIG_NET_ACT_PEDIT is not set
# CONFIG_NET_ACT_SIMP is not set
+# CONFIG_NET_ACT_SKBEDIT is not set
# CONFIG_NET_CLS_IND is not set
CONFIG_NET_SCH_FIFO=y
@@ -424,6 +427,7 @@ CONFIG_CAN_BCM=m
CONFIG_CAN_VCAN=m
# CONFIG_CAN_DEBUG_DEVICES is not set
# CONFIG_AF_RXRPC is not set
+# CONFIG_PHONET is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
# CONFIG_PCMCIA is not set
@@ -473,7 +477,7 @@ CONFIG_VIRTIO_BLK=m
CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
-# CONFIG_HAVE_IDE is not set
+# CONFIG_C2PORT is not set
#
# SCSI device support
@@ -525,6 +529,7 @@ CONFIG_SCSI_DH_EMC=m
CONFIG_SCSI_DH_ALUA=m
CONFIG_MD=y
CONFIG_BLK_DEV_MD=y
+CONFIG_MD_AUTODETECT=y
CONFIG_MD_LINEAR=m
CONFIG_MD_RAID0=m
CONFIG_MD_RAID1=m
@@ -555,6 +560,9 @@ CONFIG_NET_ETHERNET=y
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
CONFIG_NETDEV_1000=y
CONFIG_NETDEV_10000=y
# CONFIG_TR is not set
@@ -632,13 +640,12 @@ CONFIG_S390_VMUR=m
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
-
-#
-# Sonics Silicon Backplane
-#
+# CONFIG_REGULATOR is not set
# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
CONFIG_ACCESSIBILITY=y
+# CONFIG_STAGING is not set
+CONFIG_STAGING_EXCLUDE_BUILD=y
#
# File systems
@@ -650,13 +657,14 @@ CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=y
# CONFIG_XFS_FS is not set
# CONFIG_GFS2_FS is not set
# CONFIG_OCFS2_FS is not set
@@ -688,6 +696,7 @@ CONFIG_GENERIC_ACL=y
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
CONFIG_TMPFS_POSIX_ACL=y
@@ -728,6 +737,7 @@ CONFIG_LOCKD_V4=y
CONFIG_EXPORTFS=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_REGISTER_V4 is not set
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -800,12 +810,24 @@ CONFIG_DEBUG_MEMORY_INIT=y
# CONFIG_DEBUG_SG is not set
# CONFIG_FRAME_POINTER is not set
# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_KPROBES_SANITY_TEST is not set
# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
# CONFIG_LKDTM is not set
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
+
+#
+# Tracers
+#
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
CONFIG_SAMPLES=y
# CONFIG_SAMPLE_KOBJECT is not set
# CONFIG_SAMPLE_KPROBES is not set
@@ -816,16 +838,19 @@ CONFIG_SAMPLES=y
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_CRYPTO=y
#
# Crypto core or helper
#
+CONFIG_CRYPTO_FIPS=y
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD=y
CONFIG_CRYPTO_BLKCIPHER=y
-CONFIG_CRYPTO_HASH=m
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_RNG=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_GF128MUL=m
# CONFIG_CRYPTO_NULL is not set
@@ -877,7 +902,7 @@ CONFIG_CRYPTO_SHA1=m
#
# Ciphers
#
-# CONFIG_CRYPTO_AES is not set
+CONFIG_CRYPTO_AES=m
# CONFIG_CRYPTO_ANUBIS is not set
# CONFIG_CRYPTO_ARC4 is not set
# CONFIG_CRYPTO_BLOWFISH is not set
@@ -898,6 +923,11 @@ CONFIG_CRYPTO_SEED=m
#
# CONFIG_CRYPTO_DEFLATE is not set
CONFIG_CRYPTO_LZO=m
+
+#
+# Random Number Generation
+#
+CONFIG_CRYPTO_ANSI_CPRNG=m
CONFIG_CRYPTO_HW=y
CONFIG_ZCRYPT=m
# CONFIG_ZCRYPT_MONOLITHIC is not set
@@ -912,8 +942,6 @@ CONFIG_S390_PRNG=m
# Library routines
#
CONFIG_BITREVERSE=m
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
-# CONFIG_GENERIC_FIND_NEXT_BIT is not set
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC_T10DIF=y
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h
index 7fc76133b3e..5caddd4f7be 100644
--- a/arch/s390/include/asm/pgtable.h
+++ b/arch/s390/include/asm/pgtable.h
@@ -679,8 +679,6 @@ static inline void pmd_clear(pmd_t *pmd)
static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
{
- if (mm->context.has_pgste)
- ptep_rcp_copy(ptep);
pte_val(*ptep) = _PAGE_TYPE_EMPTY;
if (mm->context.noexec)
pte_val(ptep[PTRS_PER_PTE]) = _PAGE_TYPE_EMPTY;
diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h
index a7226f8143f..5396f9f1226 100644
--- a/arch/s390/include/asm/ptrace.h
+++ b/arch/s390/include/asm/ptrace.h
@@ -321,8 +321,8 @@ struct pt_regs
psw_t psw;
unsigned long gprs[NUM_GPRS];
unsigned long orig_gpr2;
+ unsigned short svcnr;
unsigned short ilc;
- unsigned short trap;
};
#endif
@@ -486,8 +486,6 @@ struct task_struct;
extern void user_enable_single_step(struct task_struct *);
extern void user_disable_single_step(struct task_struct *);
-#define __ARCH_WANT_COMPAT_SYS_PTRACE
-
#define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0)
#define instruction_pointer(regs) ((regs)->psw.addr & PSW_ADDR_INSN)
#define user_stack_pointer(regs)((regs)->gprs[15])
diff --git a/arch/s390/include/asm/syscall.h b/arch/s390/include/asm/syscall.h
index 6e623971fbb..2429b87eb28 100644
--- a/arch/s390/include/asm/syscall.h
+++ b/arch/s390/include/asm/syscall.h
@@ -17,9 +17,7 @@
static inline long syscall_get_nr(struct task_struct *task,
struct pt_regs *regs)
{
- if (regs->trap != __LC_SVC_OLD_PSW)
- return -1;
- return regs->gprs[2];
+ return regs->svcnr ? regs->svcnr : -1;
}
static inline void syscall_rollback(struct task_struct *task,
@@ -52,18 +50,20 @@ static inline void syscall_get_arguments(struct task_struct *task,
unsigned int i, unsigned int n,
unsigned long *args)
{
+ unsigned long mask = -1UL;
+
BUG_ON(i + n > 6);
#ifdef CONFIG_COMPAT
- if (test_tsk_thread_flag(task, TIF_31BIT)) {
- if (i + n == 6)
- args[--n] = (u32) regs->args[0];
- while (n-- > 0)
- args[n] = (u32) regs->gprs[2 + i + n];
- }
+ if (test_tsk_thread_flag(task, TIF_31BIT))
+ mask = 0xffffffff;
#endif
if (i + n == 6)
- args[--n] = regs->args[0];
- memcpy(args, &regs->gprs[2 + i], n * sizeof(args[0]));
+ args[--n] = regs->args[0] & mask;
+ while (n-- > 0)
+ if (i + n > 0)
+ args[n] = regs->gprs[2 + i + n] & mask;
+ if (i == 0)
+ args[0] = regs->orig_gpr2 & mask;
}
static inline void syscall_set_arguments(struct task_struct *task,
@@ -74,7 +74,11 @@ static inline void syscall_set_arguments(struct task_struct *task,
BUG_ON(i + n > 6);
if (i + n == 6)
regs->args[0] = args[--n];
- memcpy(&regs->gprs[2 + i], args, n * sizeof(args[0]));
+ while (n-- > 0)
+ if (i + n > 0)
+ regs->gprs[2 + i + n] = args[n];
+ if (i == 0)
+ regs->orig_gpr2 = args[0];
}
#endif /* _ASM_SYSCALL_H */
diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c
index fa28ecae636..3d144e6020c 100644
--- a/arch/s390/kernel/asm-offsets.c
+++ b/arch/s390/kernel/asm-offsets.c
@@ -32,7 +32,7 @@ int main(void)
DEFINE(__PT_GPRS, offsetof(struct pt_regs, gprs));
DEFINE(__PT_ORIG_GPR2, offsetof(struct pt_regs, orig_gpr2));
DEFINE(__PT_ILC, offsetof(struct pt_regs, ilc));
- DEFINE(__PT_TRAP, offsetof(struct pt_regs, trap));
+ DEFINE(__PT_SVCNR, offsetof(struct pt_regs, svcnr));
DEFINE(__PT_SIZE, sizeof(struct pt_regs));
BLANK();
DEFINE(__SF_BACKCHAIN, offsetof(struct stack_frame, back_chain));
diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c
index c7f02e777af..b537cb0e9b5 100644
--- a/arch/s390/kernel/compat_signal.c
+++ b/arch/s390/kernel/compat_signal.c
@@ -340,7 +340,7 @@ static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs)
return err;
restore_fp_regs(&current->thread.fp_regs);
- regs->trap = -1; /* disable syscall checks */
+ regs->svcnr = 0; /* disable syscall checks */
return 0;
}
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index ed500ef799b..198ea18a534 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -46,7 +46,7 @@ SP_R14 = STACK_FRAME_OVERHEAD + __PT_GPRS + 56
SP_R15 = STACK_FRAME_OVERHEAD + __PT_GPRS + 60
SP_ORIG_R2 = STACK_FRAME_OVERHEAD + __PT_ORIG_GPR2
SP_ILC = STACK_FRAME_OVERHEAD + __PT_ILC
-SP_TRAP = STACK_FRAME_OVERHEAD + __PT_TRAP
+SP_SVCNR = STACK_FRAME_OVERHEAD + __PT_SVCNR
SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE
_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
@@ -61,22 +61,25 @@ STACK_SIZE = 1 << STACK_SHIFT
#ifdef CONFIG_TRACE_IRQFLAGS
.macro TRACE_IRQS_ON
- l %r1,BASED(.Ltrace_irq_on)
+ basr %r2,%r0
+ l %r1,BASED(.Ltrace_irq_on_caller)
basr %r14,%r1
.endm
.macro TRACE_IRQS_OFF
- l %r1,BASED(.Ltrace_irq_off)
+ basr %r2,%r0
+ l %r1,BASED(.Ltrace_irq_off_caller)
basr %r14,%r1
.endm
.macro TRACE_IRQS_CHECK
+ basr %r2,%r0
tm SP_PSW(%r15),0x03 # irqs enabled?
jz 0f
- l %r1,BASED(.Ltrace_irq_on)
+ l %r1,BASED(.Ltrace_irq_on_caller)
basr %r14,%r1
j 1f
-0: l %r1,BASED(.Ltrace_irq_off)
+0: l %r1,BASED(.Ltrace_irq_off_caller)
basr %r14,%r1
1:
.endm
@@ -180,11 +183,10 @@ STACK_SIZE = 1 << STACK_SHIFT
.macro CREATE_STACK_FRAME psworg,savearea
s %r15,BASED(.Lc_spsize) # make room for registers & psw
mvc SP_PSW(8,%r15),0(%r12) # move user PSW to stack
- la %r12,\psworg
st %r2,SP_ORIG_R2(%r15) # store original content of gpr 2
- icm %r12,12,__LC_SVC_ILC
+ icm %r12,3,__LC_SVC_ILC
stm %r0,%r11,SP_R0(%r15) # store gprs %r0-%r11 to kernel stack
- st %r12,SP_ILC(%r15)
+ st %r12,SP_SVCNR(%r15)
mvc SP_R12(16,%r15),\savearea # move %r12-%r15 to stack
la %r12,0
st %r12,__SF_BACKCHAIN(%r15) # clear back chain
@@ -261,16 +263,17 @@ sysc_update:
#endif
sysc_do_svc:
l %r9,__LC_THREAD_INFO # load pointer to thread_info struct
- sla %r7,2 # *4 and test for svc 0
+ ltr %r7,%r7 # test for svc 0
bnz BASED(sysc_nr_ok) # svc number > 0
# svc 0: system call number in %r1
cl %r1,BASED(.Lnr_syscalls)
bnl BASED(sysc_nr_ok)
lr %r7,%r1 # copy svc number to %r7
- sla %r7,2 # *4
sysc_nr_ok:
mvc SP_ARGS(4,%r15),SP_R7(%r15)
sysc_do_restart:
+ sth %r7,SP_SVCNR(%r15)
+ sll %r7,2 # svc number *4
l %r8,BASED(.Lsysc_table)
tm __TI_flags+3(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
l %r8,0(%r7,%r8) # get system call addr.
@@ -373,7 +376,6 @@ sysc_notify_resume:
sysc_restart:
ni __TI_flags+3(%r9),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC
l %r7,SP_R2(%r15) # load new svc number
- sla %r7,2
mvc SP_R2(4,%r15),SP_ORIG_R2(%r15) # restore first argument
lm %r2,%r6,SP_R2(%r15) # load svc arguments
b BASED(sysc_do_restart) # restart svc
@@ -383,7 +385,8 @@ sysc_restart:
#
sysc_singlestep:
ni __TI_flags+3(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP
- mvi SP_TRAP+1(%r15),0x28 # set trap indication to pgm check
+ mvi SP_SVCNR(%r15),0xff # set trap indication to pgm check
+ mvi SP_SVCNR+1(%r15),0xff
la %r2,SP_PTREGS(%r15) # address of register-save area
l %r1,BASED(.Lhandle_per) # load adr. of per handler
la %r14,BASED(sysc_return) # load adr. of system return
@@ -404,7 +407,7 @@ sysc_tracesys:
bnl BASED(sysc_tracenogo)
l %r8,BASED(.Lsysc_table)
lr %r7,%r2
- sll %r7,2 # *4
+ sll %r7,2 # svc number *4
l %r8,0(%r7,%r8)
sysc_tracego:
lm %r3,%r6,SP_R3(%r15)
@@ -583,7 +586,8 @@ pgm_svcper:
# per was called from kernel, must be kprobes
#
kernel_per:
- mvi SP_TRAP+1(%r15),0x28 # set trap indication to pgm check
+ mvi SP_SVCNR(%r15),0xff # set trap indication to pgm check
+ mvi SP_SVCNR+1(%r15),0xff
la %r2,SP_PTREGS(%r15) # address of register-save area
l %r1,BASED(.Lhandle_per) # load adr. of per handler
la %r14,BASED(sysc_restore)# load adr. of system return
@@ -1113,9 +1117,12 @@ cleanup_io_leave_insn:
.Lschedtail: .long schedule_tail
.Lsysc_table: .long sys_call_table
#ifdef CONFIG_TRACE_IRQFLAGS
-.Ltrace_irq_on: .long trace_hardirqs_on
-.Ltrace_irq_off:
- .long trace_hardirqs_off
+.Ltrace_irq_on_caller:
+ .long trace_hardirqs_on_caller
+.Ltrace_irq_off_caller:
+ .long trace_hardirqs_off_caller
+#endif
+#ifdef CONFIG_LOCKDEP
.Llockdep_sys_exit:
.long lockdep_sys_exit
#endif
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index d7ce150453f..89c121ae633 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -46,7 +46,7 @@ SP_R14 = STACK_FRAME_OVERHEAD + __PT_GPRS + 112
SP_R15 = STACK_FRAME_OVERHEAD + __PT_GPRS + 120
SP_ORIG_R2 = STACK_FRAME_OVERHEAD + __PT_ORIG_GPR2
SP_ILC = STACK_FRAME_OVERHEAD + __PT_ILC
-SP_TRAP = STACK_FRAME_OVERHEAD + __PT_TRAP
+SP_SVCNR = STACK_FRAME_OVERHEAD + __PT_SVCNR
SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE
STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
@@ -61,19 +61,22 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
#ifdef CONFIG_TRACE_IRQFLAGS
.macro TRACE_IRQS_ON
- brasl %r14,trace_hardirqs_on
+ basr %r2,%r0
+ brasl %r14,trace_hardirqs_on_caller
.endm
.macro TRACE_IRQS_OFF
- brasl %r14,trace_hardirqs_off
+ basr %r2,%r0
+ brasl %r14,trace_hardirqs_off_caller
.endm
.macro TRACE_IRQS_CHECK
+ basr %r2,%r0
tm SP_PSW(%r15),0x03 # irqs enabled?
jz 0f
- brasl %r14,trace_hardirqs_on
+ brasl %r14,trace_hardirqs_on_caller
j 1f
-0: brasl %r14,trace_hardirqs_off
+0: brasl %r14,trace_hardirqs_off_caller
1:
.endm
#else
@@ -168,11 +171,10 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
.macro CREATE_STACK_FRAME psworg,savearea
aghi %r15,-SP_SIZE # make room for registers & psw
mvc SP_PSW(16,%r15),0(%r12) # move user PSW to stack
- la %r12,\psworg
stg %r2,SP_ORIG_R2(%r15) # store original content of gpr 2
- icm %r12,12,__LC_SVC_ILC
+ icm %r12,3,__LC_SVC_ILC
stmg %r0,%r11,SP_R0(%r15) # store gprs %r0-%r11 to kernel stack
- st %r12,SP_ILC(%r15)
+ st %r12,SP_SVCNR(%r15)
mvc SP_R12(32,%r15),\savearea # move %r12-%r15 to stack
la %r12,0
stg %r12,__SF_BACKCHAIN(%r15)
@@ -247,16 +249,17 @@ sysc_update:
#endif
sysc_do_svc:
lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct
- slag %r7,%r7,2 # *4 and test for svc 0
+ ltgr %r7,%r7 # test for svc 0
jnz sysc_nr_ok
# svc 0: system call number in %r1
cl %r1,BASED(.Lnr_syscalls)
jnl sysc_nr_ok
lgfr %r7,%r1 # clear high word in r1
- slag %r7,%r7,2 # svc 0: system call number in %r1
sysc_nr_ok:
mvc SP_ARGS(8,%r15),SP_R7(%r15)
sysc_do_restart:
+ sth %r7,SP_SVCNR(%r15)
+ sllg %r7,%r7,2 # svc number * 4
larl %r10,sys_call_table
#ifdef CONFIG_COMPAT
tm __TI_flags+5(%r9),(_TIF_31BIT>>16) # running in 31 bit mode ?
@@ -360,7 +363,6 @@ sysc_notify_resume:
sysc_restart:
ni __TI_flags+7(%r9),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC
lg %r7,SP_R2(%r15) # load new svc number
- slag %r7,%r7,2 # *4
mvc SP_R2(8,%r15),SP_ORIG_R2(%r15) # restore first argument
lmg %r2,%r6,SP_R2(%r15) # load svc arguments
j sysc_do_restart # restart svc
@@ -369,9 +371,8 @@ sysc_restart:
# _TIF_SINGLE_STEP is set, call do_single_step
#
sysc_singlestep:
- ni __TI_flags+7(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP
- lhi %r0,__LC_PGM_OLD_PSW
- sth %r0,SP_TRAP(%r15) # set trap indication to pgm check
+ ni __TI_flags+7(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP
+ xc SP_SVCNR(2,%r15),SP_SVCNR(%r15) # clear svc number
la %r2,SP_PTREGS(%r15) # address of register-save area
larl %r14,sysc_return # load adr. of system return
jg do_single_step # branch to do_sigtrap
@@ -389,7 +390,7 @@ sysc_tracesys:
lghi %r0,NR_syscalls
clgr %r0,%r2
jnh sysc_tracenogo
- slag %r7,%r2,2 # *4
+ sllg %r7,%r2,2 # svc number *4
lgf %r8,0(%r7,%r10)
sysc_tracego:
lmg %r3,%r6,SP_R3(%r15)
@@ -564,8 +565,7 @@ pgm_svcper:
# per was called from kernel, must be kprobes
#
kernel_per:
- lhi %r0,__LC_PGM_OLD_PSW
- sth %r0,SP_TRAP(%r15) # set trap indication to pgm check
+ xc SP_SVCNR(2,%r15),SP_SVCNR(%r15) # clear svc number
la %r2,SP_PTREGS(%r15) # address of register-save area
larl %r14,sysc_restore # load adr. of system ret, no work
jg do_single_step # branch to do_single_step
diff --git a/arch/s390/kernel/init_task.c b/arch/s390/kernel/init_task.c
index 7ad00396925..e8071684361 100644
--- a/arch/s390/kernel/init_task.c
+++ b/arch/s390/kernel/init_task.c
@@ -26,7 +26,7 @@ EXPORT_SYMBOL(init_mm);
/*
* Initial thread structure.
*
- * We need to make sure that this is 8192-byte aligned due to the
+ * We need to make sure that this is THREAD_SIZE aligned due to the
* way process stacks are handled. This is done by having a special
* "init_task" linker map entry..
*/
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index 3e2c05cb6a8..04f8c67a610 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -136,9 +136,12 @@ static void default_idle(void)
return;
}
trace_hardirqs_on();
+ /* Don't trace preempt off for idle. */
+ stop_critical_timings();
/* Wait for external, I/O or machine check interrupt. */
__load_psw_mask(psw_kernel_bits | PSW_MASK_WAIT |
PSW_MASK_IO | PSW_MASK_EXT);
+ start_critical_timings();
}
void cpu_idle(void)
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
index 1f31be1ecc4..38ff2bce120 100644
--- a/arch/s390/kernel/ptrace.c
+++ b/arch/s390/kernel/ptrace.c
@@ -657,7 +657,7 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
* debugger stored an invalid system call number. Skip
* the system call and the system call restart handling.
*/
- regs->trap = -1;
+ regs->svcnr = 0;
ret = -1;
}
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 62122bad1e3..400b040df7f 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -604,13 +604,13 @@ setup_memory(void)
if (memory_chunk[i].type != CHUNK_READ_WRITE)
continue;
start_chunk = PFN_DOWN(memory_chunk[i].addr);
- end_chunk = start_chunk + PFN_DOWN(memory_chunk[i].size) - 1;
+ end_chunk = start_chunk + PFN_DOWN(memory_chunk[i].size);
end_chunk = min(end_chunk, end_pfn);
if (start_chunk >= end_chunk)
continue;
add_active_range(0, start_chunk, end_chunk);
pfn = max(start_chunk, start_pfn);
- for (; pfn <= end_chunk; pfn++)
+ for (; pfn < end_chunk; pfn++)
page_set_storage_key(PFN_PHYS(pfn), PAGE_DEFAULT_KEY);
}
diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c
index 4f7fc3059a8..8e6812a2267 100644
--- a/arch/s390/kernel/signal.c
+++ b/arch/s390/kernel/signal.c
@@ -160,7 +160,7 @@ static int restore_sigregs(struct pt_regs *regs, _sigregs __user *sregs)
current->thread.fp_regs.fpc &= FPC_VALID_MASK;
restore_fp_regs(&current->thread.fp_regs);
- regs->trap = -1; /* disable syscall checks */
+ regs->svcnr = 0; /* disable syscall checks */
return 0;
}
@@ -445,7 +445,7 @@ void do_signal(struct pt_regs *regs)
oldset = &current->blocked;
/* Are we from a system call? */
- if (regs->trap == __LC_SVC_OLD_PSW) {
+ if (regs->svcnr) {
continue_addr = regs->psw.addr;
restart_addr = continue_addr - regs->ilc;
retval = regs->gprs[2];
@@ -462,7 +462,7 @@ void do_signal(struct pt_regs *regs)
case -ERESTART_RESTARTBLOCK:
regs->gprs[2] = -EINTR;
}
- regs->trap = -1; /* Don't deal with this again. */
+ regs->svcnr = 0; /* Don't deal with this again. */
}
/* Get signal to deliver. When running under ptrace, at this point
diff --git a/arch/s390/kernel/sys_s390.c b/arch/s390/kernel/sys_s390.c
index 5fdb799062b..4fe952e557a 100644
--- a/arch/s390/kernel/sys_s390.c
+++ b/arch/s390/kernel/sys_s390.c
@@ -198,7 +198,7 @@ asmlinkage long s390x_newuname(struct new_utsname __user *name)
{
int ret = sys_newuname(name);
- if (current->personality == PER_LINUX32 && !ret) {
+ if (personality(current->personality) == PER_LINUX32 && !ret) {
ret = copy_to_user(name->machine, "s390\0\0\0\0", 8);
if (ret) ret = -EFAULT;
}
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index b94e9e3b694..eccefbbff88 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -59,7 +59,7 @@
static ext_int_info_t ext_int_info_cc;
static ext_int_info_t ext_int_etr_cc;
-static u64 jiffies_timer_cc;
+static u64 sched_clock_base_cc;
static DEFINE_PER_CPU(struct clock_event_device, comparators);
@@ -68,7 +68,7 @@ static DEFINE_PER_CPU(struct clock_event_device, comparators);
*/
unsigned long long sched_clock(void)
{
- return ((get_clock_xt() - jiffies_timer_cc) * 125) >> 9;
+ return ((get_clock_xt() - sched_clock_base_cc) * 125) >> 9;
}
/*
@@ -229,13 +229,10 @@ static struct clocksource clocksource_tod = {
*/
void __init time_init(void)
{
- u64 init_timer_cc;
-
- init_timer_cc = reset_tod_clock();
- jiffies_timer_cc = init_timer_cc - jiffies_64 * CLK_TICKS_PER_JIFFY;
+ sched_clock_base_cc = reset_tod_clock();
/* set xtime */
- tod_to_timeval(init_timer_cc - TOD_UNIX_EPOCH, &xtime);
+ tod_to_timeval(sched_clock_base_cc - TOD_UNIX_EPOCH, &xtime);
set_normalized_timespec(&wall_to_monotonic,
-xtime.tv_sec, -xtime.tv_nsec);
@@ -289,7 +286,7 @@ static unsigned long long adjust_time(unsigned long long old,
delta = -delta;
adjust.offset = -ticks * (1000000 / HZ);
}
- jiffies_timer_cc += delta;
+ sched_clock_base_cc += delta;
if (adjust.offset != 0) {
printk(KERN_NOTICE "etr: time adjusted by %li micro-seconds\n",
adjust.offset);
diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c
index 632b13e1005..a947899dcba 100644
--- a/arch/s390/kernel/topology.c
+++ b/arch/s390/kernel/topology.c
@@ -65,18 +65,21 @@ static int machine_has_topology_irq;
static struct timer_list topology_timer;
static void set_topology_timer(void);
static DECLARE_WORK(topology_work, topology_work_fn);
+/* topology_lock protects the core linked list */
+static DEFINE_SPINLOCK(topology_lock);
cpumask_t cpu_core_map[NR_CPUS];
cpumask_t cpu_coregroup_map(unsigned int cpu)
{
struct core_info *core = &core_info;
+ unsigned long flags;
cpumask_t mask;
cpus_clear(mask);
if (!machine_has_topology)
return cpu_present_map;
- mutex_lock(&smp_cpu_state_mutex);
+ spin_lock_irqsave(&topology_lock, flags);
while (core) {
if (cpu_isset(cpu, core->mask)) {
mask = core->mask;
@@ -84,7 +87,7 @@ cpumask_t cpu_coregroup_map(unsigned int cpu)
}
core = core->next;
}
- mutex_unlock(&smp_cpu_state_mutex);
+ spin_unlock_irqrestore(&topology_lock, flags);
if (cpus_empty(mask))
mask = cpumask_of_cpu(cpu);
return mask;
@@ -133,7 +136,7 @@ static void tl_to_cores(struct tl_info *info)
union tl_entry *tle, *end;
struct core_info *core = &core_info;
- mutex_lock(&smp_cpu_state_mutex);
+ spin_lock_irq(&topology_lock);
clear_cores();
tle = info->tle;
end = (union tl_entry *)((unsigned long)info + info->length);
@@ -157,7 +160,7 @@ static void tl_to_cores(struct tl_info *info)
}
tle = next_tle(tle);
}
- mutex_unlock(&smp_cpu_state_mutex);
+ spin_unlock_irq(&topology_lock);
}
static void topology_update_polarization_simple(void)
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
index 607bd67a18c..d796d05c9c0 100644
--- a/arch/s390/kernel/vmlinux.lds.S
+++ b/arch/s390/kernel/vmlinux.lds.S
@@ -2,6 +2,7 @@
* Written by Martin Schwidefsky (schwidefsky@de.ibm.com)
*/
+#include <asm/thread_info.h>
#include <asm/page.h>
#include <asm-generic/vmlinux.lds.h>
@@ -86,7 +87,7 @@ SECTIONS
}
_edata = .; /* End of data section */
- . = ALIGN(2 * PAGE_SIZE); /* init_task */
+ . = ALIGN(THREAD_SIZE); /* init_task */
.data.init_task : {
*(.data.init_task)
}
diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c
index 170392687ce..2a01b9e0280 100644
--- a/arch/s390/kvm/sigp.c
+++ b/arch/s390/kvm/sigp.c
@@ -237,6 +237,11 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
u8 order_code;
int rc;
+ /* sigp in userspace can exit */
+ if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
+ return kvm_s390_inject_program_int(vcpu,
+ PGM_PRIVILEGED_OPERATION);
+
order_code = disp2;
if (base2)
order_code += vcpu->arch.guest_gprs[base2];
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 80119b3398e..5c9cbfc14c4 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -55,6 +55,8 @@ config GENERIC_HARDIRQS
config GENERIC_HARDIRQS_NO__DO_IRQ
def_bool y
+ depends on SUPERH32 && (!SH_DREAMCAST && !SH_SH4202_MICRODEV && \
+ !SH_7751_SYSTEMH && !HD64461)
config GENERIC_IRQ_PROBE
def_bool y
diff --git a/arch/sh/include/asm/io.h b/arch/sh/include/asm/io.h
index 436c2853957..65eaae34e75 100644
--- a/arch/sh/include/asm/io.h
+++ b/arch/sh/include/asm/io.h
@@ -293,6 +293,10 @@ __ioremap_mode(unsigned long offset, unsigned long size, unsigned long flags)
*/
#define xlate_dev_kmem_ptr(p) p
+#define ARCH_HAS_VALID_PHYS_ADDR_RANGE
+int valid_phys_addr_range(unsigned long addr, size_t size);
+int valid_mmap_phys_addr_range(unsigned long pfn, size_t size);
+
#endif /* __KERNEL__ */
#endif /* __ASM_SH_IO_H */
diff --git a/arch/sh/include/asm/pgtable.h b/arch/sh/include/asm/pgtable.h
index 52220d70a09..b517ae08b9c 100644
--- a/arch/sh/include/asm/pgtable.h
+++ b/arch/sh/include/asm/pgtable.h
@@ -148,6 +148,12 @@ extern void paging_init(void);
extern void page_table_range_init(unsigned long start, unsigned long end,
pgd_t *pgd);
+#if !defined(CONFIG_CACHE_OFF) && defined(CONFIG_CPU_SH4) && defined(CONFIG_MMU)
+extern void kmap_coherent_init(void);
+#else
+#define kmap_coherent_init() do { } while (0)
+#endif
+
#include <asm-generic/pgtable.h>
#endif /* __ASM_SH_PGTABLE_H */
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
index a7412cede53..6d9e6972cfc 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
@@ -119,17 +119,17 @@ static struct plat_sci_port sci_platform_data[] = {
},{
.mapbase = 0xa4e30000,
.flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCI,
+ .type = PORT_SCIFA,
.irqs = { 56, 56, 56, 56 },
},{
.mapbase = 0xa4e40000,
.flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCI,
+ .type = PORT_SCIFA,
.irqs = { 88, 88, 88, 88 },
},{
.mapbase = 0xa4e50000,
.flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCI,
+ .type = PORT_SCIFA,
.irqs = { 109, 109, 109, 109 },
}, {
.flags = 0,
diff --git a/arch/sh/kernel/early_printk.c b/arch/sh/kernel/early_printk.c
index 6b7d166694e..a952dcf9999 100644
--- a/arch/sh/kernel/early_printk.c
+++ b/arch/sh/kernel/early_printk.c
@@ -75,6 +75,7 @@ static struct console bios_console = {
#endif
static struct uart_port scif_port = {
+ .type = PORT_SCIF,
.mapbase = CONFIG_EARLY_SCIF_CONSOLE_PORT,
.membase = (char __iomem *)CONFIG_EARLY_SCIF_CONSOLE_PORT,
};
@@ -84,9 +85,9 @@ static void scif_sercon_putc(int c)
while (((sci_in(&scif_port, SCFDR) & EPK_FIFO_BITS) >= EPK_FIFO_SIZE))
;
- sci_out(&scif_port, SCxTDR, c);
sci_in(&scif_port, SCxSR);
sci_out(&scif_port, SCxSR, 0xf3 & ~(0x20 | 0x40));
+ sci_out(&scif_port, SCxTDR, c);
while ((sci_in(&scif_port, SCxSR) & 0x40) == 0)
;
diff --git a/arch/sh/kernel/timers/timer-tmu.c b/arch/sh/kernel/timers/timer-tmu.c
index aaaf90d06b8..3c61ddd4d43 100644
--- a/arch/sh/kernel/timers/timer-tmu.c
+++ b/arch/sh/kernel/timers/timer-tmu.c
@@ -120,7 +120,7 @@ static void tmu_set_mode(enum clock_event_mode mode,
{
switch (mode) {
case CLOCK_EVT_MODE_PERIODIC:
- ctrl_outl(ctrl_inl(TMU0_TCNT), TMU0_TCOR);
+ ctrl_outl(tmu_latest_interval[TMU0], TMU0_TCOR);
break;
case CLOCK_EVT_MODE_ONESHOT:
ctrl_outl(0, TMU0_TCOR);
diff --git a/arch/sh/lib/copy_page.S b/arch/sh/lib/copy_page.S
index 5d12e657be3..43de7e8e4e1 100644
--- a/arch/sh/lib/copy_page.S
+++ b/arch/sh/lib/copy_page.S
@@ -80,6 +80,11 @@ ENTRY(copy_page)
.section __ex_table, "a"; \
.long 9999b, 6000f ; \
.previous
+#define EX_NO_POP(...) \
+ 9999: __VA_ARGS__ ; \
+ .section __ex_table, "a"; \
+ .long 9999b, 6005f ; \
+ .previous
ENTRY(__copy_user)
! Check if small number of bytes
mov #11,r0
@@ -139,9 +144,9 @@ EX( mov.b r1,@r4 )
bt 1f
2:
-EX( mov.b @r5+,r0 )
+EX_NO_POP( mov.b @r5+,r0 )
dt r6
-EX( mov.b r0,@r4 )
+EX_NO_POP( mov.b r0,@r4 )
bf/s 2b
add #1,r4
@@ -150,7 +155,7 @@ EX( mov.b r0,@r4 )
# Exception handler:
.section .fixup, "ax"
-6000:
+6005:
mov.l 8000f,r1
mov r3,r0
jmp @r1
diff --git a/arch/sh/mm/Makefile_32 b/arch/sh/mm/Makefile_32
index 70e0906023c..f066e76da20 100644
--- a/arch/sh/mm/Makefile_32
+++ b/arch/sh/mm/Makefile_32
@@ -2,7 +2,7 @@
# Makefile for the Linux SuperH-specific parts of the memory manager.
#
-obj-y := init.o extable_32.o consistent.o
+obj-y := init.o extable_32.o consistent.o mmap.o
ifndef CONFIG_CACHE_OFF
cache-$(CONFIG_CPU_SH2) := cache-sh2.o
diff --git a/arch/sh/mm/Makefile_64 b/arch/sh/mm/Makefile_64
index 0d92a8a3ac9..9481d0f54ef 100644
--- a/arch/sh/mm/Makefile_64
+++ b/arch/sh/mm/Makefile_64
@@ -2,7 +2,7 @@
# Makefile for the Linux SuperH-specific parts of the memory manager.
#
-obj-y := init.o consistent.o
+obj-y := init.o consistent.o mmap.o
mmu-y := tlb-nommu.o pg-nommu.o extable_32.o
mmu-$(CONFIG_MMU) := fault_64.o ioremap_64.o tlbflush_64.o tlb-sh5.o \
diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c
index 4abf00031da..6cbef8caeb5 100644
--- a/arch/sh/mm/init.c
+++ b/arch/sh/mm/init.c
@@ -137,6 +137,7 @@ void __init page_table_range_init(unsigned long start, unsigned long end,
void __init paging_init(void)
{
unsigned long max_zone_pfns[MAX_NR_ZONES];
+ unsigned long vaddr;
int nid;
/* We don't need to map the kernel through the TLB, as
@@ -148,10 +149,15 @@ void __init paging_init(void)
* check for a null value. */
set_TTB(swapper_pg_dir);
- /* Populate the relevant portions of swapper_pg_dir so that
+ /*
+ * Populate the relevant portions of swapper_pg_dir so that
* we can use the fixmap entries without calling kmalloc.
- * pte's will be filled in by __set_fixmap(). */
- page_table_range_init(FIXADDR_START, FIXADDR_TOP, swapper_pg_dir);
+ * pte's will be filled in by __set_fixmap().
+ */
+ vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
+ page_table_range_init(vaddr, 0, swapper_pg_dir);
+
+ kmap_coherent_init();
memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
diff --git a/arch/sh/mm/mmap.c b/arch/sh/mm/mmap.c
new file mode 100644
index 00000000000..8837d511710
--- /dev/null
+++ b/arch/sh/mm/mmap.c
@@ -0,0 +1,31 @@
+/*
+ * arch/sh/mm/mmap.c
+ *
+ * Copyright (C) 2008 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/io.h>
+#include <linux/mm.h>
+#include <asm/page.h>
+
+/*
+ * You really shouldn't be using read() or write() on /dev/mem. This
+ * might go away in the future.
+ */
+int valid_phys_addr_range(unsigned long addr, size_t count)
+{
+ if (addr < __MEMORY_START)
+ return 0;
+ if (addr + count > __pa(high_memory))
+ return 0;
+
+ return 1;
+}
+
+int valid_mmap_phys_addr_range(unsigned long pfn, size_t size)
+{
+ return 1;
+}
diff --git a/arch/sh/mm/pg-sh4.c b/arch/sh/mm/pg-sh4.c
index 38870e0fc18..2fe14da1f83 100644
--- a/arch/sh/mm/pg-sh4.c
+++ b/arch/sh/mm/pg-sh4.c
@@ -7,6 +7,7 @@
* Released under the terms of the GNU GPL v2.0.
*/
#include <linux/mm.h>
+#include <linux/init.h>
#include <linux/mutex.h>
#include <linux/fs.h>
#include <linux/highmem.h>
@@ -16,6 +17,20 @@
#define CACHE_ALIAS (current_cpu_data.dcache.alias_mask)
+#define kmap_get_fixmap_pte(vaddr) \
+ pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr)), (vaddr))
+
+static pte_t *kmap_coherent_pte;
+
+void __init kmap_coherent_init(void)
+{
+ unsigned long vaddr;
+
+ /* cache the first coherent kmap pte */
+ vaddr = __fix_to_virt(FIX_CMAP_BEGIN);
+ kmap_coherent_pte = kmap_get_fixmap_pte(vaddr);
+}
+
static inline void *kmap_coherent(struct page *page, unsigned long addr)
{
enum fixed_addresses idx;
@@ -34,6 +49,8 @@ static inline void *kmap_coherent(struct page *page, unsigned long addr)
update_mmu_cache(NULL, vaddr, pte);
+ set_pte(kmap_coherent_pte - (FIX_CMAP_END - idx), pte);
+
return (void *)vaddr;
}
diff --git a/arch/sparc/include/asm/bitops_32.h b/arch/sparc/include/asm/bitops_32.h
index 68b98a7e645..9cf4ae0cd7b 100644
--- a/arch/sparc/include/asm/bitops_32.h
+++ b/arch/sparc/include/asm/bitops_32.h
@@ -98,6 +98,7 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/ffs.h>
#include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/__fls.h>
#include <asm-generic/bitops/fls64.h>
#include <asm-generic/bitops/hweight.h>
#include <asm-generic/bitops/lock.h>
diff --git a/arch/sparc/include/asm/ptrace_32.h b/arch/sparc/include/asm/ptrace_32.h
index d409c4f21a5..4cef450167d 100644
--- a/arch/sparc/include/asm/ptrace_32.h
+++ b/arch/sparc/include/asm/ptrace_32.h
@@ -62,6 +62,8 @@ struct sparc_stackf {
#ifdef __KERNEL__
+#include <asm/system.h>
+
static inline bool pt_regs_is_syscall(struct pt_regs *regs)
{
return (regs->psr & PSR_SYSCALL);
@@ -72,6 +74,14 @@ static inline bool pt_regs_clear_syscall(struct pt_regs *regs)
return (regs->psr &= ~PSR_SYSCALL);
}
+#define arch_ptrace_stop_needed(exit_code, info) \
+({ flush_user_windows(); \
+ current_thread_info()->w_saved != 0; \
+})
+
+#define arch_ptrace_stop(exit_code, info) \
+ synchronize_user_stack()
+
#define user_mode(regs) (!((regs)->psr & PSR_PS))
#define instruction_pointer(regs) ((regs)->pc)
#define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP])
diff --git a/arch/sparc/include/asm/ptrace_64.h b/arch/sparc/include/asm/ptrace_64.h
index 3d3e9c161d8..cd6fbfc2043 100644
--- a/arch/sparc/include/asm/ptrace_64.h
+++ b/arch/sparc/include/asm/ptrace_64.h
@@ -114,6 +114,7 @@ struct sparc_trapf {
#ifdef __KERNEL__
#include <linux/threads.h>
+#include <asm/system.h>
static inline int pt_regs_trap_type(struct pt_regs *regs)
{
@@ -130,6 +131,14 @@ static inline bool pt_regs_clear_syscall(struct pt_regs *regs)
return (regs->tstate &= ~TSTATE_SYSCALL);
}
+#define arch_ptrace_stop_needed(exit_code, info) \
+({ flush_user_windows(); \
+ get_thread_wsaved() != 0; \
+})
+
+#define arch_ptrace_stop(exit_code, info) \
+ synchronize_user_stack()
+
struct global_reg_snapshot {
unsigned long tstate;
unsigned long tpc;
@@ -142,8 +151,6 @@ struct global_reg_snapshot {
};
extern struct global_reg_snapshot global_reg_snapshot[NR_CPUS];
-#define __ARCH_WANT_COMPAT_SYS_PTRACE
-
#define force_successful_syscall_return() \
do { current_thread_info()->syscall_noerror = 1; \
} while (0)
diff --git a/arch/sparc/include/asm/termbits.h b/arch/sparc/include/asm/termbits.h
index d6ca3e2754f..d72dfed1f9d 100644
--- a/arch/sparc/include/asm/termbits.h
+++ b/arch/sparc/include/asm/termbits.h
@@ -29,10 +29,11 @@ struct termios {
tcflag_t c_cflag; /* control mode flags */
tcflag_t c_lflag; /* local mode flags */
cc_t c_line; /* line discipline */
+#ifndef __KERNEL__
cc_t c_cc[NCCS]; /* control characters */
-#ifdef __KERNEL__
+#else
+ cc_t c_cc[NCCS+2]; /* kernel needs 2 more to hold vmin/vtime */
#define SIZEOF_USER_TERMIOS sizeof (struct termios) - (2*sizeof (cc_t))
- cc_t _x_cc[2]; /* We need them to hold vmin/vtime */
#endif
};
@@ -42,8 +43,7 @@ struct termios2 {
tcflag_t c_cflag; /* control mode flags */
tcflag_t c_lflag; /* local mode flags */
cc_t c_line; /* line discipline */
- cc_t c_cc[NCCS]; /* control characters */
- cc_t _x_cc[2]; /* padding to match ktermios */
+ cc_t c_cc[NCCS+2]; /* control characters */
speed_t c_ispeed; /* input speed */
speed_t c_ospeed; /* output speed */
};
@@ -54,8 +54,7 @@ struct ktermios {
tcflag_t c_cflag; /* control mode flags */
tcflag_t c_lflag; /* local mode flags */
cc_t c_line; /* line discipline */
- cc_t c_cc[NCCS]; /* control characters */
- cc_t _x_cc[2]; /* We need them to hold vmin/vtime */
+ cc_t c_cc[NCCS+2]; /* control characters */
speed_t c_ispeed; /* input speed */
speed_t c_ospeed; /* output speed */
};
diff --git a/arch/sparc/include/asm/unistd_32.h b/arch/sparc/include/asm/unistd_32.h
index 648643a9f13..0d13d2a4c76 100644
--- a/arch/sparc/include/asm/unistd_32.h
+++ b/arch/sparc/include/asm/unistd_32.h
@@ -338,8 +338,9 @@
#define __NR_dup3 320
#define __NR_pipe2 321
#define __NR_inotify_init1 322
+#define __NR_accept4 323
-#define NR_SYSCALLS 323
+#define NR_SYSCALLS 324
/* Sparc 32-bit only has the "setresuid32", "getresuid32" variants,
* it never had the plain ones and there is no value to adding those
diff --git a/arch/sparc/include/asm/unistd_64.h b/arch/sparc/include/asm/unistd_64.h
index c5cc0e05232..fa5d3c0343c 100644
--- a/arch/sparc/include/asm/unistd_64.h
+++ b/arch/sparc/include/asm/unistd_64.h
@@ -340,8 +340,9 @@
#define __NR_dup3 320
#define __NR_pipe2 321
#define __NR_inotify_init1 322
+#define __NR_accept4 323
-#define NR_SYSCALLS 323
+#define NR_SYSCALLS 324
#ifdef __KERNEL__
#define __ARCH_WANT_IPC_PARSE_VERSION
diff --git a/arch/sparc/kernel/cpu.c b/arch/sparc/kernel/cpu.c
index e7a0edfc1a3..1fc17f59c6b 100644
--- a/arch/sparc/kernel/cpu.c
+++ b/arch/sparc/kernel/cpu.c
@@ -126,7 +126,7 @@ char *sparc_fpu_type;
unsigned int fsr_storage;
-void __init cpu_probe(void)
+void __cpuinit cpu_probe(void)
{
int psr_impl, psr_vers, fpu_vers;
int i, psr;
diff --git a/arch/sparc/kernel/head.S b/arch/sparc/kernel/head.S
index 2d325fd8457..51b40426f9c 100644
--- a/arch/sparc/kernel/head.S
+++ b/arch/sparc/kernel/head.S
@@ -72,7 +72,7 @@ sun4e_notsup:
.align 4
/* The Sparc trap table, bootloader gives us control at _start. */
- .text
+ .section .text.head,"ax"
.globl start, _stext, _start, __stext
.globl trapbase
_start: /* danger danger */
diff --git a/arch/sparc/kernel/of_device.c b/arch/sparc/kernel/of_device.c
index 0837bd52e28..0a83bd73765 100644
--- a/arch/sparc/kernel/of_device.c
+++ b/arch/sparc/kernel/of_device.c
@@ -563,9 +563,9 @@ build_resources:
op->dev.parent = parent;
op->dev.bus = &of_platform_bus_type;
if (!parent)
- strcpy(op->dev.bus_id, "root");
+ dev_set_name(&op->dev, "root");
else
- sprintf(op->dev.bus_id, "%08x", dp->node);
+ dev_set_name(&op->dev, "%08x", dp->node);
if (of_device_register(op)) {
printk("%s: Could not register of device.\n",
diff --git a/arch/sparc/kernel/smp.c b/arch/sparc/kernel/smp.c
index 1619ec15c09..e396c1f17a9 100644
--- a/arch/sparc/kernel/smp.c
+++ b/arch/sparc/kernel/smp.c
@@ -35,7 +35,7 @@
#include "irq.h"
-volatile unsigned long cpu_callin_map[NR_CPUS] __initdata = {0,};
+volatile unsigned long cpu_callin_map[NR_CPUS] __cpuinitdata = {0,};
unsigned char boot_cpu_id = 0;
unsigned char boot_cpu_id4 = 0; /* boot_cpu_id << 2 */
@@ -120,7 +120,7 @@ void cpu_panic(void)
panic("SMP bolixed\n");
}
-struct linux_prom_registers smp_penguin_ctable __initdata = { 0 };
+struct linux_prom_registers smp_penguin_ctable __cpuinitdata = { 0 };
void smp_send_reschedule(int cpu)
{
diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c
index 7a6a5e79592..16ab0cb731c 100644
--- a/arch/sparc/kernel/sun4d_smp.c
+++ b/arch/sparc/kernel/sun4d_smp.c
@@ -83,7 +83,7 @@ static inline void show_leds(int cpuid)
"i" (ASI_M_CTL));
}
-void __init smp4d_callin(void)
+void __cpuinit smp4d_callin(void)
{
int cpuid = hard_smp4d_processor_id();
extern spinlock_t sun4d_imsk_lock;
@@ -386,7 +386,7 @@ void smp4d_percpu_timer_interrupt(struct pt_regs *regs)
extern unsigned int lvl14_resolution;
-static void __init smp_setup_percpu_timer(void)
+static void __cpuinit smp_setup_percpu_timer(void)
{
int cpu = hard_smp4d_processor_id();
diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c
index 5fc386d08c4..4f8d60586b0 100644
--- a/arch/sparc/kernel/sun4m_smp.c
+++ b/arch/sparc/kernel/sun4m_smp.c
@@ -343,7 +343,7 @@ void smp4m_percpu_timer_interrupt(struct pt_regs *regs)
extern unsigned int lvl14_resolution;
-static void __init smp_setup_percpu_timer(void)
+static void __cpuinit smp_setup_percpu_timer(void)
{
int cpu = smp_processor_id();
diff --git a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S
index e1b9233b90a..7d080758644 100644
--- a/arch/sparc/kernel/systbls.S
+++ b/arch/sparc/kernel/systbls.S
@@ -81,4 +81,4 @@ sys_call_table:
/*305*/ .long sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait
/*310*/ .long sys_utimensat, sys_signalfd, sys_timerfd_create, sys_eventfd, sys_fallocate
/*315*/ .long sys_timerfd_settime, sys_timerfd_gettime, sys_signalfd4, sys_eventfd2, sys_epoll_create1
-/*320*/ .long sys_dup3, sys_pipe2, sys_inotify_init1
+/*320*/ .long sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4
diff --git a/arch/sparc/kernel/trampoline.S b/arch/sparc/kernel/trampoline.S
index 356c56aebc6..5e235c52d66 100644
--- a/arch/sparc/kernel/trampoline.S
+++ b/arch/sparc/kernel/trampoline.S
@@ -18,7 +18,7 @@
.globl sun4m_cpu_startup, __smp4m_processor_id
.globl sun4d_cpu_startup, __smp4d_processor_id
- __INIT
+ __CPUINIT
.align 4
/* When we start up a cpu for the first time it enters this routine.
@@ -109,7 +109,7 @@ __smp4d_processor_id:
/* CPUID in bootbus can be found at PA 0xff0140000 */
#define SUN4D_BOOTBUS_CPUID 0xf0140000
- __INIT
+ __CPUINIT
.align 4
sun4d_cpu_startup:
diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S
index b1002c60719..5b7e69a8c32 100644
--- a/arch/sparc/kernel/vmlinux.lds.S
+++ b/arch/sparc/kernel/vmlinux.lds.S
@@ -13,6 +13,7 @@ SECTIONS
.text 0xf0004000 :
{
_text = .;
+ *(.text.head)
TEXT_TEXT
SCHED_TEXT
LOCK_TEXT
diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c
index 6a5d7cabc04..dd8aa36f366 100644
--- a/arch/sparc/mm/srmmu.c
+++ b/arch/sparc/mm/srmmu.c
@@ -1251,7 +1251,7 @@ static inline void map_kernel(void)
/* Paging initialization on the Sparc Reference MMU. */
extern void sparc_context_init(int);
-void (*poke_srmmu)(void) __initdata = NULL;
+void (*poke_srmmu)(void) __cpuinitdata = NULL;
extern unsigned long bootmem_init(unsigned long *pages_avail);
@@ -1446,7 +1446,7 @@ static void __init init_vac_layout(void)
(int)vac_cache_size, (int)vac_line_size);
}
-static void __init poke_hypersparc(void)
+static void __cpuinit poke_hypersparc(void)
{
volatile unsigned long clear;
unsigned long mreg = srmmu_get_mmureg();
@@ -1501,7 +1501,7 @@ static void __init init_hypersparc(void)
hypersparc_setup_blockops();
}
-static void __init poke_cypress(void)
+static void __cpuinit poke_cypress(void)
{
unsigned long mreg = srmmu_get_mmureg();
unsigned long faddr, tagval;
@@ -1589,7 +1589,7 @@ static void __init init_cypress_605(unsigned long mrev)
init_cypress_common();
}
-static void __init poke_swift(void)
+static void __cpuinit poke_swift(void)
{
unsigned long mreg;
@@ -1771,7 +1771,7 @@ static void turbosparc_flush_tlb_page(struct vm_area_struct *vma, unsigned long
}
-static void __init poke_turbosparc(void)
+static void __cpuinit poke_turbosparc(void)
{
unsigned long mreg = srmmu_get_mmureg();
unsigned long ccreg;
@@ -1834,7 +1834,7 @@ static void __init init_turbosparc(void)
poke_srmmu = poke_turbosparc;
}
-static void __init poke_tsunami(void)
+static void __cpuinit poke_tsunami(void)
{
unsigned long mreg = srmmu_get_mmureg();
@@ -1876,7 +1876,7 @@ static void __init init_tsunami(void)
tsunami_setup_blockops();
}
-static void __init poke_viking(void)
+static void __cpuinit poke_viking(void)
{
unsigned long mreg = srmmu_get_mmureg();
static int smp_catch;
diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c
index f43adbc773c..a941c610e7c 100644
--- a/arch/sparc64/kernel/ptrace.c
+++ b/arch/sparc64/kernel/ptrace.c
@@ -1014,7 +1014,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break;
case PTRACE_SETFPREGS64:
- ret = copy_regset_to_user(child, view, REGSET_FP,
+ ret = copy_regset_from_user(child, view, REGSET_FP,
0 * sizeof(u64),
33 * sizeof(u64),
fps);
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index e5627118e61..f500b0618bb 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -282,7 +282,7 @@ static unsigned long kimage_addr_to_ra(void *p)
return kern_base + (val - KERNBASE);
}
-static void ldom_startcpu_cpuid(unsigned int cpu, unsigned long thread_reg)
+static void __cpuinit ldom_startcpu_cpuid(unsigned int cpu, unsigned long thread_reg)
{
extern unsigned long sparc64_ttable_tl0;
extern unsigned long kern_locked_tte_data;
@@ -343,7 +343,7 @@ extern unsigned long sparc64_cpu_startup;
*/
static struct thread_info *cpu_new_thread = NULL;
-static int __devinit smp_boot_one_cpu(unsigned int cpu)
+static int __cpuinit smp_boot_one_cpu(unsigned int cpu)
{
struct trap_per_cpu *tb = &trap_block[cpu];
unsigned long entry =
diff --git a/arch/sparc64/kernel/sys32.S b/arch/sparc64/kernel/sys32.S
index ade18ba0c68..f061c4dda9e 100644
--- a/arch/sparc64/kernel/sys32.S
+++ b/arch/sparc64/kernel/sys32.S
@@ -150,7 +150,7 @@ sys32_mmap2:
sys32_socketcall: /* %o0=call, %o1=args */
cmp %o0, 1
bl,pn %xcc, do_einval
- cmp %o0, 17
+ cmp %o0, 18
bg,pn %xcc, do_einval
sub %o0, 1, %o0
sllx %o0, 5, %o0
@@ -319,6 +319,15 @@ do_sys_recvmsg: /* compat_sys_recvmsg(int, struct compat_msghdr *, unsigned int)
nop
nop
nop
+do_sys_accept4: /* sys_accept4(int, struct sockaddr *, int *, int) */
+63: ldswa [%o1 + 0x0] %asi, %o0
+ sethi %hi(sys_accept4), %g1
+64: lduwa [%o1 + 0x8] %asi, %o2
+65: ldswa [%o1 + 0xc] %asi, %o3
+ jmpl %g1 + %lo(sys_accept4), %g0
+66: lduwa [%o1 + 0x4] %asi, %o1
+ nop
+ nop
.section __ex_table,"a"
.align 4
@@ -353,4 +362,6 @@ do_sys_recvmsg: /* compat_sys_recvmsg(int, struct compat_msghdr *, unsigned int)
.word 57b, __retl_efault, 58b, __retl_efault
.word 59b, __retl_efault, 60b, __retl_efault
.word 61b, __retl_efault, 62b, __retl_efault
+ .word 63b, __retl_efault, 64b, __retl_efault
+ .word 65b, __retl_efault, 66b, __retl_efault
.previous
diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S
index b2fa4c16363..9fc78cf354b 100644
--- a/arch/sparc64/kernel/systbls.S
+++ b/arch/sparc64/kernel/systbls.S
@@ -82,7 +82,7 @@ sys_call_table32:
.word compat_sys_set_mempolicy, compat_sys_kexec_load, compat_sys_move_pages, sys_getcpu, compat_sys_epoll_pwait
/*310*/ .word compat_sys_utimensat, compat_sys_signalfd, sys_timerfd_create, sys_eventfd, compat_sys_fallocate
.word compat_sys_timerfd_settime, compat_sys_timerfd_gettime, compat_sys_signalfd4, sys_eventfd2, sys_epoll_create1
-/*320*/ .word sys_dup3, sys_pipe2, sys_inotify_init1
+/*320*/ .word sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4
#endif /* CONFIG_COMPAT */
@@ -156,4 +156,4 @@ sys_call_table:
.word sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait
/*310*/ .word sys_utimensat, sys_signalfd, sys_timerfd_create, sys_eventfd, sys_fallocate
.word sys_timerfd_settime, sys_timerfd_gettime, sys_signalfd4, sys_eventfd2, sys_epoll_create1
-/*320*/ .word sys_dup3, sys_pipe2, sys_inotify_init1
+/*320*/ .word sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4
diff --git a/arch/sparc64/kernel/visemul.c b/arch/sparc64/kernel/visemul.c
index 9e05cb5cb85..b956fd71c13 100644
--- a/arch/sparc64/kernel/visemul.c
+++ b/arch/sparc64/kernel/visemul.c
@@ -131,7 +131,7 @@
#define VIS_OPF_SHIFT 5
#define VIS_OPF_MASK (0x1ff << VIS_OPF_SHIFT)
-#define RS1(INSN) (((INSN) >> 24) & 0x1f)
+#define RS1(INSN) (((INSN) >> 14) & 0x1f)
#define RS2(INSN) (((INSN) >> 0) & 0x1f)
#define RD(INSN) (((INSN) >> 25) & 0x1f)
@@ -445,7 +445,7 @@ static void pdist(struct pt_regs *regs, unsigned int insn)
unsigned long i;
rs1 = fpd_regval(f, RS1(insn));
- rs2 = fpd_regval(f, RS1(insn));
+ rs2 = fpd_regval(f, RS2(insn));
rd = fpd_regaddr(f, RD(insn));
rd_val = *rd;
@@ -807,6 +807,8 @@ int vis_emul(struct pt_regs *regs, unsigned int insn)
if (get_user(insn, (u32 __user *) pc))
return -EFAULT;
+ save_and_clear_fpu();
+
opf = (insn & VIS_OPF_MASK) >> VIS_OPF_SHIFT;
switch (opf) {
default:
diff --git a/arch/sparc64/lib/user_fixup.c b/arch/sparc64/lib/user_fixup.c
index 19d1fdb17d0..05a361b0a1a 100644
--- a/arch/sparc64/lib/user_fixup.c
+++ b/arch/sparc64/lib/user_fixup.c
@@ -24,7 +24,7 @@ static unsigned long compute_size(unsigned long start, unsigned long size, unsig
if (fault_addr < start || fault_addr >= end) {
*offset = 0;
} else {
- *offset = start - fault_addr;
+ *offset = fault_addr - start;
size = end - fault_addr;
}
return size;
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
index 3c10daf8fc0..185f3467911 100644
--- a/arch/sparc64/mm/init.c
+++ b/arch/sparc64/mm/init.c
@@ -956,7 +956,7 @@ int of_node_to_nid(struct device_node *dp)
return nid;
}
-static void add_node_ranges(void)
+static void __init add_node_ranges(void)
{
int i;
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index 19d579d74d2..8f44ebb0dec 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -16,6 +16,8 @@
#include <linux/slab.h>
#include <linux/syscalls.h>
#include <linux/utsname.h>
+#include <linux/socket.h>
+#include <linux/un.h>
#include <linux/workqueue.h>
#include <linux/mutex.h>
#include <asm/uaccess.h>
@@ -785,7 +787,7 @@ static int __init mconsole_init(void)
/* long to avoid size mismatch warnings from gcc */
long sock;
int err;
- char file[256];
+ char file[UNIX_PATH_MAX];
if (umid_file_name("mconsole", file, sizeof(file)))
return -1;
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 93224b56918..ac22bb7719f 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -167,9 +167,12 @@ config GENERIC_PENDING_IRQ
config X86_SMP
bool
depends on SMP && ((X86_32 && !X86_VOYAGER) || X86_64)
- select USE_GENERIC_SMP_HELPERS
default y
+config USE_GENERIC_SMP_HELPERS
+ def_bool y
+ depends on SMP
+
config X86_32_SMP
def_bool y
depends on X86_32 && SMP
@@ -957,7 +960,7 @@ config ARCH_PHYS_ADDR_T_64BIT
config NUMA
bool "Numa Memory Allocation and Scheduler Support (EXPERIMENTAL)"
depends on SMP
- depends on X86_64 || (X86_32 && HIGHMEM64G && (X86_NUMAQ || X86_BIGSMP || X86_SUMMIT && ACPI) && BROKEN)
+ depends on X86_64 || (X86_32 && HIGHMEM64G && (X86_NUMAQ || X86_BIGSMP || X86_SUMMIT && ACPI) && EXPERIMENTAL)
default n if X86_PC
default y if (X86_NUMAQ || X86_SUMMIT || X86_BIGSMP)
help
diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu
index b815664fe37..8e99073b9e0 100644
--- a/arch/x86/Kconfig.cpu
+++ b/arch/x86/Kconfig.cpu
@@ -520,6 +520,7 @@ config X86_PTRACE_BTS
bool "Branch Trace Store"
default y
depends on X86_DEBUGCTLMSR
+ depends on BROKEN
help
This adds a ptrace interface to the hardware's branch trace store.
diff --git a/arch/x86/boot/tty.c b/arch/x86/boot/tty.c
index 0be77b39328..7e8e8b25f5f 100644
--- a/arch/x86/boot/tty.c
+++ b/arch/x86/boot/tty.c
@@ -74,7 +74,7 @@ static int kbd_pending(void)
{
u8 pending;
asm volatile("int $0x16; setnz %0"
- : "=rm" (pending)
+ : "=qm" (pending)
: "a" (0x0100));
return pending;
}
diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h
index 8d676d8ecde..9830681446a 100644
--- a/arch/x86/include/asm/acpi.h
+++ b/arch/x86/include/asm/acpi.h
@@ -113,7 +113,6 @@ static inline void acpi_disable_pci(void)
acpi_pci_disabled = 1;
acpi_noirq_set();
}
-extern int acpi_irq_balance_set(char *str);
/* routines for saving/restoring kernel state */
extern int acpi_save_state_mem(void);
diff --git a/arch/x86/include/asm/amd_iommu_types.h b/arch/x86/include/asm/amd_iommu_types.h
index 1a30c0440c6..ac302a2fa33 100644
--- a/arch/x86/include/asm/amd_iommu_types.h
+++ b/arch/x86/include/asm/amd_iommu_types.h
@@ -251,13 +251,6 @@ struct amd_iommu {
/* Pointer to PCI device of this IOMMU */
struct pci_dev *dev;
- /*
- * Capability pointer. There could be more than one IOMMU per PCI
- * device function if there are more than one AMD IOMMU capability
- * pointers.
- */
- u16 cap_ptr;
-
/* physical address of MMIO space */
u64 mmio_phys;
/* virtual address of MMIO space */
@@ -266,6 +259,13 @@ struct amd_iommu {
/* capabilities of that IOMMU read from ACPI */
u32 cap;
+ /*
+ * Capability pointer. There could be more than one IOMMU per PCI
+ * device function if there are more than one AMD IOMMU capability
+ * pointers.
+ */
+ u16 cap_ptr;
+
/* pci domain of this IOMMU */
u16 pci_seg;
@@ -284,19 +284,19 @@ struct amd_iommu {
/* size of command buffer */
u32 cmd_buf_size;
- /* event buffer virtual address */
- u8 *evt_buf;
/* size of event buffer */
u32 evt_buf_size;
+ /* event buffer virtual address */
+ u8 *evt_buf;
/* MSI number for event interrupt */
u16 evt_msi_num;
- /* if one, we need to send a completion wait command */
- int need_sync;
-
/* true if interrupts for this IOMMU are already enabled */
bool int_enabled;
+ /* if one, we need to send a completion wait command */
+ int need_sync;
+
/* default dma_ops domain for that IOMMU */
struct dma_ops_domain *default_dom;
};
diff --git a/arch/x86/include/asm/dma-mapping.h b/arch/x86/include/asm/dma-mapping.h
index 7f225a4b2a2..097794ff6b7 100644
--- a/arch/x86/include/asm/dma-mapping.h
+++ b/arch/x86/include/asm/dma-mapping.h
@@ -71,15 +71,13 @@ static inline struct dma_mapping_ops *get_dma_ops(struct device *dev)
/* Make sure we keep the same behaviour */
static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
{
-#ifdef CONFIG_X86_32
- return 0;
-#else
+#ifdef CONFIG_X86_64
struct dma_mapping_ops *ops = get_dma_ops(dev);
if (ops->mapping_error)
return ops->mapping_error(dev, dma_addr);
- return (dma_addr == bad_dma_address);
#endif
+ return (dma_addr == bad_dma_address);
}
#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
diff --git a/arch/x86/include/asm/ds.h b/arch/x86/include/asm/ds.h
index 72c5a190bf4..a95008457ea 100644
--- a/arch/x86/include/asm/ds.h
+++ b/arch/x86/include/asm/ds.h
@@ -23,12 +23,13 @@
#ifndef _ASM_X86_DS_H
#define _ASM_X86_DS_H
-#ifdef CONFIG_X86_DS
#include <linux/types.h>
#include <linux/init.h>
+#ifdef CONFIG_X86_DS
+
struct task_struct;
/*
@@ -232,7 +233,8 @@ extern void ds_free(struct ds_context *context);
#else /* CONFIG_X86_DS */
-#define ds_init_intel(config) do {} while (0)
+struct cpuinfo_x86;
+static inline void __cpuinit ds_init_intel(struct cpuinfo_x86 *ignored) {}
#endif /* CONFIG_X86_DS */
#endif /* _ASM_X86_DS_H */
diff --git a/include/asm-x86/iomap.h b/arch/x86/include/asm/iomap.h
index c1f06289b14..c1f06289b14 100644
--- a/include/asm-x86/iomap.h
+++ b/arch/x86/include/asm/iomap.h
diff --git a/arch/x86/include/asm/iommu.h b/arch/x86/include/asm/iommu.h
index e4a552d4446..0b500c5b644 100644
--- a/arch/x86/include/asm/iommu.h
+++ b/arch/x86/include/asm/iommu.h
@@ -6,7 +6,6 @@ extern void no_iommu_init(void);
extern struct dma_mapping_ops nommu_dma_ops;
extern int force_iommu, no_iommu;
extern int iommu_detected;
-extern int dmar_disabled;
extern unsigned long iommu_nr_pages(unsigned long addr, unsigned long len);
diff --git a/arch/x86/include/asm/mmzone_32.h b/arch/x86/include/asm/mmzone_32.h
index 485bdf059ff..07f1af494ca 100644
--- a/arch/x86/include/asm/mmzone_32.h
+++ b/arch/x86/include/asm/mmzone_32.h
@@ -34,10 +34,14 @@ static inline void get_memcfg_numa(void)
extern int early_pfn_to_nid(unsigned long pfn);
+extern void resume_map_numa_kva(pgd_t *pgd);
+
#else /* !CONFIG_NUMA */
#define get_memcfg_numa get_memcfg_numa_flat
+static inline void resume_map_numa_kva(pgd_t *pgd) {}
+
#endif /* CONFIG_NUMA */
#ifdef CONFIG_DISCONTIGMEM
diff --git a/arch/x86/include/asm/pci_64.h b/arch/x86/include/asm/pci_64.h
index 5b28995d664..d02d936840a 100644
--- a/arch/x86/include/asm/pci_64.h
+++ b/arch/x86/include/asm/pci_64.h
@@ -34,8 +34,6 @@ extern void pci_iommu_alloc(void);
*/
#define PCI_DMA_BUS_IS_PHYS (dma_ops->is_phys)
-#if defined(CONFIG_GART_IOMMU) || defined(CONFIG_CALGARY_IOMMU)
-
#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) \
dma_addr_t ADDR_NAME;
#define DECLARE_PCI_UNMAP_LEN(LEN_NAME) \
@@ -49,18 +47,6 @@ extern void pci_iommu_alloc(void);
#define pci_unmap_len_set(PTR, LEN_NAME, VAL) \
(((PTR)->LEN_NAME) = (VAL))
-#else
-/* No IOMMU */
-
-#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
-#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)
-#define pci_unmap_addr(PTR, ADDR_NAME) (0)
-#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) do { } while (0)
-#define pci_unmap_len(PTR, LEN_NAME) (0)
-#define pci_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0)
-
-#endif
-
#endif /* __KERNEL__ */
#endif /* _ASM_X86_PCI_64_H */
diff --git a/arch/x86/include/asm/ptrace.h b/arch/x86/include/asm/ptrace.h
index d1531c8480b..eefb0594b05 100644
--- a/arch/x86/include/asm/ptrace.h
+++ b/arch/x86/include/asm/ptrace.h
@@ -271,8 +271,6 @@ extern int do_get_thread_area(struct task_struct *p, int idx,
extern int do_set_thread_area(struct task_struct *p, int idx,
struct user_desc __user *info, int can_allocate);
-#define __ARCH_WANT_COMPAT_SYS_PTRACE
-
#endif /* __KERNEL__ */
#endif /* !__ASSEMBLY__ */
diff --git a/arch/x86/include/asm/topology.h b/arch/x86/include/asm/topology.h
index 4850e4b02b6..ff386ff50ed 100644
--- a/arch/x86/include/asm/topology.h
+++ b/arch/x86/include/asm/topology.h
@@ -239,7 +239,7 @@ struct pci_bus;
void set_pci_bus_resources_arch_default(struct pci_bus *b);
#ifdef CONFIG_SMP
-#define mc_capable() (boot_cpu_data.x86_max_cores > 1)
+#define mc_capable() (cpus_weight(per_cpu(cpu_core_map, 0)) != nr_cpu_ids)
#define smt_capable() (smp_num_siblings > 1)
#endif
diff --git a/arch/x86/include/asm/uaccess_64.h b/arch/x86/include/asm/uaccess_64.h
index 664f15280f1..f8cfd00db45 100644
--- a/arch/x86/include/asm/uaccess_64.h
+++ b/arch/x86/include/asm/uaccess_64.h
@@ -46,7 +46,7 @@ int __copy_from_user(void *dst, const void __user *src, unsigned size)
return ret;
case 10:
__get_user_asm(*(u64 *)dst, (u64 __user *)src,
- ret, "q", "", "=r", 16);
+ ret, "q", "", "=r", 10);
if (unlikely(ret))
return ret;
__get_user_asm(*(u16 *)(8 + (char *)dst),
diff --git a/arch/x86/include/asm/unistd_64.h b/arch/x86/include/asm/unistd_64.h
index 834b2c1d89f..d2e415e6666 100644
--- a/arch/x86/include/asm/unistd_64.h
+++ b/arch/x86/include/asm/unistd_64.h
@@ -639,8 +639,8 @@ __SYSCALL(__NR_fallocate, sys_fallocate)
__SYSCALL(__NR_timerfd_settime, sys_timerfd_settime)
#define __NR_timerfd_gettime 287
__SYSCALL(__NR_timerfd_gettime, sys_timerfd_gettime)
-#define __NR_paccept 288
-__SYSCALL(__NR_paccept, sys_paccept)
+#define __NR_accept4 288
+__SYSCALL(__NR_accept4, sys_accept4)
#define __NR_signalfd4 289
__SYSCALL(__NR_signalfd4, sys_signalfd4)
#define __NR_eventfd2 290
diff --git a/arch/x86/include/asm/vmi.h b/arch/x86/include/asm/vmi.h
index b7c0dea119f..61e08c0a290 100644
--- a/arch/x86/include/asm/vmi.h
+++ b/arch/x86/include/asm/vmi.h
@@ -223,9 +223,15 @@ struct pci_header {
} __attribute__((packed));
/* Function prototypes for bootstrapping */
+#ifdef CONFIG_VMI
extern void vmi_init(void);
+extern void vmi_activate(void);
extern void vmi_bringup(void);
-extern void vmi_apply_boot_page_allocations(void);
+#else
+static inline void vmi_init(void) {}
+static inline void vmi_activate(void) {}
+static inline void vmi_bringup(void) {}
+#endif
/* State needed to start an application processor in an SMP system. */
struct vmi_ap_state {
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index e489ff9cb3e..b62a7667828 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -41,7 +41,7 @@ obj-$(CONFIG_X86_TRAMPOLINE) += trampoline.o
obj-y += process.o
obj-y += i387.o xsave.o
obj-y += ptrace.o
-obj-y += ds.o
+obj-$(CONFIG_X86_DS) += ds.o
obj-$(CONFIG_X86_32) += tls.o
obj-$(CONFIG_IA32_EMULATION) += tls.o
obj-y += step.o
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 8c1f76abae9..4c51a2f8fd3 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -1343,7 +1343,6 @@ static void __init acpi_process_madt(void)
error = acpi_parse_madt_ioapic_entries();
if (!error) {
acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC;
- acpi_irq_balance_set(NULL);
acpi_ioapic = 1;
smp_found_config = 1;
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 331b318304e..0a60d60ed03 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -187,6 +187,8 @@ static int iommu_queue_command(struct amd_iommu *iommu, struct iommu_cmd *cmd)
spin_lock_irqsave(&iommu->lock, flags);
ret = __iommu_queue_command(iommu, cmd);
+ if (!ret)
+ iommu->need_sync = 1;
spin_unlock_irqrestore(&iommu->lock, flags);
return ret;
@@ -210,10 +212,13 @@ static int iommu_completion_wait(struct amd_iommu *iommu)
cmd.data[0] = CMD_COMPL_WAIT_INT_MASK;
CMD_SET_TYPE(&cmd, CMD_COMPL_WAIT);
- iommu->need_sync = 0;
-
spin_lock_irqsave(&iommu->lock, flags);
+ if (!iommu->need_sync)
+ goto out;
+
+ iommu->need_sync = 0;
+
ret = __iommu_queue_command(iommu, &cmd);
if (ret)
@@ -230,8 +235,9 @@ static int iommu_completion_wait(struct amd_iommu *iommu)
status &= ~MMIO_STATUS_COM_WAIT_INT_MASK;
writel(status, iommu->mmio_base + MMIO_STATUS_OFFSET);
- if (unlikely((i == EXIT_LOOP_COUNT) && printk_ratelimit()))
- printk(KERN_WARNING "AMD IOMMU: Completion wait loop failed\n");
+ if (unlikely(i == EXIT_LOOP_COUNT))
+ panic("AMD IOMMU: Completion wait loop failed\n");
+
out:
spin_unlock_irqrestore(&iommu->lock, flags);
@@ -254,8 +260,6 @@ static int iommu_queue_inv_dev_entry(struct amd_iommu *iommu, u16 devid)
ret = iommu_queue_command(iommu, &cmd);
- iommu->need_sync = 1;
-
return ret;
}
@@ -281,8 +285,6 @@ static int iommu_queue_inv_iommu_pages(struct amd_iommu *iommu,
ret = iommu_queue_command(iommu, &cmd);
- iommu->need_sync = 1;
-
return ret;
}
@@ -343,7 +345,7 @@ static int iommu_map(struct protection_domain *dom,
u64 __pte, *pte, *page;
bus_addr = PAGE_ALIGN(bus_addr);
- phys_addr = PAGE_ALIGN(bus_addr);
+ phys_addr = PAGE_ALIGN(phys_addr);
/* only support 512GB address spaces for now */
if (bus_addr > IOMMU_MAP_SIZE_L3 || !(prot & IOMMU_PROT_MASK))
@@ -537,7 +539,7 @@ static void dma_ops_free_addresses(struct dma_ops_domain *dom,
address >>= PAGE_SHIFT;
iommu_area_free(dom->bitmap, address, pages);
- if (address + pages >= dom->next_bit)
+ if (address >= dom->next_bit)
dom->need_flush = true;
}
@@ -599,7 +601,7 @@ static void dma_ops_free_pagetable(struct dma_ops_domain *dma_dom)
continue;
p2 = IOMMU_PTE_PAGE(p1[i]);
- for (j = 0; j < 512; ++i) {
+ for (j = 0; j < 512; ++j) {
if (!IOMMU_PTE_PRESENT(p2[j]))
continue;
p3 = IOMMU_PTE_PAGE(p2[j]);
@@ -762,8 +764,6 @@ static void set_device_domain(struct amd_iommu *iommu,
write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
iommu_queue_inv_dev_entry(iommu, devid);
-
- iommu->need_sync = 1;
}
/*****************************************************************************
@@ -858,6 +858,9 @@ static int get_device_resources(struct device *dev,
print_devid(_bdf, 1);
}
+ if (domain_for_device(_bdf) == NULL)
+ set_device_domain(*iommu, *domain, _bdf);
+
return 1;
}
@@ -908,7 +911,7 @@ static void dma_ops_domain_unmap(struct amd_iommu *iommu,
if (address >= dom->aperture_size)
return;
- WARN_ON(address & 0xfffULL || address > dom->aperture_size);
+ WARN_ON(address & ~PAGE_MASK || address >= dom->aperture_size);
pte = dom->pte_pages[IOMMU_PTE_L1_INDEX(address)];
pte += IOMMU_PTE_L0_INDEX(address);
@@ -920,8 +923,8 @@ static void dma_ops_domain_unmap(struct amd_iommu *iommu,
/*
* This function contains common code for mapping of a physically
- * contiguous memory region into DMA address space. It is uses by all
- * mapping functions provided by this IOMMU driver.
+ * contiguous memory region into DMA address space. It is used by all
+ * mapping functions provided with this IOMMU driver.
* Must be called with the domain lock held.
*/
static dma_addr_t __map_single(struct device *dev,
@@ -981,7 +984,8 @@ static void __unmap_single(struct amd_iommu *iommu,
dma_addr_t i, start;
unsigned int pages;
- if ((dma_addr == 0) || (dma_addr + size > dma_dom->aperture_size))
+ if ((dma_addr == bad_dma_address) ||
+ (dma_addr + size > dma_dom->aperture_size))
return;
pages = iommu_num_pages(dma_addr, size, PAGE_SIZE);
@@ -1031,8 +1035,7 @@ static dma_addr_t map_single(struct device *dev, phys_addr_t paddr,
if (addr == bad_dma_address)
goto out;
- if (unlikely(iommu->need_sync))
- iommu_completion_wait(iommu);
+ iommu_completion_wait(iommu);
out:
spin_unlock_irqrestore(&domain->lock, flags);
@@ -1060,8 +1063,7 @@ static void unmap_single(struct device *dev, dma_addr_t dma_addr,
__unmap_single(iommu, domain->priv, dma_addr, size, dir);
- if (unlikely(iommu->need_sync))
- iommu_completion_wait(iommu);
+ iommu_completion_wait(iommu);
spin_unlock_irqrestore(&domain->lock, flags);
}
@@ -1127,8 +1129,7 @@ static int map_sg(struct device *dev, struct scatterlist *sglist,
goto unmap;
}
- if (unlikely(iommu->need_sync))
- iommu_completion_wait(iommu);
+ iommu_completion_wait(iommu);
out:
spin_unlock_irqrestore(&domain->lock, flags);
@@ -1173,8 +1174,7 @@ static void unmap_sg(struct device *dev, struct scatterlist *sglist,
s->dma_address = s->dma_length = 0;
}
- if (unlikely(iommu->need_sync))
- iommu_completion_wait(iommu);
+ iommu_completion_wait(iommu);
spin_unlock_irqrestore(&domain->lock, flags);
}
@@ -1225,8 +1225,7 @@ static void *alloc_coherent(struct device *dev, size_t size,
goto out;
}
- if (unlikely(iommu->need_sync))
- iommu_completion_wait(iommu);
+ iommu_completion_wait(iommu);
out:
spin_unlock_irqrestore(&domain->lock, flags);
@@ -1257,8 +1256,7 @@ static void free_coherent(struct device *dev, size_t size,
__unmap_single(iommu, domain->priv, dma_addr, size, DMA_BIDIRECTIONAL);
- if (unlikely(iommu->need_sync))
- iommu_completion_wait(iommu);
+ iommu_completion_wait(iommu);
spin_unlock_irqrestore(&domain->lock, flags);
diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c
index 0cdcda35a05..c6cc22815d3 100644
--- a/arch/x86/kernel/amd_iommu_init.c
+++ b/arch/x86/kernel/amd_iommu_init.c
@@ -121,7 +121,7 @@ u16 amd_iommu_last_bdf; /* largest PCI device id we have
LIST_HEAD(amd_iommu_unity_map); /* a list of required unity mappings
we find in ACPI */
unsigned amd_iommu_aperture_order = 26; /* size of aperture in power of 2 */
-int amd_iommu_isolate; /* if 1, device isolation is enabled */
+int amd_iommu_isolate = 1; /* if 1, device isolation is enabled */
bool amd_iommu_unmap_flush; /* if true, flush on every unmap */
LIST_HEAD(amd_iommu_list); /* list of all AMD IOMMUs in the
@@ -427,6 +427,10 @@ static u8 * __init alloc_command_buffer(struct amd_iommu *iommu)
memcpy_toio(iommu->mmio_base + MMIO_CMD_BUF_OFFSET,
&entry, sizeof(entry));
+ /* set head and tail to zero manually */
+ writel(0x00, iommu->mmio_base + MMIO_CMD_HEAD_OFFSET);
+ writel(0x00, iommu->mmio_base + MMIO_CMD_TAIL_OFFSET);
+
iommu_feature_enable(iommu, CONTROL_CMDBUF_EN);
return cmd_buf;
@@ -1074,7 +1078,8 @@ int __init amd_iommu_init(void)
goto free;
/* IOMMU rlookup table - find the IOMMU for a specific device */
- amd_iommu_rlookup_table = (void *)__get_free_pages(GFP_KERNEL,
+ amd_iommu_rlookup_table = (void *)__get_free_pages(
+ GFP_KERNEL | __GFP_ZERO,
get_order(rlookup_table_size));
if (amd_iommu_rlookup_table == NULL)
goto free;
@@ -1213,7 +1218,9 @@ static int __init parse_amd_iommu_options(char *str)
for (; *str; ++str) {
if (strncmp(str, "isolate", 7) == 0)
amd_iommu_isolate = 1;
- if (strncmp(str, "fullflush", 11) == 0)
+ if (strncmp(str, "share", 5) == 0)
+ amd_iommu_isolate = 0;
+ if (strncmp(str, "fullflush", 9) == 0)
amd_iommu_unmap_flush = true;
}
diff --git a/arch/x86/kernel/apic.c b/arch/x86/kernel/apic.c
index 04a7f960bbc..16f94879b52 100644
--- a/arch/x86/kernel/apic.c
+++ b/arch/x86/kernel/apic.c
@@ -1315,7 +1315,7 @@ void enable_x2apic(void)
}
}
-void enable_IR_x2apic(void)
+void __init enable_IR_x2apic(void)
{
#ifdef CONFIG_INTR_REMAP
int ret;
diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
index d3dcd58b87c..7f05f44b97e 100644
--- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
+++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
@@ -115,9 +115,20 @@ static int query_current_values_with_pending_wait(struct powernow_k8_data *data)
u32 i = 0;
if (cpu_family == CPU_HW_PSTATE) {
- rdmsr(MSR_PSTATE_STATUS, lo, hi);
- i = lo & HW_PSTATE_MASK;
- data->currpstate = i;
+ if (data->currpstate == HW_PSTATE_INVALID) {
+ /* read (initial) hw pstate if not yet set */
+ rdmsr(MSR_PSTATE_STATUS, lo, hi);
+ i = lo & HW_PSTATE_MASK;
+
+ /*
+ * a workaround for family 11h erratum 311 might cause
+ * an "out-of-range Pstate if the core is in Pstate-0
+ */
+ if (i >= data->numps)
+ data->currpstate = HW_PSTATE_0;
+ else
+ data->currpstate = i;
+ }
return 0;
}
do {
@@ -1121,6 +1132,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
}
data->cpu = pol->cpu;
+ data->currpstate = HW_PSTATE_INVALID;
if (powernow_k8_cpu_init_acpi(data)) {
/*
diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.h b/arch/x86/kernel/cpu/cpufreq/powernow-k8.h
index ab48cfed4d9..65cfb5d7f77 100644
--- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.h
+++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.h
@@ -5,6 +5,19 @@
* http://www.gnu.org/licenses/gpl.html
*/
+
+enum pstate {
+ HW_PSTATE_INVALID = 0xff,
+ HW_PSTATE_0 = 0,
+ HW_PSTATE_1 = 1,
+ HW_PSTATE_2 = 2,
+ HW_PSTATE_3 = 3,
+ HW_PSTATE_4 = 4,
+ HW_PSTATE_5 = 5,
+ HW_PSTATE_6 = 6,
+ HW_PSTATE_7 = 7,
+};
+
struct powernow_k8_data {
unsigned int cpu;
@@ -23,7 +36,9 @@ struct powernow_k8_data {
u32 exttype; /* extended interface = 1 */
/* keep track of the current fid / vid or pstate */
- u32 currvid, currfid, currpstate;
+ u32 currvid;
+ u32 currfid;
+ enum pstate currpstate;
/* the powernow_table includes all frequency and vid/fid pairings:
* fid are the lower 8 bits of the index, vid are the upper 8 bits.
diff --git a/arch/x86/kernel/cpu/mcheck/mce_64.c b/arch/x86/kernel/cpu/mcheck/mce_64.c
index 4b031a4ac85..1c838032fd3 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_64.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_64.c
@@ -510,12 +510,9 @@ static void __cpuinit mce_cpu_features(struct cpuinfo_x86 *c)
*/
void __cpuinit mcheck_init(struct cpuinfo_x86 *c)
{
- static cpumask_t mce_cpus = CPU_MASK_NONE;
-
mce_cpu_quirks(c);
if (mce_dont_init ||
- cpu_test_and_set(smp_processor_id(), mce_cpus) ||
!mce_available(c))
return;
diff --git a/arch/x86/kernel/ds.c b/arch/x86/kernel/ds.c
index 2b69994fd3a..a2d1176c38e 100644
--- a/arch/x86/kernel/ds.c
+++ b/arch/x86/kernel/ds.c
@@ -21,8 +21,6 @@
*/
-#ifdef CONFIG_X86_DS
-
#include <asm/ds.h>
#include <linux/errno.h>
@@ -211,14 +209,15 @@ static DEFINE_PER_CPU(struct ds_context *, system_context);
static inline struct ds_context *ds_get_context(struct task_struct *task)
{
struct ds_context *context;
+ unsigned long irq;
- spin_lock(&ds_lock);
+ spin_lock_irqsave(&ds_lock, irq);
context = (task ? task->thread.ds_ctx : this_system_context);
if (context)
context->count++;
- spin_unlock(&ds_lock);
+ spin_unlock_irqrestore(&ds_lock, irq);
return context;
}
@@ -226,18 +225,16 @@ static inline struct ds_context *ds_get_context(struct task_struct *task)
/*
* Same as ds_get_context, but allocates the context and it's DS
* structure, if necessary; returns NULL; if out of memory.
- *
- * pre: requires ds_lock to be held
*/
static inline struct ds_context *ds_alloc_context(struct task_struct *task)
{
struct ds_context **p_context =
(task ? &task->thread.ds_ctx : &this_system_context);
struct ds_context *context = *p_context;
+ unsigned long irq;
if (!context) {
context = kzalloc(sizeof(*context), GFP_KERNEL);
-
if (!context)
return NULL;
@@ -247,18 +244,27 @@ static inline struct ds_context *ds_alloc_context(struct task_struct *task)
return NULL;
}
- *p_context = context;
+ spin_lock_irqsave(&ds_lock, irq);
- context->this = p_context;
- context->task = task;
+ if (*p_context) {
+ kfree(context->ds);
+ kfree(context);
+
+ context = *p_context;
+ } else {
+ *p_context = context;
- if (task)
- set_tsk_thread_flag(task, TIF_DS_AREA_MSR);
+ context->this = p_context;
+ context->task = task;
- if (!task || (task == current))
- wrmsr(MSR_IA32_DS_AREA, (unsigned long)context->ds, 0);
+ if (task)
+ set_tsk_thread_flag(task, TIF_DS_AREA_MSR);
- get_tracer(task);
+ if (!task || (task == current))
+ wrmsrl(MSR_IA32_DS_AREA,
+ (unsigned long)context->ds);
+ }
+ spin_unlock_irqrestore(&ds_lock, irq);
}
context->count++;
@@ -272,10 +278,12 @@ static inline struct ds_context *ds_alloc_context(struct task_struct *task)
*/
static inline void ds_put_context(struct ds_context *context)
{
+ unsigned long irq;
+
if (!context)
return;
- spin_lock(&ds_lock);
+ spin_lock_irqsave(&ds_lock, irq);
if (--context->count)
goto out;
@@ -297,7 +305,7 @@ static inline void ds_put_context(struct ds_context *context)
kfree(context->ds);
kfree(context);
out:
- spin_unlock(&ds_lock);
+ spin_unlock_irqrestore(&ds_lock, irq);
}
@@ -368,6 +376,7 @@ static int ds_request(struct task_struct *task, void *base, size_t size,
struct ds_context *context;
unsigned long buffer, adj;
const unsigned long alignment = (1 << 3);
+ unsigned long irq;
int error = 0;
if (!ds_cfg.sizeof_ds)
@@ -382,25 +391,27 @@ static int ds_request(struct task_struct *task, void *base, size_t size,
return -EOPNOTSUPP;
- spin_lock(&ds_lock);
-
- if (!check_tracer(task))
- return -EPERM;
-
- error = -ENOMEM;
context = ds_alloc_context(task);
if (!context)
+ return -ENOMEM;
+
+ spin_lock_irqsave(&ds_lock, irq);
+
+ error = -EPERM;
+ if (!check_tracer(task))
goto out_unlock;
+ get_tracer(task);
+
error = -EALREADY;
if (context->owner[qual] == current)
- goto out_unlock;
+ goto out_put_tracer;
error = -EPERM;
if (context->owner[qual] != NULL)
- goto out_unlock;
+ goto out_put_tracer;
context->owner[qual] = current;
- spin_unlock(&ds_lock);
+ spin_unlock_irqrestore(&ds_lock, irq);
error = -ENOMEM;
@@ -448,10 +459,17 @@ static int ds_request(struct task_struct *task, void *base, size_t size,
out_release:
context->owner[qual] = NULL;
ds_put_context(context);
+ put_tracer(task);
+ return error;
+
+ out_put_tracer:
+ spin_unlock_irqrestore(&ds_lock, irq);
+ ds_put_context(context);
+ put_tracer(task);
return error;
out_unlock:
- spin_unlock(&ds_lock);
+ spin_unlock_irqrestore(&ds_lock, irq);
ds_put_context(context);
return error;
}
@@ -801,13 +819,21 @@ static const struct ds_configuration ds_cfg_var = {
.sizeof_ds = sizeof(long) * 12,
.sizeof_field = sizeof(long),
.sizeof_rec[ds_bts] = sizeof(long) * 3,
+#ifdef __i386__
.sizeof_rec[ds_pebs] = sizeof(long) * 10
+#else
+ .sizeof_rec[ds_pebs] = sizeof(long) * 18
+#endif
};
static const struct ds_configuration ds_cfg_64 = {
.sizeof_ds = 8 * 12,
.sizeof_field = 8,
.sizeof_rec[ds_bts] = 8 * 3,
+#ifdef __i386__
.sizeof_rec[ds_pebs] = 8 * 10
+#else
+ .sizeof_rec[ds_pebs] = 8 * 18
+#endif
};
static inline void
@@ -861,4 +887,3 @@ void ds_free(struct ds_context *context)
while (leftovers--)
ds_put_context(context);
}
-#endif /* CONFIG_X86_DS */
diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c
index 3ce029ffaa5..1b894b72c0f 100644
--- a/arch/x86/kernel/early-quirks.c
+++ b/arch/x86/kernel/early-quirks.c
@@ -188,20 +188,6 @@ static void __init ati_bugs_contd(int num, int slot, int func)
}
#endif
-#ifdef CONFIG_DMAR
-static void __init intel_g33_dmar(int num, int slot, int func)
-{
- struct acpi_table_header *dmar_tbl;
- acpi_status status;
-
- status = acpi_get_table(ACPI_SIG_DMAR, 0, &dmar_tbl);
- if (ACPI_SUCCESS(status)) {
- printk(KERN_INFO "BIOS BUG: DMAR advertised on Intel G31/G33 chipset -- ignoring\n");
- dmar_disabled = 1;
- }
-}
-#endif
-
#define QFLAG_APPLY_ONCE 0x1
#define QFLAG_APPLIED 0x2
#define QFLAG_DONE (QFLAG_APPLY_ONCE|QFLAG_APPLIED)
@@ -225,10 +211,6 @@ static struct chipset early_qrk[] __initdata = {
PCI_CLASS_SERIAL_SMBUS, PCI_ANY_ID, 0, ati_bugs },
{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS,
PCI_CLASS_SERIAL_SMBUS, PCI_ANY_ID, 0, ati_bugs_contd },
-#ifdef CONFIG_DMAR
- { PCI_VENDOR_ID_INTEL, 0x29c0,
- PCI_CLASS_BRIDGE_HOST, PCI_ANY_ID, 0, intel_g33_dmar },
-#endif
{}
};
diff --git a/arch/x86/kernel/es7000_32.c b/arch/x86/kernel/es7000_32.c
index f454c78fcef..0aa2c443d60 100644
--- a/arch/x86/kernel/es7000_32.c
+++ b/arch/x86/kernel/es7000_32.c
@@ -250,31 +250,24 @@ int __init find_unisys_acpi_oem_table(unsigned long *oem_addr)
{
struct acpi_table_header *header = NULL;
int i = 0;
- acpi_size tbl_size;
- while (ACPI_SUCCESS(acpi_get_table_with_size("OEM1", i++, &header, &tbl_size))) {
+ while (ACPI_SUCCESS(acpi_get_table("OEM1", i++, &header))) {
if (!memcmp((char *) &header->oem_id, "UNISYS", 6)) {
struct oem_table *t = (struct oem_table *)header;
oem_addrX = t->OEMTableAddr;
oem_size = t->OEMTableSize;
- early_acpi_os_unmap_memory(header, tbl_size);
*oem_addr = (unsigned long)__acpi_map_table(oem_addrX,
oem_size);
return 0;
}
- early_acpi_os_unmap_memory(header, tbl_size);
}
return -1;
}
void __init unmap_unisys_acpi_oem_table(unsigned long oem_addr)
{
- if (!oem_addr)
- return;
-
- __acpi_unmap_table((char *)oem_addr, oem_size);
}
#endif
diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c
index 1f20608d4ca..b0f61f0dcd0 100644
--- a/arch/x86/kernel/i387.c
+++ b/arch/x86/kernel/i387.c
@@ -58,7 +58,7 @@ void __cpuinit mxcsr_feature_mask_init(void)
stts();
}
-void __init init_thread_xstate(void)
+void __cpuinit init_thread_xstate(void)
{
if (!HAVE_HWFP) {
xstate_size = sizeof(struct i387_soft_struct);
diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c
index 7a3f2028e2e..9043251210f 100644
--- a/arch/x86/kernel/io_apic.c
+++ b/arch/x86/kernel/io_apic.c
@@ -1140,6 +1140,20 @@ static void __clear_irq_vector(int irq)
cfg->vector = 0;
cpus_clear(cfg->domain);
+
+ if (likely(!cfg->move_in_progress))
+ return;
+ cpus_and(mask, cfg->old_domain, cpu_online_map);
+ for_each_cpu_mask_nr(cpu, mask) {
+ for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS;
+ vector++) {
+ if (per_cpu(vector_irq, cpu)[vector] != irq)
+ continue;
+ per_cpu(vector_irq, cpu)[vector] = -1;
+ break;
+ }
+ }
+ cfg->move_in_progress = 0;
}
void __setup_vector_irq(int cpu)
@@ -3594,27 +3608,7 @@ int __init io_apic_get_redir_entries (int ioapic)
int __init probe_nr_irqs(void)
{
- int idx;
- int nr = 0;
-#ifndef CONFIG_XEN
- int nr_min = 32;
-#else
- int nr_min = NR_IRQS;
-#endif
-
- for (idx = 0; idx < nr_ioapics; idx++)
- nr += io_apic_get_redir_entries(idx) + 1;
-
- /* double it for hotplug and msi and nmi */
- nr <<= 1;
-
- /* something wrong ? */
- if (nr < nr_min)
- nr = nr_min;
- if (WARN_ON(nr > NR_IRQS))
- nr = NR_IRQS;
-
- return nr;
+ return NR_IRQS;
}
/* --------------------------------------------------------------------------
@@ -3761,7 +3755,9 @@ int acpi_get_override_irq(int bus_irq, int *trigger, int *polarity)
void __init setup_ioapic_dest(void)
{
int pin, ioapic, irq, irq_entry;
+ struct irq_desc *desc;
struct irq_cfg *cfg;
+ cpumask_t mask;
if (skip_ioapic_setup == 1)
return;
@@ -3778,16 +3774,30 @@ void __init setup_ioapic_dest(void)
* cpu is online.
*/
cfg = irq_cfg(irq);
- if (!cfg->vector)
+ if (!cfg->vector) {
setup_IO_APIC_irq(ioapic, pin, irq,
irq_trigger(irq_entry),
irq_polarity(irq_entry));
+ continue;
+
+ }
+
+ /*
+ * Honour affinities which have been set in early boot
+ */
+ desc = irq_to_desc(irq);
+ if (desc->status &
+ (IRQ_NO_BALANCING | IRQ_AFFINITY_SET))
+ mask = desc->affinity;
+ else
+ mask = TARGET_CPUS;
+
#ifdef CONFIG_INTR_REMAP
- else if (intr_remapping_enabled)
- set_ir_ioapic_affinity_irq(irq, TARGET_CPUS);
-#endif
+ if (intr_remapping_enabled)
+ set_ir_ioapic_affinity_irq(irq, mask);
else
- set_ioapic_affinity_irq(irq, TARGET_CPUS);
+#endif
+ set_ioapic_affinity_irq(irq, mask);
}
}
diff --git a/arch/x86/kernel/kvmclock.c b/arch/x86/kernel/kvmclock.c
index 774ac499156..e169ae9b6a6 100644
--- a/arch/x86/kernel/kvmclock.c
+++ b/arch/x86/kernel/kvmclock.c
@@ -128,7 +128,7 @@ static int kvm_register_clock(char *txt)
}
#ifdef CONFIG_X86_LOCAL_APIC
-static void kvm_setup_secondary_clock(void)
+static void __cpuinit kvm_setup_secondary_clock(void)
{
/*
* Now that the first cpu already had this clocksource initialized,
diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c
index 82fb2809ce3..c4b5b24e021 100644
--- a/arch/x86/kernel/microcode_core.c
+++ b/arch/x86/kernel/microcode_core.c
@@ -272,13 +272,18 @@ static struct attribute_group mc_attr_group = {
.name = "microcode",
};
-static void microcode_fini_cpu(int cpu)
+static void __microcode_fini_cpu(int cpu)
{
struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
- mutex_lock(&microcode_mutex);
microcode_ops->microcode_fini_cpu(cpu);
uci->valid = 0;
+}
+
+static void microcode_fini_cpu(int cpu)
+{
+ mutex_lock(&microcode_mutex);
+ __microcode_fini_cpu(cpu);
mutex_unlock(&microcode_mutex);
}
@@ -306,12 +311,16 @@ static int microcode_resume_cpu(int cpu)
* to this cpu (a bit of paranoia):
*/
if (microcode_ops->collect_cpu_info(cpu, &nsig)) {
- microcode_fini_cpu(cpu);
+ __microcode_fini_cpu(cpu);
+ printk(KERN_ERR "failed to collect_cpu_info for resuming cpu #%d\n",
+ cpu);
return -1;
}
- if (memcmp(&nsig, &uci->cpu_sig, sizeof(nsig))) {
- microcode_fini_cpu(cpu);
+ if ((nsig.sig != uci->cpu_sig.sig) || (nsig.pf != uci->cpu_sig.pf)) {
+ __microcode_fini_cpu(cpu);
+ printk(KERN_ERR "cached ucode doesn't match the resuming cpu #%d\n",
+ cpu);
/* Should we look for a new ucode here? */
return 1;
}
diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c
index 622dc4a2178..a8e62792d17 100644
--- a/arch/x86/kernel/microcode_intel.c
+++ b/arch/x86/kernel/microcode_intel.c
@@ -155,6 +155,7 @@ static DEFINE_SPINLOCK(microcode_update_lock);
static int collect_cpu_info(int cpu_num, struct cpu_signature *csig)
{
struct cpuinfo_x86 *c = &cpu_data(cpu_num);
+ unsigned long flags;
unsigned int val[2];
memset(csig, 0, sizeof(*csig));
@@ -174,11 +175,16 @@ static int collect_cpu_info(int cpu_num, struct cpu_signature *csig)
csig->pf = 1 << ((val[1] >> 18) & 7);
}
+ /* serialize access to the physical write to MSR 0x79 */
+ spin_lock_irqsave(&microcode_update_lock, flags);
+
wrmsr(MSR_IA32_UCODE_REV, 0, 0);
/* see notes above for revision 1.07. Apparent chip bug */
sync_core();
/* get the current revision from MSR 0x8B */
rdmsr(MSR_IA32_UCODE_REV, val[0], csig->rev);
+ spin_unlock_irqrestore(&microcode_update_lock, flags);
+
pr_debug("microcode: collect_cpu_info : sig=0x%x, pf=0x%x, rev=0x%x\n",
csig->sig, csig->pf, csig->rev);
diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c
index f98f4e1dba0..0f4c1fd5a1f 100644
--- a/arch/x86/kernel/mpparse.c
+++ b/arch/x86/kernel/mpparse.c
@@ -604,6 +604,9 @@ static void __init __get_smp_config(unsigned int early)
printk(KERN_INFO "Using ACPI for processor (LAPIC) "
"configuration information\n");
+ if (!mpf)
+ return;
+
printk(KERN_INFO "Intel MultiProcessor Specification v1.%d\n",
mpf->mpf_specification);
#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86_32)
diff --git a/arch/x86/kernel/paravirt-spinlocks.c b/arch/x86/kernel/paravirt-spinlocks.c
index 0e9f1982b1d..95777b0faa7 100644
--- a/arch/x86/kernel/paravirt-spinlocks.c
+++ b/arch/x86/kernel/paravirt-spinlocks.c
@@ -7,7 +7,8 @@
#include <asm/paravirt.h>
-static void default_spin_lock_flags(struct raw_spinlock *lock, unsigned long flags)
+static inline void
+default_spin_lock_flags(raw_spinlock_t *lock, unsigned long flags)
{
__raw_spin_lock(lock);
}
diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c
index e1e731d78f3..d28bbdc35e4 100644
--- a/arch/x86/kernel/pci-calgary_64.c
+++ b/arch/x86/kernel/pci-calgary_64.c
@@ -1567,7 +1567,7 @@ static int __init calgary_parse_options(char *p)
++p;
if (*p == '\0')
break;
- bridge = simple_strtol(p, &endp, 0);
+ bridge = simple_strtoul(p, &endp, 0);
if (p == endp)
break;
diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c
index a42b02b4df6..a35eaa379ff 100644
--- a/arch/x86/kernel/pci-gart_64.c
+++ b/arch/x86/kernel/pci-gart_64.c
@@ -123,6 +123,8 @@ static void free_iommu(unsigned long offset, int size)
spin_lock_irqsave(&iommu_bitmap_lock, flags);
iommu_area_free(iommu_gart_bitmap, offset, size);
+ if (offset >= next_bit)
+ next_bit = offset + size;
spin_unlock_irqrestore(&iommu_bitmap_lock, flags);
}
@@ -743,10 +745,8 @@ void __init gart_iommu_init(void)
unsigned long scratch;
long i;
- if (cache_k8_northbridges() < 0 || num_k8_northbridges == 0) {
- printk(KERN_INFO "PCI-GART: No AMD GART found.\n");
+ if (cache_k8_northbridges() < 0 || num_k8_northbridges == 0)
return;
- }
#ifndef CONFIG_AGP_AMD64
no_agp = 1;
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index 724adfc63cb..cc5a2545dd4 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -169,6 +169,15 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {
DMI_MATCH(DMI_BOARD_NAME, "0KW626"),
},
},
+ { /* Handle problems with rebooting on Dell Optiplex 330 with 0KP561 */
+ .callback = set_bios_reboot,
+ .ident = "Dell OptiPlex 330",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 330"),
+ DMI_MATCH(DMI_BOARD_NAME, "0KP561"),
+ },
+ },
{ /* Handle problems with rebooting on Dell 2400's */
.callback = set_bios_reboot,
.ident = "Dell PowerEdge 2400",
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 0fa6790c1dd..bdec76e5559 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -764,7 +764,7 @@ static struct dmi_system_id __initdata bad_bios_dmi_table[] = {
.callback = dmi_low_memory_corruption,
.ident = "Phoenix BIOS",
.matches = {
- DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies, LTD"),
+ DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies"),
},
},
#endif
@@ -794,6 +794,9 @@ void __init setup_arch(char **cmdline_p)
printk(KERN_INFO "Command line: %s\n", boot_command_line);
#endif
+ /* VMI may relocate the fixmap; do this before touching ioremap area */
+ vmi_init();
+
early_cpu_init();
early_ioremap_init();
@@ -880,13 +883,8 @@ void __init setup_arch(char **cmdline_p)
check_efer();
#endif
-#if defined(CONFIG_VMI) && defined(CONFIG_X86_32)
- /*
- * Must be before kernel pagetables are setup
- * or fixmap area is touched.
- */
- vmi_init();
-#endif
+ /* Must be before kernel pagetables are setup */
+ vmi_activate();
/* after early param, so could get panic from serial */
reserve_early_setup_data();
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 7b109339731..f71f96fc9e6 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -294,9 +294,7 @@ static void __cpuinit start_secondary(void *unused)
* fragile that we want to limit the things done here to the
* most necessary things.
*/
-#ifdef CONFIG_VMI
vmi_bringup();
-#endif
cpu_init();
preempt_disable();
smp_callin();
diff --git a/arch/x86/kernel/tsc_sync.c b/arch/x86/kernel/tsc_sync.c
index 9ffb01c31c4..1c0dfbca87c 100644
--- a/arch/x86/kernel/tsc_sync.c
+++ b/arch/x86/kernel/tsc_sync.c
@@ -46,7 +46,9 @@ static __cpuinit void check_tsc_warp(void)
cycles_t start, now, prev, end;
int i;
+ rdtsc_barrier();
start = get_cycles();
+ rdtsc_barrier();
/*
* The measurement runs for 20 msecs:
*/
@@ -61,7 +63,9 @@ static __cpuinit void check_tsc_warp(void)
*/
__raw_spin_lock(&sync_lock);
prev = last_tsc;
+ rdtsc_barrier();
now = get_cycles();
+ rdtsc_barrier();
last_tsc = now;
__raw_spin_unlock(&sync_lock);
diff --git a/arch/x86/kernel/vmi_32.c b/arch/x86/kernel/vmi_32.c
index 8b6c393ab9f..22fd6577156 100644
--- a/arch/x86/kernel/vmi_32.c
+++ b/arch/x86/kernel/vmi_32.c
@@ -960,8 +960,6 @@ static inline int __init activate_vmi(void)
void __init vmi_init(void)
{
- unsigned long flags;
-
if (!vmi_rom)
probe_vmi_rom();
else
@@ -973,13 +971,21 @@ void __init vmi_init(void)
reserve_top_address(-vmi_rom->virtual_top);
- local_irq_save(flags);
- activate_vmi();
-
#ifdef CONFIG_X86_IO_APIC
/* This is virtual hardware; timer routing is wired correctly */
no_timer_check = 1;
#endif
+}
+
+void vmi_activate(void)
+{
+ unsigned long flags;
+
+ if (!vmi_rom)
+ return;
+
+ local_irq_save(flags);
+ activate_vmi();
local_irq_restore(flags & X86_EFLAGS_IF);
}
diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c
index b13acb75e82..15c3e699918 100644
--- a/arch/x86/kernel/xsave.c
+++ b/arch/x86/kernel/xsave.c
@@ -310,7 +310,7 @@ static void __init setup_xstate_init(void)
/*
* Enable and initialize the xsave feature.
*/
-void __init xsave_cntxt_init(void)
+void __ref xsave_cntxt_init(void)
{
unsigned int eax, ebx, ecx, edx;
diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig
index ce3251ce550..b81125f0bde 100644
--- a/arch/x86/kvm/Kconfig
+++ b/arch/x86/kvm/Kconfig
@@ -20,6 +20,8 @@ if VIRTUALIZATION
config KVM
tristate "Kernel-based Virtual Machine (KVM) support"
depends on HAVE_KVM
+ # for device assignment:
+ depends on PCI
select PREEMPT_NOTIFIERS
select MMU_NOTIFIER
select ANON_INODES
diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c
index 8772dc94682..59ebd37ad79 100644
--- a/arch/x86/kvm/i8254.c
+++ b/arch/x86/kvm/i8254.c
@@ -548,8 +548,10 @@ struct kvm_pit *kvm_create_pit(struct kvm *kvm)
mutex_lock(&kvm->lock);
pit->irq_source_id = kvm_request_irq_source_id(kvm);
mutex_unlock(&kvm->lock);
- if (pit->irq_source_id < 0)
+ if (pit->irq_source_id < 0) {
+ kfree(pit);
return NULL;
+ }
mutex_init(&pit->pit_state.lock);
mutex_lock(&pit->pit_state.lock);
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 2a5e64881d9..410ddbc1aa2 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -314,7 +314,7 @@ static int mmu_topup_memory_caches(struct kvm_vcpu *vcpu)
if (r)
goto out;
r = mmu_topup_memory_cache(&vcpu->arch.mmu_rmap_desc_cache,
- rmap_desc_cache, 1);
+ rmap_desc_cache, 4);
if (r)
goto out;
r = mmu_topup_memory_cache_page(&vcpu->arch.mmu_page_cache, 8);
@@ -1038,13 +1038,13 @@ static int kvm_sync_page(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
}
rmap_write_protect(vcpu->kvm, sp->gfn);
+ kvm_unlink_unsync_page(vcpu->kvm, sp);
if (vcpu->arch.mmu.sync_page(vcpu, sp)) {
kvm_mmu_zap_page(vcpu->kvm, sp);
return 1;
}
kvm_mmu_flush_tlb(vcpu);
- kvm_unlink_unsync_page(vcpu->kvm, sp);
return 0;
}
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
index 613ec9aa674..84eee43bbe7 100644
--- a/arch/x86/kvm/paging_tmpl.h
+++ b/arch/x86/kvm/paging_tmpl.h
@@ -331,6 +331,7 @@ static int FNAME(shadow_walk_entry)(struct kvm_shadow_walk *_sw,
r = kvm_read_guest_atomic(vcpu->kvm, gw->pte_gpa[level - 2],
&curr_pte, sizeof(curr_pte));
if (r || curr_pte != gw->ptes[level - 2]) {
+ kvm_mmu_put_page(shadow_page, sptep);
kvm_release_pfn_clean(sw->pfn);
sw->sptep = NULL;
return 1;
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 2643b430d83..a4018b01e1f 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -3149,7 +3149,9 @@ static void vmx_intr_assist(struct kvm_vcpu *vcpu)
if (cpu_has_virtual_nmis()) {
if (vcpu->arch.nmi_pending && !vcpu->arch.nmi_injected) {
- if (vmx_nmi_enabled(vcpu)) {
+ if (vcpu->arch.interrupt.pending) {
+ enable_nmi_window(vcpu);
+ } else if (vmx_nmi_enabled(vcpu)) {
vcpu->arch.nmi_pending = false;
vcpu->arch.nmi_injected = true;
} else {
@@ -3564,7 +3566,8 @@ static int __init vmx_init(void)
bypass_guest_pf = 0;
kvm_mmu_set_base_ptes(VMX_EPT_READABLE_MASK |
VMX_EPT_WRITABLE_MASK |
- VMX_EPT_DEFAULT_MT << VMX_EPT_MT_EPTE_SHIFT);
+ VMX_EPT_DEFAULT_MT << VMX_EPT_MT_EPTE_SHIFT |
+ VMX_EPT_IGMT_BIT);
kvm_mmu_set_mask_ptes(0ull, 0ull, 0ull, 0ull,
VMX_EPT_EXECUTABLE_MASK);
kvm_enable_tdp();
diff --git a/arch/x86/kvm/vmx.h b/arch/x86/kvm/vmx.h
index 3e010d21fdd..ec5edc339da 100644
--- a/arch/x86/kvm/vmx.h
+++ b/arch/x86/kvm/vmx.h
@@ -352,6 +352,7 @@ enum vmcs_field {
#define VMX_EPT_READABLE_MASK 0x1ull
#define VMX_EPT_WRITABLE_MASK 0x2ull
#define VMX_EPT_EXECUTABLE_MASK 0x4ull
+#define VMX_EPT_IGMT_BIT (1ull << 6)
#define VMX_EPT_IDENTITY_PAGETABLE_ADDR 0xfffbc000ul
diff --git a/arch/x86/mach-voyager/voyager_smp.c b/arch/x86/mach-voyager/voyager_smp.c
index 0e331652681..52145007bd7 100644
--- a/arch/x86/mach-voyager/voyager_smp.c
+++ b/arch/x86/mach-voyager/voyager_smp.c
@@ -7,6 +7,7 @@
* This file provides all the same external entries as smp.c but uses
* the voyager hal to provide the functionality
*/
+#include <linux/cpu.h>
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/kernel_stat.h>
@@ -1790,6 +1791,17 @@ void __init smp_setup_processor_id(void)
x86_write_percpu(cpu_number, hard_smp_processor_id());
}
+static void voyager_send_call_func(cpumask_t callmask)
+{
+ __u32 mask = cpus_addr(callmask)[0] & ~(1 << smp_processor_id());
+ send_CPI(mask, VIC_CALL_FUNCTION_CPI);
+}
+
+static void voyager_send_call_func_single(int cpu)
+{
+ send_CPI(1 << cpu, VIC_CALL_FUNCTION_SINGLE_CPI);
+}
+
struct smp_ops smp_ops = {
.smp_prepare_boot_cpu = voyager_smp_prepare_boot_cpu,
.smp_prepare_cpus = voyager_smp_prepare_cpus,
@@ -1799,6 +1811,6 @@ struct smp_ops smp_ops = {
.smp_send_stop = voyager_smp_send_stop,
.smp_send_reschedule = voyager_smp_send_reschedule,
- .send_call_func_ipi = native_send_call_func_ipi,
- .send_call_func_single_ipi = native_send_call_func_single_ipi,
+ .send_call_func_ipi = voyager_send_call_func,
+ .send_call_func_single_ipi = voyager_send_call_func_single,
};
diff --git a/arch/x86/mm/numa_32.c b/arch/x86/mm/numa_32.c
index 847c164725f..8518c678d83 100644
--- a/arch/x86/mm/numa_32.c
+++ b/arch/x86/mm/numa_32.c
@@ -222,6 +222,41 @@ static void __init remap_numa_kva(void)
}
}
+#ifdef CONFIG_HIBERNATION
+/**
+ * resume_map_numa_kva - add KVA mapping to the temporary page tables created
+ * during resume from hibernation
+ * @pgd_base - temporary resume page directory
+ */
+void resume_map_numa_kva(pgd_t *pgd_base)
+{
+ int node;
+
+ for_each_online_node(node) {
+ unsigned long start_va, start_pfn, size, pfn;
+
+ start_va = (unsigned long)node_remap_start_vaddr[node];
+ start_pfn = node_remap_start_pfn[node];
+ size = node_remap_size[node];
+
+ printk(KERN_DEBUG "%s: node %d\n", __FUNCTION__, node);
+
+ for (pfn = 0; pfn < size; pfn += PTRS_PER_PTE) {
+ unsigned long vaddr = start_va + (pfn << PAGE_SHIFT);
+ pgd_t *pgd = pgd_base + pgd_index(vaddr);
+ pud_t *pud = pud_offset(pgd, vaddr);
+ pmd_t *pmd = pmd_offset(pud, vaddr);
+
+ set_pmd(pmd, pfn_pmd(start_pfn + pfn,
+ PAGE_KERNEL_LARGE_EXEC));
+
+ printk(KERN_DEBUG "%s: %08lx -> pfn %08lx\n",
+ __FUNCTION__, vaddr, start_pfn + pfn);
+ }
+ }
+}
+#endif
+
static unsigned long calculate_numa_remap_pages(void)
{
int nid;
diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c
index 022cd41ea9b..202864ad49a 100644
--- a/arch/x86/oprofile/nmi_int.c
+++ b/arch/x86/oprofile/nmi_int.c
@@ -401,14 +401,13 @@ static int __init ppro_init(char **cpu_type)
*cpu_type = "i386/pii";
break;
case 6 ... 8:
+ case 10 ... 11:
*cpu_type = "i386/piii";
break;
case 9:
+ case 13:
*cpu_type = "i386/p6_mobile";
break;
- case 10 ... 13:
- *cpu_type = "i386/p6";
- break;
case 14:
*cpu_type = "i386/core";
break;
diff --git a/arch/x86/oprofile/op_model_ppro.c b/arch/x86/oprofile/op_model_ppro.c
index 3f1b81a83e2..e9f80c744cf 100644
--- a/arch/x86/oprofile/op_model_ppro.c
+++ b/arch/x86/oprofile/op_model_ppro.c
@@ -69,7 +69,7 @@ static void ppro_setup_ctrs(struct op_msrs const * const msrs)
int i;
if (!reset_value) {
- reset_value = kmalloc(sizeof(unsigned) * num_counters,
+ reset_value = kmalloc(sizeof(reset_value[0]) * num_counters,
GFP_ATOMIC);
if (!reset_value)
return;
@@ -156,6 +156,8 @@ static void ppro_start(struct op_msrs const * const msrs)
unsigned int low, high;
int i;
+ if (!reset_value)
+ return;
for (i = 0; i < num_counters; ++i) {
if (reset_value[i]) {
CTRL_READ(low, high, msrs, i);
@@ -171,6 +173,8 @@ static void ppro_stop(struct op_msrs const * const msrs)
unsigned int low, high;
int i;
+ if (!reset_value)
+ return;
for (i = 0; i < num_counters; ++i) {
if (!reset_value[i])
continue;
diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c
index 3c27a809393..2051dc96b8e 100644
--- a/arch/x86/pci/fixup.c
+++ b/arch/x86/pci/fixup.c
@@ -496,21 +496,24 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SIEMENS, 0x0015,
pci_siemens_interrupt_controller);
/*
- * Regular PCI devices have 256 bytes, but AMD Family 10h Opteron ext config
- * have 4096 bytes. Even if the device is capable, that doesn't mean we can
- * access it. Maybe we don't have a way to generate extended config space
- * accesses. So check it
+ * Regular PCI devices have 256 bytes, but AMD Family 10h/11h CPUs have
+ * 4096 bytes configuration space for each function of their processor
+ * configuration space.
*/
-static void fam10h_pci_cfg_space_size(struct pci_dev *dev)
+static void amd_cpu_pci_cfg_space_size(struct pci_dev *dev)
{
dev->cfg_size = pci_cfg_space_size_ext(dev);
}
-
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1200, fam10h_pci_cfg_space_size);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1201, fam10h_pci_cfg_space_size);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1202, fam10h_pci_cfg_space_size);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1203, fam10h_pci_cfg_space_size);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1204, fam10h_pci_cfg_space_size);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1200, amd_cpu_pci_cfg_space_size);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1201, amd_cpu_pci_cfg_space_size);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1202, amd_cpu_pci_cfg_space_size);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1203, amd_cpu_pci_cfg_space_size);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1204, amd_cpu_pci_cfg_space_size);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1300, amd_cpu_pci_cfg_space_size);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1301, amd_cpu_pci_cfg_space_size);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1302, amd_cpu_pci_cfg_space_size);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1303, amd_cpu_pci_cfg_space_size);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1304, amd_cpu_pci_cfg_space_size);
/*
* SB600: Disable BAR1 on device 14.0 to avoid HPET resources from
diff --git a/arch/x86/power/hibernate_32.c b/arch/x86/power/hibernate_32.c
index f2b6e3f11bf..81197c62d5b 100644
--- a/arch/x86/power/hibernate_32.c
+++ b/arch/x86/power/hibernate_32.c
@@ -12,6 +12,7 @@
#include <asm/system.h>
#include <asm/page.h>
#include <asm/pgtable.h>
+#include <asm/mmzone.h>
/* Defined in hibernate_asm_32.S */
extern int restore_image(void);
@@ -127,6 +128,9 @@ static int resume_physical_mapping_init(pgd_t *pgd_base)
}
}
}
+
+ resume_map_numa_kva(pgd_base);
+
return 0;
}
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index 688936044dc..636ef4caa52 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -661,12 +661,11 @@ void xen_set_pgd(pgd_t *ptr, pgd_t val)
* For 64-bit, we must skip the Xen hole in the middle of the address
* space, just after the big x86-64 virtual hole.
*/
-static int xen_pgd_walk(struct mm_struct *mm,
- int (*func)(struct mm_struct *mm, struct page *,
- enum pt_level),
- unsigned long limit)
+static int __xen_pgd_walk(struct mm_struct *mm, pgd_t *pgd,
+ int (*func)(struct mm_struct *mm, struct page *,
+ enum pt_level),
+ unsigned long limit)
{
- pgd_t *pgd = mm->pgd;
int flush = 0;
unsigned hole_low, hole_high;
unsigned pgdidx_limit, pudidx_limit, pmdidx_limit;
@@ -753,6 +752,14 @@ out:
return flush;
}
+static int xen_pgd_walk(struct mm_struct *mm,
+ int (*func)(struct mm_struct *mm, struct page *,
+ enum pt_level),
+ unsigned long limit)
+{
+ return __xen_pgd_walk(mm, mm->pgd, func, limit);
+}
+
/* If we're using split pte locks, then take the page's lock and
return a pointer to it. Otherwise return NULL. */
static spinlock_t *xen_pte_lock(struct page *page, struct mm_struct *mm)
@@ -854,7 +861,7 @@ static void __xen_pgd_pin(struct mm_struct *mm, pgd_t *pgd)
xen_mc_batch();
- if (xen_pgd_walk(mm, xen_pin_page, USER_LIMIT)) {
+ if (__xen_pgd_walk(mm, pgd, xen_pin_page, USER_LIMIT)) {
/* re-enable interrupts for flushing */
xen_mc_issue(0);
@@ -998,7 +1005,7 @@ static void __xen_pgd_unpin(struct mm_struct *mm, pgd_t *pgd)
PT_PMD);
#endif
- xen_pgd_walk(mm, xen_unpin_page, USER_LIMIT);
+ __xen_pgd_walk(mm, pgd, xen_unpin_page, USER_LIMIT);
xen_mc_issue(0);
}
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c
index d77da613b1d..acd9b6705e0 100644
--- a/arch/x86/xen/smp.c
+++ b/arch/x86/xen/smp.c
@@ -362,7 +362,7 @@ static void xen_cpu_die(unsigned int cpu)
alternatives_smp_switch(0);
}
-static void xen_play_dead(void)
+static void __cpuinit xen_play_dead(void) /* used only with CPU_HOTPLUG */
{
play_dead_common();
HYPERVISOR_vcpu_op(VCPUOP_down, smp_processor_id(), NULL);
diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
index d7422dc2a55..9e1afae8461 100644
--- a/arch/x86/xen/xen-ops.h
+++ b/arch/x86/xen/xen-ops.h
@@ -49,7 +49,7 @@ bool xen_vcpu_stolen(int vcpu);
void xen_mark_init_mm_pinned(void);
-void __init xen_setup_vcpu_info_placement(void);
+void xen_setup_vcpu_info_placement(void);
#ifdef CONFIG_SMP
void xen_smp_init(void);
diff --git a/block/blk-barrier.c b/block/blk-barrier.c
index 5c99ff8d2db..6e72d661ae4 100644
--- a/block/blk-barrier.c
+++ b/block/blk-barrier.c
@@ -161,7 +161,7 @@ static inline struct request *start_ordered(struct request_queue *q,
/*
* Prep proxy barrier request.
*/
- blkdev_dequeue_request(rq);
+ elv_dequeue_request(q, rq);
q->orig_bar_rq = rq;
rq = &q->bar_rq;
blk_rq_init(q, rq);
@@ -219,7 +219,7 @@ int blk_do_ordered(struct request_queue *q, struct request **rqp)
* This can happen when the queue switches to
* ORDERED_NONE while this request is on it.
*/
- blkdev_dequeue_request(rq);
+ elv_dequeue_request(q, rq);
if (__blk_end_request(rq, -EOPNOTSUPP,
blk_rq_bytes(rq)))
BUG();
diff --git a/block/blk-core.c b/block/blk-core.c
index 10e8a64a5a5..c36aa98fafa 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -592,7 +592,7 @@ blk_init_queue_node(request_fn_proc *rfn, spinlock_t *lock, int node_id)
1 << QUEUE_FLAG_STACKABLE);
q->queue_lock = lock;
- blk_queue_segment_boundary(q, 0xffffffff);
+ blk_queue_segment_boundary(q, BLK_SEG_BOUNDARY_MASK);
blk_queue_make_request(q, __make_request);
blk_queue_max_segment_size(q, MAX_SEGMENT_SIZE);
@@ -1637,6 +1637,28 @@ int blk_insert_cloned_request(struct request_queue *q, struct request *rq)
EXPORT_SYMBOL_GPL(blk_insert_cloned_request);
/**
+ * blkdev_dequeue_request - dequeue request and start timeout timer
+ * @req: request to dequeue
+ *
+ * Dequeue @req and start timeout timer on it. This hands off the
+ * request to the driver.
+ *
+ * Block internal functions which don't want to start timer should
+ * call elv_dequeue_request().
+ */
+void blkdev_dequeue_request(struct request *req)
+{
+ elv_dequeue_request(req->q, req);
+
+ /*
+ * We are now handing the request to the hardware, add the
+ * timeout handler.
+ */
+ blk_add_timer(req);
+}
+EXPORT_SYMBOL(blkdev_dequeue_request);
+
+/**
* __end_that_request_first - end I/O on a request
* @req: the request being processed
* @error: %0 for success, < %0 for error
@@ -1774,7 +1796,7 @@ static void end_that_request_last(struct request *req, int error)
blk_queue_end_tag(req->q, req);
if (blk_queued_rq(req))
- blkdev_dequeue_request(req);
+ elv_dequeue_request(req->q, req);
if (unlikely(laptop_mode) && blk_fs_request(req))
laptop_io_completion();
diff --git a/block/blk-map.c b/block/blk-map.c
index 4849fa36161..2990447f45e 100644
--- a/block/blk-map.c
+++ b/block/blk-map.c
@@ -217,8 +217,14 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq,
return PTR_ERR(bio);
if (bio->bi_size != len) {
+ /*
+ * Grab an extra reference to this bio, as bio_unmap_user()
+ * expects to be able to drop it twice as it happens on the
+ * normal IO completion path
+ */
+ bio_get(bio);
bio_endio(bio, 0);
- bio_unmap_user(bio);
+ __blk_rq_unmap_user(bio);
return -EINVAL;
}
diff --git a/block/blk-settings.c b/block/blk-settings.c
index 41392fbe19f..afa55e14e27 100644
--- a/block/blk-settings.c
+++ b/block/blk-settings.c
@@ -125,6 +125,9 @@ void blk_queue_make_request(struct request_queue *q, make_request_fn *mfn)
q->nr_requests = BLKDEV_MAX_RQ;
blk_queue_max_phys_segments(q, MAX_PHYS_SEGMENTS);
blk_queue_max_hw_segments(q, MAX_HW_SEGMENTS);
+ blk_queue_segment_boundary(q, BLK_SEG_BOUNDARY_MASK);
+ blk_queue_max_segment_size(q, MAX_SEGMENT_SIZE);
+
q->make_request_fn = mfn;
q->backing_dev_info.ra_pages =
(VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE;
@@ -314,6 +317,7 @@ void blk_queue_stack_limits(struct request_queue *t, struct request_queue *b)
/* zero is "infinity" */
t->max_sectors = min_not_zero(t->max_sectors, b->max_sectors);
t->max_hw_sectors = min_not_zero(t->max_hw_sectors, b->max_hw_sectors);
+ t->seg_boundary_mask = min_not_zero(t->seg_boundary_mask, b->seg_boundary_mask);
t->max_phys_segments = min(t->max_phys_segments, b->max_phys_segments);
t->max_hw_segments = min(t->max_hw_segments, b->max_hw_segments);
diff --git a/block/bsg.c b/block/bsg.c
index e8bd2475682..e73e50daf3d 100644
--- a/block/bsg.c
+++ b/block/bsg.c
@@ -202,6 +202,8 @@ static int blk_fill_sgv4_hdr_rq(struct request_queue *q, struct request *rq,
rq->timeout = q->sg_timeout;
if (!rq->timeout)
rq->timeout = BLK_DEFAULT_SG_TIMEOUT;
+ if (rq->timeout < BLK_MIN_SG_TIMEOUT)
+ rq->timeout = BLK_MIN_SG_TIMEOUT;
return 0;
}
diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c
index 3d3e7a46f38..67eb93cff69 100644
--- a/block/compat_ioctl.c
+++ b/block/compat_ioctl.c
@@ -677,6 +677,29 @@ static int compat_blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode,
case DVD_WRITE_STRUCT:
case DVD_AUTH:
arg = (unsigned long)compat_ptr(arg);
+ /* These intepret arg as an unsigned long, not as a pointer,
+ * so we must not do compat_ptr() conversion. */
+ case HDIO_SET_MULTCOUNT:
+ case HDIO_SET_UNMASKINTR:
+ case HDIO_SET_KEEPSETTINGS:
+ case HDIO_SET_32BIT:
+ case HDIO_SET_NOWERR:
+ case HDIO_SET_DMA:
+ case HDIO_SET_PIO_MODE:
+ case HDIO_SET_NICE:
+ case HDIO_SET_WCACHE:
+ case HDIO_SET_ACOUSTIC:
+ case HDIO_SET_BUSSTATE:
+ case HDIO_SET_ADDRESS:
+ case CDROMEJECT_SW:
+ case CDROM_SET_OPTIONS:
+ case CDROM_CLEAR_OPTIONS:
+ case CDROM_SELECT_SPEED:
+ case CDROM_SELECT_DISC:
+ case CDROM_MEDIA_CHANGED:
+ case CDROM_DRIVE_STATUS:
+ case CDROM_LOCKDOOR:
+ case CDROM_DEBUG:
break;
default:
/* unknown ioctl number */
@@ -699,8 +722,14 @@ long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
struct backing_dev_info *bdi;
loff_t size;
+ /*
+ * O_NDELAY can be altered using fcntl(.., F_SETFL, ..), so we have
+ * to updated it before every ioctl.
+ */
if (file->f_flags & O_NDELAY)
- mode |= FMODE_NDELAY_NOW;
+ mode |= FMODE_NDELAY;
+ else
+ mode &= ~FMODE_NDELAY;
switch (cmd) {
case HDIO_GETGEO:
diff --git a/block/elevator.c b/block/elevator.c
index 9ac82dde99d..a6951f76ba0 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -844,14 +844,7 @@ void elv_dequeue_request(struct request_queue *q, struct request *rq)
*/
if (blk_account_rq(rq))
q->in_flight++;
-
- /*
- * We are now handing the request to the hardware, add the
- * timeout handler.
- */
- blk_add_timer(rq);
}
-EXPORT_SYMBOL(elv_dequeue_request);
int elv_queue_empty(struct request_queue *q)
{
diff --git a/block/genhd.c b/block/genhd.c
index 4e5e7493f67..2f7feda61e3 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -768,6 +768,8 @@ static int __init genhd_device_init(void)
bdev_map = kobj_map_init(base_probe, &block_class_lock);
blk_dev_init();
+ register_blkdev(BLOCK_EXT_MAJOR, "blkext");
+
#ifndef CONFIG_SYSFS_DEPRECATED
/* create top-level block dir */
block_depr = kobject_create_and_add("block", NULL);
@@ -1100,6 +1102,7 @@ struct gendisk *alloc_disk_node(int minors, int node_id)
kfree(disk);
return NULL;
}
+ disk->node_id = node_id;
if (disk_expand_part_tbl(disk, 0)) {
free_part_stats(&disk->part0);
kfree(disk);
@@ -1114,7 +1117,6 @@ struct gendisk *alloc_disk_node(int minors, int node_id)
device_initialize(disk_to_dev(disk));
INIT_WORK(&disk->async_notify,
media_change_notify_thread);
- disk->node_id = node_id;
}
return disk;
}
diff --git a/block/ioctl.c b/block/ioctl.c
index c832d639b6e..d03985b04d6 100644
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@ -18,7 +18,6 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user
struct disk_part_iter piter;
long long start, length;
int partno;
- int err;
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
@@ -61,10 +60,10 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user
disk_part_iter_exit(&piter);
/* all seems OK */
- err = add_partition(disk, partno, start, length,
- ADDPART_FLAG_NONE);
+ part = add_partition(disk, partno, start, length,
+ ADDPART_FLAG_NONE);
mutex_unlock(&bdev->bd_mutex);
- return err;
+ return IS_ERR(part) ? PTR_ERR(part) : 0;
case BLKPG_DEL_PARTITION:
part = disk_get_part(disk, partno);
if (!part)
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
index 5963cf91a3a..d0bb92cbefb 100644
--- a/block/scsi_ioctl.c
+++ b/block/scsi_ioctl.c
@@ -208,6 +208,8 @@ static int blk_fill_sghdr_rq(struct request_queue *q, struct request *rq,
rq->timeout = q->sg_timeout;
if (!rq->timeout)
rq->timeout = BLK_DEFAULT_SG_TIMEOUT;
+ if (rq->timeout < BLK_MIN_SG_TIMEOUT)
+ rq->timeout = BLK_MIN_SG_TIMEOUT;
return 0;
}
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 39dbd8e4dde..dc20a34ba5e 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -31,35 +31,63 @@ config CRYPTO_FIPS
config CRYPTO_ALGAPI
tristate
+ select CRYPTO_ALGAPI2
help
This option provides the API for cryptographic algorithms.
+config CRYPTO_ALGAPI2
+ tristate
+
config CRYPTO_AEAD
tristate
+ select CRYPTO_AEAD2
select CRYPTO_ALGAPI
+config CRYPTO_AEAD2
+ tristate
+ select CRYPTO_ALGAPI2
+
config CRYPTO_BLKCIPHER
tristate
+ select CRYPTO_BLKCIPHER2
select CRYPTO_ALGAPI
- select CRYPTO_RNG
+
+config CRYPTO_BLKCIPHER2
+ tristate
+ select CRYPTO_ALGAPI2
+ select CRYPTO_RNG2
config CRYPTO_HASH
tristate
+ select CRYPTO_HASH2
select CRYPTO_ALGAPI
+config CRYPTO_HASH2
+ tristate
+ select CRYPTO_ALGAPI2
+
config CRYPTO_RNG
tristate
+ select CRYPTO_RNG2
select CRYPTO_ALGAPI
+config CRYPTO_RNG2
+ tristate
+ select CRYPTO_ALGAPI2
+
config CRYPTO_MANAGER
tristate "Cryptographic algorithm manager"
- select CRYPTO_AEAD
- select CRYPTO_HASH
- select CRYPTO_BLKCIPHER
+ select CRYPTO_MANAGER2
help
Create default cryptographic template instantiations such as
cbc(aes).
+config CRYPTO_MANAGER2
+ def_tristate CRYPTO_MANAGER || (CRYPTO_MANAGER!=n && CRYPTO_ALGAPI=y)
+ select CRYPTO_AEAD2
+ select CRYPTO_HASH2
+ select CRYPTO_BLKCIPHER2
+
config CRYPTO_GF128MUL
tristate "GF(2^128) multiplication functions (EXPERIMENTAL)"
depends on EXPERIMENTAL
diff --git a/crypto/Makefile b/crypto/Makefile
index 5862b807334..cd4a4ed078f 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -9,24 +9,24 @@ obj-$(CONFIG_CRYPTO_FIPS) += fips.o
crypto_algapi-$(CONFIG_PROC_FS) += proc.o
crypto_algapi-objs := algapi.o scatterwalk.o $(crypto_algapi-y)
-obj-$(CONFIG_CRYPTO_ALGAPI) += crypto_algapi.o
+obj-$(CONFIG_CRYPTO_ALGAPI2) += crypto_algapi.o
-obj-$(CONFIG_CRYPTO_AEAD) += aead.o
+obj-$(CONFIG_CRYPTO_AEAD2) += aead.o
crypto_blkcipher-objs := ablkcipher.o
crypto_blkcipher-objs += blkcipher.o
-obj-$(CONFIG_CRYPTO_BLKCIPHER) += crypto_blkcipher.o
-obj-$(CONFIG_CRYPTO_BLKCIPHER) += chainiv.o
-obj-$(CONFIG_CRYPTO_BLKCIPHER) += eseqiv.o
+obj-$(CONFIG_CRYPTO_BLKCIPHER2) += crypto_blkcipher.o
+obj-$(CONFIG_CRYPTO_BLKCIPHER2) += chainiv.o
+obj-$(CONFIG_CRYPTO_BLKCIPHER2) += eseqiv.o
obj-$(CONFIG_CRYPTO_SEQIV) += seqiv.o
crypto_hash-objs := hash.o
crypto_hash-objs += ahash.o
-obj-$(CONFIG_CRYPTO_HASH) += crypto_hash.o
+obj-$(CONFIG_CRYPTO_HASH2) += crypto_hash.o
cryptomgr-objs := algboss.o testmgr.o
-obj-$(CONFIG_CRYPTO_MANAGER) += cryptomgr.o
+obj-$(CONFIG_CRYPTO_MANAGER2) += cryptomgr.o
obj-$(CONFIG_CRYPTO_HMAC) += hmac.o
obj-$(CONFIG_CRYPTO_XCBC) += xcbc.o
obj-$(CONFIG_CRYPTO_NULL) += crypto_null.o
@@ -73,8 +73,8 @@ obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o
obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o
obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o
obj-$(CONFIG_CRYPTO_LZO) += lzo.o
-obj-$(CONFIG_CRYPTO_RNG) += rng.o
-obj-$(CONFIG_CRYPTO_RNG) += krng.o
+obj-$(CONFIG_CRYPTO_RNG2) += rng.o
+obj-$(CONFIG_CRYPTO_RNG2) += krng.o
obj-$(CONFIG_CRYPTO_ANSI_CPRNG) += ansi_cprng.o
obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
diff --git a/crypto/async_tx/async_xor.c b/crypto/async_tx/async_xor.c
index c029d3eb9ef..595b78672b3 100644
--- a/crypto/async_tx/async_xor.c
+++ b/crypto/async_tx/async_xor.c
@@ -53,10 +53,17 @@ do_async_xor(struct dma_chan *chan, struct page *dest, struct page **src_list,
int xor_src_cnt;
dma_addr_t dma_dest;
- dma_dest = dma_map_page(dma->dev, dest, offset, len, DMA_FROM_DEVICE);
- for (i = 0; i < src_cnt; i++)
+ /* map the dest bidrectional in case it is re-used as a source */
+ dma_dest = dma_map_page(dma->dev, dest, offset, len, DMA_BIDIRECTIONAL);
+ for (i = 0; i < src_cnt; i++) {
+ /* only map the dest once */
+ if (unlikely(src_list[i] == dest)) {
+ dma_src[i] = dma_dest;
+ continue;
+ }
dma_src[i] = dma_map_page(dma->dev, src_list[i], offset,
len, DMA_TO_DEVICE);
+ }
while (src_cnt) {
async_flags = flags;
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index f4f63291750..b0243fd55ac 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -312,9 +312,13 @@ config ACPI_DEBUG
bool "Debug Statements"
default n
help
- The ACPI driver can optionally report errors with a great deal
- of verbosity. Saying Y enables these statements. This will increase
- your kernel size by around 50K.
+ The ACPI subsystem can produce debug output. Saying Y enables this
+ output and increases the kernel size by around 50K.
+
+ Use the acpi.debug_layer and acpi.debug_level kernel command-line
+ parameters documented in Documentation/acpi/debug.txt and
+ Documentation/kernel-parameters.txt to control the type and
+ amount of debug output.
config ACPI_DEBUG_FUNC_TRACE
bool "Additionally enable ACPI function tracing"
@@ -324,14 +328,6 @@ config ACPI_DEBUG_FUNC_TRACE
ACPI Debug Statements slow down ACPI processing. Function trace
is about half of the penalty and is rarely useful.
-config ACPI_EC
- bool
- default y
- help
- This driver is required on some systems for the proper operation of
- the battery and thermal drivers. If you are compiling for a
- mobile system, say Y.
-
config ACPI_PCI_SLOT
tristate "PCI slot detection driver"
default n
@@ -341,10 +337,6 @@ config ACPI_PCI_SLOT
help you correlate PCI bus addresses with the physical geography
of your slots. If you are unsure, say N.
-config ACPI_POWER
- bool
- default y
-
config ACPI_SYSTEM
bool
default y
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index d91c027ece8..3c0c93300f1 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -39,19 +39,23 @@ obj-y += sleep/
obj-y += bus.o glue.o
obj-y += scan.o
# Keep EC driver first. Initialization of others depend on it.
-obj-$(CONFIG_ACPI_EC) += ec.o
+obj-y += ec.o
obj-$(CONFIG_ACPI_AC) += ac.o
obj-$(CONFIG_ACPI_BATTERY) += battery.o
obj-$(CONFIG_ACPI_BUTTON) += button.o
obj-$(CONFIG_ACPI_FAN) += fan.o
obj-$(CONFIG_ACPI_DOCK) += dock.o
obj-$(CONFIG_ACPI_VIDEO) += video.o
+ifdef CONFIG_ACPI_VIDEO
+obj-y += video_detect.o
+endif
+
obj-y += pci_root.o pci_link.o pci_irq.o pci_bind.o
obj-$(CONFIG_ACPI_PCI_SLOT) += pci_slot.o
obj-$(CONFIG_ACPI_PROCESSOR) += processor.o
obj-$(CONFIG_ACPI_CONTAINER) += container.o
obj-$(CONFIG_ACPI_THERMAL) += thermal.o
-obj-$(CONFIG_ACPI_POWER) += power.o
+obj-y += power.o
obj-$(CONFIG_ACPI_SYSTEM) += system.o event.o
obj-$(CONFIG_ACPI_DEBUG) += debug.o
obj-$(CONFIG_ACPI_NUMA) += numa.o
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c
index d72a1b6c8a9..9b917dac773 100644
--- a/drivers/acpi/ac.c
+++ b/drivers/acpi/ac.c
@@ -37,7 +37,6 @@
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
-#define ACPI_AC_COMPONENT 0x00020000
#define ACPI_AC_CLASS "ac_adapter"
#define ACPI_AC_DEVICE_NAME "AC Adapter"
#define ACPI_AC_FILE_STATE "state"
@@ -242,7 +241,7 @@ static void acpi_ac_notify(acpi_handle handle, u32 event, void *data)
acpi_ac_get_state(ac);
acpi_bus_generate_proc_event(device, event, (u32) ac->state);
acpi_bus_generate_netlink_event(device->pnp.device_class,
- device->dev.bus_id, event,
+ dev_name(&device->dev), event,
(u32) ac->state);
#ifdef CONFIG_ACPI_SYSFS_POWER
kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE);
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c
index 71d21c51c45..63a17b55b39 100644
--- a/drivers/acpi/acpi_memhotplug.c
+++ b/drivers/acpi/acpi_memhotplug.c
@@ -32,7 +32,6 @@
#include <linux/memory_hotplug.h>
#include <acpi/acpi_drivers.h>
-#define ACPI_MEMORY_DEVICE_COMPONENT 0x08000000UL
#define ACPI_MEMORY_DEVICE_CLASS "memory"
#define ACPI_MEMORY_DEVICE_HID "PNP0C80"
#define ACPI_MEMORY_DEVICE_NAME "Hotplug Mem Device"
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index b2133e89ad9..1423b0c0cd2 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -46,7 +46,6 @@
#define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF
-#define ACPI_BATTERY_COMPONENT 0x00040000
#define ACPI_BATTERY_CLASS "battery"
#define ACPI_BATTERY_DEVICE_NAME "Battery"
#define ACPI_BATTERY_NOTIFY_STATUS 0x80
@@ -782,7 +781,7 @@ static void acpi_battery_notify(acpi_handle handle, u32 event, void *data)
acpi_bus_generate_proc_event(device, event,
acpi_battery_present(battery));
acpi_bus_generate_netlink_event(device->pnp.device_class,
- device->dev.bus_id, event,
+ dev_name(&device->dev), event,
acpi_battery_present(battery));
#ifdef CONFIG_ACPI_SYSFS_POWER
/* acpi_batter_update could remove power_supply object */
diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c
index ea92bac42c5..09c69806c1f 100644
--- a/drivers/acpi/blacklist.c
+++ b/drivers/acpi/blacklist.c
@@ -176,16 +176,6 @@ static int __init dmi_enable_osi_linux(const struct dmi_system_id *d)
acpi_dmi_osi_linux(1, d); /* enable */
return 0;
}
-static int __init dmi_disable_osi_linux(const struct dmi_system_id *d)
-{
- acpi_dmi_osi_linux(0, d); /* disable */
- return 0;
-}
-static int __init dmi_unknown_osi_linux(const struct dmi_system_id *d)
-{
- acpi_dmi_osi_linux(-1, d); /* unknown */
- return 0;
-}
static int __init dmi_disable_osi_vista(const struct dmi_system_id *d)
{
printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident);
@@ -193,295 +183,21 @@ static int __init dmi_disable_osi_vista(const struct dmi_system_id *d)
return 0;
}
-/*
- * Most BIOS that invoke OSI(Linux) do nothing with it.
- * But some cause Linux to break.
- * Only a couple use it to make Linux run better.
- *
- * Thus, Linux should continue to disable OSI(Linux) by default,
- * should continue to discourage BIOS writers from using it, and
- * should whitelist the few existing systems that require it.
- *
- * If it appears clear a vendor isn't using OSI(Linux)
- * for anything constructive, blacklist them by name to disable
- * unnecessary dmesg warnings on all of their products.
- */
-
static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
- /*
- * Disable OSI(Linux) warnings on all "Acer, inc."
- *
- * _OSI(Linux) disables the latest Windows BIOS code:
- * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3100"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5050"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5100"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5580"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 3010"),
- * _OSI(Linux) effect unknown:
- * DMI_MATCH(DMI_PRODUCT_NAME, "Ferrari 5000"),
- */
- /*
- * note that dmi_check_system() uses strstr()
- * to match sub-strings rather than !strcmp(),
- * so "Acer" below matches "Acer, inc." above.
- */
- /*
- * Disable OSI(Linux) warnings on all "Acer"
- *
- * _OSI(Linux) effect unknown:
- * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5610"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 7720Z"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 5520"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 6460"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 7510"),
- *
- * _OSI(Linux) is a NOP:
- * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5315"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "Extensa 5220"),
- */
- {
- .callback = dmi_disable_osi_linux,
- .ident = "Acer",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
- },
- },
- /*
- * Disable OSI(Linux) warnings on all "Apple Computer, Inc."
- * Disable OSI(Linux) warnings on all "Apple Inc."
- *
- * _OSI(Linux) confirmed to be a NOP:
- * DMI_MATCH(DMI_PRODUCT_NAME, "MacBook1,1"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "MacBook2,1"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro2,2"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3,1"),
- * _OSI(Linux) effect unknown:
- * DMI_MATCH(DMI_PRODUCT_NAME, "MacPro2,1"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro1,1"),
- */
- {
- .callback = dmi_disable_osi_linux,
- .ident = "Apple",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Apple"),
- },
- },
- /*
- * Disable OSI(Linux) warnings on all "BenQ"
- *
- * _OSI(Linux) confirmed to be a NOP:
- * DMI_MATCH(DMI_PRODUCT_NAME, "Joybook S31"),
- */
- {
- .callback = dmi_disable_osi_linux,
- .ident = "BenQ",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "BenQ"),
- },
- },
- /*
- * Disable OSI(Linux) warnings on all "Clevo Co."
- *
- * _OSI(Linux) confirmed to be a NOP:
- * DMI_MATCH(DMI_PRODUCT_NAME, "M570RU"),
- */
- {
- .callback = dmi_disable_osi_linux,
- .ident = "Clevo",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Clevo Co."),
- },
- },
- /*
- * Disable OSI(Linux) warnings on all "COMPAL"
- *
- * _OSI(Linux) confirmed to be a NOP:
- * DMI_MATCH(DMI_BOARD_NAME, "HEL8X"),
- * _OSI(Linux) unknown effect:
- * DMI_MATCH(DMI_BOARD_NAME, "IFL91"),
- */
- {
- .callback = dmi_disable_osi_linux,
- .ident = "Compal",
- .matches = {
- DMI_MATCH(DMI_BIOS_VENDOR, "COMPAL"),
- },
- },
- { /* OSI(Linux) touches USB, unknown side-effect */
- .callback = dmi_disable_osi_linux,
- .ident = "Dell Dimension 5150",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "Dell DM051"),
- },
- },
- { /* OSI(Linux) is a NOP */
- .callback = dmi_disable_osi_linux,
- .ident = "Dell i1501",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1501"),
- },
- },
- { /* OSI(Linux) effect unknown */
- .callback = dmi_unknown_osi_linux,
- .ident = "Dell Latitude D830",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "Latitude D830"),
- },
- },
- { /* OSI(Linux) effect unknown */
- .callback = dmi_unknown_osi_linux,
- .ident = "Dell OptiPlex GX620",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex GX620"),
- },
- },
- { /* OSI(Linux) causes some USB initialization to not run */
- .callback = dmi_unknown_osi_linux,
- .ident = "Dell OptiPlex 755",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 755"),
- },
- },
- { /* OSI(Linux) effect unknown */
- .callback = dmi_unknown_osi_linux,
- .ident = "Dell PE 1900",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1900"),
- },
- },
- { /* OSI(Linux) is a NOP */
- .callback = dmi_unknown_osi_linux,
- .ident = "Dell PE 1950",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1950"),
- },
- },
- { /* OSI(Linux) is a NOP */
- .callback = dmi_disable_osi_linux,
- .ident = "Dell PE R200",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge R200"),
- },
- },
- { /* OSI(Linux) touches USB */
- .callback = dmi_disable_osi_linux,
- .ident = "Dell PR 390",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "Precision WorkStation 390"),
- },
- },
- { /* OSI(Linux) touches USB */
- .callback = dmi_unknown_osi_linux,
- .ident = "Dell PR 390",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "Precision WorkStation 690"),
- },
- },
- { /* OSI(Linux) unknown - ASL looks benign, but may effect dock/SMM */
- .callback = dmi_unknown_osi_linux,
- .ident = "Dell PR M4300",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "Precision M4300"),
- },
- },
- { /* OSI(Linux) is a NOP */
- .callback = dmi_disable_osi_linux,
- .ident = "Dell Vostro 1000",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1000"),
- },
- },
- { /* OSI(Linux) effect unknown */
- .callback = dmi_unknown_osi_linux,
- .ident = "Dell PE SC440",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge SC440"),
- },
- },
- { /* OSI(Linux) effect unknown */
- .callback = dmi_unknown_osi_linux,
- .ident = "Dialogue Flybook V5",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dialogue Technology Corporation"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Flybook V5"),
- },
- },
- /*
- * Disable OSI(Linux) warnings on all "FUJITSU SIEMENS"
- *
- * _OSI(Linux) disables latest Windows BIOS code:
- * DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pa 2510"),
- * _OSI(Linux) confirmed to be a NOP:
- * DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pi 1536"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pi 1556"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 1546"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Mobile V5505"),
- * _OSI(Linux) unknown effect:
- * DMI_MATCH(DMI_PRODUCT_NAME, "Amilo M1425"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "Amilo Si 1520"),
- */
- {
- .callback = dmi_disable_osi_linux,
- .ident = "Fujitsu Siemens",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
- },
- },
{
.callback = dmi_disable_osi_vista,
.ident = "Fujitsu Siemens",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
- DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Mobile V5505"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Mobile V5505"),
},
},
+
/*
- * Disable OSI(Linux) warnings on all "Hewlett-Packard"
- *
- * _OSI(Linux) confirmed to be a NOP:
- * .ident = "HP Pavilion tx 1000"
- * DMI_MATCH(DMI_BOARD_NAME, "30BF"),
- * .ident = "HP Pavilion dv2000"
- * DMI_MATCH(DMI_BOARD_NAME, "30B5"),
- * .ident = "HP Pavilion dv5000",
- * DMI_MATCH(DMI_BOARD_NAME, "30A7"),
- * .ident = "HP Pavilion dv6300 30BC",
- * DMI_MATCH(DMI_BOARD_NAME, "30BC"),
- * .ident = "HP Pavilion dv6000",
- * DMI_MATCH(DMI_BOARD_NAME, "30B7"),
- * DMI_MATCH(DMI_BOARD_NAME, "30B8"),
- * .ident = "HP Pavilion dv9000",
- * DMI_MATCH(DMI_BOARD_NAME, "30B9"),
- * .ident = "HP Pavilion dv9500",
- * DMI_MATCH(DMI_BOARD_NAME, "30CB"),
- * .ident = "HP/Compaq Presario C500",
- * DMI_MATCH(DMI_BOARD_NAME, "30C6"),
- * .ident = "HP/Compaq Presario F500",
- * DMI_MATCH(DMI_BOARD_NAME, "30D3"),
- * _OSI(Linux) unknown effect:
- * .ident = "HP Pavilion dv6500",
- * DMI_MATCH(DMI_BOARD_NAME, "30D0"),
+ * BIOS invocation of _OSI(Linux) is almost always a BIOS bug.
+ * Linux ignores it, except for the machines enumerated below.
*/
- {
- .callback = dmi_disable_osi_linux,
- .ident = "Hewlett-Packard",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
- },
- },
+
/*
* Lenovo has a mix of systems OSI(Linux) situations
* and thus we can not wildcard the vendor.
@@ -519,113 +235,6 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X61"),
},
},
- {
- .callback = dmi_disable_osi_linux,
- .ident = "Lenovo 3000 V100",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "LENOVO3000 V100"),
- },
- },
- {
- .callback = dmi_disable_osi_linux,
- .ident = "Lenovo 3000 N100",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "3000 N100"),
- },
- },
- /*
- * Disable OSI(Linux) warnings on all "LG Electronics"
- *
- * _OSI(Linux) confirmed to be a NOP:
- * DMI_MATCH(DMI_PRODUCT_NAME, "P1-J150B"),
- * with DMI_MATCH(DMI_BOARD_NAME, "ROCKY"),
- *
- * unknown:
- * DMI_MATCH(DMI_PRODUCT_NAME, "S1-MDGDG"),
- * with DMI_MATCH(DMI_BOARD_NAME, "ROCKY"),
- */
- {
- .callback = dmi_disable_osi_linux,
- .ident = "LG",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"),
- },
- },
- /* NEC - OSI(Linux) effect unknown */
- {
- .callback = dmi_unknown_osi_linux,
- .ident = "NEC VERSA M360",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "NEC Computers SAS"),
- DMI_MATCH(DMI_PRODUCT_NAME, "NEC VERSA M360"),
- },
- },
- /* Panasonic */
- {
- .callback = dmi_unknown_osi_linux,
- .ident = "Panasonic",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Matsushita"),
- /* Toughbook CF-52 */
- DMI_MATCH(DMI_PRODUCT_NAME, "CF-52CCABVBG"),
- },
- },
- /*
- * Disable OSI(Linux) warnings on all "Samsung Electronics"
- *
- * OSI(Linux) disables PNP0C32 and other BIOS code for Windows:
- * DMI_MATCH(DMI_PRODUCT_NAME, "R40P/R41P"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "R59P/R60P/R61P"),
- */
- {
- .callback = dmi_disable_osi_linux,
- .ident = "Samsung",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
- },
- },
- /*
- * Disable OSI(Linux) warnings on all "Sony Corporation"
- *
- * _OSI(Linux) is a NOP:
- * DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NR11S_S"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SZ38GP_C"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SZ650N"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "VGN-TZ21MN_N"),
- * _OSI(Linux) unknown effect:
- * DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FZ11M"),
- */
- {
- .callback = dmi_disable_osi_linux,
- .ident = "Sony",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
- },
- },
- /*
- * Disable OSI(Linux) warnings on all "TOSHIBA"
- *
- * _OSI(Linux) breaks sound (bugzilla 7787):
- * DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P100"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P105"),
- * _OSI(Linux) is a NOP:
- * DMI_MATCH(DMI_PRODUCT_NAME, "Satellite A100"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "Satellite A210"),
- * _OSI(Linux) unknown effect:
- * DMI_MATCH(DMI_PRODUCT_NAME, "Satellite A135"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "Satellite A200"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P205"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "Satellite U305"),
- */
- {
- .callback = dmi_disable_osi_linux,
- .ident = "Toshiba",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
- },
- },
{}
};
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index c797c6473f3..765fd1c56cd 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -774,7 +774,7 @@ static int __init acpi_bus_init(void)
"Unable to initialize ACPI OS objects\n");
goto error1;
}
-#ifdef CONFIG_ACPI_EC
+
/*
* ACPI 2.0 requires the EC driver to be loaded and work before
* the EC device is found in the namespace (i.e. before acpi_initialize_objects()
@@ -785,7 +785,6 @@ static int __init acpi_bus_init(void)
*/
status = acpi_ec_ecdt_probe();
/* Ignore result. Not having an ECDT is not fatal. */
-#endif
status = acpi_initialize_objects(ACPI_FULL_INITIALIZATION);
if (ACPI_FAILURE(status)) {
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index cb046c3fc3f..171fd914f43 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -33,7 +33,6 @@
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
-#define ACPI_BUTTON_COMPONENT 0x00080000
#define ACPI_BUTTON_CLASS "button"
#define ACPI_BUTTON_FILE_INFO "info"
#define ACPI_BUTTON_FILE_STATE "state"
@@ -479,7 +478,7 @@ static int acpi_button_add(struct acpi_device *device)
device->wakeup.gpe_number,
ACPI_GPE_TYPE_WAKE_RUN);
acpi_enable_gpe(device->wakeup.gpe_device,
- device->wakeup.gpe_number, ACPI_NOT_ISR);
+ device->wakeup.gpe_number);
device->wakeup.state.enabled = 1;
}
diff --git a/drivers/acpi/cm_sbs.c b/drivers/acpi/cm_sbs.c
index 4441e84b28a..307963bd104 100644
--- a/drivers/acpi/cm_sbs.c
+++ b/drivers/acpi/cm_sbs.c
@@ -34,7 +34,6 @@
ACPI_MODULE_NAME("cm_sbs");
#define ACPI_AC_CLASS "ac_adapter"
#define ACPI_BATTERY_CLASS "battery"
-#define ACPI_SBS_COMPONENT 0x00080000
#define _COMPONENT ACPI_SBS_COMPONENT
static struct proc_dir_entry *acpi_ac_dir;
static struct proc_dir_entry *acpi_battery_dir;
@@ -105,9 +104,3 @@ void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir_param)
return;
}
EXPORT_SYMBOL(acpi_unlock_battery_dir);
-
-static int __init acpi_cm_sbs_init(void)
-{
- return 0;
-}
-subsys_initcall(acpi_cm_sbs_init);
diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c
index 134818b265a..17020c12623 100644
--- a/drivers/acpi/container.c
+++ b/drivers/acpi/container.c
@@ -41,7 +41,6 @@
#define INSTALL_NOTIFY_HANDLER 1
#define UNINSTALL_NOTIFY_HANDLER 2
-#define ACPI_CONTAINER_COMPONENT 0x01000000
#define _COMPONENT ACPI_CONTAINER_COMPONENT
ACPI_MODULE_NAME("container");
diff --git a/drivers/acpi/debug.c b/drivers/acpi/debug.c
index abf36b4b1d1..c4839689200 100644
--- a/drivers/acpi/debug.c
+++ b/drivers/acpi/debug.c
@@ -44,6 +44,21 @@ static const struct acpi_dlayer acpi_debug_layers[] = {
ACPI_DEBUG_INIT(ACPI_CA_DISASSEMBLER),
ACPI_DEBUG_INIT(ACPI_COMPILER),
ACPI_DEBUG_INIT(ACPI_TOOLS),
+
+ ACPI_DEBUG_INIT(ACPI_BUS_COMPONENT),
+ ACPI_DEBUG_INIT(ACPI_AC_COMPONENT),
+ ACPI_DEBUG_INIT(ACPI_BATTERY_COMPONENT),
+ ACPI_DEBUG_INIT(ACPI_BUTTON_COMPONENT),
+ ACPI_DEBUG_INIT(ACPI_SBS_COMPONENT),
+ ACPI_DEBUG_INIT(ACPI_FAN_COMPONENT),
+ ACPI_DEBUG_INIT(ACPI_PCI_COMPONENT),
+ ACPI_DEBUG_INIT(ACPI_POWER_COMPONENT),
+ ACPI_DEBUG_INIT(ACPI_CONTAINER_COMPONENT),
+ ACPI_DEBUG_INIT(ACPI_SYSTEM_COMPONENT),
+ ACPI_DEBUG_INIT(ACPI_THERMAL_COMPONENT),
+ ACPI_DEBUG_INIT(ACPI_MEMORY_DEVICE_COMPONENT),
+ ACPI_DEBUG_INIT(ACPI_VIDEO_COMPONENT),
+ ACPI_DEBUG_INIT(ACPI_PROCESSOR_COMPONENT),
};
static const struct acpi_dlevel acpi_debug_levels[] = {
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index ef42316f89f..30f3ef236ec 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -70,7 +70,7 @@ enum ec_command {
#define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */
#define ACPI_EC_UDELAY 100 /* Wait 100us before polling EC again */
-#define ACPI_EC_STORM_THRESHOLD 20 /* number of false interrupts
+#define ACPI_EC_STORM_THRESHOLD 8 /* number of false interrupts
per one transaction */
enum {
@@ -100,8 +100,11 @@ struct transaction {
u8 *rdata;
unsigned short irq_count;
u8 command;
+ u8 wi;
+ u8 ri;
u8 wlen;
u8 rlen;
+ bool done;
};
static struct acpi_ec {
@@ -178,34 +181,46 @@ static int ec_transaction_done(struct acpi_ec *ec)
unsigned long flags;
int ret = 0;
spin_lock_irqsave(&ec->curr_lock, flags);
- if (!ec->curr || (!ec->curr->wlen && !ec->curr->rlen))
+ if (!ec->curr || ec->curr->done)
ret = 1;
spin_unlock_irqrestore(&ec->curr_lock, flags);
return ret;
}
+static void start_transaction(struct acpi_ec *ec)
+{
+ ec->curr->irq_count = ec->curr->wi = ec->curr->ri = 0;
+ ec->curr->done = false;
+ acpi_ec_write_cmd(ec, ec->curr->command);
+}
+
static void gpe_transaction(struct acpi_ec *ec, u8 status)
{
unsigned long flags;
spin_lock_irqsave(&ec->curr_lock, flags);
if (!ec->curr)
goto unlock;
- if (ec->curr->wlen > 0) {
- if ((status & ACPI_EC_FLAG_IBF) == 0) {
- acpi_ec_write_data(ec, *(ec->curr->wdata++));
- --ec->curr->wlen;
- } else
- /* false interrupt, state didn't change */
- ++ec->curr->irq_count;
-
- } else if (ec->curr->rlen > 0) {
+ if (ec->curr->wlen > ec->curr->wi) {
+ if ((status & ACPI_EC_FLAG_IBF) == 0)
+ acpi_ec_write_data(ec,
+ ec->curr->wdata[ec->curr->wi++]);
+ else
+ goto err;
+ } else if (ec->curr->rlen > ec->curr->ri) {
if ((status & ACPI_EC_FLAG_OBF) == 1) {
- *(ec->curr->rdata++) = acpi_ec_read_data(ec);
- --ec->curr->rlen;
+ ec->curr->rdata[ec->curr->ri++] = acpi_ec_read_data(ec);
+ if (ec->curr->rlen == ec->curr->ri)
+ ec->curr->done = true;
} else
- /* false interrupt, state didn't change */
- ++ec->curr->irq_count;
- }
+ goto err;
+ } else if (ec->curr->wlen == ec->curr->wi &&
+ (status & ACPI_EC_FLAG_IBF) == 0)
+ ec->curr->done = true;
+ goto unlock;
+err:
+ /* false interrupt, state didn't change */
+ if (in_interrupt())
+ ++ec->curr->irq_count;
unlock:
spin_unlock_irqrestore(&ec->curr_lock, flags);
}
@@ -215,6 +230,15 @@ static int acpi_ec_wait(struct acpi_ec *ec)
if (wait_event_timeout(ec->wait, ec_transaction_done(ec),
msecs_to_jiffies(ACPI_EC_DELAY)))
return 0;
+ /* try restart command if we get any false interrupts */
+ if (ec->curr->irq_count &&
+ (acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF) == 0) {
+ pr_debug(PREFIX "controller reset, restart transaction\n");
+ start_transaction(ec);
+ if (wait_event_timeout(ec->wait, ec_transaction_done(ec),
+ msecs_to_jiffies(ACPI_EC_DELAY)))
+ return 0;
+ }
/* missing GPEs, switch back to poll mode */
if (printk_ratelimit())
pr_info(PREFIX "missing confirmations, "
@@ -239,10 +263,10 @@ static int ec_check_sci(struct acpi_ec *ec, u8 state)
static int ec_poll(struct acpi_ec *ec)
{
unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY);
- msleep(1);
+ udelay(ACPI_EC_UDELAY);
while (time_before(jiffies, delay)) {
gpe_transaction(ec, acpi_ec_read_status(ec));
- msleep(1);
+ udelay(ACPI_EC_UDELAY);
if (ec_transaction_done(ec))
return 0;
}
@@ -259,14 +283,13 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec,
/* disable GPE during transaction if storm is detected */
if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
clear_bit(EC_FLAGS_GPE_MODE, &ec->flags);
- acpi_disable_gpe(NULL, ec->gpe, ACPI_NOT_ISR);
+ acpi_disable_gpe(NULL, ec->gpe);
}
/* start transaction */
spin_lock_irqsave(&ec->curr_lock, tmp);
/* following two actions should be kept atomic */
- t->irq_count = 0;
ec->curr = t;
- acpi_ec_write_cmd(ec, ec->curr->command);
+ start_transaction(ec);
if (ec->curr->command == ACPI_EC_COMMAND_QUERY)
clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
spin_unlock_irqrestore(&ec->curr_lock, tmp);
@@ -283,10 +306,11 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec,
/* check if we received SCI during transaction */
ec_check_sci(ec, acpi_ec_read_status(ec));
/* it is safe to enable GPE outside of transaction */
- acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR);
+ acpi_enable_gpe(NULL, ec->gpe);
} else if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags) &&
t->irq_count > ACPI_EC_STORM_THRESHOLD) {
- pr_debug(PREFIX "GPE storm detected\n");
+ pr_info(PREFIX "GPE storm detected, "
+ "transactions will use polling mode\n");
set_bit(EC_FLAGS_GPE_STORM, &ec->flags);
}
return ret;
@@ -558,17 +582,26 @@ static u32 acpi_ec_gpe_handler(void *data)
pr_debug(PREFIX "~~~> interrupt\n");
status = acpi_ec_read_status(ec);
- gpe_transaction(ec, status);
- if (ec_transaction_done(ec) && (status & ACPI_EC_FLAG_IBF) == 0)
- wake_up(&ec->wait);
+ if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) {
+ gpe_transaction(ec, status);
+ if (ec_transaction_done(ec) &&
+ (status & ACPI_EC_FLAG_IBF) == 0)
+ wake_up(&ec->wait);
+ }
ec_check_sci(ec, status);
if (!test_bit(EC_FLAGS_GPE_MODE, &ec->flags) &&
!test_bit(EC_FLAGS_NO_GPE, &ec->flags)) {
/* this is non-query, must be confirmation */
- if (printk_ratelimit())
- pr_info(PREFIX "non-query interrupt received,"
+ if (!test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
+ if (printk_ratelimit())
+ pr_info(PREFIX "non-query interrupt received,"
+ " switching to interrupt mode\n");
+ } else {
+ /* hush, STORM switches the mode every transaction */
+ pr_debug(PREFIX "non-query interrupt received,"
" switching to interrupt mode\n");
+ }
set_bit(EC_FLAGS_GPE_MODE, &ec->flags);
}
return ACPI_INTERRUPT_HANDLED;
@@ -736,7 +769,7 @@ static acpi_status
ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval)
{
acpi_status status;
- unsigned long long tmp;
+ unsigned long long tmp = 0;
struct acpi_ec *ec = context;
status = acpi_walk_resources(handle, METHOD_NAME__CRS,
@@ -751,6 +784,7 @@ ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval)
return status;
ec->gpe = tmp;
/* Use the global lock for all EC transactions? */
+ tmp = 0;
acpi_evaluate_integer(handle, "_GLK", NULL, &tmp);
ec->global_lock = tmp;
ec->handle = handle;
@@ -868,7 +902,7 @@ static int ec_install_handlers(struct acpi_ec *ec)
if (ACPI_FAILURE(status))
return -ENODEV;
acpi_set_gpe_type(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME);
- acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR);
+ acpi_enable_gpe(NULL, ec->gpe);
status = acpi_install_address_space_handler(ec->handle,
ACPI_ADR_SPACE_EC,
&acpi_ec_space_handler,
@@ -1007,7 +1041,7 @@ static int acpi_ec_suspend(struct acpi_device *device, pm_message_t state)
/* Stop using GPE */
set_bit(EC_FLAGS_NO_GPE, &ec->flags);
clear_bit(EC_FLAGS_GPE_MODE, &ec->flags);
- acpi_disable_gpe(NULL, ec->gpe, ACPI_NOT_ISR);
+ acpi_disable_gpe(NULL, ec->gpe);
return 0;
}
@@ -1016,7 +1050,7 @@ static int acpi_ec_resume(struct acpi_device *device)
struct acpi_ec *ec = acpi_driver_data(device);
/* Enable use of GPE back */
clear_bit(EC_FLAGS_NO_GPE, &ec->flags);
- acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR);
+ acpi_enable_gpe(NULL, ec->gpe);
return 0;
}
diff --git a/drivers/acpi/events/evgpe.c b/drivers/acpi/events/evgpe.c
index c5e53aae86f..f45c74fe745 100644
--- a/drivers/acpi/events/evgpe.c
+++ b/drivers/acpi/events/evgpe.c
@@ -289,8 +289,6 @@ acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)
*/
status = acpi_hw_low_disable_gpe(gpe_event_info);
return_ACPI_STATUS(status);
-
- return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
diff --git a/drivers/acpi/events/evxfevnt.c b/drivers/acpi/events/evxfevnt.c
index 73bfd6bf962..41554f736b6 100644
--- a/drivers/acpi/events/evxfevnt.c
+++ b/drivers/acpi/events/evxfevnt.c
@@ -248,21 +248,15 @@ ACPI_EXPORT_SYMBOL(acpi_set_gpe_type)
* DESCRIPTION: Enable an ACPI event (general purpose)
*
******************************************************************************/
-acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags)
+acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number)
{
acpi_status status = AE_OK;
+ acpi_cpu_flags flags;
struct acpi_gpe_event_info *gpe_event_info;
ACPI_FUNCTION_TRACE(acpi_enable_gpe);
- /* Use semaphore lock if not executing at interrupt level */
-
- if (flags & ACPI_NOT_ISR) {
- status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
- }
+ flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
/* Ensure that we have a valid GPE number */
@@ -277,9 +271,7 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags)
status = acpi_ev_enable_gpe(gpe_event_info, TRUE);
unlock_and_exit:
- if (flags & ACPI_NOT_ISR) {
- (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
- }
+ acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
return_ACPI_STATUS(status);
}
@@ -299,22 +291,15 @@ ACPI_EXPORT_SYMBOL(acpi_enable_gpe)
* DESCRIPTION: Disable an ACPI event (general purpose)
*
******************************************************************************/
-acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags)
+acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number)
{
acpi_status status = AE_OK;
+ acpi_cpu_flags flags;
struct acpi_gpe_event_info *gpe_event_info;
ACPI_FUNCTION_TRACE(acpi_disable_gpe);
- /* Use semaphore lock if not executing at interrupt level */
-
- if (flags & ACPI_NOT_ISR) {
- status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
- }
-
+ flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
/* Ensure that we have a valid GPE number */
gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
@@ -325,10 +310,8 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags)
status = acpi_ev_disable_gpe(gpe_event_info);
- unlock_and_exit:
- if (flags & ACPI_NOT_ISR) {
- (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
- }
+unlock_and_exit:
+ acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
return_ACPI_STATUS(status);
}
@@ -521,6 +504,9 @@ acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status)
if (value)
*event_status |= ACPI_EVENT_FLAG_SET;
+ if (acpi_gbl_fixed_event_handlers[event].handler)
+ *event_status |= ACPI_EVENT_FLAG_HANDLE;
+
return_ACPI_STATUS(status);
}
@@ -571,6 +557,9 @@ acpi_get_gpe_status(acpi_handle gpe_device,
status = acpi_hw_get_gpe_status(gpe_event_info, event_status);
+ if (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)
+ *event_status |= ACPI_EVENT_FLAG_HANDLE;
+
unlock_and_exit:
if (flags & ACPI_NOT_ISR) {
(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
index 60d54d1f6b1..eaaee1660bd 100644
--- a/drivers/acpi/fan.c
+++ b/drivers/acpi/fan.c
@@ -34,7 +34,6 @@
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
-#define ACPI_FAN_COMPONENT 0x00200000
#define ACPI_FAN_CLASS "fan"
#define ACPI_FAN_FILE_STATE "state"
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index 24649ada08d..adec3d15810 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -140,6 +140,46 @@ struct device *acpi_get_physical_device(acpi_handle handle)
EXPORT_SYMBOL(acpi_get_physical_device);
+/* ToDo: When a PCI bridge is found, return the PCI device behind the bridge
+ * This should work in general, but did not on a Lenovo T61 for the
+ * graphics card. But this must be fixed when the PCI device is
+ * bound and the kernel device struct is attached to the acpi device
+ * Note: A success call will increase reference count by one
+ * Do call put_device(dev) on the returned device then
+ */
+struct device *acpi_get_physical_pci_device(acpi_handle handle)
+{
+ struct device *dev;
+ long long device_id;
+ acpi_status status;
+
+ status =
+ acpi_evaluate_integer(handle, "_ADR", NULL, &device_id);
+
+ if (ACPI_FAILURE(status))
+ return NULL;
+
+ /* We need to attempt to determine whether the _ADR refers to a
+ PCI device or not. There's no terribly good way to do this,
+ so the best we can hope for is to assume that there'll never
+ be a device in the host bridge */
+ if (device_id >= 0x10000) {
+ /* It looks like a PCI device. Does it exist? */
+ dev = acpi_get_physical_device(handle);
+ } else {
+ /* It doesn't look like a PCI device. Does its parent
+ exist? */
+ acpi_handle phandle;
+ if (acpi_get_parent(handle, &phandle))
+ return NULL;
+ dev = acpi_get_physical_device(phandle);
+ }
+ if (!dev)
+ return NULL;
+ return dev;
+}
+EXPORT_SYMBOL(acpi_get_physical_pci_device);
+
static int acpi_bind_one(struct device *dev, acpi_handle handle)
{
struct acpi_device *acpi_dev;
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 4be252145cb..c8111424dcb 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -35,7 +35,6 @@
#include <linux/interrupt.h>
#include <linux/kmod.h>
#include <linux/delay.h>
-#include <linux/dmi.h>
#include <linux/workqueue.h>
#include <linux/nmi.h>
#include <linux/acpi.h>
@@ -97,54 +96,44 @@ static DEFINE_SPINLOCK(acpi_res_lock);
static char osi_additional_string[OSI_STRING_LENGTH_MAX];
/*
- * "Ode to _OSI(Linux)"
+ * The story of _OSI(Linux)
*
- * osi_linux -- Control response to BIOS _OSI(Linux) query.
+ * From pre-history through Linux-2.6.22,
+ * Linux responded TRUE upon a BIOS OSI(Linux) query.
*
- * As Linux evolves, the features that it supports change.
- * So an OSI string such as "Linux" is not specific enough
- * to be useful across multiple versions of Linux. It
- * doesn't identify any particular feature, interface,
- * or even any particular version of Linux...
+ * Unfortunately, reference BIOS writers got wind of this
+ * and put OSI(Linux) in their example code, quickly exposing
+ * this string as ill-conceived and opening the door to
+ * an un-bounded number of BIOS incompatibilities.
*
- * Unfortunately, Linux-2.6.22 and earlier responded "yes"
- * to a BIOS _OSI(Linux) query. When
- * a reference mobile BIOS started using it, its use
- * started to spread to many vendor platforms.
- * As it is not supportable, we need to halt that spread.
+ * For example, OSI(Linux) was used on resume to re-POST a
+ * video card on one system, because Linux at that time
+ * could not do a speedy restore in its native driver.
+ * But then upon gaining quick native restore capability,
+ * Linux has no way to tell the BIOS to skip the time-consuming
+ * POST -- putting Linux at a permanent performance disadvantage.
+ * On another system, the BIOS writer used OSI(Linux)
+ * to infer native OS support for IPMI! On other systems,
+ * OSI(Linux) simply got in the way of Linux claiming to
+ * be compatible with other operating systems, exposing
+ * BIOS issues such as skipped device initialization.
*
- * Today, most BIOS references to _OSI(Linux) are noise --
- * they have no functional effect and are just dead code
- * carried over from the reference BIOS.
- *
- * The next most common case is that _OSI(Linux) harms Linux,
- * usually by causing the BIOS to follow paths that are
- * not tested during Windows validation.
- *
- * Finally, there is a short list of platforms
- * where OSI(Linux) benefits Linux.
- *
- * In Linux-2.6.23, OSI(Linux) is first disabled by default.
- * DMI is used to disable the dmesg warning about OSI(Linux)
- * on platforms where it is known to have no effect.
- * But a dmesg warning remains for systems where
- * we do not know if OSI(Linux) is good or bad for the system.
- * DMI is also used to enable OSI(Linux) for the machines
- * that are known to need it.
+ * So "Linux" turned out to be a really poor chose of
+ * OSI string, and from Linux-2.6.23 onward we respond FALSE.
*
* BIOS writers should NOT query _OSI(Linux) on future systems.
- * It will be ignored by default, and to get Linux to
- * not ignore it will require a kernel source update to
- * add a DMI entry, or a boot-time "acpi_osi=Linux" invocation.
+ * Linux will complain on the console when it sees it, and return FALSE.
+ * To get Linux to return TRUE for your system will require
+ * a kernel source update to add a DMI entry,
+ * or boot with "acpi_osi=Linux"
*/
-#define OSI_LINUX_ENABLE 0
static struct osi_linux {
unsigned int enable:1;
unsigned int dmi:1;
unsigned int cmdline:1;
unsigned int known:1;
-} osi_linux = { OSI_LINUX_ENABLE, 0, 0, 0};
+} osi_linux = { 0, 0, 0, 0};
static void __init acpi_request_region (struct acpi_generic_address *addr,
unsigned int length, char *desc)
@@ -1296,34 +1285,6 @@ acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object)
return (AE_OK);
}
-/**
- * acpi_dmi_dump - dump DMI slots needed for blacklist entry
- *
- * Returns 0 on success
- */
-static int acpi_dmi_dump(void)
-{
-
- if (!dmi_available)
- return -1;
-
- printk(KERN_NOTICE PREFIX "DMI System Vendor: %s\n",
- dmi_get_system_info(DMI_SYS_VENDOR));
- printk(KERN_NOTICE PREFIX "DMI Product Name: %s\n",
- dmi_get_system_info(DMI_PRODUCT_NAME));
- printk(KERN_NOTICE PREFIX "DMI Product Version: %s\n",
- dmi_get_system_info(DMI_PRODUCT_VERSION));
- printk(KERN_NOTICE PREFIX "DMI Board Name: %s\n",
- dmi_get_system_info(DMI_BOARD_NAME));
- printk(KERN_NOTICE PREFIX "DMI BIOS Vendor: %s\n",
- dmi_get_system_info(DMI_BIOS_VENDOR));
- printk(KERN_NOTICE PREFIX "DMI BIOS Date: %s\n",
- dmi_get_system_info(DMI_BIOS_DATE));
-
- return 0;
-}
-
-
/******************************************************************************
*
* FUNCTION: acpi_os_validate_interface
@@ -1350,21 +1311,6 @@ acpi_os_validate_interface (char *interface)
osi_linux.cmdline ? " via cmdline" :
osi_linux.dmi ? " via DMI" : "");
- if (!osi_linux.dmi) {
- if (acpi_dmi_dump())
- printk(KERN_NOTICE PREFIX
- "[please extract dmidecode output]\n");
- printk(KERN_NOTICE PREFIX
- "Please send DMI info above to "
- "linux-acpi@vger.kernel.org\n");
- }
- if (!osi_linux.known && !osi_linux.cmdline) {
- printk(KERN_NOTICE PREFIX
- "If \"acpi_osi=%sLinux\" works better, "
- "please notify linux-acpi@vger.kernel.org\n",
- osi_linux.enable ? "!" : "");
- }
-
if (osi_linux.enable)
return AE_OK;
}
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
index fcfdef7b4fd..e52ad91ce2d 100644
--- a/drivers/acpi/pci_link.c
+++ b/drivers/acpi/pci_link.c
@@ -531,7 +531,7 @@ int __init acpi_irq_penalty_init(void)
return 0;
}
-static int acpi_irq_balance; /* 0: static, 1: balance */
+static int acpi_irq_balance = -1; /* 0: static, 1: balance */
static int acpi_pci_link_allocate(struct acpi_pci_link *link)
{
@@ -950,10 +950,17 @@ device_initcall(irqrouter_init_sysfs);
static int __init acpi_pci_link_init(void)
{
-
if (acpi_noirq)
return 0;
+ if (acpi_irq_balance == -1) {
+ /* no command line switch: enable balancing in IOAPIC mode */
+ if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC)
+ acpi_irq_balance = 1;
+ else
+ acpi_irq_balance = 0;
+ }
+
acpi_link.count = 0;
INIT_LIST_HEAD(&acpi_link.entries);
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 1b8f67d21d5..642554b1b60 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -376,15 +376,9 @@ static int acpi_pci_root_remove(struct acpi_device *device, int type)
static int __init acpi_pci_root_init(void)
{
-
if (acpi_pci_disabled)
return 0;
- /* DEBUG:
- acpi_dbg_layer = ACPI_PCI_COMPONENT;
- acpi_dbg_level = 0xFFFFFFFF;
- */
-
if (acpi_bus_register_driver(&acpi_pci_root_driver) < 0)
return -ENODEV;
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index a1718e56103..bb7d50dd281 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -44,9 +44,8 @@
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
-#define _COMPONENT ACPI_POWER_COMPONENT
+#define _COMPONENT ACPI_POWER_COMPONENT
ACPI_MODULE_NAME("power");
-#define ACPI_POWER_COMPONENT 0x00800000
#define ACPI_POWER_CLASS "power_resource"
#define ACPI_POWER_DEVICE_NAME "Power Resource"
#define ACPI_POWER_FILE_INFO "info"
@@ -153,7 +152,8 @@ static int acpi_power_get_state(acpi_handle handle, int *state)
ACPI_POWER_RESOURCE_STATE_OFF;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] is %s\n",
- acpi_ut_get_node_name(handle), state ? "on" : "off"));
+ acpi_ut_get_node_name(handle),
+ *state ? "on" : "off"));
return 0;
}
@@ -516,11 +516,6 @@ int acpi_power_transition(struct acpi_device *device, int state)
cl = &device->power.states[device->power.state].resources;
tl = &device->power.states[state].resources;
- if (!cl->count && !tl->count) {
- result = -ENODEV;
- goto end;
- }
-
/* TBD: Resources must be ordered. */
/*
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index 24a362f8034..34948362f41 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -59,7 +59,6 @@
#include <acpi/acpi_drivers.h>
#include <acpi/processor.h>
-#define ACPI_PROCESSOR_COMPONENT 0x01000000
#define ACPI_PROCESSOR_CLASS "processor"
#define ACPI_PROCESSOR_DEVICE_NAME "Processor"
#define ACPI_PROCESSOR_FILE_INFO "info"
@@ -89,6 +88,7 @@ static int acpi_processor_handle_eject(struct acpi_processor *pr);
static const struct acpi_device_id processor_device_ids[] = {
+ {ACPI_PROCESSOR_OBJECT_HID, 0},
{ACPI_PROCESSOR_HID, 0},
{"", 0},
};
@@ -409,7 +409,7 @@ static int acpi_processor_remove_fs(struct acpi_device *device)
/* Use the acpiid in MADT to map cpus in case of SMP */
#ifndef CONFIG_SMP
-static int get_cpu_id(acpi_handle handle, u32 acpi_id) {return -1;}
+static int get_cpu_id(acpi_handle handle, int type, u32 acpi_id) { return -1; }
#else
static struct acpi_table_madt *madt;
@@ -428,27 +428,35 @@ static int map_lapic_id(struct acpi_subtable_header *entry,
}
static int map_lsapic_id(struct acpi_subtable_header *entry,
- u32 acpi_id, int *apic_id)
+ int device_declaration, u32 acpi_id, int *apic_id)
{
struct acpi_madt_local_sapic *lsapic =
(struct acpi_madt_local_sapic *)entry;
+ u32 tmp = (lsapic->id << 8) | lsapic->eid;
+
/* Only check enabled APICs*/
- if (lsapic->lapic_flags & ACPI_MADT_ENABLED) {
- /* First check against id */
- if (lsapic->processor_id == acpi_id) {
- *apic_id = (lsapic->id << 8) | lsapic->eid;
- return 1;
- /* Check against optional uid */
- } else if (entry->length >= 16 &&
- lsapic->uid == acpi_id) {
- *apic_id = lsapic->uid;
- return 1;
- }
- }
+ if (!(lsapic->lapic_flags & ACPI_MADT_ENABLED))
+ return 0;
+
+ /* Device statement declaration type */
+ if (device_declaration) {
+ if (entry->length < 16)
+ printk(KERN_ERR PREFIX
+ "Invalid LSAPIC with Device type processor (SAPIC ID %#x)\n",
+ tmp);
+ else if (lsapic->uid == acpi_id)
+ goto found;
+ /* Processor statement declaration type */
+ } else if (lsapic->processor_id == acpi_id)
+ goto found;
+
return 0;
+found:
+ *apic_id = tmp;
+ return 1;
}
-static int map_madt_entry(u32 acpi_id)
+static int map_madt_entry(int type, u32 acpi_id)
{
unsigned long madt_end, entry;
int apic_id = -1;
@@ -469,7 +477,7 @@ static int map_madt_entry(u32 acpi_id)
if (map_lapic_id(header, acpi_id, &apic_id))
break;
} else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) {
- if (map_lsapic_id(header, acpi_id, &apic_id))
+ if (map_lsapic_id(header, type, acpi_id, &apic_id))
break;
}
entry += header->length;
@@ -477,7 +485,7 @@ static int map_madt_entry(u32 acpi_id)
return apic_id;
}
-static int map_mat_entry(acpi_handle handle, u32 acpi_id)
+static int map_mat_entry(acpi_handle handle, int type, u32 acpi_id)
{
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
union acpi_object *obj;
@@ -500,7 +508,7 @@ static int map_mat_entry(acpi_handle handle, u32 acpi_id)
if (header->type == ACPI_MADT_TYPE_LOCAL_APIC) {
map_lapic_id(header, acpi_id, &apic_id);
} else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) {
- map_lsapic_id(header, acpi_id, &apic_id);
+ map_lsapic_id(header, type, acpi_id, &apic_id);
}
exit:
@@ -509,14 +517,14 @@ exit:
return apic_id;
}
-static int get_cpu_id(acpi_handle handle, u32 acpi_id)
+static int get_cpu_id(acpi_handle handle, int type, u32 acpi_id)
{
int i;
int apic_id = -1;
- apic_id = map_mat_entry(handle, acpi_id);
+ apic_id = map_mat_entry(handle, type, acpi_id);
if (apic_id == -1)
- apic_id = map_madt_entry(acpi_id);
+ apic_id = map_madt_entry(type, acpi_id);
if (apic_id == -1)
return apic_id;
@@ -532,15 +540,16 @@ static int get_cpu_id(acpi_handle handle, u32 acpi_id)
Driver Interface
-------------------------------------------------------------------------- */
-static int acpi_processor_get_info(struct acpi_processor *pr, unsigned has_uid)
+static int acpi_processor_get_info(struct acpi_device *device)
{
acpi_status status = 0;
union acpi_object object = { 0 };
struct acpi_buffer buffer = { sizeof(union acpi_object), &object };
- int cpu_index;
+ struct acpi_processor *pr;
+ int cpu_index, device_declaration = 0;
static int cpu0_initialized;
-
+ pr = acpi_driver_data(device);
if (!pr)
return -EINVAL;
@@ -561,22 +570,23 @@ static int acpi_processor_get_info(struct acpi_processor *pr, unsigned has_uid)
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"No bus mastering arbitration control\n"));
- /* Check if it is a Device with HID and UID */
- if (has_uid) {
+ if (!strcmp(acpi_device_hid(device), ACPI_PROCESSOR_HID)) {
+ /*
+ * Declared with "Device" statement; match _UID.
+ * Note that we don't handle string _UIDs yet.
+ */
unsigned long long value;
status = acpi_evaluate_integer(pr->handle, METHOD_NAME__UID,
NULL, &value);
if (ACPI_FAILURE(status)) {
- printk(KERN_ERR PREFIX "Evaluating processor _UID\n");
+ printk(KERN_ERR PREFIX
+ "Evaluating processor _UID [%#x]\n", status);
return -ENODEV;
}
+ device_declaration = 1;
pr->acpi_id = value;
} else {
- /*
- * Evalute the processor object. Note that it is common on SMP to
- * have the first (boot) processor with a valid PBLK address while
- * all others have a NULL address.
- */
+ /* Declared with "Processor" statement; match ProcessorID */
status = acpi_evaluate_object(pr->handle, NULL, NULL, &buffer);
if (ACPI_FAILURE(status)) {
printk(KERN_ERR PREFIX "Evaluating processor object\n");
@@ -584,12 +594,13 @@ static int acpi_processor_get_info(struct acpi_processor *pr, unsigned has_uid)
}
/*
- * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP.
- * >>> 'acpi_get_processor_id(acpi_id, &id)' in arch/xxx/acpi.c
- */
+ * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP.
+ * >>> 'acpi_get_processor_id(acpi_id, &id)' in
+ * arch/xxx/acpi.c
+ */
pr->acpi_id = object.processor.proc_id;
}
- cpu_index = get_cpu_id(pr->handle, pr->acpi_id);
+ cpu_index = get_cpu_id(pr->handle, device_declaration, pr->acpi_id);
/* Handle UP system running SMP kernel, with no LAPIC in MADT */
if (!cpu0_initialized && (cpu_index == -1) &&
@@ -661,7 +672,7 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device)
pr = acpi_driver_data(device);
- result = acpi_processor_get_info(pr, device->flags.unique_id);
+ result = acpi_processor_get_info(device);
if (result) {
/* Processor is physically not present */
return 0;
@@ -761,20 +772,20 @@ static void acpi_processor_notify(acpi_handle handle, u32 event, void *data)
acpi_bus_generate_proc_event(device, event,
pr->performance_platform_limit);
acpi_bus_generate_netlink_event(device->pnp.device_class,
- device->dev.bus_id, event,
+ dev_name(&device->dev), event,
pr->performance_platform_limit);
break;
case ACPI_PROCESSOR_NOTIFY_POWER:
acpi_processor_cst_has_changed(pr);
acpi_bus_generate_proc_event(device, event, 0);
acpi_bus_generate_netlink_event(device->pnp.device_class,
- device->dev.bus_id, event, 0);
+ dev_name(&device->dev), event, 0);
break;
case ACPI_PROCESSOR_NOTIFY_THROTTLING:
acpi_processor_tstate_has_changed(pr);
acpi_bus_generate_proc_event(device, event, 0);
acpi_bus_generate_netlink_event(device->pnp.device_class,
- device->dev.bus_id, event, 0);
+ dev_name(&device->dev), event, 0);
default:
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Unsupported event [0x%x]\n", event));
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 81b40ed5379..5f8d746a9b8 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -59,7 +59,6 @@
#include <acpi/processor.h>
#include <asm/processor.h>
-#define ACPI_PROCESSOR_COMPONENT 0x01000000
#define ACPI_PROCESSOR_CLASS "processor"
#define _COMPONENT ACPI_PROCESSOR_COMPONENT
ACPI_MODULE_NAME("processor_idle");
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
index dbcf260ea93..0d7b772bef5 100644
--- a/drivers/acpi/processor_perflib.c
+++ b/drivers/acpi/processor_perflib.c
@@ -44,9 +44,9 @@
#endif
#include <acpi/acpi_bus.h>
+#include <acpi/acpi_drivers.h>
#include <acpi/processor.h>
-#define ACPI_PROCESSOR_COMPONENT 0x01000000
#define ACPI_PROCESSOR_CLASS "processor"
#define ACPI_PROCESSOR_FILE_PERFORMANCE "performance"
#define _COMPONENT ACPI_PROCESSOR_COMPONENT
diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c
index ef34b18f95c..b1eb376fae4 100644
--- a/drivers/acpi/processor_thermal.c
+++ b/drivers/acpi/processor_thermal.c
@@ -40,7 +40,6 @@
#include <acpi/processor.h>
#include <acpi/acpi_drivers.h>
-#define ACPI_PROCESSOR_COMPONENT 0x01000000
#define ACPI_PROCESSOR_CLASS "processor"
#define _COMPONENT ACPI_PROCESSOR_COMPONENT
ACPI_MODULE_NAME("processor_thermal");
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c
index 3da2df93d92..a0c38c94a8a 100644
--- a/drivers/acpi/processor_throttling.c
+++ b/drivers/acpi/processor_throttling.c
@@ -38,9 +38,9 @@
#include <asm/uaccess.h>
#include <acpi/acpi_bus.h>
+#include <acpi/acpi_drivers.h>
#include <acpi/processor.h>
-#define ACPI_PROCESSOR_COMPONENT 0x01000000
#define ACPI_PROCESSOR_CLASS "processor"
#define _COMPONENT ACPI_PROCESSOR_COMPONENT
ACPI_MODULE_NAME("processor_throttling");
diff --git a/drivers/acpi/reboot.c b/drivers/acpi/reboot.c
index 755baf2ca70..a6b662c00b6 100644
--- a/drivers/acpi/reboot.c
+++ b/drivers/acpi/reboot.c
@@ -15,28 +15,9 @@ void acpi_reboot(void)
rr = &acpi_gbl_FADT.reset_register;
- /*
- * Is the ACPI reset register supported?
- *
- * According to ACPI 3.0, FADT.flags.RESET_REG_SUP indicates
- * whether the ACPI reset mechanism is supported.
- *
- * However, some boxes have this bit clear, yet a valid
- * ACPI_RESET_REG & RESET_VALUE, and ACPI reboot is the only
- * mechanism that works for them after S3.
- *
- * This suggests that other operating systems may not be checking
- * the RESET_REG_SUP bit, and are using other means to decide
- * whether to use the ACPI reboot mechanism or not.
- *
- * So when acpi reboot is requested,
- * only the reset_register is checked. If the following
- * conditions are met, it indicates that the reset register is supported.
- * a. reset_register is not zero
- * b. the access width is eight
- * c. the bit_offset is zero
- */
- if (!(rr->address) || rr->bit_width != 8 || rr->bit_offset != 0)
+ /* Is the reset register supported? */
+ if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER) ||
+ rr->bit_width != 8 || rr->bit_offset != 0)
return;
reset_value = acpi_gbl_FADT.reset_value;
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index a9dda8e0f9f..39b7233c348 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -109,8 +109,7 @@ static int acpi_bus_hot_remove_device(void *context)
return 0;
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Hot-removing device %s...\n", device->dev.bus_id));
-
+ "Hot-removing device %s...\n", dev_name(&device->dev)));
if (acpi_bus_trim(device, 1)) {
printk(KERN_ERR PREFIX
@@ -460,7 +459,7 @@ static int acpi_device_register(struct acpi_device *device,
acpi_device_bus_id->instance_no = 0;
list_add_tail(&acpi_device_bus_id->node, &acpi_bus_id_list);
}
- sprintf(device->dev.bus_id, "%s:%02x", acpi_device_bus_id->bus_id, acpi_device_bus_id->instance_no);
+ dev_set_name(&device->dev, "%s:%02x", acpi_device_bus_id->bus_id, acpi_device_bus_id->instance_no);
if (device->parent) {
list_add_tail(&device->node, &device->parent->children);
@@ -484,7 +483,8 @@ static int acpi_device_register(struct acpi_device *device,
result = acpi_device_setup_files(device);
if(result)
- printk(KERN_ERR PREFIX "Error creating sysfs interface for device %s\n", device->dev.bus_id);
+ printk(KERN_ERR PREFIX "Error creating sysfs interface for device %s\n",
+ dev_name(&device->dev));
device->removal_type = ACPI_BUS_REMOVAL_NORMAL;
return 0;
@@ -751,16 +751,6 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
if (!acpi_match_device_ids(device, button_device_ids))
device->wakeup.flags.run_wake = 1;
- /*
- * Don't set Power button GPE as run_wake
- * if Fixed Power button is used
- */
- if (!strcmp(device->pnp.hardware_id, "PNP0C0C") &&
- !(acpi_gbl_FADT.flags & ACPI_FADT_POWER_BUTTON)) {
- device->wakeup.flags.run_wake = 0;
- device->wakeup.flags.valid = 0;
- }
-
end:
if (ACPI_FAILURE(status))
device->flags.wake_capable = 0;
@@ -919,36 +909,6 @@ static void acpi_device_get_busid(struct acpi_device *device,
}
}
-static int
-acpi_video_bus_match(struct acpi_device *device)
-{
- acpi_handle h_dummy;
-
- if (!device)
- return -EINVAL;
-
- /* Since there is no HID, CID for ACPI Video drivers, we have
- * to check well known required nodes for each feature we support.
- */
-
- /* Does this device able to support video switching ? */
- if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOD", &h_dummy)) &&
- ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOS", &h_dummy)))
- return 0;
-
- /* Does this device able to retrieve a video ROM ? */
- if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_ROM", &h_dummy)))
- return 0;
-
- /* Does this device able to configure which video head to be POSTed ? */
- if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_VPO", &h_dummy)) &&
- ACPI_SUCCESS(acpi_get_handle(device->handle, "_GPD", &h_dummy)) &&
- ACPI_SUCCESS(acpi_get_handle(device->handle, "_SPD", &h_dummy)))
- return 0;
-
- return -ENODEV;
-}
-
/*
* acpi_bay_match - see if a device is an ejectable driver bay
*
@@ -1031,7 +991,7 @@ static void acpi_device_set_id(struct acpi_device *device,
will get autoloaded and the device might still match
against another driver.
*/
- if (ACPI_SUCCESS(acpi_video_bus_match(device)))
+ if (acpi_is_video_device(device))
cid_add = ACPI_VIDEO_HID;
else if (ACPI_SUCCESS(acpi_bay_match(device)))
cid_add = ACPI_BAY_HID;
@@ -1043,7 +1003,7 @@ static void acpi_device_set_id(struct acpi_device *device,
hid = ACPI_POWER_HID;
break;
case ACPI_BUS_TYPE_PROCESSOR:
- hid = ACPI_PROCESSOR_HID;
+ hid = ACPI_PROCESSOR_OBJECT_HID;
break;
case ACPI_BUS_TYPE_SYSTEM:
hid = ACPI_SYSTEM_HID;
diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c
index 80c0868d048..28a691cc625 100644
--- a/drivers/acpi/sleep/main.c
+++ b/drivers/acpi/sleep/main.c
@@ -90,6 +90,18 @@ void __init acpi_old_suspend_ordering(void)
old_suspend_ordering = true;
}
+/*
+ * According to the ACPI specification the BIOS should make sure that ACPI is
+ * enabled and SCI_EN bit is set on wake-up from S1 - S3 sleep states. Still,
+ * some BIOSes don't do that and therefore we use acpi_enable() to enable ACPI
+ * on such systems during resume. Unfortunately that doesn't help in
+ * particularly pathological cases in which SCI_EN has to be set directly on
+ * resume, although the specification states very clearly that this flag is
+ * owned by the hardware. The set_sci_en_on_resume variable will be set in such
+ * cases.
+ */
+static bool set_sci_en_on_resume;
+
/**
* acpi_pm_disable_gpes - Disable the GPEs.
*/
@@ -235,7 +247,11 @@ static int acpi_suspend_enter(suspend_state_t pm_state)
}
/* If ACPI is not enabled by the BIOS, we need to enable it here. */
- acpi_enable();
+ if (set_sci_en_on_resume)
+ acpi_set_register(ACPI_BITREG_SCI_ENABLE, 1);
+ else
+ acpi_enable();
+
/* Reprogram control registers and execute _BFS */
acpi_leave_sleep_state_prep(acpi_state);
@@ -323,6 +339,12 @@ static int __init init_old_suspend_ordering(const struct dmi_system_id *d)
return 0;
}
+static int __init init_set_sci_en_on_resume(const struct dmi_system_id *d)
+{
+ set_sci_en_on_resume = true;
+ return 0;
+}
+
static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
{
.callback = init_old_suspend_ordering,
@@ -340,6 +362,22 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "HP xw4600 Workstation"),
},
},
+ {
+ .callback = init_set_sci_en_on_resume,
+ .ident = "Apple MacBook 1,1",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Apple Computer, Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "MacBook1,1"),
+ },
+ },
+ {
+ .callback = init_set_sci_en_on_resume,
+ .ident = "Apple MacMini 1,1",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Apple Computer, Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Macmini1,1"),
+ },
+ },
{},
};
#endif /* CONFIG_SUSPEND */
diff --git a/drivers/acpi/sleep/proc.c b/drivers/acpi/sleep/proc.c
index 631ee2ee2ca..4dbc2271acf 100644
--- a/drivers/acpi/sleep/proc.c
+++ b/drivers/acpi/sleep/proc.c
@@ -367,7 +367,7 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset)
if (ldev)
seq_printf(seq, "%s:%s",
ldev->bus ? ldev->bus->name : "no-bus",
- ldev->bus_id);
+ dev_name(ldev));
seq_printf(seq, "\n");
put_device(ldev);
diff --git a/drivers/acpi/sleep/wakeup.c b/drivers/acpi/sleep/wakeup.c
index 38655eb132d..dea4c23df76 100644
--- a/drivers/acpi/sleep/wakeup.c
+++ b/drivers/acpi/sleep/wakeup.c
@@ -88,7 +88,7 @@ void acpi_enable_wakeup_device(u8 sleep_state)
spin_unlock(&acpi_device_lock);
if (!dev->wakeup.flags.run_wake)
acpi_enable_gpe(dev->wakeup.gpe_device,
- dev->wakeup.gpe_number, ACPI_ISR);
+ dev->wakeup.gpe_number);
spin_lock(&acpi_device_lock);
}
spin_unlock(&acpi_device_lock);
@@ -122,7 +122,7 @@ void acpi_disable_wakeup_device(u8 sleep_state)
ACPI_GPE_TYPE_WAKE_RUN);
/* Re-enable it, since set_gpe_type will disable it */
acpi_enable_gpe(dev->wakeup.gpe_device,
- dev->wakeup.gpe_number, ACPI_NOT_ISR);
+ dev->wakeup.gpe_number);
spin_lock(&acpi_device_lock);
}
continue;
@@ -133,7 +133,7 @@ void acpi_disable_wakeup_device(u8 sleep_state)
/* Never disable run-wake GPE */
if (!dev->wakeup.flags.run_wake) {
acpi_disable_gpe(dev->wakeup.gpe_device,
- dev->wakeup.gpe_number, ACPI_NOT_ISR);
+ dev->wakeup.gpe_number);
acpi_clear_gpe(dev->wakeup.gpe_device,
dev->wakeup.gpe_number, ACPI_NOT_ISR);
}
@@ -162,7 +162,7 @@ static int __init acpi_wakeup_device_init(void)
dev->wakeup.gpe_number,
ACPI_GPE_TYPE_WAKE_RUN);
acpi_enable_gpe(dev->wakeup.gpe_device,
- dev->wakeup.gpe_number, ACPI_NOT_ISR);
+ dev->wakeup.gpe_number);
dev->wakeup.state.enabled = 1;
spin_lock(&acpi_device_lock);
}
diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c
index 1d74171b794..6e4107f8240 100644
--- a/drivers/acpi/system.c
+++ b/drivers/acpi/system.c
@@ -78,9 +78,15 @@ static ssize_t acpi_table_show(struct kobject *kobj,
container_of(bin_attr, struct acpi_table_attr, attr);
struct acpi_table_header *table_header = NULL;
acpi_status status;
+ char name[ACPI_NAME_SIZE];
+
+ if (strncmp(table_attr->name, "NULL", 4))
+ memcpy(name, table_attr->name, ACPI_NAME_SIZE);
+ else
+ memcpy(name, "\0\0\0\0", 4);
status =
- acpi_get_table(table_attr->name, table_attr->instance,
+ acpi_get_table(name, table_attr->instance,
&table_header);
if (ACPI_FAILURE(status))
return -ENODEV;
@@ -95,21 +101,24 @@ static void acpi_table_attr_init(struct acpi_table_attr *table_attr,
struct acpi_table_header *header = NULL;
struct acpi_table_attr *attr = NULL;
- memcpy(table_attr->name, table_header->signature, ACPI_NAME_SIZE);
+ if (table_header->signature[0] != '\0')
+ memcpy(table_attr->name, table_header->signature,
+ ACPI_NAME_SIZE);
+ else
+ memcpy(table_attr->name, "NULL", 4);
list_for_each_entry(attr, &acpi_table_attr_list, node) {
- if (!memcmp(table_header->signature, attr->name,
- ACPI_NAME_SIZE))
+ if (!memcmp(table_attr->name, attr->name, ACPI_NAME_SIZE))
if (table_attr->instance < attr->instance)
table_attr->instance = attr->instance;
}
table_attr->instance++;
if (table_attr->instance > 1 || (table_attr->instance == 1 &&
- !acpi_get_table(table_header->
- signature, 2,
- &header)))
- sprintf(table_attr->name + 4, "%d", table_attr->instance);
+ !acpi_get_table
+ (table_header->signature, 2, &header)))
+ sprintf(table_attr->name + ACPI_NAME_SIZE, "%d",
+ table_attr->instance);
table_attr->attr.size = 0;
table_attr->attr.read = acpi_table_show;
@@ -167,7 +176,6 @@ static int acpi_system_sysfs_init(void)
#define COUNT_ERROR 2 /* other */
#define NUM_COUNTERS_EXTRA 3
-#define ACPI_EVENT_VALID 0x01
struct event_counter {
u32 count;
u32 flags;
@@ -312,12 +320,6 @@ static int get_status(u32 index, acpi_event_status *status, acpi_handle *handle)
} else if (index < (num_gpes + ACPI_NUM_FIXED_EVENTS))
result = acpi_get_event_status(index - num_gpes, status);
- /*
- * sleep/power button GPE/Fixed Event is enabled after acpi_system_init,
- * check the status at runtime and mark it as valid once it's enabled
- */
- if (!result && (*status & ACPI_EVENT_FLAG_ENABLED))
- all_counters[index].flags |= ACPI_EVENT_VALID;
end:
return result;
}
@@ -346,12 +348,14 @@ static ssize_t counter_show(struct kobject *kobj,
if (result)
goto end;
- if (!(all_counters[index].flags & ACPI_EVENT_VALID))
- size += sprintf(buf + size, " invalid");
+ if (!(status & ACPI_EVENT_FLAG_HANDLE))
+ size += sprintf(buf + size, " invalid");
else if (status & ACPI_EVENT_FLAG_ENABLED)
- size += sprintf(buf + size, " enable");
+ size += sprintf(buf + size, " enabled");
+ else if (status & ACPI_EVENT_FLAG_WAKE_ENABLED)
+ size += sprintf(buf + size, " wake_enabled");
else
- size += sprintf(buf + size, " disable");
+ size += sprintf(buf + size, " disabled");
end:
size += sprintf(buf + size, "\n");
@@ -385,7 +389,7 @@ static ssize_t counter_set(struct kobject *kobj,
if (result)
goto end;
- if (!(all_counters[index].flags & ACPI_EVENT_VALID)) {
+ if (!(status & ACPI_EVENT_FLAG_HANDLE)) {
printk(KERN_WARNING PREFIX
"Can not change Invalid GPE/Fixed Event status\n");
return -EINVAL;
@@ -394,10 +398,10 @@ static ssize_t counter_set(struct kobject *kobj,
if (index < num_gpes) {
if (!strcmp(buf, "disable\n") &&
(status & ACPI_EVENT_FLAG_ENABLED))
- result = acpi_disable_gpe(handle, index, ACPI_NOT_ISR);
+ result = acpi_disable_gpe(handle, index);
else if (!strcmp(buf, "enable\n") &&
!(status & ACPI_EVENT_FLAG_ENABLED))
- result = acpi_enable_gpe(handle, index, ACPI_NOT_ISR);
+ result = acpi_enable_gpe(handle, index);
else if (!strcmp(buf, "clear\n") &&
(status & ACPI_EVENT_FLAG_SET))
result = acpi_clear_gpe(handle, index, ACPI_NOT_ISR);
diff --git a/drivers/acpi/tables/tbfadt.c b/drivers/acpi/tables/tbfadt.c
index 2c7885e7ffb..2817158fb6a 100644
--- a/drivers/acpi/tables/tbfadt.c
+++ b/drivers/acpi/tables/tbfadt.c
@@ -304,7 +304,7 @@ static void acpi_tb_convert_fadt(void)
* The ACPI 1.0 reserved fields that will be zeroed are the bytes located at
* offset 45, 55, 95, and the word located at offset 109, 110.
*/
- if (acpi_gbl_FADT.header.revision < 3) {
+ if (acpi_gbl_FADT.header.revision < FADT2_REVISION_ID) {
acpi_gbl_FADT.preferred_profile = 0;
acpi_gbl_FADT.pstate_control = 0;
acpi_gbl_FADT.cst_control = 0;
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index ad6cae938f0..073ff09218a 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -47,7 +47,6 @@
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
-#define ACPI_THERMAL_COMPONENT 0x04000000
#define ACPI_THERMAL_CLASS "thermal_zone"
#define ACPI_THERMAL_DEVICE_NAME "Thermal Zone"
#define ACPI_THERMAL_FILE_STATE "state"
@@ -576,7 +575,7 @@ static int acpi_thermal_critical(struct acpi_thermal *tz)
acpi_bus_generate_proc_event(tz->device, ACPI_THERMAL_NOTIFY_CRITICAL,
tz->trips.critical.flags.enabled);
acpi_bus_generate_netlink_event(tz->device->pnp.device_class,
- tz->device->dev.bus_id,
+ dev_name(&tz->device->dev),
ACPI_THERMAL_NOTIFY_CRITICAL,
tz->trips.critical.flags.enabled);
@@ -605,7 +604,7 @@ static int acpi_thermal_hot(struct acpi_thermal *tz)
acpi_bus_generate_proc_event(tz->device, ACPI_THERMAL_NOTIFY_HOT,
tz->trips.hot.flags.enabled);
acpi_bus_generate_netlink_event(tz->device->pnp.device_class,
- tz->device->dev.bus_id,
+ dev_name(&tz->device->dev),
ACPI_THERMAL_NOTIFY_HOT,
tz->trips.hot.flags.enabled);
@@ -1592,14 +1591,14 @@ static void acpi_thermal_notify(acpi_handle handle, u32 event, void *data)
acpi_thermal_check(tz);
acpi_bus_generate_proc_event(device, event, 0);
acpi_bus_generate_netlink_event(device->pnp.device_class,
- device->dev.bus_id, event, 0);
+ dev_name(&device->dev), event, 0);
break;
case ACPI_THERMAL_NOTIFY_DEVICES:
acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_DEVICES);
acpi_thermal_check(tz);
acpi_bus_generate_proc_event(device, event, 0);
acpi_bus_generate_netlink_event(device->pnp.device_class,
- device->dev.bus_id, event, 0);
+ dev_name(&device->dev), event, 0);
break;
default:
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
diff --git a/drivers/acpi/toshiba_acpi.c b/drivers/acpi/toshiba_acpi.c
index 66aac06f2ac..40e60fc2e59 100644
--- a/drivers/acpi/toshiba_acpi.c
+++ b/drivers/acpi/toshiba_acpi.c
@@ -824,34 +824,36 @@ static int __init toshiba_acpi_init(void)
toshiba_acpi_exit();
return -ENOMEM;
}
- }
- /* Register input device for kill switch */
- toshiba_acpi.poll_dev = input_allocate_polled_device();
- if (!toshiba_acpi.poll_dev) {
- printk(MY_ERR "unable to allocate kill-switch input device\n");
- toshiba_acpi_exit();
- return -ENOMEM;
- }
- toshiba_acpi.poll_dev->private = &toshiba_acpi;
- toshiba_acpi.poll_dev->poll = bt_poll_rfkill;
- toshiba_acpi.poll_dev->poll_interval = 1000; /* msecs */
-
- toshiba_acpi.poll_dev->input->name = toshiba_acpi.rfk_name;
- toshiba_acpi.poll_dev->input->id.bustype = BUS_HOST;
- toshiba_acpi.poll_dev->input->id.vendor = 0x0930; /* Toshiba USB ID */
- set_bit(EV_SW, toshiba_acpi.poll_dev->input->evbit);
- set_bit(SW_RFKILL_ALL, toshiba_acpi.poll_dev->input->swbit);
- input_report_switch(toshiba_acpi.poll_dev->input, SW_RFKILL_ALL, TRUE);
- input_sync(toshiba_acpi.poll_dev->input);
-
- ret = input_register_polled_device(toshiba_acpi.poll_dev);
- if (ret) {
- printk(MY_ERR "unable to register kill-switch input device\n");
- rfkill_free(toshiba_acpi.rfk_dev);
- toshiba_acpi.rfk_dev = NULL;
- toshiba_acpi_exit();
- return ret;
+ /* Register input device for kill switch */
+ toshiba_acpi.poll_dev = input_allocate_polled_device();
+ if (!toshiba_acpi.poll_dev) {
+ printk(MY_ERR
+ "unable to allocate kill-switch input device\n");
+ toshiba_acpi_exit();
+ return -ENOMEM;
+ }
+ toshiba_acpi.poll_dev->private = &toshiba_acpi;
+ toshiba_acpi.poll_dev->poll = bt_poll_rfkill;
+ toshiba_acpi.poll_dev->poll_interval = 1000; /* msecs */
+
+ toshiba_acpi.poll_dev->input->name = toshiba_acpi.rfk_name;
+ toshiba_acpi.poll_dev->input->id.bustype = BUS_HOST;
+ /* Toshiba USB ID */
+ toshiba_acpi.poll_dev->input->id.vendor = 0x0930;
+ set_bit(EV_SW, toshiba_acpi.poll_dev->input->evbit);
+ set_bit(SW_RFKILL_ALL, toshiba_acpi.poll_dev->input->swbit);
+ input_report_switch(toshiba_acpi.poll_dev->input,
+ SW_RFKILL_ALL, TRUE);
+ input_sync(toshiba_acpi.poll_dev->input);
+
+ ret = input_register_polled_device(toshiba_acpi.poll_dev);
+ if (ret) {
+ printk(MY_ERR
+ "unable to register kill-switch input device\n");
+ toshiba_acpi_exit();
+ return ret;
+ }
}
return 0;
diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c
index 670551b95e5..17ed5ac840f 100644
--- a/drivers/acpi/utilities/utglobal.c
+++ b/drivers/acpi/utilities/utglobal.c
@@ -64,7 +64,7 @@ u32 acpi_dbg_level = ACPI_DEBUG_DEFAULT;
/* Debug switch - layer (component) mask */
-u32 acpi_dbg_layer = ACPI_COMPONENT_DEFAULT | ACPI_ALL_DRIVERS;
+u32 acpi_dbg_layer = 0;
u32 acpi_gbl_nesting_level = 0;
/* Debugger globals */
diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c
index e827be36ee8..f844941089b 100644
--- a/drivers/acpi/utils.c
+++ b/drivers/acpi/utils.c
@@ -259,34 +259,26 @@ acpi_evaluate_integer(acpi_handle handle,
struct acpi_object_list *arguments, unsigned long long *data)
{
acpi_status status = AE_OK;
- union acpi_object *element;
+ union acpi_object element;
struct acpi_buffer buffer = { 0, NULL };
-
if (!data)
return AE_BAD_PARAMETER;
- element = kzalloc(sizeof(union acpi_object), irqs_disabled() ? GFP_ATOMIC: GFP_KERNEL);
- if (!element)
- return AE_NO_MEMORY;
-
buffer.length = sizeof(union acpi_object);
- buffer.pointer = element;
+ buffer.pointer = &element;
status = acpi_evaluate_object(handle, pathname, arguments, &buffer);
if (ACPI_FAILURE(status)) {
acpi_util_eval_error(handle, pathname, status);
- kfree(element);
return status;
}
- if (element->type != ACPI_TYPE_INTEGER) {
+ if (element.type != ACPI_TYPE_INTEGER) {
acpi_util_eval_error(handle, pathname, AE_BAD_DATA);
- kfree(element);
return AE_BAD_DATA;
}
- *data = element->integer.value;
- kfree(element);
+ *data = element.integer.value;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Return value [%llu]\n", *data));
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index a29b0ccac65..baa44192972 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -41,7 +41,6 @@
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
-#define ACPI_VIDEO_COMPONENT 0x08000000
#define ACPI_VIDEO_CLASS "video"
#define ACPI_VIDEO_BUS_NAME "Video Bus"
#define ACPI_VIDEO_DEVICE_NAME "Video Device"
@@ -739,7 +738,8 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
device->cap._DSS = 1;
}
- max_level = acpi_video_init_brightness(device);
+ if (acpi_video_backlight_support())
+ max_level = acpi_video_init_brightness(device);
if (device->cap._BCL && device->cap._BCM && max_level > 0) {
int result;
@@ -785,18 +785,21 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
printk(KERN_ERR PREFIX "Create sysfs link\n");
}
- if (device->cap._DCS && device->cap._DSS){
- static int count = 0;
- char *name;
- name = kzalloc(MAX_NAME_LEN, GFP_KERNEL);
- if (!name)
- return;
- sprintf(name, "acpi_video%d", count++);
- device->output_dev = video_output_register(name,
- NULL, device, &acpi_output_properties);
- kfree(name);
+
+ if (acpi_video_display_switch_support()) {
+
+ if (device->cap._DCS && device->cap._DSS) {
+ static int count;
+ char *name;
+ name = kzalloc(MAX_NAME_LEN, GFP_KERNEL);
+ if (!name)
+ return;
+ sprintf(name, "acpi_video%d", count++);
+ device->output_dev = video_output_register(name,
+ NULL, device, &acpi_output_properties);
+ kfree(name);
+ }
}
- return;
}
/*
@@ -842,11 +845,16 @@ static void acpi_video_bus_find_cap(struct acpi_video_bus *video)
static int acpi_video_bus_check(struct acpi_video_bus *video)
{
acpi_status status = -ENOENT;
-
+ struct device *dev;
if (!video)
return -EINVAL;
+ dev = acpi_get_physical_pci_device(video->device->handle);
+ if (!dev)
+ return -ENODEV;
+ put_device(dev);
+
/* Since there is no HID, CID and so on for VGA driver, we have
* to check well known required nodes.
*/
@@ -2094,12 +2102,6 @@ static int __init acpi_video_init(void)
{
int result = 0;
-
- /*
- acpi_dbg_level = 0xFFFFFFFF;
- acpi_dbg_layer = 0x08000000;
- */
-
acpi_video_dir = proc_mkdir(ACPI_VIDEO_CLASS, acpi_root_dir);
if (!acpi_video_dir)
return -ENODEV;
diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c
new file mode 100644
index 00000000000..f022eb6f563
--- /dev/null
+++ b/drivers/acpi/video_detect.c
@@ -0,0 +1,267 @@
+/*
+ * Copyright (C) 2008 SuSE Linux Products GmbH
+ * Thomas Renninger <trenn@suse.de>
+ *
+ * May be copied or modified under the terms of the GNU General Public License
+ *
+ * video_detect.c:
+ * Provides acpi_is_video_device() for early scanning of ACPI devices in scan.c
+ * There a Linux specific (Spec does not provide a HID for video devices) is
+ * assinged
+ *
+ * After PCI devices are glued with ACPI devices
+ * acpi_get_physical_pci_device() can be called to identify ACPI graphics
+ * devices for which a real graphics card is plugged in
+ *
+ * Now acpi_video_get_capabilities() can be called to check which
+ * capabilities the graphics cards plugged in support. The check for general
+ * video capabilities will be triggered by the first caller of
+ * acpi_video_get_capabilities(NULL); which will happen when the first
+ * backlight (or display output) switching supporting driver calls:
+ * acpi_video_backlight_support();
+ *
+ * Depending on whether ACPI graphics extensions (cmp. ACPI spec Appendix B)
+ * are available, video.ko should be used to handle the device.
+ *
+ * Otherwise vendor specific drivers like thinkpad_acpi, asus_acpi,
+ * sony_acpi,... can take care about backlight brightness and display output
+ * switching.
+ *
+ * If CONFIG_ACPI_VIDEO is neither set as "compiled in" (y) nor as a module (m)
+ * this file will not be compiled, acpi_video_get_capabilities() and
+ * acpi_video_backlight_support() will always return 0 and vendor specific
+ * drivers always can handle backlight.
+ *
+ */
+
+#include <linux/acpi.h>
+#include <linux/dmi.h>
+
+ACPI_MODULE_NAME("video");
+#define _COMPONENT ACPI_VIDEO_COMPONENT
+
+static long acpi_video_support;
+static bool acpi_video_caps_checked;
+
+static acpi_status
+acpi_backlight_cap_match(acpi_handle handle, u32 level, void *context,
+ void **retyurn_value)
+{
+ long *cap = context;
+ acpi_handle h_dummy;
+
+ if (ACPI_SUCCESS(acpi_get_handle(handle, "_BCM", &h_dummy)) &&
+ ACPI_SUCCESS(acpi_get_handle(handle, "_BCL", &h_dummy))) {
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found generic backlight "
+ "support\n"));
+ *cap |= ACPI_VIDEO_BACKLIGHT;
+ /* We have backlight support, no need to scan further */
+ return AE_CTRL_TERMINATE;
+ }
+ return 0;
+}
+
+/* Returns true if the device is a video device which can be handled by
+ * video.ko.
+ * The device will get a Linux specific CID added in scan.c to
+ * identify the device as an ACPI graphics device
+ * Be aware that the graphics device may not be physically present
+ * Use acpi_video_get_capabilities() to detect general ACPI video
+ * capabilities of present cards
+ */
+long acpi_is_video_device(struct acpi_device *device)
+{
+ acpi_handle h_dummy;
+ long video_caps = 0;
+
+ if (!device)
+ return 0;
+
+ /* Does this device able to support video switching ? */
+ if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOD", &h_dummy)) &&
+ ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOS", &h_dummy)))
+ video_caps |= ACPI_VIDEO_OUTPUT_SWITCHING;
+
+ /* Does this device able to retrieve a video ROM ? */
+ if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_ROM", &h_dummy)))
+ video_caps |= ACPI_VIDEO_ROM_AVAILABLE;
+
+ /* Does this device able to configure which video head to be POSTed ? */
+ if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_VPO", &h_dummy)) &&
+ ACPI_SUCCESS(acpi_get_handle(device->handle, "_GPD", &h_dummy)) &&
+ ACPI_SUCCESS(acpi_get_handle(device->handle, "_SPD", &h_dummy)))
+ video_caps |= ACPI_VIDEO_DEVICE_POSTING;
+
+ /* Only check for backlight functionality if one of the above hit. */
+ if (video_caps)
+ acpi_walk_namespace(ACPI_TYPE_DEVICE, device->handle,
+ ACPI_UINT32_MAX, acpi_backlight_cap_match,
+ &video_caps, NULL);
+
+ return video_caps;
+}
+EXPORT_SYMBOL(acpi_is_video_device);
+
+static acpi_status
+find_video(acpi_handle handle, u32 lvl, void *context, void **rv)
+{
+ long *cap = context;
+ struct device *dev;
+ struct acpi_device *acpi_dev;
+
+ const struct acpi_device_id video_ids[] = {
+ {ACPI_VIDEO_HID, 0},
+ {"", 0},
+ };
+ if (acpi_bus_get_device(handle, &acpi_dev))
+ return AE_OK;
+
+ if (!acpi_match_device_ids(acpi_dev, video_ids)) {
+ dev = acpi_get_physical_pci_device(handle);
+ if (!dev)
+ return AE_OK;
+ put_device(dev);
+ *cap |= acpi_is_video_device(acpi_dev);
+ }
+ return AE_OK;
+}
+
+/*
+ * Returns the video capabilities of a specific ACPI graphics device
+ *
+ * if NULL is passed as argument all ACPI devices are enumerated and
+ * all graphics capabilities of physically present devices are
+ * summerized and returned. This is cached and done only once.
+ */
+long acpi_video_get_capabilities(acpi_handle graphics_handle)
+{
+ long caps = 0;
+ struct acpi_device *tmp_dev;
+ acpi_status status;
+
+ if (acpi_video_caps_checked && graphics_handle == NULL)
+ return acpi_video_support;
+
+ if (!graphics_handle) {
+ /* Only do the global walk through all graphics devices once */
+ acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX, find_video,
+ &caps, NULL);
+ /* There might be boot param flags set already... */
+ acpi_video_support |= caps;
+ acpi_video_caps_checked = 1;
+ /* Add blacklists here. Be careful to use the right *DMI* bits
+ * to still be able to override logic via boot params, e.g.:
+ *
+ * if (dmi_name_in_vendors("XY")) {
+ * acpi_video_support |=
+ * ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VENDOR;
+ * acpi_video_support |=
+ * ACPI_VIDEO_BACKLIGHT_DMI_VENDOR;
+ *}
+ */
+ } else {
+ status = acpi_bus_get_device(graphics_handle, &tmp_dev);
+ if (ACPI_FAILURE(status)) {
+ ACPI_EXCEPTION((AE_INFO, status, "Invalid device"));
+ return 0;
+ }
+ acpi_walk_namespace(ACPI_TYPE_DEVICE, graphics_handle,
+ ACPI_UINT32_MAX, find_video,
+ &caps, NULL);
+ }
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "We have 0x%lX video support %s %s\n",
+ graphics_handle ? caps : acpi_video_support,
+ graphics_handle ? "on device " : "in general",
+ graphics_handle ? acpi_device_bid(tmp_dev) : ""));
+ return caps;
+}
+EXPORT_SYMBOL(acpi_video_get_capabilities);
+
+/* Returns true if video.ko can do backlight switching */
+int acpi_video_backlight_support(void)
+{
+ /*
+ * We must check whether the ACPI graphics device is physically plugged
+ * in. Therefore this must be called after binding PCI and ACPI devices
+ */
+ if (!acpi_video_caps_checked)
+ acpi_video_get_capabilities(NULL);
+
+ /* First check for boot param -> highest prio */
+ if (acpi_video_support & ACPI_VIDEO_BACKLIGHT_FORCE_VENDOR)
+ return 0;
+ else if (acpi_video_support & ACPI_VIDEO_BACKLIGHT_FORCE_VIDEO)
+ return 1;
+
+ /* Then check for DMI blacklist -> second highest prio */
+ if (acpi_video_support & ACPI_VIDEO_BACKLIGHT_DMI_VENDOR)
+ return 0;
+ else if (acpi_video_support & ACPI_VIDEO_BACKLIGHT_DMI_VIDEO)
+ return 1;
+
+ /* Then go the default way */
+ return acpi_video_support & ACPI_VIDEO_BACKLIGHT;
+}
+EXPORT_SYMBOL(acpi_video_backlight_support);
+
+/*
+ * Returns true if video.ko can do display output switching.
+ * This does not work well/at all with binary graphics drivers
+ * which disable system io ranges and do it on their own.
+ */
+int acpi_video_display_switch_support(void)
+{
+ if (!acpi_video_caps_checked)
+ acpi_video_get_capabilities(NULL);
+
+ if (acpi_video_support & ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VENDOR)
+ return 0;
+ else if (acpi_video_support & ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VIDEO)
+ return 1;
+
+ if (acpi_video_support & ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VENDOR)
+ return 0;
+ else if (acpi_video_support & ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VIDEO)
+ return 1;
+
+ return acpi_video_support & ACPI_VIDEO_OUTPUT_SWITCHING;
+}
+EXPORT_SYMBOL(acpi_video_display_switch_support);
+
+/*
+ * Use acpi_display_output=vendor/video or acpi_backlight=vendor/video
+ * To force that backlight or display output switching is processed by vendor
+ * specific acpi drivers or video.ko driver.
+ */
+int __init acpi_backlight(char *str)
+{
+ if (str == NULL || *str == '\0')
+ return 1;
+ else {
+ if (!strcmp("vendor", str))
+ acpi_video_support |=
+ ACPI_VIDEO_BACKLIGHT_FORCE_VENDOR;
+ if (!strcmp("video", str))
+ acpi_video_support |=
+ ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VIDEO;
+ }
+ return 1;
+}
+__setup("acpi_backlight=", acpi_backlight);
+
+int __init acpi_display_output(char *str)
+{
+ if (str == NULL || *str == '\0')
+ return 1;
+ else {
+ if (!strcmp("vendor", str))
+ acpi_video_support |=
+ ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VENDOR;
+ if (!strcmp("video", str))
+ acpi_video_support |=
+ ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VIDEO;
+ }
+ return 1;
+}
+__setup("acpi_display_output=", acpi_display_output);
diff --git a/drivers/acpi/wmi.c b/drivers/acpi/wmi.c
index 47cd7baf9b1..8a8b377712c 100644
--- a/drivers/acpi/wmi.c
+++ b/drivers/acpi/wmi.c
@@ -660,7 +660,7 @@ static void acpi_wmi_notify(acpi_handle handle, u32 event, void *data)
wblock->handler(event, wblock->handler_data);
acpi_bus_generate_netlink_event(
- device->pnp.device_class, device->dev.bus_id,
+ device->pnp.device_class, dev_name(&device->dev),
event, 0);
break;
}
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 78fbec8ceda..421b7c71e72 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -153,7 +153,7 @@ config SATA_PROMISE
If unsure, say N.
config SATA_SX4
- tristate "Promise SATA SX4 support"
+ tristate "Promise SATA SX4 support (Experimental)"
depends on PCI && EXPERIMENTAL
help
This option enables support for Promise Serial ATA SX4.
@@ -219,8 +219,8 @@ config PATA_ACPI
otherwise unsupported hardware.
config PATA_ALI
- tristate "ALi PATA support (Experimental)"
- depends on PCI && EXPERIMENTAL
+ tristate "ALi PATA support"
+ depends on PCI
help
This option enables support for the ALi ATA interfaces
found on the many ALi chipsets.
@@ -263,7 +263,7 @@ config PATA_ATIIXP
If unsure, say N.
config PATA_CMD640_PCI
- tristate "CMD640 PCI PATA support (Very Experimental)"
+ tristate "CMD640 PCI PATA support (Experimental)"
depends on PCI && EXPERIMENTAL
help
This option enables support for the CMD640 PCI IDE
@@ -291,8 +291,8 @@ config PATA_CS5520
If unsure, say N.
config PATA_CS5530
- tristate "CS5530 PATA support (Experimental)"
- depends on PCI && EXPERIMENTAL
+ tristate "CS5530 PATA support"
+ depends on PCI
help
This option enables support for the Cyrix/NatSemi/AMD CS5530
companion chip used with the MediaGX/Geode processor family.
@@ -309,8 +309,8 @@ config PATA_CS5535
If unsure, say N.
config PATA_CS5536
- tristate "CS5536 PATA support (Experimental)"
- depends on PCI && X86 && !X86_64 && EXPERIMENTAL
+ tristate "CS5536 PATA support"
+ depends on PCI && X86 && !X86_64
help
This option enables support for the AMD CS5536
companion chip used with the Geode LX processor family.
@@ -363,7 +363,7 @@ config PATA_HPT37X
If unsure, say N.
config PATA_HPT3X2N
- tristate "HPT 372N/302N PATA support (Very Experimental)"
+ tristate "HPT 372N/302N PATA support (Experimental)"
depends on PCI && EXPERIMENTAL
help
This option enables support for the N variant HPT PATA
@@ -389,8 +389,8 @@ config PATA_HPT3X3_DMA
problems with DMA on this chipset.
config PATA_ISAPNP
- tristate "ISA Plug and Play PATA support (Experimental)"
- depends on EXPERIMENTAL && ISAPNP
+ tristate "ISA Plug and Play PATA support"
+ depends on ISAPNP
help
This option enables support for ISA plug & play ATA
controllers such as those found on old soundcards.
@@ -498,8 +498,8 @@ config PATA_NINJA32
If unsure, say N.
config PATA_NS87410
- tristate "Nat Semi NS87410 PATA support (Experimental)"
- depends on PCI && EXPERIMENTAL
+ tristate "Nat Semi NS87410 PATA support"
+ depends on PCI
help
This option enables support for the National Semiconductor
NS87410 PCI-IDE controller.
@@ -507,8 +507,8 @@ config PATA_NS87410
If unsure, say N.
config PATA_NS87415
- tristate "Nat Semi NS87415 PATA support (Experimental)"
- depends on PCI && EXPERIMENTAL
+ tristate "Nat Semi NS87415 PATA support"
+ depends on PCI
help
This option enables support for the National Semiconductor
NS87415 PCI-IDE controller.
@@ -544,8 +544,8 @@ config PATA_PCMCIA
If unsure, say N.
config PATA_PDC_OLD
- tristate "Older Promise PATA controller support (Experimental)"
- depends on PCI && EXPERIMENTAL
+ tristate "Older Promise PATA controller support"
+ depends on PCI
help
This option enables support for the Promise 20246, 20262, 20263,
20265 and 20267 adapters.
@@ -559,7 +559,7 @@ config PATA_QDI
Support for QDI 6500 and 6580 PATA controllers on VESA local bus.
config PATA_RADISYS
- tristate "RADISYS 82600 PATA support (Very Experimental)"
+ tristate "RADISYS 82600 PATA support (Experimental)"
depends on PCI && EXPERIMENTAL
help
This option enables support for the RADISYS 82600
@@ -586,8 +586,8 @@ config PATA_RZ1000
If unsure, say N.
config PATA_SC1200
- tristate "SC1200 PATA support (Very Experimental)"
- depends on PCI && EXPERIMENTAL
+ tristate "SC1200 PATA support"
+ depends on PCI
help
This option enables support for the NatSemi/AMD SC1200 SoC
companion chip used with the Geode processor family.
@@ -620,8 +620,8 @@ config PATA_SIL680
If unsure, say N.
config PATA_SIS
- tristate "SiS PATA support (Experimental)"
- depends on PCI && EXPERIMENTAL
+ tristate "SiS PATA support"
+ depends on PCI
help
This option enables support for SiS PATA controllers
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index 8e37be19bbf..c11936e13dd 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -1066,6 +1066,28 @@ static int piix_broken_suspend(void)
if (dmi_find_device(DMI_DEV_TYPE_OEM_STRING, oemstrs[i], NULL))
return 1;
+ /* TECRA M4 sometimes forgets its identify and reports bogus
+ * DMI information. As the bogus information is a bit
+ * generic, match as many entries as possible. This manual
+ * matching is necessary because dmi_system_id.matches is
+ * limited to four entries.
+ */
+ if (dmi_get_system_info(DMI_SYS_VENDOR) &&
+ dmi_get_system_info(DMI_PRODUCT_NAME) &&
+ dmi_get_system_info(DMI_PRODUCT_VERSION) &&
+ dmi_get_system_info(DMI_PRODUCT_SERIAL) &&
+ dmi_get_system_info(DMI_BOARD_VENDOR) &&
+ dmi_get_system_info(DMI_BOARD_NAME) &&
+ dmi_get_system_info(DMI_BOARD_VERSION) &&
+ !strcmp(dmi_get_system_info(DMI_SYS_VENDOR), "TOSHIBA") &&
+ !strcmp(dmi_get_system_info(DMI_PRODUCT_NAME), "000000") &&
+ !strcmp(dmi_get_system_info(DMI_PRODUCT_VERSION), "000000") &&
+ !strcmp(dmi_get_system_info(DMI_PRODUCT_SERIAL), "000000") &&
+ !strcmp(dmi_get_system_info(DMI_BOARD_VENDOR), "TOSHIBA") &&
+ !strcmp(dmi_get_system_info(DMI_BOARD_NAME), "Portable PC") &&
+ !strcmp(dmi_get_system_info(DMI_BOARD_VERSION), "Version A0"))
+ return 1;
+
return 0;
}
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 4214bfb13bb..bc6695e3c84 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -2492,6 +2492,13 @@ int ata_dev_configure(struct ata_device *dev)
}
}
+ if ((dev->horkage & ATA_HORKAGE_FIRMWARE_WARN) && print_info) {
+ ata_dev_printk(dev, KERN_WARNING, "WARNING: device requires "
+ "firmware update to be fully functional.\n");
+ ata_dev_printk(dev, KERN_WARNING, " contact the vendor "
+ "or visit http://ata.wiki.kernel.org.\n");
+ }
+
return 0;
err_out_nosup:
@@ -4042,6 +4049,73 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
{ "ST380817AS", "3.42", ATA_HORKAGE_NONCQ },
{ "ST3160023AS", "3.42", ATA_HORKAGE_NONCQ },
+ /* Seagate NCQ + FLUSH CACHE firmware bug */
+ { "ST31500341AS", "SD15", ATA_HORKAGE_NONCQ |
+ ATA_HORKAGE_FIRMWARE_WARN },
+ { "ST31500341AS", "SD16", ATA_HORKAGE_NONCQ |
+ ATA_HORKAGE_FIRMWARE_WARN },
+ { "ST31500341AS", "SD17", ATA_HORKAGE_NONCQ |
+ ATA_HORKAGE_FIRMWARE_WARN },
+ { "ST31500341AS", "SD18", ATA_HORKAGE_NONCQ |
+ ATA_HORKAGE_FIRMWARE_WARN },
+ { "ST31500341AS", "SD19", ATA_HORKAGE_NONCQ |
+ ATA_HORKAGE_FIRMWARE_WARN },
+
+ { "ST31000333AS", "SD15", ATA_HORKAGE_NONCQ |
+ ATA_HORKAGE_FIRMWARE_WARN },
+ { "ST31000333AS", "SD16", ATA_HORKAGE_NONCQ |
+ ATA_HORKAGE_FIRMWARE_WARN },
+ { "ST31000333AS", "SD17", ATA_HORKAGE_NONCQ |
+ ATA_HORKAGE_FIRMWARE_WARN },
+ { "ST31000333AS", "SD18", ATA_HORKAGE_NONCQ |
+ ATA_HORKAGE_FIRMWARE_WARN },
+ { "ST31000333AS", "SD19", ATA_HORKAGE_NONCQ |
+ ATA_HORKAGE_FIRMWARE_WARN },
+
+ { "ST3640623AS", "SD15", ATA_HORKAGE_NONCQ |
+ ATA_HORKAGE_FIRMWARE_WARN },
+ { "ST3640623AS", "SD16", ATA_HORKAGE_NONCQ |
+ ATA_HORKAGE_FIRMWARE_WARN },
+ { "ST3640623AS", "SD17", ATA_HORKAGE_NONCQ |
+ ATA_HORKAGE_FIRMWARE_WARN },
+ { "ST3640623AS", "SD18", ATA_HORKAGE_NONCQ |
+ ATA_HORKAGE_FIRMWARE_WARN },
+ { "ST3640623AS", "SD19", ATA_HORKAGE_NONCQ |
+ ATA_HORKAGE_FIRMWARE_WARN },
+
+ { "ST3640323AS", "SD15", ATA_HORKAGE_NONCQ |
+ ATA_HORKAGE_FIRMWARE_WARN },
+ { "ST3640323AS", "SD16", ATA_HORKAGE_NONCQ |
+ ATA_HORKAGE_FIRMWARE_WARN },
+ { "ST3640323AS", "SD17", ATA_HORKAGE_NONCQ |
+ ATA_HORKAGE_FIRMWARE_WARN },
+ { "ST3640323AS", "SD18", ATA_HORKAGE_NONCQ |
+ ATA_HORKAGE_FIRMWARE_WARN },
+ { "ST3640323AS", "SD19", ATA_HORKAGE_NONCQ |
+ ATA_HORKAGE_FIRMWARE_WARN },
+
+ { "ST3320813AS", "SD15", ATA_HORKAGE_NONCQ |
+ ATA_HORKAGE_FIRMWARE_WARN },
+ { "ST3320813AS", "SD16", ATA_HORKAGE_NONCQ |
+ ATA_HORKAGE_FIRMWARE_WARN },
+ { "ST3320813AS", "SD17", ATA_HORKAGE_NONCQ |
+ ATA_HORKAGE_FIRMWARE_WARN },
+ { "ST3320813AS", "SD18", ATA_HORKAGE_NONCQ |
+ ATA_HORKAGE_FIRMWARE_WARN },
+ { "ST3320813AS", "SD19", ATA_HORKAGE_NONCQ |
+ ATA_HORKAGE_FIRMWARE_WARN },
+
+ { "ST3320613AS", "SD15", ATA_HORKAGE_NONCQ |
+ ATA_HORKAGE_FIRMWARE_WARN },
+ { "ST3320613AS", "SD16", ATA_HORKAGE_NONCQ |
+ ATA_HORKAGE_FIRMWARE_WARN },
+ { "ST3320613AS", "SD17", ATA_HORKAGE_NONCQ |
+ ATA_HORKAGE_FIRMWARE_WARN },
+ { "ST3320613AS", "SD18", ATA_HORKAGE_NONCQ |
+ ATA_HORKAGE_FIRMWARE_WARN },
+ { "ST3320613AS", "SD19", ATA_HORKAGE_NONCQ |
+ ATA_HORKAGE_FIRMWARE_WARN },
+
/* Blacklist entries taken from Silicon Image 3124/3132
Windows driver .inf file - also several Linux problem reports */
{ "HTS541060G9SA00", "MB3OC60D", ATA_HORKAGE_NONCQ, },
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index 4b473948632..9033d164c4e 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -1227,10 +1227,19 @@ fsm_start:
/* ATA PIO protocol */
if (unlikely((status & ATA_DRQ) == 0)) {
/* handle BSY=0, DRQ=0 as error */
- if (likely(status & (ATA_ERR | ATA_DF)))
+ if (likely(status & (ATA_ERR | ATA_DF))) {
/* device stops HSM for abort/error */
qc->err_mask |= AC_ERR_DEV;
- else {
+
+ /* If diagnostic failed and this is
+ * IDENTIFY, it's likely a phantom
+ * device. Mark hint.
+ */
+ if (qc->dev->horkage &
+ ATA_HORKAGE_DIAGNOSTIC)
+ qc->err_mask |=
+ AC_ERR_NODEV_HINT;
+ } else {
/* HSM violation. Let EH handle this.
* Phantom devices also trigger this
* condition. Mark hint.
diff --git a/drivers/ata/pata_hpt366.c b/drivers/ata/pata_hpt366.c
index f2b83eabc7c..e0c4f05d7d5 100644
--- a/drivers/ata/pata_hpt366.c
+++ b/drivers/ata/pata_hpt366.c
@@ -183,7 +183,9 @@ static unsigned long hpt366_filter(struct ata_device *adev, unsigned long mask)
mask &= ~(0xF8 << ATA_SHIFT_UDMA);
if (hpt_dma_blacklisted(adev, "UDMA4", bad_ata66_4))
mask &= ~(0xF0 << ATA_SHIFT_UDMA);
- }
+ } else if (adev->class == ATA_DEV_ATAPI)
+ mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
+
return ata_bmdma_mode_filter(adev, mask);
}
@@ -211,11 +213,15 @@ static u32 hpt36x_find_mode(struct ata_port *ap, int speed)
static int hpt36x_cable_detect(struct ata_port *ap)
{
- u8 ata66;
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ u8 ata66;
+ /*
+ * Each channel of pata_hpt366 occupies separate PCI function
+ * as the primary channel and bit1 indicates the cable type.
+ */
pci_read_config_byte(pdev, 0x5A, &ata66);
- if (ata66 & (1 << ap->port_no))
+ if (ata66 & 2)
return ATA_CBL_PATA40;
return ATA_CBL_PATA80;
}
@@ -382,10 +388,10 @@ static int hpt36x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
/* PCI clocking determines the ATA timing values to use */
/* info_hpt366 is safe against re-entry so we can scribble on it */
switch((reg1 & 0x700) >> 8) {
- case 5:
+ case 9:
hpriv = &hpt366_40;
break;
- case 9:
+ case 5:
hpriv = &hpt366_25;
break;
default:
diff --git a/drivers/ata/pata_ninja32.c b/drivers/ata/pata_ninja32.c
index 4e466eae8b4..4dd9a3b031e 100644
--- a/drivers/ata/pata_ninja32.c
+++ b/drivers/ata/pata_ninja32.c
@@ -44,7 +44,7 @@
#include <linux/libata.h>
#define DRV_NAME "pata_ninja32"
-#define DRV_VERSION "0.1.1"
+#define DRV_VERSION "0.1.3"
/**
@@ -130,7 +130,8 @@ static int ninja32_init_one(struct pci_dev *dev, const struct pci_device_id *id)
return rc;
pci_set_master(dev);
- /* Set up the register mappings */
+ /* Set up the register mappings. We use the I/O mapping as only the
+ older chips also have MMIO on BAR 1 */
base = host->iomap[0];
if (!base)
return -ENOMEM;
@@ -167,8 +168,12 @@ static int ninja32_reinit_one(struct pci_dev *pdev)
#endif
static const struct pci_device_id ninja32[] = {
+ { 0x10FC, 0x0003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { 0x1145, 0x8008, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { 0x1145, 0xf008, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ 0x1145, 0xf021, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ 0x1145, 0xf024, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { 0x1145, 0xf02C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ },
};
diff --git a/drivers/ata/pata_rb532_cf.c b/drivers/ata/pata_rb532_cf.c
index f8b3ffc8ae9..c2e6fb9f2ef 100644
--- a/drivers/ata/pata_rb532_cf.c
+++ b/drivers/ata/pata_rb532_cf.c
@@ -39,9 +39,11 @@
#define RB500_CF_MAXPORTS 1
#define RB500_CF_IO_DELAY 400
-#define RB500_CF_REG_CMD 0x0800
+#define RB500_CF_REG_BASE 0x0800
+#define RB500_CF_REG_ERR 0x080D
#define RB500_CF_REG_CTRL 0x080E
-#define RB500_CF_REG_DATA 0x0C00
+/* 32bit buffered data register offset */
+#define RB500_CF_REG_DBUF32 0x0C00
struct rb532_cf_info {
void __iomem *iobase;
@@ -72,11 +74,12 @@ static void rb532_pata_exec_command(struct ata_port *ap,
rb532_pata_finish_io(ap);
}
-static void rb532_pata_data_xfer(struct ata_device *adev, unsigned char *buf,
+static unsigned int rb532_pata_data_xfer(struct ata_device *adev, unsigned char *buf,
unsigned int buflen, int write_data)
{
struct ata_port *ap = adev->link->ap;
void __iomem *ioaddr = ap->ioaddr.data_addr;
+ int retlen = buflen;
if (write_data) {
for (; buflen > 0; buflen--, buf++)
@@ -87,6 +90,7 @@ static void rb532_pata_data_xfer(struct ata_device *adev, unsigned char *buf,
}
rb532_pata_finish_io(adev->link->ap);
+ return retlen;
}
static void rb532_pata_freeze(struct ata_port *ap)
@@ -146,13 +150,14 @@ static void rb532_pata_setup_ports(struct ata_host *ah)
ap->pio_mask = 0x1f; /* PIO4 */
ap->flags = ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO;
- ap->ioaddr.cmd_addr = info->iobase + RB500_CF_REG_CMD;
+ ap->ioaddr.cmd_addr = info->iobase + RB500_CF_REG_BASE;
ap->ioaddr.ctl_addr = info->iobase + RB500_CF_REG_CTRL;
ap->ioaddr.altstatus_addr = info->iobase + RB500_CF_REG_CTRL;
ata_sff_std_ports(&ap->ioaddr);
- ap->ioaddr.data_addr = info->iobase + RB500_CF_REG_DATA;
+ ap->ioaddr.data_addr = info->iobase + RB500_CF_REG_DBUF32;
+ ap->ioaddr.error_addr = info->iobase + RB500_CF_REG_ERR;
}
static __devinit int rb532_pata_driver_probe(struct platform_device *pdev)
diff --git a/drivers/ata/pata_sis.c b/drivers/ata/pata_sis.c
index d3423661175..e4be55e047f 100644
--- a/drivers/ata/pata_sis.c
+++ b/drivers/ata/pata_sis.c
@@ -56,7 +56,6 @@ static const struct sis_laptop sis_laptop[] = {
{ 0x5513, 0x1043, 0x1107 }, /* ASUS A6K */
{ 0x5513, 0x1734, 0x105F }, /* FSC Amilo A1630 */
{ 0x5513, 0x1071, 0x8640 }, /* EasyNote K5305 */
- { 0x5513, 0x1039, 0x5513 }, /* Targa Visionary 1000 */
/* end marker */
{ 0, }
};
diff --git a/drivers/atm/horizon.c b/drivers/atm/horizon.c
index 615412364e9..6b969f8c684 100644
--- a/drivers/atm/horizon.c
+++ b/drivers/atm/horizon.c
@@ -2705,7 +2705,7 @@ static int __devinit hrz_probe(struct pci_dev *pci_dev, const struct pci_device_
/* XXX DEV_LABEL is a guess */
if (!request_region(iobase, HRZ_IO_EXTENT, DEV_LABEL)) {
- return -EINVAL;
+ err = -EINVAL;
goto out_disable;
}
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index 61ad8d639ba..0344a8a8321 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -21,7 +21,8 @@ config BLK_DEV_FD
---help---
If you want to use the floppy disk drive(s) of your PC under Linux,
say Y. Information about this driver, especially important for IBM
- Thinkpad users, is contained in <file:Documentation/floppy.txt>.
+ Thinkpad users, is contained in
+ <file:Documentation/blockdev/floppy.txt>.
That file also contains the location of the Floppy driver FAQ as
well as location of the fdutils package used to configure additional
parameters of the driver at run time.
@@ -76,7 +77,7 @@ config PARIDE
your computer's parallel port. Most of them are actually IDE devices
using a parallel port IDE adapter. This option enables the PARIDE
subsystem which contains drivers for many of these external drives.
- Read <file:Documentation/paride.txt> for more information.
+ Read <file:Documentation/blockdev/paride.txt> for more information.
If you have said Y to the "Parallel-port support" configuration
option, you may share a single port between your printer and other
@@ -114,9 +115,9 @@ config BLK_CPQ_DA
help
This is the driver for Compaq Smart Array controllers. Everyone
using these boards should say Y here. See the file
- <file:Documentation/cpqarray.txt> for the current list of boards
- supported by this driver, and for further information on the use of
- this driver.
+ <file:Documentation/blockdev/cpqarray.txt> for the current list of
+ boards supported by this driver, and for further information on the
+ use of this driver.
config BLK_CPQ_CISS_DA
tristate "Compaq Smart Array 5xxx support"
@@ -124,7 +125,7 @@ config BLK_CPQ_CISS_DA
help
This is the driver for Compaq Smart Array 5xxx controllers.
Everyone using these boards should say Y here.
- See <file:Documentation/cciss.txt> for the current list of
+ See <file:Documentation/blockdev/cciss.txt> for the current list of
boards supported by this driver, and for further information
on the use of this driver.
@@ -135,7 +136,7 @@ config CISS_SCSI_TAPE
help
When enabled (Y), this option allows SCSI tape drives and SCSI medium
changers (tape robots) to be accessed via a Compaq 5xxx array
- controller. (See <file:Documentation/cciss.txt> for more details.)
+ controller. (See <file:Documentation/blockdev/cciss.txt> for more details.)
"SCSI support" and "SCSI tape support" must also be enabled for this
option to work.
@@ -149,8 +150,8 @@ config BLK_DEV_DAC960
help
This driver adds support for the Mylex DAC960, AcceleRAID, and
eXtremeRAID PCI RAID controllers. See the file
- <file:Documentation/README.DAC960> for further information about
- this driver.
+ <file:Documentation/blockdev/README.DAC960> for further information
+ about this driver.
To compile this driver as a module, choose M here: the
module will be called DAC960.
@@ -278,9 +279,9 @@ config BLK_DEV_NBD
userland (making server and client physically the same computer,
communicating using the loopback network device).
- Read <file:Documentation/nbd.txt> for more information, especially
- about where to find the server code, which runs in user space and
- does not need special kernel support.
+ Read <file:Documentation/blockdev/nbd.txt> for more information,
+ especially about where to find the server code, which runs in user
+ space and does not need special kernel support.
Note that this has nothing to do with the network file systems NFS
or Coda; you can say N here even if you intend to use NFS or Coda.
@@ -321,8 +322,8 @@ config BLK_DEV_RAM
store a copy of a minimal root file system off of a floppy into RAM
during the initial install of Linux.
- Note that the kernel command line option "ramdisk=XX" is now
- obsolete. For details, read <file:Documentation/ramdisk.txt>.
+ Note that the kernel command line option "ramdisk=XX" is now obsolete.
+ For details, read <file:Documentation/blockdev/ramdisk.txt>.
To compile this driver as a module, choose M here: the
module will be called rd.
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 12de1fdaa6c..9f7c543cc04 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -1693,6 +1693,11 @@ static int rebuild_lun_table(ctlr_info_t *h, int first_time)
for (i = 0; i <= h->highest_lun; i++) {
int j;
drv_found = 0;
+
+ /* skip holes in the array from already deleted drives */
+ if (h->drv[i].raid_level == -1)
+ continue;
+
for (j = 0; j < num_luns; j++) {
memcpy(&lunid, &ld_buff->LUN[j][0], 4);
lunid = le32_to_cpu(lunid);
@@ -2847,7 +2852,7 @@ static void do_cciss_request(struct request_queue *q)
h->maxSG = seg;
#ifdef CCISS_DEBUG
- printk(KERN_DEBUG "cciss: Submitting %d sectors in %d segments\n",
+ printk(KERN_DEBUG "cciss: Submitting %lu sectors in %d segments\n",
creq->nr_sectors, seg);
#endif /* CCISS_DEBUG */
@@ -3197,7 +3202,7 @@ static int __devinit cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
c->paddr = pci_resource_start(pdev, 0); /* addressing mode bits already removed */
#ifdef CCISS_DEBUG
- printk("address 0 = %x\n", c->paddr);
+ printk("address 0 = %lx\n", c->paddr);
#endif /* CCISS_DEBUG */
c->vaddr = remap_pci_mem(c->paddr, 0x250);
@@ -3224,7 +3229,8 @@ static int __devinit cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
#endif /* CCISS_DEBUG */
cfg_base_addr_index = find_PCI_BAR_index(pdev, cfg_base_addr);
#ifdef CCISS_DEBUG
- printk("cfg base address index = %x\n", cfg_base_addr_index);
+ printk("cfg base address index = %llx\n",
+ (unsigned long long)cfg_base_addr_index);
#endif /* CCISS_DEBUG */
if (cfg_base_addr_index == -1) {
printk(KERN_WARNING "cciss: Cannot find cfg_base_addr_index\n");
@@ -3234,7 +3240,7 @@ static int __devinit cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
cfg_offset = readl(c->vaddr + SA5_CTMEM_OFFSET);
#ifdef CCISS_DEBUG
- printk("cfg offset = %x\n", cfg_offset);
+ printk("cfg offset = %llx\n", (unsigned long long)cfg_offset);
#endif /* CCISS_DEBUG */
c->cfgtable = remap_pci_mem(pci_resource_start(pdev,
cfg_base_addr_index) +
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 14db747a636..cf29cc4e6ab 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -4124,7 +4124,7 @@ static int __init floppy_setup(char *str)
printk("\n");
} else
DPRINT("botched floppy option\n");
- DPRINT("Read Documentation/floppy.txt\n");
+ DPRINT("Read Documentation/blockdev/floppy.txt\n");
return 0;
}
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index f20bf359b84..dc7a8c352da 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -302,7 +302,7 @@ static struct kobj_type kobj_pkt_type_wqueue = {
static void pkt_sysfs_dev_new(struct pktcdvd_device *pd)
{
if (class_pktcdvd) {
- pd->dev = device_create(class_pktcdvd, NULL, pd->pkt_dev, NULL,
+ pd->dev = device_create(class_pktcdvd, NULL, MKDEV(0, 0), NULL,
"%s", pd->name);
if (IS_ERR(pd->dev))
pd->dev = NULL;
@@ -2790,7 +2790,7 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev)
return 0;
out_mem:
- blkdev_put(bdev, FMODE_READ|FMODE_WRITE);
+ blkdev_put(bdev, FMODE_READ | FMODE_NDELAY);
/* This is safe: open() is still holding a reference. */
module_put(THIS_MODULE);
return ret;
@@ -2975,7 +2975,7 @@ static int pkt_remove_dev(dev_t pkt_dev)
pkt_debugfs_dev_remove(pd);
pkt_sysfs_dev_remove(pd);
- blkdev_put(pd->bdev, FMODE_READ|FMODE_WRITE);
+ blkdev_put(pd->bdev, FMODE_READ | FMODE_NDELAY);
remove_proc_entry(pd->name, pkt_proc);
DPRINTK(DRIVER_NAME": writer %s unmapped\n", pd->name);
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
index fccac18d311..048d71d244d 100644
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -1546,8 +1546,6 @@ static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd)
/*
* Reset management
- * XXX Move usb_reset_device to khubd. Hogging kevent is not a good thing.
- * XXX Make usb_sync_reset asynchronous.
*/
static void ub_reset_enter(struct ub_dev *sc, int try)
@@ -1633,6 +1631,22 @@ static void ub_reset_task(struct work_struct *work)
}
/*
+ * XXX Reset brackets are too much hassle to implement, so just stub them
+ * in order to prevent forced unbinding (which deadlocks solid when our
+ * ->disconnect method waits for the reset to complete and this kills keventd).
+ *
+ * XXX Tell Alan to move usb_unlock_device inside of usb_reset_device,
+ * or else the post_reset is invoked, and restats I/O on a locked device.
+ */
+static int ub_pre_reset(struct usb_interface *iface) {
+ return 0;
+}
+
+static int ub_post_reset(struct usb_interface *iface) {
+ return 0;
+}
+
+/*
* This is called from a process context.
*/
static void ub_revalidate(struct ub_dev *sc, struct ub_lun *lun)
@@ -2446,6 +2460,8 @@ static struct usb_driver ub_driver = {
.probe = ub_probe,
.disconnect = ub_disconnect,
.id_table = ub_usb_ids,
+ .pre_reset = ub_pre_reset,
+ .post_reset = ub_post_reset,
};
static int __init ub_init(void)
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index b220c686089..2d19f0cc47f 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -338,12 +338,18 @@ wait:
static int xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size)
{
struct request_queue *rq;
+ elevator_t *old_e;
rq = blk_init_queue(do_blkif_request, &blkif_io_lock);
if (rq == NULL)
return -1;
- elevator_init(rq, "noop");
+ old_e = rq->elevator;
+ if (IS_ERR_VALUE(elevator_init(rq, "noop")))
+ printk(KERN_WARNING
+ "blkfront: Switch elevator failed, use default\n");
+ else
+ elevator_exit(old_e);
/* Hard sector size and max sectors impersonate the equiv. hardware. */
blk_queue_hardsect_size(rq, sector_size);
diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c
index ecab9e67d47..29e1dfafb7c 100644
--- a/drivers/block/xsysace.c
+++ b/drivers/block/xsysace.c
@@ -194,7 +194,7 @@ struct ace_device {
int in_irq;
/* Details of hardware device */
- unsigned long physaddr;
+ resource_size_t physaddr;
void __iomem *baseaddr;
int irq;
int bus_width; /* 0 := 8 bit; 1 := 16 bit */
@@ -628,8 +628,8 @@ static void ace_fsm_dostate(struct ace_device *ace)
/* Okay, it's a data request, set it up for transfer */
dev_dbg(ace->dev,
- "request: sec=%lx hcnt=%lx, ccnt=%x, dir=%i\n",
- req->sector, req->hard_nr_sectors,
+ "request: sec=%llx hcnt=%lx, ccnt=%x, dir=%i\n",
+ (unsigned long long) req->sector, req->hard_nr_sectors,
req->current_nr_sectors, rq_data_dir(req));
ace->req = req;
@@ -935,7 +935,8 @@ static int __devinit ace_setup(struct ace_device *ace)
int rc;
dev_dbg(ace->dev, "ace_setup(ace=0x%p)\n", ace);
- dev_dbg(ace->dev, "physaddr=0x%lx irq=%i\n", ace->physaddr, ace->irq);
+ dev_dbg(ace->dev, "physaddr=0x%llx irq=%i\n",
+ (unsigned long long)ace->physaddr, ace->irq);
spin_lock_init(&ace->lock);
init_completion(&ace->id_completion);
@@ -1017,8 +1018,8 @@ static int __devinit ace_setup(struct ace_device *ace)
/* Print the identification */
dev_info(ace->dev, "Xilinx SystemACE revision %i.%i.%i\n",
(version >> 12) & 0xf, (version >> 8) & 0x0f, version & 0xff);
- dev_dbg(ace->dev, "physaddr 0x%lx, mapped to 0x%p, irq=%i\n",
- ace->physaddr, ace->baseaddr, ace->irq);
+ dev_dbg(ace->dev, "physaddr 0x%llx, mapped to 0x%p, irq=%i\n",
+ (unsigned long long) ace->physaddr, ace->baseaddr, ace->irq);
ace->media_change = 1;
ace_revalidate_disk(ace->gd);
@@ -1035,8 +1036,8 @@ err_alloc_disk:
err_blk_initq:
iounmap(ace->baseaddr);
err_ioremap:
- dev_info(ace->dev, "xsysace: error initializing device at 0x%lx\n",
- ace->physaddr);
+ dev_info(ace->dev, "xsysace: error initializing device at 0x%llx\n",
+ (unsigned long long) ace->physaddr);
return -ENOMEM;
}
@@ -1059,7 +1060,7 @@ static void __devexit ace_teardown(struct ace_device *ace)
}
static int __devinit
-ace_alloc(struct device *dev, int id, unsigned long physaddr,
+ace_alloc(struct device *dev, int id, resource_size_t physaddr,
int irq, int bus_width)
{
struct ace_device *ace;
@@ -1119,7 +1120,7 @@ static void __devexit ace_free(struct device *dev)
static int __devinit ace_probe(struct platform_device *dev)
{
- unsigned long physaddr = 0;
+ resource_size_t physaddr = 0;
int bus_width = ACE_BUS_WIDTH_16; /* FIXME: should not be hard coded */
int id = dev->id;
int irq = NO_IRQ;
@@ -1165,7 +1166,7 @@ static int __devinit
ace_of_probe(struct of_device *op, const struct of_device_id *match)
{
struct resource res;
- unsigned long physaddr;
+ resource_size_t physaddr;
const u32 *id;
int irq, bus_width, rc;
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index d16b02423d6..7d2e91cccb1 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -2081,10 +2081,6 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf,
if (!q)
return -ENXIO;
- rq = blk_get_request(q, READ, GFP_KERNEL);
- if (!rq)
- return -ENOMEM;
-
cdi->last_sense = 0;
while (nframes) {
@@ -2096,9 +2092,17 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf,
len = nr * CD_FRAMESIZE_RAW;
+ rq = blk_get_request(q, READ, GFP_KERNEL);
+ if (!rq) {
+ ret = -ENOMEM;
+ break;
+ }
+
ret = blk_rq_map_user(q, rq, NULL, ubuf, len, GFP_KERNEL);
- if (ret)
+ if (ret) {
+ blk_put_request(rq);
break;
+ }
rq->cmd[0] = GPCMD_READ_CD;
rq->cmd[1] = 1 << 2;
@@ -2124,6 +2128,7 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf,
if (blk_rq_unmap_user(bio))
ret = -EFAULT;
+ blk_put_request(rq);
if (ret)
break;
@@ -2133,7 +2138,6 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf,
ubuf += len;
}
- blk_put_request(rq);
return ret;
}
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 43b35d0369d..43d6ba83a19 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -124,7 +124,7 @@ config COMPUTONE
which give you many serial ports. You would need something like this
to connect more than two modems to your Linux box, for instance in
order to become a dial-in server. If you have a card like that, say
- Y here and read <file:Documentation/computone.txt>.
+ Y here and read <file:Documentation/serial/computone.txt>.
To compile this driver as module, choose M here: the
module will be called ip2.
@@ -136,7 +136,7 @@ config ROCKETPORT
This driver supports Comtrol RocketPort and RocketModem PCI boards.
These boards provide 2, 4, 8, 16, or 32 high-speed serial ports or
modems. For information about the RocketPort/RocketModem boards
- and this driver read <file:Documentation/rocket.txt>.
+ and this driver read <file:Documentation/serial/rocket.txt>.
To compile this driver as a module, choose M here: the
module will be called rocket.
@@ -154,7 +154,7 @@ config CYCLADES
your Linux box, for instance in order to become a dial-in server.
For information about the Cyclades-Z card, read
- <file:Documentation/README.cycladesZ>.
+ <file:Documentation/serial/README.cycladesZ>.
To compile this driver as a module, choose M here: the
module will be called cyclades.
@@ -183,7 +183,7 @@ config DIGIEPCA
box, for instance in order to become a dial-in server. This driver
supports the original PC (ISA) boards as well as PCI, and EISA. If
you have a card like this, say Y here and read the file
- <file:Documentation/digiepca.txt>.
+ <file:Documentation/serial/digiepca.txt>.
To compile this driver as a module, choose M here: the
module will be called epca.
@@ -289,7 +289,7 @@ config RISCOM8
which gives you many serial ports. You would need something like
this to connect more than two modems to your Linux box, for instance
in order to become a dial-in server. If you have a card like that,
- say Y here and read the file <file:Documentation/riscom8.txt>.
+ say Y here and read the file <file:Documentation/serial/riscom8.txt>.
Also it's possible to say M here and compile this driver as kernel
loadable module; the module will be called riscom8.
@@ -304,8 +304,8 @@ config SPECIALIX
your Linux box, for instance in order to become a dial-in server.
If you have a card like that, say Y here and read the file
- <file:Documentation/specialix.txt>. Also it's possible to say M here
- and compile this driver as kernel loadable module which will be
+ <file:Documentation/serial/specialix.txt>. Also it's possible to say
+ M here and compile this driver as kernel loadable module which will be
called specialix.
config SX
@@ -313,7 +313,7 @@ config SX
depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA)
help
This is a driver for the SX and SI multiport serial cards.
- Please read the file <file:Documentation/sx.txt> for details.
+ Please read the file <file:Documentation/serial/sx.txt> for details.
This driver can only be built as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
@@ -344,8 +344,8 @@ config STALDRV
like this to connect more than two modems to your Linux box, for
instance in order to become a dial-in server. If you say Y here,
you will be asked for your specific card model in the next
- questions. Make sure to read <file:Documentation/stallion.txt> in
- this case. If you have never heard about all this, it's safe to
+ questions. Make sure to read <file:Documentation/serial/stallion.txt>
+ in this case. If you have never heard about all this, it's safe to
say N.
config STALLION
@@ -354,7 +354,7 @@ config STALLION
help
If you have an EasyIO or EasyConnection 8/32 multiport Stallion
card, then this is for you; say Y. Make sure to read
- <file:Documentation/stallion.txt>.
+ <file:Documentation/serial/stallion.txt>.
To compile this driver as a module, choose M here: the
module will be called stallion.
@@ -365,7 +365,7 @@ config ISTALLION
help
If you have an EasyConnection 8/64, ONboard, Brumby or Stallion
serial multiport card, say Y here. Make sure to read
- <file:Documentation/stallion.txt>.
+ <file:Documentation/serial/stallion.txt>.
To compile this driver as a module, choose M here: the
module will be called istallion.
diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c
index 0f004b65ec0..03f95ec08f5 100644
--- a/drivers/char/agp/uninorth-agp.c
+++ b/drivers/char/agp/uninorth-agp.c
@@ -27,7 +27,7 @@
static int uninorth_rev;
static int is_u3;
-static char __devinitdata *aperture = NULL;
+static char *aperture = NULL;
static int uninorth_fetch_size(void)
{
diff --git a/drivers/char/cp437.uni b/drivers/char/cp437.uni
index 1f06889a96b..bc6163484f6 100644
--- a/drivers/char/cp437.uni
+++ b/drivers/char/cp437.uni
@@ -27,7 +27,7 @@
0x0c U+2640
0x0d U+266a
0x0e U+266b
-0x0f U+263c
+0x0f U+263c U+00a4
0x10 U+25b6 U+25ba
0x11 U+25c0 U+25c4
0x12 U+2195
@@ -55,7 +55,7 @@
0x24 U+0024
0x25 U+0025
0x26 U+0026
-0x27 U+0027
+0x27 U+0027 U+00b4
0x28 U+0028
0x29 U+0029
0x2a U+002a
@@ -84,7 +84,7 @@
0x41 U+0041 U+00c0 U+00c1 U+00c2 U+00c3
0x42 U+0042
0x43 U+0043 U+00a9
-0x44 U+0044
+0x44 U+0044 U+00d0
0x45 U+0045 U+00c8 U+00ca U+00cb
0x46 U+0046
0x47 U+0047
@@ -140,7 +140,7 @@
0x79 U+0079 U+00fd
0x7a U+007a
0x7b U+007b
-0x7c U+007c U+00a5
+0x7c U+007c U+00a6
0x7d U+007d
0x7e U+007e
#
@@ -263,10 +263,10 @@
0xe8 U+03a6 U+00d8
0xe9 U+0398
0xea U+03a9 U+2126
-0xeb U+03b4
+0xeb U+03b4 U+00f0
0xec U+221e
0xed U+03c6 U+00f8
-0xee U+03b5
+0xee U+03b5 U+2208
0xef U+2229
0xf0 U+2261
0xf1 U+00b1
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index 8a59aaa21be..7a88dfd4427 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -422,9 +422,11 @@ struct ipmi_smi {
/**
* The driver model view of the IPMI messaging driver.
*/
-static struct device_driver ipmidriver = {
- .name = "ipmi",
- .bus = &platform_bus_type
+static struct platform_driver ipmidriver = {
+ .driver = {
+ .name = "ipmi",
+ .bus = &platform_bus_type
+ }
};
static DEFINE_MUTEX(ipmidriver_mutex);
@@ -2384,9 +2386,9 @@ static int ipmi_bmc_register(ipmi_smi_t intf, int ifnum,
* representing the interfaced BMC already
*/
if (bmc->guid_set)
- old_bmc = ipmi_find_bmc_guid(&ipmidriver, bmc->guid);
+ old_bmc = ipmi_find_bmc_guid(&ipmidriver.driver, bmc->guid);
else
- old_bmc = ipmi_find_bmc_prod_dev_id(&ipmidriver,
+ old_bmc = ipmi_find_bmc_prod_dev_id(&ipmidriver.driver,
bmc->id.product_id,
bmc->id.device_id);
@@ -2416,7 +2418,7 @@ static int ipmi_bmc_register(ipmi_smi_t intf, int ifnum,
snprintf(name, sizeof(name),
"ipmi_bmc.%4.4x", bmc->id.product_id);
- while (ipmi_find_bmc_prod_dev_id(&ipmidriver,
+ while (ipmi_find_bmc_prod_dev_id(&ipmidriver.driver,
bmc->id.product_id,
bmc->id.device_id)) {
if (!warn_printed) {
@@ -2446,7 +2448,7 @@ static int ipmi_bmc_register(ipmi_smi_t intf, int ifnum,
" Unable to allocate platform device\n");
return -ENOMEM;
}
- bmc->dev->dev.driver = &ipmidriver;
+ bmc->dev->dev.driver = &ipmidriver.driver;
dev_set_drvdata(&bmc->dev->dev, bmc);
kref_init(&bmc->refcount);
@@ -4247,7 +4249,7 @@ static int ipmi_init_msghandler(void)
if (initialized)
return 0;
- rv = driver_register(&ipmidriver);
+ rv = driver_register(&ipmidriver.driver);
if (rv) {
printk(KERN_ERR PFX "Could not register IPMI driver\n");
return rv;
@@ -4308,7 +4310,7 @@ static __exit void cleanup_ipmi(void)
remove_proc_entry(proc_ipmi_root->name, NULL);
#endif /* CONFIG_PROC_FS */
- driver_unregister(&ipmidriver);
+ driver_unregister(&ipmidriver.driver);
initialized = 0;
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 3123bf57ad9..3000135f2ea 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -114,9 +114,11 @@ static char *si_to_str[] = { "kcs", "smic", "bt" };
#define DEVICE_NAME "ipmi_si"
-static struct device_driver ipmi_driver = {
- .name = DEVICE_NAME,
- .bus = &platform_bus_type
+static struct platform_driver ipmi_driver = {
+ .driver = {
+ .name = DEVICE_NAME,
+ .bus = &platform_bus_type
+ }
};
@@ -2868,7 +2870,7 @@ static int try_smi_init(struct smi_info *new_smi)
goto out_err;
}
new_smi->dev = &new_smi->pdev->dev;
- new_smi->dev->driver = &ipmi_driver;
+ new_smi->dev->driver = &ipmi_driver.driver;
rv = platform_device_add(new_smi->pdev);
if (rv) {
@@ -2983,7 +2985,7 @@ static __devinit int init_ipmi_si(void)
initialized = 1;
/* Register the device drivers. */
- rv = driver_register(&ipmi_driver);
+ rv = driver_register(&ipmi_driver.driver);
if (rv) {
printk(KERN_ERR
"init_ipmi_si: Unable to register driver: %d\n",
@@ -3052,7 +3054,7 @@ static __devinit int init_ipmi_si(void)
#ifdef CONFIG_PPC_OF
of_unregister_platform_driver(&ipmi_of_platform_driver);
#endif
- driver_unregister(&ipmi_driver);
+ driver_unregister(&ipmi_driver.driver);
printk(KERN_WARNING
"ipmi_si: Unable to find any System Interface(s)\n");
return -ENODEV;
@@ -3151,7 +3153,7 @@ static __exit void cleanup_ipmi_si(void)
cleanup_one_si(e);
mutex_unlock(&smi_infos_lock);
- driver_unregister(&ipmi_driver);
+ driver_unregister(&ipmi_driver.driver);
}
module_exit(cleanup_ipmi_si);
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index 44e5d60f517..4b10770fa93 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -3739,7 +3739,7 @@ static int stli_getbrdnr(void)
* do is go probing around in the usual places hoping we can find it.
*/
-static int stli_findeisabrds(void)
+static int __init stli_findeisabrds(void)
{
struct stlibrd *brdp;
unsigned int iobase, eid, i;
@@ -3935,7 +3935,7 @@ static struct stlibrd *stli_allocbrd(void)
* can find.
*/
-static int stli_initbrds(void)
+static int __init stli_initbrds(void)
{
struct stlibrd *brdp, *nxtbrdp;
struct stlconf conf;
diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c
index 3b23270eaa6..a8f15e6be59 100644
--- a/drivers/char/serial167.c
+++ b/drivers/char/serial167.c
@@ -418,7 +418,7 @@ static irqreturn_t cd2401_rxerr_interrupt(int irq, void *dev_id)
TTY_OVERRUN);
/*
If the flip buffer itself is
- overflowing, we still loose
+ overflowing, we still lose
the next incoming character.
*/
if (tty_buffer_request_room(tty, 1) !=
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
index 2457b07dabd..f4374437a03 100644
--- a/drivers/char/sonypi.c
+++ b/drivers/char/sonypi.c
@@ -523,7 +523,7 @@ static int acpi_driver_registered;
static int sonypi_ec_write(u8 addr, u8 value)
{
-#ifdef CONFIG_ACPI_EC
+#ifdef CONFIG_ACPI
if (SONYPI_ACPI_ACTIVE)
return ec_write(addr, value);
#endif
@@ -539,7 +539,7 @@ static int sonypi_ec_write(u8 addr, u8 value)
static int sonypi_ec_read(u8 addr, u8 *value)
{
-#ifdef CONFIG_ACPI_EC
+#ifdef CONFIG_ACPI
if (SONYPI_ACPI_ACTIVE)
return ec_read(addr, value);
#endif
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c
index 242fd46fda2..a16b94f12eb 100644
--- a/drivers/char/specialix.c
+++ b/drivers/char/specialix.c
@@ -72,7 +72,7 @@
/*
* There is a bunch of documentation about the card, jumpers, config
* settings, restrictions, cables, device names and numbers in
- * Documentation/specialix.txt
+ * Documentation/serial/specialix.txt
*/
#include <linux/module.h>
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 59f472143f0..1412a8d1e58 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -1795,12 +1795,15 @@ retry_open:
}
#endif
if (device == MKDEV(TTYAUX_MAJOR, 1)) {
- driver = tty_driver_kref_get(console_device(&index));
- if (driver) {
- /* Don't let /dev/console block */
- filp->f_flags |= O_NONBLOCK;
- noctty = 1;
- goto got_driver;
+ struct tty_driver *console_driver = console_device(&index);
+ if (console_driver) {
+ driver = tty_driver_kref_get(console_driver);
+ if (driver) {
+ /* Don't let /dev/console block */
+ filp->f_flags |= O_NONBLOCK;
+ noctty = 1;
+ goto got_driver;
+ }
}
mutex_unlock(&tty_mutex);
return -ENODEV;
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index a5af6072e2b..008176edbd6 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -2274,7 +2274,7 @@ rescan_last_byte:
continue; /* nothing to display */
}
/* Glyph not found */
- if ((!(vc->vc_utf && !vc->vc_disp_ctrl) || c < 128) && !(c & ~charmask)) {
+ if ((!(vc->vc_utf && !vc->vc_disp_ctrl) && c < 128) && !(c & ~charmask)) {
/* In legacy mode use the glyph we get by a 1:1 mapping.
This would make absolutely no sense with Unicode in mind,
but do this for ASCII characters since a font may lack
diff --git a/drivers/char/xilinx_hwicap/buffer_icap.c b/drivers/char/xilinx_hwicap/buffer_icap.c
index aa7f7962a9a..05d897764f0 100644
--- a/drivers/char/xilinx_hwicap/buffer_icap.c
+++ b/drivers/char/xilinx_hwicap/buffer_icap.c
@@ -21,9 +21,6 @@
* INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE.
*
- * Xilinx products are not intended for use in life support appliances,
- * devices, or systems. Use in such applications is expressly prohibited.
- *
* (c) Copyright 2003-2008 Xilinx Inc.
* All rights reserved.
*
diff --git a/drivers/char/xilinx_hwicap/buffer_icap.h b/drivers/char/xilinx_hwicap/buffer_icap.h
index 8b0252bf06e..d4f419ee87a 100644
--- a/drivers/char/xilinx_hwicap/buffer_icap.h
+++ b/drivers/char/xilinx_hwicap/buffer_icap.h
@@ -21,9 +21,6 @@
* INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE.
*
- * Xilinx products are not intended for use in life support appliances,
- * devices, or systems. Use in such applications is expressly prohibited.
- *
* (c) Copyright 2003-2008 Xilinx Inc.
* All rights reserved.
*
diff --git a/drivers/char/xilinx_hwicap/fifo_icap.c b/drivers/char/xilinx_hwicap/fifo_icap.c
index 776b5052847..02225eb19cf 100644
--- a/drivers/char/xilinx_hwicap/fifo_icap.c
+++ b/drivers/char/xilinx_hwicap/fifo_icap.c
@@ -21,9 +21,6 @@
* INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE.
*
- * Xilinx products are not intended for use in life support appliances,
- * devices, or systems. Use in such applications is expressly prohibited.
- *
* (c) Copyright 2007-2008 Xilinx Inc.
* All rights reserved.
*
diff --git a/drivers/char/xilinx_hwicap/fifo_icap.h b/drivers/char/xilinx_hwicap/fifo_icap.h
index 62bda453c90..4c9dd9a3b62 100644
--- a/drivers/char/xilinx_hwicap/fifo_icap.h
+++ b/drivers/char/xilinx_hwicap/fifo_icap.h
@@ -21,9 +21,6 @@
* INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE.
*
- * Xilinx products are not intended for use in life support appliances,
- * devices, or systems. Use in such applications is expressly prohibited.
- *
* (c) Copyright 2007-2008 Xilinx Inc.
* All rights reserved.
*
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
index ed132fe55d3..f40ab699860 100644
--- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c
+++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
@@ -21,9 +21,6 @@
* INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE.
*
- * Xilinx products are not intended for use in life support appliances,
- * devices, or systems. Use in such applications is expressly prohibited.
- *
* (c) Copyright 2002 Xilinx Inc., Systems Engineering Group
* (c) Copyright 2004 Xilinx Inc., Systems Engineering Group
* (c) Copyright 2007-2008 Xilinx Inc.
@@ -626,7 +623,7 @@ static int __devinit hwicap_setup(struct device *dev, int id,
if (!request_mem_region(drvdata->mem_start,
drvdata->mem_size, DRIVER_NAME)) {
dev_err(dev, "Couldn't lock memory region at %Lx\n",
- regs_res->start);
+ (unsigned long long) regs_res->start);
retval = -EBUSY;
goto failed1;
}
@@ -645,9 +642,10 @@ static int __devinit hwicap_setup(struct device *dev, int id,
mutex_init(&drvdata->sem);
drvdata->is_open = 0;
- dev_info(dev, "ioremap %lx to %p with size %Lx\n",
- (unsigned long int)drvdata->mem_start,
- drvdata->base_address, drvdata->mem_size);
+ dev_info(dev, "ioremap %llx to %p with size %llx\n",
+ (unsigned long long) drvdata->mem_start,
+ drvdata->base_address,
+ (unsigned long long) drvdata->mem_size);
cdev_init(&drvdata->cdev, &hwicap_fops);
drvdata->cdev.owner = THIS_MODULE;
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.h b/drivers/char/xilinx_hwicap/xilinx_hwicap.h
index 24d0d9b938f..8cca11981c5 100644
--- a/drivers/char/xilinx_hwicap/xilinx_hwicap.h
+++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.h
@@ -21,9 +21,6 @@
* INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE.
*
- * Xilinx products are not intended for use in life support appliances,
- * devices, or systems. Use in such applications is expressly prohibited.
- *
* (c) Copyright 2003-2007 Xilinx Inc.
* All rights reserved.
*
diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c
index b6ad3ac5916..24607669a52 100644
--- a/drivers/crypto/talitos.c
+++ b/drivers/crypto/talitos.c
@@ -1357,7 +1357,7 @@ static int hw_supports(struct device *dev, __be32 desc_hdr_template)
return ret;
}
-static int __devexit talitos_remove(struct of_device *ofdev)
+static int talitos_remove(struct of_device *ofdev)
{
struct device *dev = &ofdev->dev;
struct talitos_private *priv = dev_get_drvdata(dev);
@@ -1622,7 +1622,7 @@ static struct of_platform_driver talitos_driver = {
.name = "talitos",
.match_table = talitos_match,
.probe = talitos_probe,
- .remove = __devexit_p(talitos_remove),
+ .remove = talitos_remove,
};
static int __init talitos_init(void)
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index dc003a3a787..65799651737 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -388,7 +388,10 @@ int dma_async_device_register(struct dma_device *device)
init_completion(&device->done);
kref_init(&device->refcount);
+
+ mutex_lock(&dma_list_mutex);
device->dev_id = id++;
+ mutex_unlock(&dma_list_mutex);
/* represent channels in sysfs. Probably want devs too */
list_for_each_entry(chan, &device->channels, device_node) {
@@ -399,8 +402,8 @@ int dma_async_device_register(struct dma_device *device)
chan->chan_id = chancnt++;
chan->dev.class = &dma_devclass;
chan->dev.parent = device->dev;
- snprintf(chan->dev.bus_id, BUS_ID_SIZE, "dma%dchan%d",
- device->dev_id, chan->chan_id);
+ dev_set_name(&chan->dev, "dma%dchan%d",
+ device->dev_id, chan->chan_id);
rc = device_register(&chan->dev);
if (rc) {
diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c
index d1e381e35a9..ed9636bfb54 100644
--- a/drivers/dma/dmatest.c
+++ b/drivers/dma/dmatest.c
@@ -20,11 +20,11 @@ static unsigned int test_buf_size = 16384;
module_param(test_buf_size, uint, S_IRUGO);
MODULE_PARM_DESC(test_buf_size, "Size of the memcpy test buffer");
-static char test_channel[BUS_ID_SIZE];
+static char test_channel[20];
module_param_string(channel, test_channel, sizeof(test_channel), S_IRUGO);
MODULE_PARM_DESC(channel, "Bus ID of the channel to test (default: any)");
-static char test_device[BUS_ID_SIZE];
+static char test_device[20];
module_param_string(device, test_device, sizeof(test_device), S_IRUGO);
MODULE_PARM_DESC(device, "Bus ID of the DMA Engine to test (default: any)");
@@ -80,14 +80,14 @@ static bool dmatest_match_channel(struct dma_chan *chan)
{
if (test_channel[0] == '\0')
return true;
- return strcmp(chan->dev.bus_id, test_channel) == 0;
+ return strcmp(dev_name(&chan->dev), test_channel) == 0;
}
static bool dmatest_match_device(struct dma_device *device)
{
if (test_device[0] == '\0')
return true;
- return strcmp(device->dev->bus_id, test_device) == 0;
+ return strcmp(dev_name(device->dev), test_device) == 0;
}
static unsigned long dmatest_random(void)
@@ -332,7 +332,7 @@ static enum dma_state_client dmatest_add_channel(struct dma_chan *chan)
dtc = kmalloc(sizeof(struct dmatest_chan), GFP_KERNEL);
if (!dtc) {
- pr_warning("dmatest: No memory for %s\n", chan->dev.bus_id);
+ pr_warning("dmatest: No memory for %s\n", dev_name(&chan->dev));
return DMA_NAK;
}
@@ -343,16 +343,16 @@ static enum dma_state_client dmatest_add_channel(struct dma_chan *chan)
thread = kzalloc(sizeof(struct dmatest_thread), GFP_KERNEL);
if (!thread) {
pr_warning("dmatest: No memory for %s-test%u\n",
- chan->dev.bus_id, i);
+ dev_name(&chan->dev), i);
break;
}
thread->chan = dtc->chan;
smp_wmb();
thread->task = kthread_run(dmatest_func, thread, "%s-test%u",
- chan->dev.bus_id, i);
+ dev_name(&chan->dev), i);
if (IS_ERR(thread->task)) {
pr_warning("dmatest: Failed to run thread %s-test%u\n",
- chan->dev.bus_id, i);
+ dev_name(&chan->dev), i);
kfree(thread);
break;
}
@@ -362,7 +362,7 @@ static enum dma_state_client dmatest_add_channel(struct dma_chan *chan)
list_add_tail(&thread->node, &dtc->threads);
}
- pr_info("dmatest: Started %u threads using %s\n", i, chan->dev.bus_id);
+ pr_info("dmatest: Started %u threads using %s\n", i, dev_name(&chan->dev));
list_add_tail(&dtc->node, &dmatest_channels);
nr_channels++;
@@ -379,7 +379,7 @@ static enum dma_state_client dmatest_remove_channel(struct dma_chan *chan)
list_del(&dtc->node);
dmatest_cleanup_channel(dtc);
pr_debug("dmatest: lost channel %s\n",
- chan->dev.bus_id);
+ dev_name(&chan->dev));
return DMA_ACK;
}
}
@@ -418,7 +418,7 @@ dmatest_event(struct dma_client *client, struct dma_chan *chan,
default:
pr_info("dmatest: Unhandled event %u (%s)\n",
- state, chan->dev.bus_id);
+ state, dev_name(&chan->dev));
break;
}
diff --git a/drivers/dma/ioat_dma.c b/drivers/dma/ioat_dma.c
index ecd743f7cc6..6607fdd00b1 100644
--- a/drivers/dma/ioat_dma.c
+++ b/drivers/dma/ioat_dma.c
@@ -1341,10 +1341,12 @@ static void ioat_dma_start_null_desc(struct ioat_dma_chan *ioat_chan)
*/
#define IOAT_TEST_SIZE 2000
+DECLARE_COMPLETION(test_completion);
static void ioat_dma_test_callback(void *dma_async_param)
{
printk(KERN_ERR "ioatdma: ioat_dma_test_callback(%p)\n",
dma_async_param);
+ complete(&test_completion);
}
/**
@@ -1410,7 +1412,8 @@ static int ioat_dma_self_test(struct ioatdma_device *device)
goto free_resources;
}
device->common.device_issue_pending(dma_chan);
- msleep(1);
+
+ wait_for_completion_timeout(&test_completion, msecs_to_jiffies(3000));
if (device->common.device_is_tx_complete(dma_chan, cookie, NULL, NULL)
!= DMA_SUCCESS) {
diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c
index 71fba82462c..6be31726220 100644
--- a/drivers/dma/iop-adma.c
+++ b/drivers/dma/iop-adma.c
@@ -85,18 +85,28 @@ iop_adma_run_tx_complete_actions(struct iop_adma_desc_slot *desc,
enum dma_ctrl_flags flags = desc->async_tx.flags;
u32 src_cnt;
dma_addr_t addr;
+ dma_addr_t dest;
+ src_cnt = unmap->unmap_src_cnt;
+ dest = iop_desc_get_dest_addr(unmap, iop_chan);
if (!(flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
- addr = iop_desc_get_dest_addr(unmap, iop_chan);
- dma_unmap_page(dev, addr, len, DMA_FROM_DEVICE);
+ enum dma_data_direction dir;
+
+ if (src_cnt > 1) /* is xor? */
+ dir = DMA_BIDIRECTIONAL;
+ else
+ dir = DMA_FROM_DEVICE;
+
+ dma_unmap_page(dev, dest, len, dir);
}
if (!(flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
- src_cnt = unmap->unmap_src_cnt;
while (src_cnt--) {
addr = iop_desc_get_src_addr(unmap,
iop_chan,
src_cnt);
+ if (addr == dest)
+ continue;
dma_unmap_page(dev, addr, len,
DMA_TO_DEVICE);
}
@@ -411,6 +421,7 @@ iop_adma_tx_submit(struct dma_async_tx_descriptor *tx)
int slot_cnt;
int slots_per_op;
dma_cookie_t cookie;
+ dma_addr_t next_dma;
grp_start = sw_desc->group_head;
slot_cnt = grp_start->slot_cnt;
@@ -425,12 +436,12 @@ iop_adma_tx_submit(struct dma_async_tx_descriptor *tx)
&old_chain_tail->chain_node);
/* fix up the hardware chain */
- iop_desc_set_next_desc(old_chain_tail, grp_start->async_tx.phys);
+ next_dma = grp_start->async_tx.phys;
+ iop_desc_set_next_desc(old_chain_tail, next_dma);
+ BUG_ON(iop_desc_get_next_desc(old_chain_tail) != next_dma); /* flush */
- /* 1/ don't add pre-chained descriptors
- * 2/ dummy read to flush next_desc write
- */
- BUG_ON(iop_desc_get_next_desc(sw_desc));
+ /* check for pre-chained descriptors */
+ iop_paranoia(iop_desc_get_next_desc(sw_desc));
/* increment the pending count by the number of slots
* memcpy operations have a 1:1 (slot:operation) relation
diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c
index 0328da020a1..bcda1742641 100644
--- a/drivers/dma/mv_xor.c
+++ b/drivers/dma/mv_xor.c
@@ -311,17 +311,26 @@ mv_xor_run_tx_complete_actions(struct mv_xor_desc_slot *desc,
enum dma_ctrl_flags flags = desc->async_tx.flags;
u32 src_cnt;
dma_addr_t addr;
+ dma_addr_t dest;
+ src_cnt = unmap->unmap_src_cnt;
+ dest = mv_desc_get_dest_addr(unmap);
if (!(flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
- addr = mv_desc_get_dest_addr(unmap);
- dma_unmap_page(dev, addr, len, DMA_FROM_DEVICE);
+ enum dma_data_direction dir;
+
+ if (src_cnt > 1) /* is xor ? */
+ dir = DMA_BIDIRECTIONAL;
+ else
+ dir = DMA_FROM_DEVICE;
+ dma_unmap_page(dev, dest, len, dir);
}
if (!(flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
- src_cnt = unmap->unmap_src_cnt;
while (src_cnt--) {
addr = mv_desc_get_src_addr(unmap,
src_cnt);
+ if (addr == dest)
+ continue;
dma_unmap_page(dev, addr, len,
DMA_TO_DEVICE);
}
diff --git a/drivers/edac/edac_device.c b/drivers/edac/edac_device.c
index 5fcd3d89c75..4041e914328 100644
--- a/drivers/edac/edac_device.c
+++ b/drivers/edac/edac_device.c
@@ -394,6 +394,12 @@ static void edac_device_workq_function(struct work_struct *work_req)
mutex_lock(&device_ctls_mutex);
+ /* If we are being removed, bail out immediately */
+ if (edac_dev->op_state == OP_OFFLINE) {
+ mutex_unlock(&device_ctls_mutex);
+ return;
+ }
+
/* Only poll controllers that are running polled and have a check */
if ((edac_dev->op_state == OP_RUNNING_POLL) &&
(edac_dev->edac_check != NULL)) {
@@ -585,14 +591,14 @@ struct edac_device_ctl_info *edac_device_del_device(struct device *dev)
/* mark this instance as OFFLINE */
edac_dev->op_state = OP_OFFLINE;
- /* clear workq processing on this instance */
- edac_device_workq_teardown(edac_dev);
-
/* deregister from global list */
del_edac_device_from_global_list(edac_dev);
mutex_unlock(&device_ctls_mutex);
+ /* clear workq processing on this instance */
+ edac_device_workq_teardown(edac_dev);
+
/* Tear down the sysfs entries for this instance */
edac_device_remove_sysfs(edac_dev);
diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c
index f0d9b415db5..d335086f4a2 100644
--- a/drivers/edac/i5000_edac.c
+++ b/drivers/edac/i5000_edac.c
@@ -1381,6 +1381,7 @@ static int i5000_probe1(struct pci_dev *pdev, int dev_idx)
if (mci == NULL)
return -ENOMEM;
+ kobject_get(&mci->edac_mci_kobj);
debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci);
mci->dev = &pdev->dev; /* record ptr to the generic device */
@@ -1453,6 +1454,7 @@ fail1:
i5000_put_devices(mci);
fail0:
+ kobject_put(&mci->edac_mci_kobj);
edac_mc_free(mci);
return -ENODEV;
}
@@ -1498,7 +1500,7 @@ static void __devexit i5000_remove_one(struct pci_dev *pdev)
/* retrieve references to resources, and free those resources */
i5000_put_devices(mci);
-
+ kobject_put(&mci->edac_mci_kobj);
edac_mc_free(mci);
}
diff --git a/drivers/edac/i82875p_edac.c b/drivers/edac/i82875p_edac.c
index e43bdc43a1b..ebb037b7875 100644
--- a/drivers/edac/i82875p_edac.c
+++ b/drivers/edac/i82875p_edac.c
@@ -182,8 +182,6 @@ static struct pci_dev *mci_pdev; /* init dev: in case that AGP code has
* already registered driver
*/
-static int i82875p_registered = 1;
-
static struct edac_pci_ctl_info *i82875p_pci;
static void i82875p_get_error_info(struct mem_ctl_info *mci,
@@ -295,6 +293,7 @@ static int i82875p_setup_overfl_dev(struct pci_dev *pdev,
"%s(): pci_bus_add_device() Failed\n",
__func__);
}
+ pci_bus_assign_resources(dev->bus);
}
*ovrfl_pdev = dev;
@@ -409,6 +408,9 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx)
goto fail0;
}
+ /* Keeps mci available after edac_mc_del_mc() till edac_mc_free() */
+ kobject_get(&mci->edac_mci_kobj);
+
debugf3("%s(): init mci\n", __func__);
mci->dev = &pdev->dev;
mci->mtype_cap = MEM_FLAG_DDR;
@@ -451,6 +453,7 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx)
return 0;
fail1:
+ kobject_put(&mci->edac_mci_kobj);
edac_mc_free(mci);
fail0:
@@ -578,12 +581,11 @@ static void __exit i82875p_exit(void)
{
debugf3("%s()\n", __func__);
+ i82875p_remove_one(mci_pdev);
+ pci_dev_put(mci_pdev);
+
pci_unregister_driver(&i82875p_driver);
- if (!i82875p_registered) {
- i82875p_remove_one(mci_pdev);
- pci_dev_put(mci_pdev);
- }
}
module_init(i82875p_init);
diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c
index 46610b09041..ab9c01e462e 100644
--- a/drivers/firewire/fw-ohci.c
+++ b/drivers/firewire/fw-ohci.c
@@ -974,6 +974,7 @@ at_context_queue_packet(struct context *ctx, struct fw_packet *packet)
packet->ack = RCODE_SEND_ERROR;
return -1;
}
+ packet->payload_bus = payload_bus;
d[2].req_count = cpu_to_le16(packet->payload_length);
d[2].data_address = cpu_to_le32(payload_bus);
@@ -1025,7 +1026,6 @@ static int handle_at_packet(struct context *context,
struct driver_data *driver_data;
struct fw_packet *packet;
struct fw_ohci *ohci = context->ohci;
- dma_addr_t payload_bus;
int evt;
if (last->transfer_status == 0)
@@ -1038,9 +1038,8 @@ static int handle_at_packet(struct context *context,
/* This packet was cancelled, just continue. */
return 1;
- payload_bus = le32_to_cpu(last->data_address);
- if (payload_bus != 0)
- dma_unmap_single(ohci->card.device, payload_bus,
+ if (packet->payload_bus)
+ dma_unmap_single(ohci->card.device, packet->payload_bus,
packet->payload_length, DMA_TO_DEVICE);
evt = le16_to_cpu(last->transfer_status) & 0x1f;
@@ -1697,6 +1696,10 @@ static int ohci_cancel_packet(struct fw_card *card, struct fw_packet *packet)
if (packet->ack != 0)
goto out;
+ if (packet->payload_bus)
+ dma_unmap_single(ohci->card.device, packet->payload_bus,
+ packet->payload_length, DMA_TO_DEVICE);
+
log_ar_at_event('T', packet->speed, packet->header, 0x20);
driver_data->packet = NULL;
packet->ack = RCODE_CANCELLED;
diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c
index 97df6dac3a8..e54403ee59e 100644
--- a/drivers/firewire/fw-sbp2.c
+++ b/drivers/firewire/fw-sbp2.c
@@ -372,6 +372,11 @@ static const struct {
},
/* iPod mini */ {
.firmware_revision = 0x0a2700,
+ .model = 0x000022,
+ .workarounds = SBP2_WORKAROUND_FIX_CAPACITY,
+ },
+ /* iPod mini */ {
+ .firmware_revision = 0x0a2700,
.model = 0x000023,
.workarounds = SBP2_WORKAROUND_FIX_CAPACITY,
},
diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c
index 022ac4fabb6..2884f876397 100644
--- a/drivers/firewire/fw-transaction.c
+++ b/drivers/firewire/fw-transaction.c
@@ -207,6 +207,7 @@ fw_fill_request(struct fw_packet *packet, int tcode, int tlabel,
packet->speed = speed;
packet->generation = generation;
packet->ack = 0;
+ packet->payload_bus = 0;
}
/**
@@ -581,6 +582,8 @@ fw_fill_response(struct fw_packet *response, u32 *request_header,
BUG();
return;
}
+
+ response->payload_bus = 0;
}
EXPORT_SYMBOL(fw_fill_response);
diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h
index aed7dbb17cd..839466f0a79 100644
--- a/drivers/firewire/fw-transaction.h
+++ b/drivers/firewire/fw-transaction.h
@@ -27,6 +27,7 @@
#include <linux/list.h>
#include <linux/spinlock_types.h>
#include <linux/timer.h>
+#include <linux/types.h>
#include <linux/workqueue.h>
#define TCODE_IS_READ_REQUEST(tcode) (((tcode) & ~1) == 4)
@@ -153,6 +154,7 @@ struct fw_packet {
size_t header_length;
void *payload;
size_t payload_length;
+ dma_addr_t payload_bus;
u32 timestamp;
/*
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 7f2ee27fe76..48f49d93d24 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -65,6 +65,14 @@ config GPIO_SYSFS
# put expanders in the right section, in alphabetical order
+comment "Memory mapped GPIO expanders:"
+
+config GPIO_XILINX
+ bool "Xilinx GPIO support"
+ depends on PPC_OF
+ help
+ Say yes here to support the Xilinx FPGA GPIO device
+
comment "I2C GPIO expanders:"
config GPIO_MAX732X
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 6aafdeb9ad0..49ac64e515e 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -10,4 +10,5 @@ obj-$(CONFIG_GPIO_MCP23S08) += mcp23s08.o
obj-$(CONFIG_GPIO_PCA953X) += pca953x.o
obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o
obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o
+obj-$(CONFIG_GPIO_XILINX) += xilinx_gpio.o
obj-$(CONFIG_GPIO_BT8XX) += bt8xxgpio.o
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index faa1cc66e9c..82020abc329 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1134,7 +1134,7 @@ static void gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip)
continue;
is_out = test_bit(FLAG_IS_OUT, &gdesc->flags);
- seq_printf(s, " gpio-%-3d (%-12s) %s %s",
+ seq_printf(s, " gpio-%-3d (%-20.20s) %s %s",
gpio, gdesc->label,
is_out ? "out" : "in ",
chip->get
diff --git a/drivers/gpio/xilinx_gpio.c b/drivers/gpio/xilinx_gpio.c
new file mode 100644
index 00000000000..3c1177abebd
--- /dev/null
+++ b/drivers/gpio/xilinx_gpio.c
@@ -0,0 +1,235 @@
+/*
+ * Xilinx gpio driver
+ *
+ * Copyright 2008 Xilinx, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <linux/of_gpio.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+
+/* Register Offset Definitions */
+#define XGPIO_DATA_OFFSET (0x0) /* Data register */
+#define XGPIO_TRI_OFFSET (0x4) /* I/O direction register */
+
+struct xgpio_instance {
+ struct of_mm_gpio_chip mmchip;
+ u32 gpio_state; /* GPIO state shadow register */
+ u32 gpio_dir; /* GPIO direction shadow register */
+ spinlock_t gpio_lock; /* Lock used for synchronization */
+};
+
+/**
+ * xgpio_get - Read the specified signal of the GPIO device.
+ * @gc: Pointer to gpio_chip device structure.
+ * @gpio: GPIO signal number.
+ *
+ * This function reads the specified signal of the GPIO device. It returns 0 if
+ * the signal clear, 1 if signal is set or negative value on error.
+ */
+static int xgpio_get(struct gpio_chip *gc, unsigned int gpio)
+{
+ struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+
+ return (in_be32(mm_gc->regs + XGPIO_DATA_OFFSET) >> gpio) & 1;
+}
+
+/**
+ * xgpio_set - Write the specified signal of the GPIO device.
+ * @gc: Pointer to gpio_chip device structure.
+ * @gpio: GPIO signal number.
+ * @val: Value to be written to specified signal.
+ *
+ * This function writes the specified value in to the specified signal of the
+ * GPIO device.
+ */
+static void xgpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+ unsigned long flags;
+ struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+ struct xgpio_instance *chip =
+ container_of(mm_gc, struct xgpio_instance, mmchip);
+
+ spin_lock_irqsave(&chip->gpio_lock, flags);
+
+ /* Write to GPIO signal and set its direction to output */
+ if (val)
+ chip->gpio_state |= 1 << gpio;
+ else
+ chip->gpio_state &= ~(1 << gpio);
+ out_be32(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state);
+
+ spin_unlock_irqrestore(&chip->gpio_lock, flags);
+}
+
+/**
+ * xgpio_dir_in - Set the direction of the specified GPIO signal as input.
+ * @gc: Pointer to gpio_chip device structure.
+ * @gpio: GPIO signal number.
+ *
+ * This function sets the direction of specified GPIO signal as input.
+ * It returns 0 if direction of GPIO signals is set as input otherwise it
+ * returns negative error value.
+ */
+static int xgpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
+{
+ unsigned long flags;
+ struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+ struct xgpio_instance *chip =
+ container_of(mm_gc, struct xgpio_instance, mmchip);
+
+ spin_lock_irqsave(&chip->gpio_lock, flags);
+
+ /* Set the GPIO bit in shadow register and set direction as input */
+ chip->gpio_dir |= (1 << gpio);
+ out_be32(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir);
+
+ spin_unlock_irqrestore(&chip->gpio_lock, flags);
+
+ return 0;
+}
+
+/**
+ * xgpio_dir_out - Set the direction of the specified GPIO signal as output.
+ * @gc: Pointer to gpio_chip device structure.
+ * @gpio: GPIO signal number.
+ * @val: Value to be written to specified signal.
+ *
+ * This function sets the direction of specified GPIO signal as output. If all
+ * GPIO signals of GPIO chip is configured as input then it returns
+ * error otherwise it returns 0.
+ */
+static int xgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+ unsigned long flags;
+ struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+ struct xgpio_instance *chip =
+ container_of(mm_gc, struct xgpio_instance, mmchip);
+
+ spin_lock_irqsave(&chip->gpio_lock, flags);
+
+ /* Write state of GPIO signal */
+ if (val)
+ chip->gpio_state |= 1 << gpio;
+ else
+ chip->gpio_state &= ~(1 << gpio);
+ out_be32(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state);
+
+ /* Clear the GPIO bit in shadow register and set direction as output */
+ chip->gpio_dir &= (~(1 << gpio));
+ out_be32(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir);
+
+ spin_unlock_irqrestore(&chip->gpio_lock, flags);
+
+ return 0;
+}
+
+/**
+ * xgpio_save_regs - Set initial values of GPIO pins
+ * @mm_gc: pointer to memory mapped GPIO chip structure
+ */
+static void xgpio_save_regs(struct of_mm_gpio_chip *mm_gc)
+{
+ struct xgpio_instance *chip =
+ container_of(mm_gc, struct xgpio_instance, mmchip);
+
+ out_be32(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state);
+ out_be32(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir);
+}
+
+/**
+ * xgpio_of_probe - Probe method for the GPIO device.
+ * @np: pointer to device tree node
+ *
+ * This function probes the GPIO device in the device tree. It initializes the
+ * driver data structure. It returns 0, if the driver is bound to the GPIO
+ * device, or a negative value if there is an error.
+ */
+static int __devinit xgpio_of_probe(struct device_node *np)
+{
+ struct xgpio_instance *chip;
+ struct of_gpio_chip *ofchip;
+ int status = 0;
+ const u32 *tree_info;
+
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+ if (!chip)
+ return -ENOMEM;
+ ofchip = &chip->mmchip.of_gc;
+
+ /* Update GPIO state shadow register with default value */
+ tree_info = of_get_property(np, "xlnx,dout-default", NULL);
+ if (tree_info)
+ chip->gpio_state = *tree_info;
+
+ /* Update GPIO direction shadow register with default value */
+ chip->gpio_dir = 0xFFFFFFFF; /* By default, all pins are inputs */
+ tree_info = of_get_property(np, "xlnx,tri-default", NULL);
+ if (tree_info)
+ chip->gpio_dir = *tree_info;
+
+ /* Check device node and parent device node for device width */
+ ofchip->gc.ngpio = 32; /* By default assume full GPIO controller */
+ tree_info = of_get_property(np, "xlnx,gpio-width", NULL);
+ if (!tree_info)
+ tree_info = of_get_property(np->parent,
+ "xlnx,gpio-width", NULL);
+ if (tree_info)
+ ofchip->gc.ngpio = *tree_info;
+
+ spin_lock_init(&chip->gpio_lock);
+
+ ofchip->gpio_cells = 2;
+ ofchip->gc.direction_input = xgpio_dir_in;
+ ofchip->gc.direction_output = xgpio_dir_out;
+ ofchip->gc.get = xgpio_get;
+ ofchip->gc.set = xgpio_set;
+
+ chip->mmchip.save_regs = xgpio_save_regs;
+
+ /* Call the OF gpio helper to setup and register the GPIO device */
+ status = of_mm_gpiochip_add(np, &chip->mmchip);
+ if (status) {
+ kfree(chip);
+ pr_err("%s: error in probe function with status %d\n",
+ np->full_name, status);
+ return status;
+ }
+ pr_info("XGpio: %s: registered\n", np->full_name);
+ return 0;
+}
+
+static struct of_device_id xgpio_of_match[] __devinitdata = {
+ { .compatible = "xlnx,xps-gpio-1.00.a", },
+ { /* end of list */ },
+};
+
+static int __init xgpio_init(void)
+{
+ struct device_node *np;
+
+ for_each_matching_node(np, xgpio_of_match)
+ xgpio_of_probe(np);
+
+ return 0;
+}
+
+/* Make sure we get initialized before anyone else tries to use us */
+subsys_initcall(xgpio_init);
+/* No exit call at the moment as we cannot unregister of GPIO chips */
+
+MODULE_AUTHOR("Xilinx, Inc.");
+MODULE_DESCRIPTION("Xilinx GPIO driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 3ab1e9cc469..996097acb5e 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -305,6 +305,8 @@ static void drm_cleanup(struct drm_device * dev)
return;
}
+ drm_vblank_cleanup(dev);
+
drm_lastclose(dev);
if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) &&
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index 15c8dabc3e9..1e787f894b3 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -94,7 +94,7 @@ static void vblank_disable_fn(unsigned long arg)
}
}
-static void drm_vblank_cleanup(struct drm_device *dev)
+void drm_vblank_cleanup(struct drm_device *dev)
{
/* Bail if the driver didn't call drm_vblank_init() */
if (dev->num_crtcs == 0)
@@ -278,8 +278,6 @@ int drm_irq_uninstall(struct drm_device * dev)
free_irq(dev->pdev->irq, dev);
- drm_vblank_cleanup(dev);
-
return 0;
}
EXPORT_SYMBOL(drm_irq_uninstall);
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 0d215e38606..afa8a12cd00 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -717,7 +717,7 @@ static int i915_getparam(struct drm_device *dev, void *data,
value = dev->pci_device;
break;
case I915_PARAM_HAS_GEM:
- value = 1;
+ value = dev_priv->has_gem;
break;
default:
DRM_ERROR("Unknown parameter %d\n", param->param);
@@ -830,6 +830,14 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
dev_priv->regs = ioremap(base, size);
+#ifdef CONFIG_HIGHMEM64G
+ /* don't enable GEM on PAE - needs agp + set_memory_* interface fixes */
+ dev_priv->has_gem = 0;
+#else
+ /* enable GEM by default */
+ dev_priv->has_gem = 1;
+#endif
+
i915_gem_load(dev);
/* Init HWS */
@@ -847,15 +855,23 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
* and the registers being closely associated.
*
* According to chipset errata, on the 965GM, MSI interrupts may
- * be lost or delayed
+ * be lost or delayed, but we use them anyways to avoid
+ * stuck interrupts on some machines.
*/
- if (!IS_I945G(dev) && !IS_I945GM(dev) && !IS_I965GM(dev))
+ if (!IS_I945G(dev) && !IS_I945GM(dev))
pci_enable_msi(dev->pdev);
intel_opregion_init(dev);
spin_lock_init(&dev_priv->user_irq_lock);
+ ret = drm_vblank_init(dev, I915_NUM_PIPE);
+
+ if (ret) {
+ (void) i915_driver_unload(dev);
+ return ret;
+ }
+
return ret;
}
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index ef1c0b8f8d0..b3cc4731aa7 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -47,6 +47,8 @@ enum pipe {
PIPE_B,
};
+#define I915_NUM_PIPE 2
+
/* Interface history:
*
* 1.1: Original.
@@ -104,6 +106,8 @@ struct intel_opregion {
typedef struct drm_i915_private {
struct drm_device *dev;
+ int has_gem;
+
void __iomem *regs;
drm_local_map_t *sarea;
@@ -132,6 +136,7 @@ typedef struct drm_i915_private {
int user_irq_refcount;
/** Cached value of IMR to avoid reads in updating the bitfield */
u32 irq_mask_reg;
+ u32 pipestat[2];
int tex_lru_log_granularity;
int allow_batchbuffer;
@@ -147,6 +152,7 @@ typedef struct drm_i915_private {
u32 saveDSPBCNTR;
u32 saveDSPARB;
u32 saveRENDERSTANDBY;
+ u32 saveHWS;
u32 savePIPEACONF;
u32 savePIPEBCONF;
u32 savePIPEASRC;
@@ -240,6 +246,10 @@ typedef struct drm_i915_private {
* List of objects currently involved in rendering from the
* ringbuffer.
*
+ * Includes buffers having the contents of their GPU caches
+ * flushed, not necessarily primitives. last_rendering_seqno
+ * represents when the rendering involved will be completed.
+ *
* A reference is held on the buffer while on this list.
*/
struct list_head active_list;
@@ -249,6 +259,8 @@ typedef struct drm_i915_private {
* still have a write_domain which needs to be flushed before
* unbinding.
*
+ * last_rendering_seqno is 0 while an object is in this list.
+ *
* A reference is held on the buffer while on this list.
*/
struct list_head flushing_list;
@@ -257,6 +269,8 @@ typedef struct drm_i915_private {
* LRU list of objects which are not in the ringbuffer and
* are ready to unbind, but are still in the GTT.
*
+ * last_rendering_seqno is 0 while an object is in this list.
+ *
* A reference is not held on the buffer while on this list,
* as merely being GTT-bound shouldn't prevent its being
* freed, and we'll pull it off the list in the free path.
@@ -367,8 +381,8 @@ struct drm_i915_gem_object {
uint32_t agp_type;
/**
- * Flagging of which individual pages are valid in GEM_DOMAIN_CPU when
- * GEM_DOMAIN_CPU is not in the object's read domain.
+ * If present, while GEM_DOMAIN_CPU is in the read domain this array
+ * flags which individual pages are valid.
*/
uint8_t *page_cpu_valid;
};
@@ -390,9 +404,6 @@ struct drm_i915_gem_request {
/** Time at which this request was emitted, in jiffies. */
unsigned long emitted_jiffies;
- /** Cache domains that were flushed at the start of the request. */
- uint32_t flush_domains;
-
struct list_head list;
};
@@ -446,6 +457,13 @@ extern int i915_vblank_swap(struct drm_device *dev, void *data,
struct drm_file *file_priv);
extern void i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask);
+void
+i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask);
+
+void
+i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask);
+
+
/* i915_mem.c */
extern int i915_mem_alloc(struct drm_device *dev, void *data,
struct drm_file *file_priv);
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 6b4a2bd2064..24fe8c10b4b 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -31,21 +31,23 @@
#include "i915_drv.h"
#include <linux/swap.h>
-static int
-i915_gem_object_set_domain(struct drm_gem_object *obj,
- uint32_t read_domains,
- uint32_t write_domain);
-static int
-i915_gem_object_set_domain_range(struct drm_gem_object *obj,
- uint64_t offset,
- uint64_t size,
- uint32_t read_domains,
- uint32_t write_domain);
-static int
-i915_gem_set_domain(struct drm_gem_object *obj,
- struct drm_file *file_priv,
- uint32_t read_domains,
- uint32_t write_domain);
+#define I915_GEM_GPU_DOMAINS (~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT))
+
+static void
+i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj,
+ uint32_t read_domains,
+ uint32_t write_domain);
+static void i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj);
+static void i915_gem_object_flush_gtt_write_domain(struct drm_gem_object *obj);
+static void i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj);
+static int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj,
+ int write);
+static int i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj,
+ int write);
+static int i915_gem_object_set_cpu_read_domain_range(struct drm_gem_object *obj,
+ uint64_t offset,
+ uint64_t size);
+static void i915_gem_object_set_to_full_cpu_read_domain(struct drm_gem_object *obj);
static int i915_gem_object_get_page_list(struct drm_gem_object *obj);
static void i915_gem_object_free_page_list(struct drm_gem_object *obj);
static int i915_gem_object_wait_rendering(struct drm_gem_object *obj);
@@ -83,20 +85,14 @@ int
i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
- drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_i915_gem_get_aperture *args = data;
- struct drm_i915_gem_object *obj_priv;
if (!(dev->driver->driver_features & DRIVER_GEM))
return -ENODEV;
args->aper_size = dev->gtt_total;
- args->aper_available_size = args->aper_size;
-
- list_for_each_entry(obj_priv, &dev_priv->mm.active_list, list) {
- if (obj_priv->pin_count > 0)
- args->aper_available_size -= obj_priv->obj->size;
- }
+ args->aper_available_size = (args->aper_size -
+ atomic_read(&dev->pin_memory));
return 0;
}
@@ -166,8 +162,8 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data,
mutex_lock(&dev->struct_mutex);
- ret = i915_gem_object_set_domain_range(obj, args->offset, args->size,
- I915_GEM_DOMAIN_CPU, 0);
+ ret = i915_gem_object_set_cpu_read_domain_range(obj, args->offset,
+ args->size);
if (ret != 0) {
drm_gem_object_unreference(obj);
mutex_unlock(&dev->struct_mutex);
@@ -264,8 +260,7 @@ i915_gem_gtt_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
mutex_unlock(&dev->struct_mutex);
return ret;
}
- ret = i915_gem_set_domain(obj, file_priv,
- I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
+ ret = i915_gem_object_set_to_gtt_domain(obj, 1);
if (ret)
goto fail;
@@ -324,8 +319,7 @@ i915_gem_shmem_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
mutex_lock(&dev->struct_mutex);
- ret = i915_gem_set_domain(obj, file_priv,
- I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
+ ret = i915_gem_object_set_to_cpu_domain(obj, 1);
if (ret) {
mutex_unlock(&dev->struct_mutex);
return ret;
@@ -401,7 +395,8 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
}
/**
- * Called when user space prepares to use an object
+ * Called when user space prepares to use an object with the CPU, either
+ * through the mmap ioctl's mapping or a GTT mapping.
*/
int
i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
@@ -409,11 +404,26 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
{
struct drm_i915_gem_set_domain *args = data;
struct drm_gem_object *obj;
+ uint32_t read_domains = args->read_domains;
+ uint32_t write_domain = args->write_domain;
int ret;
if (!(dev->driver->driver_features & DRIVER_GEM))
return -ENODEV;
+ /* Only handle setting domains to types used by the CPU. */
+ if (write_domain & ~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT))
+ return -EINVAL;
+
+ if (read_domains & ~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT))
+ return -EINVAL;
+
+ /* Having something in the write domain implies it's in the read
+ * domain, and only that read domain. Enforce that in the request.
+ */
+ if (write_domain != 0 && read_domains != write_domain)
+ return -EINVAL;
+
obj = drm_gem_object_lookup(dev, file_priv, args->handle);
if (obj == NULL)
return -EBADF;
@@ -421,10 +431,21 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
mutex_lock(&dev->struct_mutex);
#if WATCH_BUF
DRM_INFO("set_domain_ioctl %p(%d), %08x %08x\n",
- obj, obj->size, args->read_domains, args->write_domain);
+ obj, obj->size, read_domains, write_domain);
#endif
- ret = i915_gem_set_domain(obj, file_priv,
- args->read_domains, args->write_domain);
+ if (read_domains & I915_GEM_DOMAIN_GTT) {
+ ret = i915_gem_object_set_to_gtt_domain(obj, write_domain != 0);
+
+ /* Silently promote "you're not bound, there was nothing to do"
+ * to success, since the client was just asking us to
+ * make sure everything was done.
+ */
+ if (ret == -EINVAL)
+ ret = 0;
+ } else {
+ ret = i915_gem_object_set_to_cpu_domain(obj, write_domain != 0);
+ }
+
drm_gem_object_unreference(obj);
mutex_unlock(&dev->struct_mutex);
return ret;
@@ -459,10 +480,9 @@ i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data,
obj_priv = obj->driver_private;
/* Pinned buffers may be scanout, so flush the cache */
- if ((obj->write_domain & I915_GEM_DOMAIN_CPU) && obj_priv->pin_count) {
- i915_gem_clflush_object(obj);
- drm_agp_chipset_flush(dev);
- }
+ if (obj_priv->pin_count)
+ i915_gem_object_flush_cpu_write_domain(obj);
+
drm_gem_object_unreference(obj);
mutex_unlock(&dev->struct_mutex);
return ret;
@@ -536,7 +556,7 @@ i915_gem_object_free_page_list(struct drm_gem_object *obj)
}
static void
-i915_gem_object_move_to_active(struct drm_gem_object *obj)
+i915_gem_object_move_to_active(struct drm_gem_object *obj, uint32_t seqno)
{
struct drm_device *dev = obj->dev;
drm_i915_private_t *dev_priv = dev->dev_private;
@@ -550,8 +570,20 @@ i915_gem_object_move_to_active(struct drm_gem_object *obj)
/* Move from whatever list we were on to the tail of execution. */
list_move_tail(&obj_priv->list,
&dev_priv->mm.active_list);
+ obj_priv->last_rendering_seqno = seqno;
}
+static void
+i915_gem_object_move_to_flushing(struct drm_gem_object *obj)
+{
+ struct drm_device *dev = obj->dev;
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ struct drm_i915_gem_object *obj_priv = obj->driver_private;
+
+ BUG_ON(!obj_priv->active);
+ list_move_tail(&obj_priv->list, &dev_priv->mm.flushing_list);
+ obj_priv->last_rendering_seqno = 0;
+}
static void
i915_gem_object_move_to_inactive(struct drm_gem_object *obj)
@@ -566,6 +598,7 @@ i915_gem_object_move_to_inactive(struct drm_gem_object *obj)
else
list_move_tail(&obj_priv->list, &dev_priv->mm.inactive_list);
+ obj_priv->last_rendering_seqno = 0;
if (obj_priv->active) {
obj_priv->active = 0;
drm_gem_object_unreference(obj);
@@ -614,10 +647,28 @@ i915_add_request(struct drm_device *dev, uint32_t flush_domains)
request->seqno = seqno;
request->emitted_jiffies = jiffies;
- request->flush_domains = flush_domains;
was_empty = list_empty(&dev_priv->mm.request_list);
list_add_tail(&request->list, &dev_priv->mm.request_list);
+ /* Associate any objects on the flushing list matching the write
+ * domain we're flushing with our flush.
+ */
+ if (flush_domains != 0) {
+ struct drm_i915_gem_object *obj_priv, *next;
+
+ list_for_each_entry_safe(obj_priv, next,
+ &dev_priv->mm.flushing_list, list) {
+ struct drm_gem_object *obj = obj_priv->obj;
+
+ if ((obj->write_domain & flush_domains) ==
+ obj->write_domain) {
+ obj->write_domain = 0;
+ i915_gem_object_move_to_active(obj, seqno);
+ }
+ }
+
+ }
+
if (was_empty && !dev_priv->mm.suspended)
schedule_delayed_work(&dev_priv->mm.retire_work, HZ);
return seqno;
@@ -680,30 +731,10 @@ i915_gem_retire_request(struct drm_device *dev,
__func__, request->seqno, obj);
#endif
- if (obj->write_domain != 0) {
- list_move_tail(&obj_priv->list,
- &dev_priv->mm.flushing_list);
- } else {
+ if (obj->write_domain != 0)
+ i915_gem_object_move_to_flushing(obj);
+ else
i915_gem_object_move_to_inactive(obj);
- }
- }
-
- if (request->flush_domains != 0) {
- struct drm_i915_gem_object *obj_priv, *next;
-
- /* Clear the write domain and activity from any buffers
- * that are just waiting for a flush matching the one retired.
- */
- list_for_each_entry_safe(obj_priv, next,
- &dev_priv->mm.flushing_list, list) {
- struct drm_gem_object *obj = obj_priv->obj;
-
- if (obj->write_domain & request->flush_domains) {
- obj->write_domain = 0;
- i915_gem_object_move_to_inactive(obj);
- }
- }
-
}
}
@@ -896,25 +927,10 @@ i915_gem_object_wait_rendering(struct drm_gem_object *obj)
struct drm_i915_gem_object *obj_priv = obj->driver_private;
int ret;
- /* If there are writes queued to the buffer, flush and
- * create a new seqno to wait for.
+ /* This function only exists to support waiting for existing rendering,
+ * not for emitting required flushes.
*/
- if (obj->write_domain & ~(I915_GEM_DOMAIN_CPU|I915_GEM_DOMAIN_GTT)) {
- uint32_t write_domain = obj->write_domain;
-#if WATCH_BUF
- DRM_INFO("%s: flushing object %p from write domain %08x\n",
- __func__, obj, write_domain);
-#endif
- i915_gem_flush(dev, 0, write_domain);
-
- i915_gem_object_move_to_active(obj);
- obj_priv->last_rendering_seqno = i915_add_request(dev,
- write_domain);
- BUG_ON(obj_priv->last_rendering_seqno == 0);
-#if WATCH_LRU
- DRM_INFO("%s: flush moves to exec list %p\n", __func__, obj);
-#endif
- }
+ BUG_ON((obj->write_domain & I915_GEM_GPU_DOMAINS) != 0);
/* If there is rendering queued on the buffer being evicted, wait for
* it.
@@ -954,24 +970,16 @@ i915_gem_object_unbind(struct drm_gem_object *obj)
return -EINVAL;
}
- /* Wait for any rendering to complete
- */
- ret = i915_gem_object_wait_rendering(obj);
- if (ret) {
- DRM_ERROR("wait_rendering failed: %d\n", ret);
- return ret;
- }
-
/* Move the object to the CPU domain to ensure that
* any possible CPU writes while it's not in the GTT
* are flushed when we go to remap it. This will
* also ensure that all pending GPU writes are finished
* before we unbind.
*/
- ret = i915_gem_object_set_domain(obj, I915_GEM_DOMAIN_CPU,
- I915_GEM_DOMAIN_CPU);
+ ret = i915_gem_object_set_to_cpu_domain(obj, 1);
if (ret) {
- DRM_ERROR("set_domain failed: %d\n", ret);
+ if (ret != -ERESTARTSYS)
+ DRM_ERROR("set_domain failed: %d\n", ret);
return ret;
}
@@ -1087,6 +1095,21 @@ i915_gem_evict_something(struct drm_device *dev)
}
static int
+i915_gem_evict_everything(struct drm_device *dev)
+{
+ int ret;
+
+ for (;;) {
+ ret = i915_gem_evict_something(dev);
+ if (ret != 0)
+ break;
+ }
+ if (ret == -ENOMEM)
+ return 0;
+ return ret;
+}
+
+static int
i915_gem_object_get_page_list(struct drm_gem_object *obj)
{
struct drm_i915_gem_object *obj_priv = obj->driver_private;
@@ -1172,7 +1195,8 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment)
ret = i915_gem_evict_something(dev);
if (ret != 0) {
- DRM_ERROR("Failed to evict a buffer %d\n", ret);
+ if (ret != -ERESTARTSYS)
+ DRM_ERROR("Failed to evict a buffer %d\n", ret);
return ret;
}
goto search_free;
@@ -1232,6 +1256,143 @@ i915_gem_clflush_object(struct drm_gem_object *obj)
drm_clflush_pages(obj_priv->page_list, obj->size / PAGE_SIZE);
}
+/** Flushes any GPU write domain for the object if it's dirty. */
+static void
+i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj)
+{
+ struct drm_device *dev = obj->dev;
+ uint32_t seqno;
+
+ if ((obj->write_domain & I915_GEM_GPU_DOMAINS) == 0)
+ return;
+
+ /* Queue the GPU write cache flushing we need. */
+ i915_gem_flush(dev, 0, obj->write_domain);
+ seqno = i915_add_request(dev, obj->write_domain);
+ obj->write_domain = 0;
+ i915_gem_object_move_to_active(obj, seqno);
+}
+
+/** Flushes the GTT write domain for the object if it's dirty. */
+static void
+i915_gem_object_flush_gtt_write_domain(struct drm_gem_object *obj)
+{
+ if (obj->write_domain != I915_GEM_DOMAIN_GTT)
+ return;
+
+ /* No actual flushing is required for the GTT write domain. Writes
+ * to it immediately go to main memory as far as we know, so there's
+ * no chipset flush. It also doesn't land in render cache.
+ */
+ obj->write_domain = 0;
+}
+
+/** Flushes the CPU write domain for the object if it's dirty. */
+static void
+i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj)
+{
+ struct drm_device *dev = obj->dev;
+
+ if (obj->write_domain != I915_GEM_DOMAIN_CPU)
+ return;
+
+ i915_gem_clflush_object(obj);
+ drm_agp_chipset_flush(dev);
+ obj->write_domain = 0;
+}
+
+/**
+ * Moves a single object to the GTT read, and possibly write domain.
+ *
+ * This function returns when the move is complete, including waiting on
+ * flushes to occur.
+ */
+static int
+i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, int write)
+{
+ struct drm_i915_gem_object *obj_priv = obj->driver_private;
+ int ret;
+
+ /* Not valid to be called on unbound objects. */
+ if (obj_priv->gtt_space == NULL)
+ return -EINVAL;
+
+ i915_gem_object_flush_gpu_write_domain(obj);
+ /* Wait on any GPU rendering and flushing to occur. */
+ ret = i915_gem_object_wait_rendering(obj);
+ if (ret != 0)
+ return ret;
+
+ /* If we're writing through the GTT domain, then CPU and GPU caches
+ * will need to be invalidated at next use.
+ */
+ if (write)
+ obj->read_domains &= I915_GEM_DOMAIN_GTT;
+
+ i915_gem_object_flush_cpu_write_domain(obj);
+
+ /* It should now be out of any other write domains, and we can update
+ * the domain values for our changes.
+ */
+ BUG_ON((obj->write_domain & ~I915_GEM_DOMAIN_GTT) != 0);
+ obj->read_domains |= I915_GEM_DOMAIN_GTT;
+ if (write) {
+ obj->write_domain = I915_GEM_DOMAIN_GTT;
+ obj_priv->dirty = 1;
+ }
+
+ return 0;
+}
+
+/**
+ * Moves a single object to the CPU read, and possibly write domain.
+ *
+ * This function returns when the move is complete, including waiting on
+ * flushes to occur.
+ */
+static int
+i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, int write)
+{
+ struct drm_device *dev = obj->dev;
+ int ret;
+
+ i915_gem_object_flush_gpu_write_domain(obj);
+ /* Wait on any GPU rendering and flushing to occur. */
+ ret = i915_gem_object_wait_rendering(obj);
+ if (ret != 0)
+ return ret;
+
+ i915_gem_object_flush_gtt_write_domain(obj);
+
+ /* If we have a partially-valid cache of the object in the CPU,
+ * finish invalidating it and free the per-page flags.
+ */
+ i915_gem_object_set_to_full_cpu_read_domain(obj);
+
+ /* Flush the CPU cache if it's still invalid. */
+ if ((obj->read_domains & I915_GEM_DOMAIN_CPU) == 0) {
+ i915_gem_clflush_object(obj);
+ drm_agp_chipset_flush(dev);
+
+ obj->read_domains |= I915_GEM_DOMAIN_CPU;
+ }
+
+ /* It should now be out of any other write domains, and we can update
+ * the domain values for our changes.
+ */
+ BUG_ON((obj->write_domain & ~I915_GEM_DOMAIN_CPU) != 0);
+
+ /* If we're writing through the CPU, then the GPU read domains will
+ * need to be invalidated at next use.
+ */
+ if (write) {
+ obj->read_domains &= I915_GEM_DOMAIN_CPU;
+ obj->write_domain = I915_GEM_DOMAIN_CPU;
+ }
+
+ return 0;
+}
+
/*
* Set the next domain for the specified object. This
* may not actually perform the necessary flushing/invaliding though,
@@ -1343,16 +1504,18 @@ i915_gem_clflush_object(struct drm_gem_object *obj)
* MI_FLUSH
* drm_agp_chipset_flush
*/
-static int
-i915_gem_object_set_domain(struct drm_gem_object *obj,
- uint32_t read_domains,
- uint32_t write_domain)
+static void
+i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj,
+ uint32_t read_domains,
+ uint32_t write_domain)
{
struct drm_device *dev = obj->dev;
struct drm_i915_gem_object *obj_priv = obj->driver_private;
uint32_t invalidate_domains = 0;
uint32_t flush_domains = 0;
- int ret;
+
+ BUG_ON(read_domains & I915_GEM_DOMAIN_CPU);
+ BUG_ON(write_domain == I915_GEM_DOMAIN_CPU);
#if WATCH_BUF
DRM_INFO("%s: object %p read %08x -> %08x write %08x -> %08x\n",
@@ -1389,34 +1552,11 @@ i915_gem_object_set_domain(struct drm_gem_object *obj,
DRM_INFO("%s: CPU domain flush %08x invalidate %08x\n",
__func__, flush_domains, invalidate_domains);
#endif
- /*
- * If we're invaliding the CPU cache and flushing a GPU cache,
- * then pause for rendering so that the GPU caches will be
- * flushed before the cpu cache is invalidated
- */
- if ((invalidate_domains & I915_GEM_DOMAIN_CPU) &&
- (flush_domains & ~(I915_GEM_DOMAIN_CPU |
- I915_GEM_DOMAIN_GTT))) {
- ret = i915_gem_object_wait_rendering(obj);
- if (ret)
- return ret;
- }
i915_gem_clflush_object(obj);
}
if ((write_domain | flush_domains) != 0)
obj->write_domain = write_domain;
-
- /* If we're invalidating the CPU domain, clear the per-page CPU
- * domain list as well.
- */
- if (obj_priv->page_cpu_valid != NULL &&
- (write_domain != 0 ||
- read_domains & I915_GEM_DOMAIN_CPU)) {
- drm_free(obj_priv->page_cpu_valid, obj->size / PAGE_SIZE,
- DRM_MEM_DRIVER);
- obj_priv->page_cpu_valid = NULL;
- }
obj->read_domains = read_domains;
dev->invalidate_domains |= invalidate_domains;
@@ -1427,47 +1567,94 @@ i915_gem_object_set_domain(struct drm_gem_object *obj,
obj->read_domains, obj->write_domain,
dev->invalidate_domains, dev->flush_domains);
#endif
- return 0;
}
/**
- * Set the read/write domain on a range of the object.
+ * Moves the object from a partially CPU read to a full one.
*
- * Currently only implemented for CPU reads, otherwise drops to normal
- * i915_gem_object_set_domain().
+ * Note that this only resolves i915_gem_object_set_cpu_read_domain_range(),
+ * and doesn't handle transitioning from !(read_domains & I915_GEM_DOMAIN_CPU).
*/
-static int
-i915_gem_object_set_domain_range(struct drm_gem_object *obj,
- uint64_t offset,
- uint64_t size,
- uint32_t read_domains,
- uint32_t write_domain)
+static void
+i915_gem_object_set_to_full_cpu_read_domain(struct drm_gem_object *obj)
{
+ struct drm_device *dev = obj->dev;
struct drm_i915_gem_object *obj_priv = obj->driver_private;
- int ret, i;
- if (obj->read_domains & I915_GEM_DOMAIN_CPU)
- return 0;
+ if (!obj_priv->page_cpu_valid)
+ return;
- if (read_domains != I915_GEM_DOMAIN_CPU ||
- write_domain != 0)
- return i915_gem_object_set_domain(obj,
- read_domains, write_domain);
+ /* If we're partially in the CPU read domain, finish moving it in.
+ */
+ if (obj->read_domains & I915_GEM_DOMAIN_CPU) {
+ int i;
- /* Wait on any GPU rendering to the object to be flushed. */
+ for (i = 0; i <= (obj->size - 1) / PAGE_SIZE; i++) {
+ if (obj_priv->page_cpu_valid[i])
+ continue;
+ drm_clflush_pages(obj_priv->page_list + i, 1);
+ }
+ drm_agp_chipset_flush(dev);
+ }
+
+ /* Free the page_cpu_valid mappings which are now stale, whether
+ * or not we've got I915_GEM_DOMAIN_CPU.
+ */
+ drm_free(obj_priv->page_cpu_valid, obj->size / PAGE_SIZE,
+ DRM_MEM_DRIVER);
+ obj_priv->page_cpu_valid = NULL;
+}
+
+/**
+ * Set the CPU read domain on a range of the object.
+ *
+ * The object ends up with I915_GEM_DOMAIN_CPU in its read flags although it's
+ * not entirely valid. The page_cpu_valid member of the object flags which
+ * pages have been flushed, and will be respected by
+ * i915_gem_object_set_to_cpu_domain() if it's called on to get a valid mapping
+ * of the whole object.
+ *
+ * This function returns when the move is complete, including waiting on
+ * flushes to occur.
+ */
+static int
+i915_gem_object_set_cpu_read_domain_range(struct drm_gem_object *obj,
+ uint64_t offset, uint64_t size)
+{
+ struct drm_i915_gem_object *obj_priv = obj->driver_private;
+ int i, ret;
+
+ if (offset == 0 && size == obj->size)
+ return i915_gem_object_set_to_cpu_domain(obj, 0);
+
+ i915_gem_object_flush_gpu_write_domain(obj);
+ /* Wait on any GPU rendering and flushing to occur. */
ret = i915_gem_object_wait_rendering(obj);
- if (ret)
+ if (ret != 0)
return ret;
+ i915_gem_object_flush_gtt_write_domain(obj);
+ /* If we're already fully in the CPU read domain, we're done. */
+ if (obj_priv->page_cpu_valid == NULL &&
+ (obj->read_domains & I915_GEM_DOMAIN_CPU) != 0)
+ return 0;
+
+ /* Otherwise, create/clear the per-page CPU read domain flag if we're
+ * newly adding I915_GEM_DOMAIN_CPU
+ */
if (obj_priv->page_cpu_valid == NULL) {
obj_priv->page_cpu_valid = drm_calloc(1, obj->size / PAGE_SIZE,
DRM_MEM_DRIVER);
- }
+ if (obj_priv->page_cpu_valid == NULL)
+ return -ENOMEM;
+ } else if ((obj->read_domains & I915_GEM_DOMAIN_CPU) == 0)
+ memset(obj_priv->page_cpu_valid, 0, obj->size / PAGE_SIZE);
/* Flush the cache on any pages that are still invalid from the CPU's
* perspective.
*/
- for (i = offset / PAGE_SIZE; i <= (offset + size - 1) / PAGE_SIZE; i++) {
+ for (i = offset / PAGE_SIZE; i <= (offset + size - 1) / PAGE_SIZE;
+ i++) {
if (obj_priv->page_cpu_valid[i])
continue;
@@ -1476,39 +1663,14 @@ i915_gem_object_set_domain_range(struct drm_gem_object *obj,
obj_priv->page_cpu_valid[i] = 1;
}
- return 0;
-}
-
-/**
- * Once all of the objects have been set in the proper domain,
- * perform the necessary flush and invalidate operations.
- *
- * Returns the write domains flushed, for use in flush tracking.
- */
-static uint32_t
-i915_gem_dev_set_domain(struct drm_device *dev)
-{
- uint32_t flush_domains = dev->flush_domains;
-
- /*
- * Now that all the buffers are synced to the proper domains,
- * flush and invalidate the collected domains
+ /* It should now be out of any other write domains, and we can update
+ * the domain values for our changes.
*/
- if (dev->invalidate_domains | dev->flush_domains) {
-#if WATCH_EXEC
- DRM_INFO("%s: invalidate_domains %08x flush_domains %08x\n",
- __func__,
- dev->invalidate_domains,
- dev->flush_domains);
-#endif
- i915_gem_flush(dev,
- dev->invalidate_domains,
- dev->flush_domains);
- dev->invalidate_domains = 0;
- dev->flush_domains = 0;
- }
+ BUG_ON((obj->write_domain & ~I915_GEM_DOMAIN_CPU) != 0);
- return flush_domains;
+ obj->read_domains |= I915_GEM_DOMAIN_CPU;
+
+ return 0;
}
/**
@@ -1589,6 +1751,18 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
return -EINVAL;
}
+ if (reloc.write_domain & I915_GEM_DOMAIN_CPU ||
+ reloc.read_domains & I915_GEM_DOMAIN_CPU) {
+ DRM_ERROR("reloc with read/write CPU domains: "
+ "obj %p target %d offset %d "
+ "read %08x write %08x",
+ obj, reloc.target_handle,
+ (int) reloc.offset,
+ reloc.read_domains,
+ reloc.write_domain);
+ return -EINVAL;
+ }
+
if (reloc.write_domain && target_obj->pending_write_domain &&
reloc.write_domain != target_obj->pending_write_domain) {
DRM_ERROR("Write domain conflict: "
@@ -1629,19 +1803,11 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
continue;
}
- /* Now that we're going to actually write some data in,
- * make sure that any rendering using this buffer's contents
- * is completed.
- */
- i915_gem_object_wait_rendering(obj);
-
- /* As we're writing through the gtt, flush
- * any CPU writes before we write the relocations
- */
- if (obj->write_domain & I915_GEM_DOMAIN_CPU) {
- i915_gem_clflush_object(obj);
- drm_agp_chipset_flush(dev);
- obj->write_domain = 0;
+ ret = i915_gem_object_set_to_gtt_domain(obj, 1);
+ if (ret != 0) {
+ drm_gem_object_unreference(target_obj);
+ i915_gem_object_unpin(obj);
+ return -EINVAL;
}
/* Map the page containing the relocation we're going to
@@ -1783,6 +1949,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
int ret, i, pinned = 0;
uint64_t exec_offset;
uint32_t seqno, flush_domains;
+ int pin_tries;
#if WATCH_EXEC
DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n",
@@ -1831,14 +1998,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
return -EBUSY;
}
- /* Zero the gloabl flush/invalidate flags. These
- * will be modified as each object is bound to the
- * gtt
- */
- dev->invalidate_domains = 0;
- dev->flush_domains = 0;
-
- /* Look up object handles and perform the relocations */
+ /* Look up object handles */
for (i = 0; i < args->buffer_count; i++) {
object_list[i] = drm_gem_object_lookup(dev, file_priv,
exec_list[i].handle);
@@ -1848,17 +2008,39 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
ret = -EBADF;
goto err;
}
+ }
- object_list[i]->pending_read_domains = 0;
- object_list[i]->pending_write_domain = 0;
- ret = i915_gem_object_pin_and_relocate(object_list[i],
- file_priv,
- &exec_list[i]);
- if (ret) {
- DRM_ERROR("object bind and relocate failed %d\n", ret);
+ /* Pin and relocate */
+ for (pin_tries = 0; ; pin_tries++) {
+ ret = 0;
+ for (i = 0; i < args->buffer_count; i++) {
+ object_list[i]->pending_read_domains = 0;
+ object_list[i]->pending_write_domain = 0;
+ ret = i915_gem_object_pin_and_relocate(object_list[i],
+ file_priv,
+ &exec_list[i]);
+ if (ret)
+ break;
+ pinned = i + 1;
+ }
+ /* success */
+ if (ret == 0)
+ break;
+
+ /* error other than GTT full, or we've already tried again */
+ if (ret != -ENOMEM || pin_tries >= 1) {
+ DRM_ERROR("Failed to pin buffers %d\n", ret);
goto err;
}
- pinned = i + 1;
+
+ /* unpin all of our buffers */
+ for (i = 0; i < pinned; i++)
+ i915_gem_object_unpin(object_list[i]);
+
+ /* evict everyone we can from the aperture */
+ ret = i915_gem_evict_everything(dev);
+ if (ret)
+ goto err;
}
/* Set the pending read domains for the batch buffer to COMMAND */
@@ -1868,32 +2050,37 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
i915_verify_inactive(dev, __FILE__, __LINE__);
+ /* Zero the global flush/invalidate flags. These
+ * will be modified as new domains are computed
+ * for each object
+ */
+ dev->invalidate_domains = 0;
+ dev->flush_domains = 0;
+
for (i = 0; i < args->buffer_count; i++) {
struct drm_gem_object *obj = object_list[i];
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
- if (obj_priv->gtt_space == NULL) {
- /* We evicted the buffer in the process of validating
- * our set of buffers in. We could try to recover by
- * kicking them everything out and trying again from
- * the start.
- */
- ret = -ENOMEM;
- goto err;
- }
-
- /* make sure all previous memory operations have passed */
- ret = i915_gem_object_set_domain(obj,
- obj->pending_read_domains,
- obj->pending_write_domain);
- if (ret)
- goto err;
+ /* Compute new gpu domains and update invalidate/flush */
+ i915_gem_object_set_to_gpu_domain(obj,
+ obj->pending_read_domains,
+ obj->pending_write_domain);
}
i915_verify_inactive(dev, __FILE__, __LINE__);
- /* Flush/invalidate caches and chipset buffer */
- flush_domains = i915_gem_dev_set_domain(dev);
+ if (dev->invalidate_domains | dev->flush_domains) {
+#if WATCH_EXEC
+ DRM_INFO("%s: invalidate_domains %08x flush_domains %08x\n",
+ __func__,
+ dev->invalidate_domains,
+ dev->flush_domains);
+#endif
+ i915_gem_flush(dev,
+ dev->invalidate_domains,
+ dev->flush_domains);
+ if (dev->flush_domains)
+ (void)i915_add_request(dev, dev->flush_domains);
+ }
i915_verify_inactive(dev, __FILE__, __LINE__);
@@ -1913,8 +2100,6 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
~0);
#endif
- (void)i915_add_request(dev, flush_domains);
-
/* Exec the batchbuffer */
ret = i915_dispatch_gem_execbuffer(dev, args, exec_offset);
if (ret) {
@@ -1942,10 +2127,8 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
i915_file_priv->mm.last_gem_seqno = seqno;
for (i = 0; i < args->buffer_count; i++) {
struct drm_gem_object *obj = object_list[i];
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
- i915_gem_object_move_to_active(obj);
- obj_priv->last_rendering_seqno = seqno;
+ i915_gem_object_move_to_active(obj, seqno);
#if WATCH_LRU
DRM_INFO("%s: move to exec list %p\n", __func__, obj);
#endif
@@ -2076,11 +2259,7 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data,
/* XXX - flush the CPU caches for pinned objects
* as the X server doesn't manage domains yet
*/
- if (obj->write_domain & I915_GEM_DOMAIN_CPU) {
- i915_gem_clflush_object(obj);
- drm_agp_chipset_flush(dev);
- obj->write_domain = 0;
- }
+ i915_gem_object_flush_cpu_write_domain(obj);
args->offset = obj_priv->gtt_offset;
drm_gem_object_unreference(obj);
mutex_unlock(&dev->struct_mutex);
@@ -2130,7 +2309,14 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
}
obj_priv = obj->driver_private;
- args->busy = obj_priv->active;
+ /* Don't count being on the flushing list against the object being
+ * done. Otherwise, a buffer left on the flushing list but not getting
+ * flushed (because nobody's flushing that domain) won't ever return
+ * unbusy and get reused by libdrm's bo cache. The other expected
+ * consumer of this interface, OpenGL's occlusion queries, also specs
+ * that the objects get unbusy "eventually" without any interference.
+ */
+ args->busy = obj_priv->active && obj_priv->last_rendering_seqno != 0;
drm_gem_object_unreference(obj);
mutex_unlock(&dev->struct_mutex);
@@ -2182,29 +2368,6 @@ void i915_gem_free_object(struct drm_gem_object *obj)
drm_free(obj->driver_private, 1, DRM_MEM_DRIVER);
}
-static int
-i915_gem_set_domain(struct drm_gem_object *obj,
- struct drm_file *file_priv,
- uint32_t read_domains,
- uint32_t write_domain)
-{
- struct drm_device *dev = obj->dev;
- int ret;
- uint32_t flush_domains;
-
- BUG_ON(!mutex_is_locked(&dev->struct_mutex));
-
- ret = i915_gem_object_set_domain(obj, read_domains, write_domain);
- if (ret)
- return ret;
- flush_domains = i915_gem_dev_set_domain(obj->dev);
-
- if (flush_domains & ~(I915_GEM_DOMAIN_CPU|I915_GEM_DOMAIN_GTT))
- (void) i915_add_request(dev, flush_domains);
-
- return 0;
-}
-
/** Unbinds all objects that are on the given buffer list. */
static int
i915_gem_evict_from_list(struct drm_device *dev, struct list_head *head)
@@ -2299,29 +2462,52 @@ i915_gem_idle(struct drm_device *dev)
i915_gem_retire_requests(dev);
- /* Active and flushing should now be empty as we've
- * waited for a sequence higher than any pending execbuffer
- */
- BUG_ON(!list_empty(&dev_priv->mm.active_list));
- BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
+ if (!dev_priv->mm.wedged) {
+ /* Active and flushing should now be empty as we've
+ * waited for a sequence higher than any pending execbuffer
+ */
+ WARN_ON(!list_empty(&dev_priv->mm.active_list));
+ WARN_ON(!list_empty(&dev_priv->mm.flushing_list));
+ /* Request should now be empty as we've also waited
+ * for the last request in the list
+ */
+ WARN_ON(!list_empty(&dev_priv->mm.request_list));
+ }
- /* Request should now be empty as we've also waited
- * for the last request in the list
+ /* Empty the active and flushing lists to inactive. If there's
+ * anything left at this point, it means that we're wedged and
+ * nothing good's going to happen by leaving them there. So strip
+ * the GPU domains and just stuff them onto inactive.
*/
- BUG_ON(!list_empty(&dev_priv->mm.request_list));
+ while (!list_empty(&dev_priv->mm.active_list)) {
+ struct drm_i915_gem_object *obj_priv;
+
+ obj_priv = list_first_entry(&dev_priv->mm.active_list,
+ struct drm_i915_gem_object,
+ list);
+ obj_priv->obj->write_domain &= ~I915_GEM_GPU_DOMAINS;
+ i915_gem_object_move_to_inactive(obj_priv->obj);
+ }
+
+ while (!list_empty(&dev_priv->mm.flushing_list)) {
+ struct drm_i915_gem_object *obj_priv;
- /* Move all buffers out of the GTT. */
+ obj_priv = list_first_entry(&dev_priv->mm.flushing_list,
+ struct drm_i915_gem_object,
+ list);
+ obj_priv->obj->write_domain &= ~I915_GEM_GPU_DOMAINS;
+ i915_gem_object_move_to_inactive(obj_priv->obj);
+ }
+
+
+ /* Move all inactive buffers out of the GTT. */
ret = i915_gem_evict_from_list(dev, &dev_priv->mm.inactive_list);
+ WARN_ON(!list_empty(&dev_priv->mm.inactive_list));
if (ret) {
mutex_unlock(&dev->struct_mutex);
return ret;
}
- BUG_ON(!list_empty(&dev_priv->mm.active_list));
- BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
- BUG_ON(!list_empty(&dev_priv->mm.inactive_list));
- BUG_ON(!list_empty(&dev_priv->mm.request_list));
-
i915_gem_cleanup_ringbuffer(dev);
mutex_unlock(&dev->struct_mutex);
diff --git a/drivers/gpu/drm/i915/i915_gem_proc.c b/drivers/gpu/drm/i915/i915_gem_proc.c
index 93de15b4c9a..e8d5abe1250 100644
--- a/drivers/gpu/drm/i915/i915_gem_proc.c
+++ b/drivers/gpu/drm/i915/i915_gem_proc.c
@@ -166,10 +166,9 @@ static int i915_gem_request_info(char *buf, char **start, off_t offset,
list_for_each_entry(gem_request, &dev_priv->mm.request_list,
list)
{
- DRM_PROC_PRINT(" %d @ %d %08x\n",
+ DRM_PROC_PRINT(" %d @ %d\n",
gem_request->seqno,
- (int) (jiffies - gem_request->emitted_jiffies),
- gem_request->flush_domains);
+ (int) (jiffies - gem_request->emitted_jiffies));
}
if (len > request + offset)
return request;
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c
index e8b85ac4ca0..a8cb69469c6 100644
--- a/drivers/gpu/drm/i915/i915_gem_tiling.c
+++ b/drivers/gpu/drm/i915/i915_gem_tiling.c
@@ -119,9 +119,10 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
dcc & DCC_CHANNEL_XOR_DISABLE) {
swizzle_x = I915_BIT_6_SWIZZLE_9_10;
swizzle_y = I915_BIT_6_SWIZZLE_9;
- } else if (IS_I965GM(dev) || IS_GM45(dev)) {
- /* GM965 only does bit 11-based channel
- * randomization
+ } else if ((IS_I965GM(dev) || IS_GM45(dev)) &&
+ (dcc & DCC_CHANNEL_XOR_BIT_17) == 0) {
+ /* GM965/GM45 does either bit 11 or bit 17
+ * swizzling.
*/
swizzle_x = I915_BIT_6_SWIZZLE_9_10_11;
swizzle_y = I915_BIT_6_SWIZZLE_9_11;
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 82752d6177a..69b9a42da95 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -33,11 +33,23 @@
#define MAX_NOPID ((u32)~0)
-/** These are the interrupts used by the driver */
-#define I915_INTERRUPT_ENABLE_MASK (I915_USER_INTERRUPT | \
- I915_ASLE_INTERRUPT | \
- I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | \
- I915_DISPLAY_PIPE_B_EVENT_INTERRUPT)
+/**
+ * Interrupts that are always left unmasked.
+ *
+ * Since pipe events are edge-triggered from the PIPESTAT register to IIR,
+ * we leave them always unmasked in IMR and then control enabling them through
+ * PIPESTAT alone.
+ */
+#define I915_INTERRUPT_ENABLE_FIX (I915_ASLE_INTERRUPT | \
+ I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | \
+ I915_DISPLAY_PIPE_B_EVENT_INTERRUPT)
+
+/** Interrupts that we mask and unmask at runtime. */
+#define I915_INTERRUPT_ENABLE_VAR (I915_USER_INTERRUPT)
+
+/** These are all of the interrupts used by the driver */
+#define I915_INTERRUPT_ENABLE_MASK (I915_INTERRUPT_ENABLE_FIX | \
+ I915_INTERRUPT_ENABLE_VAR)
void
i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask)
@@ -59,6 +71,41 @@ i915_disable_irq(drm_i915_private_t *dev_priv, u32 mask)
}
}
+static inline u32
+i915_pipestat(int pipe)
+{
+ if (pipe == 0)
+ return PIPEASTAT;
+ if (pipe == 1)
+ return PIPEBSTAT;
+ BUG();
+}
+
+void
+i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask)
+{
+ if ((dev_priv->pipestat[pipe] & mask) != mask) {
+ u32 reg = i915_pipestat(pipe);
+
+ dev_priv->pipestat[pipe] |= mask;
+ /* Enable the interrupt, clear any pending status */
+ I915_WRITE(reg, dev_priv->pipestat[pipe] | (mask >> 16));
+ (void) I915_READ(reg);
+ }
+}
+
+void
+i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask)
+{
+ if ((dev_priv->pipestat[pipe] & mask) != 0) {
+ u32 reg = i915_pipestat(pipe);
+
+ dev_priv->pipestat[pipe] &= ~mask;
+ I915_WRITE(reg, dev_priv->pipestat[pipe]);
+ (void) I915_READ(reg);
+ }
+}
+
/**
* i915_pipe_enabled - check if a pipe is enabled
* @dev: DRM device
@@ -121,80 +168,102 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
{
struct drm_device *dev = (struct drm_device *) arg;
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
- u32 iir;
+ u32 iir, new_iir;
u32 pipea_stats, pipeb_stats;
+ u32 vblank_status;
+ u32 vblank_enable;
int vblank = 0;
+ unsigned long irqflags;
+ int irq_received;
+ int ret = IRQ_NONE;
atomic_inc(&dev_priv->irq_received);
- if (dev->pdev->msi_enabled)
- I915_WRITE(IMR, ~0);
iir = I915_READ(IIR);
- if (iir == 0) {
- if (dev->pdev->msi_enabled) {
- I915_WRITE(IMR, dev_priv->irq_mask_reg);
- (void) I915_READ(IMR);
- }
- return IRQ_NONE;
+ if (IS_I965G(dev)) {
+ vblank_status = I915_START_VBLANK_INTERRUPT_STATUS;
+ vblank_enable = PIPE_START_VBLANK_INTERRUPT_ENABLE;
+ } else {
+ vblank_status = I915_VBLANK_INTERRUPT_STATUS;
+ vblank_enable = I915_VBLANK_INTERRUPT_ENABLE;
}
- /*
- * Clear the PIPE(A|B)STAT regs before the IIR otherwise
- * we may get extra interrupts.
- */
- if (iir & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT) {
+ for (;;) {
+ irq_received = iir != 0;
+
+ /* Can't rely on pipestat interrupt bit in iir as it might
+ * have been cleared after the pipestat interrupt was received.
+ * It doesn't set the bit in iir again, but it still produces
+ * interrupts (for non-MSI).
+ */
+ spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
pipea_stats = I915_READ(PIPEASTAT);
- if (!(dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A))
- pipea_stats &= ~(PIPE_START_VBLANK_INTERRUPT_ENABLE |
- PIPE_VBLANK_INTERRUPT_ENABLE);
- else if (pipea_stats & (PIPE_START_VBLANK_INTERRUPT_STATUS|
- PIPE_VBLANK_INTERRUPT_STATUS)) {
+ pipeb_stats = I915_READ(PIPEBSTAT);
+ /*
+ * Clear the PIPE(A|B)STAT regs before the IIR
+ */
+ if (pipea_stats & 0x8000ffff) {
+ I915_WRITE(PIPEASTAT, pipea_stats);
+ irq_received = 1;
+ }
+
+ if (pipeb_stats & 0x8000ffff) {
+ I915_WRITE(PIPEBSTAT, pipeb_stats);
+ irq_received = 1;
+ }
+ spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
+
+ if (!irq_received)
+ break;
+
+ ret = IRQ_HANDLED;
+
+ I915_WRITE(IIR, iir);
+ new_iir = I915_READ(IIR); /* Flush posted writes */
+
+ if (dev_priv->sarea_priv)
+ dev_priv->sarea_priv->last_dispatch =
+ READ_BREADCRUMB(dev_priv);
+
+ if (iir & I915_USER_INTERRUPT) {
+ dev_priv->mm.irq_gem_seqno = i915_get_gem_seqno(dev);
+ DRM_WAKEUP(&dev_priv->irq_queue);
+ }
+
+ if (pipea_stats & vblank_status) {
vblank++;
drm_handle_vblank(dev, 0);
}
- I915_WRITE(PIPEASTAT, pipea_stats);
- }
- if (iir & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) {
- pipeb_stats = I915_READ(PIPEBSTAT);
- /* Ack the event */
- I915_WRITE(PIPEBSTAT, pipeb_stats);
-
- /* The vblank interrupt gets enabled even if we didn't ask for
- it, so make sure it's shut down again */
- if (!(dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B))
- pipeb_stats &= ~(PIPE_START_VBLANK_INTERRUPT_ENABLE |
- PIPE_VBLANK_INTERRUPT_ENABLE);
- else if (pipeb_stats & (PIPE_START_VBLANK_INTERRUPT_STATUS|
- PIPE_VBLANK_INTERRUPT_STATUS)) {
+ if (pipeb_stats & vblank_status) {
vblank++;
drm_handle_vblank(dev, 1);
}
- if (pipeb_stats & I915_LEGACY_BLC_EVENT_STATUS)
+ if ((pipeb_stats & I915_LEGACY_BLC_EVENT_STATUS) ||
+ (iir & I915_ASLE_INTERRUPT))
opregion_asle_intr(dev);
- I915_WRITE(PIPEBSTAT, pipeb_stats);
- }
-
- I915_WRITE(IIR, iir);
- if (dev->pdev->msi_enabled)
- I915_WRITE(IMR, dev_priv->irq_mask_reg);
- (void) I915_READ(IIR); /* Flush posted writes */
-
- if (dev_priv->sarea_priv)
- dev_priv->sarea_priv->last_dispatch =
- READ_BREADCRUMB(dev_priv);
- if (iir & I915_USER_INTERRUPT) {
- dev_priv->mm.irq_gem_seqno = i915_get_gem_seqno(dev);
- DRM_WAKEUP(&dev_priv->irq_queue);
+ /* With MSI, interrupts are only generated when iir
+ * transitions from zero to nonzero. If another bit got
+ * set while we were handling the existing iir bits, then
+ * we would never get another interrupt.
+ *
+ * This is fine on non-MSI as well, as if we hit this path
+ * we avoid exiting the interrupt handler only to generate
+ * another one.
+ *
+ * Note that for MSI this could cause a stray interrupt report
+ * if an interrupt landed in the time between writing IIR and
+ * the posting read. This should be rare enough to never
+ * trigger the 99% of 100,000 interrupts test for disabling
+ * stray interrupts.
+ */
+ iir = new_iir;
}
- if (iir & I915_ASLE_INTERRUPT)
- opregion_asle_intr(dev);
-
- return IRQ_HANDLED;
+ return ret;
}
static int i915_emit_irq(struct drm_device * dev)
@@ -330,48 +399,16 @@ int i915_irq_wait(struct drm_device *dev, void *data,
int i915_enable_vblank(struct drm_device *dev, int pipe)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
- u32 pipestat_reg = 0;
- u32 pipestat;
- u32 interrupt = 0;
unsigned long irqflags;
- switch (pipe) {
- case 0:
- pipestat_reg = PIPEASTAT;
- interrupt = I915_DISPLAY_PIPE_A_EVENT_INTERRUPT;
- break;
- case 1:
- pipestat_reg = PIPEBSTAT;
- interrupt = I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
- break;
- default:
- DRM_ERROR("tried to enable vblank on non-existent pipe %d\n",
- pipe);
- return 0;
- }
-
spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
- /* Enabling vblank events in IMR comes before PIPESTAT write, or
- * there's a race where the PIPESTAT vblank bit gets set to 1, so
- * the OR of enabled PIPESTAT bits goes to 1, so the PIPExEVENT in
- * ISR flashes to 1, but the IIR bit doesn't get set to 1 because
- * IMR masks it. It doesn't ever get set after we clear the masking
- * in IMR because the ISR bit is edge, not level-triggered, on the
- * OR of PIPESTAT bits.
- */
- i915_enable_irq(dev_priv, interrupt);
- pipestat = I915_READ(pipestat_reg);
if (IS_I965G(dev))
- pipestat |= PIPE_START_VBLANK_INTERRUPT_ENABLE;
+ i915_enable_pipestat(dev_priv, pipe,
+ PIPE_START_VBLANK_INTERRUPT_ENABLE);
else
- pipestat |= PIPE_VBLANK_INTERRUPT_ENABLE;
- /* Clear any stale interrupt status */
- pipestat |= (PIPE_START_VBLANK_INTERRUPT_STATUS |
- PIPE_VBLANK_INTERRUPT_STATUS);
- I915_WRITE(pipestat_reg, pipestat);
- (void) I915_READ(pipestat_reg); /* Posting read */
+ i915_enable_pipestat(dev_priv, pipe,
+ PIPE_VBLANK_INTERRUPT_ENABLE);
spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
-
return 0;
}
@@ -381,37 +418,12 @@ int i915_enable_vblank(struct drm_device *dev, int pipe)
void i915_disable_vblank(struct drm_device *dev, int pipe)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
- u32 pipestat_reg = 0;
- u32 pipestat;
- u32 interrupt = 0;
unsigned long irqflags;
- switch (pipe) {
- case 0:
- pipestat_reg = PIPEASTAT;
- interrupt = I915_DISPLAY_PIPE_A_EVENT_INTERRUPT;
- break;
- case 1:
- pipestat_reg = PIPEBSTAT;
- interrupt = I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
- break;
- default:
- DRM_ERROR("tried to disable vblank on non-existent pipe %d\n",
- pipe);
- return;
- break;
- }
-
spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
- i915_disable_irq(dev_priv, interrupt);
- pipestat = I915_READ(pipestat_reg);
- pipestat &= ~(PIPE_START_VBLANK_INTERRUPT_ENABLE |
- PIPE_VBLANK_INTERRUPT_ENABLE);
- /* Clear any stale interrupt status */
- pipestat |= (PIPE_START_VBLANK_INTERRUPT_STATUS |
- PIPE_VBLANK_INTERRUPT_STATUS);
- I915_WRITE(pipestat_reg, pipestat);
- (void) I915_READ(pipestat_reg); /* Posting read */
+ i915_disable_pipestat(dev_priv, pipe,
+ PIPE_VBLANK_INTERRUPT_ENABLE |
+ PIPE_START_VBLANK_INTERRUPT_ENABLE);
spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
}
@@ -476,32 +488,35 @@ void i915_driver_irq_preinstall(struct drm_device * dev)
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
I915_WRITE(HWSTAM, 0xeffe);
+ I915_WRITE(PIPEASTAT, 0);
+ I915_WRITE(PIPEBSTAT, 0);
I915_WRITE(IMR, 0xffffffff);
I915_WRITE(IER, 0x0);
+ (void) I915_READ(IER);
}
int i915_driver_irq_postinstall(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
- int ret, num_pipes = 2;
-
- /* Set initial unmasked IRQs to just the selected vblank pipes. */
- dev_priv->irq_mask_reg = ~0;
-
- ret = drm_vblank_init(dev, num_pipes);
- if (ret)
- return ret;
dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
- dev_priv->irq_mask_reg &= ~I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT;
- dev_priv->irq_mask_reg &= ~I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
- dev_priv->irq_mask_reg &= I915_INTERRUPT_ENABLE_MASK;
+ /* Unmask the interrupts that we always want on. */
+ dev_priv->irq_mask_reg = ~I915_INTERRUPT_ENABLE_FIX;
+
+ dev_priv->pipestat[0] = 0;
+ dev_priv->pipestat[1] = 0;
+
+ /* Disable pipe interrupt enables, clear pending pipe status */
+ I915_WRITE(PIPEASTAT, I915_READ(PIPEASTAT) & 0x8000ffff);
+ I915_WRITE(PIPEBSTAT, I915_READ(PIPEBSTAT) & 0x8000ffff);
+ /* Clear pending interrupt status */
+ I915_WRITE(IIR, I915_READ(IIR));
- I915_WRITE(IMR, dev_priv->irq_mask_reg);
I915_WRITE(IER, I915_INTERRUPT_ENABLE_MASK);
+ I915_WRITE(IMR, dev_priv->irq_mask_reg);
(void) I915_READ(IER);
opregion_enable_asle(dev);
@@ -513,7 +528,6 @@ int i915_driver_irq_postinstall(struct drm_device *dev)
void i915_driver_irq_uninstall(struct drm_device * dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
- u32 temp;
if (!dev_priv)
return;
@@ -521,13 +535,12 @@ void i915_driver_irq_uninstall(struct drm_device * dev)
dev_priv->vblank_pipe = 0;
I915_WRITE(HWSTAM, 0xffffffff);
+ I915_WRITE(PIPEASTAT, 0);
+ I915_WRITE(PIPEBSTAT, 0);
I915_WRITE(IMR, 0xffffffff);
I915_WRITE(IER, 0x0);
- temp = I915_READ(PIPEASTAT);
- I915_WRITE(PIPEASTAT, temp);
- temp = I915_READ(PIPEBSTAT);
- I915_WRITE(PIPEBSTAT, temp);
- temp = I915_READ(IIR);
- I915_WRITE(IIR, temp);
+ I915_WRITE(PIPEASTAT, I915_READ(PIPEASTAT) & 0x8000ffff);
+ I915_WRITE(PIPEBSTAT, I915_READ(PIPEBSTAT) & 0x8000ffff);
+ I915_WRITE(IIR, I915_READ(IIR));
}
diff --git a/drivers/gpu/drm/i915/i915_opregion.c b/drivers/gpu/drm/i915/i915_opregion.c
index 1787a0c7e3a..13ae731a33d 100644
--- a/drivers/gpu/drm/i915/i915_opregion.c
+++ b/drivers/gpu/drm/i915/i915_opregion.c
@@ -235,17 +235,15 @@ void opregion_enable_asle(struct drm_device *dev)
struct opregion_asle *asle = dev_priv->opregion.asle;
if (asle) {
- u32 pipeb_stats = I915_READ(PIPEBSTAT);
if (IS_MOBILE(dev)) {
- /* Many devices trigger events with a write to the
- legacy backlight controller, so we need to ensure
- that it's able to generate interrupts */
- I915_WRITE(PIPEBSTAT, pipeb_stats |=
- I915_LEGACY_BLC_EVENT_ENABLE);
- i915_enable_irq(dev_priv, I915_ASLE_INTERRUPT |
- I915_DISPLAY_PIPE_B_EVENT_INTERRUPT);
- } else
- i915_enable_irq(dev_priv, I915_ASLE_INTERRUPT);
+ unsigned long irqflags;
+
+ spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
+ i915_enable_pipestat(dev_priv, 1,
+ I915_LEGACY_BLC_EVENT_ENABLE);
+ spin_unlock_irqrestore(&dev_priv->user_irq_lock,
+ irqflags);
+ }
asle->tche = ASLE_ALS_EN | ASLE_BLC_EN | ASLE_PFIT_EN |
ASLE_PFMB_EN;
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 0e476eba36e..9d24aaeb8a4 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -522,6 +522,7 @@
#define DCC_ADDRESSING_MODE_DUAL_CHANNEL_INTERLEAVED (2 << 0)
#define DCC_ADDRESSING_MODE_MASK (3 << 0)
#define DCC_CHANNEL_XOR_DISABLE (1 << 10)
+#define DCC_CHANNEL_XOR_BIT_17 (1 << 9)
/** 965 MCH register controlling DRAM channel configuration */
#define C0DRB3 0x10206
diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c
index 5ddc6e595c0..5d84027ee8f 100644
--- a/drivers/gpu/drm/i915/i915_suspend.c
+++ b/drivers/gpu/drm/i915/i915_suspend.c
@@ -244,6 +244,9 @@ int i915_save_state(struct drm_device *dev)
if (IS_I965G(dev) && IS_MOBILE(dev))
dev_priv->saveRENDERSTANDBY = I915_READ(MCHBAR_RENDER_STANDBY);
+ /* Hardware status page */
+ dev_priv->saveHWS = I915_READ(HWS_PGA);
+
/* Display arbitration control */
dev_priv->saveDSPARB = I915_READ(DSPARB);
@@ -373,6 +376,9 @@ int i915_restore_state(struct drm_device *dev)
if (IS_I965G(dev) && IS_MOBILE(dev))
I915_WRITE(MCHBAR_RENDER_STANDBY, dev_priv->saveRENDERSTANDBY);
+ /* Hardware status page */
+ I915_WRITE(HWS_PGA, dev_priv->saveHWS);
+
/* Display arbitration */
I915_WRITE(DSPARB, dev_priv->saveDSPARB);
diff --git a/drivers/gpu/drm/mga/mga_dma.c b/drivers/gpu/drm/mga/mga_dma.c
index c1d12dbfa8d..b49c5ff2958 100644
--- a/drivers/gpu/drm/mga/mga_dma.c
+++ b/drivers/gpu/drm/mga/mga_dma.c
@@ -396,6 +396,7 @@ int mga_freelist_put(struct drm_device * dev, struct drm_buf * buf)
int mga_driver_load(struct drm_device * dev, unsigned long flags)
{
drm_mga_private_t *dev_priv;
+ int ret;
dev_priv = drm_alloc(sizeof(drm_mga_private_t), DRM_MEM_DRIVER);
if (!dev_priv)
@@ -415,6 +416,13 @@ int mga_driver_load(struct drm_device * dev, unsigned long flags)
dev->types[7] = _DRM_STAT_PRIMARY;
dev->types[8] = _DRM_STAT_SECONDARY;
+ ret = drm_vblank_init(dev, 1);
+
+ if (ret) {
+ (void) mga_driver_unload(dev);
+ return ret;
+ }
+
return 0;
}
diff --git a/drivers/gpu/drm/mga/mga_irq.c b/drivers/gpu/drm/mga/mga_irq.c
index bab42f41188..daa6041a483 100644
--- a/drivers/gpu/drm/mga/mga_irq.c
+++ b/drivers/gpu/drm/mga/mga_irq.c
@@ -152,11 +152,6 @@ void mga_driver_irq_preinstall(struct drm_device * dev)
int mga_driver_irq_postinstall(struct drm_device *dev)
{
drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
- int ret;
-
- ret = drm_vblank_init(dev, 1);
- if (ret)
- return ret;
DRM_INIT_WAITQUEUE(&dev_priv->fence_queue);
diff --git a/drivers/gpu/drm/r128/r128_drv.c b/drivers/gpu/drm/r128/r128_drv.c
index 3265d53ba91..601f4c0e5da 100644
--- a/drivers/gpu/drm/r128/r128_drv.c
+++ b/drivers/gpu/drm/r128/r128_drv.c
@@ -45,6 +45,7 @@ static struct drm_driver driver = {
DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
.dev_priv_size = sizeof(drm_r128_buf_priv_t),
+ .load = r128_driver_load,
.preclose = r128_driver_preclose,
.lastclose = r128_driver_lastclose,
.get_vblank_counter = r128_get_vblank_counter,
@@ -84,6 +85,11 @@ static struct drm_driver driver = {
.patchlevel = DRIVER_PATCHLEVEL,
};
+int r128_driver_load(struct drm_device * dev, unsigned long flags)
+{
+ return drm_vblank_init(dev, 1);
+}
+
static int __init r128_init(void)
{
driver.num_ioctls = r128_max_ioctl;
diff --git a/drivers/gpu/drm/r128/r128_drv.h b/drivers/gpu/drm/r128/r128_drv.h
index 5898b274279..797a26c42da 100644
--- a/drivers/gpu/drm/r128/r128_drv.h
+++ b/drivers/gpu/drm/r128/r128_drv.h
@@ -159,6 +159,7 @@ extern void r128_driver_irq_preinstall(struct drm_device * dev);
extern int r128_driver_irq_postinstall(struct drm_device *dev);
extern void r128_driver_irq_uninstall(struct drm_device * dev);
extern void r128_driver_lastclose(struct drm_device * dev);
+extern int r128_driver_load(struct drm_device * dev, unsigned long flags);
extern void r128_driver_preclose(struct drm_device * dev,
struct drm_file *file_priv);
diff --git a/drivers/gpu/drm/r128/r128_irq.c b/drivers/gpu/drm/r128/r128_irq.c
index d7349012a68..69810fb8ac4 100644
--- a/drivers/gpu/drm/r128/r128_irq.c
+++ b/drivers/gpu/drm/r128/r128_irq.c
@@ -102,7 +102,7 @@ void r128_driver_irq_preinstall(struct drm_device * dev)
int r128_driver_irq_postinstall(struct drm_device *dev)
{
- return drm_vblank_init(dev, 1);
+ return 0;
}
void r128_driver_irq_uninstall(struct drm_device * dev)
diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c
index abdc1ae3846..dcebb4bee7a 100644
--- a/drivers/gpu/drm/radeon/radeon_cp.c
+++ b/drivers/gpu/drm/radeon/radeon_cp.c
@@ -1757,6 +1757,12 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags)
if (ret != 0)
return ret;
+ ret = drm_vblank_init(dev, 2);
+ if (ret) {
+ radeon_driver_unload(dev);
+ return ret;
+ }
+
DRM_DEBUG("%s card detected\n",
((dev_priv->flags & RADEON_IS_AGP) ? "AGP" : (((dev_priv->flags & RADEON_IS_PCIE) ? "PCIE" : "PCI"))));
return ret;
diff --git a/drivers/gpu/drm/radeon/radeon_drv.h b/drivers/gpu/drm/radeon/radeon_drv.h
index 7a183789be9..3bbb871b25d 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.h
+++ b/drivers/gpu/drm/radeon/radeon_drv.h
@@ -299,7 +299,6 @@ typedef struct drm_radeon_private {
atomic_t swi_emitted;
int vblank_crtc;
uint32_t irq_enable_reg;
- int irq_enabled;
uint32_t r500_disp_irq_reg;
struct radeon_surface surfaces[RADEON_MAX_SURFACES];
diff --git a/drivers/gpu/drm/radeon/radeon_irq.c b/drivers/gpu/drm/radeon/radeon_irq.c
index 5079f7054a2..8289e16419a 100644
--- a/drivers/gpu/drm/radeon/radeon_irq.c
+++ b/drivers/gpu/drm/radeon/radeon_irq.c
@@ -44,7 +44,8 @@ void radeon_irq_set_state(struct drm_device *dev, u32 mask, int state)
else
dev_priv->irq_enable_reg &= ~mask;
- RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg);
+ if (dev->irq_enabled)
+ RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg);
}
static void r500_vbl_irq_set_state(struct drm_device *dev, u32 mask, int state)
@@ -56,7 +57,8 @@ static void r500_vbl_irq_set_state(struct drm_device *dev, u32 mask, int state)
else
dev_priv->r500_disp_irq_reg &= ~mask;
- RADEON_WRITE(R500_DxMODE_INT_MASK, dev_priv->r500_disp_irq_reg);
+ if (dev->irq_enabled)
+ RADEON_WRITE(R500_DxMODE_INT_MASK, dev_priv->r500_disp_irq_reg);
}
int radeon_enable_vblank(struct drm_device *dev, int crtc)
@@ -337,15 +339,10 @@ int radeon_driver_irq_postinstall(struct drm_device *dev)
{
drm_radeon_private_t *dev_priv =
(drm_radeon_private_t *) dev->dev_private;
- int ret;
atomic_set(&dev_priv->swi_emitted, 0);
DRM_INIT_WAITQUEUE(&dev_priv->swi_queue);
- ret = drm_vblank_init(dev, 2);
- if (ret)
- return ret;
-
dev->max_vblank_count = 0x001fffff;
radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1);
@@ -360,8 +357,6 @@ void radeon_driver_irq_uninstall(struct drm_device * dev)
if (!dev_priv)
return;
- dev_priv->irq_enabled = 0;
-
if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS690)
RADEON_WRITE(R500_DxMODE_INT_MASK, 0);
/* Disable *all* interrupts */
diff --git a/drivers/gpu/drm/via/via_irq.c b/drivers/gpu/drm/via/via_irq.c
index 665d319b927..c248c1d3726 100644
--- a/drivers/gpu/drm/via/via_irq.c
+++ b/drivers/gpu/drm/via/via_irq.c
@@ -314,7 +314,6 @@ int via_driver_irq_postinstall(struct drm_device *dev)
if (!dev_priv)
return -EINVAL;
- drm_vblank_init(dev, 1);
status = VIA_READ(VIA_REG_INTERRUPT);
VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL
| dev_priv->irq_enable_mask);
diff --git a/drivers/gpu/drm/via/via_map.c b/drivers/gpu/drm/via/via_map.c
index a967556be01..2c4f0b48579 100644
--- a/drivers/gpu/drm/via/via_map.c
+++ b/drivers/gpu/drm/via/via_map.c
@@ -107,8 +107,17 @@ int via_driver_load(struct drm_device *dev, unsigned long chipset)
ret = drm_sman_init(&dev_priv->sman, 2, 12, 8);
if (ret) {
drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);
+ return ret;
}
- return ret;
+
+ ret = drm_vblank_init(dev, 1);
+ if (ret) {
+ drm_sman_takedown(&dev_priv->sman);
+ drm_free(dev_priv, sizeof(drm_via_private_t), DRM_MEM_DRIVER);
+ return ret;
+ }
+
+ return 0;
}
int via_driver_unload(struct drm_device *dev)
diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c
index c6ab4ba60c5..aa28aed0e46 100644
--- a/drivers/hid/hid-apple.c
+++ b/drivers/hid/hid-apple.c
@@ -55,10 +55,11 @@ struct apple_key_translation {
static struct apple_key_translation apple_fn_keys[] = {
{ KEY_BACKSPACE, KEY_DELETE },
+ { KEY_ENTER, KEY_INSERT },
{ KEY_F1, KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY },
{ KEY_F2, KEY_BRIGHTNESSUP, APPLE_FLAG_FKEY },
- { KEY_F3, KEY_FN_F5, APPLE_FLAG_FKEY }, /* Exposé */
- { KEY_F4, KEY_FN_F4, APPLE_FLAG_FKEY }, /* Dashboard */
+ { KEY_F3, KEY_SCALE, APPLE_FLAG_FKEY },
+ { KEY_F4, KEY_DASHBOARD, APPLE_FLAG_FKEY },
{ KEY_F5, KEY_KBDILLUMDOWN, APPLE_FLAG_FKEY },
{ KEY_F6, KEY_KBDILLUMUP, APPLE_FLAG_FKEY },
{ KEY_F7, KEY_PREVIOUSSONG, APPLE_FLAG_FKEY },
@@ -399,12 +400,12 @@ static const struct hid_device_id apple_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS),
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
APPLE_RDESC_JIS },
- { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI),
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI),
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
- { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO),
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO),
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
APPLE_ISO_KEYBOARD },
- { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS),
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS),
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI),
.driver_data = APPLE_HAS_FN },
@@ -418,6 +419,12 @@ static const struct hid_device_id apple_devices[] = {
.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS),
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI),
+ .driver_data = APPLE_HAS_FN },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO),
+ .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS),
+ .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY),
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY),
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index d3671b4049c..40df3e1b4bd 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1241,18 +1241,20 @@ static const struct hid_device_id hid_blacklist[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS) },
- { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI) },
- { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO) },
- { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS) },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI) },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO) },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ISO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_JIS) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
- { HID_USB_DEVICE(USB_VENDOR_ID_AVERMEDIA, USB_DEVICE_ID_AVER_FM_MR800) },
{ HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) },
{ HID_USB_DEVICE(USB_VENDOR_ID_BRIGHT, USB_DEVICE_ID_BRIGHT_ABNT2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) },
@@ -1264,8 +1266,10 @@ static const struct hid_device_id hid_blacklist[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_SK8115) },
{ HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GENERIC_13BA, USB_DEVICE_ID_GENERIC_13BA_KBD_MOUSE) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) },
- { HID_USB_DEVICE(USB_VENDOR_ID_KWORLD, USB_DEVICE_ID_KWORLD_RADIO_FM700) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) },
@@ -1409,6 +1413,7 @@ static const struct hid_device_id hid_ignore_list[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_ALCOR, USB_DEVICE_ID_ALCOR_USBRS232) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM)},
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM2)},
+ { HID_USB_DEVICE(USB_VENDOR_ID_AVERMEDIA, USB_DEVICE_ID_AVER_FM_MR800) },
{ HID_USB_DEVICE(USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CIDC, 0x0103) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_RADIO_SI470X) },
@@ -1418,7 +1423,6 @@ static const struct hid_device_id hid_ignore_list[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) },
- { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0001) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0002) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0003) },
@@ -1434,7 +1438,6 @@ static const struct hid_device_id hid_ignore_list[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_SUPER_Q2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_GOGOPEN) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_PENPOWER) },
- { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GRETAGMACBETH, USB_DEVICE_ID_GRETAGMACBETH_HUEY) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB) },
@@ -1486,6 +1489,7 @@ static const struct hid_device_id hid_ignore_list[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1007) },
{ HID_USB_DEVICE(USB_VENDOR_ID_IMATION, USB_DEVICE_ID_DISC_STAKKA) },
{ HID_USB_DEVICE(USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_KWORLD, USB_DEVICE_ID_KWORLD_RADIO_FM700) },
{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_GPEN_560) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY) },
@@ -1730,7 +1734,7 @@ static int __init hid_init(void)
goto err_bus;
#ifdef CONFIG_HID_COMPAT
- hid_compat_wq = create_workqueue("hid_compat");
+ hid_compat_wq = create_singlethread_workqueue("hid_compat");
if (!hid_compat_wq) {
hidraw_exit();
goto err;
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index f05bcbbbb0d..39289699c32 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -82,6 +82,9 @@
#define USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI 0x0230
#define USB_DEVICE_ID_APPLE_WELLSPRING2_ISO 0x0231
#define USB_DEVICE_ID_APPLE_WELLSPRING2_JIS 0x0232
+#define USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI 0x0236
+#define USB_DEVICE_ID_APPLE_WELLSPRING3_ISO 0x0237
+#define USB_DEVICE_ID_APPLE_WELLSPRING3_JIS 0x0238
#define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a
#define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b
#define USB_DEVICE_ID_APPLE_ATV_IRCONTROL 0x8241
@@ -160,6 +163,7 @@
#define USB_VENDOR_ID_GAMERON 0x0810
#define USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR 0x0001
+#define USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR 0x0002
#define USB_VENDOR_ID_GENERAL_TOUCH 0x0dfc
diff --git a/drivers/hid/hid-pl.c b/drivers/hid/hid-pl.c
index acd81558618..46941f979b9 100644
--- a/drivers/hid/hid-pl.c
+++ b/drivers/hid/hid-pl.c
@@ -178,6 +178,8 @@ err:
static const struct hid_device_id pl_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR),
.driver_data = 1 }, /* Twin USB Joystick */
+ { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR),
+ .driver_data = 1 }, /* Twin USB Joystick */
{ HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003), }, /* GreenAsia Inc. USB Joystick */
{ }
};
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index 894d52e05bf..7685ae6808c 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -38,7 +38,7 @@ static int hidraw_major;
static struct cdev hidraw_cdev;
static struct class *hidraw_class;
static struct hidraw *hidraw_table[HIDRAW_MAX_DEVICES];
-static DEFINE_SPINLOCK(minors_lock);
+static DEFINE_MUTEX(minors_lock);
static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
{
@@ -159,13 +159,13 @@ static int hidraw_open(struct inode *inode, struct file *file)
struct hidraw_list *list;
int err = 0;
- lock_kernel();
if (!(list = kzalloc(sizeof(struct hidraw_list), GFP_KERNEL))) {
err = -ENOMEM;
goto out;
}
- spin_lock(&minors_lock);
+ lock_kernel();
+ mutex_lock(&minors_lock);
if (!hidraw_table[minor]) {
printk(KERN_EMERG "hidraw device with minor %d doesn't exist\n",
minor);
@@ -180,13 +180,16 @@ static int hidraw_open(struct inode *inode, struct file *file)
file->private_data = list;
dev = hidraw_table[minor];
- if (!dev->open++)
- dev->hid->ll_driver->open(dev->hid);
+ if (!dev->open++) {
+ err = dev->hid->ll_driver->open(dev->hid);
+ if (err < 0)
+ dev->open--;
+ }
out_unlock:
- spin_unlock(&minors_lock);
-out:
+ mutex_unlock(&minors_lock);
unlock_kernel();
+out:
return err;
}
@@ -310,7 +313,7 @@ int hidraw_connect(struct hid_device *hid)
result = -EINVAL;
- spin_lock(&minors_lock);
+ mutex_lock(&minors_lock);
for (minor = 0; minor < HIDRAW_MAX_DEVICES; minor++) {
if (hidraw_table[minor])
@@ -320,9 +323,8 @@ int hidraw_connect(struct hid_device *hid)
break;
}
- spin_unlock(&minors_lock);
-
if (result) {
+ mutex_unlock(&minors_lock);
kfree(dev);
goto out;
}
@@ -331,14 +333,14 @@ int hidraw_connect(struct hid_device *hid)
NULL, "%s%d", "hidraw", minor);
if (IS_ERR(dev->dev)) {
- spin_lock(&minors_lock);
hidraw_table[minor] = NULL;
- spin_unlock(&minors_lock);
+ mutex_unlock(&minors_lock);
result = PTR_ERR(dev->dev);
kfree(dev);
goto out;
}
+ mutex_unlock(&minors_lock);
init_waitqueue_head(&dev->wait);
INIT_LIST_HEAD(&dev->list);
@@ -360,9 +362,9 @@ void hidraw_disconnect(struct hid_device *hid)
hidraw->exist = 0;
- spin_lock(&minors_lock);
+ mutex_lock(&minors_lock);
hidraw_table[hidraw->minor] = NULL;
- spin_unlock(&minors_lock);
+ mutex_unlock(&minors_lock);
device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 18e5ddd722c..606369ea24c 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -781,6 +781,8 @@ static int usbhid_start(struct hid_device *hid)
unsigned int n, insize = 0;
int ret;
+ clear_bit(HID_DISCONNECTED, &usbhid->iofl);
+
usbhid->bufsize = HID_MIN_BUFFER_SIZE;
hid_find_max_report(hid, HID_INPUT_REPORT, &usbhid->bufsize);
hid_find_max_report(hid, HID_OUTPUT_REPORT, &usbhid->bufsize);
@@ -794,7 +796,6 @@ static int usbhid_start(struct hid_device *hid)
if (insize > HID_MAX_BUFFER_SIZE)
insize = HID_MAX_BUFFER_SIZE;
- mutex_lock(&usbhid->setup);
if (hid_alloc_buffers(dev, hid)) {
ret = -ENOMEM;
goto fail;
@@ -847,12 +848,6 @@ static int usbhid_start(struct hid_device *hid)
}
}
- if (!usbhid->urbin) {
- err_hid("couldn't find an input interrupt endpoint");
- ret = -ENODEV;
- goto fail;
- }
-
init_waitqueue_head(&usbhid->wait);
INIT_WORK(&usbhid->reset_work, hid_reset);
setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid);
@@ -880,7 +875,6 @@ static int usbhid_start(struct hid_device *hid)
hid_dump_device(hid);
set_bit(HID_STARTED, &usbhid->iofl);
- mutex_unlock(&usbhid->setup);
return 0;
@@ -888,8 +882,10 @@ fail:
usb_free_urb(usbhid->urbin);
usb_free_urb(usbhid->urbout);
usb_free_urb(usbhid->urbctrl);
+ usbhid->urbin = NULL;
+ usbhid->urbout = NULL;
+ usbhid->urbctrl = NULL;
hid_free_buffers(dev, hid);
- mutex_unlock(&usbhid->setup);
return ret;
}
@@ -900,7 +896,6 @@ static void usbhid_stop(struct hid_device *hid)
if (WARN_ON(!usbhid))
return;
- mutex_lock(&usbhid->setup);
clear_bit(HID_STARTED, &usbhid->iofl);
spin_lock_irq(&usbhid->inlock); /* Sync with error handler */
set_bit(HID_DISCONNECTED, &usbhid->iofl);
@@ -924,9 +919,11 @@ static void usbhid_stop(struct hid_device *hid)
usb_free_urb(usbhid->urbin);
usb_free_urb(usbhid->urbctrl);
usb_free_urb(usbhid->urbout);
+ usbhid->urbin = NULL; /* don't mess up next start */
+ usbhid->urbctrl = NULL;
+ usbhid->urbout = NULL;
hid_free_buffers(hid_to_usb_dev(hid), hid);
- mutex_unlock(&usbhid->setup);
}
static struct hid_ll_driver usb_hid_driver = {
@@ -940,15 +937,26 @@ static struct hid_ll_driver usb_hid_driver = {
static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
+ struct usb_host_interface *interface = intf->cur_altsetting;
struct usb_device *dev = interface_to_usbdev(intf);
struct usbhid_device *usbhid;
struct hid_device *hid;
+ unsigned int n, has_in = 0;
size_t len;
int ret;
dbg_hid("HID probe called for ifnum %d\n",
intf->altsetting->desc.bInterfaceNumber);
+ for (n = 0; n < interface->desc.bNumEndpoints; n++)
+ if (usb_endpoint_is_int_in(&interface->endpoint[n].desc))
+ has_in++;
+ if (!has_in) {
+ dev_err(&intf->dev, "couldn't find an input interrupt "
+ "endpoint\n");
+ return -ENODEV;
+ }
+
hid = hid_allocate_device();
if (IS_ERR(hid))
return PTR_ERR(hid);
@@ -1003,7 +1011,6 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
hid->driver_data = usbhid;
usbhid->hid = hid;
- mutex_init(&usbhid->setup); /* needed on suspend/resume */
ret = hid_add_device(hid);
if (ret) {
@@ -1038,18 +1045,14 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
struct hid_device *hid = usb_get_intfdata (intf);
struct usbhid_device *usbhid = hid->driver_data;
- mutex_lock(&usbhid->setup);
- if (!test_bit(HID_STARTED, &usbhid->iofl)) {
- mutex_unlock(&usbhid->setup);
+ if (!test_bit(HID_STARTED, &usbhid->iofl))
return 0;
- }
spin_lock_irq(&usbhid->inlock); /* Sync with error handler */
set_bit(HID_SUSPENDED, &usbhid->iofl);
spin_unlock_irq(&usbhid->inlock);
del_timer_sync(&usbhid->io_retry);
usb_kill_urb(usbhid->urbin);
- mutex_unlock(&usbhid->setup);
dev_dbg(&intf->dev, "suspend\n");
return 0;
}
@@ -1060,16 +1063,12 @@ static int hid_resume(struct usb_interface *intf)
struct usbhid_device *usbhid = hid->driver_data;
int status;
- mutex_lock(&usbhid->setup);
- if (!test_bit(HID_STARTED, &usbhid->iofl)) {
- mutex_unlock(&usbhid->setup);
+ if (!test_bit(HID_STARTED, &usbhid->iofl))
return 0;
- }
clear_bit(HID_SUSPENDED, &usbhid->iofl);
usbhid->retry_delay = 0;
status = hid_start_in(hid);
- mutex_unlock(&usbhid->setup);
dev_dbg(&intf->dev, "resume status %d\n", status);
return status;
}
diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h
index 55973ff5400..332abcdf995 100644
--- a/drivers/hid/usbhid/usbhid.h
+++ b/drivers/hid/usbhid/usbhid.h
@@ -74,7 +74,6 @@ struct usbhid_device {
dma_addr_t outbuf_dma; /* Output buffer dma */
spinlock_t outlock; /* Output fifo spinlock */
- struct mutex setup;
unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */
struct timer_list io_retry; /* Retry timer */
unsigned long stop_retry; /* Time to give up, in jiffies */
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 6de1e0ffd39..c709e821f04 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -159,6 +159,16 @@ config SENSORS_ADM9240
This driver can also be built as a module. If so, the module
will be called adm9240.
+config SENSORS_ADT7462
+ tristate "Analog Devices ADT7462"
+ depends on I2C && EXPERIMENTAL
+ help
+ If you say yes here you get support for the Analog Devices
+ ADT7462 temperature monitoring chips.
+
+ This driver can also be built as a module. If so, the module
+ will be called adt7462.
+
config SENSORS_ADT7470
tristate "Analog Devices ADT7470"
depends on I2C && EXPERIMENTAL
@@ -825,6 +835,25 @@ config SENSORS_HDAPS
Say Y here if you have an applicable laptop and want to experience
the awesome power of hdaps.
+config SENSORS_LIS3LV02D
+ tristate "STMicroeletronics LIS3LV02Dx three-axis digital accelerometer"
+ depends on ACPI && INPUT
+ default n
+ help
+ This driver provides support for the LIS3LV02Dx accelerometer. In
+ particular, it can be found in a number of HP laptops, which have the
+ "Mobile Data Protection System 3D" or "3D DriveGuard" feature. On such
+ systems the driver should load automatically (via ACPI). The
+ accelerometer might also be found in other systems, connected via SPI
+ or I2C. The accelerometer data is readable via
+ /sys/devices/platform/lis3lv02d.
+
+ This driver also provides an absolute input class device, allowing
+ the laptop to act as a pinball machine-esque joystick.
+
+ This driver can also be built as a module. If so, the module
+ will be called lis3lv02d.
+
config SENSORS_APPLESMC
tristate "Apple SMC (Motion sensor, light sensor, keyboard backlight)"
depends on INPUT && X86
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 042d5a78622..58fc5be5355 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_SENSORS_ADM1029) += adm1029.o
obj-$(CONFIG_SENSORS_ADM1031) += adm1031.o
obj-$(CONFIG_SENSORS_ADM9240) += adm9240.o
obj-$(CONFIG_SENSORS_ADS7828) += ads7828.o
+obj-$(CONFIG_SENSORS_ADT7462) += adt7462.o
obj-$(CONFIG_SENSORS_ADT7470) += adt7470.o
obj-$(CONFIG_SENSORS_ADT7473) += adt7473.o
obj-$(CONFIG_SENSORS_APPLESMC) += applesmc.o
@@ -48,6 +49,7 @@ obj-$(CONFIG_SENSORS_IBMAEM) += ibmaem.o
obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o
obj-$(CONFIG_SENSORS_IT87) += it87.o
obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o
+obj-$(CONFIG_SENSORS_LIS3LV02D) += lis3lv02d.o
obj-$(CONFIG_SENSORS_LM63) += lm63.o
obj-$(CONFIG_SENSORS_LM70) += lm70.o
obj-$(CONFIG_SENSORS_LM75) += lm75.o
diff --git a/drivers/hwmon/adt7462.c b/drivers/hwmon/adt7462.c
new file mode 100644
index 00000000000..66107b4dc12
--- /dev/null
+++ b/drivers/hwmon/adt7462.c
@@ -0,0 +1,2002 @@
+/*
+ * A hwmon driver for the Analog Devices ADT7462
+ * Copyright (C) 2008 IBM
+ *
+ * Author: Darrick J. Wong <djwong@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/jiffies.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/log2.h>
+
+/* Addresses to scan */
+static const unsigned short normal_i2c[] = { 0x58, 0x5C, I2C_CLIENT_END };
+
+/* Insmod parameters */
+I2C_CLIENT_INSMOD_1(adt7462);
+
+/* ADT7462 registers */
+#define ADT7462_REG_DEVICE 0x3D
+#define ADT7462_REG_VENDOR 0x3E
+#define ADT7462_REG_REVISION 0x3F
+
+#define ADT7462_REG_MIN_TEMP_BASE_ADDR 0x44
+#define ADT7462_REG_MIN_TEMP_MAX_ADDR 0x47
+#define ADT7462_REG_MAX_TEMP_BASE_ADDR 0x48
+#define ADT7462_REG_MAX_TEMP_MAX_ADDR 0x4B
+#define ADT7462_REG_TEMP_BASE_ADDR 0x88
+#define ADT7462_REG_TEMP_MAX_ADDR 0x8F
+
+#define ADT7462_REG_FAN_BASE_ADDR 0x98
+#define ADT7462_REG_FAN_MAX_ADDR 0x9F
+#define ADT7462_REG_FAN2_BASE_ADDR 0xA2
+#define ADT7462_REG_FAN2_MAX_ADDR 0xA9
+#define ADT7462_REG_FAN_ENABLE 0x07
+#define ADT7462_REG_FAN_MIN_BASE_ADDR 0x78
+#define ADT7462_REG_FAN_MIN_MAX_ADDR 0x7F
+
+#define ADT7462_REG_CFG2 0x02
+#define ADT7462_FSPD_MASK 0x20
+
+#define ADT7462_REG_PWM_BASE_ADDR 0xAA
+#define ADT7462_REG_PWM_MAX_ADDR 0xAD
+#define ADT7462_REG_PWM_MIN_BASE_ADDR 0x28
+#define ADT7462_REG_PWM_MIN_MAX_ADDR 0x2B
+#define ADT7462_REG_PWM_MAX 0x2C
+#define ADT7462_REG_PWM_TEMP_MIN_BASE_ADDR 0x5C
+#define ADT7462_REG_PWM_TEMP_MIN_MAX_ADDR 0x5F
+#define ADT7462_REG_PWM_TEMP_RANGE_BASE_ADDR 0x60
+#define ADT7462_REG_PWM_TEMP_RANGE_MAX_ADDR 0x63
+#define ADT7462_PWM_HYST_MASK 0x0F
+#define ADT7462_PWM_RANGE_MASK 0xF0
+#define ADT7462_PWM_RANGE_SHIFT 4
+#define ADT7462_REG_PWM_CFG_BASE_ADDR 0x21
+#define ADT7462_REG_PWM_CFG_MAX_ADDR 0x24
+#define ADT7462_PWM_CHANNEL_MASK 0xE0
+#define ADT7462_PWM_CHANNEL_SHIFT 5
+
+#define ADT7462_REG_PIN_CFG_BASE_ADDR 0x10
+#define ADT7462_REG_PIN_CFG_MAX_ADDR 0x13
+#define ADT7462_PIN7_INPUT 0x01 /* cfg0 */
+#define ADT7462_DIODE3_INPUT 0x20
+#define ADT7462_DIODE1_INPUT 0x40
+#define ADT7462_VID_INPUT 0x80
+#define ADT7462_PIN22_INPUT 0x04 /* cfg1 */
+#define ADT7462_PIN21_INPUT 0x08
+#define ADT7462_PIN19_INPUT 0x10
+#define ADT7462_PIN15_INPUT 0x20
+#define ADT7462_PIN13_INPUT 0x40
+#define ADT7462_PIN8_INPUT 0x80
+#define ADT7462_PIN23_MASK 0x03
+#define ADT7462_PIN23_SHIFT 0
+#define ADT7462_PIN26_MASK 0x0C /* cfg2 */
+#define ADT7462_PIN26_SHIFT 2
+#define ADT7462_PIN25_MASK 0x30
+#define ADT7462_PIN25_SHIFT 4
+#define ADT7462_PIN24_MASK 0xC0
+#define ADT7462_PIN24_SHIFT 6
+#define ADT7462_PIN26_VOLT_INPUT 0x08
+#define ADT7462_PIN25_VOLT_INPUT 0x20
+#define ADT7462_PIN28_SHIFT 6 /* cfg3 */
+#define ADT7462_PIN28_VOLT 0x5
+
+#define ADT7462_REG_ALARM1 0xB8
+#define ADT7462_LT_ALARM 0x02
+#define ADT7462_R1T_ALARM 0x04
+#define ADT7462_R2T_ALARM 0x08
+#define ADT7462_R3T_ALARM 0x10
+#define ADT7462_REG_ALARM2 0xBB
+#define ADT7462_V0_ALARM 0x01
+#define ADT7462_V1_ALARM 0x02
+#define ADT7462_V2_ALARM 0x04
+#define ADT7462_V3_ALARM 0x08
+#define ADT7462_V4_ALARM 0x10
+#define ADT7462_V5_ALARM 0x20
+#define ADT7462_V6_ALARM 0x40
+#define ADT7462_V7_ALARM 0x80
+#define ADT7462_REG_ALARM3 0xBC
+#define ADT7462_V8_ALARM 0x08
+#define ADT7462_V9_ALARM 0x10
+#define ADT7462_V10_ALARM 0x20
+#define ADT7462_V11_ALARM 0x40
+#define ADT7462_V12_ALARM 0x80
+#define ADT7462_REG_ALARM4 0xBD
+#define ADT7462_F0_ALARM 0x01
+#define ADT7462_F1_ALARM 0x02
+#define ADT7462_F2_ALARM 0x04
+#define ADT7462_F3_ALARM 0x08
+#define ADT7462_F4_ALARM 0x10
+#define ADT7462_F5_ALARM 0x20
+#define ADT7462_F6_ALARM 0x40
+#define ADT7462_F7_ALARM 0x80
+#define ADT7462_ALARM1 0x0000
+#define ADT7462_ALARM2 0x0100
+#define ADT7462_ALARM3 0x0200
+#define ADT7462_ALARM4 0x0300
+#define ADT7462_ALARM_REG_SHIFT 8
+#define ADT7462_ALARM_FLAG_MASK 0x0F
+
+#define ADT7462_TEMP_COUNT 4
+#define ADT7462_TEMP_REG(x) (ADT7462_REG_TEMP_BASE_ADDR + (x * 2))
+#define ADT7462_TEMP_MIN_REG(x) (ADT7462_REG_MIN_TEMP_BASE_ADDR + (x))
+#define ADT7462_TEMP_MAX_REG(x) (ADT7462_REG_MAX_TEMP_BASE_ADDR + (x))
+#define TEMP_FRAC_OFFSET 6
+
+#define ADT7462_FAN_COUNT 8
+#define ADT7462_REG_FAN_MIN(x) (ADT7462_REG_FAN_MIN_BASE_ADDR + (x))
+
+#define ADT7462_PWM_COUNT 4
+#define ADT7462_REG_PWM(x) (ADT7462_REG_PWM_BASE_ADDR + (x))
+#define ADT7462_REG_PWM_MIN(x) (ADT7462_REG_PWM_MIN_BASE_ADDR + (x))
+#define ADT7462_REG_PWM_TMIN(x) \
+ (ADT7462_REG_PWM_TEMP_MIN_BASE_ADDR + (x))
+#define ADT7462_REG_PWM_TRANGE(x) \
+ (ADT7462_REG_PWM_TEMP_RANGE_BASE_ADDR + (x))
+
+#define ADT7462_PIN_CFG_REG_COUNT 4
+#define ADT7462_REG_PIN_CFG(x) (ADT7462_REG_PIN_CFG_BASE_ADDR + (x))
+#define ADT7462_REG_PWM_CFG(x) (ADT7462_REG_PWM_CFG_BASE_ADDR + (x))
+
+#define ADT7462_ALARM_REG_COUNT 4
+
+/*
+ * The chip can measure 13 different voltage sources:
+ *
+ * 1. +12V1 (pin 7)
+ * 2. Vccp1/+2.5V/+1.8V/+1.5V (pin 23)
+ * 3. +12V3 (pin 22)
+ * 4. +5V (pin 21)
+ * 5. +1.25V/+0.9V (pin 19)
+ * 6. +2.5V/+1.8V (pin 15)
+ * 7. +3.3v (pin 13)
+ * 8. +12V2 (pin 8)
+ * 9. Vbatt/FSB_Vtt (pin 26)
+ * A. +3.3V/+1.2V1 (pin 25)
+ * B. Vccp2/+2.5V/+1.8V/+1.5V (pin 24)
+ * C. +1.5V ICH (only if BOTH pin 28/29 are set to +1.5V)
+ * D. +1.5V 3GPIO (only if BOTH pin 28/29 are set to +1.5V)
+ *
+ * Each of these 13 has a factor to convert raw to voltage. Even better,
+ * the pins can be connected to other sensors (tach/gpio/hot/etc), which
+ * makes the bookkeeping tricky.
+ *
+ * Some, but not all, of these voltages have low/high limits.
+ */
+#define ADT7462_VOLT_COUNT 12
+
+#define ADT7462_VENDOR 0x41
+#define ADT7462_DEVICE 0x62
+/* datasheet only mentions a revision 4 */
+#define ADT7462_REVISION 0x04
+
+/* How often do we reread sensors values? (In jiffies) */
+#define SENSOR_REFRESH_INTERVAL (2 * HZ)
+
+/* How often do we reread sensor limit values? (In jiffies) */
+#define LIMIT_REFRESH_INTERVAL (60 * HZ)
+
+/* datasheet says to divide this number by the fan reading to get fan rpm */
+#define FAN_PERIOD_TO_RPM(x) ((90000 * 60) / (x))
+#define FAN_RPM_TO_PERIOD FAN_PERIOD_TO_RPM
+#define FAN_PERIOD_INVALID 65535
+#define FAN_DATA_VALID(x) ((x) && (x) != FAN_PERIOD_INVALID)
+
+#define MASK_AND_SHIFT(value, prefix) \
+ (((value) & prefix##_MASK) >> prefix##_SHIFT)
+
+#define ROUND_DIV(x, divisor) (((x) + ((divisor) / 2)) / (divisor))
+
+struct adt7462_data {
+ struct device *hwmon_dev;
+ struct attribute_group attrs;
+ struct mutex lock;
+ char sensors_valid;
+ char limits_valid;
+ unsigned long sensors_last_updated; /* In jiffies */
+ unsigned long limits_last_updated; /* In jiffies */
+
+ u8 temp[ADT7462_TEMP_COUNT];
+ /* bits 6-7 are quarter pieces of temp */
+ u8 temp_frac[ADT7462_TEMP_COUNT];
+ u8 temp_min[ADT7462_TEMP_COUNT];
+ u8 temp_max[ADT7462_TEMP_COUNT];
+ u16 fan[ADT7462_FAN_COUNT];
+ u8 fan_enabled;
+ u8 fan_min[ADT7462_FAN_COUNT];
+ u8 cfg2;
+ u8 pwm[ADT7462_PWM_COUNT];
+ u8 pin_cfg[ADT7462_PIN_CFG_REG_COUNT];
+ u8 voltages[ADT7462_VOLT_COUNT];
+ u8 volt_max[ADT7462_VOLT_COUNT];
+ u8 volt_min[ADT7462_VOLT_COUNT];
+ u8 pwm_min[ADT7462_PWM_COUNT];
+ u8 pwm_tmin[ADT7462_PWM_COUNT];
+ u8 pwm_trange[ADT7462_PWM_COUNT];
+ u8 pwm_max; /* only one per chip */
+ u8 pwm_cfg[ADT7462_PWM_COUNT];
+ u8 alarms[ADT7462_ALARM_REG_COUNT];
+};
+
+static int adt7462_probe(struct i2c_client *client,
+ const struct i2c_device_id *id);
+static int adt7462_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info);
+static int adt7462_remove(struct i2c_client *client);
+
+static const struct i2c_device_id adt7462_id[] = {
+ { "adt7462", adt7462 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, adt7462_id);
+
+static struct i2c_driver adt7462_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "adt7462",
+ },
+ .probe = adt7462_probe,
+ .remove = adt7462_remove,
+ .id_table = adt7462_id,
+ .detect = adt7462_detect,
+ .address_data = &addr_data,
+};
+
+/*
+ * 16-bit registers on the ADT7462 are low-byte first. The data sheet says
+ * that the low byte must be read before the high byte.
+ */
+static inline int adt7462_read_word_data(struct i2c_client *client, u8 reg)
+{
+ u16 foo;
+ foo = i2c_smbus_read_byte_data(client, reg);
+ foo |= ((u16)i2c_smbus_read_byte_data(client, reg + 1) << 8);
+ return foo;
+}
+
+/* For some reason these registers are not contiguous. */
+static int ADT7462_REG_FAN(int fan)
+{
+ if (fan < 4)
+ return ADT7462_REG_FAN_BASE_ADDR + (2 * fan);
+ return ADT7462_REG_FAN2_BASE_ADDR + (2 * (fan - 4));
+}
+
+/* Voltage registers are scattered everywhere */
+static int ADT7462_REG_VOLT_MAX(struct adt7462_data *data, int which)
+{
+ switch (which) {
+ case 0:
+ if (!(data->pin_cfg[0] & ADT7462_PIN7_INPUT))
+ return 0x7C;
+ break;
+ case 1:
+ return 0x69;
+ case 2:
+ if (!(data->pin_cfg[1] & ADT7462_PIN22_INPUT))
+ return 0x7F;
+ break;
+ case 3:
+ if (!(data->pin_cfg[1] & ADT7462_PIN21_INPUT))
+ return 0x7E;
+ break;
+ case 4:
+ if (!(data->pin_cfg[0] & ADT7462_DIODE3_INPUT))
+ return 0x4B;
+ break;
+ case 5:
+ if (!(data->pin_cfg[0] & ADT7462_DIODE1_INPUT))
+ return 0x49;
+ break;
+ case 6:
+ if (!(data->pin_cfg[1] & ADT7462_PIN13_INPUT))
+ return 0x68;
+ break;
+ case 7:
+ if (!(data->pin_cfg[1] & ADT7462_PIN8_INPUT))
+ return 0x7D;
+ break;
+ case 8:
+ if (!(data->pin_cfg[2] & ADT7462_PIN26_VOLT_INPUT))
+ return 0x6C;
+ break;
+ case 9:
+ if (!(data->pin_cfg[2] & ADT7462_PIN25_VOLT_INPUT))
+ return 0x6B;
+ break;
+ case 10:
+ return 0x6A;
+ case 11:
+ if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT ==
+ ADT7462_PIN28_VOLT &&
+ !(data->pin_cfg[0] & ADT7462_VID_INPUT))
+ return 0x50;
+ break;
+ case 12:
+ if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT ==
+ ADT7462_PIN28_VOLT &&
+ !(data->pin_cfg[0] & ADT7462_VID_INPUT))
+ return 0x4C;
+ break;
+ }
+ return -ENODEV;
+}
+
+static int ADT7462_REG_VOLT_MIN(struct adt7462_data *data, int which)
+{
+ switch (which) {
+ case 0:
+ if (!(data->pin_cfg[0] & ADT7462_PIN7_INPUT))
+ return 0x6D;
+ break;
+ case 1:
+ return 0x72;
+ case 2:
+ if (!(data->pin_cfg[1] & ADT7462_PIN22_INPUT))
+ return 0x6F;
+ break;
+ case 3:
+ if (!(data->pin_cfg[1] & ADT7462_PIN21_INPUT))
+ return 0x71;
+ break;
+ case 4:
+ if (!(data->pin_cfg[0] & ADT7462_DIODE3_INPUT))
+ return 0x47;
+ break;
+ case 5:
+ if (!(data->pin_cfg[0] & ADT7462_DIODE1_INPUT))
+ return 0x45;
+ break;
+ case 6:
+ if (!(data->pin_cfg[1] & ADT7462_PIN13_INPUT))
+ return 0x70;
+ break;
+ case 7:
+ if (!(data->pin_cfg[1] & ADT7462_PIN8_INPUT))
+ return 0x6E;
+ break;
+ case 8:
+ if (!(data->pin_cfg[2] & ADT7462_PIN26_VOLT_INPUT))
+ return 0x75;
+ break;
+ case 9:
+ if (!(data->pin_cfg[2] & ADT7462_PIN25_VOLT_INPUT))
+ return 0x74;
+ break;
+ case 10:
+ return 0x73;
+ case 11:
+ if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT ==
+ ADT7462_PIN28_VOLT &&
+ !(data->pin_cfg[0] & ADT7462_VID_INPUT))
+ return 0x76;
+ break;
+ case 12:
+ if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT ==
+ ADT7462_PIN28_VOLT &&
+ !(data->pin_cfg[0] & ADT7462_VID_INPUT))
+ return 0x77;
+ break;
+ }
+ return -ENODEV;
+}
+
+static int ADT7462_REG_VOLT(struct adt7462_data *data, int which)
+{
+ switch (which) {
+ case 0:
+ if (!(data->pin_cfg[0] & ADT7462_PIN7_INPUT))
+ return 0xA3;
+ break;
+ case 1:
+ return 0x90;
+ case 2:
+ if (!(data->pin_cfg[1] & ADT7462_PIN22_INPUT))
+ return 0xA9;
+ break;
+ case 3:
+ if (!(data->pin_cfg[1] & ADT7462_PIN21_INPUT))
+ return 0xA7;
+ break;
+ case 4:
+ if (!(data->pin_cfg[0] & ADT7462_DIODE3_INPUT))
+ return 0x8F;
+ break;
+ case 5:
+ if (!(data->pin_cfg[0] & ADT7462_DIODE1_INPUT))
+ return 0x8B;
+ break;
+ case 6:
+ if (!(data->pin_cfg[1] & ADT7462_PIN13_INPUT))
+ return 0x96;
+ break;
+ case 7:
+ if (!(data->pin_cfg[1] & ADT7462_PIN8_INPUT))
+ return 0xA5;
+ break;
+ case 8:
+ if (!(data->pin_cfg[2] & ADT7462_PIN26_VOLT_INPUT))
+ return 0x93;
+ break;
+ case 9:
+ if (!(data->pin_cfg[2] & ADT7462_PIN25_VOLT_INPUT))
+ return 0x92;
+ break;
+ case 10:
+ return 0x91;
+ case 11:
+ if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT ==
+ ADT7462_PIN28_VOLT &&
+ !(data->pin_cfg[0] & ADT7462_VID_INPUT))
+ return 0x94;
+ break;
+ case 12:
+ if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT ==
+ ADT7462_PIN28_VOLT &&
+ !(data->pin_cfg[0] & ADT7462_VID_INPUT))
+ return 0x95;
+ break;
+ }
+ return -ENODEV;
+}
+
+/* Provide labels for sysfs */
+static const char *voltage_label(struct adt7462_data *data, int which)
+{
+ switch (which) {
+ case 0:
+ if (!(data->pin_cfg[0] & ADT7462_PIN7_INPUT))
+ return "+12V1";
+ break;
+ case 1:
+ switch (MASK_AND_SHIFT(data->pin_cfg[1], ADT7462_PIN23)) {
+ case 0:
+ return "Vccp1";
+ case 1:
+ return "+2.5V";
+ case 2:
+ return "+1.8V";
+ case 3:
+ return "+1.5V";
+ }
+ case 2:
+ if (!(data->pin_cfg[1] & ADT7462_PIN22_INPUT))
+ return "+12V3";
+ break;
+ case 3:
+ if (!(data->pin_cfg[1] & ADT7462_PIN21_INPUT))
+ return "+5V";
+ break;
+ case 4:
+ if (!(data->pin_cfg[0] & ADT7462_DIODE3_INPUT)) {
+ if (data->pin_cfg[1] & ADT7462_PIN19_INPUT)
+ return "+0.9V";
+ return "+1.25V";
+ }
+ break;
+ case 5:
+ if (!(data->pin_cfg[0] & ADT7462_DIODE1_INPUT)) {
+ if (data->pin_cfg[1] & ADT7462_PIN19_INPUT)
+ return "+1.8V";
+ return "+2.5V";
+ }
+ break;
+ case 6:
+ if (!(data->pin_cfg[1] & ADT7462_PIN13_INPUT))
+ return "+3.3V";
+ break;
+ case 7:
+ if (!(data->pin_cfg[1] & ADT7462_PIN8_INPUT))
+ return "+12V2";
+ break;
+ case 8:
+ switch (MASK_AND_SHIFT(data->pin_cfg[2], ADT7462_PIN26)) {
+ case 0:
+ return "Vbatt";
+ case 1:
+ return "FSB_Vtt";
+ }
+ break;
+ case 9:
+ switch (MASK_AND_SHIFT(data->pin_cfg[2], ADT7462_PIN25)) {
+ case 0:
+ return "+3.3V";
+ case 1:
+ return "+1.2V1";
+ }
+ break;
+ case 10:
+ switch (MASK_AND_SHIFT(data->pin_cfg[2], ADT7462_PIN24)) {
+ case 0:
+ return "Vccp2";
+ case 1:
+ return "+2.5V";
+ case 2:
+ return "+1.8V";
+ case 3:
+ return "+1.5";
+ }
+ case 11:
+ if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT ==
+ ADT7462_PIN28_VOLT &&
+ !(data->pin_cfg[0] & ADT7462_VID_INPUT))
+ return "+1.5V ICH";
+ break;
+ case 12:
+ if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT ==
+ ADT7462_PIN28_VOLT &&
+ !(data->pin_cfg[0] & ADT7462_VID_INPUT))
+ return "+1.5V 3GPIO";
+ break;
+ }
+ return "N/A";
+}
+
+/* Multipliers are actually in uV, not mV. */
+static int voltage_multiplier(struct adt7462_data *data, int which)
+{
+ switch (which) {
+ case 0:
+ if (!(data->pin_cfg[0] & ADT7462_PIN7_INPUT))
+ return 62500;
+ break;
+ case 1:
+ switch (MASK_AND_SHIFT(data->pin_cfg[1], ADT7462_PIN23)) {
+ case 0:
+ if (data->pin_cfg[0] & ADT7462_VID_INPUT)
+ return 12500;
+ return 6250;
+ case 1:
+ return 13000;
+ case 2:
+ return 9400;
+ case 3:
+ return 7800;
+ }
+ case 2:
+ if (!(data->pin_cfg[1] & ADT7462_PIN22_INPUT))
+ return 62500;
+ break;
+ case 3:
+ if (!(data->pin_cfg[1] & ADT7462_PIN21_INPUT))
+ return 26000;
+ break;
+ case 4:
+ if (!(data->pin_cfg[0] & ADT7462_DIODE3_INPUT)) {
+ if (data->pin_cfg[1] & ADT7462_PIN19_INPUT)
+ return 4690;
+ return 6500;
+ }
+ break;
+ case 5:
+ if (!(data->pin_cfg[0] & ADT7462_DIODE1_INPUT)) {
+ if (data->pin_cfg[1] & ADT7462_PIN15_INPUT)
+ return 9400;
+ return 13000;
+ }
+ break;
+ case 6:
+ if (!(data->pin_cfg[1] & ADT7462_PIN13_INPUT))
+ return 17200;
+ break;
+ case 7:
+ if (!(data->pin_cfg[1] & ADT7462_PIN8_INPUT))
+ return 62500;
+ break;
+ case 8:
+ switch (MASK_AND_SHIFT(data->pin_cfg[2], ADT7462_PIN26)) {
+ case 0:
+ return 15600;
+ case 1:
+ return 6250;
+ }
+ break;
+ case 9:
+ switch (MASK_AND_SHIFT(data->pin_cfg[2], ADT7462_PIN25)) {
+ case 0:
+ return 17200;
+ case 1:
+ return 6250;
+ }
+ break;
+ case 10:
+ switch (MASK_AND_SHIFT(data->pin_cfg[2], ADT7462_PIN24)) {
+ case 0:
+ return 6250;
+ case 1:
+ return 13000;
+ case 2:
+ return 9400;
+ case 3:
+ return 7800;
+ }
+ case 11:
+ case 12:
+ if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT ==
+ ADT7462_PIN28_VOLT &&
+ !(data->pin_cfg[0] & ADT7462_VID_INPUT))
+ return 7800;
+ }
+ return 0;
+}
+
+static int temp_enabled(struct adt7462_data *data, int which)
+{
+ switch (which) {
+ case 0:
+ case 2:
+ return 1;
+ case 1:
+ if (data->pin_cfg[0] & ADT7462_DIODE1_INPUT)
+ return 1;
+ break;
+ case 3:
+ if (data->pin_cfg[0] & ADT7462_DIODE3_INPUT)
+ return 1;
+ break;
+ }
+ return 0;
+}
+
+static const char *temp_label(struct adt7462_data *data, int which)
+{
+ switch (which) {
+ case 0:
+ return "local";
+ case 1:
+ if (data->pin_cfg[0] & ADT7462_DIODE1_INPUT)
+ return "remote1";
+ break;
+ case 2:
+ return "remote2";
+ case 3:
+ if (data->pin_cfg[0] & ADT7462_DIODE3_INPUT)
+ return "remote3";
+ break;
+ }
+ return "N/A";
+}
+
+/* Map Trange register values to mC */
+#define NUM_TRANGE_VALUES 16
+static const int trange_values[NUM_TRANGE_VALUES] = {
+ 2000,
+ 2500,
+ 3300,
+ 4000,
+ 5000,
+ 6700,
+ 8000,
+ 10000,
+ 13300,
+ 16000,
+ 20000,
+ 26700,
+ 32000,
+ 40000,
+ 53300,
+ 80000
+};
+
+static int find_trange_value(int trange)
+{
+ int i;
+
+ for (i = 0; i < NUM_TRANGE_VALUES; i++)
+ if (trange_values[i] == trange)
+ return i;
+
+ return -ENODEV;
+}
+
+static struct adt7462_data *adt7462_update_device(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct adt7462_data *data = i2c_get_clientdata(client);
+ unsigned long local_jiffies = jiffies;
+ int i;
+
+ mutex_lock(&data->lock);
+ if (time_before(local_jiffies, data->sensors_last_updated +
+ SENSOR_REFRESH_INTERVAL)
+ && data->sensors_valid)
+ goto no_sensor_update;
+
+ for (i = 0; i < ADT7462_TEMP_COUNT; i++) {
+ /*
+ * Reading the fractional register locks the integral
+ * register until both have been read.
+ */
+ data->temp_frac[i] = i2c_smbus_read_byte_data(client,
+ ADT7462_TEMP_REG(i));
+ data->temp[i] = i2c_smbus_read_byte_data(client,
+ ADT7462_TEMP_REG(i) + 1);
+ }
+
+ for (i = 0; i < ADT7462_FAN_COUNT; i++)
+ data->fan[i] = adt7462_read_word_data(client,
+ ADT7462_REG_FAN(i));
+
+ data->fan_enabled = i2c_smbus_read_byte_data(client,
+ ADT7462_REG_FAN_ENABLE);
+
+ for (i = 0; i < ADT7462_PWM_COUNT; i++)
+ data->pwm[i] = i2c_smbus_read_byte_data(client,
+ ADT7462_REG_PWM(i));
+
+ for (i = 0; i < ADT7462_PIN_CFG_REG_COUNT; i++)
+ data->pin_cfg[i] = i2c_smbus_read_byte_data(client,
+ ADT7462_REG_PIN_CFG(i));
+
+ for (i = 0; i < ADT7462_VOLT_COUNT; i++) {
+ int reg = ADT7462_REG_VOLT(data, i);
+ if (!reg)
+ data->voltages[i] = 0;
+ else
+ data->voltages[i] = i2c_smbus_read_byte_data(client,
+ reg);
+ }
+
+ data->alarms[0] = i2c_smbus_read_byte_data(client, ADT7462_REG_ALARM1);
+ data->alarms[1] = i2c_smbus_read_byte_data(client, ADT7462_REG_ALARM2);
+ data->alarms[2] = i2c_smbus_read_byte_data(client, ADT7462_REG_ALARM3);
+ data->alarms[3] = i2c_smbus_read_byte_data(client, ADT7462_REG_ALARM4);
+
+ data->sensors_last_updated = local_jiffies;
+ data->sensors_valid = 1;
+
+no_sensor_update:
+ if (time_before(local_jiffies, data->limits_last_updated +
+ LIMIT_REFRESH_INTERVAL)
+ && data->limits_valid)
+ goto out;
+
+ for (i = 0; i < ADT7462_TEMP_COUNT; i++) {
+ data->temp_min[i] = i2c_smbus_read_byte_data(client,
+ ADT7462_TEMP_MIN_REG(i));
+ data->temp_max[i] = i2c_smbus_read_byte_data(client,
+ ADT7462_TEMP_MAX_REG(i));
+ }
+
+ for (i = 0; i < ADT7462_FAN_COUNT; i++)
+ data->fan_min[i] = i2c_smbus_read_byte_data(client,
+ ADT7462_REG_FAN_MIN(i));
+
+ for (i = 0; i < ADT7462_VOLT_COUNT; i++) {
+ int reg = ADT7462_REG_VOLT_MAX(data, i);
+ data->volt_max[i] =
+ (reg ? i2c_smbus_read_byte_data(client, reg) : 0);
+
+ reg = ADT7462_REG_VOLT_MIN(data, i);
+ data->volt_min[i] =
+ (reg ? i2c_smbus_read_byte_data(client, reg) : 0);
+ }
+
+ for (i = 0; i < ADT7462_PWM_COUNT; i++) {
+ data->pwm_min[i] = i2c_smbus_read_byte_data(client,
+ ADT7462_REG_PWM_MIN(i));
+ data->pwm_tmin[i] = i2c_smbus_read_byte_data(client,
+ ADT7462_REG_PWM_TMIN(i));
+ data->pwm_trange[i] = i2c_smbus_read_byte_data(client,
+ ADT7462_REG_PWM_TRANGE(i));
+ data->pwm_cfg[i] = i2c_smbus_read_byte_data(client,
+ ADT7462_REG_PWM_CFG(i));
+ }
+
+ data->pwm_max = i2c_smbus_read_byte_data(client, ADT7462_REG_PWM_MAX);
+
+ data->cfg2 = i2c_smbus_read_byte_data(client, ADT7462_REG_CFG2);
+
+ data->limits_last_updated = local_jiffies;
+ data->limits_valid = 1;
+
+out:
+ mutex_unlock(&data->lock);
+ return data;
+}
+
+static ssize_t show_temp_min(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct adt7462_data *data = adt7462_update_device(dev);
+
+ if (!temp_enabled(data, attr->index))
+ return sprintf(buf, "0\n");
+
+ return sprintf(buf, "%d\n", 1000 * (data->temp_min[attr->index] - 64));
+}
+
+static ssize_t set_temp_min(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf,
+ size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct adt7462_data *data = i2c_get_clientdata(client);
+ long temp;
+
+ if (strict_strtol(buf, 10, &temp) || !temp_enabled(data, attr->index))
+ return -EINVAL;
+
+ temp = ROUND_DIV(temp, 1000) + 64;
+ temp = SENSORS_LIMIT(temp, 0, 255);
+
+ mutex_lock(&data->lock);
+ data->temp_min[attr->index] = temp;
+ i2c_smbus_write_byte_data(client, ADT7462_TEMP_MIN_REG(attr->index),
+ temp);
+ mutex_unlock(&data->lock);
+
+ return count;
+}
+
+static ssize_t show_temp_max(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct adt7462_data *data = adt7462_update_device(dev);
+
+ if (!temp_enabled(data, attr->index))
+ return sprintf(buf, "0\n");
+
+ return sprintf(buf, "%d\n", 1000 * (data->temp_max[attr->index] - 64));
+}
+
+static ssize_t set_temp_max(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf,
+ size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct adt7462_data *data = i2c_get_clientdata(client);
+ long temp;
+
+ if (strict_strtol(buf, 10, &temp) || !temp_enabled(data, attr->index))
+ return -EINVAL;
+
+ temp = ROUND_DIV(temp, 1000) + 64;
+ temp = SENSORS_LIMIT(temp, 0, 255);
+
+ mutex_lock(&data->lock);
+ data->temp_max[attr->index] = temp;
+ i2c_smbus_write_byte_data(client, ADT7462_TEMP_MAX_REG(attr->index),
+ temp);
+ mutex_unlock(&data->lock);
+
+ return count;
+}
+
+static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct adt7462_data *data = adt7462_update_device(dev);
+ u8 frac = data->temp_frac[attr->index] >> TEMP_FRAC_OFFSET;
+
+ if (!temp_enabled(data, attr->index))
+ return sprintf(buf, "0\n");
+
+ return sprintf(buf, "%d\n", 1000 * (data->temp[attr->index] - 64) +
+ 250 * frac);
+}
+
+static ssize_t show_temp_label(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct adt7462_data *data = adt7462_update_device(dev);
+
+ return sprintf(buf, "%s\n", temp_label(data, attr->index));
+}
+
+static ssize_t show_volt_max(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct adt7462_data *data = adt7462_update_device(dev);
+ int x = voltage_multiplier(data, attr->index);
+
+ x *= data->volt_max[attr->index];
+ x /= 1000; /* convert from uV to mV */
+
+ return sprintf(buf, "%d\n", x);
+}
+
+static ssize_t set_volt_max(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf,
+ size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct adt7462_data *data = i2c_get_clientdata(client);
+ int x = voltage_multiplier(data, attr->index);
+ long temp;
+
+ if (strict_strtol(buf, 10, &temp) || !x)
+ return -EINVAL;
+
+ temp *= 1000; /* convert mV to uV */
+ temp = ROUND_DIV(temp, x);
+ temp = SENSORS_LIMIT(temp, 0, 255);
+
+ mutex_lock(&data->lock);
+ data->volt_max[attr->index] = temp;
+ i2c_smbus_write_byte_data(client,
+ ADT7462_REG_VOLT_MAX(data, attr->index),
+ temp);
+ mutex_unlock(&data->lock);
+
+ return count;
+}
+
+static ssize_t show_volt_min(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct adt7462_data *data = adt7462_update_device(dev);
+ int x = voltage_multiplier(data, attr->index);
+
+ x *= data->volt_min[attr->index];
+ x /= 1000; /* convert from uV to mV */
+
+ return sprintf(buf, "%d\n", x);
+}
+
+static ssize_t set_volt_min(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf,
+ size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct adt7462_data *data = i2c_get_clientdata(client);
+ int x = voltage_multiplier(data, attr->index);
+ long temp;
+
+ if (strict_strtol(buf, 10, &temp) || !x)
+ return -EINVAL;
+
+ temp *= 1000; /* convert mV to uV */
+ temp = ROUND_DIV(temp, x);
+ temp = SENSORS_LIMIT(temp, 0, 255);
+
+ mutex_lock(&data->lock);
+ data->volt_min[attr->index] = temp;
+ i2c_smbus_write_byte_data(client,
+ ADT7462_REG_VOLT_MIN(data, attr->index),
+ temp);
+ mutex_unlock(&data->lock);
+
+ return count;
+}
+
+static ssize_t show_voltage(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct adt7462_data *data = adt7462_update_device(dev);
+ int x = voltage_multiplier(data, attr->index);
+
+ x *= data->voltages[attr->index];
+ x /= 1000; /* convert from uV to mV */
+
+ return sprintf(buf, "%d\n", x);
+}
+
+static ssize_t show_voltage_label(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct adt7462_data *data = adt7462_update_device(dev);
+
+ return sprintf(buf, "%s\n", voltage_label(data, attr->index));
+}
+
+static ssize_t show_alarm(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct adt7462_data *data = adt7462_update_device(dev);
+ int reg = attr->index >> ADT7462_ALARM_REG_SHIFT;
+ int mask = attr->index & ADT7462_ALARM_FLAG_MASK;
+
+ if (data->alarms[reg] & mask)
+ return sprintf(buf, "1\n");
+ else
+ return sprintf(buf, "0\n");
+}
+
+static int fan_enabled(struct adt7462_data *data, int fan)
+{
+ return data->fan_enabled & (1 << fan);
+}
+
+static ssize_t show_fan_min(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct adt7462_data *data = adt7462_update_device(dev);
+ u16 temp;
+
+ /* Only the MSB of the min fan period is stored... */
+ temp = data->fan_min[attr->index];
+ temp <<= 8;
+
+ if (!fan_enabled(data, attr->index) ||
+ !FAN_DATA_VALID(temp))
+ return sprintf(buf, "0\n");
+
+ return sprintf(buf, "%d\n", FAN_PERIOD_TO_RPM(temp));
+}
+
+static ssize_t set_fan_min(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct adt7462_data *data = i2c_get_clientdata(client);
+ long temp;
+
+ if (strict_strtol(buf, 10, &temp) || !temp ||
+ !fan_enabled(data, attr->index))
+ return -EINVAL;
+
+ temp = FAN_RPM_TO_PERIOD(temp);
+ temp >>= 8;
+ temp = SENSORS_LIMIT(temp, 1, 255);
+
+ mutex_lock(&data->lock);
+ data->fan_min[attr->index] = temp;
+ i2c_smbus_write_byte_data(client, ADT7462_REG_FAN_MIN(attr->index),
+ temp);
+ mutex_unlock(&data->lock);
+
+ return count;
+}
+
+static ssize_t show_fan(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct adt7462_data *data = adt7462_update_device(dev);
+
+ if (!fan_enabled(data, attr->index) ||
+ !FAN_DATA_VALID(data->fan[attr->index]))
+ return sprintf(buf, "0\n");
+
+ return sprintf(buf, "%d\n",
+ FAN_PERIOD_TO_RPM(data->fan[attr->index]));
+}
+
+static ssize_t show_force_pwm_max(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct adt7462_data *data = adt7462_update_device(dev);
+ return sprintf(buf, "%d\n", (data->cfg2 & ADT7462_FSPD_MASK ? 1 : 0));
+}
+
+static ssize_t set_force_pwm_max(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf,
+ size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct adt7462_data *data = i2c_get_clientdata(client);
+ long temp;
+ u8 reg;
+
+ if (strict_strtol(buf, 10, &temp))
+ return -EINVAL;
+
+ mutex_lock(&data->lock);
+ reg = i2c_smbus_read_byte_data(client, ADT7462_REG_CFG2);
+ if (temp)
+ reg |= ADT7462_FSPD_MASK;
+ else
+ reg &= ~ADT7462_FSPD_MASK;
+ data->cfg2 = reg;
+ i2c_smbus_write_byte_data(client, ADT7462_REG_CFG2, reg);
+ mutex_unlock(&data->lock);
+
+ return count;
+}
+
+static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct adt7462_data *data = adt7462_update_device(dev);
+ return sprintf(buf, "%d\n", data->pwm[attr->index]);
+}
+
+static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct adt7462_data *data = i2c_get_clientdata(client);
+ long temp;
+
+ if (strict_strtol(buf, 10, &temp))
+ return -EINVAL;
+
+ temp = SENSORS_LIMIT(temp, 0, 255);
+
+ mutex_lock(&data->lock);
+ data->pwm[attr->index] = temp;
+ i2c_smbus_write_byte_data(client, ADT7462_REG_PWM(attr->index), temp);
+ mutex_unlock(&data->lock);
+
+ return count;
+}
+
+static ssize_t show_pwm_max(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct adt7462_data *data = adt7462_update_device(dev);
+ return sprintf(buf, "%d\n", data->pwm_max);
+}
+
+static ssize_t set_pwm_max(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf,
+ size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct adt7462_data *data = i2c_get_clientdata(client);
+ long temp;
+
+ if (strict_strtol(buf, 10, &temp))
+ return -EINVAL;
+
+ temp = SENSORS_LIMIT(temp, 0, 255);
+
+ mutex_lock(&data->lock);
+ data->pwm_max = temp;
+ i2c_smbus_write_byte_data(client, ADT7462_REG_PWM_MAX, temp);
+ mutex_unlock(&data->lock);
+
+ return count;
+}
+
+static ssize_t show_pwm_min(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct adt7462_data *data = adt7462_update_device(dev);
+ return sprintf(buf, "%d\n", data->pwm_min[attr->index]);
+}
+
+static ssize_t set_pwm_min(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf,
+ size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct adt7462_data *data = i2c_get_clientdata(client);
+ long temp;
+
+ if (strict_strtol(buf, 10, &temp))
+ return -EINVAL;
+
+ temp = SENSORS_LIMIT(temp, 0, 255);
+
+ mutex_lock(&data->lock);
+ data->pwm_min[attr->index] = temp;
+ i2c_smbus_write_byte_data(client, ADT7462_REG_PWM_MIN(attr->index),
+ temp);
+ mutex_unlock(&data->lock);
+
+ return count;
+}
+
+static ssize_t show_pwm_hyst(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct adt7462_data *data = adt7462_update_device(dev);
+ return sprintf(buf, "%d\n", 1000 *
+ (data->pwm_trange[attr->index] & ADT7462_PWM_HYST_MASK));
+}
+
+static ssize_t set_pwm_hyst(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf,
+ size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct adt7462_data *data = i2c_get_clientdata(client);
+ long temp;
+
+ if (strict_strtol(buf, 10, &temp))
+ return -EINVAL;
+
+ temp = ROUND_DIV(temp, 1000);
+ temp = SENSORS_LIMIT(temp, 0, 15);
+
+ /* package things up */
+ temp &= ADT7462_PWM_HYST_MASK;
+ temp |= data->pwm_trange[attr->index] & ADT7462_PWM_RANGE_MASK;
+
+ mutex_lock(&data->lock);
+ data->pwm_trange[attr->index] = temp;
+ i2c_smbus_write_byte_data(client, ADT7462_REG_PWM_TRANGE(attr->index),
+ temp);
+ mutex_unlock(&data->lock);
+
+ return count;
+}
+
+static ssize_t show_pwm_tmax(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct adt7462_data *data = adt7462_update_device(dev);
+
+ /* tmax = tmin + trange */
+ int trange = trange_values[data->pwm_trange[attr->index] >>
+ ADT7462_PWM_RANGE_SHIFT];
+ int tmin = (data->pwm_tmin[attr->index] - 64) * 1000;
+
+ return sprintf(buf, "%d\n", tmin + trange);
+}
+
+static ssize_t set_pwm_tmax(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf,
+ size_t count)
+{
+ int temp;
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct adt7462_data *data = i2c_get_clientdata(client);
+ int tmin, trange_value;
+ long trange;
+
+ if (strict_strtol(buf, 10, &trange))
+ return -EINVAL;
+
+ /* trange = tmax - tmin */
+ tmin = (data->pwm_tmin[attr->index] - 64) * 1000;
+ trange_value = find_trange_value(trange - tmin);
+
+ if (trange_value < 0)
+ return -EINVAL;
+
+ temp = trange_value << ADT7462_PWM_RANGE_SHIFT;
+ temp |= data->pwm_trange[attr->index] & ADT7462_PWM_HYST_MASK;
+
+ mutex_lock(&data->lock);
+ data->pwm_trange[attr->index] = temp;
+ i2c_smbus_write_byte_data(client, ADT7462_REG_PWM_TRANGE(attr->index),
+ temp);
+ mutex_unlock(&data->lock);
+
+ return count;
+}
+
+static ssize_t show_pwm_tmin(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct adt7462_data *data = adt7462_update_device(dev);
+ return sprintf(buf, "%d\n", 1000 * (data->pwm_tmin[attr->index] - 64));
+}
+
+static ssize_t set_pwm_tmin(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf,
+ size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct adt7462_data *data = i2c_get_clientdata(client);
+ long temp;
+
+ if (strict_strtol(buf, 10, &temp))
+ return -EINVAL;
+
+ temp = ROUND_DIV(temp, 1000) + 64;
+ temp = SENSORS_LIMIT(temp, 0, 255);
+
+ mutex_lock(&data->lock);
+ data->pwm_tmin[attr->index] = temp;
+ i2c_smbus_write_byte_data(client, ADT7462_REG_PWM_TMIN(attr->index),
+ temp);
+ mutex_unlock(&data->lock);
+
+ return count;
+}
+
+static ssize_t show_pwm_auto(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct adt7462_data *data = adt7462_update_device(dev);
+ int cfg = data->pwm_cfg[attr->index] >> ADT7462_PWM_CHANNEL_SHIFT;
+
+ switch (cfg) {
+ case 4: /* off */
+ return sprintf(buf, "0\n");
+ case 7: /* manual */
+ return sprintf(buf, "1\n");
+ default: /* automatic */
+ return sprintf(buf, "2\n");
+ }
+}
+
+static void set_pwm_channel(struct i2c_client *client,
+ struct adt7462_data *data,
+ int which,
+ int value)
+{
+ int temp = data->pwm_cfg[which] & ~ADT7462_PWM_CHANNEL_MASK;
+ temp |= value << ADT7462_PWM_CHANNEL_SHIFT;
+
+ mutex_lock(&data->lock);
+ data->pwm_cfg[which] = temp;
+ i2c_smbus_write_byte_data(client, ADT7462_REG_PWM_CFG(which), temp);
+ mutex_unlock(&data->lock);
+}
+
+static ssize_t set_pwm_auto(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf,
+ size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct adt7462_data *data = i2c_get_clientdata(client);
+ long temp;
+
+ if (strict_strtol(buf, 10, &temp))
+ return -EINVAL;
+
+ switch (temp) {
+ case 0: /* off */
+ set_pwm_channel(client, data, attr->index, 4);
+ return count;
+ case 1: /* manual */
+ set_pwm_channel(client, data, attr->index, 7);
+ return count;
+ default:
+ return -EINVAL;
+ }
+}
+
+static ssize_t show_pwm_auto_temp(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct adt7462_data *data = adt7462_update_device(dev);
+ int channel = data->pwm_cfg[attr->index] >> ADT7462_PWM_CHANNEL_SHIFT;
+
+ switch (channel) {
+ case 0: /* temp[1234] only */
+ case 1:
+ case 2:
+ case 3:
+ return sprintf(buf, "%d\n", (1 << channel));
+ case 5: /* temp1 & temp4 */
+ return sprintf(buf, "9\n");
+ case 6:
+ return sprintf(buf, "15\n");
+ default:
+ return sprintf(buf, "0\n");
+ }
+}
+
+static int cvt_auto_temp(int input)
+{
+ if (input == 0xF)
+ return 6;
+ if (input == 0x9)
+ return 5;
+ if (input < 1 || !is_power_of_2(input))
+ return -EINVAL;
+ return ilog2(input);
+}
+
+static ssize_t set_pwm_auto_temp(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf,
+ size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct adt7462_data *data = i2c_get_clientdata(client);
+ long temp;
+
+ if (strict_strtol(buf, 10, &temp))
+ return -EINVAL;
+
+ temp = cvt_auto_temp(temp);
+ if (temp < 0)
+ return temp;
+
+ set_pwm_channel(client, data, attr->index, temp);
+
+ return count;
+}
+
+static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max,
+ set_temp_max, 0);
+static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp_max,
+ set_temp_max, 1);
+static SENSOR_DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_temp_max,
+ set_temp_max, 2);
+static SENSOR_DEVICE_ATTR(temp4_max, S_IWUSR | S_IRUGO, show_temp_max,
+ set_temp_max, 3);
+
+static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp_min,
+ set_temp_min, 0);
+static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp_min,
+ set_temp_min, 1);
+static SENSOR_DEVICE_ATTR(temp3_min, S_IWUSR | S_IRUGO, show_temp_min,
+ set_temp_min, 2);
+static SENSOR_DEVICE_ATTR(temp4_min, S_IWUSR | S_IRUGO, show_temp_min,
+ set_temp_min, 3);
+
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3);
+
+static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_temp_label, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_label, S_IRUGO, show_temp_label, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp3_label, S_IRUGO, show_temp_label, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp4_label, S_IRUGO, show_temp_label, NULL, 3);
+
+static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL,
+ ADT7462_ALARM1 | ADT7462_LT_ALARM);
+static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL,
+ ADT7462_ALARM1 | ADT7462_R1T_ALARM);
+static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL,
+ ADT7462_ALARM1 | ADT7462_R2T_ALARM);
+static SENSOR_DEVICE_ATTR(temp4_alarm, S_IRUGO, show_alarm, NULL,
+ ADT7462_ALARM1 | ADT7462_R3T_ALARM);
+
+static SENSOR_DEVICE_ATTR(in1_max, S_IWUSR | S_IRUGO, show_volt_max,
+ set_volt_max, 0);
+static SENSOR_DEVICE_ATTR(in2_max, S_IWUSR | S_IRUGO, show_volt_max,
+ set_volt_max, 1);
+static SENSOR_DEVICE_ATTR(in3_max, S_IWUSR | S_IRUGO, show_volt_max,
+ set_volt_max, 2);
+static SENSOR_DEVICE_ATTR(in4_max, S_IWUSR | S_IRUGO, show_volt_max,
+ set_volt_max, 3);
+static SENSOR_DEVICE_ATTR(in5_max, S_IWUSR | S_IRUGO, show_volt_max,
+ set_volt_max, 4);
+static SENSOR_DEVICE_ATTR(in6_max, S_IWUSR | S_IRUGO, show_volt_max,
+ set_volt_max, 5);
+static SENSOR_DEVICE_ATTR(in7_max, S_IWUSR | S_IRUGO, show_volt_max,
+ set_volt_max, 6);
+static SENSOR_DEVICE_ATTR(in8_max, S_IWUSR | S_IRUGO, show_volt_max,
+ set_volt_max, 7);
+static SENSOR_DEVICE_ATTR(in9_max, S_IWUSR | S_IRUGO, show_volt_max,
+ set_volt_max, 8);
+static SENSOR_DEVICE_ATTR(in10_max, S_IWUSR | S_IRUGO, show_volt_max,
+ set_volt_max, 9);
+static SENSOR_DEVICE_ATTR(in11_max, S_IWUSR | S_IRUGO, show_volt_max,
+ set_volt_max, 10);
+static SENSOR_DEVICE_ATTR(in12_max, S_IWUSR | S_IRUGO, show_volt_max,
+ set_volt_max, 11);
+static SENSOR_DEVICE_ATTR(in13_max, S_IWUSR | S_IRUGO, show_volt_max,
+ set_volt_max, 12);
+
+static SENSOR_DEVICE_ATTR(in1_min, S_IWUSR | S_IRUGO, show_volt_min,
+ set_volt_min, 0);
+static SENSOR_DEVICE_ATTR(in2_min, S_IWUSR | S_IRUGO, show_volt_min,
+ set_volt_min, 1);
+static SENSOR_DEVICE_ATTR(in3_min, S_IWUSR | S_IRUGO, show_volt_min,
+ set_volt_min, 2);
+static SENSOR_DEVICE_ATTR(in4_min, S_IWUSR | S_IRUGO, show_volt_min,
+ set_volt_min, 3);
+static SENSOR_DEVICE_ATTR(in5_min, S_IWUSR | S_IRUGO, show_volt_min,
+ set_volt_min, 4);
+static SENSOR_DEVICE_ATTR(in6_min, S_IWUSR | S_IRUGO, show_volt_min,
+ set_volt_min, 5);
+static SENSOR_DEVICE_ATTR(in7_min, S_IWUSR | S_IRUGO, show_volt_min,
+ set_volt_min, 6);
+static SENSOR_DEVICE_ATTR(in8_min, S_IWUSR | S_IRUGO, show_volt_min,
+ set_volt_min, 7);
+static SENSOR_DEVICE_ATTR(in9_min, S_IWUSR | S_IRUGO, show_volt_min,
+ set_volt_min, 8);
+static SENSOR_DEVICE_ATTR(in10_min, S_IWUSR | S_IRUGO, show_volt_min,
+ set_volt_min, 9);
+static SENSOR_DEVICE_ATTR(in11_min, S_IWUSR | S_IRUGO, show_volt_min,
+ set_volt_min, 10);
+static SENSOR_DEVICE_ATTR(in12_min, S_IWUSR | S_IRUGO, show_volt_min,
+ set_volt_min, 11);
+static SENSOR_DEVICE_ATTR(in13_min, S_IWUSR | S_IRUGO, show_volt_min,
+ set_volt_min, 12);
+
+static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_voltage, NULL, 0);
+static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_voltage, NULL, 1);
+static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_voltage, NULL, 2);
+static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_voltage, NULL, 3);
+static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_voltage, NULL, 4);
+static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_voltage, NULL, 5);
+static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, show_voltage, NULL, 6);
+static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, show_voltage, NULL, 7);
+static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, show_voltage, NULL, 8);
+static SENSOR_DEVICE_ATTR(in10_input, S_IRUGO, show_voltage, NULL, 9);
+static SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, show_voltage, NULL, 10);
+static SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, show_voltage, NULL, 11);
+static SENSOR_DEVICE_ATTR(in13_input, S_IRUGO, show_voltage, NULL, 12);
+
+static SENSOR_DEVICE_ATTR(in1_label, S_IRUGO, show_voltage_label, NULL, 0);
+static SENSOR_DEVICE_ATTR(in2_label, S_IRUGO, show_voltage_label, NULL, 1);
+static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, show_voltage_label, NULL, 2);
+static SENSOR_DEVICE_ATTR(in4_label, S_IRUGO, show_voltage_label, NULL, 3);
+static SENSOR_DEVICE_ATTR(in5_label, S_IRUGO, show_voltage_label, NULL, 4);
+static SENSOR_DEVICE_ATTR(in6_label, S_IRUGO, show_voltage_label, NULL, 5);
+static SENSOR_DEVICE_ATTR(in7_label, S_IRUGO, show_voltage_label, NULL, 6);
+static SENSOR_DEVICE_ATTR(in8_label, S_IRUGO, show_voltage_label, NULL, 7);
+static SENSOR_DEVICE_ATTR(in9_label, S_IRUGO, show_voltage_label, NULL, 8);
+static SENSOR_DEVICE_ATTR(in10_label, S_IRUGO, show_voltage_label, NULL, 9);
+static SENSOR_DEVICE_ATTR(in11_label, S_IRUGO, show_voltage_label, NULL, 10);
+static SENSOR_DEVICE_ATTR(in12_label, S_IRUGO, show_voltage_label, NULL, 11);
+static SENSOR_DEVICE_ATTR(in13_label, S_IRUGO, show_voltage_label, NULL, 12);
+
+static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL,
+ ADT7462_ALARM2 | ADT7462_V0_ALARM);
+static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL,
+ ADT7462_ALARM2 | ADT7462_V7_ALARM);
+static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL,
+ ADT7462_ALARM2 | ADT7462_V2_ALARM);
+static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL,
+ ADT7462_ALARM2 | ADT7462_V6_ALARM);
+static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL,
+ ADT7462_ALARM2 | ADT7462_V5_ALARM);
+static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL,
+ ADT7462_ALARM2 | ADT7462_V4_ALARM);
+static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL,
+ ADT7462_ALARM2 | ADT7462_V3_ALARM);
+static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL,
+ ADT7462_ALARM2 | ADT7462_V1_ALARM);
+static SENSOR_DEVICE_ATTR(in9_alarm, S_IRUGO, show_alarm, NULL,
+ ADT7462_ALARM3 | ADT7462_V10_ALARM);
+static SENSOR_DEVICE_ATTR(in10_alarm, S_IRUGO, show_alarm, NULL,
+ ADT7462_ALARM3 | ADT7462_V9_ALARM);
+static SENSOR_DEVICE_ATTR(in11_alarm, S_IRUGO, show_alarm, NULL,
+ ADT7462_ALARM3 | ADT7462_V8_ALARM);
+static SENSOR_DEVICE_ATTR(in12_alarm, S_IRUGO, show_alarm, NULL,
+ ADT7462_ALARM3 | ADT7462_V11_ALARM);
+static SENSOR_DEVICE_ATTR(in13_alarm, S_IRUGO, show_alarm, NULL,
+ ADT7462_ALARM3 | ADT7462_V12_ALARM);
+
+static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min,
+ set_fan_min, 0);
+static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min,
+ set_fan_min, 1);
+static SENSOR_DEVICE_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min,
+ set_fan_min, 2);
+static SENSOR_DEVICE_ATTR(fan4_min, S_IWUSR | S_IRUGO, show_fan_min,
+ set_fan_min, 3);
+static SENSOR_DEVICE_ATTR(fan5_min, S_IWUSR | S_IRUGO, show_fan_min,
+ set_fan_min, 4);
+static SENSOR_DEVICE_ATTR(fan6_min, S_IWUSR | S_IRUGO, show_fan_min,
+ set_fan_min, 5);
+static SENSOR_DEVICE_ATTR(fan7_min, S_IWUSR | S_IRUGO, show_fan_min,
+ set_fan_min, 6);
+static SENSOR_DEVICE_ATTR(fan8_min, S_IWUSR | S_IRUGO, show_fan_min,
+ set_fan_min, 7);
+
+static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0);
+static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1);
+static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2);
+static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3);
+static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 4);
+static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_fan, NULL, 5);
+static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_fan, NULL, 6);
+static SENSOR_DEVICE_ATTR(fan8_input, S_IRUGO, show_fan, NULL, 7);
+
+static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL,
+ ADT7462_ALARM4 | ADT7462_F0_ALARM);
+static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL,
+ ADT7462_ALARM4 | ADT7462_F1_ALARM);
+static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL,
+ ADT7462_ALARM4 | ADT7462_F2_ALARM);
+static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL,
+ ADT7462_ALARM4 | ADT7462_F3_ALARM);
+static SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL,
+ ADT7462_ALARM4 | ADT7462_F4_ALARM);
+static SENSOR_DEVICE_ATTR(fan6_alarm, S_IRUGO, show_alarm, NULL,
+ ADT7462_ALARM4 | ADT7462_F5_ALARM);
+static SENSOR_DEVICE_ATTR(fan7_alarm, S_IRUGO, show_alarm, NULL,
+ ADT7462_ALARM4 | ADT7462_F6_ALARM);
+static SENSOR_DEVICE_ATTR(fan8_alarm, S_IRUGO, show_alarm, NULL,
+ ADT7462_ALARM4 | ADT7462_F7_ALARM);
+
+static SENSOR_DEVICE_ATTR(force_pwm_max, S_IWUSR | S_IRUGO,
+ show_force_pwm_max, set_force_pwm_max, 0);
+
+static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 0);
+static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 1);
+static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 2);
+static SENSOR_DEVICE_ATTR(pwm4, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 3);
+
+static SENSOR_DEVICE_ATTR(pwm1_auto_point1_pwm, S_IWUSR | S_IRUGO,
+ show_pwm_min, set_pwm_min, 0);
+static SENSOR_DEVICE_ATTR(pwm2_auto_point1_pwm, S_IWUSR | S_IRUGO,
+ show_pwm_min, set_pwm_min, 1);
+static SENSOR_DEVICE_ATTR(pwm3_auto_point1_pwm, S_IWUSR | S_IRUGO,
+ show_pwm_min, set_pwm_min, 2);
+static SENSOR_DEVICE_ATTR(pwm4_auto_point1_pwm, S_IWUSR | S_IRUGO,
+ show_pwm_min, set_pwm_min, 3);
+
+static SENSOR_DEVICE_ATTR(pwm1_auto_point2_pwm, S_IWUSR | S_IRUGO,
+ show_pwm_max, set_pwm_max, 0);
+static SENSOR_DEVICE_ATTR(pwm2_auto_point2_pwm, S_IWUSR | S_IRUGO,
+ show_pwm_max, set_pwm_max, 1);
+static SENSOR_DEVICE_ATTR(pwm3_auto_point2_pwm, S_IWUSR | S_IRUGO,
+ show_pwm_max, set_pwm_max, 2);
+static SENSOR_DEVICE_ATTR(pwm4_auto_point2_pwm, S_IWUSR | S_IRUGO,
+ show_pwm_max, set_pwm_max, 3);
+
+static SENSOR_DEVICE_ATTR(temp1_auto_point1_hyst, S_IWUSR | S_IRUGO,
+ show_pwm_hyst, set_pwm_hyst, 0);
+static SENSOR_DEVICE_ATTR(temp2_auto_point1_hyst, S_IWUSR | S_IRUGO,
+ show_pwm_hyst, set_pwm_hyst, 1);
+static SENSOR_DEVICE_ATTR(temp3_auto_point1_hyst, S_IWUSR | S_IRUGO,
+ show_pwm_hyst, set_pwm_hyst, 2);
+static SENSOR_DEVICE_ATTR(temp4_auto_point1_hyst, S_IWUSR | S_IRUGO,
+ show_pwm_hyst, set_pwm_hyst, 3);
+
+static SENSOR_DEVICE_ATTR(temp1_auto_point2_hyst, S_IWUSR | S_IRUGO,
+ show_pwm_hyst, set_pwm_hyst, 0);
+static SENSOR_DEVICE_ATTR(temp2_auto_point2_hyst, S_IWUSR | S_IRUGO,
+ show_pwm_hyst, set_pwm_hyst, 1);
+static SENSOR_DEVICE_ATTR(temp3_auto_point2_hyst, S_IWUSR | S_IRUGO,
+ show_pwm_hyst, set_pwm_hyst, 2);
+static SENSOR_DEVICE_ATTR(temp4_auto_point2_hyst, S_IWUSR | S_IRUGO,
+ show_pwm_hyst, set_pwm_hyst, 3);
+
+static SENSOR_DEVICE_ATTR(temp1_auto_point1_temp, S_IWUSR | S_IRUGO,
+ show_pwm_tmin, set_pwm_tmin, 0);
+static SENSOR_DEVICE_ATTR(temp2_auto_point1_temp, S_IWUSR | S_IRUGO,
+ show_pwm_tmin, set_pwm_tmin, 1);
+static SENSOR_DEVICE_ATTR(temp3_auto_point1_temp, S_IWUSR | S_IRUGO,
+ show_pwm_tmin, set_pwm_tmin, 2);
+static SENSOR_DEVICE_ATTR(temp4_auto_point1_temp, S_IWUSR | S_IRUGO,
+ show_pwm_tmin, set_pwm_tmin, 3);
+
+static SENSOR_DEVICE_ATTR(temp1_auto_point2_temp, S_IWUSR | S_IRUGO,
+ show_pwm_tmax, set_pwm_tmax, 0);
+static SENSOR_DEVICE_ATTR(temp2_auto_point2_temp, S_IWUSR | S_IRUGO,
+ show_pwm_tmax, set_pwm_tmax, 1);
+static SENSOR_DEVICE_ATTR(temp3_auto_point2_temp, S_IWUSR | S_IRUGO,
+ show_pwm_tmax, set_pwm_tmax, 2);
+static SENSOR_DEVICE_ATTR(temp4_auto_point2_temp, S_IWUSR | S_IRUGO,
+ show_pwm_tmax, set_pwm_tmax, 3);
+
+static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, show_pwm_auto,
+ set_pwm_auto, 0);
+static SENSOR_DEVICE_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, show_pwm_auto,
+ set_pwm_auto, 1);
+static SENSOR_DEVICE_ATTR(pwm3_enable, S_IWUSR | S_IRUGO, show_pwm_auto,
+ set_pwm_auto, 2);
+static SENSOR_DEVICE_ATTR(pwm4_enable, S_IWUSR | S_IRUGO, show_pwm_auto,
+ set_pwm_auto, 3);
+
+static SENSOR_DEVICE_ATTR(pwm1_auto_channels_temp, S_IWUSR | S_IRUGO,
+ show_pwm_auto_temp, set_pwm_auto_temp, 0);
+static SENSOR_DEVICE_ATTR(pwm2_auto_channels_temp, S_IWUSR | S_IRUGO,
+ show_pwm_auto_temp, set_pwm_auto_temp, 1);
+static SENSOR_DEVICE_ATTR(pwm3_auto_channels_temp, S_IWUSR | S_IRUGO,
+ show_pwm_auto_temp, set_pwm_auto_temp, 2);
+static SENSOR_DEVICE_ATTR(pwm4_auto_channels_temp, S_IWUSR | S_IRUGO,
+ show_pwm_auto_temp, set_pwm_auto_temp, 3);
+
+static struct attribute *adt7462_attr[] =
+{
+ &sensor_dev_attr_temp1_max.dev_attr.attr,
+ &sensor_dev_attr_temp2_max.dev_attr.attr,
+ &sensor_dev_attr_temp3_max.dev_attr.attr,
+ &sensor_dev_attr_temp4_max.dev_attr.attr,
+
+ &sensor_dev_attr_temp1_min.dev_attr.attr,
+ &sensor_dev_attr_temp2_min.dev_attr.attr,
+ &sensor_dev_attr_temp3_min.dev_attr.attr,
+ &sensor_dev_attr_temp4_min.dev_attr.attr,
+
+ &sensor_dev_attr_temp1_input.dev_attr.attr,
+ &sensor_dev_attr_temp2_input.dev_attr.attr,
+ &sensor_dev_attr_temp3_input.dev_attr.attr,
+ &sensor_dev_attr_temp4_input.dev_attr.attr,
+
+ &sensor_dev_attr_temp1_label.dev_attr.attr,
+ &sensor_dev_attr_temp2_label.dev_attr.attr,
+ &sensor_dev_attr_temp3_label.dev_attr.attr,
+ &sensor_dev_attr_temp4_label.dev_attr.attr,
+
+ &sensor_dev_attr_temp1_alarm.dev_attr.attr,
+ &sensor_dev_attr_temp2_alarm.dev_attr.attr,
+ &sensor_dev_attr_temp3_alarm.dev_attr.attr,
+ &sensor_dev_attr_temp4_alarm.dev_attr.attr,
+
+ &sensor_dev_attr_in1_max.dev_attr.attr,
+ &sensor_dev_attr_in2_max.dev_attr.attr,
+ &sensor_dev_attr_in3_max.dev_attr.attr,
+ &sensor_dev_attr_in4_max.dev_attr.attr,
+ &sensor_dev_attr_in5_max.dev_attr.attr,
+ &sensor_dev_attr_in6_max.dev_attr.attr,
+ &sensor_dev_attr_in7_max.dev_attr.attr,
+ &sensor_dev_attr_in8_max.dev_attr.attr,
+ &sensor_dev_attr_in9_max.dev_attr.attr,
+ &sensor_dev_attr_in10_max.dev_attr.attr,
+ &sensor_dev_attr_in11_max.dev_attr.attr,
+ &sensor_dev_attr_in12_max.dev_attr.attr,
+ &sensor_dev_attr_in13_max.dev_attr.attr,
+
+ &sensor_dev_attr_in1_min.dev_attr.attr,
+ &sensor_dev_attr_in2_min.dev_attr.attr,
+ &sensor_dev_attr_in3_min.dev_attr.attr,
+ &sensor_dev_attr_in4_min.dev_attr.attr,
+ &sensor_dev_attr_in5_min.dev_attr.attr,
+ &sensor_dev_attr_in6_min.dev_attr.attr,
+ &sensor_dev_attr_in7_min.dev_attr.attr,
+ &sensor_dev_attr_in8_min.dev_attr.attr,
+ &sensor_dev_attr_in9_min.dev_attr.attr,
+ &sensor_dev_attr_in10_min.dev_attr.attr,
+ &sensor_dev_attr_in11_min.dev_attr.attr,
+ &sensor_dev_attr_in12_min.dev_attr.attr,
+ &sensor_dev_attr_in13_min.dev_attr.attr,
+
+ &sensor_dev_attr_in1_input.dev_attr.attr,
+ &sensor_dev_attr_in2_input.dev_attr.attr,
+ &sensor_dev_attr_in3_input.dev_attr.attr,
+ &sensor_dev_attr_in4_input.dev_attr.attr,
+ &sensor_dev_attr_in5_input.dev_attr.attr,
+ &sensor_dev_attr_in6_input.dev_attr.attr,
+ &sensor_dev_attr_in7_input.dev_attr.attr,
+ &sensor_dev_attr_in8_input.dev_attr.attr,
+ &sensor_dev_attr_in9_input.dev_attr.attr,
+ &sensor_dev_attr_in10_input.dev_attr.attr,
+ &sensor_dev_attr_in11_input.dev_attr.attr,
+ &sensor_dev_attr_in12_input.dev_attr.attr,
+ &sensor_dev_attr_in13_input.dev_attr.attr,
+
+ &sensor_dev_attr_in1_label.dev_attr.attr,
+ &sensor_dev_attr_in2_label.dev_attr.attr,
+ &sensor_dev_attr_in3_label.dev_attr.attr,
+ &sensor_dev_attr_in4_label.dev_attr.attr,
+ &sensor_dev_attr_in5_label.dev_attr.attr,
+ &sensor_dev_attr_in6_label.dev_attr.attr,
+ &sensor_dev_attr_in7_label.dev_attr.attr,
+ &sensor_dev_attr_in8_label.dev_attr.attr,
+ &sensor_dev_attr_in9_label.dev_attr.attr,
+ &sensor_dev_attr_in10_label.dev_attr.attr,
+ &sensor_dev_attr_in11_label.dev_attr.attr,
+ &sensor_dev_attr_in12_label.dev_attr.attr,
+ &sensor_dev_attr_in13_label.dev_attr.attr,
+
+ &sensor_dev_attr_in1_alarm.dev_attr.attr,
+ &sensor_dev_attr_in2_alarm.dev_attr.attr,
+ &sensor_dev_attr_in3_alarm.dev_attr.attr,
+ &sensor_dev_attr_in4_alarm.dev_attr.attr,
+ &sensor_dev_attr_in5_alarm.dev_attr.attr,
+ &sensor_dev_attr_in6_alarm.dev_attr.attr,
+ &sensor_dev_attr_in7_alarm.dev_attr.attr,
+ &sensor_dev_attr_in8_alarm.dev_attr.attr,
+ &sensor_dev_attr_in9_alarm.dev_attr.attr,
+ &sensor_dev_attr_in10_alarm.dev_attr.attr,
+ &sensor_dev_attr_in11_alarm.dev_attr.attr,
+ &sensor_dev_attr_in12_alarm.dev_attr.attr,
+ &sensor_dev_attr_in13_alarm.dev_attr.attr,
+
+ &sensor_dev_attr_fan1_min.dev_attr.attr,
+ &sensor_dev_attr_fan2_min.dev_attr.attr,
+ &sensor_dev_attr_fan3_min.dev_attr.attr,
+ &sensor_dev_attr_fan4_min.dev_attr.attr,
+ &sensor_dev_attr_fan5_min.dev_attr.attr,
+ &sensor_dev_attr_fan6_min.dev_attr.attr,
+ &sensor_dev_attr_fan7_min.dev_attr.attr,
+ &sensor_dev_attr_fan8_min.dev_attr.attr,
+
+ &sensor_dev_attr_fan1_input.dev_attr.attr,
+ &sensor_dev_attr_fan2_input.dev_attr.attr,
+ &sensor_dev_attr_fan3_input.dev_attr.attr,
+ &sensor_dev_attr_fan4_input.dev_attr.attr,
+ &sensor_dev_attr_fan5_input.dev_attr.attr,
+ &sensor_dev_attr_fan6_input.dev_attr.attr,
+ &sensor_dev_attr_fan7_input.dev_attr.attr,
+ &sensor_dev_attr_fan8_input.dev_attr.attr,
+
+ &sensor_dev_attr_fan1_alarm.dev_attr.attr,
+ &sensor_dev_attr_fan2_alarm.dev_attr.attr,
+ &sensor_dev_attr_fan3_alarm.dev_attr.attr,
+ &sensor_dev_attr_fan4_alarm.dev_attr.attr,
+ &sensor_dev_attr_fan5_alarm.dev_attr.attr,
+ &sensor_dev_attr_fan6_alarm.dev_attr.attr,
+ &sensor_dev_attr_fan7_alarm.dev_attr.attr,
+ &sensor_dev_attr_fan8_alarm.dev_attr.attr,
+
+ &sensor_dev_attr_force_pwm_max.dev_attr.attr,
+ &sensor_dev_attr_pwm1.dev_attr.attr,
+ &sensor_dev_attr_pwm2.dev_attr.attr,
+ &sensor_dev_attr_pwm3.dev_attr.attr,
+ &sensor_dev_attr_pwm4.dev_attr.attr,
+
+ &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm4_auto_point1_pwm.dev_attr.attr,
+
+ &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm2_auto_point2_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm3_auto_point2_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm4_auto_point2_pwm.dev_attr.attr,
+
+ &sensor_dev_attr_temp1_auto_point1_hyst.dev_attr.attr,
+ &sensor_dev_attr_temp2_auto_point1_hyst.dev_attr.attr,
+ &sensor_dev_attr_temp3_auto_point1_hyst.dev_attr.attr,
+ &sensor_dev_attr_temp4_auto_point1_hyst.dev_attr.attr,
+
+ &sensor_dev_attr_temp1_auto_point2_hyst.dev_attr.attr,
+ &sensor_dev_attr_temp2_auto_point2_hyst.dev_attr.attr,
+ &sensor_dev_attr_temp3_auto_point2_hyst.dev_attr.attr,
+ &sensor_dev_attr_temp4_auto_point2_hyst.dev_attr.attr,
+
+ &sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr,
+ &sensor_dev_attr_temp2_auto_point1_temp.dev_attr.attr,
+ &sensor_dev_attr_temp3_auto_point1_temp.dev_attr.attr,
+ &sensor_dev_attr_temp4_auto_point1_temp.dev_attr.attr,
+
+ &sensor_dev_attr_temp1_auto_point2_temp.dev_attr.attr,
+ &sensor_dev_attr_temp2_auto_point2_temp.dev_attr.attr,
+ &sensor_dev_attr_temp3_auto_point2_temp.dev_attr.attr,
+ &sensor_dev_attr_temp4_auto_point2_temp.dev_attr.attr,
+
+ &sensor_dev_attr_pwm1_enable.dev_attr.attr,
+ &sensor_dev_attr_pwm2_enable.dev_attr.attr,
+ &sensor_dev_attr_pwm3_enable.dev_attr.attr,
+ &sensor_dev_attr_pwm4_enable.dev_attr.attr,
+
+ &sensor_dev_attr_pwm1_auto_channels_temp.dev_attr.attr,
+ &sensor_dev_attr_pwm2_auto_channels_temp.dev_attr.attr,
+ &sensor_dev_attr_pwm3_auto_channels_temp.dev_attr.attr,
+ &sensor_dev_attr_pwm4_auto_channels_temp.dev_attr.attr,
+ NULL
+};
+
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int adt7462_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info)
+{
+ struct i2c_adapter *adapter = client->adapter;
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ return -ENODEV;
+
+ if (kind <= 0) {
+ int vendor, device, revision;
+
+ vendor = i2c_smbus_read_byte_data(client, ADT7462_REG_VENDOR);
+ if (vendor != ADT7462_VENDOR)
+ return -ENODEV;
+
+ device = i2c_smbus_read_byte_data(client, ADT7462_REG_DEVICE);
+ if (device != ADT7462_DEVICE)
+ return -ENODEV;
+
+ revision = i2c_smbus_read_byte_data(client,
+ ADT7462_REG_REVISION);
+ if (revision != ADT7462_REVISION)
+ return -ENODEV;
+ } else
+ dev_dbg(&adapter->dev, "detection forced\n");
+
+ strlcpy(info->type, "adt7462", I2C_NAME_SIZE);
+
+ return 0;
+}
+
+static int adt7462_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct adt7462_data *data;
+ int err;
+
+ data = kzalloc(sizeof(struct adt7462_data), GFP_KERNEL);
+ if (!data) {
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ i2c_set_clientdata(client, data);
+ mutex_init(&data->lock);
+
+ dev_info(&client->dev, "%s chip found\n", client->name);
+
+ /* Register sysfs hooks */
+ data->attrs.attrs = adt7462_attr;
+ err = sysfs_create_group(&client->dev.kobj, &data->attrs);
+ if (err)
+ goto exit_free;
+
+ data->hwmon_dev = hwmon_device_register(&client->dev);
+ if (IS_ERR(data->hwmon_dev)) {
+ err = PTR_ERR(data->hwmon_dev);
+ goto exit_remove;
+ }
+
+ return 0;
+
+exit_remove:
+ sysfs_remove_group(&client->dev.kobj, &data->attrs);
+exit_free:
+ kfree(data);
+exit:
+ return err;
+}
+
+static int adt7462_remove(struct i2c_client *client)
+{
+ struct adt7462_data *data = i2c_get_clientdata(client);
+
+ hwmon_device_unregister(data->hwmon_dev);
+ sysfs_remove_group(&client->dev.kobj, &data->attrs);
+ kfree(data);
+ return 0;
+}
+
+static int __init adt7462_init(void)
+{
+ return i2c_add_driver(&adt7462_driver);
+}
+
+static void __exit adt7462_exit(void)
+{
+ i2c_del_driver(&adt7462_driver);
+}
+
+MODULE_AUTHOR("Darrick J. Wong <djwong@us.ibm.com>");
+MODULE_DESCRIPTION("ADT7462 driver");
+MODULE_LICENSE("GPL");
+
+module_init(adt7462_init);
+module_exit(adt7462_exit);
diff --git a/drivers/hwmon/adt7470.c b/drivers/hwmon/adt7470.c
index d368d8f845e..1311a595147 100644
--- a/drivers/hwmon/adt7470.c
+++ b/drivers/hwmon/adt7470.c
@@ -137,6 +137,8 @@ I2C_CLIENT_INSMOD_1(adt7470);
#define FAN_PERIOD_INVALID 65535
#define FAN_DATA_VALID(x) ((x) && (x) != FAN_PERIOD_INVALID)
+#define ROUND_DIV(x, divisor) (((x) + ((divisor) / 2)) / (divisor))
+
struct adt7470_data {
struct device *hwmon_dev;
struct attribute_group attrs;
@@ -353,7 +355,13 @@ static ssize_t set_temp_min(struct device *dev,
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct i2c_client *client = to_i2c_client(dev);
struct adt7470_data *data = i2c_get_clientdata(client);
- int temp = simple_strtol(buf, NULL, 10) / 1000;
+ long temp;
+
+ if (strict_strtol(buf, 10, &temp))
+ return -EINVAL;
+
+ temp = ROUND_DIV(temp, 1000);
+ temp = SENSORS_LIMIT(temp, 0, 255);
mutex_lock(&data->lock);
data->temp_min[attr->index] = temp;
@@ -381,7 +389,13 @@ static ssize_t set_temp_max(struct device *dev,
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct i2c_client *client = to_i2c_client(dev);
struct adt7470_data *data = i2c_get_clientdata(client);
- int temp = simple_strtol(buf, NULL, 10) / 1000;
+ long temp;
+
+ if (strict_strtol(buf, 10, &temp))
+ return -EINVAL;
+
+ temp = ROUND_DIV(temp, 1000);
+ temp = SENSORS_LIMIT(temp, 0, 255);
mutex_lock(&data->lock);
data->temp_max[attr->index] = temp;
@@ -430,11 +444,13 @@ static ssize_t set_fan_max(struct device *dev,
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct i2c_client *client = to_i2c_client(dev);
struct adt7470_data *data = i2c_get_clientdata(client);
- int temp = simple_strtol(buf, NULL, 10);
+ long temp;
- if (!temp)
+ if (strict_strtol(buf, 10, &temp) || !temp)
return -EINVAL;
+
temp = FAN_RPM_TO_PERIOD(temp);
+ temp = SENSORS_LIMIT(temp, 1, 65534);
mutex_lock(&data->lock);
data->fan_max[attr->index] = temp;
@@ -465,11 +481,13 @@ static ssize_t set_fan_min(struct device *dev,
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct i2c_client *client = to_i2c_client(dev);
struct adt7470_data *data = i2c_get_clientdata(client);
- int temp = simple_strtol(buf, NULL, 10);
+ long temp;
- if (!temp)
+ if (strict_strtol(buf, 10, &temp) || !temp)
return -EINVAL;
+
temp = FAN_RPM_TO_PERIOD(temp);
+ temp = SENSORS_LIMIT(temp, 1, 65534);
mutex_lock(&data->lock);
data->fan_min[attr->index] = temp;
@@ -507,9 +525,12 @@ static ssize_t set_force_pwm_max(struct device *dev,
{
struct i2c_client *client = to_i2c_client(dev);
struct adt7470_data *data = i2c_get_clientdata(client);
- int temp = simple_strtol(buf, NULL, 10);
+ long temp;
u8 reg;
+ if (strict_strtol(buf, 10, &temp))
+ return -EINVAL;
+
mutex_lock(&data->lock);
data->force_pwm_max = temp;
reg = i2c_smbus_read_byte_data(client, ADT7470_REG_CFG);
@@ -537,7 +558,12 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr,
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct i2c_client *client = to_i2c_client(dev);
struct adt7470_data *data = i2c_get_clientdata(client);
- int temp = simple_strtol(buf, NULL, 10);
+ long temp;
+
+ if (strict_strtol(buf, 10, &temp))
+ return -EINVAL;
+
+ temp = SENSORS_LIMIT(temp, 0, 255);
mutex_lock(&data->lock);
data->pwm[attr->index] = temp;
@@ -564,7 +590,12 @@ static ssize_t set_pwm_max(struct device *dev,
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct i2c_client *client = to_i2c_client(dev);
struct adt7470_data *data = i2c_get_clientdata(client);
- int temp = simple_strtol(buf, NULL, 10);
+ long temp;
+
+ if (strict_strtol(buf, 10, &temp))
+ return -EINVAL;
+
+ temp = SENSORS_LIMIT(temp, 0, 255);
mutex_lock(&data->lock);
data->pwm_max[attr->index] = temp;
@@ -592,7 +623,12 @@ static ssize_t set_pwm_min(struct device *dev,
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct i2c_client *client = to_i2c_client(dev);
struct adt7470_data *data = i2c_get_clientdata(client);
- int temp = simple_strtol(buf, NULL, 10);
+ long temp;
+
+ if (strict_strtol(buf, 10, &temp))
+ return -EINVAL;
+
+ temp = SENSORS_LIMIT(temp, 0, 255);
mutex_lock(&data->lock);
data->pwm_min[attr->index] = temp;
@@ -630,7 +666,13 @@ static ssize_t set_pwm_tmin(struct device *dev,
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct i2c_client *client = to_i2c_client(dev);
struct adt7470_data *data = i2c_get_clientdata(client);
- int temp = simple_strtol(buf, NULL, 10) / 1000;
+ long temp;
+
+ if (strict_strtol(buf, 10, &temp))
+ return -EINVAL;
+
+ temp = ROUND_DIV(temp, 1000);
+ temp = SENSORS_LIMIT(temp, 0, 255);
mutex_lock(&data->lock);
data->pwm_tmin[attr->index] = temp;
@@ -658,11 +700,14 @@ static ssize_t set_pwm_auto(struct device *dev,
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct i2c_client *client = to_i2c_client(dev);
struct adt7470_data *data = i2c_get_clientdata(client);
- int temp = simple_strtol(buf, NULL, 10);
int pwm_auto_reg = ADT7470_REG_PWM_CFG(attr->index);
int pwm_auto_reg_mask;
+ long temp;
u8 reg;
+ if (strict_strtol(buf, 10, &temp))
+ return -EINVAL;
+
if (attr->index % 2)
pwm_auto_reg_mask = ADT7470_PWM2_AUTO_MASK;
else
@@ -716,10 +761,14 @@ static ssize_t set_pwm_auto_temp(struct device *dev,
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct i2c_client *client = to_i2c_client(dev);
struct adt7470_data *data = i2c_get_clientdata(client);
- int temp = cvt_auto_temp(simple_strtol(buf, NULL, 10));
int pwm_auto_reg = ADT7470_REG_PWM_AUTO_TEMP(attr->index);
+ long temp;
u8 reg;
+ if (strict_strtol(buf, 10, &temp))
+ return -EINVAL;
+
+ temp = cvt_auto_temp(temp);
if (temp < 0)
return temp;
diff --git a/drivers/hwmon/adt7473.c b/drivers/hwmon/adt7473.c
index b9a8ea30c99..18aa30866a6 100644
--- a/drivers/hwmon/adt7473.c
+++ b/drivers/hwmon/adt7473.c
@@ -129,6 +129,8 @@ I2C_CLIENT_INSMOD_1(adt7473);
#define FAN_PERIOD_INVALID 65535
#define FAN_DATA_VALID(x) ((x) && (x) != FAN_PERIOD_INVALID)
+#define ROUND_DIV(x, divisor) (((x) + ((divisor) / 2)) / (divisor))
+
struct adt7473_data {
struct device *hwmon_dev;
struct attribute_group attrs;
@@ -357,7 +359,12 @@ static ssize_t set_volt_min(struct device *dev,
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct i2c_client *client = to_i2c_client(dev);
struct adt7473_data *data = i2c_get_clientdata(client);
- int volt = encode_volt(attr->index, simple_strtol(buf, NULL, 10));
+ long volt;
+
+ if (strict_strtol(buf, 10, &volt))
+ return -EINVAL;
+
+ volt = encode_volt(attr->index, volt);
mutex_lock(&data->lock);
data->volt_min[attr->index] = volt;
@@ -386,7 +393,12 @@ static ssize_t set_volt_max(struct device *dev,
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct i2c_client *client = to_i2c_client(dev);
struct adt7473_data *data = i2c_get_clientdata(client);
- int volt = encode_volt(attr->index, simple_strtol(buf, NULL, 10));
+ long volt;
+
+ if (strict_strtol(buf, 10, &volt))
+ return -EINVAL;
+
+ volt = encode_volt(attr->index, volt);
mutex_lock(&data->lock);
data->volt_max[attr->index] = volt;
@@ -419,7 +431,8 @@ static int decode_temp(u8 twos_complement, u8 raw)
static u8 encode_temp(u8 twos_complement, int cooked)
{
- return twos_complement ? cooked & 0xFF : cooked + 64;
+ u8 ret = twos_complement ? cooked & 0xFF : cooked + 64;
+ return SENSORS_LIMIT(ret, 0, 255);
}
static ssize_t show_temp_min(struct device *dev,
@@ -441,7 +454,12 @@ static ssize_t set_temp_min(struct device *dev,
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct i2c_client *client = to_i2c_client(dev);
struct adt7473_data *data = i2c_get_clientdata(client);
- int temp = simple_strtol(buf, NULL, 10) / 1000;
+ long temp;
+
+ if (strict_strtol(buf, 10, &temp))
+ return -EINVAL;
+
+ temp = ROUND_DIV(temp, 1000);
temp = encode_temp(data->temp_twos_complement, temp);
mutex_lock(&data->lock);
@@ -472,7 +490,12 @@ static ssize_t set_temp_max(struct device *dev,
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct i2c_client *client = to_i2c_client(dev);
struct adt7473_data *data = i2c_get_clientdata(client);
- int temp = simple_strtol(buf, NULL, 10) / 1000;
+ long temp;
+
+ if (strict_strtol(buf, 10, &temp))
+ return -EINVAL;
+
+ temp = ROUND_DIV(temp, 1000);
temp = encode_temp(data->temp_twos_complement, temp);
mutex_lock(&data->lock);
@@ -515,11 +538,13 @@ static ssize_t set_fan_min(struct device *dev,
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct i2c_client *client = to_i2c_client(dev);
struct adt7473_data *data = i2c_get_clientdata(client);
- int temp = simple_strtol(buf, NULL, 10);
+ long temp;
- if (!temp)
+ if (strict_strtol(buf, 10, &temp) || !temp)
return -EINVAL;
+
temp = FAN_RPM_TO_PERIOD(temp);
+ temp = SENSORS_LIMIT(temp, 1, 65534);
mutex_lock(&data->lock);
data->fan_min[attr->index] = temp;
@@ -558,7 +583,10 @@ static ssize_t set_max_duty_at_crit(struct device *dev,
u8 reg;
struct i2c_client *client = to_i2c_client(dev);
struct adt7473_data *data = i2c_get_clientdata(client);
- int temp = simple_strtol(buf, NULL, 10);
+ long temp;
+
+ if (strict_strtol(buf, 10, &temp))
+ return -EINVAL;
mutex_lock(&data->lock);
data->max_duty_at_overheat = !!temp;
@@ -587,7 +615,12 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr,
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct i2c_client *client = to_i2c_client(dev);
struct adt7473_data *data = i2c_get_clientdata(client);
- int temp = simple_strtol(buf, NULL, 10);
+ long temp;
+
+ if (strict_strtol(buf, 10, &temp))
+ return -EINVAL;
+
+ temp = SENSORS_LIMIT(temp, 0, 255);
mutex_lock(&data->lock);
data->pwm[attr->index] = temp;
@@ -614,7 +647,12 @@ static ssize_t set_pwm_max(struct device *dev,
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct i2c_client *client = to_i2c_client(dev);
struct adt7473_data *data = i2c_get_clientdata(client);
- int temp = simple_strtol(buf, NULL, 10);
+ long temp;
+
+ if (strict_strtol(buf, 10, &temp))
+ return -EINVAL;
+
+ temp = SENSORS_LIMIT(temp, 0, 255);
mutex_lock(&data->lock);
data->pwm_max[attr->index] = temp;
@@ -642,7 +680,12 @@ static ssize_t set_pwm_min(struct device *dev,
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct i2c_client *client = to_i2c_client(dev);
struct adt7473_data *data = i2c_get_clientdata(client);
- int temp = simple_strtol(buf, NULL, 10);
+ long temp;
+
+ if (strict_strtol(buf, 10, &temp))
+ return -EINVAL;
+
+ temp = SENSORS_LIMIT(temp, 0, 255);
mutex_lock(&data->lock);
data->pwm_min[attr->index] = temp;
@@ -672,7 +715,12 @@ static ssize_t set_temp_tmax(struct device *dev,
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct i2c_client *client = to_i2c_client(dev);
struct adt7473_data *data = i2c_get_clientdata(client);
- int temp = simple_strtol(buf, NULL, 10) / 1000;
+ long temp;
+
+ if (strict_strtol(buf, 10, &temp))
+ return -EINVAL;
+
+ temp = ROUND_DIV(temp, 1000);
temp = encode_temp(data->temp_twos_complement, temp);
mutex_lock(&data->lock);
@@ -703,7 +751,12 @@ static ssize_t set_temp_tmin(struct device *dev,
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct i2c_client *client = to_i2c_client(dev);
struct adt7473_data *data = i2c_get_clientdata(client);
- int temp = simple_strtol(buf, NULL, 10) / 1000;
+ long temp;
+
+ if (strict_strtol(buf, 10, &temp))
+ return -EINVAL;
+
+ temp = ROUND_DIV(temp, 1000);
temp = encode_temp(data->temp_twos_complement, temp);
mutex_lock(&data->lock);
@@ -741,7 +794,10 @@ static ssize_t set_pwm_enable(struct device *dev,
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct i2c_client *client = to_i2c_client(dev);
struct adt7473_data *data = i2c_get_clientdata(client);
- int temp = simple_strtol(buf, NULL, 10);
+ long temp;
+
+ if (strict_strtol(buf, 10, &temp))
+ return -EINVAL;
switch (temp) {
case 0:
@@ -805,7 +861,10 @@ static ssize_t set_pwm_auto_temp(struct device *dev,
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct i2c_client *client = to_i2c_client(dev);
struct adt7473_data *data = i2c_get_clientdata(client);
- int temp = simple_strtol(buf, NULL, 10);
+ long temp;
+
+ if (strict_strtol(buf, 10, &temp))
+ return -EINVAL;
switch (temp) {
case 1:
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
index be3285912cb..086c2a5cef0 100644
--- a/drivers/hwmon/applesmc.c
+++ b/drivers/hwmon/applesmc.c
@@ -128,6 +128,9 @@ static const char* temperature_sensors_sets[][36] = {
/* Set 13: iMac 8,1 */
{ "TA0P", "TC0D", "TC0H", "TC0P", "TG0D", "TG0H", "TG0P", "TH0P",
"TL0P", "TO0P", "TW0P", "Tm0P", "Tp0P", NULL },
+/* Set 14: iMac 6,1 */
+ { "TA0P", "TC0D", "TC0H", "TC0P", "TG0D", "TG0H", "TG0P", "TH0P",
+ "TO0P", "Tp0P", NULL },
};
/* List of keys used to read/write fan speeds */
@@ -1280,7 +1283,7 @@ static __initdata struct dmi_match_data applesmc_dmi_data[] = {
{ .accelerometer = 0, .light = 0, .temperature_set = 4 },
/* iMac: temperature set 5 */
{ .accelerometer = 0, .light = 0, .temperature_set = 5 },
-/* MacBook3: accelerometer and temperature set 6 */
+/* MacBook3, MacBook4: accelerometer and temperature set 6 */
{ .accelerometer = 1, .light = 0, .temperature_set = 6 },
/* MacBook Air: accelerometer, backlight and temperature set 7 */
{ .accelerometer = 1, .light = 1, .temperature_set = 7 },
@@ -1296,6 +1299,8 @@ static __initdata struct dmi_match_data applesmc_dmi_data[] = {
{ .accelerometer = 1, .light = 1, .temperature_set = 12 },
/* iMac 8: light sensor only, temperature set 13 */
{ .accelerometer = 0, .light = 0, .temperature_set = 13 },
+/* iMac 6: light sensor only, temperature set 14 */
+ { .accelerometer = 0, .light = 0, .temperature_set = 14 },
};
/* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1".
@@ -1329,6 +1334,10 @@ static __initdata struct dmi_system_id applesmc_whitelist[] = {
DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
DMI_MATCH(DMI_PRODUCT_NAME,"MacBook3") },
&applesmc_dmi_data[6]},
+ { applesmc_dmi_match, "Apple MacBook 4", {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "MacBook4") },
+ &applesmc_dmi_data[6]},
{ applesmc_dmi_match, "Apple MacBook 5", {
DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
DMI_MATCH(DMI_PRODUCT_NAME, "MacBook5") },
@@ -1345,10 +1354,18 @@ static __initdata struct dmi_system_id applesmc_whitelist[] = {
DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
DMI_MATCH(DMI_PRODUCT_NAME,"MacPro2") },
&applesmc_dmi_data[4]},
+ { applesmc_dmi_match, "Apple MacPro", {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "MacPro") },
+ &applesmc_dmi_data[4]},
{ applesmc_dmi_match, "Apple iMac 8", {
DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
DMI_MATCH(DMI_PRODUCT_NAME, "iMac8") },
&applesmc_dmi_data[13]},
+ { applesmc_dmi_match, "Apple iMac 6", {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "iMac6") },
+ &applesmc_dmi_data[14]},
{ applesmc_dmi_match, "Apple iMac 5", {
DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
DMI_MATCH(DMI_PRODUCT_NAME, "iMac5") },
@@ -1547,3 +1564,4 @@ module_exit(applesmc_exit);
MODULE_AUTHOR("Nicolas Boichat");
MODULE_DESCRIPTION("Apple SMC");
MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(dmi, applesmc_whitelist);
diff --git a/drivers/hwmon/ibmaem.c b/drivers/hwmon/ibmaem.c
index 7b0ed5dea39..fe74609a7fe 100644
--- a/drivers/hwmon/ibmaem.c
+++ b/drivers/hwmon/ibmaem.c
@@ -88,9 +88,11 @@
static DEFINE_IDR(aem_idr);
static DEFINE_SPINLOCK(aem_idr_lock);
-static struct device_driver aem_driver = {
- .name = DRVNAME,
- .bus = &platform_bus_type,
+static struct platform_driver aem_driver = {
+ .driver = {
+ .name = DRVNAME,
+ .bus = &platform_bus_type,
+ }
};
struct aem_ipmi_data {
@@ -583,7 +585,7 @@ static int aem_init_aem1_inst(struct aem_ipmi_data *probe, u8 module_handle)
data->pdev = platform_device_alloc(DRVNAME, data->id);
if (!data->pdev)
goto dev_err;
- data->pdev->dev.driver = &aem_driver;
+ data->pdev->dev.driver = &aem_driver.driver;
res = platform_device_add(data->pdev);
if (res)
@@ -716,7 +718,7 @@ static int aem_init_aem2_inst(struct aem_ipmi_data *probe,
data->pdev = platform_device_alloc(DRVNAME, data->id);
if (!data->pdev)
goto dev_err;
- data->pdev->dev.driver = &aem_driver;
+ data->pdev->dev.driver = &aem_driver.driver;
res = platform_device_add(data->pdev);
if (res)
@@ -1085,7 +1087,7 @@ static int __init aem_init(void)
{
int res;
- res = driver_register(&aem_driver);
+ res = driver_register(&aem_driver.driver);
if (res) {
printk(KERN_ERR "Can't register aem driver\n");
return res;
@@ -1097,7 +1099,7 @@ static int __init aem_init(void)
return 0;
ipmi_reg_err:
- driver_unregister(&aem_driver);
+ driver_unregister(&aem_driver.driver);
return res;
}
@@ -1107,7 +1109,7 @@ static void __exit aem_exit(void)
struct aem_data *p1, *next1;
ipmi_smi_watcher_unregister(&driver_data.bmc_events);
- driver_unregister(&aem_driver);
+ driver_unregister(&aem_driver.driver);
list_for_each_entry_safe(p1, next1, &driver_data.aem_devices, list)
aem_delete(p1);
}
diff --git a/drivers/hwmon/lis3lv02d.c b/drivers/hwmon/lis3lv02d.c
new file mode 100644
index 00000000000..c002144c76b
--- /dev/null
+++ b/drivers/hwmon/lis3lv02d.c
@@ -0,0 +1,581 @@
+/*
+ * lis3lv02d.c - ST LIS3LV02DL accelerometer driver
+ *
+ * Copyright (C) 2007-2008 Yan Burman
+ * Copyright (C) 2008 Eric Piel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/dmi.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/kthread.h>
+#include <linux/semaphore.h>
+#include <linux/delay.h>
+#include <linux/wait.h>
+#include <linux/poll.h>
+#include <linux/freezer.h>
+#include <linux/uaccess.h>
+#include <acpi/acpi_drivers.h>
+#include <asm/atomic.h>
+#include "lis3lv02d.h"
+
+#define DRIVER_NAME "lis3lv02d"
+#define ACPI_MDPS_CLASS "accelerometer"
+
+/* joystick device poll interval in milliseconds */
+#define MDPS_POLL_INTERVAL 50
+/*
+ * The sensor can also generate interrupts (DRDY) but it's pretty pointless
+ * because their are generated even if the data do not change. So it's better
+ * to keep the interrupt for the free-fall event. The values are updated at
+ * 40Hz (at the lowest frequency), but as it can be pretty time consuming on
+ * some low processor, we poll the sensor only at 20Hz... enough for the
+ * joystick.
+ */
+
+/* Maximum value our axis may get for the input device (signed 12 bits) */
+#define MDPS_MAX_VAL 2048
+
+struct axis_conversion {
+ s8 x;
+ s8 y;
+ s8 z;
+};
+
+struct acpi_lis3lv02d {
+ struct acpi_device *device; /* The ACPI device */
+ struct input_dev *idev; /* input device */
+ struct task_struct *kthread; /* kthread for input */
+ struct mutex lock;
+ struct platform_device *pdev; /* platform device */
+ atomic_t count; /* interrupt count after last read */
+ int xcalib; /* calibrated null value for x */
+ int ycalib; /* calibrated null value for y */
+ int zcalib; /* calibrated null value for z */
+ unsigned char is_on; /* whether the device is on or off */
+ unsigned char usage; /* usage counter */
+ struct axis_conversion ac; /* hw -> logical axis */
+};
+
+static struct acpi_lis3lv02d adev;
+
+static int lis3lv02d_remove_fs(void);
+static int lis3lv02d_add_fs(struct acpi_device *device);
+
+/* For automatic insertion of the module */
+static struct acpi_device_id lis3lv02d_device_ids[] = {
+ {"HPQ0004", 0}, /* HP Mobile Data Protection System PNP */
+ {"", 0},
+};
+MODULE_DEVICE_TABLE(acpi, lis3lv02d_device_ids);
+
+/**
+ * lis3lv02d_acpi_init - ACPI _INI method: initialize the device.
+ * @handle: the handle of the device
+ *
+ * Returns AE_OK on success.
+ */
+static inline acpi_status lis3lv02d_acpi_init(acpi_handle handle)
+{
+ return acpi_evaluate_object(handle, METHOD_NAME__INI, NULL, NULL);
+}
+
+/**
+ * lis3lv02d_acpi_read - ACPI ALRD method: read a register
+ * @handle: the handle of the device
+ * @reg: the register to read
+ * @ret: result of the operation
+ *
+ * Returns AE_OK on success.
+ */
+static acpi_status lis3lv02d_acpi_read(acpi_handle handle, int reg, u8 *ret)
+{
+ union acpi_object arg0 = { ACPI_TYPE_INTEGER };
+ struct acpi_object_list args = { 1, &arg0 };
+ unsigned long long lret;
+ acpi_status status;
+
+ arg0.integer.value = reg;
+
+ status = acpi_evaluate_integer(handle, "ALRD", &args, &lret);
+ *ret = lret;
+ return status;
+}
+
+/**
+ * lis3lv02d_acpi_write - ACPI ALWR method: write to a register
+ * @handle: the handle of the device
+ * @reg: the register to write to
+ * @val: the value to write
+ *
+ * Returns AE_OK on success.
+ */
+static acpi_status lis3lv02d_acpi_write(acpi_handle handle, int reg, u8 val)
+{
+ unsigned long long ret; /* Not used when writting */
+ union acpi_object in_obj[2];
+ struct acpi_object_list args = { 2, in_obj };
+
+ in_obj[0].type = ACPI_TYPE_INTEGER;
+ in_obj[0].integer.value = reg;
+ in_obj[1].type = ACPI_TYPE_INTEGER;
+ in_obj[1].integer.value = val;
+
+ return acpi_evaluate_integer(handle, "ALWR", &args, &ret);
+}
+
+static s16 lis3lv02d_read_16(acpi_handle handle, int reg)
+{
+ u8 lo, hi;
+
+ lis3lv02d_acpi_read(handle, reg, &lo);
+ lis3lv02d_acpi_read(handle, reg + 1, &hi);
+ /* In "12 bit right justified" mode, bit 6, bit 7, bit 8 = bit 5 */
+ return (s16)((hi << 8) | lo);
+}
+
+/**
+ * lis3lv02d_get_axis - For the given axis, give the value converted
+ * @axis: 1,2,3 - can also be negative
+ * @hw_values: raw values returned by the hardware
+ *
+ * Returns the converted value.
+ */
+static inline int lis3lv02d_get_axis(s8 axis, int hw_values[3])
+{
+ if (axis > 0)
+ return hw_values[axis - 1];
+ else
+ return -hw_values[-axis - 1];
+}
+
+/**
+ * lis3lv02d_get_xyz - Get X, Y and Z axis values from the accelerometer
+ * @handle: the handle to the device
+ * @x: where to store the X axis value
+ * @y: where to store the Y axis value
+ * @z: where to store the Z axis value
+ *
+ * Note that 40Hz input device can eat up about 10% CPU at 800MHZ
+ */
+static void lis3lv02d_get_xyz(acpi_handle handle, int *x, int *y, int *z)
+{
+ int position[3];
+
+ position[0] = lis3lv02d_read_16(handle, OUTX_L);
+ position[1] = lis3lv02d_read_16(handle, OUTY_L);
+ position[2] = lis3lv02d_read_16(handle, OUTZ_L);
+
+ *x = lis3lv02d_get_axis(adev.ac.x, position);
+ *y = lis3lv02d_get_axis(adev.ac.y, position);
+ *z = lis3lv02d_get_axis(adev.ac.z, position);
+}
+
+static inline void lis3lv02d_poweroff(acpi_handle handle)
+{
+ adev.is_on = 0;
+ /* disable X,Y,Z axis and power down */
+ lis3lv02d_acpi_write(handle, CTRL_REG1, 0x00);
+}
+
+static void lis3lv02d_poweron(acpi_handle handle)
+{
+ u8 val;
+
+ adev.is_on = 1;
+ lis3lv02d_acpi_init(handle);
+ lis3lv02d_acpi_write(handle, FF_WU_CFG, 0);
+ /*
+ * BDU: LSB and MSB values are not updated until both have been read.
+ * So the value read will always be correct.
+ * IEN: Interrupt for free-fall and DD, not for data-ready.
+ */
+ lis3lv02d_acpi_read(handle, CTRL_REG2, &val);
+ val |= CTRL2_BDU | CTRL2_IEN;
+ lis3lv02d_acpi_write(handle, CTRL_REG2, val);
+}
+
+#ifdef CONFIG_PM
+static int lis3lv02d_suspend(struct acpi_device *device, pm_message_t state)
+{
+ /* make sure the device is off when we suspend */
+ lis3lv02d_poweroff(device->handle);
+ return 0;
+}
+
+static int lis3lv02d_resume(struct acpi_device *device)
+{
+ /* put back the device in the right state (ACPI might turn it on) */
+ mutex_lock(&adev.lock);
+ if (adev.usage > 0)
+ lis3lv02d_poweron(device->handle);
+ else
+ lis3lv02d_poweroff(device->handle);
+ mutex_unlock(&adev.lock);
+ return 0;
+}
+#else
+#define lis3lv02d_suspend NULL
+#define lis3lv02d_resume NULL
+#endif
+
+
+/*
+ * To be called before starting to use the device. It makes sure that the
+ * device will always be on until a call to lis3lv02d_decrease_use(). Not to be
+ * used from interrupt context.
+ */
+static void lis3lv02d_increase_use(struct acpi_lis3lv02d *dev)
+{
+ mutex_lock(&dev->lock);
+ dev->usage++;
+ if (dev->usage == 1) {
+ if (!dev->is_on)
+ lis3lv02d_poweron(dev->device->handle);
+ }
+ mutex_unlock(&dev->lock);
+}
+
+/*
+ * To be called whenever a usage of the device is stopped.
+ * It will make sure to turn off the device when there is not usage.
+ */
+static void lis3lv02d_decrease_use(struct acpi_lis3lv02d *dev)
+{
+ mutex_lock(&dev->lock);
+ dev->usage--;
+ if (dev->usage == 0)
+ lis3lv02d_poweroff(dev->device->handle);
+ mutex_unlock(&dev->lock);
+}
+
+/**
+ * lis3lv02d_joystick_kthread - Kthread polling function
+ * @data: unused - here to conform to threadfn prototype
+ */
+static int lis3lv02d_joystick_kthread(void *data)
+{
+ int x, y, z;
+
+ while (!kthread_should_stop()) {
+ lis3lv02d_get_xyz(adev.device->handle, &x, &y, &z);
+ input_report_abs(adev.idev, ABS_X, x - adev.xcalib);
+ input_report_abs(adev.idev, ABS_Y, y - adev.ycalib);
+ input_report_abs(adev.idev, ABS_Z, z - adev.zcalib);
+
+ input_sync(adev.idev);
+
+ try_to_freeze();
+ msleep_interruptible(MDPS_POLL_INTERVAL);
+ }
+
+ return 0;
+}
+
+static int lis3lv02d_joystick_open(struct input_dev *input)
+{
+ lis3lv02d_increase_use(&adev);
+ adev.kthread = kthread_run(lis3lv02d_joystick_kthread, NULL, "klis3lv02d");
+ if (IS_ERR(adev.kthread)) {
+ lis3lv02d_decrease_use(&adev);
+ return PTR_ERR(adev.kthread);
+ }
+
+ return 0;
+}
+
+static void lis3lv02d_joystick_close(struct input_dev *input)
+{
+ kthread_stop(adev.kthread);
+ lis3lv02d_decrease_use(&adev);
+}
+
+
+static inline void lis3lv02d_calibrate_joystick(void)
+{
+ lis3lv02d_get_xyz(adev.device->handle, &adev.xcalib, &adev.ycalib, &adev.zcalib);
+}
+
+static int lis3lv02d_joystick_enable(void)
+{
+ int err;
+
+ if (adev.idev)
+ return -EINVAL;
+
+ adev.idev = input_allocate_device();
+ if (!adev.idev)
+ return -ENOMEM;
+
+ lis3lv02d_calibrate_joystick();
+
+ adev.idev->name = "ST LIS3LV02DL Accelerometer";
+ adev.idev->phys = DRIVER_NAME "/input0";
+ adev.idev->id.bustype = BUS_HOST;
+ adev.idev->id.vendor = 0;
+ adev.idev->dev.parent = &adev.pdev->dev;
+ adev.idev->open = lis3lv02d_joystick_open;
+ adev.idev->close = lis3lv02d_joystick_close;
+
+ set_bit(EV_ABS, adev.idev->evbit);
+ input_set_abs_params(adev.idev, ABS_X, -MDPS_MAX_VAL, MDPS_MAX_VAL, 3, 3);
+ input_set_abs_params(adev.idev, ABS_Y, -MDPS_MAX_VAL, MDPS_MAX_VAL, 3, 3);
+ input_set_abs_params(adev.idev, ABS_Z, -MDPS_MAX_VAL, MDPS_MAX_VAL, 3, 3);
+
+ err = input_register_device(adev.idev);
+ if (err) {
+ input_free_device(adev.idev);
+ adev.idev = NULL;
+ }
+
+ return err;
+}
+
+static void lis3lv02d_joystick_disable(void)
+{
+ if (!adev.idev)
+ return;
+
+ input_unregister_device(adev.idev);
+ adev.idev = NULL;
+}
+
+
+/*
+ * Initialise the accelerometer and the various subsystems.
+ * Should be rather independant of the bus system.
+ */
+static int lis3lv02d_init_device(struct acpi_lis3lv02d *dev)
+{
+ mutex_init(&dev->lock);
+ lis3lv02d_add_fs(dev->device);
+ lis3lv02d_increase_use(dev);
+
+ if (lis3lv02d_joystick_enable())
+ printk(KERN_ERR DRIVER_NAME ": joystick initialization failed\n");
+
+ lis3lv02d_decrease_use(dev);
+ return 0;
+}
+
+static int lis3lv02d_dmi_matched(const struct dmi_system_id *dmi)
+{
+ adev.ac = *((struct axis_conversion *)dmi->driver_data);
+ printk(KERN_INFO DRIVER_NAME ": hardware type %s found.\n", dmi->ident);
+
+ return 1;
+}
+
+/* Represents, for each axis seen by userspace, the corresponding hw axis (+1).
+ * If the value is negative, the opposite of the hw value is used. */
+static struct axis_conversion lis3lv02d_axis_normal = {1, 2, 3};
+static struct axis_conversion lis3lv02d_axis_y_inverted = {1, -2, 3};
+static struct axis_conversion lis3lv02d_axis_x_inverted = {-1, 2, 3};
+static struct axis_conversion lis3lv02d_axis_z_inverted = {1, 2, -3};
+static struct axis_conversion lis3lv02d_axis_xy_rotated_left = {-2, 1, 3};
+static struct axis_conversion lis3lv02d_axis_xy_swap_inverted = {-2, -1, 3};
+
+#define AXIS_DMI_MATCH(_ident, _name, _axis) { \
+ .ident = _ident, \
+ .callback = lis3lv02d_dmi_matched, \
+ .matches = { \
+ DMI_MATCH(DMI_PRODUCT_NAME, _name) \
+ }, \
+ .driver_data = &lis3lv02d_axis_##_axis \
+}
+static struct dmi_system_id lis3lv02d_dmi_ids[] = {
+ /* product names are truncated to match all kinds of a same model */
+ AXIS_DMI_MATCH("NC64x0", "HP Compaq nc64", x_inverted),
+ AXIS_DMI_MATCH("NC84x0", "HP Compaq nc84", z_inverted),
+ AXIS_DMI_MATCH("NX9420", "HP Compaq nx9420", x_inverted),
+ AXIS_DMI_MATCH("NW9440", "HP Compaq nw9440", x_inverted),
+ AXIS_DMI_MATCH("NC2510", "HP Compaq 2510", y_inverted),
+ AXIS_DMI_MATCH("NC8510", "HP Compaq 8510", xy_swap_inverted),
+ AXIS_DMI_MATCH("HP2133", "HP 2133", xy_rotated_left),
+ { NULL, }
+/* Laptop models without axis info (yet):
+ * "NC651xx" "HP Compaq 651"
+ * "NC671xx" "HP Compaq 671"
+ * "NC6910" "HP Compaq 6910"
+ * HP Compaq 8710x Notebook PC / Mobile Workstation
+ * "NC2400" "HP Compaq nc2400"
+ * "NX74x0" "HP Compaq nx74"
+ * "NX6325" "HP Compaq nx6325"
+ * "NC4400" "HP Compaq nc4400"
+ */
+};
+
+static int lis3lv02d_add(struct acpi_device *device)
+{
+ u8 val;
+
+ if (!device)
+ return -EINVAL;
+
+ adev.device = device;
+ strcpy(acpi_device_name(device), DRIVER_NAME);
+ strcpy(acpi_device_class(device), ACPI_MDPS_CLASS);
+ device->driver_data = &adev;
+
+ lis3lv02d_acpi_read(device->handle, WHO_AM_I, &val);
+ if ((val != LIS3LV02DL_ID) && (val != LIS302DL_ID)) {
+ printk(KERN_ERR DRIVER_NAME
+ ": Accelerometer chip not LIS3LV02D{L,Q}\n");
+ }
+
+ /* If possible use a "standard" axes order */
+ if (dmi_check_system(lis3lv02d_dmi_ids) == 0) {
+ printk(KERN_INFO DRIVER_NAME ": laptop model unknown, "
+ "using default axes configuration\n");
+ adev.ac = lis3lv02d_axis_normal;
+ }
+
+ return lis3lv02d_init_device(&adev);
+}
+
+static int lis3lv02d_remove(struct acpi_device *device, int type)
+{
+ if (!device)
+ return -EINVAL;
+
+ lis3lv02d_joystick_disable();
+ lis3lv02d_poweroff(device->handle);
+
+ return lis3lv02d_remove_fs();
+}
+
+
+/* Sysfs stuff */
+static ssize_t lis3lv02d_position_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int x, y, z;
+
+ lis3lv02d_increase_use(&adev);
+ lis3lv02d_get_xyz(adev.device->handle, &x, &y, &z);
+ lis3lv02d_decrease_use(&adev);
+ return sprintf(buf, "(%d,%d,%d)\n", x, y, z);
+}
+
+static ssize_t lis3lv02d_calibrate_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "(%d,%d,%d)\n", adev.xcalib, adev.ycalib, adev.zcalib);
+}
+
+static ssize_t lis3lv02d_calibrate_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ lis3lv02d_increase_use(&adev);
+ lis3lv02d_calibrate_joystick();
+ lis3lv02d_decrease_use(&adev);
+ return count;
+}
+
+/* conversion btw sampling rate and the register values */
+static int lis3lv02dl_df_val[4] = {40, 160, 640, 2560};
+static ssize_t lis3lv02d_rate_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ u8 ctrl;
+ int val;
+
+ lis3lv02d_increase_use(&adev);
+ lis3lv02d_acpi_read(adev.device->handle, CTRL_REG1, &ctrl);
+ lis3lv02d_decrease_use(&adev);
+ val = (ctrl & (CTRL1_DF0 | CTRL1_DF1)) >> 4;
+ return sprintf(buf, "%d\n", lis3lv02dl_df_val[val]);
+}
+
+static DEVICE_ATTR(position, S_IRUGO, lis3lv02d_position_show, NULL);
+static DEVICE_ATTR(calibrate, S_IRUGO|S_IWUSR, lis3lv02d_calibrate_show,
+ lis3lv02d_calibrate_store);
+static DEVICE_ATTR(rate, S_IRUGO, lis3lv02d_rate_show, NULL);
+
+static struct attribute *lis3lv02d_attributes[] = {
+ &dev_attr_position.attr,
+ &dev_attr_calibrate.attr,
+ &dev_attr_rate.attr,
+ NULL
+};
+
+static struct attribute_group lis3lv02d_attribute_group = {
+ .attrs = lis3lv02d_attributes
+};
+
+static int lis3lv02d_add_fs(struct acpi_device *device)
+{
+ adev.pdev = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0);
+ if (IS_ERR(adev.pdev))
+ return PTR_ERR(adev.pdev);
+
+ return sysfs_create_group(&adev.pdev->dev.kobj, &lis3lv02d_attribute_group);
+}
+
+static int lis3lv02d_remove_fs(void)
+{
+ sysfs_remove_group(&adev.pdev->dev.kobj, &lis3lv02d_attribute_group);
+ platform_device_unregister(adev.pdev);
+ return 0;
+}
+
+/* For the HP MDPS aka 3D Driveguard */
+static struct acpi_driver lis3lv02d_driver = {
+ .name = DRIVER_NAME,
+ .class = ACPI_MDPS_CLASS,
+ .ids = lis3lv02d_device_ids,
+ .ops = {
+ .add = lis3lv02d_add,
+ .remove = lis3lv02d_remove,
+ .suspend = lis3lv02d_suspend,
+ .resume = lis3lv02d_resume,
+ }
+};
+
+static int __init lis3lv02d_init_module(void)
+{
+ int ret;
+
+ if (acpi_disabled)
+ return -ENODEV;
+
+ ret = acpi_bus_register_driver(&lis3lv02d_driver);
+ if (ret < 0)
+ return ret;
+
+ printk(KERN_INFO DRIVER_NAME " driver loaded.\n");
+
+ return 0;
+}
+
+static void __exit lis3lv02d_exit_module(void)
+{
+ acpi_bus_unregister_driver(&lis3lv02d_driver);
+}
+
+MODULE_DESCRIPTION("ST LIS3LV02Dx three-axis digital accelerometer driver");
+MODULE_AUTHOR("Yan Burman and Eric Piel");
+MODULE_LICENSE("GPL");
+
+module_init(lis3lv02d_init_module);
+module_exit(lis3lv02d_exit_module);
diff --git a/drivers/hwmon/lis3lv02d.h b/drivers/hwmon/lis3lv02d.h
new file mode 100644
index 00000000000..330cfc60e94
--- /dev/null
+++ b/drivers/hwmon/lis3lv02d.h
@@ -0,0 +1,149 @@
+/*
+ * lis3lv02d.h - ST LIS3LV02DL accelerometer driver
+ *
+ * Copyright (C) 2007-2008 Yan Burman
+ * Copyright (C) 2008 Eric Piel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ * The actual chip is STMicroelectronics LIS3LV02DL or LIS3LV02DQ that seems to
+ * be connected via SPI. There exists also several similar chips (such as LIS302DL or
+ * LIS3L02DQ) but not in the HP laptops and they have slightly different registers.
+ * They can also be connected via I²C.
+ */
+
+#define LIS3LV02DL_ID 0x3A /* Also the LIS3LV02DQ */
+#define LIS302DL_ID 0x3B /* Also the LIS202DL! */
+
+enum lis3lv02d_reg {
+ WHO_AM_I = 0x0F,
+ OFFSET_X = 0x16,
+ OFFSET_Y = 0x17,
+ OFFSET_Z = 0x18,
+ GAIN_X = 0x19,
+ GAIN_Y = 0x1A,
+ GAIN_Z = 0x1B,
+ CTRL_REG1 = 0x20,
+ CTRL_REG2 = 0x21,
+ CTRL_REG3 = 0x22,
+ HP_FILTER_RESET = 0x23,
+ STATUS_REG = 0x27,
+ OUTX_L = 0x28,
+ OUTX_H = 0x29,
+ OUTY_L = 0x2A,
+ OUTY_H = 0x2B,
+ OUTZ_L = 0x2C,
+ OUTZ_H = 0x2D,
+ FF_WU_CFG = 0x30,
+ FF_WU_SRC = 0x31,
+ FF_WU_ACK = 0x32,
+ FF_WU_THS_L = 0x34,
+ FF_WU_THS_H = 0x35,
+ FF_WU_DURATION = 0x36,
+ DD_CFG = 0x38,
+ DD_SRC = 0x39,
+ DD_ACK = 0x3A,
+ DD_THSI_L = 0x3C,
+ DD_THSI_H = 0x3D,
+ DD_THSE_L = 0x3E,
+ DD_THSE_H = 0x3F,
+};
+
+enum lis3lv02d_ctrl1 {
+ CTRL1_Xen = 0x01,
+ CTRL1_Yen = 0x02,
+ CTRL1_Zen = 0x04,
+ CTRL1_ST = 0x08,
+ CTRL1_DF0 = 0x10,
+ CTRL1_DF1 = 0x20,
+ CTRL1_PD0 = 0x40,
+ CTRL1_PD1 = 0x80,
+};
+enum lis3lv02d_ctrl2 {
+ CTRL2_DAS = 0x01,
+ CTRL2_SIM = 0x02,
+ CTRL2_DRDY = 0x04,
+ CTRL2_IEN = 0x08,
+ CTRL2_BOOT = 0x10,
+ CTRL2_BLE = 0x20,
+ CTRL2_BDU = 0x40, /* Block Data Update */
+ CTRL2_FS = 0x80, /* Full Scale selection */
+};
+
+
+enum lis3lv02d_ctrl3 {
+ CTRL3_CFS0 = 0x01,
+ CTRL3_CFS1 = 0x02,
+ CTRL3_FDS = 0x10,
+ CTRL3_HPFF = 0x20,
+ CTRL3_HPDD = 0x40,
+ CTRL3_ECK = 0x80,
+};
+
+enum lis3lv02d_status_reg {
+ STATUS_XDA = 0x01,
+ STATUS_YDA = 0x02,
+ STATUS_ZDA = 0x04,
+ STATUS_XYZDA = 0x08,
+ STATUS_XOR = 0x10,
+ STATUS_YOR = 0x20,
+ STATUS_ZOR = 0x40,
+ STATUS_XYZOR = 0x80,
+};
+
+enum lis3lv02d_ff_wu_cfg {
+ FF_WU_CFG_XLIE = 0x01,
+ FF_WU_CFG_XHIE = 0x02,
+ FF_WU_CFG_YLIE = 0x04,
+ FF_WU_CFG_YHIE = 0x08,
+ FF_WU_CFG_ZLIE = 0x10,
+ FF_WU_CFG_ZHIE = 0x20,
+ FF_WU_CFG_LIR = 0x40,
+ FF_WU_CFG_AOI = 0x80,
+};
+
+enum lis3lv02d_ff_wu_src {
+ FF_WU_SRC_XL = 0x01,
+ FF_WU_SRC_XH = 0x02,
+ FF_WU_SRC_YL = 0x04,
+ FF_WU_SRC_YH = 0x08,
+ FF_WU_SRC_ZL = 0x10,
+ FF_WU_SRC_ZH = 0x20,
+ FF_WU_SRC_IA = 0x40,
+};
+
+enum lis3lv02d_dd_cfg {
+ DD_CFG_XLIE = 0x01,
+ DD_CFG_XHIE = 0x02,
+ DD_CFG_YLIE = 0x04,
+ DD_CFG_YHIE = 0x08,
+ DD_CFG_ZLIE = 0x10,
+ DD_CFG_ZHIE = 0x20,
+ DD_CFG_LIR = 0x40,
+ DD_CFG_IEND = 0x80,
+};
+
+enum lis3lv02d_dd_src {
+ DD_SRC_XL = 0x01,
+ DD_SRC_XH = 0x02,
+ DD_SRC_YL = 0x04,
+ DD_SRC_YH = 0x08,
+ DD_SRC_ZL = 0x10,
+ DD_SRC_ZH = 0x20,
+ DD_SRC_IA = 0x40,
+};
+
diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c
index 3ff0285396f..cfc1ee90f5a 100644
--- a/drivers/hwmon/lm85.c
+++ b/drivers/hwmon/lm85.c
@@ -39,7 +39,8 @@
static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
/* Insmod parameters */
-I2C_CLIENT_INSMOD_6(lm85b, lm85c, adm1027, adt7463, emc6d100, emc6d102);
+I2C_CLIENT_INSMOD_7(lm85b, lm85c, adm1027, adt7463, adt7468, emc6d100,
+ emc6d102);
/* The LM85 registers */
@@ -59,6 +60,12 @@ I2C_CLIENT_INSMOD_6(lm85b, lm85c, adm1027, adt7463, emc6d100, emc6d102);
#define LM85_REG_COMPANY 0x3e
#define LM85_REG_VERSTEP 0x3f
+
+#define ADT7468_REG_CFG5 0x7c
+#define ADT7468_OFF64 0x01
+#define IS_ADT7468_OFF64(data) \
+ ((data)->type == adt7468 && !((data)->cfg5 & ADT7468_OFF64))
+
/* These are the recognized values for the above regs */
#define LM85_COMPANY_NATIONAL 0x01
#define LM85_COMPANY_ANALOG_DEV 0x41
@@ -70,6 +77,8 @@ I2C_CLIENT_INSMOD_6(lm85b, lm85c, adm1027, adt7463, emc6d100, emc6d102);
#define LM85_VERSTEP_ADM1027 0x60
#define LM85_VERSTEP_ADT7463 0x62
#define LM85_VERSTEP_ADT7463C 0x6A
+#define LM85_VERSTEP_ADT7468_1 0x71
+#define LM85_VERSTEP_ADT7468_2 0x72
#define LM85_VERSTEP_EMC6D100_A0 0x60
#define LM85_VERSTEP_EMC6D100_A1 0x61
#define LM85_VERSTEP_EMC6D102 0x65
@@ -306,6 +315,7 @@ struct lm85_data {
u8 vid; /* Register value */
u8 vrm; /* VRM version */
u32 alarms; /* Register encoding, combined */
+ u8 cfg5; /* Config Register 5 on ADT7468 */
struct lm85_autofan autofan[3];
struct lm85_zone zone[3];
};
@@ -685,6 +695,9 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
struct lm85_data *data = i2c_get_clientdata(client);
long val = simple_strtol(buf, NULL, 10);
+ if (IS_ADT7468_OFF64(data))
+ val += 64;
+
mutex_lock(&data->update_lock);
data->temp_min[nr] = TEMP_TO_REG(val);
lm85_write_value(client, LM85_REG_TEMP_MIN(nr), data->temp_min[nr]);
@@ -708,6 +721,9 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
struct lm85_data *data = i2c_get_clientdata(client);
long val = simple_strtol(buf, NULL, 10);
+ if (IS_ADT7468_OFF64(data))
+ val += 64;
+
mutex_lock(&data->update_lock);
data->temp_max[nr] = TEMP_TO_REG(val);
lm85_write_value(client, LM85_REG_TEMP_MAX(nr), data->temp_max[nr]);
@@ -1163,6 +1179,10 @@ static int lm85_detect(struct i2c_client *client, int kind,
case LM85_VERSTEP_ADT7463C:
kind = adt7463;
break;
+ case LM85_VERSTEP_ADT7468_1:
+ case LM85_VERSTEP_ADT7468_2:
+ kind = adt7468;
+ break;
}
} else if (company == LM85_COMPANY_SMSC) {
switch (verstep) {
@@ -1195,6 +1215,9 @@ static int lm85_detect(struct i2c_client *client, int kind,
case adt7463:
type_name = "adt7463";
break;
+ case adt7468:
+ type_name = "adt7468";
+ break;
case emc6d100:
type_name = "emc6d100";
break;
@@ -1246,10 +1269,11 @@ static int lm85_probe(struct i2c_client *client,
if (err)
goto err_kfree;
- /* The ADT7463 has an optional VRM 10 mode where pin 21 is used
+ /* The ADT7463/68 have an optional VRM 10 mode where pin 21 is used
as a sixth digital VID input rather than an analog input. */
data->vid = lm85_read_value(client, LM85_REG_VID);
- if (!(data->type == adt7463 && (data->vid & 0x80)))
+ if (!((data->type == adt7463 || data->type == adt7468) &&
+ (data->vid & 0x80)))
if ((err = sysfs_create_group(&client->dev.kobj,
&lm85_group_in4)))
goto err_remove_files;
@@ -1357,7 +1381,8 @@ static struct lm85_data *lm85_update_device(struct device *dev)
* There are 2 additional resolution bits per channel and we
* have room for 4, so we shift them to the left.
*/
- if (data->type == adm1027 || data->type == adt7463) {
+ if (data->type == adm1027 || data->type == adt7463 ||
+ data->type == adt7468) {
int ext1 = lm85_read_value(client,
ADM1027_REG_EXTEND_ADC1);
int ext2 = lm85_read_value(client,
@@ -1382,16 +1407,23 @@ static struct lm85_data *lm85_update_device(struct device *dev)
lm85_read_value(client, LM85_REG_FAN(i));
}
- if (!(data->type == adt7463 && (data->vid & 0x80))) {
+ if (!((data->type == adt7463 || data->type == adt7468) &&
+ (data->vid & 0x80))) {
data->in[4] = lm85_read_value(client,
LM85_REG_IN(4));
}
+ if (data->type == adt7468)
+ data->cfg5 = lm85_read_value(client, ADT7468_REG_CFG5);
+
for (i = 0; i <= 2; ++i) {
data->temp[i] =
lm85_read_value(client, LM85_REG_TEMP(i));
data->pwm[i] =
lm85_read_value(client, LM85_REG_PWM(i));
+
+ if (IS_ADT7468_OFF64(data))
+ data->temp[i] -= 64;
}
data->alarms = lm85_read_value(client, LM85_REG_ALARM1);
@@ -1446,7 +1478,8 @@ static struct lm85_data *lm85_update_device(struct device *dev)
lm85_read_value(client, LM85_REG_FAN_MIN(i));
}
- if (!(data->type == adt7463 && (data->vid & 0x80))) {
+ if (!((data->type == adt7463 || data->type == adt7468) &&
+ (data->vid & 0x80))) {
data->in_min[4] = lm85_read_value(client,
LM85_REG_IN_MIN(4));
data->in_max[4] = lm85_read_value(client,
@@ -1481,6 +1514,13 @@ static struct lm85_data *lm85_update_device(struct device *dev)
lm85_read_value(client, LM85_REG_AFAN_LIMIT(i));
data->zone[i].critical =
lm85_read_value(client, LM85_REG_AFAN_CRITICAL(i));
+
+ if (IS_ADT7468_OFF64(data)) {
+ data->temp_min[i] -= 64;
+ data->temp_max[i] -= 64;
+ data->zone[i].limit -= 64;
+ data->zone[i].critical -= 64;
+ }
}
i = lm85_read_value(client, LM85_REG_AFAN_SPIKE1);
diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c
index 228f7572306..3fcf78e906d 100644
--- a/drivers/i2c/busses/i2c-cpm.c
+++ b/drivers/i2c/busses/i2c-cpm.c
@@ -365,6 +365,7 @@ static int cpm_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
pmsg = &msgs[tptr];
if (pmsg->flags & I2C_M_RD)
ret = wait_event_interruptible_timeout(cpm->i2c_wait,
+ (in_be16(&tbdf[tptr].cbd_sc) & BD_SC_NAK) ||
!(in_be16(&rbdf[rptr].cbd_sc) & BD_SC_EMPTY),
1 * HZ);
else
diff --git a/drivers/i2c/busses/i2c-highlander.c b/drivers/i2c/busses/i2c-highlander.c
index f4d22ae9d29..e5a8dae4a28 100644
--- a/drivers/i2c/busses/i2c-highlander.c
+++ b/drivers/i2c/busses/i2c-highlander.c
@@ -92,7 +92,7 @@ static void highlander_i2c_setup(struct highlander_i2c_dev *dev)
static void smbus_write_data(u8 *src, u16 *dst, int len)
{
for (; len > 1; len -= 2) {
- *dst++ = be16_to_cpup((u16 *)src);
+ *dst++ = be16_to_cpup((__be16 *)src);
src += 2;
}
@@ -103,7 +103,7 @@ static void smbus_write_data(u8 *src, u16 *dst, int len)
static void smbus_read_data(u16 *src, u8 *dst, int len)
{
for (; len > 1; len -= 2) {
- *(u16 *)dst = cpu_to_be16p(src++);
+ *(__be16 *)dst = cpu_to_be16p(src++);
dst += 2;
}
diff --git a/drivers/i2c/busses/i2c-parport.c b/drivers/i2c/busses/i2c-parport.c
index 59ba2086d2f..a257cd5cd13 100644
--- a/drivers/i2c/busses/i2c-parport.c
+++ b/drivers/i2c/busses/i2c-parport.c
@@ -189,8 +189,6 @@ static void i2c_parport_attach (struct parport *port)
if (adapter_parm[type].init.val)
line_set(port, 1, &adapter_parm[type].init);
- parport_release(adapter->pdev);
-
if (i2c_bit_add_bus(&adapter->adapter) < 0) {
printk(KERN_ERR "i2c-parport: Unable to register with I2C\n");
goto ERROR1;
@@ -202,6 +200,7 @@ static void i2c_parport_attach (struct parport *port)
return;
ERROR1:
+ parport_release(adapter->pdev);
parport_unregister_device(adapter->pdev);
ERROR0:
kfree(adapter);
@@ -221,6 +220,7 @@ static void i2c_parport_detach (struct parport *port)
if (adapter_parm[type].init.val)
line_set(port, 0, &adapter_parm[type].init);
+ parport_release(adapter->pdev);
parport_unregister_device(adapter->pdev);
if (prev)
prev->next = adapter->next;
diff --git a/drivers/i2c/busses/i2c-pmcmsp.c b/drivers/i2c/busses/i2c-pmcmsp.c
index dcf2045b522..0bdb2d7f057 100644
--- a/drivers/i2c/busses/i2c-pmcmsp.c
+++ b/drivers/i2c/busses/i2c-pmcmsp.c
@@ -486,7 +486,7 @@ static enum pmcmsptwi_xfer_result pmcmsptwi_xfer_cmd(
if (cmd->type == MSP_TWI_CMD_WRITE ||
cmd->type == MSP_TWI_CMD_WRITE_READ) {
- __be64 tmp = cpu_to_be64p((u64 *)cmd->write_data);
+ u64 tmp = be64_to_cpup((__be64 *)cmd->write_data);
tmp >>= (MSP_MAX_BYTES_PER_RW - cmd->write_len) * 8;
dev_dbg(&pmcmsptwi_adapter.dev, "Writing 0x%016llx\n", tmp);
pmcmsptwi_writel(tmp & 0x00000000ffffffffLL,
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index 1fac4e23313..b7434d24904 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -56,6 +56,7 @@ enum s3c24xx_i2c_state {
struct s3c24xx_i2c {
spinlock_t lock;
wait_queue_head_t wait;
+ unsigned int suspended:1;
struct i2c_msg *msg;
unsigned int msg_num;
@@ -507,7 +508,7 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, struct i2c_msg *msgs, int
unsigned long timeout;
int ret;
- if (!(readl(i2c->regs + S3C2410_IICCON) & S3C2410_IICCON_IRQEN))
+ if (i2c->suspended)
return -EIO;
ret = s3c24xx_i2c_set_master(i2c);
@@ -986,17 +987,26 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev)
}
#ifdef CONFIG_PM
+static int s3c24xx_i2c_suspend_late(struct platform_device *dev,
+ pm_message_t msg)
+{
+ struct s3c24xx_i2c *i2c = platform_get_drvdata(dev);
+ i2c->suspended = 1;
+ return 0;
+}
+
static int s3c24xx_i2c_resume(struct platform_device *dev)
{
struct s3c24xx_i2c *i2c = platform_get_drvdata(dev);
- if (i2c != NULL)
- s3c24xx_i2c_init(i2c);
+ i2c->suspended = 0;
+ s3c24xx_i2c_init(i2c);
return 0;
}
#else
+#define s3c24xx_i2c_suspend_late NULL
#define s3c24xx_i2c_resume NULL
#endif
@@ -1005,6 +1015,7 @@ static int s3c24xx_i2c_resume(struct platform_device *dev)
static struct platform_driver s3c2410_i2c_driver = {
.probe = s3c24xx_i2c_probe,
.remove = s3c24xx_i2c_remove,
+ .suspend_late = s3c24xx_i2c_suspend_late,
.resume = s3c24xx_i2c_resume,
.driver = {
.owner = THIS_MODULE,
@@ -1015,6 +1026,7 @@ static struct platform_driver s3c2410_i2c_driver = {
static struct platform_driver s3c2440_i2c_driver = {
.probe = s3c24xx_i2c_probe,
.remove = s3c24xx_i2c_remove,
+ .suspend_late = s3c24xx_i2c_suspend_late,
.resume = s3c24xx_i2c_resume,
.driver = {
.owner = THIS_MODULE,
diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c
index 640cbb23732..3384a717fec 100644
--- a/drivers/i2c/busses/i2c-sh_mobile.c
+++ b/drivers/i2c/busses/i2c-sh_mobile.c
@@ -318,7 +318,8 @@ static int sh_mobile_i2c_isr_rx(struct sh_mobile_i2c_data *pd)
} else
data = i2c_op(pd, OP_RX, 0);
- pd->msg->buf[real_pos] = data;
+ if (real_pos >= 0)
+ pd->msg->buf[real_pos] = data;
} while (0);
pd->pos++;
diff --git a/drivers/i2c/chips/isp1301_omap.c b/drivers/i2c/chips/isp1301_omap.c
index 28902ebd553..e0d56ef2bcb 100644
--- a/drivers/i2c/chips/isp1301_omap.c
+++ b/drivers/i2c/chips/isp1301_omap.c
@@ -25,6 +25,7 @@
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
+#include <linux/gpio.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/usb.h>
@@ -33,7 +34,10 @@
#include <linux/workqueue.h>
#include <asm/irq.h>
+#include <asm/mach-types.h>
+
#include <mach/usb.h>
+#include <mach/mux.h>
#ifndef DEBUG
@@ -88,14 +92,9 @@ struct isp1301 {
/*-------------------------------------------------------------------------*/
-#ifdef CONFIG_MACH_OMAP_H2
-
/* board-specific PM hooks */
-#include <asm/gpio.h>
-#include <mach/mux.h>
-#include <asm/mach-types.h>
-
+#if defined(CONFIG_MACH_OMAP_H2) || defined(CONFIG_MACH_OMAP_H3)
#if defined(CONFIG_TPS65010) || defined(CONFIG_TPS65010_MODULE)
@@ -135,6 +134,33 @@ static inline void notresponding(struct isp1301 *isp)
#endif
+#if defined(CONFIG_MACH_OMAP_H4)
+
+static void enable_vbus_draw(struct isp1301 *isp, unsigned mA)
+{
+ /* H4 controls this by DIP switch S2.4; no soft control.
+ * ON means the charger is always enabled. Leave it OFF
+ * unless the OTG port is used only in B-peripheral mode.
+ */
+}
+
+static void enable_vbus_source(struct isp1301 *isp)
+{
+ /* this board won't supply more than 8mA vbus power.
+ * some boards can switch a 100ma "unit load" (or more).
+ */
+}
+
+
+/* products will deliver OTG messages with LEDs, GUI, etc */
+static inline void notresponding(struct isp1301 *isp)
+{
+ printk(KERN_NOTICE "OTG device not responding.\n");
+}
+
+
+#endif
+
/*-------------------------------------------------------------------------*/
static struct i2c_driver isp1301_driver;
@@ -334,8 +360,7 @@ static int gadget_suspend(struct isp1301 *isp)
* NOTE: guaranteeing certain response times might mean we shouldn't
* share keventd's work queue; a realtime task might be safest.
*/
-void
-isp1301_defer_work(struct isp1301 *isp, int work)
+static void isp1301_defer_work(struct isp1301 *isp, int work)
{
int status;
@@ -512,7 +537,6 @@ static void update_otg1(struct isp1301 *isp, u8 int_src)
otg_ctrl &= ~OTG_XCEIV_INPUTS;
otg_ctrl &= ~(OTG_ID|OTG_ASESSVLD|OTG_VBUSVLD);
-
if (int_src & INTR_SESS_VLD)
otg_ctrl |= OTG_ASESSVLD;
else if (isp->otg.state == OTG_STATE_A_WAIT_VFALL) {
@@ -886,11 +910,11 @@ static int otg_probe(struct platform_device *dev)
static int otg_remove(struct platform_device *dev)
{
- otg_dev = 0;
+ otg_dev = NULL;
return 0;
}
-struct platform_driver omap_otg_driver = {
+static struct platform_driver omap_otg_driver = {
.probe = otg_probe,
.remove = otg_remove,
.driver = {
@@ -1212,6 +1236,8 @@ static void isp1301_release(struct device *dev)
isp = dev_get_drvdata(dev);
+ /* FIXME -- not with a "new style" driver, it doesn't!! */
+
/* ugly -- i2c hijacks our memory hook to wait_for_completion() */
if (isp->i2c_release)
isp->i2c_release(dev);
@@ -1233,7 +1259,7 @@ static int __exit isp1301_remove(struct i2c_client *i2c)
otg_unbind(isp);
#endif
if (machine_is_omap_h2())
- omap_free_gpio(2);
+ gpio_free(2);
isp->timer.data = 0;
set_bit(WORK_STOP, &isp->todo);
@@ -1241,7 +1267,7 @@ static int __exit isp1301_remove(struct i2c_client *i2c)
flush_scheduled_work();
put_device(&i2c->dev);
- the_transceiver = 0;
+ the_transceiver = NULL;
return 0;
}
@@ -1295,7 +1321,7 @@ isp1301_set_host(struct otg_transceiver *otg, struct usb_bus *host)
if (!host) {
omap_writew(0, OTG_IRQ_EN);
power_down(isp);
- isp->otg.host = 0;
+ isp->otg.host = NULL;
return 0;
}
@@ -1344,7 +1370,9 @@ static int
isp1301_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *gadget)
{
struct isp1301 *isp = container_of(otg, struct isp1301, otg);
+#ifndef CONFIG_USB_OTG
u32 l;
+#endif
if (!otg || isp != the_transceiver)
return -ENODEV;
@@ -1354,7 +1382,7 @@ isp1301_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *gadget)
if (!isp->otg.default_a)
enable_vbus_draw(isp, 0);
usb_gadget_vbus_disconnect(isp->otg.gadget);
- isp->otg.gadget = 0;
+ isp->otg.gadget = NULL;
power_down(isp);
return 0;
}
@@ -1379,7 +1407,7 @@ isp1301_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *gadget)
power_up(isp);
isp->otg.state = OTG_STATE_B_IDLE;
- if (machine_is_omap_h2())
+ if (machine_is_omap_h2() || machine_is_omap_h3())
isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_DAT_SE0);
isp1301_set_bits(isp, ISP1301_INTERRUPT_RISING,
@@ -1499,7 +1527,8 @@ isp1301_start_hnp(struct otg_transceiver *dev)
/*-------------------------------------------------------------------------*/
-static int __init isp1301_probe(struct i2c_client *i2c)
+static int __init
+isp1301_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
{
int status;
struct isp1301 *isp;
@@ -1647,7 +1676,7 @@ module_init(isp_init);
static void __exit isp_exit(void)
{
if (the_transceiver)
- otg_set_transceiver(0);
+ otg_set_transceiver(NULL);
i2c_del_driver(&isp1301_driver);
}
module_exit(isp_exit);
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 5a485c22660..c6a63f46bc1 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -631,7 +631,7 @@ int i2c_del_adapter(struct i2c_adapter *adap)
/* detach any active clients. This must be done first, because
* it can fail; in which case we give up. */
- list_for_each_entry_safe(client, _n, &adap->clients, list) {
+ list_for_each_entry_safe_reverse(client, _n, &adap->clients, list) {
struct i2c_driver *driver;
driver = client->driver;
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index 6d7401772a8..e6857e01d1b 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -669,10 +669,12 @@ config BLK_DEV_CELLEB
endif
+# TODO: BLK_DEV_IDEDMA_PCI -> BLK_DEV_IDEDMA_SFF
config BLK_DEV_IDE_PMAC
tristate "PowerMac on-board IDE support"
depends on PPC_PMAC && IDE=y
select IDE_TIMINGS
+ select BLK_DEV_IDEDMA_PCI
help
This driver provides support for the on-board IDE controller on
most of the recent Apple Power Macintoshes and PowerBooks.
@@ -689,16 +691,6 @@ config BLK_DEV_IDE_PMAC_ATA100FIRST
CD-ROM on hda. This option changes this to more natural hda for
hard disk and hdc for CD-ROM.
-config BLK_DEV_IDEDMA_PMAC
- bool "PowerMac IDE DMA support"
- depends on BLK_DEV_IDE_PMAC
- select BLK_DEV_IDEDMA_PCI
- help
- This option allows the driver for the on-board IDE controller on
- Power Macintoshes and PowerBooks to use DMA (direct memory access)
- to transfer data to and from memory. Saying Y is safe and improves
- performance.
-
config BLK_DEV_IDE_AU1XXX
bool "IDE for AMD Alchemy Au1200"
depends on SOC_AU1200
@@ -912,7 +904,7 @@ config BLK_DEV_UMC8672
endif
config BLK_DEV_IDEDMA
- def_bool BLK_DEV_IDEDMA_SFF || BLK_DEV_IDEDMA_PMAC || \
+ def_bool BLK_DEV_IDEDMA_SFF || \
BLK_DEV_IDEDMA_ICS || BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
endif # IDE
diff --git a/drivers/ide/alim15x3.c b/drivers/ide/alim15x3.c
index e56c7b72f9e..45d2356bb72 100644
--- a/drivers/ide/alim15x3.c
+++ b/drivers/ide/alim15x3.c
@@ -591,7 +591,7 @@ static int __init ali15x3_ide_init(void)
static void __exit ali15x3_ide_exit(void)
{
- return pci_unregister_driver(&alim15x3_pci_driver);
+ pci_unregister_driver(&alim15x3_pci_driver);
}
module_init(ali15x3_ide_init);
diff --git a/drivers/ide/amd74xx.c b/drivers/ide/amd74xx.c
index 81ec73134ed..c6bcd3014a2 100644
--- a/drivers/ide/amd74xx.c
+++ b/drivers/ide/amd74xx.c
@@ -3,7 +3,7 @@
* IDE driver for Linux.
*
* Copyright (c) 2000-2002 Vojtech Pavlik
- * Copyright (c) 2007 Bartlomiej Zolnierkiewicz
+ * Copyright (c) 2007-2008 Bartlomiej Zolnierkiewicz
*
* Based on the work of:
* Andre Hedrick
@@ -263,6 +263,15 @@ static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_
d.udma_mask = ATA_UDMA5;
}
+ /*
+ * It seems that on some nVidia controllers using AltStatus
+ * register can be unreliable so default to Status register
+ * if the device is in Compatibility Mode.
+ */
+ if (dev->vendor == PCI_VENDOR_ID_NVIDIA &&
+ ide_pci_is_in_compatibility_mode(dev))
+ d.host_flags |= IDE_HFLAG_BROKEN_ALTSTATUS;
+
printk(KERN_INFO "%s %s: UDMA%s controller\n",
d.name, pci_name(dev), amd_dma[fls(d.udma_mask) - 1]);
diff --git a/drivers/ide/cs5530.c b/drivers/ide/cs5530.c
index 53f079cc00a..d8ede85fe17 100644
--- a/drivers/ide/cs5530.c
+++ b/drivers/ide/cs5530.c
@@ -81,11 +81,12 @@ static u8 cs5530_udma_filter(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
ide_drive_t *mate = ide_get_pair_dev(drive);
- u16 *mateid = mate->id;
+ u16 *mateid;
u8 mask = hwif->ultra_mask;
if (mate == NULL)
goto out;
+ mateid = mate->id;
if (ata_id_has_dma(mateid) && __ide_dma_bad_drive(mate) == 0) {
if ((mateid[ATA_ID_FIELD_VALID] & 4) &&
diff --git a/drivers/ide/icside.c b/drivers/ide/icside.c
index 2d848010499..81f70caeb40 100644
--- a/drivers/ide/icside.c
+++ b/drivers/ide/icside.c
@@ -419,7 +419,7 @@ static void icside_setup_ports(hw_regs_t *hw, void __iomem *base,
hw->chipset = ide_acorn;
}
-static int __init
+static int __devinit
icside_register_v5(struct icside_state *state, struct expansion_card *ec)
{
void __iomem *base;
@@ -473,7 +473,7 @@ static const struct ide_port_info icside_v6_port_info __initdata = {
.swdma_mask = ATA_SWDMA2,
};
-static int __init
+static int __devinit
icside_register_v6(struct icside_state *state, struct expansion_card *ec)
{
void __iomem *ioc_base, *easi_base;
diff --git a/drivers/ide/ide-cs.c b/drivers/ide/ide-cs.c
index cb199c815b5..f50210fe558 100644
--- a/drivers/ide/ide-cs.c
+++ b/drivers/ide/ide-cs.c
@@ -444,6 +444,7 @@ static struct pcmcia_device_id ide_ids[] = {
PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209),
PCMCIA_DEVICE_PROD_ID12("STI", "Flash 5.0", 0xbf2df18d, 0x8cb57a0e),
PCMCIA_MFC_DEVICE_PROD_ID12(1, "SanDisk", "ConnectPlus", 0x7a954bd9, 0x74be00c6),
+ PCMCIA_DEVICE_PROD_ID2("Flash Card", 0x5a362506),
PCMCIA_DEVICE_NULL,
};
MODULE_DEVICE_TABLE(pcmcia, ide_ids);
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index 7162d67562a..cc35d6dbd41 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -132,10 +132,14 @@ int ide_end_request (ide_drive_t *drive, int uptodate, int nr_sectors)
}
EXPORT_SYMBOL(ide_end_request);
-static void ide_complete_power_step(ide_drive_t *drive, struct request *rq, u8 stat, u8 error)
+static void ide_complete_power_step(ide_drive_t *drive, struct request *rq)
{
struct request_pm_state *pm = rq->data;
+#ifdef DEBUG_PM
+ printk(KERN_INFO "%s: complete_power_step(step: %d)\n",
+ drive->name, pm->pm_step);
+#endif
if (drive->media != ide_disk)
return;
@@ -172,7 +176,7 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
/* Not supported? Switch to next step now. */
if (ata_id_flush_enabled(drive->id) == 0 ||
(drive->dev_flags & IDE_DFLAG_WCACHE) == 0) {
- ide_complete_power_step(drive, rq, 0, 0);
+ ide_complete_power_step(drive, rq);
return ide_stopped;
}
if (ata_id_flush_ext_enabled(drive->id))
@@ -191,7 +195,7 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
if (drive->media != ide_disk)
pm->pm_step = IDE_PM_RESTORE_DMA;
else
- ide_complete_power_step(drive, rq, 0, 0);
+ ide_complete_power_step(drive, rq);
return ide_stopped;
case IDE_PM_IDLE: /* Resume step 2 (idle) */
args->tf.command = ATA_CMD_IDLEIMMEDIATE;
@@ -322,11 +326,8 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
}
} else if (blk_pm_request(rq)) {
struct request_pm_state *pm = rq->data;
-#ifdef DEBUG_PM
- printk("%s: complete_power_step(step: %d, stat: %x, err: %x)\n",
- drive->name, rq->pm->pm_step, stat, err);
-#endif
- ide_complete_power_step(drive, rq, stat, err);
+
+ ide_complete_power_step(drive, rq);
if (pm->pm_step == IDE_PM_COMPLETED)
ide_complete_pm_request(drive, rq);
return;
@@ -804,7 +805,7 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
struct request_pm_state *pm = rq->data;
#ifdef DEBUG_PM
printk("%s: start_power_step(step: %d)\n",
- drive->name, rq->pm->pm_step);
+ drive->name, pm->pm_step);
#endif
startstop = ide_start_power_step(drive, rq);
if (startstop == ide_stopped &&
@@ -967,14 +968,13 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
ide_startstop_t startstop;
int loops = 0;
- /* for atari only: POSSIBLY BROKEN HERE(?) */
- ide_get_lock(ide_intr, hwgroup);
-
/* caller must own ide_lock */
BUG_ON(!irqs_disabled());
while (!hwgroup->busy) {
hwgroup->busy = 1;
+ /* for atari only */
+ ide_get_lock(ide_intr, hwgroup);
drive = choose_drive(hwgroup);
if (drive == NULL) {
int sleeping = 0;
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
index 5d6ba14e211..c41c3b9b6f0 100644
--- a/drivers/ide/ide-iops.c
+++ b/drivers/ide/ide-iops.c
@@ -457,18 +457,14 @@ int drive_is_ready (ide_drive_t *drive)
if (drive->waiting_for_dma)
return hwif->dma_ops->dma_test_irq(drive);
-#if 0
- /* need to guarantee 400ns since last command was issued */
- udelay(1);
-#endif
-
/*
* We do a passive status test under shared PCI interrupts on
* cards that truly share the ATA side interrupt, but may also share
* an interrupt with another pci card/device. We make no assumptions
* about possible isa-pnp and pci-pnp issues yet.
*/
- if (hwif->io_ports.ctl_addr)
+ if (hwif->io_ports.ctl_addr &&
+ (hwif->host_flags & IDE_HFLAG_BROKEN_ALTSTATUS) == 0)
stat = hwif->tp_ops->read_altstatus(hwif);
else
/* Note: this may clear a pending IRQ!! */
@@ -610,6 +606,7 @@ static const struct drive_list_entry ivb_list[] = {
{ "TSSTcorp CDDVDW SH-S202N" , "SB01" },
{ "TSSTcorp CDDVDW SH-S202H" , "SB00" },
{ "TSSTcorp CDDVDW SH-S202H" , "SB01" },
+ { "SAMSUNG SP0822N" , "WA100-10" },
{ NULL , NULL }
};
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 1649ea54f76..c55bdbd2231 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -266,7 +266,8 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
/* take a deep breath */
msleep(50);
- if (io_ports->ctl_addr) {
+ if (io_ports->ctl_addr &&
+ (hwif->host_flags & IDE_HFLAG_BROKEN_ALTSTATUS) == 0) {
a = tp_ops->read_altstatus(hwif);
s = tp_ops->read_status(hwif);
if ((a ^ s) & ~ATA_IDX)
diff --git a/drivers/ide/pmac.c b/drivers/ide/pmac.c
index 2e19d629853..7c481bb56fa 100644
--- a/drivers/ide/pmac.c
+++ b/drivers/ide/pmac.c
@@ -66,7 +66,6 @@ typedef struct pmac_ide_hwif {
struct macio_dev *mdev;
u32 timings[4];
volatile u32 __iomem * *kauai_fcr;
-#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
/* Those fields are duplicating what is in hwif. We currently
* can't use the hwif ones because of some assumptions that are
* beeing done by the generic code about the kind of dma controller
@@ -74,8 +73,6 @@ typedef struct pmac_ide_hwif {
*/
volatile struct dbdma_regs __iomem * dma_regs;
struct dbdma_cmd* dma_table_cpu;
-#endif
-
} pmac_ide_hwif_t;
enum {
@@ -222,8 +219,6 @@ static const char* model_name[] = {
#define KAUAI_FCR_UATA_RESET_N 0x00000002
#define KAUAI_FCR_UATA_ENABLE 0x00000001
-#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
-
/* Rounded Multiword DMA timings
*
* I gave up finding a generic formula for all controller
@@ -413,8 +408,6 @@ static int pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq);
static void pmac_ide_selectproc(ide_drive_t *drive);
static void pmac_ide_kauai_selectproc(ide_drive_t *drive);
-#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
-
#define PMAC_IDE_REG(x) \
((void __iomem *)((drive)->hwif->io_ports.data_addr + (x)))
@@ -584,8 +577,6 @@ pmac_ide_set_pio_mode(ide_drive_t *drive, const u8 pio)
pmac_ide_do_update_timings(drive);
}
-#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
-
/*
* Calculate KeyLargo ATA/66 UDMA timings
*/
@@ -786,7 +777,6 @@ set_timings_mdma(ide_drive_t *drive, int intf_type, u32 *timings, u32 *timings2,
drive->name, speed & 0xf, *timings);
#endif
}
-#endif /* #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC */
static void pmac_ide_set_dma_mode(ide_drive_t *drive, const u8 speed)
{
@@ -804,7 +794,6 @@ static void pmac_ide_set_dma_mode(ide_drive_t *drive, const u8 speed)
tl[0] = *timings;
tl[1] = *timings2;
-#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
if (speed >= XFER_UDMA_0) {
if (pmif->kind == controller_kl_ata4)
ret = set_timings_udma_ata4(&tl[0], speed);
@@ -817,7 +806,7 @@ static void pmac_ide_set_dma_mode(ide_drive_t *drive, const u8 speed)
ret = -1;
} else
set_timings_mdma(drive, pmif->kind, &tl[0], &tl[1], speed);
-#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
+
if (ret)
return;
@@ -1008,9 +997,7 @@ static const struct ide_port_info pmac_port_info = {
.chipset = ide_pmac,
.tp_ops = &pmac_tp_ops,
.port_ops = &pmac_ide_port_ops,
-#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
.dma_ops = &pmac_dma_ops,
-#endif
.host_flags = IDE_HFLAG_SET_PIO_MODE_KEEP_DMA |
IDE_HFLAG_POST_SET_MODE |
IDE_HFLAG_MMIO |
@@ -1182,7 +1169,7 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
pmif->regbase = regbase;
pmif->irq = irq;
pmif->kauai_fcr = NULL;
-#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
+
if (macio_resource_count(mdev) >= 2) {
if (macio_request_resource(mdev, 1, "ide-pmac (dma)"))
printk(KERN_WARNING "ide-pmac: can't request DMA "
@@ -1192,7 +1179,7 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
pmif->dma_regs = ioremap(macio_resource_start(mdev, 1), 0x1000);
} else
pmif->dma_regs = NULL;
-#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
+
dev_set_drvdata(&mdev->ofdev.dev, pmif);
memset(&hw, 0, sizeof(hw));
@@ -1300,9 +1287,7 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
base = ioremap(rbase, rlen);
pmif->regbase = (unsigned long) base + 0x2000;
-#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
pmif->dma_regs = base + 0x1000;
-#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
pmif->kauai_fcr = base;
pmif->irq = pdev->irq;
@@ -1434,8 +1419,6 @@ out:
return error;
}
-#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
-
/*
* pmac_ide_build_dmatable builds the DBDMA command list
* for a transfer and sets the DBDMA channel to point to it.
@@ -1723,13 +1706,6 @@ static int __devinit pmac_ide_init_dma(ide_hwif_t *hwif,
return 0;
}
-#else
-static int __devinit pmac_ide_init_dma(ide_hwif_t *hwif,
- const struct ide_port_info *d)
-{
- return -EOPNOTSUPP;
-}
-#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
module_init(pmac_ide_probe);
diff --git a/drivers/ide/sc1200.c b/drivers/ide/sc1200.c
index f1a8758e3a9..ec7f766ef5e 100644
--- a/drivers/ide/sc1200.c
+++ b/drivers/ide/sc1200.c
@@ -104,11 +104,12 @@ static u8 sc1200_udma_filter(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
ide_drive_t *mate = ide_get_pair_dev(drive);
- u16 *mateid = mate->id;
+ u16 *mateid;
u8 mask = hwif->ultra_mask;
if (mate == NULL)
goto out;
+ mateid = mate->id;
if (ata_id_has_dma(mateid) && __ide_dma_bad_drive(mate) == 0) {
if ((mateid[ATA_ID_FIELD_VALID] & 4) &&
diff --git a/drivers/ide/sgiioc4.c b/drivers/ide/sgiioc4.c
index 7defa0ae201..a687a7dfea6 100644
--- a/drivers/ide/sgiioc4.c
+++ b/drivers/ide/sgiioc4.c
@@ -550,7 +550,7 @@ static const struct ide_dma_ops sgiioc4_dma_ops = {
.dma_timeout = ide_dma_timeout,
};
-static const struct ide_port_info sgiioc4_port_info __devinitdata = {
+static const struct ide_port_info sgiioc4_port_info __devinitconst = {
.name = DRV_NAME,
.chipset = ide_pci,
.init_dma = ide_dma_sgiioc4,
@@ -633,7 +633,7 @@ out:
return ret;
}
-int
+int __devinit
ioc4_ide_attach_one(struct ioc4_driver_data *idd)
{
/* PCI-RT does not bring out IDE connection.
@@ -645,7 +645,7 @@ ioc4_ide_attach_one(struct ioc4_driver_data *idd)
return pci_init_sgiioc4(idd->idd_pdev);
}
-static struct ioc4_submodule ioc4_ide_submodule = {
+static struct ioc4_submodule __devinitdata ioc4_ide_submodule = {
.is_name = "IOC4_ide",
.is_owner = THIS_MODULE,
.is_probe = ioc4_ide_attach_one,
diff --git a/drivers/idle/Kconfig b/drivers/idle/Kconfig
index 108264de0ac..f15e90a453d 100644
--- a/drivers/idle/Kconfig
+++ b/drivers/idle/Kconfig
@@ -1,5 +1,6 @@
menu "Memory power savings"
+depends on X86_64
config I7300_IDLE_IOAT_CHANNEL
bool
@@ -7,7 +8,7 @@ config I7300_IDLE_IOAT_CHANNEL
config I7300_IDLE
tristate "Intel chipset idle memory power saving driver"
select I7300_IDLE_IOAT_CHANNEL
- depends on X86_64 && EXPERIMENTAL
+ depends on EXPERIMENTAL
help
Enable memory power savings when idle with certain Intel server
chipsets. The chipset must have I/O AT support, such as the
diff --git a/drivers/ieee1394/highlevel.c b/drivers/ieee1394/highlevel.c
index 918ffc4fc8a..272543a42a4 100644
--- a/drivers/ieee1394/highlevel.c
+++ b/drivers/ieee1394/highlevel.c
@@ -46,10 +46,6 @@ static DEFINE_RWLOCK(hl_irqs_lock);
static DEFINE_RWLOCK(addr_space_lock);
-/* addr_space list will have zero and max already included as bounds */
-static struct hpsb_address_ops dummy_ops = { NULL, NULL, NULL, NULL };
-static struct hpsb_address_serve dummy_zero_addr, dummy_max_addr;
-
static struct hl_host_info *hl_get_hostinfo(struct hpsb_highlevel *hl,
struct hpsb_host *host)
@@ -481,20 +477,23 @@ int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
return retval;
}
+static struct hpsb_address_ops dummy_ops;
+
+/* dummy address spaces as lower and upper bounds of the host's a.s. list */
static void init_hpsb_highlevel(struct hpsb_host *host)
{
- INIT_LIST_HEAD(&dummy_zero_addr.host_list);
- INIT_LIST_HEAD(&dummy_zero_addr.hl_list);
- INIT_LIST_HEAD(&dummy_max_addr.host_list);
- INIT_LIST_HEAD(&dummy_max_addr.hl_list);
+ INIT_LIST_HEAD(&host->dummy_zero_addr.host_list);
+ INIT_LIST_HEAD(&host->dummy_zero_addr.hl_list);
+ INIT_LIST_HEAD(&host->dummy_max_addr.host_list);
+ INIT_LIST_HEAD(&host->dummy_max_addr.hl_list);
- dummy_zero_addr.op = dummy_max_addr.op = &dummy_ops;
+ host->dummy_zero_addr.op = host->dummy_max_addr.op = &dummy_ops;
- dummy_zero_addr.start = dummy_zero_addr.end = 0;
- dummy_max_addr.start = dummy_max_addr.end = ((u64) 1) << 48;
+ host->dummy_zero_addr.start = host->dummy_zero_addr.end = 0;
+ host->dummy_max_addr.start = host->dummy_max_addr.end = ((u64) 1) << 48;
- list_add_tail(&dummy_zero_addr.host_list, &host->addr_space);
- list_add_tail(&dummy_max_addr.host_list, &host->addr_space);
+ list_add_tail(&host->dummy_zero_addr.host_list, &host->addr_space);
+ list_add_tail(&host->dummy_max_addr.host_list, &host->addr_space);
}
void highlevel_add_host(struct hpsb_host *host)
diff --git a/drivers/ieee1394/hosts.h b/drivers/ieee1394/hosts.h
index e4e8aeb4d77..dd229950acc 100644
--- a/drivers/ieee1394/hosts.h
+++ b/drivers/ieee1394/hosts.h
@@ -13,6 +13,7 @@ struct module;
#include "ieee1394_types.h"
#include "csr.h"
+#include "highlevel.h"
struct hpsb_packet;
struct hpsb_iso;
@@ -72,6 +73,9 @@ struct hpsb_host {
struct { DECLARE_BITMAP(map, 64); } tl_pool[ALL_NODES];
struct csr_control csr;
+
+ struct hpsb_address_serve dummy_zero_addr;
+ struct hpsb_address_serve dummy_max_addr;
};
enum devctl_cmd {
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
index 9e39f73282e..79ef5fd928a 100644
--- a/drivers/ieee1394/nodemgr.c
+++ b/drivers/ieee1394/nodemgr.c
@@ -115,8 +115,14 @@ static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr, u16 length,
return error;
}
+#define OUI_FREECOM_TECHNOLOGIES_GMBH 0x0001db
+
static int nodemgr_get_max_rom(quadlet_t *bus_info_data, void *__ci)
{
+ /* Freecom FireWire Hard Drive firmware bug */
+ if (be32_to_cpu(bus_info_data[3]) >> 8 == OUI_FREECOM_TECHNOLOGIES_GMBH)
+ return 0;
+
return (be32_to_cpu(bus_info_data[2]) >> 8) & 0x3;
}
@@ -1685,6 +1691,7 @@ static int nodemgr_host_thread(void *data)
g = get_hpsb_generation(host);
for (i = 0; i < 4 ; i++) {
msleep_interruptible(63);
+ try_to_freeze();
if (kthread_should_stop())
goto exit;
@@ -1725,6 +1732,7 @@ static int nodemgr_host_thread(void *data)
/* Sleep 3 seconds */
for (i = 3000/200; i; i--) {
msleep_interruptible(200);
+ try_to_freeze();
if (kthread_should_stop())
goto exit;
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index c52f6e6e8af..a373c18cf7b 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -402,6 +402,11 @@ static const struct {
},
/* iPod mini */ {
.firmware_revision = 0x0a2700,
+ .model_id = 0x000022,
+ .workarounds = SBP2_WORKAROUND_FIX_CAPACITY,
+ },
+ /* iPod mini */ {
+ .firmware_revision = 0x0a2700,
.model_id = 0x000023,
.workarounds = SBP2_WORKAROUND_FIX_CAPACITY,
},
@@ -890,12 +895,13 @@ static void sbp2_host_reset(struct hpsb_host *host)
return;
read_lock_irqsave(&sbp2_hi_logical_units_lock, flags);
+
list_for_each_entry(lu, &hi->logical_units, lu_list)
- if (likely(atomic_read(&lu->state) !=
- SBP2LU_STATE_IN_SHUTDOWN)) {
- atomic_set(&lu->state, SBP2LU_STATE_IN_RESET);
+ if (atomic_cmpxchg(&lu->state,
+ SBP2LU_STATE_RUNNING, SBP2LU_STATE_IN_RESET)
+ == SBP2LU_STATE_RUNNING)
scsi_block_requests(lu->shost);
- }
+
read_unlock_irqrestore(&sbp2_hi_logical_units_lock, flags);
}
diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c b/drivers/infiniband/hw/cxgb3/iwch_provider.c
index ecff9804358..160ef482712 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_provider.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c
@@ -1102,9 +1102,7 @@ static u64 fw_vers_string_to_u64(struct iwch_dev *iwch_dev)
char *cp, *next;
unsigned fw_maj, fw_min, fw_mic;
- rtnl_lock();
lldev->ethtool_ops->get_drvinfo(lldev, &info);
- rtnl_unlock();
next = info.fw_version + 1;
cp = strsep(&next, ".");
@@ -1192,9 +1190,7 @@ static ssize_t show_fw_ver(struct device *dev, struct device_attribute *attr, ch
struct net_device *lldev = iwch_dev->rdev.t3cdev_p->lldev;
PDBG("%s dev 0x%p\n", __func__, dev);
- rtnl_lock();
lldev->ethtool_ops->get_drvinfo(lldev, &info);
- rtnl_unlock();
return sprintf(buf, "%s\n", info.fw_version);
}
@@ -1207,9 +1203,7 @@ static ssize_t show_hca(struct device *dev, struct device_attribute *attr,
struct net_device *lldev = iwch_dev->rdev.t3cdev_p->lldev;
PDBG("%s dev 0x%p\n", __func__, dev);
- rtnl_lock();
lldev->ethtool_ops->get_drvinfo(lldev, &info);
- rtnl_unlock();
return sprintf(buf, "%s\n", info.driver);
}
diff --git a/drivers/infiniband/hw/cxgb3/iwch_qp.c b/drivers/infiniband/hw/cxgb3/iwch_qp.c
index 3e4585c2318..19661b2f040 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_qp.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_qp.c
@@ -745,7 +745,6 @@ int iwch_post_zb_read(struct iwch_qp *qhp)
wqe->read.rdmaop = T3_READ_REQ;
wqe->read.reserved[0] = 0;
wqe->read.reserved[1] = 0;
- wqe->read.reserved[2] = 0;
wqe->read.rem_stag = cpu_to_be32(1);
wqe->read.rem_to = cpu_to_be64(1);
wqe->read.local_stag = cpu_to_be32(1);
diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h
index 4df887af66a..7fc35cf0cdd 100644
--- a/drivers/infiniband/hw/ehca/ehca_classes.h
+++ b/drivers/infiniband/hw/ehca/ehca_classes.h
@@ -163,7 +163,8 @@ struct ehca_mod_qp_parm {
/* struct for tracking if cqes have been reported to the application */
struct ehca_qmap_entry {
u16 app_wr_id;
- u16 reported;
+ u8 reported;
+ u8 cqe_req;
};
struct ehca_queue_map {
@@ -171,6 +172,7 @@ struct ehca_queue_map {
unsigned int entries;
unsigned int tail;
unsigned int left_to_poll;
+ unsigned int next_wqe_idx; /* Idx to first wqe to be flushed */
};
struct ehca_qp {
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c b/drivers/infiniband/hw/ehca/ehca_irq.c
index cb55be04442..757035ea246 100644
--- a/drivers/infiniband/hw/ehca/ehca_irq.c
+++ b/drivers/infiniband/hw/ehca/ehca_irq.c
@@ -359,36 +359,48 @@ static void notify_port_conf_change(struct ehca_shca *shca, int port_num)
*old_attr = new_attr;
}
+/* replay modify_qp for sqps -- return 0 if all is well, 1 if AQP1 destroyed */
+static int replay_modify_qp(struct ehca_sport *sport)
+{
+ int aqp1_destroyed;
+ unsigned long flags;
+
+ spin_lock_irqsave(&sport->mod_sqp_lock, flags);
+
+ aqp1_destroyed = !sport->ibqp_sqp[IB_QPT_GSI];
+
+ if (sport->ibqp_sqp[IB_QPT_SMI])
+ ehca_recover_sqp(sport->ibqp_sqp[IB_QPT_SMI]);
+ if (!aqp1_destroyed)
+ ehca_recover_sqp(sport->ibqp_sqp[IB_QPT_GSI]);
+
+ spin_unlock_irqrestore(&sport->mod_sqp_lock, flags);
+
+ return aqp1_destroyed;
+}
+
static void parse_ec(struct ehca_shca *shca, u64 eqe)
{
u8 ec = EHCA_BMASK_GET(NEQE_EVENT_CODE, eqe);
u8 port = EHCA_BMASK_GET(NEQE_PORT_NUMBER, eqe);
u8 spec_event;
struct ehca_sport *sport = &shca->sport[port - 1];
- unsigned long flags;
switch (ec) {
case 0x30: /* port availability change */
if (EHCA_BMASK_GET(NEQE_PORT_AVAILABILITY, eqe)) {
- int suppress_event;
- /* replay modify_qp for sqps */
- spin_lock_irqsave(&sport->mod_sqp_lock, flags);
- suppress_event = !sport->ibqp_sqp[IB_QPT_GSI];
- if (sport->ibqp_sqp[IB_QPT_SMI])
- ehca_recover_sqp(sport->ibqp_sqp[IB_QPT_SMI]);
- if (!suppress_event)
- ehca_recover_sqp(sport->ibqp_sqp[IB_QPT_GSI]);
- spin_unlock_irqrestore(&sport->mod_sqp_lock, flags);
-
- /* AQP1 was destroyed, ignore this event */
- if (suppress_event)
- break;
+ /* only replay modify_qp calls in autodetect mode;
+ * if AQP1 was destroyed, the port is already down
+ * again and we can drop the event.
+ */
+ if (ehca_nr_ports < 0)
+ if (replay_modify_qp(sport))
+ break;
sport->port_state = IB_PORT_ACTIVE;
dispatch_port_event(shca, port, IB_EVENT_PORT_ACTIVE,
"is active");
- ehca_query_sma_attr(shca, port,
- &sport->saved_attr);
+ ehca_query_sma_attr(shca, port, &sport->saved_attr);
} else {
sport->port_state = IB_PORT_DOWN;
dispatch_port_event(shca, port, IB_EVENT_PORT_ERR,
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c
index bb02a86aa52..bec7e024935 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -994,8 +994,7 @@ static int ehca_mem_notifier(struct notifier_block *nb,
if (printk_timed_ratelimit(&ehca_dmem_warn_time,
30 * 1000))
ehca_gen_err("DMEM operations are not allowed"
- "as long as an ehca adapter is"
- "attached to the LPAR");
+ "in conjunction with eHCA");
return NOTIFY_BAD;
}
}
diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c
index 4d54b9f6456..cadbf0cdd91 100644
--- a/drivers/infiniband/hw/ehca/ehca_qp.c
+++ b/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -435,9 +435,13 @@ static void reset_queue_map(struct ehca_queue_map *qmap)
{
int i;
- qmap->tail = 0;
- for (i = 0; i < qmap->entries; i++)
+ qmap->tail = qmap->entries - 1;
+ qmap->left_to_poll = 0;
+ qmap->next_wqe_idx = 0;
+ for (i = 0; i < qmap->entries; i++) {
qmap->map[i].reported = 1;
+ qmap->map[i].cqe_req = 0;
+ }
}
/*
@@ -860,6 +864,11 @@ static struct ehca_qp *internal_create_qp(
if (qp_type == IB_QPT_GSI) {
h_ret = ehca_define_sqp(shca, my_qp, init_attr);
if (h_ret != H_SUCCESS) {
+ kfree(my_qp->mod_qp_parm);
+ my_qp->mod_qp_parm = NULL;
+ /* the QP pointer is no longer valid */
+ shca->sport[init_attr->port_num - 1].ibqp_sqp[qp_type] =
+ NULL;
ret = ehca2ib_return_code(h_ret);
goto create_qp_exit6;
}
@@ -1116,6 +1125,7 @@ static int calc_left_cqes(u64 wqe_p, struct ipz_queue *ipz_queue,
void *wqe_v;
u64 q_ofs;
u32 wqe_idx;
+ unsigned int tail_idx;
/* convert real to abs address */
wqe_p = wqe_p & (~(1UL << 63));
@@ -1128,12 +1138,17 @@ static int calc_left_cqes(u64 wqe_p, struct ipz_queue *ipz_queue,
return -EFAULT;
}
+ tail_idx = (qmap->tail + 1) % qmap->entries;
wqe_idx = q_ofs / ipz_queue->qe_size;
- if (wqe_idx < qmap->tail)
- qmap->left_to_poll = (qmap->entries - qmap->tail) + wqe_idx;
- else
- qmap->left_to_poll = wqe_idx - qmap->tail;
+ /* check all processed wqes, whether a cqe is requested or not */
+ while (tail_idx != wqe_idx) {
+ if (qmap->map[tail_idx].cqe_req)
+ qmap->left_to_poll++;
+ tail_idx = (tail_idx + 1) % qmap->entries;
+ }
+ /* save index in queue, where we have to start flushing */
+ qmap->next_wqe_idx = wqe_idx;
return 0;
}
@@ -1180,10 +1195,14 @@ static int check_for_left_cqes(struct ehca_qp *my_qp, struct ehca_shca *shca)
} else {
spin_lock_irqsave(&my_qp->send_cq->spinlock, flags);
my_qp->sq_map.left_to_poll = 0;
+ my_qp->sq_map.next_wqe_idx = (my_qp->sq_map.tail + 1) %
+ my_qp->sq_map.entries;
spin_unlock_irqrestore(&my_qp->send_cq->spinlock, flags);
spin_lock_irqsave(&my_qp->recv_cq->spinlock, flags);
my_qp->rq_map.left_to_poll = 0;
+ my_qp->rq_map.next_wqe_idx = (my_qp->rq_map.tail + 1) %
+ my_qp->rq_map.entries;
spin_unlock_irqrestore(&my_qp->recv_cq->spinlock, flags);
}
diff --git a/drivers/infiniband/hw/ehca/ehca_reqs.c b/drivers/infiniband/hw/ehca/ehca_reqs.c
index 64928079eaf..00a648f4316 100644
--- a/drivers/infiniband/hw/ehca/ehca_reqs.c
+++ b/drivers/infiniband/hw/ehca/ehca_reqs.c
@@ -179,6 +179,7 @@ static inline int ehca_write_swqe(struct ehca_qp *qp,
qmap_entry->app_wr_id = get_app_wr_id(send_wr->wr_id);
qmap_entry->reported = 0;
+ qmap_entry->cqe_req = 0;
switch (send_wr->opcode) {
case IB_WR_SEND:
@@ -203,8 +204,10 @@ static inline int ehca_write_swqe(struct ehca_qp *qp,
if ((send_wr->send_flags & IB_SEND_SIGNALED ||
qp->init_attr.sq_sig_type == IB_SIGNAL_ALL_WR)
- && !hidden)
+ && !hidden) {
wqe_p->wr_flag |= WQE_WRFLAG_REQ_SIGNAL_COM;
+ qmap_entry->cqe_req = 1;
+ }
if (send_wr->opcode == IB_WR_SEND_WITH_IMM ||
send_wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM) {
@@ -569,6 +572,7 @@ static int internal_post_recv(struct ehca_qp *my_qp,
qmap_entry = &my_qp->rq_map.map[rq_map_idx];
qmap_entry->app_wr_id = get_app_wr_id(cur_recv_wr->wr_id);
qmap_entry->reported = 0;
+ qmap_entry->cqe_req = 1;
wqe_cnt++;
} /* eof for cur_recv_wr */
@@ -706,27 +710,34 @@ repoll:
goto repoll;
wc->qp = &my_qp->ib_qp;
+ qmap_tail_idx = get_app_wr_id(cqe->work_request_id);
+ if (!(cqe->w_completion_flags & WC_SEND_RECEIVE_BIT))
+ /* We got a send completion. */
+ qmap = &my_qp->sq_map;
+ else
+ /* We got a receive completion. */
+ qmap = &my_qp->rq_map;
+
+ /* advance the tail pointer */
+ qmap->tail = qmap_tail_idx;
+
if (is_error) {
/*
* set left_to_poll to 0 because in error state, we will not
* get any additional CQEs
*/
- ehca_add_to_err_list(my_qp, 1);
+ my_qp->sq_map.next_wqe_idx = (my_qp->sq_map.tail + 1) %
+ my_qp->sq_map.entries;
my_qp->sq_map.left_to_poll = 0;
+ ehca_add_to_err_list(my_qp, 1);
+ my_qp->rq_map.next_wqe_idx = (my_qp->rq_map.tail + 1) %
+ my_qp->rq_map.entries;
+ my_qp->rq_map.left_to_poll = 0;
if (HAS_RQ(my_qp))
ehca_add_to_err_list(my_qp, 0);
- my_qp->rq_map.left_to_poll = 0;
}
- qmap_tail_idx = get_app_wr_id(cqe->work_request_id);
- if (!(cqe->w_completion_flags & WC_SEND_RECEIVE_BIT))
- /* We got a send completion. */
- qmap = &my_qp->sq_map;
- else
- /* We got a receive completion. */
- qmap = &my_qp->rq_map;
-
qmap_entry = &qmap->map[qmap_tail_idx];
if (qmap_entry->reported) {
ehca_warn(cq->device, "Double cqe on qp_num=%#x",
@@ -738,10 +749,6 @@ repoll:
wc->wr_id = replace_wr_id(cqe->work_request_id, qmap_entry->app_wr_id);
qmap_entry->reported = 1;
- /* this is a proper completion, we need to advance the tail pointer */
- if (++qmap->tail == qmap->entries)
- qmap->tail = 0;
-
/* if left_to_poll is decremented to 0, add the QP to the error list */
if (qmap->left_to_poll > 0) {
qmap->left_to_poll--;
@@ -805,13 +812,14 @@ static int generate_flush_cqes(struct ehca_qp *my_qp, struct ib_cq *cq,
else
qmap = &my_qp->rq_map;
- qmap_entry = &qmap->map[qmap->tail];
+ qmap_entry = &qmap->map[qmap->next_wqe_idx];
while ((nr < num_entries) && (qmap_entry->reported == 0)) {
/* generate flush CQE */
+
memset(wc, 0, sizeof(*wc));
- offset = qmap->tail * ipz_queue->qe_size;
+ offset = qmap->next_wqe_idx * ipz_queue->qe_size;
wqe = (struct ehca_wqe *)ipz_qeit_calc(ipz_queue, offset);
if (!wqe) {
ehca_err(cq->device, "Invalid wqe offset=%#lx on "
@@ -850,11 +858,12 @@ static int generate_flush_cqes(struct ehca_qp *my_qp, struct ib_cq *cq,
wc->qp = &my_qp->ib_qp;
- /* mark as reported and advance tail pointer */
+ /* mark as reported and advance next_wqe pointer */
qmap_entry->reported = 1;
- if (++qmap->tail == qmap->entries)
- qmap->tail = 0;
- qmap_entry = &qmap->map[qmap->tail];
+ qmap->next_wqe_idx++;
+ if (qmap->next_wqe_idx == qmap->entries)
+ qmap->next_wqe_idx = 0;
+ qmap_entry = &qmap->map[qmap->next_wqe_idx];
wc++; nr++;
}
diff --git a/drivers/infiniband/hw/ipath/ipath_ruc.c b/drivers/infiniband/hw/ipath/ipath_ruc.c
index fc0f6d9e603..2296832f94d 100644
--- a/drivers/infiniband/hw/ipath/ipath_ruc.c
+++ b/drivers/infiniband/hw/ipath/ipath_ruc.c
@@ -156,7 +156,7 @@ bail:
/**
* ipath_get_rwqe - copy the next RWQE into the QP's RWQE
* @qp: the QP
- * @wr_id_only: update wr_id only, not SGEs
+ * @wr_id_only: update qp->r_wr_id only, not qp->r_sge
*
* Return 0 if no RWQE is available, otherwise return 1.
*
@@ -173,8 +173,6 @@ int ipath_get_rwqe(struct ipath_qp *qp, int wr_id_only)
u32 tail;
int ret;
- qp->r_sge.sg_list = qp->r_sg_list;
-
if (qp->ibqp.srq) {
srq = to_isrq(qp->ibqp.srq);
handler = srq->ibsrq.event_handler;
@@ -206,8 +204,10 @@ int ipath_get_rwqe(struct ipath_qp *qp, int wr_id_only)
wqe = get_rwqe_ptr(rq, tail);
if (++tail >= rq->size)
tail = 0;
- } while (!wr_id_only && !ipath_init_sge(qp, wqe, &qp->r_len,
- &qp->r_sge));
+ if (wr_id_only)
+ break;
+ qp->r_sge.sg_list = qp->r_sg_list;
+ } while (!ipath_init_sge(qp, wqe, &qp->r_len, &qp->r_sge));
qp->r_wr_id = wqe->wr_id;
wq->tail = tail;
diff --git a/drivers/infiniband/hw/mlx4/cq.c b/drivers/infiniband/hw/mlx4/cq.c
index d0866a3636e..18308494a19 100644
--- a/drivers/infiniband/hw/mlx4/cq.c
+++ b/drivers/infiniband/hw/mlx4/cq.c
@@ -343,6 +343,7 @@ int mlx4_ib_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *udata)
{
struct mlx4_ib_dev *dev = to_mdev(ibcq->device);
struct mlx4_ib_cq *cq = to_mcq(ibcq);
+ struct mlx4_mtt mtt;
int outst_cqe;
int err;
@@ -376,10 +377,13 @@ int mlx4_ib_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *udata)
goto out;
}
+ mtt = cq->buf.mtt;
+
err = mlx4_cq_resize(dev->dev, &cq->mcq, entries, &cq->resize_buf->buf.mtt);
if (err)
goto err_buf;
+ mlx4_mtt_cleanup(dev->dev, &mtt);
if (ibcq->uobject) {
cq->buf = cq->resize_buf->buf;
cq->ibcq.cqe = cq->resize_buf->cqe;
@@ -406,6 +410,7 @@ int mlx4_ib_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *udata)
goto out;
err_buf:
+ mlx4_mtt_cleanup(dev->dev, &cq->resize_buf->buf.mtt);
if (!ibcq->uobject)
mlx4_ib_free_cq_buf(dev, &cq->resize_buf->buf,
cq->resize_buf->cqe);
diff --git a/drivers/infiniband/hw/mlx4/mr.c b/drivers/infiniband/hw/mlx4/mr.c
index 87f5c5a87b9..8e4d26d56a9 100644
--- a/drivers/infiniband/hw/mlx4/mr.c
+++ b/drivers/infiniband/hw/mlx4/mr.c
@@ -205,6 +205,7 @@ struct ib_mr *mlx4_ib_alloc_fast_reg_mr(struct ib_pd *pd,
goto err_mr;
mr->ibmr.rkey = mr->ibmr.lkey = mr->mmr.key;
+ mr->umem = NULL;
return &mr->ibmr;
diff --git a/drivers/infiniband/hw/nes/nes.c b/drivers/infiniband/hw/nes/nes.c
index a2b04d62b1a..aa1dc41f04c 100644
--- a/drivers/infiniband/hw/nes/nes.c
+++ b/drivers/infiniband/hw/nes/nes.c
@@ -95,6 +95,10 @@ unsigned int wqm_quanta = 0x10000;
module_param(wqm_quanta, int, 0644);
MODULE_PARM_DESC(wqm_quanta, "WQM quanta");
+static unsigned int limit_maxrdreqsz;
+module_param(limit_maxrdreqsz, bool, 0644);
+MODULE_PARM_DESC(limit_maxrdreqsz, "Limit max read request size to 256 Bytes");
+
LIST_HEAD(nes_adapter_list);
static LIST_HEAD(nes_dev_list);
@@ -588,6 +592,18 @@ static int __devinit nes_probe(struct pci_dev *pcidev, const struct pci_device_i
nesdev->nesadapter->port_count;
}
+ if ((limit_maxrdreqsz ||
+ ((nesdev->nesadapter->phy_type[0] == NES_PHY_TYPE_GLADIUS) &&
+ (hw_rev == NE020_REV1))) &&
+ (pcie_get_readrq(pcidev) > 256)) {
+ if (pcie_set_readrq(pcidev, 256))
+ printk(KERN_ERR PFX "Unable to set max read request"
+ " to 256 bytes\n");
+ else
+ nes_debug(NES_DBG_INIT, "Max read request size set"
+ " to 256 bytes\n");
+ }
+
tasklet_init(&nesdev->dpc_tasklet, nes_dpc, (unsigned long)nesdev);
/* bring up the Control QP */
diff --git a/drivers/infiniband/hw/nes/nes_hw.h b/drivers/infiniband/hw/nes/nes_hw.h
index 610b9d85959..bc0b4de0445 100644
--- a/drivers/infiniband/hw/nes/nes_hw.h
+++ b/drivers/infiniband/hw/nes/nes_hw.h
@@ -40,6 +40,7 @@
#define NES_PHY_TYPE_ARGUS 4
#define NES_PHY_TYPE_PUMA_1G 5
#define NES_PHY_TYPE_PUMA_10G 6
+#define NES_PHY_TYPE_GLADIUS 7
#define NES_MULTICAST_PF_MAX 8
diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c
index 932e56fcf77..d36c9a0bf1b 100644
--- a/drivers/infiniband/hw/nes/nes_verbs.c
+++ b/drivers/infiniband/hw/nes/nes_verbs.c
@@ -220,14 +220,14 @@ static int nes_bind_mw(struct ib_qp *ibqp, struct ib_mw *ibmw,
if (nesqp->ibqp_state > IB_QPS_RTS)
return -EINVAL;
- spin_lock_irqsave(&nesqp->lock, flags);
+ spin_lock_irqsave(&nesqp->lock, flags);
head = nesqp->hwqp.sq_head;
qsize = nesqp->hwqp.sq_tail;
/* Check for SQ overflow */
if (((head + (2 * qsize) - nesqp->hwqp.sq_tail) % qsize) == (qsize - 1)) {
- spin_unlock_irqrestore(&nesqp->lock, flags);
+ spin_unlock_irqrestore(&nesqp->lock, flags);
return -EINVAL;
}
@@ -269,7 +269,7 @@ static int nes_bind_mw(struct ib_qp *ibqp, struct ib_mw *ibmw,
nes_write32(nesdev->regs+NES_WQE_ALLOC,
(1 << 24) | 0x00800000 | nesqp->hwqp.qp_id);
- spin_unlock_irqrestore(&nesqp->lock, flags);
+ spin_unlock_irqrestore(&nesqp->lock, flags);
return 0;
}
@@ -349,7 +349,7 @@ static struct ib_fmr *nes_alloc_fmr(struct ib_pd *ibpd,
if (nesfmr->nesmr.pbls_used > nesadapter->free_4kpbl) {
spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
ret = -ENOMEM;
- goto failed_vpbl_alloc;
+ goto failed_vpbl_avail;
} else {
nesadapter->free_4kpbl -= nesfmr->nesmr.pbls_used;
}
@@ -357,7 +357,7 @@ static struct ib_fmr *nes_alloc_fmr(struct ib_pd *ibpd,
if (nesfmr->nesmr.pbls_used > nesadapter->free_256pbl) {
spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
ret = -ENOMEM;
- goto failed_vpbl_alloc;
+ goto failed_vpbl_avail;
} else {
nesadapter->free_256pbl -= nesfmr->nesmr.pbls_used;
}
@@ -391,14 +391,14 @@ static struct ib_fmr *nes_alloc_fmr(struct ib_pd *ibpd,
goto failed_vpbl_alloc;
}
- nesfmr->root_vpbl.leaf_vpbl = kzalloc(sizeof(*nesfmr->root_vpbl.leaf_vpbl)*1024, GFP_KERNEL);
+ nesfmr->leaf_pbl_cnt = nesfmr->nesmr.pbls_used-1;
+ nesfmr->root_vpbl.leaf_vpbl = kzalloc(sizeof(*nesfmr->root_vpbl.leaf_vpbl)*1024, GFP_ATOMIC);
if (!nesfmr->root_vpbl.leaf_vpbl) {
spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
ret = -ENOMEM;
goto failed_leaf_vpbl_alloc;
}
- nesfmr->leaf_pbl_cnt = nesfmr->nesmr.pbls_used-1;
nes_debug(NES_DBG_MR, "two level pbl, root_vpbl.pbl_vbase=%p"
" leaf_pbl_cnt=%d root_vpbl.leaf_vpbl=%p\n",
nesfmr->root_vpbl.pbl_vbase, nesfmr->leaf_pbl_cnt, nesfmr->root_vpbl.leaf_vpbl);
@@ -519,6 +519,16 @@ static struct ib_fmr *nes_alloc_fmr(struct ib_pd *ibpd,
nesfmr->root_vpbl.pbl_pbase);
failed_vpbl_alloc:
+ if (nesfmr->nesmr.pbls_used != 0) {
+ spin_lock_irqsave(&nesadapter->pbl_lock, flags);
+ if (nesfmr->nesmr.pbl_4k)
+ nesadapter->free_4kpbl += nesfmr->nesmr.pbls_used;
+ else
+ nesadapter->free_256pbl += nesfmr->nesmr.pbls_used;
+ spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
+ }
+
+failed_vpbl_avail:
kfree(nesfmr);
failed_fmr_alloc:
@@ -534,18 +544,14 @@ static struct ib_fmr *nes_alloc_fmr(struct ib_pd *ibpd,
*/
static int nes_dealloc_fmr(struct ib_fmr *ibfmr)
{
+ unsigned long flags;
struct nes_mr *nesmr = to_nesmr_from_ibfmr(ibfmr);
struct nes_fmr *nesfmr = to_nesfmr(nesmr);
struct nes_vnic *nesvnic = to_nesvnic(ibfmr->device);
struct nes_device *nesdev = nesvnic->nesdev;
- struct nes_mr temp_nesmr = *nesmr;
+ struct nes_adapter *nesadapter = nesdev->nesadapter;
int i = 0;
- temp_nesmr.ibmw.device = ibfmr->device;
- temp_nesmr.ibmw.pd = ibfmr->pd;
- temp_nesmr.ibmw.rkey = ibfmr->rkey;
- temp_nesmr.ibmw.uobject = NULL;
-
/* free the resources */
if (nesfmr->leaf_pbl_cnt == 0) {
/* single PBL case */
@@ -561,8 +567,24 @@ static int nes_dealloc_fmr(struct ib_fmr *ibfmr)
pci_free_consistent(nesdev->pcidev, 8192, nesfmr->root_vpbl.pbl_vbase,
nesfmr->root_vpbl.pbl_pbase);
}
+ nesmr->ibmw.device = ibfmr->device;
+ nesmr->ibmw.pd = ibfmr->pd;
+ nesmr->ibmw.rkey = ibfmr->rkey;
+ nesmr->ibmw.uobject = NULL;
- return nes_dealloc_mw(&temp_nesmr.ibmw);
+ if (nesfmr->nesmr.pbls_used != 0) {
+ spin_lock_irqsave(&nesadapter->pbl_lock, flags);
+ if (nesfmr->nesmr.pbl_4k) {
+ nesadapter->free_4kpbl += nesfmr->nesmr.pbls_used;
+ WARN_ON(nesadapter->free_4kpbl > nesadapter->max_4kpbl);
+ } else {
+ nesadapter->free_256pbl += nesfmr->nesmr.pbls_used;
+ WARN_ON(nesadapter->free_256pbl > nesadapter->max_256pbl);
+ }
+ spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
+ }
+
+ return nes_dealloc_mw(&nesmr->ibmw);
}
@@ -1595,7 +1617,7 @@ static struct ib_cq *nes_create_cq(struct ib_device *ibdev, int entries,
nes_ucontext->mcrqf = req.mcrqf;
if (nes_ucontext->mcrqf) {
if (nes_ucontext->mcrqf & 0x80000000)
- nescq->hw_cq.cq_number = nesvnic->nic.qp_id + 12 + (nes_ucontext->mcrqf & 0xf) - 1;
+ nescq->hw_cq.cq_number = nesvnic->nic.qp_id + 28 + 2 * ((nes_ucontext->mcrqf & 0xf) - 1);
else if (nes_ucontext->mcrqf & 0x40000000)
nescq->hw_cq.cq_number = nes_ucontext->mcrqf & 0xffff;
else
@@ -3212,7 +3234,7 @@ static int nes_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr,
if (nesqp->ibqp_state > IB_QPS_RTS)
return -EINVAL;
- spin_lock_irqsave(&nesqp->lock, flags);
+ spin_lock_irqsave(&nesqp->lock, flags);
head = nesqp->hwqp.sq_head;
@@ -3337,7 +3359,7 @@ static int nes_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr,
(counter << 24) | 0x00800000 | nesqp->hwqp.qp_id);
}
- spin_unlock_irqrestore(&nesqp->lock, flags);
+ spin_unlock_irqrestore(&nesqp->lock, flags);
if (err)
*bad_wr = ib_wr;
@@ -3368,7 +3390,7 @@ static int nes_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *ib_wr,
if (nesqp->ibqp_state > IB_QPS_RTS)
return -EINVAL;
- spin_lock_irqsave(&nesqp->lock, flags);
+ spin_lock_irqsave(&nesqp->lock, flags);
head = nesqp->hwqp.rq_head;
@@ -3421,7 +3443,7 @@ static int nes_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *ib_wr,
nes_write32(nesdev->regs+NES_WQE_ALLOC, (counter<<24) | nesqp->hwqp.qp_id);
}
- spin_unlock_irqrestore(&nesqp->lock, flags);
+ spin_unlock_irqrestore(&nesqp->lock, flags);
if (err)
*bad_wr = ib_wr;
@@ -3453,7 +3475,7 @@ static int nes_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry)
nes_debug(NES_DBG_CQ, "\n");
- spin_lock_irqsave(&nescq->lock, flags);
+ spin_lock_irqsave(&nescq->lock, flags);
head = nescq->hw_cq.cq_head;
cq_size = nescq->hw_cq.cq_size;
@@ -3562,7 +3584,7 @@ static int nes_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry)
nes_debug(NES_DBG_CQ, "Reporting %u completions for CQ%u.\n",
cqe_count, nescq->hw_cq.cq_number);
- spin_unlock_irqrestore(&nescq->lock, flags);
+ spin_unlock_irqrestore(&nescq->lock, flags);
return cqe_count;
}
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index fddded7900d..85257f6b957 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -106,12 +106,13 @@ int ipoib_open(struct net_device *dev)
ipoib_dbg(priv, "bringing up interface\n");
- napi_enable(&priv->napi);
set_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags);
if (ipoib_pkey_dev_delay_open(dev))
return 0;
+ napi_enable(&priv->napi);
+
if (ipoib_ib_dev_open(dev)) {
napi_disable(&priv->napi);
return -EINVAL;
@@ -546,6 +547,7 @@ static int path_rec_start(struct net_device *dev,
if (path->query_id < 0) {
ipoib_warn(priv, "ib_sa_path_rec_get failed: %d\n", path->query_id);
path->query = NULL;
+ complete(&path->done);
return path->query_id;
}
@@ -662,7 +664,7 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev,
skb_push(skb, sizeof *phdr);
__skb_queue_tail(&path->queue, skb);
- if (path_rec_start(dev, path)) {
+ if (!path->query && path_rec_start(dev, path)) {
spin_unlock_irqrestore(&priv->lock, flags);
path_free(dev, path);
return;
diff --git a/drivers/input/ff-memless.c b/drivers/input/ff-memless.c
index 6790e975a98..bc4e40f3ede 100644
--- a/drivers/input/ff-memless.c
+++ b/drivers/input/ff-memless.c
@@ -397,8 +397,9 @@ static int ml_ff_playback(struct input_dev *dev, int effect_id, int value)
{
struct ml_device *ml = dev->ff->private;
struct ml_effect_state *state = &ml->states[effect_id];
+ unsigned long flags;
- spin_lock_bh(&ml->timer_lock);
+ spin_lock_irqsave(&ml->timer_lock, flags);
if (value > 0) {
debug("initiated play");
@@ -424,7 +425,7 @@ static int ml_ff_playback(struct input_dev *dev, int effect_id, int value)
ml_play_effects(ml);
}
- spin_unlock_bh(&ml->timer_lock);
+ spin_unlock_irqrestore(&ml->timer_lock, flags);
return 0;
}
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index 22016ca1535..379b7ff354e 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -824,7 +824,7 @@ static void atkbd_disconnect(struct serio *serio)
atkbd_disable(atkbd);
/* make sure we don't have a command in flight */
- flush_scheduled_work();
+ cancel_delayed_work_sync(&atkbd->event_work);
sysfs_remove_group(&serio->dev.kobj, &atkbd_attribute_group);
input_unregister_device(atkbd->dev);
@@ -868,6 +868,22 @@ static void atkbd_hp_keymap_fixup(struct atkbd *atkbd)
}
/*
+ * Inventec system with broken key release on volume keys
+ */
+static void atkbd_inventec_keymap_fixup(struct atkbd *atkbd)
+{
+ const unsigned int forced_release_keys[] = {
+ 0xae, 0xb0,
+ };
+ int i;
+
+ if (atkbd->set == 2)
+ for (i = 0; i < ARRAY_SIZE(forced_release_keys); i++)
+ __set_bit(forced_release_keys[i],
+ atkbd->force_release_mask);
+}
+
+/*
* atkbd_set_keycode_table() initializes keyboard's keycode table
* according to the selected scancode set
*/
@@ -1468,6 +1484,15 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
.callback = atkbd_setup_fixup,
.driver_data = atkbd_hp_keymap_fixup,
},
+ {
+ .ident = "Inventec Symphony",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "INVENTEC"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "SYMPHONY 6.0/7.0"),
+ },
+ .callback = atkbd_setup_fixup,
+ .driver_data = atkbd_inventec_keymap_fixup,
+ },
{ }
};
diff --git a/drivers/input/misc/cm109.c b/drivers/input/misc/cm109.c
index bce160f4349..86457feccfc 100644
--- a/drivers/input/misc/cm109.c
+++ b/drivers/input/misc/cm109.c
@@ -42,7 +42,7 @@
static char *phone = "kip1000";
module_param(phone, charp, S_IRUSR);
-MODULE_PARM_DESC(phone, "Phone name {kip1000, gtalk, usbph01}");
+MODULE_PARM_DESC(phone, "Phone name {kip1000, gtalk, usbph01, atcom}");
enum {
/* HID Registers */
@@ -258,6 +258,37 @@ static unsigned short keymap_usbph01(int scancode)
}
}
+/*
+ * Keymap for ATCom AU-100
+ * http://www.atcom.cn/En_products_AU100.html
+ * http://www.packetizer.com/products/au100/
+ * http://www.voip-info.org/wiki/view/AU-100
+ *
+ * Contributed by daniel@gimpelevich.san-francisco.ca.us
+ */
+static unsigned short keymap_atcom(int scancode)
+{
+ switch (scancode) { /* phone key: */
+ case 0x82: return KEY_NUMERIC_0; /* 0 */
+ case 0x11: return KEY_NUMERIC_1; /* 1 */
+ case 0x12: return KEY_NUMERIC_2; /* 2 */
+ case 0x14: return KEY_NUMERIC_3; /* 3 */
+ case 0x21: return KEY_NUMERIC_4; /* 4 */
+ case 0x22: return KEY_NUMERIC_5; /* 5 */
+ case 0x24: return KEY_NUMERIC_6; /* 6 */
+ case 0x41: return KEY_NUMERIC_7; /* 7 */
+ case 0x42: return KEY_NUMERIC_8; /* 8 */
+ case 0x44: return KEY_NUMERIC_9; /* 9 */
+ case 0x84: return KEY_NUMERIC_POUND; /* # */
+ case 0x81: return KEY_NUMERIC_STAR; /* * */
+ case 0x18: return KEY_ENTER; /* pickup */
+ case 0x28: return KEY_ESC; /* hangup */
+ case 0x48: return KEY_LEFT; /* left arrow */
+ case 0x88: return KEY_RIGHT; /* right arrow */
+ default: return special_keymap(scancode);
+ }
+}
+
static unsigned short (*keymap)(int) = keymap_kip1000;
/*
@@ -840,6 +871,10 @@ static int __init cm109_select_keymap(void)
keymap = keymap_usbph01;
printk(KERN_INFO KBUILD_MODNAME ": "
"Keymap for Allied-Telesis Corega USBPH01 phone loaded\n");
+ } else if (!strcasecmp(phone, "atcom")) {
+ keymap = keymap_atcom;
+ printk(KERN_INFO KBUILD_MODNAME ": "
+ "Keymap for ATCom AU-100 phone loaded\n");
} else {
printk(KERN_ERR KBUILD_MODNAME ": "
"Unsupported phone: %s\n", phone);
diff --git a/drivers/input/mouse/hgpk.c b/drivers/input/mouse/hgpk.c
index e82d34201e9..88f04bf2ad6 100644
--- a/drivers/input/mouse/hgpk.c
+++ b/drivers/input/mouse/hgpk.c
@@ -125,7 +125,7 @@ static void hgpk_spewing_hack(struct psmouse *psmouse,
*/
static int hgpk_validate_byte(unsigned char *packet)
{
- return (packet[0] & 0x0C) == 0x08;
+ return (packet[0] & 0x0C) != 0x08;
}
static void hgpk_process_packet(struct psmouse *psmouse)
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index eec375cd10e..29e686388a2 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -337,6 +337,20 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "2656"),
},
},
+ {
+ .ident = "Dell XPS M1530",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "XPS M1530"),
+ },
+ },
+ {
+ .ident = "Compal HEL80I",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "COMPAL"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HEL80I"),
+ },
+ },
{ }
};
diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h
index ca62ec639f8..677680e9f54 100644
--- a/drivers/input/tablet/wacom.h
+++ b/drivers/input/tablet/wacom.h
@@ -66,6 +66,7 @@
* - Support Intuos3 4x6
* v1.47 (pc) - Added support for Bamboo
* v1.48 (pc) - Added support for Bamboo1, BambooFun, and Cintiq 12WX
+ * v1.49 (pc) - Added support for USB Tablet PC (0x90, 0x93, and 0x9A)
*/
/*
@@ -86,7 +87,7 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v1.48"
+#define DRIVER_VERSION "v1.49"
#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
#define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver"
#define DRIVER_LICENSE "GPL"
@@ -103,15 +104,15 @@ struct wacom {
struct usb_device *usbdev;
struct usb_interface *intf;
struct urb *irq;
- struct wacom_wac * wacom_wac;
+ struct wacom_wac *wacom_wac;
struct mutex lock;
unsigned int open:1;
char phys[32];
};
struct wacom_combo {
- struct wacom * wacom;
- struct urb * urb;
+ struct wacom *wacom;
+ struct urb *urb;
};
extern int wacom_wac_irq(struct wacom_wac * wacom_wac, void * wcombo);
@@ -132,7 +133,7 @@ extern void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wa
extern void input_dev_bee(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
extern __u16 wacom_le16_to_cpu(unsigned char *data);
extern __u16 wacom_be16_to_cpu(unsigned char *data);
-extern struct wacom_features * get_wacom_feature(const struct usb_device_id *id);
-extern const struct usb_device_id * get_device_table(void);
+extern struct wacom_features *get_wacom_feature(const struct usb_device_id *id);
+extern const struct usb_device_id *get_device_table(void);
#endif
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index 09e227aa0d4..484496daa0f 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -14,8 +14,41 @@
#include "wacom.h"
#include "wacom_wac.h"
+/* defines to get HID report descriptor */
+#define HID_DEVICET_HID (USB_TYPE_CLASS | 0x01)
+#define HID_DEVICET_REPORT (USB_TYPE_CLASS | 0x02)
+#define HID_USAGE_UNDEFINED 0x00
+#define HID_USAGE_PAGE 0x05
+#define HID_USAGE_PAGE_DIGITIZER 0x0d
+#define HID_USAGE_PAGE_DESKTOP 0x01
+#define HID_USAGE 0x09
+#define HID_USAGE_X 0x30
+#define HID_USAGE_Y 0x31
+#define HID_USAGE_X_TILT 0x3d
+#define HID_USAGE_Y_TILT 0x3e
+#define HID_USAGE_FINGER 0x22
+#define HID_USAGE_STYLUS 0x20
+#define HID_COLLECTION 0xc0
+
+enum {
+ WCM_UNDEFINED = 0,
+ WCM_DESKTOP,
+ WCM_DIGITIZER,
+};
+
+struct hid_descriptor {
+ struct usb_descriptor_header header;
+ __le16 bcdHID;
+ u8 bCountryCode;
+ u8 bNumDescriptors;
+ u8 bDescriptorType;
+ __le16 wDescriptorLength;
+} __attribute__ ((packed));
+
+/* defines to get/set USB message */
#define USB_REQ_GET_REPORT 0x01
#define USB_REQ_SET_REPORT 0x09
+#define WAC_HID_FEATURE_REPORT 0x03
static int usb_get_report(struct usb_interface *intf, unsigned char type,
unsigned char id, void *buf, int size)
@@ -80,25 +113,21 @@ static void wacom_sys_irq(struct urb *urb)
void wacom_report_key(void *wcombo, unsigned int key_type, int key_data)
{
input_report_key(get_input_dev((struct wacom_combo *)wcombo), key_type, key_data);
- return;
}
void wacom_report_abs(void *wcombo, unsigned int abs_type, int abs_data)
{
input_report_abs(get_input_dev((struct wacom_combo *)wcombo), abs_type, abs_data);
- return;
}
void wacom_report_rel(void *wcombo, unsigned int rel_type, int rel_data)
{
input_report_rel(get_input_dev((struct wacom_combo *)wcombo), rel_type, rel_data);
- return;
}
void wacom_input_event(void *wcombo, unsigned int type, unsigned int code, int value)
{
input_event(get_input_dev((struct wacom_combo *)wcombo), type, code, value);
- return;
}
__u16 wacom_be16_to_cpu(unsigned char *data)
@@ -118,7 +147,6 @@ __u16 wacom_le16_to_cpu(unsigned char *data)
void wacom_input_sync(void *wcombo)
{
input_sync(get_input_dev((struct wacom_combo *)wcombo));
- return;
}
static int wacom_open(struct input_dev *dev)
@@ -160,7 +188,7 @@ static void wacom_close(struct input_dev *dev)
void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
{
- input_dev->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_1) |
+ input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_1) |
BIT_MASK(BTN_5);
input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
}
@@ -170,7 +198,7 @@ void input_dev_g4(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
input_dev->evbit[0] |= BIT_MASK(EV_MSC);
input_dev->mscbit[0] |= BIT_MASK(MSC_SERIAL);
input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_FINGER);
- input_dev->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_0) |
+ input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_0) |
BIT_MASK(BTN_4);
}
@@ -178,7 +206,7 @@ void input_dev_g(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
{
input_dev->evbit[0] |= BIT_MASK(EV_REL);
input_dev->relbit[0] |= BIT_MASK(REL_WHEEL);
- input_dev->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_LEFT) |
+ input_dev->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_LEFT) |
BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE);
input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER) |
BIT_MASK(BTN_TOOL_MOUSE) | BIT_MASK(BTN_STYLUS2);
@@ -188,7 +216,7 @@ void input_dev_g(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
void input_dev_i3s(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
{
input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_FINGER);
- input_dev->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_0) |
+ input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_0) |
BIT_MASK(BTN_1) | BIT_MASK(BTN_2) | BIT_MASK(BTN_3);
input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0);
input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
@@ -196,14 +224,14 @@ void input_dev_i3s(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
void input_dev_i3(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
{
- input_dev->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_4) |
+ input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_4) |
BIT_MASK(BTN_5) | BIT_MASK(BTN_6) | BIT_MASK(BTN_7);
input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0);
}
void input_dev_bee(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
{
- input_dev->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_8) | BIT_MASK(BTN_9);
+ input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_8) | BIT_MASK(BTN_9);
}
void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
@@ -211,7 +239,7 @@ void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
input_dev->evbit[0] |= BIT_MASK(EV_MSC) | BIT_MASK(EV_REL);
input_dev->mscbit[0] |= BIT_MASK(MSC_SERIAL);
input_dev->relbit[0] |= BIT_MASK(REL_WHEEL);
- input_dev->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_LEFT) |
+ input_dev->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_LEFT) |
BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE) |
BIT_MASK(BTN_SIDE) | BIT_MASK(BTN_EXTRA);
input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER) |
@@ -228,8 +256,7 @@ void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
{
- input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_STYLUS2) |
- BIT_MASK(BTN_TOOL_RUBBER);
+ input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_STYLUS2);
}
void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
@@ -237,15 +264,129 @@ void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER);
}
+static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hid_desc,
+ struct wacom_wac *wacom_wac)
+{
+ struct usb_device *dev = interface_to_usbdev(intf);
+ struct wacom_features *features = wacom_wac->features;
+ char limit = 0, result = 0;
+ int i = 0, usage = WCM_UNDEFINED, finger = 0, pen = 0;
+ unsigned char *report;
+
+ report = kzalloc(hid_desc->wDescriptorLength, GFP_KERNEL);
+ if (!report)
+ return -ENOMEM;
+
+ /* retrive report descriptors */
+ do {
+ result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+ USB_REQ_GET_DESCRIPTOR,
+ USB_RECIP_INTERFACE | USB_DIR_IN,
+ HID_DEVICET_REPORT << 8,
+ intf->altsetting[0].desc.bInterfaceNumber, /* interface */
+ report,
+ hid_desc->wDescriptorLength,
+ 5000); /* 5 secs */
+ } while (result < 0 && limit++ < 5);
+
+ if (result < 0)
+ goto out;
+
+ for (i = 0; i < hid_desc->wDescriptorLength; i++) {
+
+ switch (report[i]) {
+ case HID_USAGE_PAGE:
+ switch (report[i + 1]) {
+ case HID_USAGE_PAGE_DIGITIZER:
+ usage = WCM_DIGITIZER;
+ i++;
+ break;
+
+ case HID_USAGE_PAGE_DESKTOP:
+ usage = WCM_DESKTOP;
+ i++;
+ break;
+ }
+ break;
+
+ case HID_USAGE:
+ switch (report[i + 1]) {
+ case HID_USAGE_X:
+ if (usage == WCM_DESKTOP) {
+ if (finger) {
+ features->touch_x_max =
+ features->touch_y_max =
+ wacom_le16_to_cpu(&report[i + 3]);
+ features->x_max =
+ wacom_le16_to_cpu(&report[i + 6]);
+ i += 7;
+ } else if (pen) {
+ features->x_max =
+ wacom_le16_to_cpu(&report[i + 3]);
+ i += 4;
+ }
+ } else if (usage == WCM_DIGITIZER) {
+ /* max pressure isn't reported
+ features->pressure_max = (unsigned short)
+ (report[i+4] << 8 | report[i + 3]);
+ */
+ features->pressure_max = 255;
+ i += 4;
+ }
+ break;
+
+ case HID_USAGE_Y:
+ if (usage == WCM_DESKTOP)
+ features->y_max =
+ wacom_le16_to_cpu(&report[i + 3]);
+ i += 4;
+ break;
+
+ case HID_USAGE_FINGER:
+ finger = 1;
+ i++;
+ break;
+
+ case HID_USAGE_STYLUS:
+ pen = 1;
+ i++;
+ break;
+
+ case HID_USAGE_UNDEFINED:
+ if (usage == WCM_DESKTOP && finger) /* capacity */
+ features->pressure_max =
+ wacom_le16_to_cpu(&report[i + 3]);
+ i += 4;
+ break;
+ }
+ break;
+
+ case HID_COLLECTION:
+ /* reset UsagePage ans Finger */
+ finger = usage = 0;
+ break;
+ }
+ }
+
+ result = 0;
+
+ out:
+ kfree(report);
+ return result;
+}
+
static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
struct usb_device *dev = interface_to_usbdev(intf);
+ struct usb_host_interface *interface = intf->cur_altsetting;
struct usb_endpoint_descriptor *endpoint;
struct wacom *wacom;
struct wacom_wac *wacom_wac;
+ struct wacom_features *features;
struct input_dev *input_dev;
int error = -ENOMEM;
char rep_data[2], limit = 0;
+ struct hid_descriptor *hid_desc;
wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL);
wacom_wac = kzalloc(sizeof(struct wacom_wac), GFP_KERNEL);
@@ -268,8 +409,8 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
usb_make_path(dev, wacom->phys, sizeof(wacom->phys));
strlcat(wacom->phys, "/input0", sizeof(wacom->phys));
- wacom_wac->features = get_wacom_feature(id);
- BUG_ON(wacom_wac->features->pktlen > 10);
+ wacom_wac->features = features = get_wacom_feature(id);
+ BUG_ON(features->pktlen > 10);
input_dev->name = wacom_wac->features->name;
wacom->wacom_wac = wacom_wac;
@@ -282,18 +423,37 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
input_dev->open = wacom_open;
input_dev->close = wacom_close;
+ endpoint = &intf->cur_altsetting->endpoint[0].desc;
+
+ /* TabletPC need to retrieve the physical and logical maximum from report descriptor */
+ if (wacom_wac->features->type == TABLETPC) {
+ if (usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc)) {
+ if (usb_get_extra_descriptor(&interface->endpoint[0],
+ HID_DEVICET_REPORT, &hid_desc)) {
+ printk("wacom: can not retrive extra class descriptor\n");
+ goto fail2;
+ }
+ }
+ error = wacom_parse_hid(intf, hid_desc, wacom_wac);
+ if (error)
+ goto fail2;
+ }
+
input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_PEN) |
BIT_MASK(BTN_TOUCH) | BIT_MASK(BTN_STYLUS);
- input_set_abs_params(input_dev, ABS_X, 0, wacom_wac->features->x_max, 4, 0);
- input_set_abs_params(input_dev, ABS_Y, 0, wacom_wac->features->y_max, 4, 0);
- input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom_wac->features->pressure_max, 0, 0);
+ input_set_abs_params(input_dev, ABS_X, 0, features->x_max, 4, 0);
+ input_set_abs_params(input_dev, ABS_Y, 0, features->y_max, 4, 0);
+ input_set_abs_params(input_dev, ABS_PRESSURE, 0, features->pressure_max, 0, 0);
+ if (features->type == TABLETPC) {
+ input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_DOUBLETAP);
+ input_set_abs_params(input_dev, ABS_RX, 0, features->touch_x_max, 4, 0);
+ input_set_abs_params(input_dev, ABS_RY, 0, features->touch_y_max, 4, 0);
+ }
input_dev->absbit[BIT_WORD(ABS_MISC)] |= BIT_MASK(ABS_MISC);
wacom_init_input_dev(input_dev, wacom_wac);
- endpoint = &intf->cur_altsetting->endpoint[0].desc;
-
usb_fill_int_urb(wacom->irq, dev,
usb_rcvintpipe(dev, endpoint->bEndpointAddress),
wacom_wac->data, wacom_wac->features->pktlen,
@@ -305,13 +465,22 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
if (error)
goto fail3;
- /* Ask the tablet to report tablet data. Repeat until it succeeds */
- do {
- rep_data[0] = 2;
- rep_data[1] = 2;
- usb_set_report(intf, 3, 2, rep_data, 2);
- usb_get_report(intf, 3, 2, rep_data, 2);
- } while (rep_data[1] != 2 && limit++ < 5);
+ /*
+ * Ask the tablet to report tablet data if it is not a Tablet PC.
+ * Repeat until it succeeds
+ */
+ if (wacom_wac->features->type != TABLETPC) {
+ do {
+ rep_data[0] = 2;
+ rep_data[1] = 2;
+ error = usb_set_report(intf, WAC_HID_FEATURE_REPORT,
+ 2, rep_data, 2);
+ if (error >= 0)
+ error = usb_get_report(intf,
+ WAC_HID_FEATURE_REPORT, 2,
+ rep_data, 2);
+ } while ((error < 0 || rep_data[1] != 2) && limit++ < 5);
+ }
usb_set_intfdata(intf, wacom);
return 0;
@@ -333,7 +502,8 @@ static void wacom_disconnect(struct usb_interface *intf)
usb_kill_urb(wacom->irq);
input_unregister_device(wacom->dev);
usb_free_urb(wacom->irq);
- usb_buffer_free(interface_to_usbdev(intf), 10, wacom->wacom_wac->data, wacom->data_dma);
+ usb_buffer_free(interface_to_usbdev(intf), 10,
+ wacom->wacom_wac->data, wacom->data_dma);
kfree(wacom->wacom_wac);
kfree(wacom);
}
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index bf3d9a8b2c1..8dc8d1e59be 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -535,31 +535,147 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo)
return 1;
}
+int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo)
+{
+ char *data = wacom->data;
+ int prox = 0, pressure;
+ static int stylusInProx, touchInProx = 1, touchOut;
+ struct urb *urb = ((struct wacom_combo *)wcombo)->urb;
+
+ dbg("wacom_tpc_irq: received report #%d", data[0]);
+
+ if (urb->actual_length == 5 || data[0] == 6) { /* Touch data */
+ if (urb->actual_length == 5) { /* with touch */
+ prox = data[0] & 0x03;
+ } else { /* with capacity */
+ prox = data[1] & 0x03;
+ }
+
+ if (!stylusInProx) { /* stylus not in prox */
+ if (prox) {
+ if (touchInProx) {
+ wacom->tool[1] = BTN_TOOL_DOUBLETAP;
+ wacom->id[0] = TOUCH_DEVICE_ID;
+ if (urb->actual_length != 5) {
+ wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2]));
+ wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4]));
+ wacom_report_abs(wcombo, ABS_PRESSURE, wacom_le16_to_cpu(&data[6]));
+ wacom_report_key(wcombo, BTN_TOUCH, wacom_le16_to_cpu(&data[6]));
+ } else {
+ wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[1]));
+ wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[3]));
+ wacom_report_key(wcombo, BTN_TOUCH, 1);
+ }
+ wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]);
+ wacom_report_key(wcombo, wacom->tool[1], prox & 0x01);
+ touchOut = 1;
+ return 1;
+ }
+ } else {
+ wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]);
+ wacom_report_key(wcombo, wacom->tool[1], prox & 0x01);
+ wacom_report_key(wcombo, BTN_TOUCH, 0);
+ touchOut = 0;
+ touchInProx = 1;
+ return 1;
+ }
+ } else if (touchOut || !prox) { /* force touch out-prox */
+ wacom_report_abs(wcombo, ABS_MISC, TOUCH_DEVICE_ID);
+ wacom_report_key(wcombo, BTN_TOUCH, 0);
+ touchOut = 0;
+ touchInProx = 1;
+ return 1;
+ }
+ } else if (data[0] == 2) { /* Penabled */
+ prox = data[1] & 0x20;
+
+ touchInProx = 0;
+
+ wacom->id[0] = ERASER_DEVICE_ID;
+
+ /*
+ * if going from out of proximity into proximity select between the eraser
+ * and the pen based on the state of the stylus2 button, choose eraser if
+ * pressed else choose pen. if not a proximity change from out to in, send
+ * an out of proximity for previous tool then a in for new tool.
+ */
+ if (prox) { /* in prox */
+ if (!wacom->tool[0]) {
+ /* Going into proximity select tool */
+ wacom->tool[1] = (data[1] & 0x08) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
+ if (wacom->tool[1] == BTN_TOOL_PEN)
+ wacom->id[0] = STYLUS_DEVICE_ID;
+ } else if (wacom->tool[1] == BTN_TOOL_RUBBER && !(data[1] & 0x08)) {
+ /*
+ * was entered with stylus2 pressed
+ * report out proximity for previous tool
+ */
+ wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]);
+ wacom_report_key(wcombo, wacom->tool[1], 0);
+ wacom_input_sync(wcombo);
+
+ /* set new tool */
+ wacom->tool[1] = BTN_TOOL_PEN;
+ wacom->id[0] = STYLUS_DEVICE_ID;
+ return 0;
+ }
+ if (wacom->tool[1] != BTN_TOOL_RUBBER) {
+ /* Unknown tool selected default to pen tool */
+ wacom->tool[1] = BTN_TOOL_PEN;
+ wacom->id[0] = STYLUS_DEVICE_ID;
+ }
+ wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02);
+ wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x10);
+ wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2]));
+ wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4]));
+ pressure = ((data[7] & 0x01) << 8) | data[6];
+ if (pressure < 0)
+ pressure = wacom->features->pressure_max + pressure + 1;
+ wacom_report_abs(wcombo, ABS_PRESSURE, pressure);
+ wacom_report_key(wcombo, BTN_TOUCH, pressure);
+ } else {
+ wacom_report_abs(wcombo, ABS_PRESSURE, 0);
+ wacom_report_key(wcombo, BTN_STYLUS, 0);
+ wacom_report_key(wcombo, BTN_STYLUS2, 0);
+ wacom_report_key(wcombo, BTN_TOUCH, 0);
+ }
+ wacom_report_key(wcombo, wacom->tool[1], prox);
+ wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]);
+ stylusInProx = prox;
+ wacom->tool[0] = prox;
+ return 1;
+ }
+ return 0;
+}
+
int wacom_wac_irq(struct wacom_wac *wacom_wac, void *wcombo)
{
switch (wacom_wac->features->type) {
case PENPARTNER:
- return (wacom_penpartner_irq(wacom_wac, wcombo));
- break;
+ return wacom_penpartner_irq(wacom_wac, wcombo);
+
case PL:
- return (wacom_pl_irq(wacom_wac, wcombo));
- break;
+ return wacom_pl_irq(wacom_wac, wcombo);
+
case WACOM_G4:
case GRAPHIRE:
case WACOM_MO:
- return (wacom_graphire_irq(wacom_wac, wcombo));
- break;
+ return wacom_graphire_irq(wacom_wac, wcombo);
+
case PTU:
- return (wacom_ptu_irq(wacom_wac, wcombo));
- break;
+ return wacom_ptu_irq(wacom_wac, wcombo);
+
case INTUOS:
case INTUOS3S:
case INTUOS3:
case INTUOS3L:
case CINTIQ:
case WACOM_BEE:
- return (wacom_intuos_irq(wacom_wac, wcombo));
- break;
+ return wacom_intuos_irq(wacom_wac, wcombo);
+
+ case TABLETPC:
+ return wacom_tpc_irq(wacom_wac, wcombo);
+
default:
return 0;
}
@@ -586,13 +702,15 @@ void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_w
/* fall through */
case INTUOS3S:
input_dev_i3s(input_dev, wacom_wac);
+ /* fall through */
case INTUOS:
input_dev_i(input_dev, wacom_wac);
break;
case PL:
case PTU:
+ case TABLETPC:
input_dev_pl(input_dev, wacom_wac);
- break;
+ /* fall through */
case PENPARTNER:
input_dev_pt(input_dev, wacom_wac);
break;
@@ -611,6 +729,7 @@ static struct wacom_features wacom_features[] = {
{ "Wacom Graphire4 6x8", 8, 16704, 12064, 511, 63, WACOM_G4 },
{ "Wacom BambooFun 4x5", 9, 14760, 9225, 511, 63, WACOM_MO },
{ "Wacom BambooFun 6x8", 9, 21648, 13530, 511, 63, WACOM_MO },
+ { "Wacom Bamboo1 Medium",8, 16704, 12064, 511, 63, GRAPHIRE },
{ "Wacom Volito", 8, 5104, 3712, 511, 63, GRAPHIRE },
{ "Wacom PenStation2", 8, 3250, 2320, 255, 63, GRAPHIRE },
{ "Wacom Volito2 4x5", 8, 5104, 3712, 511, 63, GRAPHIRE },
@@ -650,6 +769,10 @@ static struct wacom_features wacom_features[] = {
{ "Wacom Cintiq 21UX", 10, 87200, 65600, 1023, 63, CINTIQ },
{ "Wacom Cintiq 20WSX", 10, 86680, 54180, 1023, 63, WACOM_BEE },
{ "Wacom Cintiq 12WX", 10, 53020, 33440, 1023, 63, WACOM_BEE },
+ { "Wacom DTU1931", 8, 37832, 30305, 511, 0, PL },
+ { "Wacom ISDv4 90", 8, 26202, 16325, 255, 0, TABLETPC },
+ { "Wacom ISDv4 93", 8, 26202, 16325, 255, 0, TABLETPC },
+ { "Wacom ISDv4 9A", 8, 26202, 16325, 255, 0, TABLETPC },
{ "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 31, INTUOS },
{ }
};
@@ -665,6 +788,7 @@ static struct usb_device_id wacom_ids[] = {
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x16) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x17) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x18) },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x19) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x60) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x61) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x62) },
@@ -704,18 +828,26 @@ static struct usb_device_id wacom_ids[] = {
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x3F) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC5) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC6) },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC7) },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x90) },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x93) },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x9A) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) },
{ }
};
-const struct usb_device_id * get_device_table(void) {
- const struct usb_device_id * id_table = wacom_ids;
+const struct usb_device_id *get_device_table(void)
+{
+ const struct usb_device_id *id_table = wacom_ids;
+
return id_table;
}
-struct wacom_features * get_wacom_feature(const struct usb_device_id * id) {
+struct wacom_features * get_wacom_feature(const struct usb_device_id *id)
+{
int index = id - wacom_ids;
struct wacom_features *wf = &wacom_features[index];
+
return wf;
}
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h
index 3342bc05847..f9c8b69673b 100644
--- a/drivers/input/tablet/wacom_wac.h
+++ b/drivers/input/tablet/wacom_wac.h
@@ -10,6 +10,7 @@
#define WACOM_WAC_H
#define STYLUS_DEVICE_ID 0x02
+#define TOUCH_DEVICE_ID 0x03
#define CURSOR_DEVICE_ID 0x06
#define ERASER_DEVICE_ID 0x0A
#define PAD_DEVICE_ID 0x0F
@@ -27,6 +28,7 @@ enum {
CINTIQ,
WACOM_BEE,
WACOM_MO,
+ TABLETPC,
MAX_TYPE
};
@@ -38,6 +40,8 @@ struct wacom_features {
int pressure_max;
int distance_max;
int type;
+ int touch_x_max;
+ int touch_y_max;
};
struct wacom_wac {
diff --git a/drivers/input/touchscreen/elo.c b/drivers/input/touchscreen/elo.c
index d20689cdbd5..8f38c5e55ce 100644
--- a/drivers/input/touchscreen/elo.c
+++ b/drivers/input/touchscreen/elo.c
@@ -262,7 +262,7 @@ static int elo_setup_10(struct elo *elo)
input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0);
printk(KERN_INFO "elo: %sTouch touchscreen, fw: %02x.%02x, "
- "features: %x02x, controller: 0x%02x\n",
+ "features: 0x%02x, controller: 0x%02x\n",
elo_types[(packet[1] -'0') & 0x03],
packet[5], packet[4], packet[3], packet[7]);
diff --git a/drivers/input/xen-kbdfront.c b/drivers/input/xen-kbdfront.c
index 3ab6362f043..928d2ed8865 100644
--- a/drivers/input/xen-kbdfront.c
+++ b/drivers/input/xen-kbdfront.c
@@ -323,7 +323,7 @@ static struct xenbus_device_id xenkbd_ids[] = {
{ "" }
};
-static struct xenbus_driver xenkbd = {
+static struct xenbus_driver xenkbd_driver = {
.name = "vkbd",
.owner = THIS_MODULE,
.ids = xenkbd_ids,
@@ -342,12 +342,12 @@ static int __init xenkbd_init(void)
if (xen_initial_domain())
return -ENODEV;
- return xenbus_register_frontend(&xenkbd);
+ return xenbus_register_frontend(&xenkbd_driver);
}
static void __exit xenkbd_cleanup(void)
{
- xenbus_unregister_driver(&xenkbd);
+ xenbus_unregister_driver(&xenkbd_driver);
}
module_init(xenkbd_init);
diff --git a/drivers/isdn/hardware/avm/b1isa.c b/drivers/isdn/hardware/avm/b1isa.c
index 1e288eeb5e2..6461a32bc83 100644
--- a/drivers/isdn/hardware/avm/b1isa.c
+++ b/drivers/isdn/hardware/avm/b1isa.c
@@ -233,10 +233,8 @@ static void __exit b1isa_exit(void)
int i;
for (i = 0; i < MAX_CARDS; i++) {
- if (!io[i])
- break;
-
- b1isa_remove(&isa_dev[i]);
+ if (isa_dev[i].resource[0].start)
+ b1isa_remove(&isa_dev[i]);
}
unregister_capi_driver(&capi_driver_b1isa);
}
diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c
index 84d75a3f5d1..ded9d0baf60 100644
--- a/drivers/isdn/hisax/config.c
+++ b/drivers/isdn/hisax/config.c
@@ -1213,7 +1213,7 @@ static void HiSax_shiftcards(int idx)
memcpy(&cards[i], &cards[i + 1], sizeof(cards[i]));
}
-static int HiSax_inithardware(int *busy_flag)
+static int __init HiSax_inithardware(int *busy_flag)
{
int foundcards = 0;
int i = 0;
@@ -1542,7 +1542,9 @@ static void __exit HiSax_exit(void)
printk(KERN_INFO "HiSax module removed\n");
}
-int hisax_init_pcmcia(void *pcm_iob, int *busy_flag, struct IsdnCard *card)
+#ifdef CONFIG_HOTPLUG
+
+int __devinit hisax_init_pcmcia(void *pcm_iob, int *busy_flag, struct IsdnCard *card)
{
u_char ids[16];
int ret = -1;
@@ -1563,6 +1565,8 @@ error:
}
EXPORT_SYMBOL(hisax_init_pcmcia);
+#endif
+
EXPORT_SYMBOL(HiSax_closecard);
#include "hisax_if.h"
@@ -1580,6 +1584,11 @@ static void hisax_bc_close(struct BCState *bcs);
static void hisax_bh(struct work_struct *work);
static void EChannel_proc_rcv(struct hisax_d_if *d_if);
+static int hisax_setup_card_dynamic(struct IsdnCard *card)
+{
+ return 2;
+}
+
int hisax_register(struct hisax_d_if *hisax_d_if, struct hisax_b_if *b_if[],
char *name, int protocol)
{
@@ -1599,7 +1608,8 @@ int hisax_register(struct hisax_d_if *hisax_d_if, struct hisax_b_if *b_if[],
cards[i].protocol = protocol;
sprintf(id, "%s%d", name, i);
nrcards++;
- retval = checkcard(i, id, NULL, hisax_d_if->owner, hisax_cs_setup_card);
+ retval = checkcard(i, id, NULL, hisax_d_if->owner,
+ hisax_setup_card_dynamic);
if (retval == 0) { // yuck
cards[i].typ = 0;
nrcards--;
diff --git a/drivers/isdn/hysdn/hysdn_net.c b/drivers/isdn/hysdn/hysdn_net.c
index cfa8fa5e44a..3f2a0a20c19 100644
--- a/drivers/isdn/hysdn/hysdn_net.c
+++ b/drivers/isdn/hysdn/hysdn_net.c
@@ -83,12 +83,12 @@ net_open(struct net_device *dev)
/* Fill in the MAC-level header (if not already set) */
if (!card->mac_addr[0]) {
- for (i = 0; i < ETH_ALEN - sizeof(unsigned long); i++)
+ for (i = 0; i < ETH_ALEN; i++)
dev->dev_addr[i] = 0xfc;
if ((in_dev = dev->ip_ptr) != NULL) {
struct in_ifaddr *ifa = in_dev->ifa_list;
if (ifa != NULL)
- memcpy(dev->dev_addr + (ETH_ALEN - sizeof(unsigned long)), &ifa->ifa_local, sizeof(unsigned long));
+ memcpy(dev->dev_addr + (ETH_ALEN - sizeof(ifa->ifa_local)), &ifa->ifa_local, sizeof(ifa->ifa_local));
}
} else
memcpy(dev->dev_addr, card->mac_addr, ETH_ALEN);
diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c
index bb904a0a98b..1bfc55d7a26 100644
--- a/drivers/isdn/i4l/isdn_net.c
+++ b/drivers/isdn/i4l/isdn_net.c
@@ -1641,8 +1641,10 @@ isdn_net_ciscohdlck_slarp_send_reply(isdn_net_local *lp)
/* slarp reply, send own ip/netmask; if values are nonsense remote
* should think we are unable to provide it with an address via SLARP */
p += put_u32(p, CISCO_SLARP_REPLY);
- p += put_u32(p, addr); // address
- p += put_u32(p, mask); // netmask
+ *(__be32 *)p = addr; // address
+ p += 4;
+ *(__be32 *)p = mask; // netmask
+ p += 4;
p += put_u16(p, 0); // unused
isdn_net_write_super(lp, skb);
diff --git a/drivers/macintosh/rack-meter.c b/drivers/macintosh/rack-meter.c
index 2c21d4f25cc..a98ab72adf9 100644
--- a/drivers/macintosh/rack-meter.c
+++ b/drivers/macintosh/rack-meter.c
@@ -288,7 +288,7 @@ static void __devexit rackmeter_stop_cpu_sniffer(struct rackmeter *rm)
cancel_rearming_delayed_work(&rm->cpu[1].sniffer);
}
-static int rackmeter_setup(struct rackmeter *rm)
+static int __devinit rackmeter_setup(struct rackmeter *rm)
{
pr_debug("rackmeter: setting up i2s..\n");
rackmeter_setup_i2s(rm);
@@ -582,12 +582,12 @@ static struct of_device_id rackmeter_match[] = {
{ }
};
-static struct macio_driver rackmeter_drv = {
+static struct macio_driver rackmeter_driver = {
.name = "rackmeter",
.owner = THIS_MODULE,
.match_table = rackmeter_match,
.probe = rackmeter_probe,
- .remove = rackmeter_remove,
+ .remove = __devexit_p(rackmeter_remove),
.shutdown = rackmeter_shutdown,
};
@@ -596,14 +596,14 @@ static int __init rackmeter_init(void)
{
pr_debug("rackmeter_init()\n");
- return macio_register_driver(&rackmeter_drv);
+ return macio_register_driver(&rackmeter_driver);
}
static void __exit rackmeter_exit(void)
{
pr_debug("rackmeter_exit()\n");
- macio_unregister_driver(&rackmeter_drv);
+ macio_unregister_driver(&rackmeter_driver);
}
module_init(rackmeter_init);
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index ac89a5deaca..ab7c8e4a61f 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -208,16 +208,19 @@ static void bitmap_checkfree(struct bitmap *bitmap, unsigned long page)
*/
/* IO operations when bitmap is stored near all superblocks */
-static struct page *read_sb_page(mddev_t *mddev, long offset, unsigned long index)
+static struct page *read_sb_page(mddev_t *mddev, long offset,
+ struct page *page,
+ unsigned long index, int size)
{
/* choose a good rdev and read the page from there */
mdk_rdev_t *rdev;
struct list_head *tmp;
- struct page *page = alloc_page(GFP_KERNEL);
sector_t target;
if (!page)
+ page = alloc_page(GFP_KERNEL);
+ if (!page)
return ERR_PTR(-ENOMEM);
rdev_for_each(rdev, tmp, mddev) {
@@ -227,7 +230,9 @@ static struct page *read_sb_page(mddev_t *mddev, long offset, unsigned long inde
target = rdev->sb_start + offset + index * (PAGE_SIZE/512);
- if (sync_page_io(rdev->bdev, target, PAGE_SIZE, page, READ)) {
+ if (sync_page_io(rdev->bdev, target,
+ roundup(size, bdev_hardsect_size(rdev->bdev)),
+ page, READ)) {
page->index = index;
attach_page_buffers(page, NULL); /* so that free_buffer will
* quietly no-op */
@@ -544,7 +549,9 @@ static int bitmap_read_sb(struct bitmap *bitmap)
bitmap->sb_page = read_page(bitmap->file, 0, bitmap, bytes);
} else {
- bitmap->sb_page = read_sb_page(bitmap->mddev, bitmap->offset, 0);
+ bitmap->sb_page = read_sb_page(bitmap->mddev, bitmap->offset,
+ NULL,
+ 0, sizeof(bitmap_super_t));
}
if (IS_ERR(bitmap->sb_page)) {
err = PTR_ERR(bitmap->sb_page);
@@ -957,11 +964,16 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
*/
page = bitmap->sb_page;
offset = sizeof(bitmap_super_t);
+ read_sb_page(bitmap->mddev, bitmap->offset,
+ page,
+ index, count);
} else if (file) {
page = read_page(file, index, bitmap, count);
offset = 0;
} else {
- page = read_sb_page(bitmap->mddev, bitmap->offset, index);
+ page = read_sb_page(bitmap->mddev, bitmap->offset,
+ NULL,
+ index, count);
offset = 0;
}
if (IS_ERR(page)) { /* read error */
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index 4840733cd90..3d7f4923cd1 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -441,13 +441,13 @@ static void process_queued_ios(struct work_struct *work)
__choose_pgpath(m);
pgpath = m->current_pgpath;
- m->pgpath_to_activate = m->current_pgpath;
if ((pgpath && !m->queue_io) ||
(!pgpath && !m->queue_if_no_path))
must_queue = 0;
- if (m->pg_init_required && !m->pg_init_in_progress) {
+ if (m->pg_init_required && !m->pg_init_in_progress && pgpath) {
+ m->pgpath_to_activate = pgpath;
m->pg_init_count++;
m->pg_init_required = 0;
m->pg_init_in_progress = 1;
@@ -708,6 +708,10 @@ static int parse_hw_handler(struct arg_set *as, struct multipath *m)
m->hw_handler_name = NULL;
return -EINVAL;
}
+
+ if (hw_argc > 1)
+ DMWARN("Ignoring user-specified arguments for "
+ "hardware handler \"%s\"", m->hw_handler_name);
consume(as, hw_argc - 1);
return 0;
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index 9d7b53ed75b..ec43f9fa4b2 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -1032,6 +1032,7 @@ static void mirror_dtr(struct dm_target *ti)
del_timer_sync(&ms->timer);
flush_workqueue(ms->kmirrord_wq);
+ flush_scheduled_work();
dm_kcopyd_client_destroy(ms->kcopyd_client);
destroy_workqueue(ms->kmirrord_wq);
free_context(ms, ti, ms->nr_mirrors);
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c
index a2d068dbe9e..9e4ef88d421 100644
--- a/drivers/md/dm-stripe.c
+++ b/drivers/md/dm-stripe.c
@@ -320,8 +320,10 @@ int __init dm_stripe_init(void)
int r;
r = dm_register_target(&stripe_target);
- if (r < 0)
+ if (r < 0) {
DMWARN("target registration failed");
+ return r;
+ }
kstriped = create_singlethread_workqueue("kstriped");
if (!kstriped) {
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index a63161aec48..04e5fd742c2 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -668,7 +668,7 @@ static void check_for_valid_limits(struct io_restrictions *rs)
if (!rs->max_segment_size)
rs->max_segment_size = MAX_SEGMENT_SIZE;
if (!rs->seg_boundary_mask)
- rs->seg_boundary_mask = -1;
+ rs->seg_boundary_mask = BLK_SEG_BOUNDARY_MASK;
if (!rs->bounce_pfn)
rs->bounce_pfn = -1;
}
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 6963ad14840..c99e4728ff4 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -375,7 +375,7 @@ static void start_io_acct(struct dm_io *io)
dm_disk(md)->part0.in_flight = atomic_inc_return(&md->pending);
}
-static int end_io_acct(struct dm_io *io)
+static void end_io_acct(struct dm_io *io)
{
struct mapped_device *md = io->md;
struct bio *bio = io->bio;
@@ -391,7 +391,9 @@ static int end_io_acct(struct dm_io *io)
dm_disk(md)->part0.in_flight = pending =
atomic_dec_return(&md->pending);
- return !pending;
+ /* nudge anyone waiting on suspend queue */
+ if (!pending)
+ wake_up(&md->wait);
}
/*
@@ -499,9 +501,7 @@ static void dec_pending(struct dm_io *io, int error)
spin_unlock_irqrestore(&io->md->pushback_lock, flags);
}
- if (end_io_acct(io))
- /* nudge anyone waiting on suspend queue */
- wake_up(&io->md->wait);
+ end_io_acct(io);
if (io->error != DM_ENDIO_REQUEUE) {
blk_add_trace_bio(io->md->queue, io->bio,
@@ -937,16 +937,24 @@ static void dm_unplug_all(struct request_queue *q)
static int dm_any_congested(void *congested_data, int bdi_bits)
{
- int r;
- struct mapped_device *md = (struct mapped_device *) congested_data;
- struct dm_table *map = dm_get_table(md);
+ int r = bdi_bits;
+ struct mapped_device *md = congested_data;
+ struct dm_table *map;
- if (!map || test_bit(DMF_BLOCK_IO, &md->flags))
- r = bdi_bits;
- else
- r = dm_table_any_congested(map, bdi_bits);
+ atomic_inc(&md->pending);
+
+ if (!test_bit(DMF_BLOCK_IO, &md->flags)) {
+ map = dm_get_table(md);
+ if (map) {
+ r = dm_table_any_congested(map, bdi_bits);
+ dm_table_put(map);
+ }
+ }
+
+ if (!atomic_dec_return(&md->pending))
+ /* nudge anyone waiting on suspend queue */
+ wake_up(&md->wait);
- dm_table_put(map);
return r;
}
diff --git a/drivers/media/dvb/b2c2/Kconfig b/drivers/media/dvb/b2c2/Kconfig
index 73dc2ee9b01..b34301d56cd 100644
--- a/drivers/media/dvb/b2c2/Kconfig
+++ b/drivers/media/dvb/b2c2/Kconfig
@@ -9,11 +9,11 @@ config DVB_B2C2_FLEXCOP
select DVB_STV0297 if !DVB_FE_CUSTOMISE
select DVB_BCM3510 if !DVB_FE_CUSTOMISE
select DVB_LGDT330X if !DVB_FE_CUSTOMISE
- select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE
select DVB_S5H1420 if !DVB_FE_CUSTOMISE
select DVB_TUNER_ITD1000 if !DVB_FE_CUSTOMISE
select DVB_ISL6421 if !DVB_FE_CUSTOMISE
select DVB_CX24123 if !DVB_FE_CUSTOMISE
+ select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE
help
Support for the digital TV receiver chip made by B2C2 Inc. included in
Technisats PCI cards and USB boxes.
diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
index a127a4175c4..5cded370854 100644
--- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
+++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
@@ -628,12 +628,14 @@ int flexcop_frontend_init(struct flexcop_device *fc)
}
/* try the cable dvb (stv0297) */
+ fc->fc_i2c_adap[0].no_base_addr = 1;
fc->fe = dvb_attach(stv0297_attach, &alps_tdee4_stv0297_config, i2c);
if (fc->fe != NULL) {
fc->dev_type = FC_CABLE;
fc->fe->ops.tuner_ops.set_params = alps_tdee4_stv0297_tuner_set_params;
goto fe_found;
}
+ fc->fc_i2c_adap[0].no_base_addr = 0;
/* try the sky v2.3 (vp310/Samsung tbdu18132(tsa5059)) */
fc->fe = dvb_attach(mt312_attach,
diff --git a/drivers/media/dvb/b2c2/flexcop-i2c.c b/drivers/media/dvb/b2c2/flexcop-i2c.c
index 43a112ec6d4..f13783f08f0 100644
--- a/drivers/media/dvb/b2c2/flexcop-i2c.c
+++ b/drivers/media/dvb/b2c2/flexcop-i2c.c
@@ -47,9 +47,13 @@ static int flexcop_i2c_read4(struct flexcop_i2c_adapter *i2c,
int len = r100.tw_sm_c_100.total_bytes, /* remember total_bytes is buflen-1 */
ret;
- r100.tw_sm_c_100.no_base_addr_ack_error = i2c->no_base_addr;
ret = flexcop_i2c_operation(i2c->fc, &r100);
if (ret != 0) {
+ deb_i2c("Retrying operation\n");
+ r100.tw_sm_c_100.no_base_addr_ack_error = i2c->no_base_addr;
+ ret = flexcop_i2c_operation(i2c->fc, &r100);
+ }
+ if (ret != 0) {
deb_i2c("read failed. %d\n", ret);
return ret;
}
diff --git a/drivers/media/dvb/bt8xx/Kconfig b/drivers/media/dvb/bt8xx/Kconfig
index 7e9c090fc04..27edb0ece58 100644
--- a/drivers/media/dvb/bt8xx/Kconfig
+++ b/drivers/media/dvb/bt8xx/Kconfig
@@ -8,7 +8,7 @@ config DVB_BT8XX
select DVB_OR51211 if !DVB_FE_CUSTOMISE
select DVB_LGDT330X if !DVB_FE_CUSTOMISE
select DVB_ZL10353 if !DVB_FE_CUSTOMISE
- select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE
+ select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE
help
Support for PCI cards based on the Bt8xx PCI bridge. Examples are
the Nebula cards, the Pinnacle PCTV cards, the Twinhan DST cards,
diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c
index 14e627ef646..c1d92f838ca 100644
--- a/drivers/media/dvb/dm1105/dm1105.c
+++ b/drivers/media/dvb/dm1105/dm1105.c
@@ -376,7 +376,7 @@ static void dm1105dvb_dma_unmap(struct dm1105dvb *dm1105dvb)
pci_free_consistent(dm1105dvb->pdev, 6*DM1105_DMA_BYTES, dm1105dvb->ts_buf, dm1105dvb->dma_addr);
}
-static void __devinit dm1105dvb_enable_irqs(struct dm1105dvb *dm1105dvb)
+static void dm1105dvb_enable_irqs(struct dm1105dvb *dm1105dvb)
{
outb(INTMAK_ALLMASK, dm_io_mem(DM1105_INTMAK));
outb(1, dm_io_mem(DM1105_CR));
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
index 8557bf12cfb..7a421e9dba5 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -585,6 +585,8 @@ restart:
if (fe->ops.set_voltage)
fe->ops.set_voltage(fe, SEC_VOLTAGE_OFF);
if (fe->ops.tuner_ops.sleep) {
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
fe->ops.tuner_ops.sleep(fe);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
@@ -934,7 +936,8 @@ void dtv_property_dump(struct dtv_property *tvp)
int is_legacy_delivery_system(fe_delivery_system_t s)
{
if((s == SYS_UNDEFINED) || (s == SYS_DVBC_ANNEX_AC) ||
- (s == SYS_DVBC_ANNEX_B) || (s == SYS_DVBT) || (s == SYS_DVBS))
+ (s == SYS_DVBC_ANNEX_B) || (s == SYS_DVBT) || (s == SYS_DVBS) ||
+ (s == SYS_ATSC))
return 1;
return 0;
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig
index 62b68c291d9..49f7b20c25d 100644
--- a/drivers/media/dvb/dvb-usb/Kconfig
+++ b/drivers/media/dvb/dvb-usb/Kconfig
@@ -24,8 +24,8 @@ config DVB_USB_A800
tristate "AVerMedia AverTV DVB-T USB 2.0 (A800)"
depends on DVB_USB
select DVB_DIB3000MC
- select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE
select DVB_PLL if !DVB_FE_CUSTOMISE
+ select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE
help
Say Y here to support the AVerMedia AverTV DVB-T USB 2.0 (A800) receiver.
@@ -34,7 +34,7 @@ config DVB_USB_DIBUSB_MB
depends on DVB_USB
select DVB_PLL if !DVB_FE_CUSTOMISE
select DVB_DIB3000MB
- select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE
+ select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE
help
Support for USB 1.1 and 2.0 DVB-T receivers based on reference designs made by
DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-B demodulator.
@@ -55,7 +55,7 @@ config DVB_USB_DIBUSB_MC
tristate "DiBcom USB DVB-T devices (based on the DiB3000M-C/P) (see help for device list)"
depends on DVB_USB
select DVB_DIB3000MC
- select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE
+ select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE
help
Support for USB2.0 DVB-T receivers based on reference designs made by
DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-C/P demodulator.
@@ -73,11 +73,11 @@ config DVB_USB_DIB0700
select DVB_DIB7000M
select DVB_DIB3000MC
select DVB_S5H1411 if !DVB_FE_CUSTOMISE
- select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE
- select MEDIA_TUNER_MT2266 if !DVB_FE_CUSTOMISE
- select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMISE
- select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMIZE
select DVB_TUNER_DIB0070
+ select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE
+ select MEDIA_TUNER_MT2266 if !MEDIA_TUNER_CUSTOMIZE
+ select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE
+ select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMIZE
help
Support for USB2.0/1.1 DVB receivers based on the DiB0700 USB bridge. The
USB bridge is also present in devices having the DiB7700 DVB-T-USB
@@ -95,7 +95,7 @@ config DVB_USB_UMT_010
depends on DVB_USB
select DVB_PLL if !DVB_FE_CUSTOMISE
select DVB_DIB3000MC
- select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE
+ select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE
help
Say Y here to support the HanfTek UMT-010 USB2.0 stick-sized DVB-T receiver.
@@ -107,11 +107,11 @@ config DVB_USB_CXUSB
select DVB_LGDT330X if !DVB_FE_CUSTOMISE
select DVB_MT352 if !DVB_FE_CUSTOMISE
select DVB_ZL10353 if !DVB_FE_CUSTOMISE
- select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE
- select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMISE
- select MEDIA_TUNER_MXL5005S if !DVB_FE_CUSTOMISE
select DVB_DIB7000P if !DVB_FE_CUSTOMISE
select DVB_TUNER_DIB0070 if !DVB_FE_CUSTOMISE
+ select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE
+ select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE
+ select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMIZE
help
Say Y here to support the Conexant USB2.0 hybrid reference design.
Currently, only DVB and ATSC modes are supported, analog mode
@@ -124,9 +124,9 @@ config DVB_USB_M920X
tristate "Uli m920x DVB-T USB2.0 support"
depends on DVB_USB
select DVB_MT352 if !DVB_FE_CUSTOMISE
- select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE
- select MEDIA_TUNER_TDA827X if !DVB_FE_CUSTOMISE
select DVB_TDA1004X if !DVB_FE_CUSTOMISE
+ select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE
+ select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMIZE
help
Say Y here to support the MSI Mega Sky 580 USB2.0 DVB-T receiver.
Currently, only devices with a product id of
@@ -137,7 +137,7 @@ config DVB_USB_GL861
tristate "Genesys Logic GL861 USB2.0 support"
depends on DVB_USB
select DVB_ZL10353 if !DVB_FE_CUSTOMISE
- select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE
+ select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE
help
Say Y here to support the MSI Megasky 580 (55801) DVB-T USB2.0
receiver with USB ID 0db0:5581.
@@ -146,7 +146,7 @@ config DVB_USB_AU6610
tristate "Alcor Micro AU6610 USB2.0 support"
depends on DVB_USB
select DVB_ZL10353 if !DVB_FE_CUSTOMISE
- select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE
+ select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE
help
Say Y here to support the Sigmatek DVB-110 DVB-T USB2.0 receiver.
@@ -198,8 +198,8 @@ config DVB_USB_NOVA_T_USB2
tristate "Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 support"
depends on DVB_USB
select DVB_DIB3000MC
- select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE
select DVB_PLL if !DVB_FE_CUSTOMISE
+ select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE
help
Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 receiver.
@@ -235,8 +235,8 @@ config DVB_USB_OPERA1
config DVB_USB_AF9005
tristate "Afatech AF9005 DVB-T USB1.1 support"
depends on DVB_USB && EXPERIMENTAL
- select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE
- select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE
+ select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE
+ select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE
help
Say Y here to support the Afatech AF9005 based DVB-T USB1.1 receiver
and the TerraTec Cinergy T USB XE (Rev.1)
@@ -284,7 +284,7 @@ config DVB_USB_DTV5100
tristate "AME DTV-5100 USB2.0 DVB-T support"
depends on DVB_USB
select DVB_ZL10353 if !DVB_FE_CUSTOMISE
- select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE
+ select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE
help
Say Y here to support the AME DTV-5100 USB2.0 DVB-T receiver.
@@ -293,9 +293,9 @@ config DVB_USB_AF9015
depends on DVB_USB && EXPERIMENTAL
select DVB_AF9013
select DVB_PLL if !DVB_FE_CUSTOMISE
- select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE
- select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE
- select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMISE
- select MEDIA_TUNER_MXL5005S if !DVB_FE_CUSTOMISE
+ select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE
+ select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE
+ select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMIZE
+ select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMIZE
help
Say Y here to support the Afatech AF9015 based DVB-T USB2.0 receiver
diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c
index 847d8fdd9ec..e9ab0249d13 100644
--- a/drivers/media/dvb/dvb-usb/af9015.c
+++ b/drivers/media/dvb/dvb-usb/af9015.c
@@ -681,12 +681,6 @@ static int af9015_download_firmware(struct usb_device *udev,
goto error;
}
- /* firmware is running, reconnect device in the usb bus */
- req.cmd = RECONNECT_USB;
- ret = af9015_rw_udev(udev, &req);
- if (ret)
- err("reconnect failed: %d", ret);
-
error:
return ret;
}
@@ -1208,6 +1202,7 @@ static struct dvb_usb_device_properties af9015_properties[] = {
.usb_ctrl = DEVICE_SPECIFIC,
.download_firmware = af9015_download_firmware,
.firmware = "dvb-usb-af9015.fw",
+ .no_reconnect = 1,
.size_of_priv = sizeof(struct af9015_state), \
@@ -1306,6 +1301,7 @@ static struct dvb_usb_device_properties af9015_properties[] = {
.usb_ctrl = DEVICE_SPECIFIC,
.download_firmware = af9015_download_firmware,
.firmware = "dvb-usb-af9015.fw",
+ .no_reconnect = 1,
.size_of_priv = sizeof(struct af9015_state), \
diff --git a/drivers/media/dvb/dvb-usb/dib0700.h b/drivers/media/dvb/dvb-usb/dib0700.h
index 739193943c1..8b544fe79b0 100644
--- a/drivers/media/dvb/dvb-usb/dib0700.h
+++ b/drivers/media/dvb/dvb-usb/dib0700.h
@@ -22,7 +22,7 @@ extern int dvb_usb_dib0700_debug;
#define REQUEST_I2C_READ 0x2
#define REQUEST_I2C_WRITE 0x3
-#define REQUEST_POLL_RC 0x4
+#define REQUEST_POLL_RC 0x4 /* deprecated in firmware v1.20 */
#define REQUEST_JUMPRAM 0x8
#define REQUEST_SET_CLOCK 0xB
#define REQUEST_SET_GPIO 0xC
@@ -40,11 +40,14 @@ struct dib0700_state {
u16 mt2060_if1[2];
u8 rc_toggle;
u8 rc_counter;
+ u8 rc_func_version;
u8 is_dib7000pc;
u8 fw_use_new_i2c_api;
u8 disable_streaming_master_mode;
};
+extern int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion,
+ u32 *romversion, u32 *ramversion, u32 *fwtype);
extern int dib0700_set_gpio(struct dvb_usb_device *, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val);
extern int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3);
extern int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen);
diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c
index dd53cee3896..200b215f4d8 100644
--- a/drivers/media/dvb/dvb-usb/dib0700_core.c
+++ b/drivers/media/dvb/dvb-usb/dib0700_core.c
@@ -19,6 +19,22 @@ MODULE_PARM_DESC(dvb_usb_dib0700_ir_proto, "set ir protocol (0=NEC, 1=RC5 (defau
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion,
+ u32 *romversion, u32 *ramversion, u32 *fwtype)
+{
+ u8 b[16];
+ int ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0),
+ REQUEST_GET_VERSION,
+ USB_TYPE_VENDOR | USB_DIR_IN, 0, 0,
+ b, sizeof(b), USB_CTRL_GET_TIMEOUT);
+ *hwversion = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];
+ *romversion = (b[4] << 24) | (b[5] << 16) | (b[6] << 8) | b[7];
+ *ramversion = (b[8] << 24) | (b[9] << 16) | (b[10] << 8) | b[11];
+ *fwtype = (b[12] << 24) | (b[13] << 16) | (b[14] << 8) | b[15];
+ return ret;
+}
+
/* expecting rx buffer: request data[0] data[1] ... data[2] */
static int dib0700_ctrl_wr(struct dvb_usb_device *d, u8 *tx, u8 txlen)
{
diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c
index 0cfccc24b19..39173278891 100644
--- a/drivers/media/dvb/dvb-usb/dib0700_devices.c
+++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c
@@ -38,6 +38,7 @@ static struct mt2060_config bristol_mt2060_config[2] = {
}
};
+
static struct dibx000_agc_config bristol_dib3000p_mt2060_agc_config = {
.band_caps = BAND_VHF | BAND_UHF,
.setup = (1 << 8) | (5 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (2 << 0),
@@ -445,14 +446,19 @@ static int stk7700ph_tuner_attach(struct dvb_usb_adapter *adap)
== NULL ? -ENODEV : 0;
}
-#define DEFAULT_RC_INTERVAL 150
+#define DEFAULT_RC_INTERVAL 50
static u8 rc_request[] = { REQUEST_POLL_RC, 0 };
/* Number of keypresses to ignore before start repeating */
-#define RC_REPEAT_DELAY 2
+#define RC_REPEAT_DELAY 6
+#define RC_REPEAT_DELAY_V1_20 10
-static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+
+
+/* Used by firmware versions < 1.20 (deprecated) */
+static int dib0700_rc_query_legacy(struct dvb_usb_device *d, u32 *event,
+ int *state)
{
u8 key[4];
int i;
@@ -529,6 +535,137 @@ static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
return 0;
}
+/* This is the structure of the RC response packet starting in firmware 1.20 */
+struct dib0700_rc_response {
+ u8 report_id;
+ u8 data_state;
+ u8 system_msb;
+ u8 system_lsb;
+ u8 data;
+ u8 not_data;
+};
+
+/* This supports the new IR response format for firmware v1.20 */
+static int dib0700_rc_query_v1_20(struct dvb_usb_device *d, u32 *event,
+ int *state)
+{
+ struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
+ struct dib0700_state *st = d->priv;
+ struct dib0700_rc_response poll_reply;
+ u8 buf[6];
+ int i;
+ int status;
+ int actlen;
+ int found = 0;
+
+ /* Set initial results in case we exit the function early */
+ *event = 0;
+ *state = REMOTE_NO_KEY_PRESSED;
+
+ /* Firmware v1.20 provides RC data via bulk endpoint 1 */
+ status = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev, 1), buf,
+ sizeof(buf), &actlen, 50);
+ if (status < 0) {
+ /* No data available (meaning no key press) */
+ return 0;
+ }
+
+ if (actlen != sizeof(buf)) {
+ /* We didn't get back the 6 byte message we expected */
+ err("Unexpected RC response size [%d]", actlen);
+ return -1;
+ }
+
+ poll_reply.report_id = buf[0];
+ poll_reply.data_state = buf[1];
+ poll_reply.system_msb = buf[2];
+ poll_reply.system_lsb = buf[3];
+ poll_reply.data = buf[4];
+ poll_reply.not_data = buf[5];
+
+ /*
+ info("rid=%02x ds=%02x sm=%02x sl=%02x d=%02x nd=%02x\n",
+ poll_reply.report_id, poll_reply.data_state,
+ poll_reply.system_msb, poll_reply.system_lsb,
+ poll_reply.data, poll_reply.not_data);
+ */
+
+ if ((poll_reply.data + poll_reply.not_data) != 0xff) {
+ /* Key failed integrity check */
+ err("key failed integrity check: %02x %02x %02x %02x",
+ poll_reply.system_msb, poll_reply.system_lsb,
+ poll_reply.data, poll_reply.not_data);
+ return -1;
+ }
+
+ /* Find the key in the map */
+ for (i = 0; i < d->props.rc_key_map_size; i++) {
+ if (keymap[i].custom == poll_reply.system_lsb &&
+ keymap[i].data == poll_reply.data) {
+ *event = keymap[i].event;
+ found = 1;
+ break;
+ }
+ }
+
+ if (found == 0) {
+ err("Unknown remote controller key: %02x %02x %02x %02x",
+ poll_reply.system_msb, poll_reply.system_lsb,
+ poll_reply.data, poll_reply.not_data);
+ d->last_event = 0;
+ return 0;
+ }
+
+ if (poll_reply.data_state == 1) {
+ /* New key hit */
+ st->rc_counter = 0;
+ *event = keymap[i].event;
+ *state = REMOTE_KEY_PRESSED;
+ d->last_event = keymap[i].event;
+ } else if (poll_reply.data_state == 2) {
+ /* Key repeated */
+ st->rc_counter++;
+
+ /* prevents unwanted double hits */
+ if (st->rc_counter > RC_REPEAT_DELAY_V1_20) {
+ *event = d->last_event;
+ *state = REMOTE_KEY_PRESSED;
+ st->rc_counter = RC_REPEAT_DELAY_V1_20;
+ }
+ } else {
+ err("Unknown data state [%d]", poll_reply.data_state);
+ }
+
+ return 0;
+}
+
+static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+{
+ struct dib0700_state *st = d->priv;
+
+ /* Because some people may have improperly named firmware files,
+ let's figure out whether to use the new firmware call or the legacy
+ call based on the firmware version embedded in the file */
+ if (st->rc_func_version == 0) {
+ u32 hwver, romver, ramver, fwtype;
+ int ret = dib0700_get_version(d, &hwver, &romver, &ramver,
+ &fwtype);
+ if (ret < 0) {
+ err("Could not determine version info");
+ return -1;
+ }
+ if (ramver < 0x10200)
+ st->rc_func_version = 1;
+ else
+ st->rc_func_version = 2;
+ }
+
+ if (st->rc_func_version == 2)
+ return dib0700_rc_query_v1_20(d, event, state);
+ else
+ return dib0700_rc_query_legacy(d, event, state);
+}
+
static struct dvb_usb_rc_key dib0700_rc_keys[] = {
/* Key codes for the tiny Pinnacle remote*/
{ 0x07, 0x00, KEY_MUTE },
diff --git a/drivers/media/dvb/dvb-usb/usb-urb.c b/drivers/media/dvb/dvb-usb/usb-urb.c
index 397f51a7b2a..da93b9e982c 100644
--- a/drivers/media/dvb/dvb-usb/usb-urb.c
+++ b/drivers/media/dvb/dvb-usb/usb-urb.c
@@ -135,7 +135,7 @@ stream->buf_list[stream->buf_num], (long long)stream->dma_addr[stream->buf_num])
static int usb_bulk_urb_init(struct usb_data_stream *stream)
{
- int i;
+ int i, j;
if ((i = usb_allocate_stream_buffers(stream,stream->props.count,
stream->props.u.bulk.buffersize)) < 0)
@@ -143,9 +143,13 @@ static int usb_bulk_urb_init(struct usb_data_stream *stream)
/* allocate the URBs */
for (i = 0; i < stream->props.count; i++) {
- if ((stream->urb_list[i] = usb_alloc_urb(0,GFP_ATOMIC)) == NULL)
+ stream->urb_list[i] = usb_alloc_urb(0, GFP_ATOMIC);
+ if (!stream->urb_list[i]) {
+ deb_mem("not enough memory for urb_alloc_urb!.\n");
+ for (j = 0; j < i; j++)
+ usb_free_urb(stream->urb_list[i]);
return -ENOMEM;
-
+ }
usb_fill_bulk_urb( stream->urb_list[i], stream->udev,
usb_rcvbulkpipe(stream->udev,stream->props.endpoint),
stream->buf_list[i],
@@ -170,9 +174,14 @@ static int usb_isoc_urb_init(struct usb_data_stream *stream)
for (i = 0; i < stream->props.count; i++) {
struct urb *urb;
int frame_offset = 0;
- if ((stream->urb_list[i] =
- usb_alloc_urb(stream->props.u.isoc.framesperurb,GFP_ATOMIC)) == NULL)
+
+ stream->urb_list[i] = usb_alloc_urb(stream->props.u.isoc.framesperurb, GFP_ATOMIC);
+ if (!stream->urb_list[i]) {
+ deb_mem("not enough memory for urb_alloc_urb!\n");
+ for (j = 0; j < i; j++)
+ usb_free_urb(stream->urb_list[i]);
return -ENOMEM;
+ }
urb = stream->urb_list[i];
diff --git a/drivers/media/dvb/siano/sms-cards.c b/drivers/media/dvb/siano/sms-cards.c
index 6f9b7736044..e98d6caf2c2 100644
--- a/drivers/media/dvb/siano/sms-cards.c
+++ b/drivers/media/dvb/siano/sms-cards.c
@@ -95,7 +95,7 @@ static struct sms_board sms_boards[] = {
[SMS1XXX_BOARD_HAUPPAUGE_WINDHAM] = {
.name = "Hauppauge WinTV MiniStick",
.type = SMS_NOVA_B0,
- .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-01.fw",
+ .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw",
},
};
diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig
index 867027ceab3..401a04effc0 100644
--- a/drivers/media/dvb/ttpci/Kconfig
+++ b/drivers/media/dvb/ttpci/Kconfig
@@ -106,7 +106,7 @@ config DVB_BUDGET_CI
select DVB_TDA1004X if !DVB_FE_CUSTOMISE
select DVB_LNBP21 if !DVB_FE_CUSTOMISE
select DVB_TDA10023 if !DVB_FE_CUSTOMISE
- select MEDIA_TUNER_TDA827X if !DVB_FE_CUSTOMISE
+ select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMIZE
select VIDEO_IR
help
Support for simple SAA7146 based DVB cards
diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
index 66ab0c6e978..4a3f2b8ea37 100644
--- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
+++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
@@ -808,6 +808,12 @@ static int ttusb_alloc_iso_urbs(struct ttusb *ttusb)
ISO_BUF_COUNT,
&ttusb->iso_dma_handle);
+ if (!ttusb->iso_buffer) {
+ dprintk("%s: pci_alloc_consistent - not enough memory\n",
+ __func__);
+ return -ENOMEM;
+ }
+
memset(ttusb->iso_buffer, 0,
ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF * ISO_BUF_COUNT);
@@ -1659,7 +1665,14 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i
ttusb_setup_interfaces(ttusb);
- ttusb_alloc_iso_urbs(ttusb);
+ result = ttusb_alloc_iso_urbs(ttusb);
+ if (result < 0) {
+ dprintk("%s: ttusb_alloc_iso_urbs - failed\n", __func__);
+ mutex_unlock(&ttusb->semi2c);
+ kfree(ttusb);
+ return result;
+ }
+
if (ttusb_init_controller(ttusb))
printk("ttusb_init_controller: error\n");
diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
index ab33fec8a19..0aa96df80fc 100644
--- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c
+++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
@@ -1157,6 +1157,12 @@ static int ttusb_dec_alloc_iso_urbs(struct ttusb_dec *dec)
ISO_BUF_COUNT),
&dec->iso_dma_handle);
+ if (!dec->iso_buffer) {
+ dprintk("%s: pci_alloc_consistent - not enough memory\n",
+ __func__);
+ return -ENOMEM;
+ }
+
memset(dec->iso_buffer, 0,
ISO_FRAME_SIZE * (FRAMES_PER_ISO_BUF * ISO_BUF_COUNT));
@@ -1254,6 +1260,7 @@ static int ttusb_dec_init_usb(struct ttusb_dec *dec)
dec->irq_buffer = usb_buffer_alloc(dec->udev,IRQ_PACKET_SIZE,
GFP_ATOMIC, &dec->irq_dma_handle);
if(!dec->irq_buffer) {
+ usb_free_urb(dec->irq_urb);
return -ENOMEM;
}
usb_fill_int_urb(dec->irq_urb, dec->udev,dec->irq_pipe,
diff --git a/drivers/media/video/compat_ioctl32.c b/drivers/media/video/compat_ioctl32.c
index e6ca4012b5f..0ea85a05e5c 100644
--- a/drivers/media/video/compat_ioctl32.c
+++ b/drivers/media/video/compat_ioctl32.c
@@ -831,7 +831,7 @@ long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
{
int ret = -ENOIOCTLCMD;
- if (!file->f_op->ioctl)
+ if (!file->f_op->ioctl && !file->f_op->unlocked_ioctl)
return ret;
switch (cmd) {
diff --git a/drivers/media/video/cx18/Kconfig b/drivers/media/video/cx18/Kconfig
index ef48565de7f..8940b5387de 100644
--- a/drivers/media/video/cx18/Kconfig
+++ b/drivers/media/video/cx18/Kconfig
@@ -9,7 +9,7 @@ config VIDEO_CX18
select VIDEO_CX2341X
select VIDEO_CS5345
select DVB_S5H1409 if !DVB_FE_CUSTOMISE
- select MEDIA_TUNER_MXL5005S if !DVB_FE_CUSTOMISE
+ select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMIZE
---help---
This is a video4linux driver for Conexant cx23418 based
PCI combo video recorder devices.
diff --git a/drivers/media/video/cx23885/Kconfig b/drivers/media/video/cx23885/Kconfig
index 8c1b7fa47a4..00f1e2e8889 100644
--- a/drivers/media/video/cx23885/Kconfig
+++ b/drivers/media/video/cx23885/Kconfig
@@ -11,16 +11,16 @@ config VIDEO_CX23885
select VIDEO_CX25840
select VIDEO_CX2341X
select DVB_DIB7000P if !DVB_FE_CUSTOMISE
- select MEDIA_TUNER_MT2131 if !DVB_FE_CUSTOMISE
select DVB_S5H1409 if !DVB_FE_CUSTOMISE
select DVB_S5H1411 if !DVB_FE_CUSTOMISE
select DVB_LGDT330X if !DVB_FE_CUSTOMISE
select DVB_ZL10353 if !DVB_FE_CUSTOMISE
+ select DVB_TDA10048 if !DVB_FE_CUSTOMIZE
+ select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMIZE
select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMIZE
select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMIZE
select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMIZE
select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMIZE
- select DVB_TDA10048 if !DVB_FE_CUSTOMIZE
---help---
This is a video4linux driver for Conexant 23885 based
TV cards.
diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig
index 0b9e5fac623..b0f837588e0 100644
--- a/drivers/media/video/cx88/Kconfig
+++ b/drivers/media/video/cx88/Kconfig
@@ -56,12 +56,12 @@ config VIDEO_CX88_DVB
select DVB_NXT200X if !DVB_FE_CUSTOMISE
select DVB_CX24123 if !DVB_FE_CUSTOMISE
select DVB_ISL6421 if !DVB_FE_CUSTOMISE
- select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE
select DVB_S5H1411 if !DVB_FE_CUSTOMISE
select DVB_CX24116 if !DVB_FE_CUSTOMISE
select DVB_STV0299 if !DVB_FE_CUSTOMISE
select DVB_STV0288 if !DVB_FE_CUSTOMISE
select DVB_STB6000 if !DVB_FE_CUSTOMISE
+ select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE
---help---
This adds support for DVB/ATSC cards based on the
Conexant 2388x chip.
diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c
index ac3292d7646..7a8d49ef646 100644
--- a/drivers/media/video/em28xx/em28xx-audio.c
+++ b/drivers/media/video/em28xx/em28xx-audio.c
@@ -62,7 +62,7 @@ static int em28xx_isoc_audio_deinit(struct em28xx *dev)
dprintk("Stopping isoc\n");
for (i = 0; i < EM28XX_AUDIO_BUFS; i++) {
- usb_kill_urb(dev->adev->urb[i]);
+ usb_unlink_urb(dev->adev->urb[i]);
usb_free_urb(dev->adev->urb[i]);
dev->adev->urb[i] = NULL;
}
@@ -75,7 +75,6 @@ static void em28xx_audio_isocirq(struct urb *urb)
struct em28xx *dev = urb->context;
int i;
unsigned int oldptr;
- unsigned long flags;
int period_elapsed = 0;
int status;
unsigned char *cp;
@@ -96,9 +95,21 @@ static void em28xx_audio_isocirq(struct urb *urb)
if (!length)
continue;
- spin_lock_irqsave(&dev->adev->slock, flags);
-
oldptr = dev->adev->hwptr_done_capture;
+ if (oldptr + length >= runtime->buffer_size) {
+ unsigned int cnt =
+ runtime->buffer_size - oldptr;
+ memcpy(runtime->dma_area + oldptr * stride, cp,
+ cnt * stride);
+ memcpy(runtime->dma_area, cp + cnt * stride,
+ length * stride - cnt * stride);
+ } else {
+ memcpy(runtime->dma_area + oldptr * stride, cp,
+ length * stride);
+ }
+
+ snd_pcm_stream_lock(substream);
+
dev->adev->hwptr_done_capture += length;
if (dev->adev->hwptr_done_capture >=
runtime->buffer_size)
@@ -113,19 +124,7 @@ static void em28xx_audio_isocirq(struct urb *urb)
period_elapsed = 1;
}
- spin_unlock_irqrestore(&dev->adev->slock, flags);
-
- if (oldptr + length >= runtime->buffer_size) {
- unsigned int cnt =
- runtime->buffer_size - oldptr;
- memcpy(runtime->dma_area + oldptr * stride, cp,
- cnt * stride);
- memcpy(runtime->dma_area, cp + cnt * stride,
- length * stride - cnt * stride);
- } else {
- memcpy(runtime->dma_area + oldptr * stride, cp,
- length * stride);
- }
+ snd_pcm_stream_unlock(substream);
}
if (period_elapsed)
snd_pcm_period_elapsed(substream);
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c
index 5d837c16ee2..15e2b525310 100644
--- a/drivers/media/video/em28xx/em28xx-core.c
+++ b/drivers/media/video/em28xx/em28xx-core.c
@@ -69,19 +69,33 @@ int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg,
int ret, byte;
if (dev->state & DEV_DISCONNECTED)
- return(-ENODEV);
+ return -ENODEV;
+
+ if (len > URB_MAX_CTRL_SIZE)
+ return -EINVAL;
em28xx_regdbg("req=%02x, reg=%02x ", req, reg);
+ mutex_lock(&dev->ctrl_urb_lock);
ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- 0x0000, reg, buf, len, HZ);
+ 0x0000, reg, dev->urb_buf, len, HZ);
+ if (ret < 0) {
+ if (reg_debug)
+ printk(" failed!\n");
+ mutex_unlock(&dev->ctrl_urb_lock);
+ return ret;
+ }
+
+ if (len)
+ memcpy(buf, dev->urb_buf, len);
+
+ mutex_unlock(&dev->ctrl_urb_lock);
if (reg_debug) {
- printk(ret < 0 ? " failed!\n" : "%02x values: ", ret);
+ printk("%02x values: ", ret);
for (byte = 0; byte < len; byte++)
printk(" %02x", (unsigned char)buf[byte]);
-
printk("\n");
}
@@ -102,16 +116,20 @@ int em28xx_read_reg_req(struct em28xx *dev, u8 req, u16 reg)
em28xx_regdbg("req=%02x, reg=%02x:", req, reg);
+ mutex_lock(&dev->ctrl_urb_lock);
ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- 0x0000, reg, &val, 1, HZ);
-
- if (reg_debug)
- printk(ret < 0 ? " failed!\n" :
- "%02x\n", (unsigned char) val);
+ 0x0000, reg, dev->urb_buf, 1, HZ);
+ val = dev->urb_buf[0];
+ mutex_unlock(&dev->ctrl_urb_lock);
- if (ret < 0)
+ if (ret < 0) {
+ printk(" failed!\n");
return ret;
+ }
+
+ if (reg_debug)
+ printk("%02x\n", (unsigned char) val);
return val;
}
@@ -130,19 +148,13 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf,
{
int ret;
- /*usb_control_msg seems to expect a kmalloced buffer */
- unsigned char *bufs;
-
if (dev->state & DEV_DISCONNECTED)
return -ENODEV;
- if (len < 1)
+ if ((len < 1) || (len > URB_MAX_CTRL_SIZE))
return -EINVAL;
- bufs = kmalloc(len, GFP_KERNEL);
-
em28xx_regdbg("req=%02x reg=%02x:", req, reg);
-
if (reg_debug) {
int i;
for (i = 0; i < len; ++i)
@@ -150,16 +162,16 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf,
printk("\n");
}
- if (!bufs)
- return -ENOMEM;
- memcpy(bufs, buf, len);
+ mutex_lock(&dev->ctrl_urb_lock);
+ memcpy(dev->urb_buf, buf, len);
ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), req,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- 0x0000, reg, bufs, len, HZ);
+ 0x0000, reg, dev->urb_buf, len, HZ);
+ mutex_unlock(&dev->ctrl_urb_lock);
+
if (dev->wait_after_write)
msleep(dev->wait_after_write);
- kfree(bufs);
return ret;
}
@@ -270,6 +282,8 @@ static int em28xx_set_audio_source(struct em28xx *dev)
break;
case EM28XX_AMUX_LINE_IN:
input = EM28XX_AUDIO_SRC_LINE;
+ video = disable;
+ line = enable;
break;
case EM28XX_AMUX_AC97_VIDEO:
input = EM28XX_AUDIO_SRC_LINE;
diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c
index 3bab56b997f..2360c61ddca 100644
--- a/drivers/media/video/em28xx/em28xx-i2c.c
+++ b/drivers/media/video/em28xx/em28xx-i2c.c
@@ -337,9 +337,9 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len)
/* Check if board has eeprom */
err = i2c_master_recv(&dev->i2c_client, &buf, 0);
if (err < 0) {
- em28xx_errdev("%s: i2c_master_recv failed! err [%d]\n",
- __func__, err);
- return err;
+ em28xx_errdev("board has no eeprom\n");
+ memset(eedata, 0, len);
+ return -ENODEV;
}
buf = 0;
@@ -609,14 +609,16 @@ int em28xx_i2c_register(struct em28xx *dev)
dev->i2c_client.adapter = &dev->i2c_adap;
retval = em28xx_i2c_eeprom(dev, dev->eedata, sizeof(dev->eedata));
- if (retval < 0) {
+ if ((retval < 0) && (retval != -ENODEV)) {
em28xx_errdev("%s: em28xx_i2_eeprom failed! retval [%d]\n",
__func__, retval);
+
return retval;
}
if (i2c_scan)
em28xx_do_i2c_scan(dev);
+
return 0;
}
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index a1ab2ef4557..4ea1f1e0489 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -73,6 +73,7 @@ MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
static LIST_HEAD(em28xx_devlist);
+static DEFINE_MUTEX(em28xx_devlist_mutex);
static unsigned int card[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET };
static unsigned int video_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET };
@@ -548,10 +549,11 @@ static int em28xx_config(struct em28xx *dev)
static void em28xx_config_i2c(struct em28xx *dev)
{
struct v4l2_routing route;
+ int zero = 0;
route.input = INPUT(dev->ctl_input)->vmux;
route.output = 0;
- em28xx_i2c_call_clients(dev, VIDIOC_INT_RESET, NULL);
+ em28xx_i2c_call_clients(dev, VIDIOC_INT_RESET, &zero);
em28xx_i2c_call_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route);
em28xx_i2c_call_clients(dev, VIDIOC_STREAMON, NULL);
}
@@ -1519,7 +1521,7 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
struct em28xx_fh *fh;
enum v4l2_buf_type fh_type = 0;
- lock_kernel();
+ mutex_lock(&em28xx_devlist_mutex);
list_for_each_entry(h, &em28xx_devlist, devlist) {
if (h->vdev->minor == minor) {
dev = h;
@@ -1535,10 +1537,11 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
dev = h;
}
}
- if (NULL == dev) {
- unlock_kernel();
+ mutex_unlock(&em28xx_devlist_mutex);
+ if (NULL == dev)
return -ENODEV;
- }
+
+ mutex_lock(&dev->lock);
em28xx_videodbg("open minor=%d type=%s users=%d\n",
minor, v4l2_type_names[fh_type], dev->users);
@@ -1547,10 +1550,9 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL);
if (!fh) {
em28xx_errdev("em28xx-video.c: Out of memory?!\n");
- unlock_kernel();
+ mutex_unlock(&dev->lock);
return -ENOMEM;
}
- mutex_lock(&dev->lock);
fh->dev = dev;
fh->radio = radio;
fh->type = fh_type;
@@ -1584,7 +1586,6 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
sizeof(struct em28xx_buffer), fh);
mutex_unlock(&dev->lock);
- unlock_kernel();
return errCode;
}
@@ -1871,6 +1872,7 @@ int em28xx_register_extension(struct em28xx_ops *ops)
{
struct em28xx *dev = NULL;
+ mutex_lock(&em28xx_devlist_mutex);
mutex_lock(&em28xx_extension_devlist_lock);
list_add_tail(&ops->next, &em28xx_extension_devlist);
list_for_each_entry(dev, &em28xx_devlist, devlist) {
@@ -1879,6 +1881,7 @@ int em28xx_register_extension(struct em28xx_ops *ops)
}
printk(KERN_INFO "Em28xx: Initialized (%s) extension\n", ops->name);
mutex_unlock(&em28xx_extension_devlist_lock);
+ mutex_unlock(&em28xx_devlist_mutex);
return 0;
}
EXPORT_SYMBOL(em28xx_register_extension);
@@ -1887,6 +1890,7 @@ void em28xx_unregister_extension(struct em28xx_ops *ops)
{
struct em28xx *dev = NULL;
+ mutex_lock(&em28xx_devlist_mutex);
list_for_each_entry(dev, &em28xx_devlist, devlist) {
if (dev)
ops->fini(dev);
@@ -1896,6 +1900,7 @@ void em28xx_unregister_extension(struct em28xx_ops *ops)
printk(KERN_INFO "Em28xx: Removed (%s) extension\n", ops->name);
list_del(&ops->next);
mutex_unlock(&em28xx_extension_devlist_lock);
+ mutex_unlock(&em28xx_devlist_mutex);
}
EXPORT_SYMBOL(em28xx_unregister_extension);
@@ -1921,6 +1926,60 @@ static struct video_device *em28xx_vdev_init(struct em28xx *dev,
}
+static int register_analog_devices(struct em28xx *dev)
+{
+ int ret;
+
+ /* allocate and fill video video_device struct */
+ dev->vdev = em28xx_vdev_init(dev, &em28xx_video_template, "video");
+ if (!dev->vdev) {
+ em28xx_errdev("cannot allocate video_device.\n");
+ return -ENODEV;
+ }
+
+ /* register v4l2 video video_device */
+ ret = video_register_device(dev->vdev, VFL_TYPE_GRABBER,
+ video_nr[dev->devno]);
+ if (ret) {
+ em28xx_errdev("unable to register video device (error=%i).\n",
+ ret);
+ return ret;
+ }
+
+ /* Allocate and fill vbi video_device struct */
+ dev->vbi_dev = em28xx_vdev_init(dev, &em28xx_video_template, "vbi");
+
+ /* register v4l2 vbi video_device */
+ ret = video_register_device(dev->vbi_dev, VFL_TYPE_VBI,
+ vbi_nr[dev->devno]);
+ if (ret < 0) {
+ em28xx_errdev("unable to register vbi device\n");
+ return ret;
+ }
+
+ if (em28xx_boards[dev->model].radio.type == EM28XX_RADIO) {
+ dev->radio_dev = em28xx_vdev_init(dev, &em28xx_radio_template, "radio");
+ if (!dev->radio_dev) {
+ em28xx_errdev("cannot allocate video_device.\n");
+ return -ENODEV;
+ }
+ ret = video_register_device(dev->radio_dev, VFL_TYPE_RADIO,
+ radio_nr[dev->devno]);
+ if (ret < 0) {
+ em28xx_errdev("can't register radio device\n");
+ return ret;
+ }
+ em28xx_info("Registered radio device as /dev/radio%d\n",
+ dev->radio_dev->num);
+ }
+
+ em28xx_info("V4L2 device registered as /dev/video%d and /dev/vbi%d\n",
+ dev->vdev->num, dev->vbi_dev->num);
+
+ return 0;
+}
+
+
/*
* em28xx_init_dev()
* allocates and inits the device structs, registers i2c bus and v4l device
@@ -1936,6 +1995,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
dev->udev = udev;
mutex_init(&dev->lock);
+ mutex_init(&dev->ctrl_urb_lock);
spin_lock_init(&dev->slock);
init_waitqueue_head(&dev->open);
init_waitqueue_head(&dev->wait_frame);
@@ -1953,8 +2013,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
errCode = em28xx_config(dev);
if (errCode) {
em28xx_errdev("error configuring device\n");
- em28xx_devused &= ~(1<<dev->devno);
- kfree(dev);
return -ENOMEM;
}
@@ -2001,50 +2059,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
return errCode;
}
- list_add_tail(&dev->devlist, &em28xx_devlist);
-
- /* allocate and fill video video_device struct */
- dev->vdev = em28xx_vdev_init(dev, &em28xx_video_template, "video");
- if (NULL == dev->vdev) {
- em28xx_errdev("cannot allocate video_device.\n");
- goto fail_unreg;
- }
-
- /* register v4l2 video video_device */
- retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER,
- video_nr[dev->devno]);
- if (retval) {
- em28xx_errdev("unable to register video device (error=%i).\n",
- retval);
- goto fail_unreg;
- }
-
- /* Allocate and fill vbi video_device struct */
- dev->vbi_dev = em28xx_vdev_init(dev, &em28xx_video_template, "vbi");
- /* register v4l2 vbi video_device */
- if (video_register_device(dev->vbi_dev, VFL_TYPE_VBI,
- vbi_nr[dev->devno]) < 0) {
- em28xx_errdev("unable to register vbi device\n");
- retval = -ENODEV;
- goto fail_unreg;
- }
-
- if (em28xx_boards[dev->model].radio.type == EM28XX_RADIO) {
- dev->radio_dev = em28xx_vdev_init(dev, &em28xx_radio_template, "radio");
- if (NULL == dev->radio_dev) {
- em28xx_errdev("cannot allocate video_device.\n");
- goto fail_unreg;
- }
- retval = video_register_device(dev->radio_dev, VFL_TYPE_RADIO,
- radio_nr[dev->devno]);
- if (retval < 0) {
- em28xx_errdev("can't register radio device\n");
- goto fail_unreg;
- }
- em28xx_info("Registered radio device as /dev/radio%d\n",
- dev->radio_dev->num);
- }
-
/* init video dma queues */
INIT_LIST_HEAD(&dev->vidq.active);
INIT_LIST_HEAD(&dev->vidq.queued);
@@ -2071,8 +2085,14 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
video_mux(dev, 0);
- em28xx_info("V4L2 device registered as /dev/video%d and /dev/vbi%d\n",
- dev->vdev->num, dev->vbi_dev->num);
+ mutex_lock(&em28xx_devlist_mutex);
+ list_add_tail(&dev->devlist, &em28xx_devlist);
+ retval = register_analog_devices(dev);
+ if (retval < 0) {
+ em28xx_release_resources(dev);
+ mutex_unlock(&em28xx_devlist_mutex);
+ goto fail_reg_devices;
+ }
mutex_lock(&em28xx_extension_devlist_lock);
if (!list_empty(&em28xx_extension_devlist)) {
@@ -2082,13 +2102,12 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
}
}
mutex_unlock(&em28xx_extension_devlist_lock);
+ mutex_unlock(&em28xx_devlist_mutex);
return 0;
-fail_unreg:
- em28xx_release_resources(dev);
+fail_reg_devices:
mutex_unlock(&dev->lock);
- kfree(dev);
return retval;
}
@@ -2231,8 +2250,12 @@ static int em28xx_usb_probe(struct usb_interface *interface,
/* allocate device struct */
retval = em28xx_init_dev(&dev, udev, nr);
- if (retval)
+ if (retval) {
+ em28xx_devused &= ~(1<<dev->devno);
+ kfree(dev);
+
return retval;
+ }
em28xx_info("Found %s\n", em28xx_boards[dev->model].name);
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h
index 82781178e0a..5956e9b3062 100644
--- a/drivers/media/video/em28xx/em28xx.h
+++ b/drivers/media/video/em28xx/em28xx.h
@@ -102,6 +102,9 @@
#define EM28XX_MIN_BUF 4
#define EM28XX_DEF_BUF 8
+/*Limits the max URB message size */
+#define URB_MAX_CTRL_SIZE 80
+
/* Params for validated field */
#define EM28XX_BOARD_NOT_VALIDATED 1
#define EM28XX_BOARD_VALIDATED 0
@@ -430,6 +433,7 @@ struct em28xx {
/* locks */
struct mutex lock;
+ struct mutex ctrl_urb_lock; /* protects urb_buf */
/* spinlock_t queue_lock; */
struct list_head inqueue, outqueue;
wait_queue_head_t open, wait_frame, wait_stream;
@@ -451,6 +455,8 @@ struct em28xx {
unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */
struct urb *urb[EM28XX_NUM_BUFS]; /* urb for isoc transfers */
char *transfer_buffer[EM28XX_NUM_BUFS]; /* transfer buffers for isoc transfer */
+ char urb_buf[URB_MAX_CTRL_SIZE]; /* urb control msg buffer */
+
/* helper funcs that call usb_control_msg */
int (*em28xx_write_regs) (struct em28xx *dev, u16 reg,
char *buf, int len);
diff --git a/drivers/media/video/gspca/conex.c b/drivers/media/video/gspca/conex.c
index a9d51ba7c57..de28354ea5b 100644
--- a/drivers/media/video/gspca/conex.c
+++ b/drivers/media/video/gspca/conex.c
@@ -846,10 +846,13 @@ static int sd_start(struct gspca_dev *gspca_dev)
return 0;
}
+/* called on streamoff with alt 0 and on disconnect */
static void sd_stop0(struct gspca_dev *gspca_dev)
{
int retry = 50;
+ if (!gspca_dev->present)
+ return;
reg_w_val(gspca_dev, 0x0000, 0x00);
reg_r(gspca_dev, 0x0002, 1);
reg_w_val(gspca_dev, 0x0053, 0x00);
diff --git a/drivers/media/video/gspca/finepix.c b/drivers/media/video/gspca/finepix.c
index 65d3cbfe6b2..607942fd797 100644
--- a/drivers/media/video/gspca/finepix.c
+++ b/drivers/media/video/gspca/finepix.c
@@ -276,6 +276,12 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
/* Stop the state machine */
if (dev->state != FPIX_NOP)
wait_for_completion(&dev->can_close);
+}
+
+/* called on streamoff with alt 0 and disconnect */
+static void sd_stop0(struct gspca_dev *gspca_dev)
+{
+ struct usb_fpix *dev = (struct usb_fpix *) gspca_dev;
usb_free_urb(dev->control_urb);
dev->control_urb = NULL;
@@ -385,6 +391,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
error:
/* Free the ressources */
sd_stopN(gspca_dev);
+ sd_stop0(gspca_dev);
return ret;
}
@@ -425,6 +432,7 @@ static const struct sd_desc sd_desc = {
.init = sd_init,
.start = sd_start,
.stopN = sd_stopN,
+ .stop0 = sd_stop0,
};
/* -- device connect -- */
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c
index e48fbfc8ad0..02a6e9ef033 100644
--- a/drivers/media/video/gspca/gspca.c
+++ b/drivers/media/video/gspca/gspca.c
@@ -646,15 +646,14 @@ static void gspca_stream_off(struct gspca_dev *gspca_dev)
{
gspca_dev->streaming = 0;
atomic_set(&gspca_dev->nevent, 0);
- if (gspca_dev->present) {
- if (gspca_dev->sd_desc->stopN)
- gspca_dev->sd_desc->stopN(gspca_dev);
- destroy_urbs(gspca_dev);
- gspca_set_alt0(gspca_dev);
- if (gspca_dev->sd_desc->stop0)
- gspca_dev->sd_desc->stop0(gspca_dev);
- PDEBUG(D_STREAM, "stream off OK");
- }
+ if (gspca_dev->present
+ && gspca_dev->sd_desc->stopN)
+ gspca_dev->sd_desc->stopN(gspca_dev);
+ destroy_urbs(gspca_dev);
+ gspca_set_alt0(gspca_dev);
+ if (gspca_dev->sd_desc->stop0)
+ gspca_dev->sd_desc->stop0(gspca_dev);
+ PDEBUG(D_STREAM, "stream off OK");
}
static void gspca_set_default_mode(struct gspca_dev *gspca_dev)
@@ -863,7 +862,7 @@ static int dev_open(struct inode *inode, struct file *file)
int ret;
PDEBUG(D_STREAM, "%s open", current->comm);
- gspca_dev = (struct gspca_dev *) video_devdata(file);
+ gspca_dev = video_drvdata(file);
if (mutex_lock_interruptible(&gspca_dev->queue_lock))
return -ERESTARTSYS;
if (!gspca_dev->present) {
@@ -875,6 +874,13 @@ static int dev_open(struct inode *inode, struct file *file)
ret = -EBUSY;
goto out;
}
+
+ /* protect the subdriver against rmmod */
+ if (!try_module_get(gspca_dev->module)) {
+ ret = -ENODEV;
+ goto out;
+ }
+
gspca_dev->users++;
/* one more user */
@@ -884,10 +890,10 @@ static int dev_open(struct inode *inode, struct file *file)
#ifdef GSPCA_DEBUG
/* activate the v4l2 debug */
if (gspca_debug & D_V4L2)
- gspca_dev->vdev.debug |= V4L2_DEBUG_IOCTL
+ gspca_dev->vdev->debug |= V4L2_DEBUG_IOCTL
| V4L2_DEBUG_IOCTL_ARG;
else
- gspca_dev->vdev.debug &= ~(V4L2_DEBUG_IOCTL
+ gspca_dev->vdev->debug &= ~(V4L2_DEBUG_IOCTL
| V4L2_DEBUG_IOCTL_ARG);
#endif
ret = 0;
@@ -921,6 +927,7 @@ static int dev_close(struct inode *inode, struct file *file)
gspca_dev->memory = GSPCA_MEMORY_NO;
}
file->private_data = NULL;
+ module_put(gspca_dev->module);
mutex_unlock(&gspca_dev->queue_lock);
PDEBUG(D_STREAM, "close done");
@@ -1257,10 +1264,10 @@ static int vidioc_s_jpegcomp(struct file *file, void *priv,
struct gspca_dev *gspca_dev = priv;
int ret;
- if (mutex_lock_interruptible(&gspca_dev->usb_lock))
- return -ERESTARTSYS;
if (!gspca_dev->sd_desc->set_jcomp)
return -EINVAL;
+ if (mutex_lock_interruptible(&gspca_dev->usb_lock))
+ return -ERESTARTSYS;
ret = gspca_dev->sd_desc->set_jcomp(gspca_dev, jpegcomp);
mutex_unlock(&gspca_dev->usb_lock);
return ret;
@@ -1748,11 +1755,6 @@ out:
return ret;
}
-static void dev_release(struct video_device *vfd)
-{
- /* nothing */
-}
-
static struct file_operations dev_fops = {
.owner = THIS_MODULE,
.open = dev_open,
@@ -1800,7 +1802,7 @@ static struct video_device gspca_template = {
.name = "gspca main driver",
.fops = &dev_fops,
.ioctl_ops = &dev_ioctl_ops,
- .release = dev_release, /* mandatory */
+ .release = video_device_release,
.minor = -1,
};
@@ -1869,17 +1871,18 @@ int gspca_dev_probe(struct usb_interface *intf,
init_waitqueue_head(&gspca_dev->wq);
/* init video stuff */
- memcpy(&gspca_dev->vdev, &gspca_template, sizeof gspca_template);
- gspca_dev->vdev.parent = &dev->dev;
- memcpy(&gspca_dev->fops, &dev_fops, sizeof gspca_dev->fops);
- gspca_dev->vdev.fops = &gspca_dev->fops;
- gspca_dev->fops.owner = module; /* module protection */
+ gspca_dev->vdev = video_device_alloc();
+ memcpy(gspca_dev->vdev, &gspca_template, sizeof gspca_template);
+ gspca_dev->vdev->parent = &dev->dev;
+ gspca_dev->module = module;
gspca_dev->present = 1;
- ret = video_register_device(&gspca_dev->vdev,
+ video_set_drvdata(gspca_dev->vdev, gspca_dev);
+ ret = video_register_device(gspca_dev->vdev,
VFL_TYPE_GRABBER,
video_nr);
if (ret < 0) {
err("video_register_device err %d", ret);
+ video_device_release(gspca_dev->vdev);
goto out;
}
@@ -1887,7 +1890,8 @@ int gspca_dev_probe(struct usb_interface *intf,
PDEBUG(D_PROBE, "probe ok");
return 0;
out:
- kref_put(&gspca_dev->kref, gspca_delete);
+ kfree(gspca_dev->usb_buf);
+ kfree(gspca_dev);
return ret;
}
EXPORT_SYMBOL(gspca_dev_probe);
@@ -1905,7 +1909,7 @@ void gspca_disconnect(struct usb_interface *intf)
usb_set_intfdata(intf, NULL);
/* We don't want people trying to open up the device */
- video_unregister_device(&gspca_dev->vdev);
+ video_unregister_device(gspca_dev->vdev);
gspca_dev->present = 0;
gspca_dev->streaming = 0;
diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h
index 1d9dc90b479..d25e8d69373 100644
--- a/drivers/media/video/gspca/gspca.h
+++ b/drivers/media/video/gspca/gspca.h
@@ -97,7 +97,7 @@ struct sd_desc {
cam_pkt_op pkt_scan;
/* optional operations */
cam_v_op stopN; /* called on stream off - main alt */
- cam_v_op stop0; /* called on stream off - alt 0 */
+ cam_v_op stop0; /* called on stream off & disconnect - alt 0 */
cam_v_op dq_callback; /* called when a frame has been dequeued */
cam_jpg_op get_jcomp;
cam_jpg_op set_jcomp;
@@ -120,8 +120,8 @@ struct gspca_frame {
};
struct gspca_dev {
- struct video_device vdev; /* !! must be the first item */
- struct file_operations fops;
+ struct video_device *vdev;
+ struct module *module; /* subdriver handling the device */
struct usb_device *dev;
struct kref kref;
struct file *capt_file; /* file doing video capture */
diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c
index e5ff9a6199e..fbd45e235d9 100644
--- a/drivers/media/video/gspca/pac7311.c
+++ b/drivers/media/video/gspca/pac7311.c
@@ -749,10 +749,13 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
}
+/* called on streamoff with alt 0 and on disconnect */
static void sd_stop0(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
+ if (!gspca_dev->present)
+ return;
if (sd->sensor == SENSOR_PAC7302) {
reg_w(gspca_dev, 0xff, 0x01);
reg_w(gspca_dev, 0x78, 0x40);
diff --git a/drivers/media/video/gspca/spca501.c b/drivers/media/video/gspca/spca501.c
index b742f260c7c..e29954c1c38 100644
--- a/drivers/media/video/gspca/spca501.c
+++ b/drivers/media/video/gspca/spca501.c
@@ -2022,8 +2022,11 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
reg_write(gspca_dev->dev, SPCA501_REG_CTLRL, 0x01, 0x00);
}
+/* called on streamoff with alt 0 and on disconnect */
static void sd_stop0(struct gspca_dev *gspca_dev)
{
+ if (!gspca_dev->present)
+ return;
reg_write(gspca_dev->dev, SPCA501_REG_CTLRL, 0x05, 0x00);
}
diff --git a/drivers/media/video/gspca/spca505.c b/drivers/media/video/gspca/spca505.c
index b345749213c..895b9fe4018 100644
--- a/drivers/media/video/gspca/spca505.c
+++ b/drivers/media/video/gspca/spca505.c
@@ -742,8 +742,12 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
reg_write(gspca_dev->dev, 0x02, 0x00, 0x00);
}
+/* called on streamoff with alt 0 and on disconnect */
static void sd_stop0(struct gspca_dev *gspca_dev)
{
+ if (!gspca_dev->present)
+ return;
+
/* This maybe reset or power control */
reg_write(gspca_dev->dev, 0x03, 0x03, 0x20);
reg_write(gspca_dev->dev, 0x03, 0x01, 0x0);
diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c
index 020a03c466c..c3de4e44123 100644
--- a/drivers/media/video/gspca/spca561.c
+++ b/drivers/media/video/gspca/spca561.c
@@ -766,10 +766,13 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
}
}
+/* called on streamoff with alt 0 and on disconnect */
static void sd_stop0(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
+ if (!gspca_dev->present)
+ return;
if (sd->chip_revision == Rev012A) {
reg_w_val(gspca_dev->dev, 0x8118, 0x29);
reg_w_val(gspca_dev->dev, 0x8114, 0x08);
diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c
index be46d923254..17af353ddd1 100644
--- a/drivers/media/video/gspca/vc032x.c
+++ b/drivers/media/video/gspca/vc032x.c
@@ -1633,10 +1633,13 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
reg_w(dev, 0xa0, 0x09, 0xb003);
}
+/* called on streamoff with alt 0 and on disconnect */
static void sd_stop0(struct gspca_dev *gspca_dev)
{
struct usb_device *dev = gspca_dev->dev;
+ if (!gspca_dev->present)
+ return;
reg_w(dev, 0x89, 0xffff, 0xffff);
}
diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c
index 8b3101d347c..0befacf4985 100644
--- a/drivers/media/video/gspca/zc3xx.c
+++ b/drivers/media/video/gspca/zc3xx.c
@@ -7336,10 +7336,13 @@ static int sd_start(struct gspca_dev *gspca_dev)
return 0;
}
+/* called on streamoff with alt 0 and on disconnect */
static void sd_stop0(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
+ if (!gspca_dev->present)
+ return;
send_unknown(gspca_dev->dev, sd->sensor);
}
diff --git a/drivers/media/video/pvrusb2/Kconfig b/drivers/media/video/pvrusb2/Kconfig
index 19eb274c9cd..854c2a88535 100644
--- a/drivers/media/video/pvrusb2/Kconfig
+++ b/drivers/media/video/pvrusb2/Kconfig
@@ -42,7 +42,7 @@ config VIDEO_PVRUSB2_DVB
select DVB_S5H1411 if !DVB_FE_CUSTOMISE
select DVB_TDA10048 if !DVB_FE_CUSTOMIZE
select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMIZE
- select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE
+ select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE
select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMIZE
---help---
diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c
index 5272926db73..3c3f8cf7310 100644
--- a/drivers/media/video/s2255drv.c
+++ b/drivers/media/video/s2255drv.c
@@ -192,7 +192,7 @@ struct s2255_dmaqueue {
#define S2255_FW_FAILED 3
#define S2255_FW_DISCONNECTING 4
-#define S2255_FW_MARKER 0x22552f2f
+#define S2255_FW_MARKER cpu_to_le32(0x22552f2f)
/* 2255 read states */
#define S2255_READ_IDLE 0
#define S2255_READ_FRAME 1
diff --git a/drivers/media/video/saa7134/Kconfig b/drivers/media/video/saa7134/Kconfig
index 7021bbf5897..fc2164e28e7 100644
--- a/drivers/media/video/saa7134/Kconfig
+++ b/drivers/media/video/saa7134/Kconfig
@@ -34,9 +34,9 @@ config VIDEO_SAA7134_DVB
select DVB_NXT200X if !DVB_FE_CUSTOMISE
select DVB_TDA10086 if !DVB_FE_CUSTOMISE
select DVB_TDA826X if !DVB_FE_CUSTOMISE
- select MEDIA_TUNER_TDA827X if !DVB_FE_CUSTOMISE
select DVB_ISL6421 if !DVB_FE_CUSTOMISE
- select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE
+ select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMIZE
+ select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE
---help---
This adds support for DVB cards based on the
Philips saa7134 chip.
diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c
index b59e47272ab..3720f0e03a1 100644
--- a/drivers/media/video/tvaudio.c
+++ b/drivers/media/video/tvaudio.c
@@ -1,5 +1,5 @@
/*
- * experimental driver for simple i2c audio chips.
+ * Driver for simple i2c audio chips.
*
* Copyright (c) 2000 Gerd Knorr
* based on code by:
@@ -7,6 +7,10 @@
* Steve VanDeBogart (vandebo@uclink.berkeley.edu)
* Greg Alexander (galexand@acm.org)
*
+ * Copyright(c) 2005-2008 Mauro Carvalho Chehab
+ * - Some cleanups, code fixes, etc
+ * - Convert it to V4L2 API
+ *
* This code is placed under the terms of the GNU General Public License
*
* OPTIONS:
@@ -30,6 +34,7 @@
#include <media/tvaudio.h>
#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
#include <media/v4l2-chip-ident.h>
#include <media/v4l2-i2c-drv-legacy.h>
@@ -58,7 +63,6 @@ typedef int (*checkit)(struct CHIPSTATE*);
typedef int (*initialize)(struct CHIPSTATE*);
typedef int (*getmode)(struct CHIPSTATE*);
typedef void (*setmode)(struct CHIPSTATE*, int mode);
-typedef void (*checkmode)(struct CHIPSTATE*);
/* i2c command */
typedef struct AUDIOCMD {
@@ -79,6 +83,7 @@ struct CHIPDESC {
#define CHIP_HAS_VOLUME 1
#define CHIP_HAS_BASSTREBLE 2
#define CHIP_HAS_INPUTSEL 4
+#define CHIP_NEED_CHECKMODE 8
/* various i2c command sequences */
audiocmd init;
@@ -96,23 +101,20 @@ struct CHIPDESC {
getmode getmode;
setmode setmode;
- /* check / autoswitch audio after channel switches */
- checkmode checkmode;
-
/* input switch register + values for v4l inputs */
int inputreg;
int inputmap[4];
int inputmute;
int inputmask;
};
-static struct CHIPDESC chiplist[];
/* current state of the chip */
struct CHIPSTATE {
struct i2c_client *c;
- /* index into CHIPDESC array */
- int type;
+ /* chip-specific description - should point to
+ an entry at CHIPDESC table */
+ struct CHIPDESC *desc;
/* shadow register set */
audiocmd shadow;
@@ -152,7 +154,7 @@ static int chip_write(struct CHIPSTATE *chip, int subaddr, int val)
{
unsigned char buffer[2];
- if (-1 == subaddr) {
+ if (subaddr < 0) {
v4l_dbg(1, debug, chip->c, "%s: chip_write: 0x%x\n",
chip->c->name, val);
chip->shadow.bytes[1] = val;
@@ -163,6 +165,13 @@ static int chip_write(struct CHIPSTATE *chip, int subaddr, int val)
return -1;
}
} else {
+ if (subaddr + 1 >= ARRAY_SIZE(chip->shadow.bytes)) {
+ v4l_info(chip->c,
+ "Tried to access a non-existent register: %d\n",
+ subaddr);
+ return -EINVAL;
+ }
+
v4l_dbg(1, debug, chip->c, "%s: chip_write: reg%d=0x%x\n",
chip->c->name, subaddr, val);
chip->shadow.bytes[subaddr+1] = val;
@@ -177,12 +186,20 @@ static int chip_write(struct CHIPSTATE *chip, int subaddr, int val)
return 0;
}
-static int chip_write_masked(struct CHIPSTATE *chip, int subaddr, int val, int mask)
+static int chip_write_masked(struct CHIPSTATE *chip,
+ int subaddr, int val, int mask)
{
if (mask != 0) {
- if (-1 == subaddr) {
+ if (subaddr < 0) {
val = (chip->shadow.bytes[1] & ~mask) | (val & mask);
} else {
+ if (subaddr + 1 >= ARRAY_SIZE(chip->shadow.bytes)) {
+ v4l_info(chip->c,
+ "Tried to access a non-existent register: %d\n",
+ subaddr);
+ return -EINVAL;
+ }
+
val = (chip->shadow.bytes[subaddr+1] & ~mask) | (val & mask);
}
}
@@ -228,6 +245,15 @@ static int chip_cmd(struct CHIPSTATE *chip, char *name, audiocmd *cmd)
if (0 == cmd->count)
return 0;
+ if (cmd->count + cmd->bytes[0] - 1 >= ARRAY_SIZE(chip->shadow.bytes)) {
+ v4l_info(chip->c,
+ "Tried to access a non-existent register range: %d to %d\n",
+ cmd->bytes[0] + 1, cmd->bytes[0] + cmd->count - 1);
+ return -EINVAL;
+ }
+
+ /* FIXME: it seems that the shadow bytes are wrong bellow !*/
+
/* update our shadow register set; print bytes if (debug > 0) */
v4l_dbg(1, debug, chip->c, "%s: chip_cmd(%s): reg=%d, data:",
chip->c->name, name,cmd->bytes[0]);
@@ -263,7 +289,8 @@ static void chip_thread_wake(unsigned long data)
static int chip_thread(void *data)
{
struct CHIPSTATE *chip = data;
- struct CHIPDESC *desc = chiplist + chip->type;
+ struct CHIPDESC *desc = chip->desc;
+ int mode;
v4l_dbg(1, debug, chip->c, "%s: thread started\n", chip->c->name);
set_freezable();
@@ -282,7 +309,26 @@ static int chip_thread(void *data)
continue;
/* have a look what's going on */
- desc->checkmode(chip);
+ mode = desc->getmode(chip);
+ if (mode == chip->prevmode)
+ continue;
+
+ /* chip detected a new audio mode - set it */
+ v4l_dbg(1, debug, chip->c, "%s: thread checkmode\n",
+ chip->c->name);
+
+ chip->prevmode = mode;
+
+ if (mode & V4L2_TUNER_MODE_STEREO)
+ desc->setmode(chip, V4L2_TUNER_MODE_STEREO);
+ if (mode & V4L2_TUNER_MODE_LANG1_LANG2)
+ desc->setmode(chip, V4L2_TUNER_MODE_STEREO);
+ else if (mode & V4L2_TUNER_MODE_LANG1)
+ desc->setmode(chip, V4L2_TUNER_MODE_LANG1);
+ else if (mode & V4L2_TUNER_MODE_LANG2)
+ desc->setmode(chip, V4L2_TUNER_MODE_LANG2);
+ else
+ desc->setmode(chip, V4L2_TUNER_MODE_MONO);
/* schedule next check */
mod_timer(&chip->wt, jiffies+msecs_to_jiffies(2000));
@@ -292,29 +338,6 @@ static int chip_thread(void *data)
return 0;
}
-static void generic_checkmode(struct CHIPSTATE *chip)
-{
- struct CHIPDESC *desc = chiplist + chip->type;
- int mode = desc->getmode(chip);
-
- if (mode == chip->prevmode)
- return;
-
- v4l_dbg(1, debug, chip->c, "%s: thread checkmode\n", chip->c->name);
- chip->prevmode = mode;
-
- if (mode & V4L2_TUNER_MODE_STEREO)
- desc->setmode(chip,V4L2_TUNER_MODE_STEREO);
- if (mode & V4L2_TUNER_MODE_LANG1_LANG2)
- desc->setmode(chip,V4L2_TUNER_MODE_STEREO);
- else if (mode & V4L2_TUNER_MODE_LANG1)
- desc->setmode(chip,V4L2_TUNER_MODE_LANG1);
- else if (mode & V4L2_TUNER_MODE_LANG2)
- desc->setmode(chip,V4L2_TUNER_MODE_LANG2);
- else
- desc->setmode(chip,V4L2_TUNER_MODE_MONO);
-}
-
/* ---------------------------------------------------------------------- */
/* audio chip descriptions - defines+functions for tda9840 */
@@ -777,7 +800,7 @@ static struct tda9874a_MODES {
char *name;
audiocmd cmd;
} tda9874a_modelist[9] = {
- { "A2, B/G",
+ { "A2, B/G", /* default */
{ 9, { TDA9874A_C1FRA, 0x72,0x95,0x55, 0x77,0xA0,0x00, 0x00,0x00 }} },
{ "A2, M (Korea)",
{ 9, { TDA9874A_C1FRA, 0x5D,0xC0,0x00, 0x62,0x6A,0xAA, 0x20,0x22 }} },
@@ -791,7 +814,7 @@ static struct tda9874a_MODES {
{ 9, { TDA9874A_C1FRA, 0x7D,0x00,0x00, 0x88,0x8A,0xAA, 0x08,0x33 }} },
{ "NICAM, B/G",
{ 9, { TDA9874A_C1FRA, 0x72,0x95,0x55, 0x79,0xEA,0xAA, 0x08,0x33 }} },
- { "NICAM, D/K", /* default */
+ { "NICAM, D/K",
{ 9, { TDA9874A_C1FRA, 0x87,0x6A,0xAA, 0x79,0xEA,0xAA, 0x08,0x33 }} },
{ "NICAM, L",
{ 9, { TDA9874A_C1FRA, 0x87,0x6A,0xAA, 0x79,0xEA,0xAA, 0x09,0x33 }} }
@@ -981,7 +1004,7 @@ static int tda9874a_initialize(struct CHIPSTATE *chip)
{
if (tda9874a_SIF > 2)
tda9874a_SIF = 1;
- if (tda9874a_STD > 8)
+ if (tda9874a_STD >= ARRAY_SIZE(tda9874a_modelist))
tda9874a_STD = 0;
if(tda9874a_AMSEL > 1)
tda9874a_AMSEL = 0;
@@ -1089,7 +1112,7 @@ static int tda8425_shift12(int val) { return (val >> 12) | 0xf0; }
static int tda8425_initialize(struct CHIPSTATE *chip)
{
- struct CHIPDESC *desc = chiplist + chip->type;
+ struct CHIPDESC *desc = chip->desc;
int inputmap[4] = { /* tuner */ TDA8425_S1_CH2, /* radio */ TDA8425_S1_CH1,
/* extern */ TDA8425_S1_CH1, /* intern */ TDA8425_S1_OFF};
@@ -1259,27 +1282,28 @@ static struct CHIPDESC chiplist[] = {
.addr_lo = I2C_ADDR_TDA9840 >> 1,
.addr_hi = I2C_ADDR_TDA9840 >> 1,
.registers = 5,
+ .flags = CHIP_NEED_CHECKMODE,
+ /* callbacks */
.checkit = tda9840_checkit,
.getmode = tda9840_getmode,
.setmode = tda9840_setmode,
- .checkmode = generic_checkmode,
.init = { 2, { TDA9840_TEST, TDA9840_TEST_INT1SN
/* ,TDA9840_SW, TDA9840_MONO */} }
},
{
.name = "tda9873h",
- .checkit = tda9873_checkit,
.insmodopt = &tda9873,
.addr_lo = I2C_ADDR_TDA985x_L >> 1,
.addr_hi = I2C_ADDR_TDA985x_H >> 1,
.registers = 3,
- .flags = CHIP_HAS_INPUTSEL,
+ .flags = CHIP_HAS_INPUTSEL | CHIP_NEED_CHECKMODE,
+ /* callbacks */
+ .checkit = tda9873_checkit,
.getmode = tda9873_getmode,
.setmode = tda9873_setmode,
- .checkmode = generic_checkmode,
.init = { 4, { TDA9873_SW, 0xa4, 0x06, 0x03 } },
.inputreg = TDA9873_SW,
@@ -1290,15 +1314,16 @@ static struct CHIPDESC chiplist[] = {
},
{
.name = "tda9874h/a",
- .checkit = tda9874a_checkit,
- .initialize = tda9874a_initialize,
.insmodopt = &tda9874a,
.addr_lo = I2C_ADDR_TDA9874 >> 1,
.addr_hi = I2C_ADDR_TDA9874 >> 1,
+ .flags = CHIP_NEED_CHECKMODE,
+ /* callbacks */
+ .initialize = tda9874a_initialize,
+ .checkit = tda9874a_checkit,
.getmode = tda9874a_getmode,
.setmode = tda9874a_setmode,
- .checkmode = generic_checkmode,
},
{
.name = "tda9850",
@@ -1324,10 +1349,11 @@ static struct CHIPDESC chiplist[] = {
.rightreg = TDA9855_VR,
.bassreg = TDA9855_BA,
.treblereg = TDA9855_TR,
+
+ /* callbacks */
.volfunc = tda9855_volume,
.bassfunc = tda9855_bass,
.treblefunc = tda9855_treble,
-
.getmode = tda985x_getmode,
.setmode = tda985x_setmode,
@@ -1348,6 +1374,8 @@ static struct CHIPDESC chiplist[] = {
.rightreg = TEA6300_VL,
.bassreg = TEA6300_BA,
.treblereg = TEA6300_TR,
+
+ /* callbacks */
.volfunc = tea6300_shift10,
.bassfunc = tea6300_shift12,
.treblefunc = tea6300_shift12,
@@ -1358,7 +1386,6 @@ static struct CHIPDESC chiplist[] = {
},
{
.name = "tea6320",
- .initialize = tea6320_initialize,
.insmodopt = &tea6320,
.addr_lo = I2C_ADDR_TEA6300 >> 1,
.addr_hi = I2C_ADDR_TEA6300 >> 1,
@@ -1369,6 +1396,9 @@ static struct CHIPDESC chiplist[] = {
.rightreg = TEA6320_V,
.bassreg = TEA6320_BA,
.treblereg = TEA6320_TR,
+
+ /* callbacks */
+ .initialize = tea6320_initialize,
.volfunc = tea6320_volume,
.bassfunc = tea6320_shift11,
.treblefunc = tea6320_shift11,
@@ -1401,16 +1431,18 @@ static struct CHIPDESC chiplist[] = {
.rightreg = TDA8425_VR,
.bassreg = TDA8425_BA,
.treblereg = TDA8425_TR,
+
+ /* callbacks */
+ .initialize = tda8425_initialize,
.volfunc = tda8425_shift10,
.bassfunc = tda8425_shift12,
.treblefunc = tda8425_shift12,
+ .setmode = tda8425_setmode,
.inputreg = TDA8425_S1,
.inputmap = { TDA8425_S1_CH1, TDA8425_S1_CH1, TDA8425_S1_CH1 },
.inputmute = TDA8425_S1_OFF,
- .setmode = tda8425_setmode,
- .initialize = tda8425_initialize,
},
{
.name = "pic16c54 (PV951)",
@@ -1434,10 +1466,11 @@ static struct CHIPDESC chiplist[] = {
.addr_lo = I2C_ADDR_TDA9840 >> 1,
.addr_hi = I2C_ADDR_TDA9840 >> 1,
.registers = 2,
+ .flags = CHIP_NEED_CHECKMODE,
+ /* callbacks */
.getmode = ta8874z_getmode,
.setmode = ta8874z_setmode,
- .checkmode = generic_checkmode,
.init = {2, { TA8874Z_MONO_SET, TA8874Z_SEPARATION_DEFAULT}},
},
@@ -1481,6 +1514,7 @@ static int chip_probe(struct i2c_client *client, const struct i2c_device_id *id)
}
if (desc->name == NULL) {
v4l_dbg(1, debug, client, "no matching chip description found\n");
+ kfree(chip);
return -EIO;
}
v4l_info(client, "%s found @ 0x%x (%s)\n", desc->name, client->addr<<1, client->adapter->name);
@@ -1494,7 +1528,7 @@ static int chip_probe(struct i2c_client *client, const struct i2c_device_id *id)
/* fill required data structures */
if (!id)
strlcpy(client->name, desc->name, I2C_NAME_SIZE);
- chip->type = desc-chiplist;
+ chip->desc = desc;
chip->shadow.count = desc->registers+1;
chip->prevmode = -1;
chip->audmode = V4L2_TUNER_MODE_LANG1;
@@ -1506,20 +1540,49 @@ static int chip_probe(struct i2c_client *client, const struct i2c_device_id *id)
chip_cmd(chip,"init",&desc->init);
if (desc->flags & CHIP_HAS_VOLUME) {
- chip->left = desc->leftinit ? desc->leftinit : 65535;
- chip->right = desc->rightinit ? desc->rightinit : 65535;
- chip_write(chip,desc->leftreg,desc->volfunc(chip->left));
- chip_write(chip,desc->rightreg,desc->volfunc(chip->right));
+ if (!desc->volfunc) {
+ /* This shouldn't be happen. Warn user, but keep working
+ without volume controls
+ */
+ v4l_info(chip->c, "volume callback undefined!\n");
+ desc->flags &= ~CHIP_HAS_VOLUME;
+ } else {
+ chip->left = desc->leftinit ? desc->leftinit : 65535;
+ chip->right = desc->rightinit ? desc->rightinit : 65535;
+ chip_write(chip, desc->leftreg,
+ desc->volfunc(chip->left));
+ chip_write(chip, desc->rightreg,
+ desc->volfunc(chip->right));
+ }
}
if (desc->flags & CHIP_HAS_BASSTREBLE) {
- chip->treble = desc->trebleinit ? desc->trebleinit : 32768;
- chip->bass = desc->bassinit ? desc->bassinit : 32768;
- chip_write(chip,desc->bassreg,desc->bassfunc(chip->bass));
- chip_write(chip,desc->treblereg,desc->treblefunc(chip->treble));
+ if (!desc->bassfunc || !desc->treblefunc) {
+ /* This shouldn't be happen. Warn user, but keep working
+ without bass/treble controls
+ */
+ v4l_info(chip->c, "bass/treble callbacks undefined!\n");
+ desc->flags &= ~CHIP_HAS_BASSTREBLE;
+ } else {
+ chip->treble = desc->trebleinit ?
+ desc->trebleinit : 32768;
+ chip->bass = desc->bassinit ?
+ desc->bassinit : 32768;
+ chip_write(chip, desc->bassreg,
+ desc->bassfunc(chip->bass));
+ chip_write(chip, desc->treblereg,
+ desc->treblefunc(chip->treble));
+ }
}
chip->thread = NULL;
- if (desc->checkmode) {
+ if (desc->flags & CHIP_NEED_CHECKMODE) {
+ if (!desc->getmode || !desc->setmode) {
+ /* This shouldn't be happen. Warn user, but keep working
+ without kthread
+ */
+ v4l_info(chip->c, "set/get mode callbacks undefined!\n");
+ return 0;
+ }
/* start async thread */
init_timer(&chip->wt);
chip->wt.function = chip_thread_wake;
@@ -1552,7 +1615,7 @@ static int chip_remove(struct i2c_client *client)
static int tvaudio_get_ctrl(struct CHIPSTATE *chip,
struct v4l2_control *ctrl)
{
- struct CHIPDESC *desc = chiplist + chip->type;
+ struct CHIPDESC *desc = chip->desc;
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -1576,13 +1639,13 @@ static int tvaudio_get_ctrl(struct CHIPSTATE *chip,
return 0;
}
case V4L2_CID_AUDIO_BASS:
- if (desc->flags & CHIP_HAS_BASSTREBLE)
+ if (!(desc->flags & CHIP_HAS_BASSTREBLE))
break;
ctrl->value = chip->bass;
return 0;
case V4L2_CID_AUDIO_TREBLE:
- if (desc->flags & CHIP_HAS_BASSTREBLE)
- return -EINVAL;
+ if (!(desc->flags & CHIP_HAS_BASSTREBLE))
+ break;
ctrl->value = chip->treble;
return 0;
}
@@ -1592,7 +1655,7 @@ static int tvaudio_get_ctrl(struct CHIPSTATE *chip,
static int tvaudio_set_ctrl(struct CHIPSTATE *chip,
struct v4l2_control *ctrl)
{
- struct CHIPDESC *desc = chiplist + chip->type;
+ struct CHIPDESC *desc = chip->desc;
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -1642,16 +1705,15 @@ static int tvaudio_set_ctrl(struct CHIPSTATE *chip,
return 0;
}
case V4L2_CID_AUDIO_BASS:
- if (desc->flags & CHIP_HAS_BASSTREBLE)
+ if (!(desc->flags & CHIP_HAS_BASSTREBLE))
break;
chip->bass = ctrl->value;
chip_write(chip,desc->bassreg,desc->bassfunc(chip->bass));
return 0;
case V4L2_CID_AUDIO_TREBLE:
- if (desc->flags & CHIP_HAS_BASSTREBLE)
- return -EINVAL;
-
+ if (!(desc->flags & CHIP_HAS_BASSTREBLE))
+ break;
chip->treble = ctrl->value;
chip_write(chip,desc->treblereg,desc->treblefunc(chip->treble));
@@ -1668,9 +1730,12 @@ static int chip_command(struct i2c_client *client,
unsigned int cmd, void *arg)
{
struct CHIPSTATE *chip = i2c_get_clientdata(client);
- struct CHIPDESC *desc = chiplist + chip->type;
+ struct CHIPDESC *desc = chip->desc;
- v4l_dbg(1, debug, chip->c, "%s: chip_command 0x%x\n", chip->c->name, cmd);
+ if (debug > 0) {
+ v4l_i2c_print_ioctl(chip->c, cmd);
+ printk("\n");
+ }
switch (cmd) {
case AUDC_SET_RADIO:
@@ -1695,7 +1760,7 @@ static int chip_command(struct i2c_client *client,
break;
case V4L2_CID_AUDIO_BASS:
case V4L2_CID_AUDIO_TREBLE:
- if (desc->flags & CHIP_HAS_BASSTREBLE)
+ if (!(desc->flags & CHIP_HAS_BASSTREBLE))
return -EINVAL;
break;
default:
@@ -1792,12 +1857,20 @@ static int chip_command(struct i2c_client *client,
break;
case VIDIOC_S_FREQUENCY:
chip->mode = 0; /* automatic */
- if (desc->checkmode && desc->setmode) {
+
+ /* For chips that provide getmode and setmode, and doesn't
+ automatically follows the stereo carrier, a kthread is
+ created to set the audio standard. In this case, when then
+ the video channel is changed, tvaudio starts on MONO mode.
+ After waiting for 2 seconds, the kernel thread is called,
+ to follow whatever audio standard is pointed by the
+ audio carrier.
+ */
+ if (chip->thread) {
desc->setmode(chip,V4L2_TUNER_MODE_MONO);
if (chip->prevmode != V4L2_TUNER_MODE_MONO)
chip->prevmode = -1; /* reset previous mode */
mod_timer(&chip->wt, jiffies+msecs_to_jiffies(2000));
- /* the thread will call checkmode() later */
}
break;
@@ -1836,9 +1909,3 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = {
.legacy_probe = chip_legacy_probe,
.id_table = chip_id,
};
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index d62fd4f6b52..ee090413e59 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -2008,6 +2008,9 @@ mptscsih_host_reset(struct scsi_cmnd *SCpnt)
return FAILED;
}
+ /* make sure we have no outstanding commands at this stage */
+ mptscsih_flush_running_cmds(hd);
+
ioc = hd->ioc;
printk(MYIOC_s_INFO_FMT "attempting host reset! (sc=%p)\n",
ioc->name, SCpnt);
diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c
index 84bdc2ee69e..a443e136dc4 100644
--- a/drivers/message/i2o/i2o_block.c
+++ b/drivers/message/i2o/i2o_block.c
@@ -354,7 +354,7 @@ static inline void i2o_block_sglist_free(struct i2o_block_request *ireq)
* @req: the request to prepare
*
* Allocate the necessary i2o_block_request struct and connect it to
- * the request. This is needed that we not loose the SG list later on.
+ * the request. This is needed that we not lose the SG list later on.
*
* Returns BLKPREP_OK on success or BLKPREP_DEFER on failure.
*/
diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c
index be2b5926d26..6e53a30bfd3 100644
--- a/drivers/message/i2o/iop.c
+++ b/drivers/message/i2o/iop.c
@@ -49,7 +49,6 @@ static int i2o_hrt_get(struct i2o_controller *c);
/**
* i2o_msg_get_wait - obtain an I2O message from the IOP
* @c: I2O controller
- * @msg: pointer to a I2O message pointer
* @wait: how long to wait until timeout
*
* This function waits up to wait seconds for a message slot to be
diff --git a/drivers/mfd/da903x.c b/drivers/mfd/da903x.c
index b57326ae464..0b5bd85dfce 100644
--- a/drivers/mfd/da903x.c
+++ b/drivers/mfd/da903x.c
@@ -267,7 +267,7 @@ static int da9030_mask_events(struct da903x_chip *chip, unsigned int events)
{
uint8_t v[3];
- chip->events_mask &= ~events;
+ chip->events_mask |= events;
v[0] = (chip->events_mask & 0xff);
v[1] = (chip->events_mask >> 8) & 0xff;
diff --git a/drivers/mfd/wm8350-i2c.c b/drivers/mfd/wm8350-i2c.c
index 8dfe21bb3bd..3e0ce0e50ea 100644
--- a/drivers/mfd/wm8350-i2c.c
+++ b/drivers/mfd/wm8350-i2c.c
@@ -30,7 +30,12 @@ static int wm8350_i2c_read_device(struct wm8350 *wm8350, char reg,
ret = i2c_master_send(wm8350->i2c_client, &reg, 1);
if (ret < 0)
return ret;
- return i2c_master_recv(wm8350->i2c_client, dest, bytes);
+ ret = i2c_master_recv(wm8350->i2c_client, dest, bytes);
+ if (ret < 0)
+ return ret;
+ if (ret != bytes)
+ return -EIO;
+ return 0;
}
static int wm8350_i2c_write_device(struct wm8350 *wm8350, char reg,
@@ -38,13 +43,19 @@ static int wm8350_i2c_write_device(struct wm8350 *wm8350, char reg,
{
/* we add 1 byte for device register */
u8 msg[(WM8350_MAX_REGISTER << 1) + 1];
+ int ret;
if (bytes > ((WM8350_MAX_REGISTER << 1) + 1))
return -EINVAL;
msg[0] = reg;
memcpy(&msg[1], src, bytes);
- return i2c_master_send(wm8350->i2c_client, msg, bytes + 1);
+ ret = i2c_master_send(wm8350->i2c_client, msg, bytes + 1);
+ if (ret < 0)
+ return ret;
+ if (ret != bytes + 1)
+ return -EIO;
+ return 0;
}
static int wm8350_i2c_probe(struct i2c_client *i2c,
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 9494400e8fd..fee7304102a 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -227,10 +227,20 @@ config HP_WMI
To compile this driver as a module, choose M here: the module will
be called hp-wmi.
+config ICS932S401
+ tristate "Integrated Circuits ICS932S401"
+ depends on I2C && EXPERIMENTAL
+ help
+ If you say yes here you get support for the Integrated Circuits
+ ICS932S401 clock control chips.
+
+ This driver can also be built as a module. If so, the module
+ will be called ics932s401.
+
config MSI_LAPTOP
tristate "MSI Laptop Extras"
depends on X86
- depends on ACPI_EC
+ depends on ACPI
depends on BACKLIGHT_CLASS_DEVICE
---help---
This is a driver for laptops built by MSI (MICRO-STAR
@@ -260,7 +270,7 @@ config PANASONIC_LAPTOP
config COMPAL_LAPTOP
tristate "Compal Laptop Extras"
depends on X86
- depends on ACPI_EC
+ depends on ACPI
depends on BACKLIGHT_CLASS_DEVICE
---help---
This is a driver for laptops built by Compal:
@@ -488,4 +498,6 @@ config SGI_GRU_DEBUG
This option enables addition debugging code for the SGI GRU driver. If
you are unsure, say N.
+source "drivers/misc/c2port/Kconfig"
+
endif # MISC_DEVICES
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 909e2468cdc..817f7f5ab3b 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_ATMEL_PWM) += atmel_pwm.o
obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o
obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o
obj-$(CONFIG_HP_WMI) += hp-wmi.o
+obj-$(CONFIG_ICS932S401) += ics932s401.o
obj-$(CONFIG_TC1100_WMI) += tc1100-wmi.o
obj-$(CONFIG_LKDTM) += lkdtm.o
obj-$(CONFIG_TIFM_CORE) += tifm_core.o
@@ -31,3 +32,4 @@ obj-$(CONFIG_KGDB_TESTS) += kgdbts.o
obj-$(CONFIG_SGI_XP) += sgi-xp/
obj-$(CONFIG_SGI_GRU) += sgi-gru/
obj-$(CONFIG_HP_ILO) += hpilo.o
+obj-$(CONFIG_C2PORT) += c2port/
diff --git a/drivers/misc/acer-wmi.c b/drivers/misc/acer-wmi.c
index 0532a2de2ce..94c9f911824 100644
--- a/drivers/misc/acer-wmi.c
+++ b/drivers/misc/acer-wmi.c
@@ -1297,6 +1297,12 @@ static int __init acer_wmi_init(void)
set_quirks();
+ if (!acpi_video_backlight_support() && has_cap(ACER_CAP_BRIGHTNESS)) {
+ interface->capability &= ~ACER_CAP_BRIGHTNESS;
+ printk(ACER_INFO "Brightness must be controlled by "
+ "generic video driver\n");
+ }
+
if (platform_driver_register(&acer_platform_driver)) {
printk(ACER_ERR "Unable to register platform driver.\n");
goto error_platform_register;
diff --git a/drivers/misc/asus-laptop.c b/drivers/misc/asus-laptop.c
index a9d5228724a..8fb8b359104 100644
--- a/drivers/misc/asus-laptop.c
+++ b/drivers/misc/asus-laptop.c
@@ -1208,9 +1208,13 @@ static int __init asus_laptop_init(void)
dev = acpi_get_physical_device(hotk->device->handle);
- result = asus_backlight_init(dev);
- if (result)
- goto fail_backlight;
+ if (!acpi_video_backlight_support()) {
+ result = asus_backlight_init(dev);
+ if (result)
+ goto fail_backlight;
+ } else
+ printk(ASUS_INFO "Brightness ignored, must be controlled by "
+ "ACPI video driver\n");
result = asus_led_init(dev);
if (result)
diff --git a/drivers/misc/c2port/Kconfig b/drivers/misc/c2port/Kconfig
new file mode 100644
index 00000000000..e46af9a5810
--- /dev/null
+++ b/drivers/misc/c2port/Kconfig
@@ -0,0 +1,35 @@
+#
+# C2 port devices
+#
+
+menuconfig C2PORT
+ tristate "Silicon Labs C2 port support (EXPERIMENTAL)"
+ depends on EXPERIMENTAL
+ default no
+ help
+ This option enables support for Silicon Labs C2 port used to
+ program Silicon micro controller chips (and other 8051 compatible).
+
+ If your board have no such micro controllers you don't need this
+ interface at all.
+
+ To compile this driver as a module, choose M here: the module will
+ be called c2port_core. Note that you also need a client module
+ usually called c2port-*.
+
+ If you are not sure, say N here.
+
+if C2PORT
+
+config C2PORT_DURAMAR_2150
+ tristate "C2 port support for Eurotech's Duramar 2150 (EXPERIMENTAL)"
+ depends on X86 && C2PORT
+ default no
+ help
+ This option enables C2 support for the Eurotech's Duramar 2150
+ on board micro controller.
+
+ To compile this driver as a module, choose M here: the module will
+ be called c2port-duramar2150.
+
+endif # C2PORT
diff --git a/drivers/misc/c2port/Makefile b/drivers/misc/c2port/Makefile
new file mode 100644
index 00000000000..3b2cf43d60f
--- /dev/null
+++ b/drivers/misc/c2port/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_C2PORT) += core.o
+
+obj-$(CONFIG_C2PORT_DURAMAR_2150) += c2port-duramar2150.o
diff --git a/drivers/misc/c2port/c2port-duramar2150.c b/drivers/misc/c2port/c2port-duramar2150.c
new file mode 100644
index 00000000000..338dcc12150
--- /dev/null
+++ b/drivers/misc/c2port/c2port-duramar2150.c
@@ -0,0 +1,158 @@
+/*
+ * Silicon Labs C2 port Linux support for Eurotech Duramar 2150
+ *
+ * Copyright (c) 2008 Rodolfo Giometti <giometti@linux.it>
+ * Copyright (c) 2008 Eurotech S.p.A. <info@eurotech.it>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation
+ */
+
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/c2port.h>
+
+#define DATA_PORT 0x325
+#define DIR_PORT 0x326
+#define C2D (1 << 0)
+#define C2CK (1 << 1)
+
+static DEFINE_MUTEX(update_lock);
+
+/*
+ * C2 port operations
+ */
+
+static void duramar2150_c2port_access(struct c2port_device *dev, int status)
+{
+ u8 v;
+
+ mutex_lock(&update_lock);
+
+ v = inb(DIR_PORT);
+
+ /* 0 = input, 1 = output */
+ if (status)
+ outb(v | (C2D | C2CK), DIR_PORT);
+ else
+ /* When access is "off" is important that both lines are set
+ * as inputs or hi-impedence */
+ outb(v & ~(C2D | C2CK), DIR_PORT);
+
+ mutex_unlock(&update_lock);
+}
+
+static void duramar2150_c2port_c2d_dir(struct c2port_device *dev, int dir)
+{
+ u8 v;
+
+ mutex_lock(&update_lock);
+
+ v = inb(DIR_PORT);
+
+ if (dir)
+ outb(v & ~C2D, DIR_PORT);
+ else
+ outb(v | C2D, DIR_PORT);
+
+ mutex_unlock(&update_lock);
+}
+
+static int duramar2150_c2port_c2d_get(struct c2port_device *dev)
+{
+ return inb(DATA_PORT) & C2D;
+}
+
+static void duramar2150_c2port_c2d_set(struct c2port_device *dev, int status)
+{
+ u8 v;
+
+ mutex_lock(&update_lock);
+
+ v = inb(DATA_PORT);
+
+ if (status)
+ outb(v | C2D, DATA_PORT);
+ else
+ outb(v & ~C2D, DATA_PORT);
+
+ mutex_unlock(&update_lock);
+}
+
+static void duramar2150_c2port_c2ck_set(struct c2port_device *dev, int status)
+{
+ u8 v;
+
+ mutex_lock(&update_lock);
+
+ v = inb(DATA_PORT);
+
+ if (status)
+ outb(v | C2CK, DATA_PORT);
+ else
+ outb(v & ~C2CK, DATA_PORT);
+
+ mutex_unlock(&update_lock);
+}
+
+static struct c2port_ops duramar2150_c2port_ops = {
+ .block_size = 512, /* bytes */
+ .blocks_num = 30, /* total flash size: 15360 bytes */
+
+ .access = duramar2150_c2port_access,
+ .c2d_dir = duramar2150_c2port_c2d_dir,
+ .c2d_get = duramar2150_c2port_c2d_get,
+ .c2d_set = duramar2150_c2port_c2d_set,
+ .c2ck_set = duramar2150_c2port_c2ck_set,
+};
+
+static struct c2port_device *duramar2150_c2port_dev;
+
+/*
+ * Module stuff
+ */
+
+static int __init duramar2150_c2port_init(void)
+{
+ struct resource *res;
+ int ret = 0;
+
+ res = request_region(0x325, 2, "c2port");
+ if (!res)
+ return -EBUSY;
+
+ duramar2150_c2port_dev = c2port_device_register("uc",
+ &duramar2150_c2port_ops, NULL);
+ if (!duramar2150_c2port_dev) {
+ ret = -ENODEV;
+ goto free_region;
+ }
+
+ return 0;
+
+free_region:
+ release_region(0x325, 2);
+ return ret;
+}
+
+static void __exit duramar2150_c2port_exit(void)
+{
+ /* Setup the GPIOs as input by default (access = 0) */
+ duramar2150_c2port_access(duramar2150_c2port_dev, 0);
+
+ c2port_device_unregister(duramar2150_c2port_dev);
+
+ release_region(0x325, 2);
+}
+
+module_init(duramar2150_c2port_init);
+module_exit(duramar2150_c2port_exit);
+
+MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>");
+MODULE_DESCRIPTION("Silicon Labs C2 port Linux support for Duramar 2150");
+MODULE_LICENSE("GPL");
diff --git a/drivers/misc/c2port/core.c b/drivers/misc/c2port/core.c
new file mode 100644
index 00000000000..0207dd59090
--- /dev/null
+++ b/drivers/misc/c2port/core.c
@@ -0,0 +1,1003 @@
+/*
+ * Silicon Labs C2 port core Linux support
+ *
+ * Copyright (c) 2007 Rodolfo Giometti <giometti@linux.it>
+ * Copyright (c) 2007 Eurotech S.p.A. <info@eurotech.it>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/ctype.h>
+#include <linux/delay.h>
+#include <linux/idr.h>
+#include <linux/sched.h>
+
+#include <linux/c2port.h>
+
+#define DRIVER_NAME "c2port"
+#define DRIVER_VERSION "0.51.0"
+
+static DEFINE_SPINLOCK(c2port_idr_lock);
+static DEFINE_IDR(c2port_idr);
+
+/*
+ * Local variables
+ */
+
+static struct class *c2port_class;
+
+/*
+ * C2 registers & commands defines
+ */
+
+/* C2 registers */
+#define C2PORT_DEVICEID 0x00
+#define C2PORT_REVID 0x01
+#define C2PORT_FPCTL 0x02
+#define C2PORT_FPDAT 0xB4
+
+/* C2 interface commands */
+#define C2PORT_GET_VERSION 0x01
+#define C2PORT_DEVICE_ERASE 0x03
+#define C2PORT_BLOCK_READ 0x06
+#define C2PORT_BLOCK_WRITE 0x07
+#define C2PORT_PAGE_ERASE 0x08
+
+/* C2 status return codes */
+#define C2PORT_INVALID_COMMAND 0x00
+#define C2PORT_COMMAND_FAILED 0x02
+#define C2PORT_COMMAND_OK 0x0d
+
+/*
+ * C2 port low level signal managements
+ */
+
+static void c2port_reset(struct c2port_device *dev)
+{
+ struct c2port_ops *ops = dev->ops;
+
+ /* To reset the device we have to keep clock line low for at least
+ * 20us.
+ */
+ local_irq_disable();
+ ops->c2ck_set(dev, 0);
+ udelay(25);
+ ops->c2ck_set(dev, 1);
+ local_irq_enable();
+
+ udelay(1);
+}
+
+static void c2port_strobe_ck(struct c2port_device *dev)
+{
+ struct c2port_ops *ops = dev->ops;
+
+ /* During hi-low-hi transition we disable local IRQs to avoid
+ * interructions since C2 port specification says that it must be
+ * shorter than 5us, otherwise the microcontroller may consider
+ * it as a reset signal!
+ */
+ local_irq_disable();
+ ops->c2ck_set(dev, 0);
+ udelay(1);
+ ops->c2ck_set(dev, 1);
+ local_irq_enable();
+
+ udelay(1);
+}
+
+/*
+ * C2 port basic functions
+ */
+
+static void c2port_write_ar(struct c2port_device *dev, u8 addr)
+{
+ struct c2port_ops *ops = dev->ops;
+ int i;
+
+ /* START field */
+ c2port_strobe_ck(dev);
+
+ /* INS field (11b, LSB first) */
+ ops->c2d_dir(dev, 0);
+ ops->c2d_set(dev, 1);
+ c2port_strobe_ck(dev);
+ ops->c2d_set(dev, 1);
+ c2port_strobe_ck(dev);
+
+ /* ADDRESS field */
+ for (i = 0; i < 8; i++) {
+ ops->c2d_set(dev, addr & 0x01);
+ c2port_strobe_ck(dev);
+
+ addr >>= 1;
+ }
+
+ /* STOP field */
+ ops->c2d_dir(dev, 1);
+ c2port_strobe_ck(dev);
+}
+
+static int c2port_read_ar(struct c2port_device *dev, u8 *addr)
+{
+ struct c2port_ops *ops = dev->ops;
+ int i;
+
+ /* START field */
+ c2port_strobe_ck(dev);
+
+ /* INS field (10b, LSB first) */
+ ops->c2d_dir(dev, 0);
+ ops->c2d_set(dev, 0);
+ c2port_strobe_ck(dev);
+ ops->c2d_set(dev, 1);
+ c2port_strobe_ck(dev);
+
+ /* ADDRESS field */
+ ops->c2d_dir(dev, 1);
+ *addr = 0;
+ for (i = 0; i < 8; i++) {
+ *addr >>= 1; /* shift in 8-bit ADDRESS field LSB first */
+
+ c2port_strobe_ck(dev);
+ if (ops->c2d_get(dev))
+ *addr |= 0x80;
+ }
+
+ /* STOP field */
+ c2port_strobe_ck(dev);
+
+ return 0;
+}
+
+static int c2port_write_dr(struct c2port_device *dev, u8 data)
+{
+ struct c2port_ops *ops = dev->ops;
+ int timeout, i;
+
+ /* START field */
+ c2port_strobe_ck(dev);
+
+ /* INS field (01b, LSB first) */
+ ops->c2d_dir(dev, 0);
+ ops->c2d_set(dev, 1);
+ c2port_strobe_ck(dev);
+ ops->c2d_set(dev, 0);
+ c2port_strobe_ck(dev);
+
+ /* LENGTH field (00b, LSB first -> 1 byte) */
+ ops->c2d_set(dev, 0);
+ c2port_strobe_ck(dev);
+ ops->c2d_set(dev, 0);
+ c2port_strobe_ck(dev);
+
+ /* DATA field */
+ for (i = 0; i < 8; i++) {
+ ops->c2d_set(dev, data & 0x01);
+ c2port_strobe_ck(dev);
+
+ data >>= 1;
+ }
+
+ /* WAIT field */
+ ops->c2d_dir(dev, 1);
+ timeout = 20;
+ do {
+ c2port_strobe_ck(dev);
+ if (ops->c2d_get(dev))
+ break;
+
+ udelay(1);
+ } while (--timeout > 0);
+ if (timeout == 0)
+ return -EIO;
+
+ /* STOP field */
+ c2port_strobe_ck(dev);
+
+ return 0;
+}
+
+static int c2port_read_dr(struct c2port_device *dev, u8 *data)
+{
+ struct c2port_ops *ops = dev->ops;
+ int timeout, i;
+
+ /* START field */
+ c2port_strobe_ck(dev);
+
+ /* INS field (00b, LSB first) */
+ ops->c2d_dir(dev, 0);
+ ops->c2d_set(dev, 0);
+ c2port_strobe_ck(dev);
+ ops->c2d_set(dev, 0);
+ c2port_strobe_ck(dev);
+
+ /* LENGTH field (00b, LSB first -> 1 byte) */
+ ops->c2d_set(dev, 0);
+ c2port_strobe_ck(dev);
+ ops->c2d_set(dev, 0);
+ c2port_strobe_ck(dev);
+
+ /* WAIT field */
+ ops->c2d_dir(dev, 1);
+ timeout = 20;
+ do {
+ c2port_strobe_ck(dev);
+ if (ops->c2d_get(dev))
+ break;
+
+ udelay(1);
+ } while (--timeout > 0);
+ if (timeout == 0)
+ return -EIO;
+
+ /* DATA field */
+ *data = 0;
+ for (i = 0; i < 8; i++) {
+ *data >>= 1; /* shift in 8-bit DATA field LSB first */
+
+ c2port_strobe_ck(dev);
+ if (ops->c2d_get(dev))
+ *data |= 0x80;
+ }
+
+ /* STOP field */
+ c2port_strobe_ck(dev);
+
+ return 0;
+}
+
+static int c2port_poll_in_busy(struct c2port_device *dev)
+{
+ u8 addr;
+ int ret, timeout = 20;
+
+ do {
+ ret = (c2port_read_ar(dev, &addr));
+ if (ret < 0)
+ return -EIO;
+
+ if (!(addr & 0x02))
+ break;
+
+ udelay(1);
+ } while (--timeout > 0);
+ if (timeout == 0)
+ return -EIO;
+
+ return 0;
+}
+
+static int c2port_poll_out_ready(struct c2port_device *dev)
+{
+ u8 addr;
+ int ret, timeout = 10000; /* erase flash needs long time... */
+
+ do {
+ ret = (c2port_read_ar(dev, &addr));
+ if (ret < 0)
+ return -EIO;
+
+ if (addr & 0x01)
+ break;
+
+ udelay(1);
+ } while (--timeout > 0);
+ if (timeout == 0)
+ return -EIO;
+
+ return 0;
+}
+
+/*
+ * sysfs methods
+ */
+
+static ssize_t c2port_show_name(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct c2port_device *c2dev = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%s\n", c2dev->name);
+}
+
+static ssize_t c2port_show_flash_blocks_num(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct c2port_device *c2dev = dev_get_drvdata(dev);
+ struct c2port_ops *ops = c2dev->ops;
+
+ return sprintf(buf, "%d\n", ops->blocks_num);
+}
+
+static ssize_t c2port_show_flash_block_size(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct c2port_device *c2dev = dev_get_drvdata(dev);
+ struct c2port_ops *ops = c2dev->ops;
+
+ return sprintf(buf, "%d\n", ops->block_size);
+}
+
+static ssize_t c2port_show_flash_size(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct c2port_device *c2dev = dev_get_drvdata(dev);
+ struct c2port_ops *ops = c2dev->ops;
+
+ return sprintf(buf, "%d\n", ops->blocks_num * ops->block_size);
+}
+
+static ssize_t c2port_show_access(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct c2port_device *c2dev = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%d\n", c2dev->access);
+}
+
+static ssize_t c2port_store_access(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct c2port_device *c2dev = dev_get_drvdata(dev);
+ struct c2port_ops *ops = c2dev->ops;
+ int status, ret;
+
+ ret = sscanf(buf, "%d", &status);
+ if (ret != 1)
+ return -EINVAL;
+
+ mutex_lock(&c2dev->mutex);
+
+ c2dev->access = !!status;
+
+ /* If access is "on" clock should be HIGH _before_ setting the line
+ * as output and data line should be set as INPUT anyway */
+ if (c2dev->access)
+ ops->c2ck_set(c2dev, 1);
+ ops->access(c2dev, c2dev->access);
+ if (c2dev->access)
+ ops->c2d_dir(c2dev, 1);
+
+ mutex_unlock(&c2dev->mutex);
+
+ return count;
+}
+
+static ssize_t c2port_store_reset(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct c2port_device *c2dev = dev_get_drvdata(dev);
+
+ /* Check the device access status */
+ if (!c2dev->access)
+ return -EBUSY;
+
+ mutex_lock(&c2dev->mutex);
+
+ c2port_reset(c2dev);
+ c2dev->flash_access = 0;
+
+ mutex_unlock(&c2dev->mutex);
+
+ return count;
+}
+
+static ssize_t __c2port_show_dev_id(struct c2port_device *dev, char *buf)
+{
+ u8 data;
+ int ret;
+
+ /* Select DEVICEID register for C2 data register accesses */
+ c2port_write_ar(dev, C2PORT_DEVICEID);
+
+ /* Read and return the device ID register */
+ ret = c2port_read_dr(dev, &data);
+ if (ret < 0)
+ return ret;
+
+ return sprintf(buf, "%d\n", data);
+}
+
+static ssize_t c2port_show_dev_id(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct c2port_device *c2dev = dev_get_drvdata(dev);
+ ssize_t ret;
+
+ /* Check the device access status */
+ if (!c2dev->access)
+ return -EBUSY;
+
+ mutex_lock(&c2dev->mutex);
+ ret = __c2port_show_dev_id(c2dev, buf);
+ mutex_unlock(&c2dev->mutex);
+
+ if (ret < 0)
+ dev_err(dev, "cannot read from %s\n", c2dev->name);
+
+ return ret;
+}
+
+static ssize_t __c2port_show_rev_id(struct c2port_device *dev, char *buf)
+{
+ u8 data;
+ int ret;
+
+ /* Select REVID register for C2 data register accesses */
+ c2port_write_ar(dev, C2PORT_REVID);
+
+ /* Read and return the revision ID register */
+ ret = c2port_read_dr(dev, &data);
+ if (ret < 0)
+ return ret;
+
+ return sprintf(buf, "%d\n", data);
+}
+
+static ssize_t c2port_show_rev_id(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct c2port_device *c2dev = dev_get_drvdata(dev);
+ ssize_t ret;
+
+ /* Check the device access status */
+ if (!c2dev->access)
+ return -EBUSY;
+
+ mutex_lock(&c2dev->mutex);
+ ret = __c2port_show_rev_id(c2dev, buf);
+ mutex_unlock(&c2dev->mutex);
+
+ if (ret < 0)
+ dev_err(c2dev->dev, "cannot read from %s\n", c2dev->name);
+
+ return ret;
+}
+
+static ssize_t c2port_show_flash_access(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct c2port_device *c2dev = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%d\n", c2dev->flash_access);
+}
+
+static ssize_t __c2port_store_flash_access(struct c2port_device *dev,
+ int status)
+{
+ int ret;
+
+ /* Check the device access status */
+ if (!dev->access)
+ return -EBUSY;
+
+ dev->flash_access = !!status;
+
+ /* If flash_access is off we have nothing to do... */
+ if (dev->flash_access == 0)
+ return 0;
+
+ /* Target the C2 flash programming control register for C2 data
+ * register access */
+ c2port_write_ar(dev, C2PORT_FPCTL);
+
+ /* Write the first keycode to enable C2 Flash programming */
+ ret = c2port_write_dr(dev, 0x02);
+ if (ret < 0)
+ return ret;
+
+ /* Write the second keycode to enable C2 Flash programming */
+ ret = c2port_write_dr(dev, 0x01);
+ if (ret < 0)
+ return ret;
+
+ /* Delay for at least 20ms to ensure the target is ready for
+ * C2 flash programming */
+ mdelay(25);
+
+ return 0;
+}
+
+static ssize_t c2port_store_flash_access(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct c2port_device *c2dev = dev_get_drvdata(dev);
+ int status;
+ ssize_t ret;
+
+ ret = sscanf(buf, "%d", &status);
+ if (ret != 1)
+ return -EINVAL;
+
+ mutex_lock(&c2dev->mutex);
+ ret = __c2port_store_flash_access(c2dev, status);
+ mutex_unlock(&c2dev->mutex);
+
+ if (ret < 0) {
+ dev_err(c2dev->dev, "cannot enable %s flash programming\n",
+ c2dev->name);
+ return ret;
+ }
+
+ return count;
+}
+
+static ssize_t __c2port_write_flash_erase(struct c2port_device *dev)
+{
+ u8 status;
+ int ret;
+
+ /* Target the C2 flash programming data register for C2 data register
+ * access.
+ */
+ c2port_write_ar(dev, C2PORT_FPDAT);
+
+ /* Send device erase command */
+ c2port_write_dr(dev, C2PORT_DEVICE_ERASE);
+
+ /* Wait for input acknowledge */
+ ret = c2port_poll_in_busy(dev);
+ if (ret < 0)
+ return ret;
+
+ /* Should check status before starting FLASH access sequence */
+
+ /* Wait for status information */
+ ret = c2port_poll_out_ready(dev);
+ if (ret < 0)
+ return ret;
+
+ /* Read flash programming interface status */
+ ret = c2port_read_dr(dev, &status);
+ if (ret < 0)
+ return ret;
+ if (status != C2PORT_COMMAND_OK)
+ return -EBUSY;
+
+ /* Send a three-byte arming sequence to enable the device erase.
+ * If the sequence is not received correctly, the command will be
+ * ignored.
+ * Sequence is: 0xde, 0xad, 0xa5.
+ */
+ c2port_write_dr(dev, 0xde);
+ ret = c2port_poll_in_busy(dev);
+ if (ret < 0)
+ return ret;
+ c2port_write_dr(dev, 0xad);
+ ret = c2port_poll_in_busy(dev);
+ if (ret < 0)
+ return ret;
+ c2port_write_dr(dev, 0xa5);
+ ret = c2port_poll_in_busy(dev);
+ if (ret < 0)
+ return ret;
+
+ ret = c2port_poll_out_ready(dev);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static ssize_t c2port_store_flash_erase(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct c2port_device *c2dev = dev_get_drvdata(dev);
+ int ret;
+
+ /* Check the device and flash access status */
+ if (!c2dev->access || !c2dev->flash_access)
+ return -EBUSY;
+
+ mutex_lock(&c2dev->mutex);
+ ret = __c2port_write_flash_erase(c2dev);
+ mutex_unlock(&c2dev->mutex);
+
+ if (ret < 0) {
+ dev_err(c2dev->dev, "cannot erase %s flash\n", c2dev->name);
+ return ret;
+ }
+
+ return count;
+}
+
+static ssize_t __c2port_read_flash_data(struct c2port_device *dev,
+ char *buffer, loff_t offset, size_t count)
+{
+ struct c2port_ops *ops = dev->ops;
+ u8 status, nread = 128;
+ int i, ret;
+
+ /* Check for flash end */
+ if (offset >= ops->block_size * ops->blocks_num)
+ return 0;
+
+ if (ops->block_size * ops->blocks_num - offset < nread)
+ nread = ops->block_size * ops->blocks_num - offset;
+ if (count < nread)
+ nread = count;
+ if (nread == 0)
+ return nread;
+
+ /* Target the C2 flash programming data register for C2 data register
+ * access */
+ c2port_write_ar(dev, C2PORT_FPDAT);
+
+ /* Send flash block read command */
+ c2port_write_dr(dev, C2PORT_BLOCK_READ);
+
+ /* Wait for input acknowledge */
+ ret = c2port_poll_in_busy(dev);
+ if (ret < 0)
+ return ret;
+
+ /* Should check status before starting FLASH access sequence */
+
+ /* Wait for status information */
+ ret = c2port_poll_out_ready(dev);
+ if (ret < 0)
+ return ret;
+
+ /* Read flash programming interface status */
+ ret = c2port_read_dr(dev, &status);
+ if (ret < 0)
+ return ret;
+ if (status != C2PORT_COMMAND_OK)
+ return -EBUSY;
+
+ /* Send address high byte */
+ c2port_write_dr(dev, offset >> 8);
+ ret = c2port_poll_in_busy(dev);
+ if (ret < 0)
+ return ret;
+
+ /* Send address low byte */
+ c2port_write_dr(dev, offset & 0x00ff);
+ ret = c2port_poll_in_busy(dev);
+ if (ret < 0)
+ return ret;
+
+ /* Send address block size */
+ c2port_write_dr(dev, nread);
+ ret = c2port_poll_in_busy(dev);
+ if (ret < 0)
+ return ret;
+
+ /* Should check status before reading FLASH block */
+
+ /* Wait for status information */
+ ret = c2port_poll_out_ready(dev);
+ if (ret < 0)
+ return ret;
+
+ /* Read flash programming interface status */
+ ret = c2port_read_dr(dev, &status);
+ if (ret < 0)
+ return ret;
+ if (status != C2PORT_COMMAND_OK)
+ return -EBUSY;
+
+ /* Read flash block */
+ for (i = 0; i < nread; i++) {
+ ret = c2port_poll_out_ready(dev);
+ if (ret < 0)
+ return ret;
+
+ ret = c2port_read_dr(dev, buffer+i);
+ if (ret < 0)
+ return ret;
+ }
+
+ return nread;
+}
+
+static ssize_t c2port_read_flash_data(struct kobject *kobj,
+ struct bin_attribute *attr,
+ char *buffer, loff_t offset, size_t count)
+{
+ struct c2port_device *c2dev =
+ dev_get_drvdata(container_of(kobj,
+ struct device, kobj));
+ ssize_t ret;
+
+ /* Check the device and flash access status */
+ if (!c2dev->access || !c2dev->flash_access)
+ return -EBUSY;
+
+ mutex_lock(&c2dev->mutex);
+ ret = __c2port_read_flash_data(c2dev, buffer, offset, count);
+ mutex_unlock(&c2dev->mutex);
+
+ if (ret < 0)
+ dev_err(c2dev->dev, "cannot read %s flash\n", c2dev->name);
+
+ return ret;
+}
+
+static ssize_t __c2port_write_flash_data(struct c2port_device *dev,
+ char *buffer, loff_t offset, size_t count)
+{
+ struct c2port_ops *ops = dev->ops;
+ u8 status, nwrite = 128;
+ int i, ret;
+
+ if (nwrite > count)
+ nwrite = count;
+ if (ops->block_size * ops->blocks_num - offset < nwrite)
+ nwrite = ops->block_size * ops->blocks_num - offset;
+
+ /* Check for flash end */
+ if (offset >= ops->block_size * ops->blocks_num)
+ return -EINVAL;
+
+ /* Target the C2 flash programming data register for C2 data register
+ * access */
+ c2port_write_ar(dev, C2PORT_FPDAT);
+
+ /* Send flash block write command */
+ c2port_write_dr(dev, C2PORT_BLOCK_WRITE);
+
+ /* Wait for input acknowledge */
+ ret = c2port_poll_in_busy(dev);
+ if (ret < 0)
+ return ret;
+
+ /* Should check status before starting FLASH access sequence */
+
+ /* Wait for status information */
+ ret = c2port_poll_out_ready(dev);
+ if (ret < 0)
+ return ret;
+
+ /* Read flash programming interface status */
+ ret = c2port_read_dr(dev, &status);
+ if (ret < 0)
+ return ret;
+ if (status != C2PORT_COMMAND_OK)
+ return -EBUSY;
+
+ /* Send address high byte */
+ c2port_write_dr(dev, offset >> 8);
+ ret = c2port_poll_in_busy(dev);
+ if (ret < 0)
+ return ret;
+
+ /* Send address low byte */
+ c2port_write_dr(dev, offset & 0x00ff);
+ ret = c2port_poll_in_busy(dev);
+ if (ret < 0)
+ return ret;
+
+ /* Send address block size */
+ c2port_write_dr(dev, nwrite);
+ ret = c2port_poll_in_busy(dev);
+ if (ret < 0)
+ return ret;
+
+ /* Should check status before writing FLASH block */
+
+ /* Wait for status information */
+ ret = c2port_poll_out_ready(dev);
+ if (ret < 0)
+ return ret;
+
+ /* Read flash programming interface status */
+ ret = c2port_read_dr(dev, &status);
+ if (ret < 0)
+ return ret;
+ if (status != C2PORT_COMMAND_OK)
+ return -EBUSY;
+
+ /* Write flash block */
+ for (i = 0; i < nwrite; i++) {
+ ret = c2port_write_dr(dev, *(buffer+i));
+ if (ret < 0)
+ return ret;
+
+ ret = c2port_poll_in_busy(dev);
+ if (ret < 0)
+ return ret;
+
+ }
+
+ /* Wait for last flash write to complete */
+ ret = c2port_poll_out_ready(dev);
+ if (ret < 0)
+ return ret;
+
+ return nwrite;
+}
+
+static ssize_t c2port_write_flash_data(struct kobject *kobj,
+ struct bin_attribute *attr,
+ char *buffer, loff_t offset, size_t count)
+{
+ struct c2port_device *c2dev =
+ dev_get_drvdata(container_of(kobj,
+ struct device, kobj));
+ int ret;
+
+ /* Check the device access status */
+ if (!c2dev->access || !c2dev->flash_access)
+ return -EBUSY;
+
+ mutex_lock(&c2dev->mutex);
+ ret = __c2port_write_flash_data(c2dev, buffer, offset, count);
+ mutex_unlock(&c2dev->mutex);
+
+ if (ret < 0)
+ dev_err(c2dev->dev, "cannot write %s flash\n", c2dev->name);
+
+ return ret;
+}
+
+/*
+ * Class attributes
+ */
+
+static struct device_attribute c2port_attrs[] = {
+ __ATTR(name, 0444, c2port_show_name, NULL),
+ __ATTR(flash_blocks_num, 0444, c2port_show_flash_blocks_num, NULL),
+ __ATTR(flash_block_size, 0444, c2port_show_flash_block_size, NULL),
+ __ATTR(flash_size, 0444, c2port_show_flash_size, NULL),
+ __ATTR(access, 0644, c2port_show_access, c2port_store_access),
+ __ATTR(reset, 0200, NULL, c2port_store_reset),
+ __ATTR(dev_id, 0444, c2port_show_dev_id, NULL),
+ __ATTR(rev_id, 0444, c2port_show_rev_id, NULL),
+
+ __ATTR(flash_access, 0644, c2port_show_flash_access,
+ c2port_store_flash_access),
+ __ATTR(flash_erase, 0200, NULL, c2port_store_flash_erase),
+ __ATTR_NULL,
+};
+
+static struct bin_attribute c2port_bin_attrs = {
+ .attr = {
+ .name = "flash_data",
+ .mode = 0644
+ },
+ .read = c2port_read_flash_data,
+ .write = c2port_write_flash_data,
+ /* .size is computed at run-time */
+};
+
+/*
+ * Exported functions
+ */
+
+struct c2port_device *c2port_device_register(char *name,
+ struct c2port_ops *ops, void *devdata)
+{
+ struct c2port_device *c2dev;
+ int id, ret;
+
+ if (unlikely(!ops) || unlikely(!ops->access) || \
+ unlikely(!ops->c2d_dir) || unlikely(!ops->c2ck_set) || \
+ unlikely(!ops->c2d_get) || unlikely(!ops->c2d_set))
+ return ERR_PTR(-EINVAL);
+
+ c2dev = kmalloc(sizeof(struct c2port_device), GFP_KERNEL);
+ if (unlikely(!c2dev))
+ return ERR_PTR(-ENOMEM);
+
+ ret = idr_pre_get(&c2port_idr, GFP_KERNEL);
+ if (!ret) {
+ ret = -ENOMEM;
+ goto error_idr_get_new;
+ }
+
+ spin_lock_irq(&c2port_idr_lock);
+ ret = idr_get_new(&c2port_idr, c2dev, &id);
+ spin_unlock_irq(&c2port_idr_lock);
+
+ if (ret < 0)
+ goto error_idr_get_new;
+ c2dev->id = id;
+
+ c2dev->dev = device_create(c2port_class, NULL, 0, c2dev,
+ "c2port%d", id);
+ if (unlikely(!c2dev->dev)) {
+ ret = -ENOMEM;
+ goto error_device_create;
+ }
+ dev_set_drvdata(c2dev->dev, c2dev);
+
+ strncpy(c2dev->name, name, C2PORT_NAME_LEN);
+ c2dev->ops = ops;
+ mutex_init(&c2dev->mutex);
+
+ /* Create binary file */
+ c2port_bin_attrs.size = ops->blocks_num * ops->block_size;
+ ret = device_create_bin_file(c2dev->dev, &c2port_bin_attrs);
+ if (unlikely(ret))
+ goto error_device_create_bin_file;
+
+ /* By default C2 port access is off */
+ c2dev->access = c2dev->flash_access = 0;
+ ops->access(c2dev, 0);
+
+ dev_info(c2dev->dev, "C2 port %s added\n", name);
+ dev_info(c2dev->dev, "%s flash has %d blocks x %d bytes "
+ "(%d bytes total)\n",
+ name, ops->blocks_num, ops->block_size,
+ ops->blocks_num * ops->block_size);
+
+ return c2dev;
+
+error_device_create_bin_file:
+ device_destroy(c2port_class, 0);
+
+error_device_create:
+ spin_lock_irq(&c2port_idr_lock);
+ idr_remove(&c2port_idr, id);
+ spin_unlock_irq(&c2port_idr_lock);
+
+error_idr_get_new:
+ kfree(c2dev);
+
+ return ERR_PTR(ret);
+}
+EXPORT_SYMBOL(c2port_device_register);
+
+void c2port_device_unregister(struct c2port_device *c2dev)
+{
+ if (!c2dev)
+ return;
+
+ dev_info(c2dev->dev, "C2 port %s removed\n", c2dev->name);
+
+ device_remove_bin_file(c2dev->dev, &c2port_bin_attrs);
+ spin_lock_irq(&c2port_idr_lock);
+ idr_remove(&c2port_idr, c2dev->id);
+ spin_unlock_irq(&c2port_idr_lock);
+
+ device_destroy(c2port_class, c2dev->id);
+
+ kfree(c2dev);
+}
+EXPORT_SYMBOL(c2port_device_unregister);
+
+/*
+ * Module stuff
+ */
+
+static int __init c2port_init(void)
+{
+ printk(KERN_INFO "Silicon Labs C2 port support v. " DRIVER_VERSION
+ " - (C) 2007 Rodolfo Giometti\n");
+
+ c2port_class = class_create(THIS_MODULE, "c2port");
+ if (!c2port_class) {
+ printk(KERN_ERR "c2port: failed to allocate class\n");
+ return -ENOMEM;
+ }
+ c2port_class->dev_attrs = c2port_attrs;
+
+ return 0;
+}
+
+static void __exit c2port_exit(void)
+{
+ class_destroy(c2port_class);
+}
+
+module_init(c2port_init);
+module_exit(c2port_exit);
+
+MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>");
+MODULE_DESCRIPTION("Silicon Labs C2 port support v. " DRIVER_VERSION);
+MODULE_LICENSE("GPL");
diff --git a/drivers/misc/compal-laptop.c b/drivers/misc/compal-laptop.c
index 344b790a625..11003bba10d 100644
--- a/drivers/misc/compal-laptop.c
+++ b/drivers/misc/compal-laptop.c
@@ -326,12 +326,14 @@ static int __init compal_init(void)
/* Register backlight stuff */
- compalbl_device = backlight_device_register("compal-laptop", NULL, NULL,
- &compalbl_ops);
- if (IS_ERR(compalbl_device))
- return PTR_ERR(compalbl_device);
+ if (!acpi_video_backlight_support()) {
+ compalbl_device = backlight_device_register("compal-laptop", NULL, NULL,
+ &compalbl_ops);
+ if (IS_ERR(compalbl_device))
+ return PTR_ERR(compalbl_device);
- compalbl_device->props.max_brightness = COMPAL_LCD_LEVEL_MAX-1;
+ compalbl_device->props.max_brightness = COMPAL_LCD_LEVEL_MAX-1;
+ }
ret = platform_driver_register(&compal_driver);
if (ret)
diff --git a/drivers/misc/eeepc-laptop.c b/drivers/misc/eeepc-laptop.c
index 9ef98b2d503..02fe2b8b893 100644
--- a/drivers/misc/eeepc-laptop.c
+++ b/drivers/misc/eeepc-laptop.c
@@ -825,9 +825,15 @@ static int __init eeepc_laptop_init(void)
return -ENODEV;
}
dev = acpi_get_physical_device(ehotk->device->handle);
- result = eeepc_backlight_init(dev);
- if (result)
- goto fail_backlight;
+
+ if (!acpi_video_backlight_support()) {
+ result = eeepc_backlight_init(dev);
+ if (result)
+ goto fail_backlight;
+ } else
+ printk(EEEPC_INFO "Backlight controlled by ACPI video "
+ "driver\n");
+
result = eeepc_hwmon_init(dev);
if (result)
goto fail_hwmon;
diff --git a/drivers/misc/fujitsu-laptop.c b/drivers/misc/fujitsu-laptop.c
index d2cf0bfe316..a7dd3e9fb79 100644
--- a/drivers/misc/fujitsu-laptop.c
+++ b/drivers/misc/fujitsu-laptop.c
@@ -464,6 +464,14 @@ static int dmi_check_cb_s6410(const struct dmi_system_id *id)
return 0;
}
+static int dmi_check_cb_s6420(const struct dmi_system_id *id)
+{
+ dmi_check_cb_common(id);
+ fujitsu->keycode1 = KEY_SCREENLOCK; /* "Lock" */
+ fujitsu->keycode2 = KEY_HELP; /* "Mobility Center" */
+ return 0;
+}
+
static int dmi_check_cb_p8010(const struct dmi_system_id *id)
{
dmi_check_cb_common(id);
@@ -473,7 +481,7 @@ static int dmi_check_cb_p8010(const struct dmi_system_id *id)
return 0;
}
-static struct dmi_system_id __initdata fujitsu_dmi_table[] = {
+static struct dmi_system_id fujitsu_dmi_table[] = {
{
.ident = "Fujitsu Siemens S6410",
.matches = {
@@ -482,6 +490,13 @@ static struct dmi_system_id __initdata fujitsu_dmi_table[] = {
},
.callback = dmi_check_cb_s6410},
{
+ .ident = "Fujitsu Siemens S6420",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK S6420"),
+ },
+ .callback = dmi_check_cb_s6420},
+ {
.ident = "Fujitsu LifeBook P8010",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
@@ -990,16 +1005,16 @@ static int __init fujitsu_init(void)
/* Register backlight stuff */
- fujitsu->bl_device =
- backlight_device_register("fujitsu-laptop", NULL, NULL,
- &fujitsubl_ops);
- if (IS_ERR(fujitsu->bl_device))
- return PTR_ERR(fujitsu->bl_device);
-
- max_brightness = fujitsu->max_brightness;
-
- fujitsu->bl_device->props.max_brightness = max_brightness - 1;
- fujitsu->bl_device->props.brightness = fujitsu->brightness_level;
+ if (!acpi_video_backlight_support()) {
+ fujitsu->bl_device =
+ backlight_device_register("fujitsu-laptop", NULL, NULL,
+ &fujitsubl_ops);
+ if (IS_ERR(fujitsu->bl_device))
+ return PTR_ERR(fujitsu->bl_device);
+ max_brightness = fujitsu->max_brightness;
+ fujitsu->bl_device->props.max_brightness = max_brightness - 1;
+ fujitsu->bl_device->props.brightness = fujitsu->brightness_level;
+ }
ret = platform_driver_register(&fujitsupf_driver);
if (ret)
@@ -1035,7 +1050,8 @@ fail_hotkey:
fail_backlight:
- backlight_device_unregister(fujitsu->bl_device);
+ if (fujitsu->bl_device)
+ backlight_device_unregister(fujitsu->bl_device);
fail_platform_device2:
@@ -1062,7 +1078,8 @@ static void __exit fujitsu_cleanup(void)
&fujitsupf_attribute_group);
platform_device_unregister(fujitsu->pf_device);
platform_driver_unregister(&fujitsupf_driver);
- backlight_device_unregister(fujitsu->bl_device);
+ if (fujitsu->bl_device)
+ backlight_device_unregister(fujitsu->bl_device);
acpi_bus_unregister_driver(&acpi_fujitsu_driver);
diff --git a/drivers/misc/ics932s401.c b/drivers/misc/ics932s401.c
new file mode 100644
index 00000000000..6e43ab4231a
--- /dev/null
+++ b/drivers/misc/ics932s401.c
@@ -0,0 +1,515 @@
+/*
+ * A driver for the Integrated Circuits ICS932S401
+ * Copyright (C) 2008 IBM
+ *
+ * Author: Darrick J. Wong <djwong@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/jiffies.h>
+#include <linux/i2c.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/log2.h>
+
+/* Addresses to scan */
+static const unsigned short normal_i2c[] = { 0x69, I2C_CLIENT_END };
+
+/* Insmod parameters */
+I2C_CLIENT_INSMOD_1(ics932s401);
+
+/* ICS932S401 registers */
+#define ICS932S401_REG_CFG2 0x01
+#define ICS932S401_CFG1_SPREAD 0x01
+#define ICS932S401_REG_CFG7 0x06
+#define ICS932S401_FS_MASK 0x07
+#define ICS932S401_REG_VENDOR_REV 0x07
+#define ICS932S401_VENDOR 1
+#define ICS932S401_VENDOR_MASK 0x0F
+#define ICS932S401_REV 4
+#define ICS932S401_REV_SHIFT 4
+#define ICS932S401_REG_DEVICE 0x09
+#define ICS932S401_DEVICE 11
+#define ICS932S401_REG_CTRL 0x0A
+#define ICS932S401_MN_ENABLED 0x80
+#define ICS932S401_CPU_ALT 0x04
+#define ICS932S401_SRC_ALT 0x08
+#define ICS932S401_REG_CPU_M_CTRL 0x0B
+#define ICS932S401_M_MASK 0x3F
+#define ICS932S401_REG_CPU_N_CTRL 0x0C
+#define ICS932S401_REG_CPU_SPREAD1 0x0D
+#define ICS932S401_REG_CPU_SPREAD2 0x0E
+#define ICS932S401_SPREAD_MASK 0x7FFF
+#define ICS932S401_REG_SRC_M_CTRL 0x0F
+#define ICS932S401_REG_SRC_N_CTRL 0x10
+#define ICS932S401_REG_SRC_SPREAD1 0x11
+#define ICS932S401_REG_SRC_SPREAD2 0x12
+#define ICS932S401_REG_CPU_DIVISOR 0x13
+#define ICS932S401_CPU_DIVISOR_SHIFT 4
+#define ICS932S401_REG_PCISRC_DIVISOR 0x14
+#define ICS932S401_SRC_DIVISOR_MASK 0x0F
+#define ICS932S401_PCI_DIVISOR_SHIFT 4
+
+/* Base clock is 14.318MHz */
+#define BASE_CLOCK 14318
+
+#define NUM_REGS 21
+#define NUM_MIRRORED_REGS 15
+
+static int regs_to_copy[NUM_MIRRORED_REGS] = {
+ ICS932S401_REG_CFG2,
+ ICS932S401_REG_CFG7,
+ ICS932S401_REG_VENDOR_REV,
+ ICS932S401_REG_DEVICE,
+ ICS932S401_REG_CTRL,
+ ICS932S401_REG_CPU_M_CTRL,
+ ICS932S401_REG_CPU_N_CTRL,
+ ICS932S401_REG_CPU_SPREAD1,
+ ICS932S401_REG_CPU_SPREAD2,
+ ICS932S401_REG_SRC_M_CTRL,
+ ICS932S401_REG_SRC_N_CTRL,
+ ICS932S401_REG_SRC_SPREAD1,
+ ICS932S401_REG_SRC_SPREAD2,
+ ICS932S401_REG_CPU_DIVISOR,
+ ICS932S401_REG_PCISRC_DIVISOR,
+};
+
+/* How often do we reread sensors values? (In jiffies) */
+#define SENSOR_REFRESH_INTERVAL (2 * HZ)
+
+/* How often do we reread sensor limit values? (In jiffies) */
+#define LIMIT_REFRESH_INTERVAL (60 * HZ)
+
+struct ics932s401_data {
+ struct attribute_group attrs;
+ struct mutex lock;
+ char sensors_valid;
+ unsigned long sensors_last_updated; /* In jiffies */
+
+ u8 regs[NUM_REGS];
+};
+
+static int ics932s401_probe(struct i2c_client *client,
+ const struct i2c_device_id *id);
+static int ics932s401_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info);
+static int ics932s401_remove(struct i2c_client *client);
+
+static const struct i2c_device_id ics932s401_id[] = {
+ { "ics932s401", ics932s401 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, ics932s401_id);
+
+static struct i2c_driver ics932s401_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "ics932s401",
+ },
+ .probe = ics932s401_probe,
+ .remove = ics932s401_remove,
+ .id_table = ics932s401_id,
+ .detect = ics932s401_detect,
+ .address_data = &addr_data,
+};
+
+static struct ics932s401_data *ics932s401_update_device(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct ics932s401_data *data = i2c_get_clientdata(client);
+ unsigned long local_jiffies = jiffies;
+ int i, temp;
+
+ mutex_lock(&data->lock);
+ if (time_before(local_jiffies, data->sensors_last_updated +
+ SENSOR_REFRESH_INTERVAL)
+ && data->sensors_valid)
+ goto out;
+
+ /*
+ * Each register must be read as a word and then right shifted 8 bits.
+ * Not really sure why this is; setting the "byte count programming"
+ * register to 1 does not fix this problem.
+ */
+ for (i = 0; i < NUM_MIRRORED_REGS; i++) {
+ temp = i2c_smbus_read_word_data(client, regs_to_copy[i]);
+ data->regs[regs_to_copy[i]] = temp >> 8;
+ }
+
+ data->sensors_last_updated = local_jiffies;
+ data->sensors_valid = 1;
+
+out:
+ mutex_unlock(&data->lock);
+ return data;
+}
+
+static ssize_t show_spread_enabled(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct ics932s401_data *data = ics932s401_update_device(dev);
+
+ if (data->regs[ICS932S401_REG_CFG2] & ICS932S401_CFG1_SPREAD)
+ return sprintf(buf, "1\n");
+
+ return sprintf(buf, "0\n");
+}
+
+/* bit to cpu khz map */
+static const int fs_speeds[] = {
+ 266666,
+ 133333,
+ 200000,
+ 166666,
+ 333333,
+ 100000,
+ 400000,
+ 0,
+};
+
+/* clock divisor map */
+static const int divisors[] = {2, 3, 5, 15, 4, 6, 10, 30, 8, 12, 20, 60, 16,
+ 24, 40, 120};
+
+/* Calculate CPU frequency from the M/N registers. */
+static int calculate_cpu_freq(struct ics932s401_data *data)
+{
+ int m, n, freq;
+
+ m = data->regs[ICS932S401_REG_CPU_M_CTRL] & ICS932S401_M_MASK;
+ n = data->regs[ICS932S401_REG_CPU_N_CTRL];
+
+ /* Pull in bits 8 & 9 from the M register */
+ n |= ((int)data->regs[ICS932S401_REG_CPU_M_CTRL] & 0x80) << 1;
+ n |= ((int)data->regs[ICS932S401_REG_CPU_M_CTRL] & 0x40) << 3;
+
+ freq = BASE_CLOCK * (n + 8) / (m + 2);
+ freq /= divisors[data->regs[ICS932S401_REG_CPU_DIVISOR] >>
+ ICS932S401_CPU_DIVISOR_SHIFT];
+
+ return freq;
+}
+
+static ssize_t show_cpu_clock(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct ics932s401_data *data = ics932s401_update_device(dev);
+
+ return sprintf(buf, "%d\n", calculate_cpu_freq(data));
+}
+
+static ssize_t show_cpu_clock_sel(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct ics932s401_data *data = ics932s401_update_device(dev);
+ int freq;
+
+ if (data->regs[ICS932S401_REG_CTRL] & ICS932S401_MN_ENABLED)
+ freq = calculate_cpu_freq(data);
+ else {
+ /* Freq is neatly wrapped up for us */
+ int fid = data->regs[ICS932S401_REG_CFG7] & ICS932S401_FS_MASK;
+ freq = fs_speeds[fid];
+ if (data->regs[ICS932S401_REG_CTRL] & ICS932S401_CPU_ALT) {
+ switch (freq) {
+ case 166666:
+ freq = 160000;
+ break;
+ case 333333:
+ freq = 320000;
+ break;
+ }
+ }
+ }
+
+ return sprintf(buf, "%d\n", freq);
+}
+
+/* Calculate SRC frequency from the M/N registers. */
+static int calculate_src_freq(struct ics932s401_data *data)
+{
+ int m, n, freq;
+
+ m = data->regs[ICS932S401_REG_SRC_M_CTRL] & ICS932S401_M_MASK;
+ n = data->regs[ICS932S401_REG_SRC_N_CTRL];
+
+ /* Pull in bits 8 & 9 from the M register */
+ n |= ((int)data->regs[ICS932S401_REG_SRC_M_CTRL] & 0x80) << 1;
+ n |= ((int)data->regs[ICS932S401_REG_SRC_M_CTRL] & 0x40) << 3;
+
+ freq = BASE_CLOCK * (n + 8) / (m + 2);
+ freq /= divisors[data->regs[ICS932S401_REG_PCISRC_DIVISOR] &
+ ICS932S401_SRC_DIVISOR_MASK];
+
+ return freq;
+}
+
+static ssize_t show_src_clock(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct ics932s401_data *data = ics932s401_update_device(dev);
+
+ return sprintf(buf, "%d\n", calculate_src_freq(data));
+}
+
+static ssize_t show_src_clock_sel(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct ics932s401_data *data = ics932s401_update_device(dev);
+ int freq;
+
+ if (data->regs[ICS932S401_REG_CTRL] & ICS932S401_MN_ENABLED)
+ freq = calculate_src_freq(data);
+ else
+ /* Freq is neatly wrapped up for us */
+ if (data->regs[ICS932S401_REG_CTRL] & ICS932S401_CPU_ALT &&
+ data->regs[ICS932S401_REG_CTRL] & ICS932S401_SRC_ALT)
+ freq = 96000;
+ else
+ freq = 100000;
+
+ return sprintf(buf, "%d\n", freq);
+}
+
+/* Calculate PCI frequency from the SRC M/N registers. */
+static int calculate_pci_freq(struct ics932s401_data *data)
+{
+ int m, n, freq;
+
+ m = data->regs[ICS932S401_REG_SRC_M_CTRL] & ICS932S401_M_MASK;
+ n = data->regs[ICS932S401_REG_SRC_N_CTRL];
+
+ /* Pull in bits 8 & 9 from the M register */
+ n |= ((int)data->regs[ICS932S401_REG_SRC_M_CTRL] & 0x80) << 1;
+ n |= ((int)data->regs[ICS932S401_REG_SRC_M_CTRL] & 0x40) << 3;
+
+ freq = BASE_CLOCK * (n + 8) / (m + 2);
+ freq /= divisors[data->regs[ICS932S401_REG_PCISRC_DIVISOR] >>
+ ICS932S401_PCI_DIVISOR_SHIFT];
+
+ return freq;
+}
+
+static ssize_t show_pci_clock(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct ics932s401_data *data = ics932s401_update_device(dev);
+
+ return sprintf(buf, "%d\n", calculate_pci_freq(data));
+}
+
+static ssize_t show_pci_clock_sel(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct ics932s401_data *data = ics932s401_update_device(dev);
+ int freq;
+
+ if (data->regs[ICS932S401_REG_CTRL] & ICS932S401_MN_ENABLED)
+ freq = calculate_pci_freq(data);
+ else
+ freq = 33333;
+
+ return sprintf(buf, "%d\n", freq);
+}
+
+static ssize_t show_value(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf);
+
+static ssize_t show_spread(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf);
+
+static DEVICE_ATTR(spread_enabled, S_IRUGO, show_spread_enabled, NULL);
+static DEVICE_ATTR(cpu_clock_selection, S_IRUGO, show_cpu_clock_sel, NULL);
+static DEVICE_ATTR(cpu_clock, S_IRUGO, show_cpu_clock, NULL);
+static DEVICE_ATTR(src_clock_selection, S_IRUGO, show_src_clock_sel, NULL);
+static DEVICE_ATTR(src_clock, S_IRUGO, show_src_clock, NULL);
+static DEVICE_ATTR(pci_clock_selection, S_IRUGO, show_pci_clock_sel, NULL);
+static DEVICE_ATTR(pci_clock, S_IRUGO, show_pci_clock, NULL);
+static DEVICE_ATTR(usb_clock, S_IRUGO, show_value, NULL);
+static DEVICE_ATTR(ref_clock, S_IRUGO, show_value, NULL);
+static DEVICE_ATTR(cpu_spread, S_IRUGO, show_spread, NULL);
+static DEVICE_ATTR(src_spread, S_IRUGO, show_spread, NULL);
+
+static struct attribute *ics932s401_attr[] =
+{
+ &dev_attr_spread_enabled.attr,
+ &dev_attr_cpu_clock_selection.attr,
+ &dev_attr_cpu_clock.attr,
+ &dev_attr_src_clock_selection.attr,
+ &dev_attr_src_clock.attr,
+ &dev_attr_pci_clock_selection.attr,
+ &dev_attr_pci_clock.attr,
+ &dev_attr_usb_clock.attr,
+ &dev_attr_ref_clock.attr,
+ &dev_attr_cpu_spread.attr,
+ &dev_attr_src_spread.attr,
+ NULL
+};
+
+static ssize_t show_value(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ int x;
+
+ if (devattr == &dev_attr_usb_clock)
+ x = 48000;
+ else if (devattr == &dev_attr_ref_clock)
+ x = BASE_CLOCK;
+ else
+ BUG();
+
+ return sprintf(buf, "%d\n", x);
+}
+
+static ssize_t show_spread(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct ics932s401_data *data = ics932s401_update_device(dev);
+ int reg;
+ unsigned long val;
+
+ if (!(data->regs[ICS932S401_REG_CFG2] & ICS932S401_CFG1_SPREAD))
+ return sprintf(buf, "0%%\n");
+
+ if (devattr == &dev_attr_src_spread)
+ reg = ICS932S401_REG_SRC_SPREAD1;
+ else if (devattr == &dev_attr_cpu_spread)
+ reg = ICS932S401_REG_CPU_SPREAD1;
+ else
+ BUG();
+
+ val = data->regs[reg] | (data->regs[reg + 1] << 8);
+ val &= ICS932S401_SPREAD_MASK;
+
+ /* Scale 0..2^14 to -0.5. */
+ val = 500000 * val / 16384;
+ return sprintf(buf, "-0.%lu%%\n", val);
+}
+
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int ics932s401_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info)
+{
+ struct i2c_adapter *adapter = client->adapter;
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ return -ENODEV;
+
+ if (kind <= 0) {
+ int vendor, device, revision;
+
+ vendor = i2c_smbus_read_word_data(client,
+ ICS932S401_REG_VENDOR_REV);
+ vendor >>= 8;
+ revision = vendor >> ICS932S401_REV_SHIFT;
+ vendor &= ICS932S401_VENDOR_MASK;
+ if (vendor != ICS932S401_VENDOR)
+ return -ENODEV;
+
+ device = i2c_smbus_read_word_data(client,
+ ICS932S401_REG_DEVICE);
+ device >>= 8;
+ if (device != ICS932S401_DEVICE)
+ return -ENODEV;
+
+ if (revision != ICS932S401_REV)
+ dev_info(&adapter->dev, "Unknown revision %d\n",
+ revision);
+ } else
+ dev_dbg(&adapter->dev, "detection forced\n");
+
+ strlcpy(info->type, "ics932s401", I2C_NAME_SIZE);
+
+ return 0;
+}
+
+static int ics932s401_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct ics932s401_data *data;
+ int err;
+
+ data = kzalloc(sizeof(struct ics932s401_data), GFP_KERNEL);
+ if (!data) {
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ i2c_set_clientdata(client, data);
+ mutex_init(&data->lock);
+
+ dev_info(&client->dev, "%s chip found\n", client->name);
+
+ /* Register sysfs hooks */
+ data->attrs.attrs = ics932s401_attr;
+ err = sysfs_create_group(&client->dev.kobj, &data->attrs);
+ if (err)
+ goto exit_free;
+
+ return 0;
+
+exit_free:
+ kfree(data);
+exit:
+ return err;
+}
+
+static int ics932s401_remove(struct i2c_client *client)
+{
+ struct ics932s401_data *data = i2c_get_clientdata(client);
+
+ sysfs_remove_group(&client->dev.kobj, &data->attrs);
+ kfree(data);
+ return 0;
+}
+
+static int __init ics932s401_init(void)
+{
+ return i2c_add_driver(&ics932s401_driver);
+}
+
+static void __exit ics932s401_exit(void)
+{
+ i2c_del_driver(&ics932s401_driver);
+}
+
+MODULE_AUTHOR("Darrick J. Wong <djwong@us.ibm.com>");
+MODULE_DESCRIPTION("ICS932S401 driver");
+MODULE_LICENSE("GPL");
+
+module_init(ics932s401_init);
+module_exit(ics932s401_exit);
+
+/* IBM IntelliStation Z30 */
+MODULE_ALIAS("dmi:bvnIBM:*:rn9228:*");
+MODULE_ALIAS("dmi:bvnIBM:*:rn9232:*");
+
+/* IBM x3650/x3550 */
+MODULE_ALIAS("dmi:bvnIBM:*:pnIBMSystemx3650*");
+MODULE_ALIAS("dmi:bvnIBM:*:pnIBMSystemx3550*");
diff --git a/drivers/misc/intel_menlow.c b/drivers/misc/intel_menlow.c
index e00a2756e97..27b7662955b 100644
--- a/drivers/misc/intel_menlow.c
+++ b/drivers/misc/intel_menlow.c
@@ -52,6 +52,11 @@ MODULE_LICENSE("GPL");
#define MEMORY_ARG_CUR_BANDWIDTH 1
#define MEMORY_ARG_MAX_BANDWIDTH 0
+/*
+ * GTHS returning 'n' would mean that [0,n-1] states are supported
+ * In that case max_cstate would be n-1
+ * GTHS returning '0' would mean that no bandwidth control states are supported
+ */
static int memory_get_int_max_bandwidth(struct thermal_cooling_device *cdev,
unsigned long *max_state)
{
@@ -71,6 +76,9 @@ static int memory_get_int_max_bandwidth(struct thermal_cooling_device *cdev,
if (ACPI_FAILURE(status))
return -EFAULT;
+ if (!value)
+ return -EINVAL;
+
*max_state = value - 1;
return 0;
}
@@ -121,7 +129,7 @@ static int memory_set_cur_bandwidth(struct thermal_cooling_device *cdev,
if (memory_get_int_max_bandwidth(cdev, &max_state))
return -EFAULT;
- if (max_state < 0 || state > max_state)
+ if (state > max_state)
return -EINVAL;
arg_list.count = 1;
diff --git a/drivers/misc/msi-laptop.c b/drivers/misc/msi-laptop.c
index de898c6938f..759763d18e4 100644
--- a/drivers/misc/msi-laptop.c
+++ b/drivers/misc/msi-laptop.c
@@ -347,12 +347,16 @@ static int __init msi_init(void)
/* Register backlight stuff */
- msibl_device = backlight_device_register("msi-laptop-bl", NULL, NULL,
- &msibl_ops);
- if (IS_ERR(msibl_device))
- return PTR_ERR(msibl_device);
-
- msibl_device->props.max_brightness = MSI_LCD_LEVEL_MAX-1;
+ if (acpi_video_backlight_support()) {
+ printk(KERN_INFO "MSI: Brightness ignored, must be controlled "
+ "by ACPI video driver\n");
+ } else {
+ msibl_device = backlight_device_register("msi-laptop-bl", NULL,
+ NULL, &msibl_ops);
+ if (IS_ERR(msibl_device))
+ return PTR_ERR(msibl_device);
+ msibl_device->props.max_brightness = MSI_LCD_LEVEL_MAX-1;
+ }
ret = platform_driver_register(&msipf_driver);
if (ret)
diff --git a/drivers/misc/sgi-gru/Makefile b/drivers/misc/sgi-gru/Makefile
index d03597a521b..9e9170b3599 100644
--- a/drivers/misc/sgi-gru/Makefile
+++ b/drivers/misc/sgi-gru/Makefile
@@ -1,3 +1,7 @@
+ifdef CONFIG_SGI_GRU_DEBUG
+ EXTRA_CFLAGS += -DDEBUG
+endif
+
obj-$(CONFIG_SGI_GRU) := gru.o
gru-y := grufile.o grumain.o grufault.o grutlbpurge.o gruprocfs.o grukservices.o
diff --git a/drivers/misc/sgi-gru/grufault.c b/drivers/misc/sgi-gru/grufault.c
index 8c389d606c3..3ee698ad859 100644
--- a/drivers/misc/sgi-gru/grufault.c
+++ b/drivers/misc/sgi-gru/grufault.c
@@ -254,7 +254,11 @@ static int atomic_pte_lookup(struct vm_area_struct *vma, unsigned long vaddr,
return 1;
*paddr = pte_pfn(pte) << PAGE_SHIFT;
+#ifdef CONFIG_HUGETLB_PAGE
*pageshift = is_vm_hugetlb_page(vma) ? HPAGE_SHIFT : PAGE_SHIFT;
+#else
+ *pageshift = PAGE_SHIFT;
+#endif
return 0;
err:
diff --git a/drivers/misc/sgi-gru/grufile.c b/drivers/misc/sgi-gru/grufile.c
index 5c027b6b4e5..65098380639 100644
--- a/drivers/misc/sgi-gru/grufile.c
+++ b/drivers/misc/sgi-gru/grufile.c
@@ -481,7 +481,7 @@ struct vm_operations_struct gru_vm_ops = {
.fault = gru_fault,
};
-module_init(gru_init);
+fs_initcall(gru_init);
module_exit(gru_exit);
module_param(gru_options, ulong, 0644);
diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c
index 06f07e19dc7..571b211608d 100644
--- a/drivers/misc/sony-laptop.c
+++ b/drivers/misc/sony-laptop.c
@@ -1038,7 +1038,11 @@ static int sony_nc_add(struct acpi_device *device)
goto outinput;
}
- if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT", &handle))) {
+ if (acpi_video_backlight_support()) {
+ printk(KERN_INFO DRV_PFX "brightness ignored, must be "
+ "controlled by ACPI video driver\n");
+ } else if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT",
+ &handle))) {
sony_backlight_device = backlight_device_register("sony", NULL,
NULL,
&sony_backlight_ops);
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c
index 4db1cf9078d..899766e16fa 100644
--- a/drivers/misc/thinkpad_acpi.c
+++ b/drivers/misc/thinkpad_acpi.c
@@ -4932,16 +4932,25 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
*/
b = tpacpi_check_std_acpi_brightness_support();
if (b > 0) {
- if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) {
- printk(TPACPI_NOTICE
- "Lenovo BIOS switched to ACPI backlight "
- "control mode\n");
- }
- if (brightness_enable > 1) {
- printk(TPACPI_NOTICE
- "standard ACPI backlight interface "
- "available, not loading native one...\n");
- return 1;
+
+ if (acpi_video_backlight_support()) {
+ if (brightness_enable > 1) {
+ printk(TPACPI_NOTICE
+ "Standard ACPI backlight interface "
+ "available, not loading native one.\n");
+ return 1;
+ } else if (brightness_enable == 1) {
+ printk(TPACPI_NOTICE
+ "Backlight control force enabled, even if standard "
+ "ACPI backlight interface is available\n");
+ }
+ } else {
+ if (brightness_enable > 1) {
+ printk(TPACPI_NOTICE
+ "Standard ACPI backlight interface not "
+ "available, thinkpad_acpi native "
+ "brightness control enabled\n");
+ }
}
}
@@ -5309,6 +5318,7 @@ static enum fan_control_commands fan_control_commands;
static u8 fan_control_initial_status;
static u8 fan_control_desired_level;
+static u8 fan_control_resume_level;
static int fan_watchdog_maxinterval;
static struct mutex fan_mutex;
@@ -5431,8 +5441,8 @@ static int fan_set_level(int level)
case TPACPI_FAN_WR_ACPI_FANS:
case TPACPI_FAN_WR_TPEC:
- if ((level != TP_EC_FAN_AUTO) &&
- (level != TP_EC_FAN_FULLSPEED) &&
+ if (!(level & TP_EC_FAN_AUTO) &&
+ !(level & TP_EC_FAN_FULLSPEED) &&
((level < 0) || (level > 7)))
return -EINVAL;
@@ -5996,38 +6006,67 @@ static void fan_exit(void)
static void fan_suspend(pm_message_t state)
{
+ int rc;
+
if (!fan_control_allowed)
return;
/* Store fan status in cache */
- fan_get_status_safe(NULL);
+ fan_control_resume_level = 0;
+ rc = fan_get_status_safe(&fan_control_resume_level);
+ if (rc < 0)
+ printk(TPACPI_NOTICE
+ "failed to read fan level for later "
+ "restore during resume: %d\n", rc);
+
+ /* if it is undefined, don't attempt to restore it.
+ * KEEP THIS LAST */
if (tp_features.fan_ctrl_status_undef)
- fan_control_desired_level = TP_EC_FAN_AUTO;
+ fan_control_resume_level = 0;
}
static void fan_resume(void)
{
- u8 saved_fan_level;
u8 current_level = 7;
bool do_set = false;
+ int rc;
/* DSDT *always* updates status on resume */
tp_features.fan_ctrl_status_undef = 0;
- saved_fan_level = fan_control_desired_level;
if (!fan_control_allowed ||
+ !fan_control_resume_level ||
(fan_get_status_safe(&current_level) < 0))
return;
switch (fan_control_access_mode) {
case TPACPI_FAN_WR_ACPI_SFAN:
- do_set = (saved_fan_level > current_level);
+ /* never decrease fan level */
+ do_set = (fan_control_resume_level > current_level);
break;
case TPACPI_FAN_WR_ACPI_FANS:
case TPACPI_FAN_WR_TPEC:
- do_set = ((saved_fan_level & TP_EC_FAN_FULLSPEED) ||
- (saved_fan_level == 7 &&
- !(current_level & TP_EC_FAN_FULLSPEED)));
+ /* never decrease fan level, scale is:
+ * TP_EC_FAN_FULLSPEED > 7 >= TP_EC_FAN_AUTO
+ *
+ * We expect the firmware to set either 7 or AUTO, but we
+ * handle FULLSPEED out of paranoia.
+ *
+ * So, we can safely only restore FULLSPEED or 7, anything
+ * else could slow the fan. Restoring AUTO is useless, at
+ * best that's exactly what the DSDT already set (it is the
+ * slower it uses).
+ *
+ * Always keep in mind that the DSDT *will* have set the
+ * fans to what the vendor supposes is the best level. We
+ * muck with it only to speed the fan up.
+ */
+ if (fan_control_resume_level != 7 &&
+ !(fan_control_resume_level & TP_EC_FAN_FULLSPEED))
+ return;
+ else
+ do_set = !(current_level & TP_EC_FAN_FULLSPEED) &&
+ (current_level != fan_control_resume_level);
break;
default:
return;
@@ -6035,8 +6074,11 @@ static void fan_resume(void)
if (do_set) {
printk(TPACPI_NOTICE
"restoring fan level to 0x%02x\n",
- saved_fan_level);
- fan_set_level_safe(saved_fan_level);
+ fan_control_resume_level);
+ rc = fan_set_level_safe(fan_control_resume_level);
+ if (rc < 0)
+ printk(TPACPI_NOTICE
+ "failed to restore fan level: %d\n", rc);
}
}
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 76a76751da3..6659b2275c0 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -37,9 +37,9 @@
#define OPCODE_NORM_READ 0x03 /* Read data bytes (low frequency) */
#define OPCODE_FAST_READ 0x0b /* Read data bytes (high frequency) */
#define OPCODE_PP 0x02 /* Page program (up to 256 bytes) */
-#define OPCODE_BE_4K 0x20 /* Erase 4KiB block */
+#define OPCODE_BE_4K 0x20 /* Erase 4KiB block */
#define OPCODE_BE_32K 0x52 /* Erase 32KiB block */
-#define OPCODE_BE 0xc7 /* Erase whole flash block */
+#define OPCODE_CHIP_ERASE 0xc7 /* Erase whole flash chip */
#define OPCODE_SE 0xd8 /* Sector erase (usually 64KiB) */
#define OPCODE_RDID 0x9f /* Read JEDEC ID */
@@ -167,7 +167,7 @@ static int wait_till_ready(struct m25p *flash)
*
* Returns 0 if successful, non-zero otherwise.
*/
-static int erase_block(struct m25p *flash)
+static int erase_chip(struct m25p *flash)
{
DEBUG(MTD_DEBUG_LEVEL3, "%s: %s %dKiB\n",
flash->spi->dev.bus_id, __func__,
@@ -181,7 +181,7 @@ static int erase_block(struct m25p *flash)
write_enable(flash);
/* Set up command buffer. */
- flash->command[0] = OPCODE_BE;
+ flash->command[0] = OPCODE_CHIP_ERASE;
spi_write(flash->spi, flash->command, 1);
@@ -250,15 +250,18 @@ static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr)
mutex_lock(&flash->lock);
- /* REVISIT in some cases we could speed up erasing large regions
- * by using OPCODE_SE instead of OPCODE_BE_4K
- */
-
- /* now erase those sectors */
- if (len == flash->mtd.size && erase_block(flash)) {
+ /* whole-chip erase? */
+ if (len == flash->mtd.size && erase_chip(flash)) {
instr->state = MTD_ERASE_FAILED;
mutex_unlock(&flash->lock);
return -EIO;
+
+ /* REVISIT in some cases we could speed up erasing large regions
+ * by using OPCODE_SE instead of OPCODE_BE_4K. We may have set up
+ * to use "small sector erase", but that's not always optimal.
+ */
+
+ /* "sector"-at-a-time erase */
} else {
while (len) {
if (erase_sector(flash, addr)) {
@@ -574,10 +577,11 @@ static struct flash_info *__devinit jedec_probe(struct spi_device *spi)
for (tmp = 0, info = m25p_data;
tmp < ARRAY_SIZE(m25p_data);
tmp++, info++) {
- if (info->jedec_id == jedec)
- if (ext_jedec != 0 && info->ext_id != ext_jedec)
+ if (info->jedec_id == jedec) {
+ if (info->ext_id != 0 && info->ext_id != ext_jedec)
continue;
return info;
+ }
}
dev_err(&spi->dev, "unrecognized JEDEC id %06x\n", jedec);
return NULL;
diff --git a/drivers/mtd/maps/cdb89712.c b/drivers/mtd/maps/cdb89712.c
index e5059aa3c72..8d92d8db9a9 100644
--- a/drivers/mtd/maps/cdb89712.c
+++ b/drivers/mtd/maps/cdb89712.c
@@ -14,7 +14,18 @@
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
-
+/* dynamic ioremap() areas */
+#define FLASH_START 0x00000000
+#define FLASH_SIZE 0x800000
+#define FLASH_WIDTH 4
+
+#define SRAM_START 0x60000000
+#define SRAM_SIZE 0xc000
+#define SRAM_WIDTH 4
+
+#define BOOTROM_START 0x70000000
+#define BOOTROM_SIZE 0x80
+#define BOOTROM_WIDTH 4
static struct mtd_info *flash_mtd;
diff --git a/drivers/mtd/maps/h720x-flash.c b/drivers/mtd/maps/h720x-flash.c
index 35fef655ccc..3b959fad1c4 100644
--- a/drivers/mtd/maps/h720x-flash.c
+++ b/drivers/mtd/maps/h720x-flash.c
@@ -24,8 +24,8 @@ static struct mtd_info *mymtd;
static struct map_info h720x_map = {
.name = "H720X",
.bankwidth = 4,
- .size = FLASH_SIZE,
- .phys = FLASH_PHYS,
+ .size = H720X_FLASH_SIZE,
+ .phys = H720X_FLASH_PHYS,
};
static struct mtd_partition h720x_partitions[] = {
@@ -70,7 +70,7 @@ int __init h720x_mtd_init(void)
char *part_type = NULL;
- h720x_map.virt = ioremap(FLASH_PHYS, FLASH_SIZE);
+ h720x_map.virt = ioremap(h720x_map.phys, h720x_map.size);
if (!h720x_map.virt) {
printk(KERN_ERR "H720x-MTD: ioremap failed\n");
diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c
index 42d844f8f6b..dfbf3f270ce 100644
--- a/drivers/mtd/maps/physmap.c
+++ b/drivers/mtd/maps/physmap.c
@@ -19,7 +19,7 @@
#include <linux/mtd/partitions.h>
#include <linux/mtd/physmap.h>
#include <linux/mtd/concat.h>
-#include <asm/io.h>
+#include <linux/io.h>
#define MAX_RESOURCES 4
@@ -27,7 +27,6 @@ struct physmap_flash_info {
struct mtd_info *mtd[MAX_RESOURCES];
struct mtd_info *cmtd;
struct map_info map[MAX_RESOURCES];
- struct resource *res;
#ifdef CONFIG_MTD_PARTITIONS
int nr_parts;
struct mtd_partition *parts;
@@ -70,16 +69,7 @@ static int physmap_flash_remove(struct platform_device *dev)
#endif
map_destroy(info->mtd[i]);
}
-
- if (info->map[i].virt != NULL)
- iounmap(info->map[i].virt);
- }
-
- if (info->res != NULL) {
- release_resource(info->res);
- kfree(info->res);
}
-
return 0;
}
@@ -101,7 +91,8 @@ static int physmap_flash_probe(struct platform_device *dev)
if (physmap_data == NULL)
return -ENODEV;
- info = kzalloc(sizeof(struct physmap_flash_info), GFP_KERNEL);
+ info = devm_kzalloc(&dev->dev, sizeof(struct physmap_flash_info),
+ GFP_KERNEL);
if (info == NULL) {
err = -ENOMEM;
goto err_out;
@@ -114,10 +105,10 @@ static int physmap_flash_probe(struct platform_device *dev)
(unsigned long long)(dev->resource[i].end - dev->resource[i].start + 1),
(unsigned long long)dev->resource[i].start);
- info->res = request_mem_region(dev->resource[i].start,
- dev->resource[i].end - dev->resource[i].start + 1,
- dev->dev.bus_id);
- if (info->res == NULL) {
+ if (!devm_request_mem_region(&dev->dev,
+ dev->resource[i].start,
+ dev->resource[i].end - dev->resource[i].start + 1,
+ dev->dev.bus_id)) {
dev_err(&dev->dev, "Could not reserve memory region\n");
err = -ENOMEM;
goto err_out;
@@ -129,7 +120,8 @@ static int physmap_flash_probe(struct platform_device *dev)
info->map[i].bankwidth = physmap_data->width;
info->map[i].set_vpp = physmap_data->set_vpp;
- info->map[i].virt = ioremap(info->map[i].phys, info->map[i].size);
+ info->map[i].virt = devm_ioremap(&dev->dev, info->map[i].phys,
+ info->map[i].size);
if (info->map[i].virt == NULL) {
dev_err(&dev->dev, "Failed to ioremap flash region\n");
err = EIO;
diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c
index 024e3fffd4b..a83192f80eb 100644
--- a/drivers/mtd/nand/fsl_upm.c
+++ b/drivers/mtd/nand/fsl_upm.c
@@ -163,9 +163,11 @@ static int __devinit fun_chip_init(struct fsl_upm_nand *fun,
ret = parse_mtd_partitions(&fun->mtd, part_types, &fun->parts, 0);
#ifdef CONFIG_MTD_OF_PARTS
- if (ret == 0)
- ret = of_mtd_parse_partitions(fun->dev, &fun->mtd,
- flash_np, &fun->parts);
+ if (ret == 0) {
+ ret = of_mtd_parse_partitions(fun->dev, flash_np, &fun->parts);
+ if (ret < 0)
+ goto err;
+ }
#endif
if (ret > 0)
ret = add_mtd_partitions(&fun->mtd, fun->parts, ret);
diff --git a/drivers/mtd/nand/pasemi_nand.c b/drivers/mtd/nand/pasemi_nand.c
index 75c89903902..9bd6c9ac844 100644
--- a/drivers/mtd/nand/pasemi_nand.c
+++ b/drivers/mtd/nand/pasemi_nand.c
@@ -141,6 +141,7 @@ static int __devinit pasemi_nand_probe(struct of_device *ofdev,
}
lpcctl = pci_resource_start(pdev, 0);
+ pci_dev_put(pdev);
if (!request_region(lpcctl, 4, driver_name)) {
err = -EBUSY;
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index c0fa9c9edf0..15f0a26730a 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -269,6 +269,7 @@ static struct pxa3xx_nand_timing stm2GbX16_timing = {
static struct pxa3xx_nand_flash stm2GbX16 = {
.timing = &stm2GbX16_timing,
+ .cmdset = &largepage_cmdset,
.page_per_block = 64,
.page_size = 2048,
.flash_width = 16,
diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c
index e39b21d3e16..a7e4d985f5e 100644
--- a/drivers/mtd/onenand/omap2.c
+++ b/drivers/mtd/onenand/omap2.c
@@ -32,19 +32,18 @@
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
-#include <asm/io.h>
#include <asm/mach/flash.h>
-#include <asm/arch/gpmc.h>
-#include <asm/arch/onenand.h>
-#include <asm/arch/gpio.h>
-#include <asm/arch/pm.h>
+#include <mach/gpmc.h>
+#include <mach/onenand.h>
+#include <mach/gpio.h>
+#include <mach/pm.h>
-#include <linux/dma-mapping.h>
-#include <asm/dma-mapping.h>
-#include <asm/arch/dma.h>
+#include <mach/dma.h>
-#include <asm/arch/board.h>
+#include <mach/board.h>
#define DRIVER_NAME "omap2-onenand"
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c
index e04bcf1dff8..d8966bae0e0 100644
--- a/drivers/mtd/ubi/eba.c
+++ b/drivers/mtd/ubi/eba.c
@@ -1022,7 +1022,7 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
}
/*
- * OK, now the LEB is locked and we can safely start moving iy. Since
+ * OK, now the LEB is locked and we can safely start moving it. Since
* this function utilizes thie @ubi->peb1_buf buffer which is shared
* with some other functions, so lock the buffer by taking the
* @ubi->buf_mutex.
diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c
index 4f2daa5bbec..41d47e1cf15 100644
--- a/drivers/mtd/ubi/scan.c
+++ b/drivers/mtd/ubi/scan.c
@@ -320,7 +320,7 @@ static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb,
}
err = ubi_io_read_data(ubi, buf, pnum, 0, len);
- if (err && err != UBI_IO_BITFLIPS)
+ if (err && err != UBI_IO_BITFLIPS && err != -EBADMSG)
goto out_free_buf;
data_crc = be32_to_cpu(vid_hdr->data_crc);
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index 05d70937b54..dcb6dac1dc5 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -1396,7 +1396,8 @@ int ubi_thread(void *u)
ubi_msg("%s: %d consecutive failures",
ubi->bgt_name, WL_MAX_FAILURES);
ubi_ro_mode(ubi);
- break;
+ ubi->thread_enabled = 0;
+ continue;
}
} else
failures = 0;
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 11f143f4adf..231eeaf1d55 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1825,9 +1825,10 @@ config FEC2
config FEC_MPC52xx
tristate "MPC52xx FEC driver"
- depends on PPC_MPC52xx && PPC_BESTCOMM_FEC
+ depends on PPC_MPC52xx && PPC_BESTCOMM
select CRC32
select PHYLIB
+ select PPC_BESTCOMM_FEC
---help---
This option enables support for the MPC5200's on-chip
Fast Ethernet Controller
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index f19acf8b922..017383ad5ec 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -114,7 +114,7 @@ obj-$(CONFIG_EL2) += 3c503.o 8390p.o
obj-$(CONFIG_NE2000) += ne.o 8390p.o
obj-$(CONFIG_NE2_MCA) += ne2.o 8390p.o
obj-$(CONFIG_HPLAN) += hp.o 8390p.o
-obj-$(CONFIG_HPLAN_PLUS) += hp-plus.o 8390.o
+obj-$(CONFIG_HPLAN_PLUS) += hp-plus.o 8390p.o
obj-$(CONFIG_ULTRA) += smc-ultra.o 8390.o
obj-$(CONFIG_ULTRAMCA) += smc-mca.o 8390.o
obj-$(CONFIG_ULTRA32) += smc-ultra32.o 8390.o
diff --git a/drivers/net/atl1e/atl1e_hw.c b/drivers/net/atl1e/atl1e_hw.c
index 8cbc1b59bd6..4a770062011 100644
--- a/drivers/net/atl1e/atl1e_hw.c
+++ b/drivers/net/atl1e/atl1e_hw.c
@@ -163,9 +163,6 @@ int atl1e_read_mac_addr(struct atl1e_hw *hw)
* atl1e_hash_mc_addr
* purpose
* set hash value for a multicast address
- * hash calcu processing :
- * 1. calcu 32bit CRC for multicast address
- * 2. reverse crc with MSB to LSB
*/
u32 atl1e_hash_mc_addr(struct atl1e_hw *hw, u8 *mc_addr)
{
@@ -174,7 +171,6 @@ u32 atl1e_hash_mc_addr(struct atl1e_hw *hw, u8 *mc_addr)
int i;
crc32 = ether_crc_le(6, mc_addr);
- crc32 = ~crc32;
for (i = 0; i < 32; i++)
value |= (((crc32 >> i) & 1) << (31 - i));
diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c
index 246d92b4263..aef403d299e 100644
--- a/drivers/net/atlx/atl1.c
+++ b/drivers/net/atlx/atl1.c
@@ -3404,14 +3404,8 @@ static void atl1_get_wol(struct net_device *netdev,
{
struct atl1_adapter *adapter = netdev_priv(netdev);
- wol->supported = WAKE_UCAST | WAKE_MCAST | WAKE_BCAST | WAKE_MAGIC;
+ wol->supported = WAKE_MAGIC;
wol->wolopts = 0;
- if (adapter->wol & ATLX_WUFC_EX)
- wol->wolopts |= WAKE_UCAST;
- if (adapter->wol & ATLX_WUFC_MC)
- wol->wolopts |= WAKE_MCAST;
- if (adapter->wol & ATLX_WUFC_BC)
- wol->wolopts |= WAKE_BCAST;
if (adapter->wol & ATLX_WUFC_MAG)
wol->wolopts |= WAKE_MAGIC;
return;
@@ -3422,15 +3416,10 @@ static int atl1_set_wol(struct net_device *netdev,
{
struct atl1_adapter *adapter = netdev_priv(netdev);
- if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE))
+ if (wol->wolopts & (WAKE_PHY | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST |
+ WAKE_ARP | WAKE_MAGICSECURE))
return -EOPNOTSUPP;
adapter->wol = 0;
- if (wol->wolopts & WAKE_UCAST)
- adapter->wol |= ATLX_WUFC_EX;
- if (wol->wolopts & WAKE_MCAST)
- adapter->wol |= ATLX_WUFC_MC;
- if (wol->wolopts & WAKE_BCAST)
- adapter->wol |= ATLX_WUFC_BC;
if (wol->wolopts & WAKE_MAGIC)
adapter->wol |= ATLX_WUFC_MAG;
return 0;
diff --git a/drivers/net/atlx/atl2.c b/drivers/net/atlx/atl2.c
index f5bdc92c1a6..8571e8c0bc6 100644
--- a/drivers/net/atlx/atl2.c
+++ b/drivers/net/atlx/atl2.c
@@ -1690,9 +1690,11 @@ static int atl2_resume(struct pci_dev *pdev)
ATL2_WRITE_REG(&adapter->hw, REG_WOL_CTRL, 0);
- err = atl2_request_irq(adapter);
- if (netif_running(netdev) && err)
- return err;
+ if (netif_running(netdev)) {
+ err = atl2_request_irq(adapter);
+ if (err)
+ return err;
+ }
atl2_reset_hw(&adapter->hw);
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 430d430bce2..9e8222f9e90 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -543,9 +543,9 @@ bnx2_free_rx_mem(struct bnx2 *bp)
for (j = 0; j < bp->rx_max_pg_ring; j++) {
if (rxr->rx_pg_desc_ring[j])
pci_free_consistent(bp->pdev, RXBD_RING_SIZE,
- rxr->rx_pg_desc_ring[i],
- rxr->rx_pg_desc_mapping[i]);
- rxr->rx_pg_desc_ring[i] = NULL;
+ rxr->rx_pg_desc_ring[j],
+ rxr->rx_pg_desc_mapping[j]);
+ rxr->rx_pg_desc_ring[j] = NULL;
}
if (rxr->rx_pg_ring)
vfree(rxr->rx_pg_ring);
@@ -3144,6 +3144,28 @@ bnx2_has_work(struct bnx2_napi *bnapi)
return 0;
}
+static void
+bnx2_chk_missed_msi(struct bnx2 *bp)
+{
+ struct bnx2_napi *bnapi = &bp->bnx2_napi[0];
+ u32 msi_ctrl;
+
+ if (bnx2_has_work(bnapi)) {
+ msi_ctrl = REG_RD(bp, BNX2_PCICFG_MSI_CONTROL);
+ if (!(msi_ctrl & BNX2_PCICFG_MSI_CONTROL_ENABLE))
+ return;
+
+ if (bnapi->last_status_idx == bp->idle_chk_status_idx) {
+ REG_WR(bp, BNX2_PCICFG_MSI_CONTROL, msi_ctrl &
+ ~BNX2_PCICFG_MSI_CONTROL_ENABLE);
+ REG_WR(bp, BNX2_PCICFG_MSI_CONTROL, msi_ctrl);
+ bnx2_msi(bp->irq_tbl[0].vector, bnapi);
+ }
+ }
+
+ bp->idle_chk_status_idx = bnapi->last_status_idx;
+}
+
static void bnx2_poll_link(struct bnx2 *bp, struct bnx2_napi *bnapi)
{
struct status_block *sblk = bnapi->status_blk.msi;
@@ -3218,14 +3240,15 @@ static int bnx2_poll(struct napi_struct *napi, int budget)
work_done = bnx2_poll_work(bp, bnapi, work_done, budget);
- if (unlikely(work_done >= budget))
- break;
-
/* bnapi->last_status_idx is used below to tell the hw how
* much work has been processed, so we must read it before
* checking for more work.
*/
bnapi->last_status_idx = sblk->status_idx;
+
+ if (unlikely(work_done >= budget))
+ break;
+
rmb();
if (likely(!bnx2_has_work(bnapi))) {
netif_rx_complete(bp->dev, napi);
@@ -4570,6 +4593,8 @@ bnx2_init_chip(struct bnx2 *bp)
for (i = 0; i < BNX2_MAX_MSIX_VEC; i++)
bp->bnx2_napi[i].last_status_idx = 0;
+ bp->idle_chk_status_idx = 0xffff;
+
bp->rx_mode = BNX2_EMAC_RX_MODE_SORT_MODE;
/* Set up how to generate a link change interrupt. */
@@ -5718,6 +5743,10 @@ bnx2_timer(unsigned long data)
if (atomic_read(&bp->intr_sem) != 0)
goto bnx2_restart_timer;
+ if ((bp->flags & (BNX2_FLAG_USING_MSI | BNX2_FLAG_ONE_SHOT_MSI)) ==
+ BNX2_FLAG_USING_MSI)
+ bnx2_chk_missed_msi(bp);
+
bnx2_send_heart_beat(bp);
bp->stats_blk->stat_FwRxDrop =
@@ -7204,10 +7233,13 @@ static void
poll_bnx2(struct net_device *dev)
{
struct bnx2 *bp = netdev_priv(dev);
+ int i;
- disable_irq(bp->pdev->irq);
- bnx2_interrupt(bp->pdev->irq, dev);
- enable_irq(bp->pdev->irq);
+ for (i = 0; i < bp->irq_nvecs; i++) {
+ disable_irq(bp->irq_tbl[i].vector);
+ bnx2_interrupt(bp->irq_tbl[i].vector, &bp->bnx2_napi[i]);
+ enable_irq(bp->irq_tbl[i].vector);
+ }
}
#endif
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index 617d9534016..0b032c3c7b6 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -378,6 +378,9 @@ struct l2_fhdr {
* pci_config_l definition
* offset: 0000
*/
+#define BNX2_PCICFG_MSI_CONTROL 0x00000058
+#define BNX2_PCICFG_MSI_CONTROL_ENABLE (1L<<16)
+
#define BNX2_PCICFG_MISC_CONFIG 0x00000068
#define BNX2_PCICFG_MISC_CONFIG_TARGET_BYTE_SWAP (1L<<2)
#define BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP (1L<<3)
@@ -6863,6 +6866,9 @@ struct bnx2 {
u8 num_tx_rings;
u8 num_rx_rings;
+
+ u32 idle_chk_status_idx;
+
};
#define REG_RD(bp, offset) \
diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c
index d6c7d2aa761..7092df50ff7 100644
--- a/drivers/net/chelsio/sge.c
+++ b/drivers/net/chelsio/sge.c
@@ -1035,10 +1035,6 @@ MODULE_PARM_DESC(copybreak, "Receive copy threshold");
* @pdev: the PCI device that received the packet
* @fl: the SGE free list holding the packet
* @len: the actual packet length, excluding any SGE padding
- * @dma_pad: padding at beginning of buffer left by SGE DMA
- * @skb_pad: padding to be used if the packet is copied
- * @copy_thres: length threshold under which a packet should be copied
- * @drop_thres: # of remaining buffers before we start dropping packets
*
* Get the next packet from a free list and complete setup of the
* sk_buff. If the packet is small we make a copy and recycle the
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c
index 1ace41a13ac..2c341f83d32 100644
--- a/drivers/net/cxgb3/cxgb3_main.c
+++ b/drivers/net/cxgb3/cxgb3_main.c
@@ -1307,8 +1307,10 @@ static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
u32 fw_vers = 0;
u32 tp_vers = 0;
+ spin_lock(&adapter->stats_lock);
t3_get_fw_version(adapter, &fw_vers);
t3_get_tp_version(adapter, &tp_vers);
+ spin_unlock(&adapter->stats_lock);
strcpy(info->driver, DRV_NAME);
strcpy(info->version, DRV_VERSION);
@@ -2699,7 +2701,7 @@ static void set_nqsets(struct adapter *adap)
int hwports = adap->params.nports;
int nqsets = SGE_QSETS;
- if (adap->params.rev > 0) {
+ if (adap->params.rev > 0 && adap->flags & USING_MSIX) {
if (hwports == 2 &&
(hwports * nqsets > SGE_QSETS ||
num_cpus >= nqsets / hwports))
diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c
index 968f64be374..9a0898b0dbc 100644
--- a/drivers/net/cxgb3/t3_hw.c
+++ b/drivers/net/cxgb3/t3_hw.c
@@ -572,7 +572,7 @@ struct t3_vpd {
u32 pad; /* for multiple-of-4 sizing and alignment */
};
-#define EEPROM_MAX_POLL 4
+#define EEPROM_MAX_POLL 40
#define EEPROM_STAT_ADDR 0x4000
#define VPD_BASE 0xc00
@@ -3690,6 +3690,12 @@ int t3_prep_adapter(struct adapter *adapter, const struct adapter_info *ai,
;
pti = &port_types[adapter->params.vpd.port_type[j]];
+ if (!pti->phy_prep) {
+ CH_ALERT(adapter, "Invalid port type index %d\n",
+ adapter->params.vpd.port_type[j]);
+ return -EINVAL;
+ }
+
ret = pti->phy_prep(&p->phy, adapter, ai->phy_base_addr + j,
ai->mdio_ops);
if (ret)
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index 3d69fae781c..e8bfcce6b31 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -166,7 +166,7 @@
#define DRV_NAME "e100"
#define DRV_EXT "-NAPI"
-#define DRV_VERSION "3.5.23-k4"DRV_EXT
+#define DRV_VERSION "3.5.23-k6"DRV_EXT
#define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver"
#define DRV_COPYRIGHT "Copyright(c) 1999-2006 Intel Corporation"
#define PFX DRV_NAME ": "
@@ -1804,7 +1804,7 @@ static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx)
struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data;
put_unaligned_le32(rx->dma_addr, &prev_rfd->link);
pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr,
- sizeof(struct rfd), PCI_DMA_TODEVICE);
+ sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL);
}
return 0;
@@ -1823,7 +1823,7 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx,
/* Need to sync before taking a peek at cb_complete bit */
pci_dma_sync_single_for_cpu(nic->pdev, rx->dma_addr,
- sizeof(struct rfd), PCI_DMA_FROMDEVICE);
+ sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL);
rfd_status = le16_to_cpu(rfd->status);
DPRINTK(RX_STATUS, DEBUG, "status=0x%04X\n", rfd_status);
@@ -1850,7 +1850,7 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx,
/* Get data */
pci_unmap_single(nic->pdev, rx->dma_addr,
- RFD_BUF_LEN, PCI_DMA_FROMDEVICE);
+ RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL);
/* If this buffer has the el bit, but we think the receiver
* is still running, check to see if it really stopped while
@@ -1943,7 +1943,7 @@ static void e100_rx_clean(struct nic *nic, unsigned int *work_done,
new_before_last_rfd->command |= cpu_to_le16(cb_el);
pci_dma_sync_single_for_device(nic->pdev,
new_before_last_rx->dma_addr, sizeof(struct rfd),
- PCI_DMA_TODEVICE);
+ PCI_DMA_BIDIRECTIONAL);
/* Now that we have a new stopping point, we can clear the old
* stopping point. We must sync twice to get the proper
@@ -1951,11 +1951,11 @@ static void e100_rx_clean(struct nic *nic, unsigned int *work_done,
old_before_last_rfd->command &= ~cpu_to_le16(cb_el);
pci_dma_sync_single_for_device(nic->pdev,
old_before_last_rx->dma_addr, sizeof(struct rfd),
- PCI_DMA_TODEVICE);
+ PCI_DMA_BIDIRECTIONAL);
old_before_last_rfd->size = cpu_to_le16(VLAN_ETH_FRAME_LEN);
pci_dma_sync_single_for_device(nic->pdev,
old_before_last_rx->dma_addr, sizeof(struct rfd),
- PCI_DMA_TODEVICE);
+ PCI_DMA_BIDIRECTIONAL);
}
if(restart_required) {
@@ -1978,7 +1978,7 @@ static void e100_rx_clean_list(struct nic *nic)
for(rx = nic->rxs, i = 0; i < count; rx++, i++) {
if(rx->skb) {
pci_unmap_single(nic->pdev, rx->dma_addr,
- RFD_BUF_LEN, PCI_DMA_FROMDEVICE);
+ RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL);
dev_kfree_skb(rx->skb);
}
}
@@ -2021,7 +2021,7 @@ static int e100_rx_alloc_list(struct nic *nic)
before_last->command |= cpu_to_le16(cb_el);
before_last->size = 0;
pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr,
- sizeof(struct rfd), PCI_DMA_TODEVICE);
+ sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL);
nic->rx_to_use = nic->rx_to_clean = nic->rxs;
nic->ru_running = RU_SUSPENDED;
@@ -2222,7 +2222,7 @@ static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode)
msleep(10);
pci_dma_sync_single_for_cpu(nic->pdev, nic->rx_to_clean->dma_addr,
- RFD_BUF_LEN, PCI_DMA_FROMDEVICE);
+ RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL);
if(memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd),
skb->data, ETH_DATA_LEN))
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
index 6a3893acfe0..c854c96f5ab 100644
--- a/drivers/net/e1000/e1000_ethtool.c
+++ b/drivers/net/e1000/e1000_ethtool.c
@@ -1774,7 +1774,8 @@ static void e1000_get_wol(struct net_device *netdev,
/* this function will set ->supported = 0 and return 1 if wol is not
* supported by this hardware */
- if (e1000_wol_exclusion(adapter, wol))
+ if (e1000_wol_exclusion(adapter, wol) ||
+ !device_can_wakeup(&adapter->pdev->dev))
return;
/* apply any specific unsupported masks here */
@@ -1811,7 +1812,8 @@ static int e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE))
return -EOPNOTSUPP;
- if (e1000_wol_exclusion(adapter, wol))
+ if (e1000_wol_exclusion(adapter, wol) ||
+ !device_can_wakeup(&adapter->pdev->dev))
return wol->wolopts ? -EOPNOTSUPP : 0;
switch (hw->device_id) {
@@ -1838,6 +1840,8 @@ static int e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
if (wol->wolopts & WAKE_MAGIC)
adapter->wol |= E1000_WUFC_MAG;
+ device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
+
return 0;
}
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index fac82152e4c..872799b746f 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -1179,6 +1179,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
/* initialize the wol settings based on the eeprom settings */
adapter->wol = adapter->eeprom_wol;
+ device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
/* print bus type/speed/width info */
DPRINTK(PROBE, INFO, "(PCI%s:%s:%s) ",
diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h
index c55de1c027a..c55fd6fdb91 100644
--- a/drivers/net/e1000e/e1000.h
+++ b/drivers/net/e1000e/e1000.h
@@ -299,6 +299,7 @@ struct e1000_adapter {
unsigned long led_status;
unsigned int flags;
+ unsigned int flags2;
struct work_struct downshift_task;
struct work_struct update_phy_task;
};
@@ -306,6 +307,7 @@ struct e1000_adapter {
struct e1000_info {
enum e1000_mac_type mac;
unsigned int flags;
+ unsigned int flags2;
u32 pba;
s32 (*get_variants)(struct e1000_adapter *);
struct e1000_mac_operations *mac_ops;
@@ -347,6 +349,9 @@ struct e1000_info {
#define FLAG_RX_RESTART_NOW (1 << 30)
#define FLAG_MSI_TEST_FAILED (1 << 31)
+/* CRC Stripping defines */
+#define FLAG2_CRC_STRIPPING (1 << 0)
+
#define E1000_RX_DESC_PS(R, i) \
(&(((union e1000_rx_desc_packet_split *)((R).desc))[i]))
#define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i]))
diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c
index 70c11c811a0..62421ce9631 100644
--- a/drivers/net/e1000e/ethtool.c
+++ b/drivers/net/e1000e/ethtool.c
@@ -1713,7 +1713,8 @@ static void e1000_get_wol(struct net_device *netdev,
wol->supported = 0;
wol->wolopts = 0;
- if (!(adapter->flags & FLAG_HAS_WOL))
+ if (!(adapter->flags & FLAG_HAS_WOL) ||
+ !device_can_wakeup(&adapter->pdev->dev))
return;
wol->supported = WAKE_UCAST | WAKE_MCAST |
@@ -1751,7 +1752,8 @@ static int e1000_set_wol(struct net_device *netdev,
if (wol->wolopts & WAKE_MAGICSECURE)
return -EOPNOTSUPP;
- if (!(adapter->flags & FLAG_HAS_WOL))
+ if (!(adapter->flags & FLAG_HAS_WOL) ||
+ !device_can_wakeup(&adapter->pdev->dev))
return wol->wolopts ? -EOPNOTSUPP : 0;
/* these settings will always override what we currently have */
@@ -1770,6 +1772,8 @@ static int e1000_set_wol(struct net_device *netdev,
if (wol->wolopts & WAKE_ARP)
adapter->wol |= E1000_WUFC_ARP;
+ device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
+
return 0;
}
diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c
index 523b9716a54..d115a6d30f2 100644
--- a/drivers/net/e1000e/ich8lan.c
+++ b/drivers/net/e1000e/ich8lan.c
@@ -1893,12 +1893,17 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
ctrl |= E1000_CTRL_PHY_RST;
}
ret_val = e1000_acquire_swflag_ich8lan(hw);
+ /* Whether or not the swflag was acquired, we need to reset the part */
hw_dbg(hw, "Issuing a global reset to ich8lan");
ew32(CTRL, (ctrl | E1000_CTRL_RST));
msleep(20);
- /* release the swflag because it is not reset by hardware reset */
- e1000_release_swflag_ich8lan(hw);
+ if (!ret_val) {
+ /* release the swflag because it is not reset by
+ * hardware reset
+ */
+ e1000_release_swflag_ich8lan(hw);
+ }
ret_val = e1000e_get_auto_rd_done(hw);
if (ret_val) {
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index abd492b7336..122539a0e1f 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -345,7 +345,6 @@ no_buffers:
/**
* e1000_alloc_jumbo_rx_buffers - Replace used jumbo receive buffers
* @adapter: address of board private structure
- * @rx_ring: pointer to receive ring structure
* @cleaned_count: number of buffers to allocate this pass
**/
@@ -499,6 +498,10 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
goto next_desc;
}
+ /* adjust length to remove Ethernet CRC */
+ if (!(adapter->flags2 & FLAG2_CRC_STRIPPING))
+ length -= 4;
+
total_rx_bytes += length;
total_rx_packets++;
@@ -804,6 +807,10 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
pci_dma_sync_single_for_device(pdev, ps_page->dma,
PAGE_SIZE, PCI_DMA_FROMDEVICE);
+ /* remove the CRC */
+ if (!(adapter->flags2 & FLAG2_CRC_STRIPPING))
+ l1 -= 4;
+
skb_put(skb, l1);
goto copydone;
} /* if */
@@ -825,6 +832,12 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
skb->truesize += length;
}
+ /* strip the ethernet crc, problem is we're using pages now so
+ * this whole operation can get a little cpu intensive
+ */
+ if (!(adapter->flags2 & FLAG2_CRC_STRIPPING))
+ pskb_trim(skb, skb->len - 4);
+
copydone:
total_rx_bytes += skb->len;
total_rx_packets++;
@@ -2301,8 +2314,12 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
else
rctl |= E1000_RCTL_LPE;
- /* Enable hardware CRC frame stripping */
- rctl |= E1000_RCTL_SECRC;
+ /* Some systems expect that the CRC is included in SMBUS traffic. The
+ * hardware strips the CRC before sending to both SMBUS (BMC) and to
+ * host memory when this is enabled
+ */
+ if (adapter->flags2 & FLAG2_CRC_STRIPPING)
+ rctl |= E1000_RCTL_SECRC;
/* Setup buffer sizes */
rctl &= ~E1000_RCTL_SZ_4096;
@@ -4766,6 +4783,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
adapter->ei = ei;
adapter->pba = ei->pba;
adapter->flags = ei->flags;
+ adapter->flags2 = ei->flags2;
adapter->hw.adapter = adapter;
adapter->hw.mac.type = ei->mac;
adapter->msg_enable = (1 << NETIF_MSG_DRV | NETIF_MSG_PROBE) - 1;
@@ -4970,6 +4988,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
/* initialize the wol settings based on the eeprom settings */
adapter->wol = adapter->eeprom_wol;
+ device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
/* reset the hardware with the new settings */
e1000e_reset(adapter);
@@ -5008,6 +5027,7 @@ err_hw_init:
err_sw_init:
if (adapter->hw.flash_address)
iounmap(adapter->hw.flash_address);
+ e1000e_reset_interrupt_capability(adapter);
err_flashmap:
iounmap(adapter->hw.hw_addr);
err_ioremap:
diff --git a/drivers/net/e1000e/param.c b/drivers/net/e1000e/param.c
index 77a3d7207a5..e909f96698e 100644
--- a/drivers/net/e1000e/param.c
+++ b/drivers/net/e1000e/param.c
@@ -151,6 +151,16 @@ E1000_PARAM(KumeranLockLoss, "Enable Kumeran lock loss workaround");
*/
E1000_PARAM(WriteProtectNVM, "Write-protect NVM [WARNING: disabling this can lead to corrupted NVM]");
+/*
+ * Enable CRC Stripping
+ *
+ * Valid Range: 0, 1
+ *
+ * Default Value: 1 (enabled)
+ */
+E1000_PARAM(CrcStripping, "Enable CRC Stripping, disable if your BMC needs " \
+ "the CRC");
+
struct e1000_option {
enum { enable_option, range_option, list_option } type;
const char *name;
@@ -404,6 +414,21 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter)
adapter->flags |= FLAG_SMART_POWER_DOWN;
}
}
+ { /* CRC Stripping */
+ const struct e1000_option opt = {
+ .type = enable_option,
+ .name = "CRC Stripping",
+ .err = "defaulting to enabled",
+ .def = OPTION_ENABLED
+ };
+
+ if (num_CrcStripping > bd) {
+ unsigned int crc_stripping = CrcStripping[bd];
+ e1000_validate_option(&crc_stripping, &opt, adapter);
+ if (crc_stripping == OPTION_ENABLED)
+ adapter->flags2 |= FLAG2_CRC_STRIPPING;
+ }
+ }
{ /* Kumeran Lock Loss Workaround */
const struct e1000_option opt = {
.type = enable_option,
diff --git a/drivers/net/enc28j60.c b/drivers/net/enc28j60.c
index e1b441effbb..36cb6e95b46 100644
--- a/drivers/net/enc28j60.c
+++ b/drivers/net/enc28j60.c
@@ -568,6 +568,17 @@ static u16 erxrdpt_workaround(u16 next_packet_ptr, u16 start, u16 end)
return erxrdpt;
}
+/*
+ * Calculate wrap around when reading beyond the end of the RX buffer
+ */
+static u16 rx_packet_start(u16 ptr)
+{
+ if (ptr + RSV_SIZE > RXEND_INIT)
+ return (ptr + RSV_SIZE) - (RXEND_INIT - RXSTART_INIT + 1);
+ else
+ return ptr + RSV_SIZE;
+}
+
static void nolock_rxfifo_init(struct enc28j60_net *priv, u16 start, u16 end)
{
u16 erxrdpt;
@@ -938,8 +949,9 @@ static void enc28j60_hw_rx(struct net_device *ndev)
skb->dev = ndev;
skb_reserve(skb, NET_IP_ALIGN);
/* copy the packet from the receive buffer */
- enc28j60_mem_read(priv, priv->next_pk_ptr + sizeof(rsv),
- len, skb_put(skb, len));
+ enc28j60_mem_read(priv,
+ rx_packet_start(priv->next_pk_ptr),
+ len, skb_put(skb, len));
if (netif_msg_pktdata(priv))
dump_packet(__func__, skb->len, skb->data);
skb->protocol = eth_type_trans(skb, ndev);
@@ -947,7 +959,7 @@ static void enc28j60_hw_rx(struct net_device *ndev)
ndev->stats.rx_packets++;
ndev->stats.rx_bytes += len;
ndev->last_rx = jiffies;
- netif_rx(skb);
+ netif_rx_ni(skb);
}
}
/*
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 83a5cb6aa23..c4af949bf86 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -1407,6 +1407,10 @@ static int gfar_clean_tx_ring(struct net_device *dev)
if (bdp->status & TXBD_DEF)
dev->stats.collisions++;
+ /* Unmap the DMA memory */
+ dma_unmap_single(&priv->dev->dev, bdp->bufPtr,
+ bdp->length, DMA_TO_DEVICE);
+
/* Free the sk buffer associated with this TxBD */
dev_kfree_skb_irq(priv->tx_skbuff[priv->skb_dirtytx]);
@@ -1666,6 +1670,9 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit)
skb = priv->rx_skbuff[priv->skb_currx];
+ dma_unmap_single(&priv->dev->dev, bdp->bufPtr,
+ priv->rx_buffer_size, DMA_FROM_DEVICE);
+
/* We drop the frame if we failed to allocate a new buffer */
if (unlikely(!newskb || !(bdp->status & RXBD_LAST) ||
bdp->status & RXBD_ERR)) {
@@ -1674,14 +1681,8 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit)
if (unlikely(!newskb))
newskb = skb;
- if (skb) {
- dma_unmap_single(&priv->dev->dev,
- bdp->bufPtr,
- priv->rx_buffer_size,
- DMA_FROM_DEVICE);
-
+ if (skb)
dev_kfree_skb_any(skb);
- }
} else {
/* Increment the number of packets */
dev->stats.rx_packets++;
diff --git a/drivers/net/hp-plus.c b/drivers/net/hp-plus.c
index fbbd3e660c2..c01e290d09d 100644
--- a/drivers/net/hp-plus.c
+++ b/drivers/net/hp-plus.c
@@ -230,7 +230,7 @@ static int __init hpp_probe1(struct net_device *dev, int ioaddr)
dev->open = &hpp_open;
dev->stop = &hpp_close;
#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = ei_poll;
+ dev->poll_controller = eip_poll;
#endif
ei_status.name = name;
diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c
index 58906c984be..89964fa739a 100644
--- a/drivers/net/igb/igb_ethtool.c
+++ b/drivers/net/igb/igb_ethtool.c
@@ -1776,7 +1776,8 @@ static void igb_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
/* this function will set ->supported = 0 and return 1 if wol is not
* supported by this hardware */
- if (igb_wol_exclusion(adapter, wol))
+ if (igb_wol_exclusion(adapter, wol) ||
+ !device_can_wakeup(&adapter->pdev->dev))
return;
/* apply any specific unsupported masks here */
@@ -1805,7 +1806,8 @@ static int igb_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE))
return -EOPNOTSUPP;
- if (igb_wol_exclusion(adapter, wol))
+ if (igb_wol_exclusion(adapter, wol) ||
+ !device_can_wakeup(&adapter->pdev->dev))
return wol->wolopts ? -EOPNOTSUPP : 0;
switch (hw->device_id) {
@@ -1825,6 +1827,8 @@ static int igb_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
if (wol->wolopts & WAKE_MAGIC)
adapter->wol |= E1000_WUFC_MAG;
+ device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
+
return 0;
}
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index 1f397cd9941..20d27e622ec 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -1019,10 +1019,9 @@ static int __devinit igb_probe(struct pci_dev *pdev,
state &= ~PCIE_LINK_STATE_L0S;
pci_write_config_word(us_dev, pos + PCI_EXP_LNKCTL,
state);
- printk(KERN_INFO "Disabling ASPM L0s upstream switch "
- "port %x:%x.%x\n", us_dev->bus->number,
- PCI_SLOT(us_dev->devfn),
- PCI_FUNC(us_dev->devfn));
+ dev_info(&pdev->dev,
+ "Disabling ASPM L0s upstream switch port %s\n",
+ pci_name(us_dev));
}
default:
break;
@@ -1244,6 +1243,7 @@ static int __devinit igb_probe(struct pci_dev *pdev,
/* initialize the wol settings based on the eeprom settings */
adapter->wol = adapter->eeprom_wol;
+ device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
/* reset the hardware with the new settings */
igb_reset(adapter);
@@ -1980,7 +1980,6 @@ static void igb_configure_rx(struct igb_adapter *adapter)
/**
* igb_free_tx_resources - Free Tx Resources per Queue
- * @adapter: board private structure
* @tx_ring: Tx descriptor ring for a specific queue
*
* Free all transmit software resources
@@ -2033,7 +2032,6 @@ static void igb_unmap_and_free_tx_resource(struct igb_adapter *adapter,
/**
* igb_clean_tx_ring - Free Tx Buffers
- * @adapter: board private structure
* @tx_ring: ring to be cleaned
**/
static void igb_clean_tx_ring(struct igb_ring *tx_ring)
@@ -2080,7 +2078,6 @@ static void igb_clean_all_tx_rings(struct igb_adapter *adapter)
/**
* igb_free_rx_resources - Free Rx Resources
- * @adapter: board private structure
* @rx_ring: ring to clean the resources from
*
* Free all receive software resources
@@ -2120,7 +2117,6 @@ static void igb_free_all_rx_resources(struct igb_adapter *adapter)
/**
* igb_clean_rx_ring - Free Rx Buffers per Queue
- * @adapter: board private structure
* @rx_ring: ring to free buffers from
**/
static void igb_clean_rx_ring(struct igb_ring *rx_ring)
diff --git a/drivers/net/ipg.c b/drivers/net/ipg.c
index 7373dafbb3f..059369885be 100644
--- a/drivers/net/ipg.c
+++ b/drivers/net/ipg.c
@@ -1112,7 +1112,7 @@ static void ipg_nic_rx_free_skb(struct net_device *dev)
struct ipg_rx *rxfd = sp->rxd + entry;
pci_unmap_single(sp->pdev,
- le64_to_cpu(rxfd->frag_info & ~IPG_RFI_FRAGLEN),
+ le64_to_cpu(rxfd->frag_info) & ~IPG_RFI_FRAGLEN,
sp->rx_buf_sz, PCI_DMA_FROMDEVICE);
dev_kfree_skb_irq(sp->rx_buff[entry]);
sp->rx_buff[entry] = NULL;
@@ -1179,7 +1179,7 @@ static int ipg_nic_rx_check_error(struct net_device *dev)
*/
if (sp->rx_buff[entry]) {
pci_unmap_single(sp->pdev,
- le64_to_cpu(rxfd->frag_info & ~IPG_RFI_FRAGLEN),
+ le64_to_cpu(rxfd->frag_info) & ~IPG_RFI_FRAGLEN,
sp->rx_buf_sz, PCI_DMA_FROMDEVICE);
dev_kfree_skb_irq(sp->rx_buff[entry]);
@@ -1246,7 +1246,7 @@ static void ipg_nic_rx_with_start(struct net_device *dev,
if (jumbo->found_start)
dev_kfree_skb_irq(jumbo->skb);
- pci_unmap_single(pdev, le64_to_cpu(rxfd->frag_info & ~IPG_RFI_FRAGLEN),
+ pci_unmap_single(pdev, le64_to_cpu(rxfd->frag_info) & ~IPG_RFI_FRAGLEN,
sp->rx_buf_sz, PCI_DMA_FROMDEVICE);
skb_put(skb, sp->rxfrag_size);
@@ -1349,7 +1349,7 @@ static int ipg_nic_rx_jumbo(struct net_device *dev)
unsigned int entry = curr % IPG_RFDLIST_LENGTH;
struct ipg_rx *rxfd = sp->rxd + entry;
- if (!(rxfd->rfs & le64_to_cpu(IPG_RFS_RFDDONE)))
+ if (!(rxfd->rfs & cpu_to_le64(IPG_RFS_RFDDONE)))
break;
switch (ipg_nic_rx_check_frame_type(dev)) {
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index 7548fb7360d..5236f633ee3 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -1287,13 +1287,39 @@ static void ixgbe_set_itr(struct ixgbe_adapter *adapter)
return;
}
-static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter);
+/**
+ * ixgbe_irq_disable - Mask off interrupt generation on the NIC
+ * @adapter: board private structure
+ **/
+static inline void ixgbe_irq_disable(struct ixgbe_adapter *adapter)
+{
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0);
+ IXGBE_WRITE_FLUSH(&adapter->hw);
+ if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
+ int i;
+ for (i = 0; i < adapter->num_msix_vectors; i++)
+ synchronize_irq(adapter->msix_entries[i].vector);
+ } else {
+ synchronize_irq(adapter->pdev->irq);
+ }
+}
+
+/**
+ * ixgbe_irq_enable - Enable default interrupt generation settings
+ * @adapter: board private structure
+ **/
+static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter)
+{
+ u32 mask;
+ mask = IXGBE_EIMS_ENABLE_MASK;
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask);
+ IXGBE_WRITE_FLUSH(&adapter->hw);
+}
/**
* ixgbe_intr - legacy mode Interrupt Handler
* @irq: interrupt number
* @data: pointer to a network interface device structure
- * @pt_regs: CPU registers structure
**/
static irqreturn_t ixgbe_intr(int irq, void *data)
{
@@ -1394,35 +1420,6 @@ static void ixgbe_free_irq(struct ixgbe_adapter *adapter)
}
/**
- * ixgbe_irq_disable - Mask off interrupt generation on the NIC
- * @adapter: board private structure
- **/
-static inline void ixgbe_irq_disable(struct ixgbe_adapter *adapter)
-{
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0);
- IXGBE_WRITE_FLUSH(&adapter->hw);
- if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
- int i;
- for (i = 0; i < adapter->num_msix_vectors; i++)
- synchronize_irq(adapter->msix_entries[i].vector);
- } else {
- synchronize_irq(adapter->pdev->irq);
- }
-}
-
-/**
- * ixgbe_irq_enable - Enable default interrupt generation settings
- * @adapter: board private structure
- **/
-static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter)
-{
- u32 mask;
- mask = IXGBE_EIMS_ENABLE_MASK;
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask);
- IXGBE_WRITE_FLUSH(&adapter->hw);
-}
-
-/**
* ixgbe_configure_msi_and_legacy - Initialize PIN (INTA...) and MSI interrupts
*
**/
@@ -2332,7 +2329,7 @@ static void ixgbe_acquire_msix_vectors(struct ixgbe_adapter *adapter,
* Once we know the feature-set enabled for the device, we'll cache
* the register offset the descriptor ring is assigned to.
**/
-static void __devinit ixgbe_cache_ring_register(struct ixgbe_adapter *adapter)
+static void ixgbe_cache_ring_register(struct ixgbe_adapter *adapter)
{
int feature_mask = 0, rss_i;
int i, txr_idx, rxr_idx;
@@ -2369,7 +2366,7 @@ static void __devinit ixgbe_cache_ring_register(struct ixgbe_adapter *adapter)
* number of queues at compile-time. The polling_netdev array is
* intended for Multiqueue, but should work fine with a single queue.
**/
-static int __devinit ixgbe_alloc_queues(struct ixgbe_adapter *adapter)
+static int ixgbe_alloc_queues(struct ixgbe_adapter *adapter)
{
int i;
@@ -2410,8 +2407,7 @@ err_tx_ring_allocation:
* Attempt to configure the interrupts using the best available
* capabilities of the hardware and the kernel.
**/
-static int __devinit ixgbe_set_interrupt_capability(struct ixgbe_adapter
- *adapter)
+static int ixgbe_set_interrupt_capability(struct ixgbe_adapter *adapter)
{
int err = 0;
int vector, v_budget;
@@ -2503,7 +2499,7 @@ static void ixgbe_reset_interrupt_capability(struct ixgbe_adapter *adapter)
* - Hardware queue count (num_*_queues)
* - defined by miscellaneous hardware support/features (RSS, etc.)
**/
-static int __devinit ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter)
+static int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter)
{
int err;
diff --git a/drivers/net/jme.c b/drivers/net/jme.c
index 81c6cdc3851..665e70d620f 100644
--- a/drivers/net/jme.c
+++ b/drivers/net/jme.c
@@ -912,23 +912,23 @@ jme_alloc_and_feed_skb(struct jme_adapter *jme, int idx)
skb_put(skb, framesize);
skb->protocol = eth_type_trans(skb, jme->dev);
- if (jme_rxsum_ok(jme, rxdesc->descwb.flags))
+ if (jme_rxsum_ok(jme, le16_to_cpu(rxdesc->descwb.flags)))
skb->ip_summed = CHECKSUM_UNNECESSARY;
else
skb->ip_summed = CHECKSUM_NONE;
- if (rxdesc->descwb.flags & RXWBFLAG_TAGON) {
+ if (rxdesc->descwb.flags & cpu_to_le16(RXWBFLAG_TAGON)) {
if (jme->vlgrp) {
jme->jme_vlan_rx(skb, jme->vlgrp,
- le32_to_cpu(rxdesc->descwb.vlan));
+ le16_to_cpu(rxdesc->descwb.vlan));
NET_STAT(jme).rx_bytes += 4;
}
} else {
jme->jme_rx(skb);
}
- if ((le16_to_cpu(rxdesc->descwb.flags) & RXWBFLAG_DEST) ==
- RXWBFLAG_DEST_MUL)
+ if ((rxdesc->descwb.flags & cpu_to_le16(RXWBFLAG_DEST)) ==
+ cpu_to_le16(RXWBFLAG_DEST_MUL))
++(NET_STAT(jme).multicast);
jme->dev->last_rx = jiffies;
@@ -961,7 +961,7 @@ jme_process_receive(struct jme_adapter *jme, int limit)
rxdesc = rxring->desc;
rxdesc += i;
- if ((rxdesc->descwb.flags & RXWBFLAG_OWN) ||
+ if ((rxdesc->descwb.flags & cpu_to_le16(RXWBFLAG_OWN)) ||
!(rxdesc->descwb.desccnt & RXWBDCNT_WBCPL))
goto out;
@@ -1763,10 +1763,9 @@ jme_expand_header(struct jme_adapter *jme, struct sk_buff *skb)
}
static int
-jme_tx_tso(struct sk_buff *skb,
- u16 *mss, u8 *flags)
+jme_tx_tso(struct sk_buff *skb, __le16 *mss, u8 *flags)
{
- *mss = skb_shinfo(skb)->gso_size << TXDESC_MSS_SHIFT;
+ *mss = cpu_to_le16(skb_shinfo(skb)->gso_size << TXDESC_MSS_SHIFT);
if (*mss) {
*flags |= TXFLAG_LSEN;
@@ -1826,11 +1825,11 @@ jme_tx_csum(struct jme_adapter *jme, struct sk_buff *skb, u8 *flags)
}
static inline void
-jme_tx_vlan(struct sk_buff *skb, u16 *vlan, u8 *flags)
+jme_tx_vlan(struct sk_buff *skb, __le16 *vlan, u8 *flags)
{
if (vlan_tx_tag_present(skb)) {
*flags |= TXFLAG_TAGON;
- *vlan = vlan_tx_tag_get(skb);
+ *vlan = cpu_to_le16(vlan_tx_tag_get(skb));
}
}
diff --git a/drivers/net/jme.h b/drivers/net/jme.h
index f863aee6648..3f5d9154324 100644
--- a/drivers/net/jme.h
+++ b/drivers/net/jme.h
@@ -22,7 +22,7 @@
*/
#ifndef __JME_H_INCLUDED__
-#define __JME_H_INCLUDEE__
+#define __JME_H_INCLUDED__
#define DRV_NAME "jme"
#define DRV_VERSION "1.0.3"
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 42394505bb5..590039cbb14 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -70,6 +70,9 @@ static void macvlan_broadcast(struct sk_buff *skb,
struct sk_buff *nskb;
unsigned int i;
+ if (skb->protocol == htons(ETH_P_PAUSE))
+ return;
+
for (i = 0; i < MACVLAN_HASH_SIZE; i++) {
hlist_for_each_entry_rcu(vlan, n, &port->vlan_hash[i], hlist) {
dev = vlan->dev;
diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c
index a3f732418c4..96e709d6440 100644
--- a/drivers/net/mlx4/en_netdev.c
+++ b/drivers/net/mlx4/en_netdev.c
@@ -656,10 +656,10 @@ static int mlx4_en_start_port(struct net_device *dev)
/* Configure port */
err = mlx4_SET_PORT_general(mdev->dev, priv->port,
priv->rx_skb_size + ETH_FCS_LEN,
- mdev->profile.tx_pause,
- mdev->profile.tx_ppp,
- mdev->profile.rx_pause,
- mdev->profile.rx_ppp);
+ priv->prof->tx_pause,
+ priv->prof->tx_ppp,
+ priv->prof->rx_pause,
+ priv->prof->rx_ppp);
if (err) {
mlx4_err(mdev, "Failed setting port general configurations"
" for port %d, with error %d\n", priv->port, err);
diff --git a/drivers/net/mlx4/en_params.c b/drivers/net/mlx4/en_params.c
index c2e69b1bcd0..95706ee1c01 100644
--- a/drivers/net/mlx4/en_params.c
+++ b/drivers/net/mlx4/en_params.c
@@ -90,6 +90,7 @@ MLX4_EN_PARM_INT(rx_ring_size2, MLX4_EN_AUTO_CONF, "Rx ring size for port 2");
int mlx4_en_get_profile(struct mlx4_en_dev *mdev)
{
struct mlx4_en_profile *params = &mdev->profile;
+ int i;
params->rx_moder_cnt = min_t(int, rx_moder_cnt, MLX4_EN_AUTO_CONF);
params->rx_moder_time = min_t(int, rx_moder_time, MLX4_EN_AUTO_CONF);
@@ -97,11 +98,13 @@ int mlx4_en_get_profile(struct mlx4_en_dev *mdev)
params->rss_xor = (rss_xor != 0);
params->rss_mask = rss_mask & 0x1f;
params->num_lro = min_t(int, num_lro , MLX4_EN_MAX_LRO_DESCRIPTORS);
- params->rx_pause = pprx;
- params->rx_ppp = pfcrx;
- params->tx_pause = pptx;
- params->tx_ppp = pfctx;
- if (params->rx_ppp || params->tx_ppp) {
+ for (i = 1; i <= MLX4_MAX_PORTS; i++) {
+ params->prof[i].rx_pause = pprx;
+ params->prof[i].rx_ppp = pfcrx;
+ params->prof[i].tx_pause = pptx;
+ params->prof[i].tx_ppp = pfctx;
+ }
+ if (pfcrx || pfctx) {
params->prof[1].tx_ring_num = MLX4_EN_TX_RING_NUM;
params->prof[2].tx_ring_num = MLX4_EN_TX_RING_NUM;
} else {
@@ -407,14 +410,14 @@ static int mlx4_en_set_pauseparam(struct net_device *dev,
struct mlx4_en_dev *mdev = priv->mdev;
int err;
- mdev->profile.tx_pause = pause->tx_pause != 0;
- mdev->profile.rx_pause = pause->rx_pause != 0;
+ priv->prof->tx_pause = pause->tx_pause != 0;
+ priv->prof->rx_pause = pause->rx_pause != 0;
err = mlx4_SET_PORT_general(mdev->dev, priv->port,
priv->rx_skb_size + ETH_FCS_LEN,
- mdev->profile.tx_pause,
- mdev->profile.tx_ppp,
- mdev->profile.rx_pause,
- mdev->profile.rx_ppp);
+ priv->prof->tx_pause,
+ priv->prof->tx_ppp,
+ priv->prof->rx_pause,
+ priv->prof->rx_ppp);
if (err)
mlx4_err(mdev, "Failed setting pause params to\n");
@@ -425,10 +428,9 @@ static void mlx4_en_get_pauseparam(struct net_device *dev,
struct ethtool_pauseparam *pause)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
- struct mlx4_en_dev *mdev = priv->mdev;
- pause->tx_pause = mdev->profile.tx_pause;
- pause->rx_pause = mdev->profile.rx_pause;
+ pause->tx_pause = priv->prof->tx_pause;
+ pause->rx_pause = priv->prof->rx_pause;
}
static void mlx4_en_get_ringparam(struct net_device *dev,
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
index 468921b8f4b..90a0281d15e 100644
--- a/drivers/net/mlx4/main.c
+++ b/drivers/net/mlx4/main.c
@@ -753,6 +753,7 @@ static int mlx4_setup_hca(struct mlx4_dev *dev)
struct mlx4_priv *priv = mlx4_priv(dev);
int err;
int port;
+ __be32 ib_port_default_caps;
err = mlx4_init_uar_table(dev);
if (err) {
@@ -852,6 +853,13 @@ static int mlx4_setup_hca(struct mlx4_dev *dev)
}
for (port = 1; port <= dev->caps.num_ports; port++) {
+ ib_port_default_caps = 0;
+ err = mlx4_get_port_ib_caps(dev, port, &ib_port_default_caps);
+ if (err)
+ mlx4_warn(dev, "failed to get port %d default "
+ "ib capabilities (%d). Continuing with "
+ "caps = 0\n", port, err);
+ dev->caps.ib_port_def_cap[port] = ib_port_default_caps;
err = mlx4_SET_PORT(dev, port);
if (err) {
mlx4_err(dev, "Failed to set port %d, aborting\n",
diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h
index fa431fad0ee..34c909deaff 100644
--- a/drivers/net/mlx4/mlx4.h
+++ b/drivers/net/mlx4/mlx4.h
@@ -87,6 +87,9 @@ enum {
#ifdef CONFIG_MLX4_DEBUG
extern int mlx4_debug_level;
+#else /* CONFIG_MLX4_DEBUG */
+#define mlx4_debug_level (0)
+#endif /* CONFIG_MLX4_DEBUG */
#define mlx4_dbg(mdev, format, arg...) \
do { \
@@ -94,12 +97,6 @@ extern int mlx4_debug_level;
dev_printk(KERN_DEBUG, &mdev->pdev->dev, format, ## arg); \
} while (0)
-#else /* CONFIG_MLX4_DEBUG */
-
-#define mlx4_dbg(mdev, format, arg...) do { (void) mdev; } while (0)
-
-#endif /* CONFIG_MLX4_DEBUG */
-
#define mlx4_err(mdev, format, arg...) \
dev_err(&mdev->pdev->dev, format, ## arg)
#define mlx4_info(mdev, format, arg...) \
@@ -388,5 +385,6 @@ void mlx4_init_mac_table(struct mlx4_dev *dev, struct mlx4_mac_table *table);
void mlx4_init_vlan_table(struct mlx4_dev *dev, struct mlx4_vlan_table *table);
int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port);
+int mlx4_get_port_ib_caps(struct mlx4_dev *dev, u8 port, __be32 *caps);
#endif /* MLX4_H */
diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h
index 11fb17c6e97..98ddc0811f9 100644
--- a/drivers/net/mlx4/mlx4_en.h
+++ b/drivers/net/mlx4/mlx4_en.h
@@ -322,6 +322,10 @@ struct mlx4_en_port_profile {
u32 rx_ring_num;
u32 tx_ring_size;
u32 rx_ring_size;
+ u8 rx_pause;
+ u8 rx_ppp;
+ u8 tx_pause;
+ u8 tx_ppp;
};
struct mlx4_en_profile {
@@ -333,10 +337,6 @@ struct mlx4_en_profile {
int rx_moder_cnt;
int rx_moder_time;
int auto_moder;
- u8 rx_pause;
- u8 rx_ppp;
- u8 tx_pause;
- u8 tx_ppp;
u8 no_reset;
struct mlx4_en_port_profile prof[MLX4_MAX_PORTS + 1];
};
diff --git a/drivers/net/mlx4/port.c b/drivers/net/mlx4/port.c
index e2fdab42c4c..0a057e5dc63 100644
--- a/drivers/net/mlx4/port.c
+++ b/drivers/net/mlx4/port.c
@@ -258,6 +258,42 @@ out:
}
EXPORT_SYMBOL_GPL(mlx4_unregister_vlan);
+int mlx4_get_port_ib_caps(struct mlx4_dev *dev, u8 port, __be32 *caps)
+{
+ struct mlx4_cmd_mailbox *inmailbox, *outmailbox;
+ u8 *inbuf, *outbuf;
+ int err;
+
+ inmailbox = mlx4_alloc_cmd_mailbox(dev);
+ if (IS_ERR(inmailbox))
+ return PTR_ERR(inmailbox);
+
+ outmailbox = mlx4_alloc_cmd_mailbox(dev);
+ if (IS_ERR(outmailbox)) {
+ mlx4_free_cmd_mailbox(dev, inmailbox);
+ return PTR_ERR(outmailbox);
+ }
+
+ inbuf = inmailbox->buf;
+ outbuf = outmailbox->buf;
+ memset(inbuf, 0, 256);
+ memset(outbuf, 0, 256);
+ inbuf[0] = 1;
+ inbuf[1] = 1;
+ inbuf[2] = 1;
+ inbuf[3] = 1;
+ *(__be16 *) (&inbuf[16]) = cpu_to_be16(0x0015);
+ *(__be32 *) (&inbuf[20]) = cpu_to_be32(port);
+
+ err = mlx4_cmd_box(dev, inmailbox->dma, outmailbox->dma, port, 3,
+ MLX4_CMD_MAD_IFC, MLX4_CMD_TIME_CLASS_C);
+ if (!err)
+ *caps = *(__be32 *) (outbuf + 84);
+ mlx4_free_cmd_mailbox(dev, inmailbox);
+ mlx4_free_cmd_mailbox(dev, outmailbox);
+ return err;
+}
+
int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port)
{
struct mlx4_cmd_mailbox *mailbox;
@@ -273,7 +309,8 @@ int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port)
((u8 *) mailbox->buf)[3] = 6;
((__be16 *) mailbox->buf)[4] = cpu_to_be16(1 << 15);
((__be16 *) mailbox->buf)[6] = cpu_to_be16(1 << 15);
- }
+ } else
+ ((__be32 *) mailbox->buf)[1] = dev->caps.ib_port_def_cap[port];
err = mlx4_cmd(dev, mailbox->dma, port, is_eth, MLX4_CMD_SET_PORT,
MLX4_CMD_TIME_CLASS_B);
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index b9dcdbd369f..e513f76f2a9 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -899,7 +899,8 @@ static int txq_reclaim(struct tx_queue *txq, int budget, int force)
if (skb != NULL) {
if (skb_queue_len(&mp->rx_recycle) <
mp->default_rx_ring_size &&
- skb_recycle_check(skb, mp->skb_size))
+ skb_recycle_check(skb, mp->skb_size +
+ dma_get_cache_alignment() - 1))
__skb_queue_head(&mp->rx_recycle, skb);
else
dev_kfree_skb(skb);
@@ -2435,8 +2436,8 @@ static int mv643xx_eth_shared_remove(struct platform_device *pdev)
struct mv643xx_eth_shared_platform_data *pd = pdev->dev.platform_data;
if (pd == NULL || pd->shared_smi == NULL) {
- mdiobus_free(msp->smi_bus);
mdiobus_unregister(msp->smi_bus);
+ mdiobus_free(msp->smi_bus);
}
if (msp->err_interrupt != NO_IRQ)
free_irq(msp->err_interrupt, msp);
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
index a5f428bcc0e..b3786709730 100644
--- a/drivers/net/myri10ge/myri10ge.c
+++ b/drivers/net/myri10ge/myri10ge.c
@@ -75,7 +75,7 @@
#include "myri10ge_mcp.h"
#include "myri10ge_mcp_gen_header.h"
-#define MYRI10GE_VERSION_STR "1.4.3-1.375"
+#define MYRI10GE_VERSION_STR "1.4.3-1.378"
MODULE_DESCRIPTION("Myricom 10G driver (10GbE)");
MODULE_AUTHOR("Maintainer: help@myri.com");
@@ -1393,6 +1393,7 @@ myri10ge_tx_done(struct myri10ge_slice_state *ss, int mcp_index)
if (tx->req == tx->done) {
tx->queue_active = 0;
put_be32(htonl(1), tx->send_stop);
+ mb();
mmiowb();
}
__netif_tx_unlock(dev_queue);
@@ -2865,6 +2866,7 @@ again:
if ((mgp->dev->real_num_tx_queues > 1) && tx->queue_active == 0) {
tx->queue_active = 1;
put_be32(htonl(1), tx->send_go);
+ mb();
mmiowb();
}
tx->pkt_start++;
diff --git a/drivers/net/netx-eth.c b/drivers/net/netx-eth.c
index b9bed82e1d2..b289a0a2b94 100644
--- a/drivers/net/netx-eth.c
+++ b/drivers/net/netx-eth.c
@@ -401,6 +401,8 @@ static int netx_eth_drv_probe(struct platform_device *pdev)
priv->xmac_base = priv->xc->xmac_base;
priv->sram_base = priv->xc->sram_base;
+ spin_lock_init(&priv->lock);
+
ret = pfifo_request(PFIFO_MASK(priv->id));
if (ret) {
printk("unable to request PFIFO\n");
diff --git a/drivers/net/niu.c b/drivers/net/niu.c
index 9acb5d70a3a..1b6f548c441 100644
--- a/drivers/net/niu.c
+++ b/drivers/net/niu.c
@@ -33,8 +33,8 @@
#define DRV_MODULE_NAME "niu"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "0.9"
-#define DRV_MODULE_RELDATE "May 4, 2008"
+#define DRV_MODULE_VERSION "1.0"
+#define DRV_MODULE_RELDATE "Nov 14, 2008"
static char version[] __devinitdata =
DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
@@ -51,8 +51,7 @@ MODULE_VERSION(DRV_MODULE_VERSION);
#ifndef readq
static u64 readq(void __iomem *reg)
{
- return (((u64)readl(reg + 0x4UL) << 32) |
- (u64)readl(reg));
+ return ((u64) readl(reg)) | (((u64) readl(reg + 4UL)) << 32);
}
static void writeq(u64 val, void __iomem *reg)
@@ -407,7 +406,7 @@ static int esr2_set_rx_cfg(struct niu *np, unsigned long channel, u32 val)
}
/* Mode is always 10G fiber. */
-static int serdes_init_niu(struct niu *np)
+static int serdes_init_niu_10g_fiber(struct niu *np)
{
struct niu_link_config *lp = &np->link_config;
u32 tx_cfg, rx_cfg;
@@ -444,6 +443,223 @@ static int serdes_init_niu(struct niu *np)
return 0;
}
+static int serdes_init_niu_1g_serdes(struct niu *np)
+{
+ struct niu_link_config *lp = &np->link_config;
+ u16 pll_cfg, pll_sts;
+ int max_retry = 100;
+ u64 sig, mask, val;
+ u32 tx_cfg, rx_cfg;
+ unsigned long i;
+ int err;
+
+ tx_cfg = (PLL_TX_CFG_ENTX | PLL_TX_CFG_SWING_1375MV |
+ PLL_TX_CFG_RATE_HALF);
+ rx_cfg = (PLL_RX_CFG_ENRX | PLL_RX_CFG_TERM_0P8VDDT |
+ PLL_RX_CFG_ALIGN_ENA | PLL_RX_CFG_LOS_LTHRESH |
+ PLL_RX_CFG_RATE_HALF);
+
+ if (np->port == 0)
+ rx_cfg |= PLL_RX_CFG_EQ_LP_ADAPTIVE;
+
+ if (lp->loopback_mode == LOOPBACK_PHY) {
+ u16 test_cfg = PLL_TEST_CFG_LOOPBACK_CML_DIS;
+
+ mdio_write(np, np->port, NIU_ESR2_DEV_ADDR,
+ ESR2_TI_PLL_TEST_CFG_L, test_cfg);
+
+ tx_cfg |= PLL_TX_CFG_ENTEST;
+ rx_cfg |= PLL_RX_CFG_ENTEST;
+ }
+
+ /* Initialize PLL for 1G */
+ pll_cfg = (PLL_CFG_ENPLL | PLL_CFG_MPY_8X);
+
+ err = mdio_write(np, np->port, NIU_ESR2_DEV_ADDR,
+ ESR2_TI_PLL_CFG_L, pll_cfg);
+ if (err) {
+ dev_err(np->device, PFX "NIU Port %d "
+ "serdes_init_niu_1g_serdes: "
+ "mdio write to ESR2_TI_PLL_CFG_L failed", np->port);
+ return err;
+ }
+
+ pll_sts = PLL_CFG_ENPLL;
+
+ err = mdio_write(np, np->port, NIU_ESR2_DEV_ADDR,
+ ESR2_TI_PLL_STS_L, pll_sts);
+ if (err) {
+ dev_err(np->device, PFX "NIU Port %d "
+ "serdes_init_niu_1g_serdes: "
+ "mdio write to ESR2_TI_PLL_STS_L failed", np->port);
+ return err;
+ }
+
+ udelay(200);
+
+ /* Initialize all 4 lanes of the SERDES. */
+ for (i = 0; i < 4; i++) {
+ err = esr2_set_tx_cfg(np, i, tx_cfg);
+ if (err)
+ return err;
+ }
+
+ for (i = 0; i < 4; i++) {
+ err = esr2_set_rx_cfg(np, i, rx_cfg);
+ if (err)
+ return err;
+ }
+
+ switch (np->port) {
+ case 0:
+ val = (ESR_INT_SRDY0_P0 | ESR_INT_DET0_P0);
+ mask = val;
+ break;
+
+ case 1:
+ val = (ESR_INT_SRDY0_P1 | ESR_INT_DET0_P1);
+ mask = val;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ while (max_retry--) {
+ sig = nr64(ESR_INT_SIGNALS);
+ if ((sig & mask) == val)
+ break;
+
+ mdelay(500);
+ }
+
+ if ((sig & mask) != val) {
+ dev_err(np->device, PFX "Port %u signal bits [%08x] are not "
+ "[%08x]\n", np->port, (int) (sig & mask), (int) val);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int serdes_init_niu_10g_serdes(struct niu *np)
+{
+ struct niu_link_config *lp = &np->link_config;
+ u32 tx_cfg, rx_cfg, pll_cfg, pll_sts;
+ int max_retry = 100;
+ u64 sig, mask, val;
+ unsigned long i;
+ int err;
+
+ tx_cfg = (PLL_TX_CFG_ENTX | PLL_TX_CFG_SWING_1375MV);
+ rx_cfg = (PLL_RX_CFG_ENRX | PLL_RX_CFG_TERM_0P8VDDT |
+ PLL_RX_CFG_ALIGN_ENA | PLL_RX_CFG_LOS_LTHRESH |
+ PLL_RX_CFG_EQ_LP_ADAPTIVE);
+
+ if (lp->loopback_mode == LOOPBACK_PHY) {
+ u16 test_cfg = PLL_TEST_CFG_LOOPBACK_CML_DIS;
+
+ mdio_write(np, np->port, NIU_ESR2_DEV_ADDR,
+ ESR2_TI_PLL_TEST_CFG_L, test_cfg);
+
+ tx_cfg |= PLL_TX_CFG_ENTEST;
+ rx_cfg |= PLL_RX_CFG_ENTEST;
+ }
+
+ /* Initialize PLL for 10G */
+ pll_cfg = (PLL_CFG_ENPLL | PLL_CFG_MPY_10X);
+
+ err = mdio_write(np, np->port, NIU_ESR2_DEV_ADDR,
+ ESR2_TI_PLL_CFG_L, pll_cfg & 0xffff);
+ if (err) {
+ dev_err(np->device, PFX "NIU Port %d "
+ "serdes_init_niu_10g_serdes: "
+ "mdio write to ESR2_TI_PLL_CFG_L failed", np->port);
+ return err;
+ }
+
+ pll_sts = PLL_CFG_ENPLL;
+
+ err = mdio_write(np, np->port, NIU_ESR2_DEV_ADDR,
+ ESR2_TI_PLL_STS_L, pll_sts & 0xffff);
+ if (err) {
+ dev_err(np->device, PFX "NIU Port %d "
+ "serdes_init_niu_10g_serdes: "
+ "mdio write to ESR2_TI_PLL_STS_L failed", np->port);
+ return err;
+ }
+
+ udelay(200);
+
+ /* Initialize all 4 lanes of the SERDES. */
+ for (i = 0; i < 4; i++) {
+ err = esr2_set_tx_cfg(np, i, tx_cfg);
+ if (err)
+ return err;
+ }
+
+ for (i = 0; i < 4; i++) {
+ err = esr2_set_rx_cfg(np, i, rx_cfg);
+ if (err)
+ return err;
+ }
+
+ /* check if serdes is ready */
+
+ switch (np->port) {
+ case 0:
+ mask = ESR_INT_SIGNALS_P0_BITS;
+ val = (ESR_INT_SRDY0_P0 |
+ ESR_INT_DET0_P0 |
+ ESR_INT_XSRDY_P0 |
+ ESR_INT_XDP_P0_CH3 |
+ ESR_INT_XDP_P0_CH2 |
+ ESR_INT_XDP_P0_CH1 |
+ ESR_INT_XDP_P0_CH0);
+ break;
+
+ case 1:
+ mask = ESR_INT_SIGNALS_P1_BITS;
+ val = (ESR_INT_SRDY0_P1 |
+ ESR_INT_DET0_P1 |
+ ESR_INT_XSRDY_P1 |
+ ESR_INT_XDP_P1_CH3 |
+ ESR_INT_XDP_P1_CH2 |
+ ESR_INT_XDP_P1_CH1 |
+ ESR_INT_XDP_P1_CH0);
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ while (max_retry--) {
+ sig = nr64(ESR_INT_SIGNALS);
+ if ((sig & mask) == val)
+ break;
+
+ mdelay(500);
+ }
+
+ if ((sig & mask) != val) {
+ pr_info(PFX "NIU Port %u signal bits [%08x] are not "
+ "[%08x] for 10G...trying 1G\n",
+ np->port, (int) (sig & mask), (int) val);
+
+ /* 10G failed, try initializing at 1G */
+ err = serdes_init_niu_1g_serdes(np);
+ if (!err) {
+ np->flags &= ~NIU_FLAGS_10G;
+ np->mac_xcvr = MAC_XCVR_PCS;
+ } else {
+ dev_err(np->device, PFX "Port %u 10G/1G SERDES "
+ "Link Failed \n", np->port);
+ return -ENODEV;
+ }
+ }
+ return 0;
+}
+
static int esr_read_rxtx_ctrl(struct niu *np, unsigned long chan, u32 *val)
{
int err;
@@ -1955,13 +2171,23 @@ static const struct niu_phy_ops phy_ops_10g_serdes = {
.link_status = link_status_10g_serdes,
};
+static const struct niu_phy_ops phy_ops_10g_serdes_niu = {
+ .serdes_init = serdes_init_niu_10g_serdes,
+ .link_status = link_status_10g_serdes,
+};
+
+static const struct niu_phy_ops phy_ops_1g_serdes_niu = {
+ .serdes_init = serdes_init_niu_1g_serdes,
+ .link_status = link_status_1g_serdes,
+};
+
static const struct niu_phy_ops phy_ops_1g_rgmii = {
.xcvr_init = xcvr_init_1g_rgmii,
.link_status = link_status_1g_rgmii,
};
static const struct niu_phy_ops phy_ops_10g_fiber_niu = {
- .serdes_init = serdes_init_niu,
+ .serdes_init = serdes_init_niu_10g_fiber,
.xcvr_init = xcvr_init_10g,
.link_status = link_status_10g,
};
@@ -1999,11 +2225,21 @@ struct niu_phy_template {
u32 phy_addr_base;
};
-static const struct niu_phy_template phy_template_niu = {
+static const struct niu_phy_template phy_template_niu_10g_fiber = {
.ops = &phy_ops_10g_fiber_niu,
.phy_addr_base = 16,
};
+static const struct niu_phy_template phy_template_niu_10g_serdes = {
+ .ops = &phy_ops_10g_serdes_niu,
+ .phy_addr_base = 0,
+};
+
+static const struct niu_phy_template phy_template_niu_1g_serdes = {
+ .ops = &phy_ops_1g_serdes_niu,
+ .phy_addr_base = 0,
+};
+
static const struct niu_phy_template phy_template_10g_fiber = {
.ops = &phy_ops_10g_fiber,
.phy_addr_base = 8,
@@ -2183,8 +2419,25 @@ static int niu_determine_phy_disposition(struct niu *np)
u32 phy_addr_off = 0;
if (plat_type == PLAT_TYPE_NIU) {
- tp = &phy_template_niu;
- phy_addr_off += np->port;
+ switch (np->flags &
+ (NIU_FLAGS_10G |
+ NIU_FLAGS_FIBER |
+ NIU_FLAGS_XCVR_SERDES)) {
+ case NIU_FLAGS_10G | NIU_FLAGS_XCVR_SERDES:
+ /* 10G Serdes */
+ tp = &phy_template_niu_10g_serdes;
+ break;
+ case NIU_FLAGS_XCVR_SERDES:
+ /* 1G Serdes */
+ tp = &phy_template_niu_1g_serdes;
+ break;
+ case NIU_FLAGS_10G | NIU_FLAGS_FIBER:
+ /* 10G Fiber */
+ default:
+ tp = &phy_template_niu_10g_fiber;
+ phy_addr_off += np->port;
+ break;
+ }
} else {
switch (np->flags &
(NIU_FLAGS_10G |
@@ -7214,6 +7467,12 @@ static int __devinit niu_phy_type_prop_decode(struct niu *np,
np->flags |= NIU_FLAGS_10G;
np->flags &= ~NIU_FLAGS_FIBER;
np->mac_xcvr = MAC_XCVR_XPCS;
+ } else if (!strcmp(phy_prop, "xgsd") || !strcmp(phy_prop, "gsd")) {
+ /* 10G Serdes or 1G Serdes, default to 10G */
+ np->flags |= NIU_FLAGS_10G;
+ np->flags &= ~NIU_FLAGS_FIBER;
+ np->flags |= NIU_FLAGS_XCVR_SERDES;
+ np->mac_xcvr = MAC_XCVR_XPCS;
} else {
return -EINVAL;
}
@@ -7742,6 +8001,8 @@ static int __devinit walk_phys(struct niu *np, struct niu_parent *parent)
u32 val;
int err;
+ num_10g = num_1g = 0;
+
if (!strcmp(np->vpd.model, NIU_ALONSO_MDL_STR) ||
!strcmp(np->vpd.model, NIU_KIMI_MDL_STR)) {
num_10g = 0;
@@ -7758,6 +8019,16 @@ static int __devinit walk_phys(struct niu *np, struct niu_parent *parent)
parent->num_ports = 2;
val = (phy_encode(PORT_TYPE_10G, 0) |
phy_encode(PORT_TYPE_10G, 1));
+ } else if ((np->flags & NIU_FLAGS_XCVR_SERDES) &&
+ (parent->plat_type == PLAT_TYPE_NIU)) {
+ /* this is the Monza case */
+ if (np->flags & NIU_FLAGS_10G) {
+ val = (phy_encode(PORT_TYPE_10G, 0) |
+ phy_encode(PORT_TYPE_10G, 1));
+ } else {
+ val = (phy_encode(PORT_TYPE_1G, 0) |
+ phy_encode(PORT_TYPE_1G, 1));
+ }
} else {
err = fill_phy_probe_info(np, parent, info);
if (err)
@@ -8657,7 +8928,9 @@ static void __devinit niu_device_announce(struct niu *np)
dev->name,
(np->flags & NIU_FLAGS_XMAC ? "XMAC" : "BMAC"),
(np->flags & NIU_FLAGS_10G ? "10G" : "1G"),
- (np->flags & NIU_FLAGS_FIBER ? "FIBER" : "COPPER"),
+ (np->flags & NIU_FLAGS_FIBER ? "FIBER" :
+ (np->flags & NIU_FLAGS_XCVR_SERDES ? "SERDES" :
+ "COPPER")),
(np->mac_xcvr == MAC_XCVR_MII ? "MII" :
(np->mac_xcvr == MAC_XCVR_PCS ? "PCS" : "XPCS")),
np->vpd.phy_type);
diff --git a/drivers/net/niu.h b/drivers/net/niu.h
index c6fa883daa2..180ca8ae93d 100644
--- a/drivers/net/niu.h
+++ b/drivers/net/niu.h
@@ -1048,6 +1048,13 @@
#define PLL_CFG_LD_SHIFT 8
#define PLL_CFG_MPY 0x0000001e
#define PLL_CFG_MPY_SHIFT 1
+#define PLL_CFG_MPY_4X 0x0
+#define PLL_CFG_MPY_5X 0x00000002
+#define PLL_CFG_MPY_6X 0x00000004
+#define PLL_CFG_MPY_8X 0x00000008
+#define PLL_CFG_MPY_10X 0x0000000a
+#define PLL_CFG_MPY_12X 0x0000000c
+#define PLL_CFG_MPY_12P5X 0x0000000e
#define PLL_CFG_ENPLL 0x00000001
#define ESR2_TI_PLL_STS_L (ESR2_BASE + 0x002)
@@ -1093,6 +1100,9 @@
#define PLL_TX_CFG_INVPAIR 0x00000080
#define PLL_TX_CFG_RATE 0x00000060
#define PLL_TX_CFG_RATE_SHIFT 5
+#define PLL_TX_CFG_RATE_FULL 0x0
+#define PLL_TX_CFG_RATE_HALF 0x20
+#define PLL_TX_CFG_RATE_QUAD 0x40
#define PLL_TX_CFG_BUSWIDTH 0x0000001c
#define PLL_TX_CFG_BUSWIDTH_SHIFT 2
#define PLL_TX_CFG_ENTEST 0x00000002
@@ -1132,6 +1142,9 @@
#define PLL_RX_CFG_INVPAIR 0x00000080
#define PLL_RX_CFG_RATE 0x00000060
#define PLL_RX_CFG_RATE_SHIFT 5
+#define PLL_RX_CFG_RATE_FULL 0x0
+#define PLL_RX_CFG_RATE_HALF 0x20
+#define PLL_RX_CFG_RATE_QUAD 0x40
#define PLL_RX_CFG_BUSWIDTH 0x0000001c
#define PLL_RX_CFG_BUSWIDTH_SHIFT 2
#define PLL_RX_CFG_ENTEST 0x00000002
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c
index b37a498939a..0418045166c 100644
--- a/drivers/net/pcmcia/axnet_cs.c
+++ b/drivers/net/pcmcia/axnet_cs.c
@@ -779,6 +779,7 @@ static struct pcmcia_device_id axnet_ids[] = {
PCMCIA_DEVICE_PROD_ID12("IO DATA", "ETXPCM", 0x547e66dc, 0x233adac2),
PCMCIA_DEVICE_PROD_ID12("Linksys", "EtherFast 10/100 PC Card (PCMPC100 V3)", 0x0733cc81, 0x232019a8),
PCMCIA_DEVICE_PROD_ID12("MELCO", "LPC3-TX", 0x481e0094, 0xf91af609),
+ PCMCIA_DEVICE_PROD_ID12("NETGEAR", "FA411", 0x9aa79dc3, 0x40fad875),
PCMCIA_DEVICE_PROD_ID12("PCMCIA", "100BASE", 0x281f1c5d, 0x7c2add04),
PCMCIA_DEVICE_PROD_ID12("PCMCIA", "FastEtherCard", 0x281f1c5d, 0x7ef26116),
PCMCIA_DEVICE_PROD_ID12("PCMCIA", "FEP501", 0x281f1c5d, 0x2e272058),
@@ -1174,7 +1175,6 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
* ax_interrupt - handle the interrupts from an 8390
* @irq: interrupt number
* @dev_id: a pointer to the net_device
- * @regs: unused
*
* Handle the ether interface interrupts. We pull packets from
* the 8390 via the card specific functions and fire them at the networking
diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c
index cf3cca4642f..f51944b28cf 100644
--- a/drivers/net/pcmcia/ibmtr_cs.c
+++ b/drivers/net/pcmcia/ibmtr_cs.c
@@ -349,7 +349,7 @@ static int ibmtr_suspend(struct pcmcia_device *link)
return 0;
}
-static int ibmtr_resume(struct pcmcia_device *link)
+static int __devinit ibmtr_resume(struct pcmcia_device *link)
{
ibmtr_dev_t *info = link->priv;
struct net_device *dev = info->dev;
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index e40d6301aa7..ce486f09449 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -1693,7 +1693,6 @@ static struct pcmcia_device_id pcnet_ids[] = {
PCMCIA_DEVICE_PROD_ID12("National Semiconductor", "InfoMover NE4100", 0x36e1191f, 0xa6617ec8),
PCMCIA_DEVICE_PROD_ID12("NEC", "PC-9801N-J12", 0x18df0ba0, 0xbc912d76),
PCMCIA_DEVICE_PROD_ID12("NETGEAR", "FA410TX", 0x9aa79dc3, 0x60e5bc0e),
- PCMCIA_DEVICE_PROD_ID12("NETGEAR", "FA411", 0x9aa79dc3, 0x40fad875),
PCMCIA_DEVICE_PROD_ID12("Network Everywhere", "Fast Ethernet 10/100 PC Card", 0x820a67b6, 0x31ed1a5f),
PCMCIA_DEVICE_PROD_ID12("NextCom K.K.", "Next Hawk", 0xaedaec74, 0xad050ef1),
PCMCIA_DEVICE_PROD_ID12("PCMCIA", "10/100Mbps Ethernet Card", 0x281f1c5d, 0x6e41773b),
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index 4aa54794704..eb6411c4694 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -227,6 +227,59 @@ static int m88e1111_config_init(struct phy_device *phydev)
return 0;
}
+static int m88e1118_config_aneg(struct phy_device *phydev)
+{
+ int err;
+
+ err = phy_write(phydev, MII_BMCR, BMCR_RESET);
+ if (err < 0)
+ return err;
+
+ err = phy_write(phydev, MII_M1011_PHY_SCR,
+ MII_M1011_PHY_SCR_AUTO_CROSS);
+ if (err < 0)
+ return err;
+
+ err = genphy_config_aneg(phydev);
+ return 0;
+}
+
+static int m88e1118_config_init(struct phy_device *phydev)
+{
+ int err;
+
+ /* Change address */
+ err = phy_write(phydev, 0x16, 0x0002);
+ if (err < 0)
+ return err;
+
+ /* Enable 1000 Mbit */
+ err = phy_write(phydev, 0x15, 0x1070);
+ if (err < 0)
+ return err;
+
+ /* Change address */
+ err = phy_write(phydev, 0x16, 0x0003);
+ if (err < 0)
+ return err;
+
+ /* Adjust LED Control */
+ err = phy_write(phydev, 0x10, 0x021e);
+ if (err < 0)
+ return err;
+
+ /* Reset address */
+ err = phy_write(phydev, 0x16, 0x0);
+ if (err < 0)
+ return err;
+
+ err = phy_write(phydev, MII_BMCR, BMCR_RESET);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
static int m88e1145_config_init(struct phy_device *phydev)
{
int err;
@@ -416,6 +469,19 @@ static struct phy_driver marvell_drivers[] = {
.driver = { .owner = THIS_MODULE },
},
{
+ .phy_id = 0x01410e10,
+ .phy_id_mask = 0xfffffff0,
+ .name = "Marvell 88E1118",
+ .features = PHY_GBIT_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_init = &m88e1118_config_init,
+ .config_aneg = &m88e1118_config_aneg,
+ .read_status = &genphy_read_status,
+ .ack_interrupt = &marvell_ack_interrupt,
+ .config_intr = &marvell_config_intr,
+ .driver = {.owner = THIS_MODULE,},
+ },
+ {
.phy_id = 0x01410cd0,
.phy_id_mask = 0xfffffff0,
.name = "Marvell 88E1145",
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index d0ed1ef284a..289fc267edf 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -105,8 +105,6 @@ int mdiobus_register(struct mii_bus *bus)
return -EINVAL;
}
- bus->state = MDIOBUS_REGISTERED;
-
mutex_init(&bus->mdio_lock);
if (bus->reset)
@@ -123,6 +121,9 @@ int mdiobus_register(struct mii_bus *bus)
}
}
+ if (!err)
+ bus->state = MDIOBUS_REGISTERED;
+
pr_info("%s: probed\n", bus->name);
return err;
@@ -136,7 +137,7 @@ void mdiobus_unregister(struct mii_bus *bus)
BUG_ON(bus->state != MDIOBUS_REGISTERED);
bus->state = MDIOBUS_UNREGISTERED;
- device_unregister(&bus->dev);
+ device_del(&bus->dev);
for (i = 0; i < PHY_MAX_ADDR; i++) {
if (bus->phy_map[i])
device_unregister(&bus->phy_map[i]->dev);
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index e11b03b2b25..25acbbde4a6 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -227,8 +227,17 @@ struct phy_device * get_phy_device(struct mii_bus *bus, int addr)
if (r)
return ERR_PTR(r);
- /* If the phy_id is all Fs, there is no device there */
- if (0xffffffff == phy_id)
+ /* If the phy_id is mostly Fs, there is no device there */
+ if ((phy_id & 0x1fffffff) == 0x1fffffff)
+ return NULL;
+
+ /*
+ * Broken hardware is sometimes missing the pull down resistor on the
+ * MDIO line, which results in reads to non-existent devices returning
+ * 0 rather than 0xffff. Catch this here and treat 0 as a non-existent
+ * device as well.
+ */
+ if (phy_id == 0)
return NULL;
dev = phy_device_create(bus, addr, phy_id);
@@ -564,20 +573,32 @@ EXPORT_SYMBOL(genphy_restart_aneg);
*/
int genphy_config_aneg(struct phy_device *phydev)
{
- int result = 0;
+ int result;
- if (AUTONEG_ENABLE == phydev->autoneg) {
- int result = genphy_config_advert(phydev);
+ if (AUTONEG_ENABLE != phydev->autoneg)
+ return genphy_setup_forced(phydev);
- if (result < 0) /* error */
- return result;
+ result = genphy_config_advert(phydev);
+
+ if (result < 0) /* error */
+ return result;
+
+ if (result == 0) {
+ /* Advertisment hasn't changed, but maybe aneg was never on to
+ * begin with? Or maybe phy was isolated? */
+ int ctl = phy_read(phydev, MII_BMCR);
+
+ if (ctl < 0)
+ return ctl;
+
+ if (!(ctl & BMCR_ANENABLE) || (ctl & BMCR_ISOLATE))
+ result = 1; /* do restart aneg */
+ }
- /* Only restart aneg if we are advertising something different
- * than we were before. */
- if (result > 0)
- result = genphy_restart_aneg(phydev);
- } else
- result = genphy_setup_forced(phydev);
+ /* Only restart aneg if we are advertising something different
+ * than we were before. */
+ if (result > 0)
+ result = genphy_restart_aneg(phydev);
return result;
}
diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c
index 8874497b6bb..dd3b2447e85 100644
--- a/drivers/net/phy/vitesse.c
+++ b/drivers/net/phy/vitesse.c
@@ -34,6 +34,8 @@
#define MII_VSC8244_IMASK_DUPLEX 0x1000
#define MII_VSC8244_IMASK_MASK 0xf000
+#define MII_VSC8221_IMASK_MASK 0xa000
+
/* Vitesse Interrupt Status Register */
#define MII_VSC8244_ISTAT 0x1a
#define MII_VSC8244_ISTAT_STATUS 0x8000
@@ -49,6 +51,12 @@
#define MII_VSC8244_AUXCONSTAT_GBIT 0x0010
#define MII_VSC8244_AUXCONSTAT_100 0x0008
+#define MII_VSC8221_AUXCONSTAT_INIT 0x0004 /* need to set this bit? */
+#define MII_VSC8221_AUXCONSTAT_RESERVED 0x0004
+
+#define PHY_ID_VSC8244 0x000fc6c0
+#define PHY_ID_VSC8221 0x000fc550
+
MODULE_DESCRIPTION("Vitesse PHY driver");
MODULE_AUTHOR("Kriston Carson");
MODULE_LICENSE("GPL");
@@ -95,13 +103,15 @@ static int vsc824x_ack_interrupt(struct phy_device *phydev)
return (err < 0) ? err : 0;
}
-static int vsc824x_config_intr(struct phy_device *phydev)
+static int vsc82xx_config_intr(struct phy_device *phydev)
{
int err;
if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
err = phy_write(phydev, MII_VSC8244_IMASK,
- MII_VSC8244_IMASK_MASK);
+ phydev->drv->phy_id == PHY_ID_VSC8244 ?
+ MII_VSC8244_IMASK_MASK :
+ MII_VSC8221_IMASK_MASK);
else {
/*
* The Vitesse PHY cannot clear the interrupt
@@ -120,7 +130,7 @@ static int vsc824x_config_intr(struct phy_device *phydev)
/* Vitesse 824x */
static struct phy_driver vsc8244_driver = {
- .phy_id = 0x000fc6c0,
+ .phy_id = PHY_ID_VSC8244,
.name = "Vitesse VSC8244",
.phy_id_mask = 0x000fffc0,
.features = PHY_GBIT_FEATURES,
@@ -129,19 +139,55 @@ static struct phy_driver vsc8244_driver = {
.config_aneg = &genphy_config_aneg,
.read_status = &genphy_read_status,
.ack_interrupt = &vsc824x_ack_interrupt,
- .config_intr = &vsc824x_config_intr,
+ .config_intr = &vsc82xx_config_intr,
.driver = { .owner = THIS_MODULE,},
};
-static int __init vsc8244_init(void)
+static int vsc8221_config_init(struct phy_device *phydev)
{
- return phy_driver_register(&vsc8244_driver);
+ int err;
+
+ err = phy_write(phydev, MII_VSC8244_AUX_CONSTAT,
+ MII_VSC8221_AUXCONSTAT_INIT);
+ return err;
+
+ /* Perhaps we should set EXT_CON1 based on the interface?
+ Options are 802.3Z SerDes or SGMII */
+}
+
+/* Vitesse 8221 */
+static struct phy_driver vsc8221_driver = {
+ .phy_id = PHY_ID_VSC8221,
+ .phy_id_mask = 0x000ffff0,
+ .name = "Vitesse VSC8221",
+ .features = PHY_GBIT_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_init = &vsc8221_config_init,
+ .config_aneg = &genphy_config_aneg,
+ .read_status = &genphy_read_status,
+ .ack_interrupt = &vsc824x_ack_interrupt,
+ .config_intr = &vsc82xx_config_intr,
+ .driver = { .owner = THIS_MODULE,},
+};
+
+static int __init vsc82xx_init(void)
+{
+ int err;
+
+ err = phy_driver_register(&vsc8244_driver);
+ if (err < 0)
+ return err;
+ err = phy_driver_register(&vsc8221_driver);
+ if (err < 0)
+ phy_driver_unregister(&vsc8244_driver);
+ return err;
}
-static void __exit vsc8244_exit(void)
+static void __exit vsc82xx_exit(void)
{
phy_driver_unregister(&vsc8244_driver);
+ phy_driver_unregister(&vsc8221_driver);
}
-module_init(vsc8244_init);
-module_exit(vsc8244_exit);
+module_init(vsc82xx_init);
+module_exit(vsc82xx_exit);
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index 7e857e938ad..714a23035de 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -116,6 +116,7 @@ struct ppp {
unsigned long last_xmit; /* jiffies when last pkt sent 9c */
unsigned long last_recv; /* jiffies when last pkt rcvd a0 */
struct net_device *dev; /* network interface device a4 */
+ int closing; /* is device closing down? a8 */
#ifdef CONFIG_PPP_MULTILINK
int nxchan; /* next channel to send something on */
u32 nxseq; /* next sequence number to send */
@@ -995,7 +996,7 @@ ppp_xmit_process(struct ppp *ppp)
struct sk_buff *skb;
ppp_xmit_lock(ppp);
- if (ppp->dev) {
+ if (!ppp->closing) {
ppp_push(ppp);
while (!ppp->xmit_pending
&& (skb = skb_dequeue(&ppp->file.xq)))
@@ -1463,8 +1464,7 @@ static inline void
ppp_do_recv(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
{
ppp_recv_lock(ppp);
- /* ppp->dev == 0 means interface is closing down */
- if (ppp->dev)
+ if (!ppp->closing)
ppp_receive_frame(ppp, skb, pch);
else
kfree_skb(skb);
@@ -2498,18 +2498,16 @@ init_ppp_file(struct ppp_file *pf, int kind)
*/
static void ppp_shutdown_interface(struct ppp *ppp)
{
- struct net_device *dev;
-
mutex_lock(&all_ppp_mutex);
- ppp_lock(ppp);
- dev = ppp->dev;
- ppp->dev = NULL;
- ppp_unlock(ppp);
/* This will call dev_close() for us. */
- if (dev) {
- unregister_netdev(dev);
- free_netdev(dev);
- }
+ ppp_lock(ppp);
+ if (!ppp->closing) {
+ ppp->closing = 1;
+ ppp_unlock(ppp);
+ unregister_netdev(ppp->dev);
+ } else
+ ppp_unlock(ppp);
+
cardmap_set(&all_ppp_units, ppp->file.index, NULL);
ppp->file.dead = 1;
ppp->owner = NULL;
@@ -2554,7 +2552,7 @@ static void ppp_destroy_interface(struct ppp *ppp)
if (ppp->xmit_pending)
kfree_skb(ppp->xmit_pending);
- kfree(ppp);
+ free_netdev(ppp->dev);
}
/*
@@ -2616,7 +2614,7 @@ ppp_connect_channel(struct channel *pch, int unit)
if (pch->file.hdrlen > ppp->file.hdrlen)
ppp->file.hdrlen = pch->file.hdrlen;
hdrlen = pch->file.hdrlen + 2; /* for protocol bytes */
- if (ppp->dev && hdrlen > ppp->dev->hard_header_len)
+ if (hdrlen > ppp->dev->hard_header_len)
ppp->dev->hard_header_len = hdrlen;
list_add_tail(&pch->clist, &ppp->channels);
++ppp->n_channels;
diff --git a/drivers/net/pppol2tp.c b/drivers/net/pppol2tp.c
index 185b1dff10a..e98d9773158 100644
--- a/drivers/net/pppol2tp.c
+++ b/drivers/net/pppol2tp.c
@@ -1353,6 +1353,7 @@ static int pppol2tp_release(struct socket *sock)
kfree_skb(skb);
sock_put(sk);
}
+ sock_put(sk);
}
release_sock(sk);
diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c
index 3cdd07c45b6..508452c0215 100644
--- a/drivers/net/qla3xxx.c
+++ b/drivers/net/qla3xxx.c
@@ -1515,9 +1515,6 @@ static u32 ql_get_link_state(struct ql3_adapter *qdev)
linkState = LS_UP;
} else {
linkState = LS_DOWN;
- if (netif_msg_link(qdev))
- printk(KERN_WARNING PFX
- "%s: Link is down.\n", qdev->ndev->name);
}
return linkState;
}
@@ -1581,10 +1578,6 @@ static int ql_finish_auto_neg(struct ql3_adapter *qdev)
ql_mac_enable(qdev, 1);
}
- if (netif_msg_link(qdev))
- printk(KERN_DEBUG PFX
- "%s: Change port_link_state LS_DOWN to LS_UP.\n",
- qdev->ndev->name);
qdev->port_link_state = LS_UP;
netif_start_queue(qdev->ndev);
netif_carrier_on(qdev->ndev);
@@ -1655,14 +1648,9 @@ static void ql_link_state_machine_work(struct work_struct *work)
/* Fall Through */
case LS_DOWN:
- if (netif_msg_link(qdev))
- printk(KERN_DEBUG PFX
- "%s: port_link_state = LS_DOWN.\n",
- qdev->ndev->name);
if (curr_link_state == LS_UP) {
if (netif_msg_link(qdev))
- printk(KERN_DEBUG PFX
- "%s: curr_link_state = LS_UP.\n",
+ printk(KERN_INFO PFX "%s: Link is up.\n",
qdev->ndev->name);
if (ql_is_auto_neg_complete(qdev))
ql_finish_auto_neg(qdev);
@@ -1670,6 +1658,7 @@ static void ql_link_state_machine_work(struct work_struct *work)
if (qdev->port_link_state == LS_UP)
ql_link_down_detect_clear(qdev);
+ qdev->port_link_state = LS_UP;
}
break;
@@ -1678,12 +1667,14 @@ static void ql_link_state_machine_work(struct work_struct *work)
* See if the link is currently down or went down and came
* back up
*/
- if ((curr_link_state == LS_DOWN) || ql_link_down_detect(qdev)) {
+ if (curr_link_state == LS_DOWN) {
if (netif_msg_link(qdev))
printk(KERN_INFO PFX "%s: Link is down.\n",
qdev->ndev->name);
qdev->port_link_state = LS_DOWN;
}
+ if (ql_link_down_detect(qdev))
+ qdev->port_link_state = LS_DOWN;
break;
}
spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c
index a24bb68887a..59f242a6771 100644
--- a/drivers/net/sh_eth.c
+++ b/drivers/net/sh_eth.c
@@ -927,7 +927,7 @@ static int sh_eth_start_xmit(struct sk_buff *skb, struct net_device *ndev)
struct sh_eth_private *mdp = netdev_priv(ndev);
struct sh_eth_txdesc *txdesc;
u32 entry;
- int flags;
+ unsigned long flags;
spin_lock_irqsave(&mdp->lock, flags);
if ((mdp->cur_tx - mdp->dirty_tx) >= (TX_RING_SIZE - 4)) {
@@ -1141,7 +1141,7 @@ static int sh_mdio_init(struct net_device *ndev, int id)
/* Hook up MII support for ethtool */
mdp->mii_bus->name = "sh_mii";
mdp->mii_bus->parent = &ndev->dev;
- mdp->mii_bus->id[0] = id;
+ snprintf(mdp->mii_bus->id, MII_BUS_ID_SIZE, "%x", id);
/* PHY IRQ */
mdp->mii_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c
index fa3a460f8e2..8e8337e8b07 100644
--- a/drivers/net/sis900.c
+++ b/drivers/net/sis900.c
@@ -1630,7 +1630,6 @@ sis900_start_xmit(struct sk_buff *skb, struct net_device *net_dev)
* sis900_interrupt - sis900 interrupt handler
* @irq: the irq number
* @dev_instance: the client data object
- * @regs: snapshot of processor context
*
* The interrupt handler does all of the Rx thread work,
* and cleans up after the Tx thread
diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c
index 5051554ff05..9a16a79b67d 100644
--- a/drivers/net/smc911x.c
+++ b/drivers/net/smc911x.c
@@ -1735,7 +1735,7 @@ static const struct ethtool_ops smc911x_ethtool_ops = {
* This routine has a simple purpose -- make the SMC chip generate an
* interrupt, so an auto-detect routine can detect it, and find the IRQ,
*/
-static int __init smc911x_findirq(struct net_device *dev)
+static int __devinit smc911x_findirq(struct net_device *dev)
{
struct smc911x_local *lp = netdev_priv(dev);
int timeout = 20;
@@ -1799,7 +1799,7 @@ static int __init smc911x_findirq(struct net_device *dev)
* o actually GRAB the irq.
* o GRAB the region
*/
-static int __init smc911x_probe(struct net_device *dev)
+static int __devinit smc911x_probe(struct net_device *dev)
{
struct smc911x_local *lp = netdev_priv(dev);
int i, retval;
@@ -1813,7 +1813,7 @@ static int __init smc911x_probe(struct net_device *dev)
val = SMC_GET_BYTE_TEST(lp);
DBG(SMC_DEBUG_MISC, "%s: endian probe returned 0x%04x\n", CARDNAME, val);
if (val != 0x87654321) {
- printk(KERN_ERR "Invalid chip endian 0x08%x\n",val);
+ printk(KERN_ERR "Invalid chip endian 0x%08x\n",val);
retval = -ENODEV;
goto err_out;
}
@@ -2048,9 +2048,11 @@ err_out:
* 0 --> there is a device
* anything else, error
*/
-static int smc911x_drv_probe(struct platform_device *pdev)
+static int __devinit smc911x_drv_probe(struct platform_device *pdev)
{
+#ifdef SMC_DYNAMIC_BUS_CONFIG
struct smc911x_platdata *pd = pdev->dev.platform_data;
+#endif
struct net_device *ndev;
struct resource *res;
struct smc911x_local *lp;
@@ -2122,7 +2124,7 @@ out:
return ret;
}
-static int smc911x_drv_remove(struct platform_device *pdev)
+static int __devexit smc911x_drv_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
struct smc911x_local *lp = netdev_priv(ndev);
@@ -2182,9 +2184,9 @@ static int smc911x_drv_resume(struct platform_device *dev)
if (netif_running(ndev)) {
smc911x_reset(ndev);
- smc911x_enable(ndev);
if (lp->phy_type != 0)
smc911x_phy_configure(&lp->phy_configure);
+ smc911x_enable(ndev);
netif_device_attach(ndev);
}
}
@@ -2193,7 +2195,7 @@ static int smc911x_drv_resume(struct platform_device *dev)
static struct platform_driver smc911x_driver = {
.probe = smc911x_drv_probe,
- .remove = smc911x_drv_remove,
+ .remove = __devexit_p(smc911x_drv_remove),
.suspend = smc911x_drv_suspend,
.resume = smc911x_drv_resume,
.driver = {
diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c
index fc80f250da3..35c56abf411 100644
--- a/drivers/net/smc91x.c
+++ b/drivers/net/smc91x.c
@@ -1696,7 +1696,7 @@ static const struct ethtool_ops smc_ethtool_ops = {
* I just deleted auto_irq.c, since it was never built...
* --jgarzik
*/
-static int __init smc_findirq(struct smc_local *lp)
+static int __devinit smc_findirq(struct smc_local *lp)
{
void __iomem *ioaddr = lp->base;
int timeout = 20;
@@ -1770,7 +1770,7 @@ static int __init smc_findirq(struct smc_local *lp)
* o actually GRAB the irq.
* o GRAB the region
*/
-static int __init smc_probe(struct net_device *dev, void __iomem *ioaddr,
+static int __devinit smc_probe(struct net_device *dev, void __iomem *ioaddr,
unsigned long irq_flags)
{
struct smc_local *lp = netdev_priv(dev);
@@ -2126,7 +2126,7 @@ static void smc_release_datacs(struct platform_device *pdev, struct net_device *
* 0 --> there is a device
* anything else, error
*/
-static int smc_drv_probe(struct platform_device *pdev)
+static int __devinit smc_drv_probe(struct platform_device *pdev)
{
struct smc91x_platdata *pd = pdev->dev.platform_data;
struct smc_local *lp;
@@ -2240,7 +2240,7 @@ static int smc_drv_probe(struct platform_device *pdev)
return ret;
}
-static int smc_drv_remove(struct platform_device *pdev)
+static int __devexit smc_drv_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
struct smc_local *lp = netdev_priv(ndev);
@@ -2305,7 +2305,7 @@ static int smc_drv_resume(struct platform_device *dev)
static struct platform_driver smc_driver = {
.probe = smc_drv_probe,
- .remove = smc_drv_remove,
+ .remove = __devexit_p(smc_drv_remove),
.suspend = smc_drv_suspend,
.resume = smc_drv_resume,
.driver = {
diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c
index b6435d0d71f..07599b49235 100644
--- a/drivers/net/spider_net.c
+++ b/drivers/net/spider_net.c
@@ -672,7 +672,6 @@ write_hash:
/**
* spider_net_prepare_tx_descr - fill tx descriptor with skb data
* @card: card structure
- * @descr: descriptor structure to fill out
* @skb: packet to use
*
* returns 0 on success, <0 on failure.
@@ -867,7 +866,6 @@ spider_net_release_tx_chain(struct spider_net_card *card, int brutal)
/**
* spider_net_kick_tx_dma - enables TX DMA processing
* @card: card structure
- * @descr: descriptor address to enable TX processing at
*
* This routine will start the transmit DMA running if
* it is not already running. This routine ned only be
@@ -1637,7 +1635,6 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg,
* spider_net_interrupt - interrupt handler for spider_net
* @irq: interrupt number
* @ptr: pointer to net_device
- * @regs: PU registers
*
* returns IRQ_HANDLED, if interrupt was for driver, or IRQ_NONE, if no
* interrupt found raised by card.
@@ -2419,7 +2416,6 @@ spider_net_undo_pci_setup(struct spider_net_card *card)
/**
* spider_net_setup_pci_dev - sets up the device in terms of PCI operations
- * @card: card structure
* @pdev: PCI device
*
* Returns the card structure or NULL if any errors occur
diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c
index 1d2ef8f4778..5a40f2d78be 100644
--- a/drivers/net/starfire.c
+++ b/drivers/net/starfire.c
@@ -1509,6 +1509,11 @@ static int __netdev_rx(struct net_device *dev, int *quota)
desc->status = 0;
np->rx_done = (np->rx_done + 1) % DONE_Q_SIZE;
}
+
+ if (*quota == 0) { /* out of rx quota */
+ retcode = 1;
+ goto out;
+ }
writew(np->rx_done, np->base + CompletionQConsumerIdx);
out:
diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c
index 4291458955e..fed7eba65ea 100644
--- a/drivers/net/sungem.c
+++ b/drivers/net/sungem.c
@@ -1142,6 +1142,70 @@ static int gem_start_xmit(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_OK;
}
+static void gem_pcs_reset(struct gem *gp)
+{
+ int limit;
+ u32 val;
+
+ /* Reset PCS unit. */
+ val = readl(gp->regs + PCS_MIICTRL);
+ val |= PCS_MIICTRL_RST;
+ writel(val, gp->regs + PCS_MIICTRL);
+
+ limit = 32;
+ while (readl(gp->regs + PCS_MIICTRL) & PCS_MIICTRL_RST) {
+ udelay(100);
+ if (limit-- <= 0)
+ break;
+ }
+ if (limit <= 0)
+ printk(KERN_WARNING "%s: PCS reset bit would not clear.\n",
+ gp->dev->name);
+}
+
+static void gem_pcs_reinit_adv(struct gem *gp)
+{
+ u32 val;
+
+ /* Make sure PCS is disabled while changing advertisement
+ * configuration.
+ */
+ val = readl(gp->regs + PCS_CFG);
+ val &= ~(PCS_CFG_ENABLE | PCS_CFG_TO);
+ writel(val, gp->regs + PCS_CFG);
+
+ /* Advertise all capabilities except assymetric
+ * pause.
+ */
+ val = readl(gp->regs + PCS_MIIADV);
+ val |= (PCS_MIIADV_FD | PCS_MIIADV_HD |
+ PCS_MIIADV_SP | PCS_MIIADV_AP);
+ writel(val, gp->regs + PCS_MIIADV);
+
+ /* Enable and restart auto-negotiation, disable wrapback/loopback,
+ * and re-enable PCS.
+ */
+ val = readl(gp->regs + PCS_MIICTRL);
+ val |= (PCS_MIICTRL_RAN | PCS_MIICTRL_ANE);
+ val &= ~PCS_MIICTRL_WB;
+ writel(val, gp->regs + PCS_MIICTRL);
+
+ val = readl(gp->regs + PCS_CFG);
+ val |= PCS_CFG_ENABLE;
+ writel(val, gp->regs + PCS_CFG);
+
+ /* Make sure serialink loopback is off. The meaning
+ * of this bit is logically inverted based upon whether
+ * you are in Serialink or SERDES mode.
+ */
+ val = readl(gp->regs + PCS_SCTRL);
+ if (gp->phy_type == phy_serialink)
+ val &= ~PCS_SCTRL_LOOP;
+ else
+ val |= PCS_SCTRL_LOOP;
+ writel(val, gp->regs + PCS_SCTRL);
+}
+
#define STOP_TRIES 32
/* Must be invoked under gp->lock and gp->tx_lock. */
@@ -1168,6 +1232,9 @@ static void gem_reset(struct gem *gp)
if (limit <= 0)
printk(KERN_ERR "%s: SW reset is ghetto.\n", gp->dev->name);
+
+ if (gp->phy_type == phy_serialink || gp->phy_type == phy_serdes)
+ gem_pcs_reinit_adv(gp);
}
/* Must be invoked under gp->lock and gp->tx_lock. */
@@ -1324,7 +1391,7 @@ static int gem_set_link_modes(struct gem *gp)
gp->phy_type == phy_serdes) {
u32 pcs_lpa = readl(gp->regs + PCS_MIILP);
- if (pcs_lpa & PCS_MIIADV_FD)
+ if ((pcs_lpa & PCS_MIIADV_FD) || gp->phy_type == phy_serdes)
full_duplex = 1;
speed = SPEED_1000;
}
@@ -1488,6 +1555,9 @@ static void gem_link_timer(unsigned long data)
val = readl(gp->regs + PCS_MIISTAT);
if ((val & PCS_MIISTAT_LS) != 0) {
+ if (gp->lstate == link_up)
+ goto restart;
+
gp->lstate = link_up;
netif_carrier_on(gp->dev);
(void)gem_set_link_modes(gp);
@@ -1708,61 +1778,8 @@ static void gem_init_phy(struct gem *gp)
if (gp->phy_mii.def && gp->phy_mii.def->ops->init)
gp->phy_mii.def->ops->init(&gp->phy_mii);
} else {
- u32 val;
- int limit;
-
- /* Reset PCS unit. */
- val = readl(gp->regs + PCS_MIICTRL);
- val |= PCS_MIICTRL_RST;
- writeb(val, gp->regs + PCS_MIICTRL);
-
- limit = 32;
- while (readl(gp->regs + PCS_MIICTRL) & PCS_MIICTRL_RST) {
- udelay(100);
- if (limit-- <= 0)
- break;
- }
- if (limit <= 0)
- printk(KERN_WARNING "%s: PCS reset bit would not clear.\n",
- gp->dev->name);
-
- /* Make sure PCS is disabled while changing advertisement
- * configuration.
- */
- val = readl(gp->regs + PCS_CFG);
- val &= ~(PCS_CFG_ENABLE | PCS_CFG_TO);
- writel(val, gp->regs + PCS_CFG);
-
- /* Advertise all capabilities except assymetric
- * pause.
- */
- val = readl(gp->regs + PCS_MIIADV);
- val |= (PCS_MIIADV_FD | PCS_MIIADV_HD |
- PCS_MIIADV_SP | PCS_MIIADV_AP);
- writel(val, gp->regs + PCS_MIIADV);
-
- /* Enable and restart auto-negotiation, disable wrapback/loopback,
- * and re-enable PCS.
- */
- val = readl(gp->regs + PCS_MIICTRL);
- val |= (PCS_MIICTRL_RAN | PCS_MIICTRL_ANE);
- val &= ~PCS_MIICTRL_WB;
- writel(val, gp->regs + PCS_MIICTRL);
-
- val = readl(gp->regs + PCS_CFG);
- val |= PCS_CFG_ENABLE;
- writel(val, gp->regs + PCS_CFG);
-
- /* Make sure serialink loopback is off. The meaning
- * of this bit is logically inverted based upon whether
- * you are in Serialink or SERDES mode.
- */
- val = readl(gp->regs + PCS_SCTRL);
- if (gp->phy_type == phy_serialink)
- val &= ~PCS_SCTRL_LOOP;
- else
- val |= PCS_SCTRL_LOOP;
- writel(val, gp->regs + PCS_SCTRL);
+ gem_pcs_reset(gp);
+ gem_pcs_reinit_adv(gp);
}
/* Default aneg parameters */
@@ -2680,6 +2697,21 @@ static int gem_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
cmd->speed = 0;
cmd->duplex = cmd->port = cmd->phy_address =
cmd->transceiver = cmd->autoneg = 0;
+
+ /* serdes means usually a Fibre connector, with most fixed */
+ if (gp->phy_type == phy_serdes) {
+ cmd->port = PORT_FIBRE;
+ cmd->supported = (SUPPORTED_1000baseT_Half |
+ SUPPORTED_1000baseT_Full |
+ SUPPORTED_FIBRE | SUPPORTED_Autoneg |
+ SUPPORTED_Pause | SUPPORTED_Asym_Pause);
+ cmd->advertising = cmd->supported;
+ cmd->transceiver = XCVR_INTERNAL;
+ if (gp->lstate == link_up)
+ cmd->speed = SPEED_1000;
+ cmd->duplex = DUPLEX_FULL;
+ cmd->autoneg = 1;
+ }
}
cmd->maxtxpkt = cmd->maxrxpkt = 0;
diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c
index c41d6876136..e60498232b9 100644
--- a/drivers/net/tlan.c
+++ b/drivers/net/tlan.c
@@ -1098,6 +1098,7 @@ static int TLan_StartTx( struct sk_buff *skb, struct net_device *dev )
dma_addr_t tail_list_phys;
u8 *tail_buffer;
unsigned long flags;
+ unsigned int txlen;
if ( ! priv->phyOnline ) {
TLAN_DBG( TLAN_DEBUG_TX, "TRANSMIT: %s PHY is not ready\n",
@@ -1108,6 +1109,7 @@ static int TLan_StartTx( struct sk_buff *skb, struct net_device *dev )
if (skb_padto(skb, TLAN_MIN_FRAME_SIZE))
return 0;
+ txlen = max(skb->len, (unsigned int)TLAN_MIN_FRAME_SIZE);
tail_list = priv->txList + priv->txTail;
tail_list_phys = priv->txListDMA + sizeof(TLanList) * priv->txTail;
@@ -1125,16 +1127,16 @@ static int TLan_StartTx( struct sk_buff *skb, struct net_device *dev )
if ( bbuf ) {
tail_buffer = priv->txBuffer + ( priv->txTail * TLAN_MAX_FRAME_SIZE );
- skb_copy_from_linear_data(skb, tail_buffer, skb->len);
+ skb_copy_from_linear_data(skb, tail_buffer, txlen);
} else {
tail_list->buffer[0].address = pci_map_single(priv->pciDev,
- skb->data, skb->len,
+ skb->data, txlen,
PCI_DMA_TODEVICE);
TLan_StoreSKB(tail_list, skb);
}
- tail_list->frameSize = (u16) skb->len;
- tail_list->buffer[0].count = TLAN_LAST_BUFFER | (u32) skb->len;
+ tail_list->frameSize = (u16) txlen;
+ tail_list->buffer[0].count = TLAN_LAST_BUFFER | (u32) txlen;
tail_list->buffer[1].count = 0;
tail_list->buffer[1].address = 0;
@@ -1431,7 +1433,9 @@ static u32 TLan_HandleTxEOF( struct net_device *dev, u16 host_int )
if ( ! bbuf ) {
struct sk_buff *skb = TLan_GetSKB(head_list);
pci_unmap_single(priv->pciDev, head_list->buffer[0].address,
- skb->len, PCI_DMA_TODEVICE);
+ max(skb->len,
+ (unsigned int)TLAN_MIN_FRAME_SIZE),
+ PCI_DMA_TODEVICE);
dev_kfree_skb_any(skb);
head_list->buffer[8].address = 0;
head_list->buffer[9].address = 0;
@@ -2055,9 +2059,12 @@ static void TLan_FreeLists( struct net_device *dev )
list = priv->txList + i;
skb = TLan_GetSKB(list);
if ( skb ) {
- pci_unmap_single(priv->pciDev,
- list->buffer[0].address, skb->len,
- PCI_DMA_TODEVICE);
+ pci_unmap_single(
+ priv->pciDev,
+ list->buffer[0].address,
+ max(skb->len,
+ (unsigned int)TLAN_MIN_FRAME_SIZE),
+ PCI_DMA_TODEVICE);
dev_kfree_skb_any( skb );
list->buffer[8].address = 0;
list->buffer[9].address = 0;
diff --git a/drivers/net/ucc_geth_ethtool.c b/drivers/net/ucc_geth_ethtool.c
index 85f38a6b6a4..68a7f541413 100644
--- a/drivers/net/ucc_geth_ethtool.c
+++ b/drivers/net/ucc_geth_ethtool.c
@@ -323,17 +323,17 @@ static void uec_get_ethtool_stats(struct net_device *netdev,
if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_HARDWARE) {
base = (u32 __iomem *)&ugeth->ug_regs->tx64;
for (i = 0; i < UEC_HW_STATS_LEN; i++)
- data[j++] = (u64)in_be32(&base[i]);
+ data[j++] = in_be32(&base[i]);
}
if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX) {
base = (u32 __iomem *)ugeth->p_tx_fw_statistics_pram;
for (i = 0; i < UEC_TX_FW_STATS_LEN; i++)
- data[j++] = (u64)in_be32(&base[i]);
+ data[j++] = base ? in_be32(&base[i]) : 0;
}
if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX) {
base = (u32 __iomem *)ugeth->p_rx_fw_statistics_pram;
for (i = 0; i < UEC_RX_FW_STATS_LEN; i++)
- data[j++] = (u64)in_be32(&base[i]);
+ data[j++] = base ? in_be32(&base[i]) : 0;
}
}
diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c
index 37ecf845edf..de57490103f 100644
--- a/drivers/net/usb/asix.c
+++ b/drivers/net/usb/asix.c
@@ -1102,12 +1102,14 @@ static int ax88178_link_reset(struct usbnet *dev)
mode = AX88178_MEDIUM_DEFAULT;
if (ecmd.speed == SPEED_1000)
- mode |= AX_MEDIUM_GM | AX_MEDIUM_ENCK;
+ mode |= AX_MEDIUM_GM;
else if (ecmd.speed == SPEED_100)
mode |= AX_MEDIUM_PS;
else
mode &= ~(AX_MEDIUM_PS | AX_MEDIUM_GM);
+ mode |= AX_MEDIUM_ENCK;
+
if (ecmd.duplex == DUPLEX_FULL)
mode |= AX_MEDIUM_FD;
else
@@ -1444,6 +1446,10 @@ static const struct usb_device_id products [] = {
// Apple USB Ethernet Adapter
USB_DEVICE(0x05ac, 0x1402),
.driver_info = (unsigned long) &ax88772_info,
+}, {
+ // Cables-to-Go USB Ethernet Adapter
+ USB_DEVICE(0x0b95, 0x772a),
+ .driver_info = (unsigned long) &ax88772_info,
},
{ }, // END
};
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
index 3590ea5a902..11cb3e504e1 100644
--- a/drivers/net/via-velocity.c
+++ b/drivers/net/via-velocity.c
@@ -2296,7 +2296,7 @@ static void velocity_set_multi(struct net_device *dev)
}
mac_set_cam_mask(regs, vptr->mCAMmask);
- rx_mode = (RCR_AM | RCR_AB);
+ rx_mode = RCR_AM | RCR_AB | RCR_AP;
}
if (dev->mtu > 1500)
rx_mode |= RCR_AL;
diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c
index cfd4d052d66..2d14255eb10 100644
--- a/drivers/net/wireless/ath5k/base.c
+++ b/drivers/net/wireless/ath5k/base.c
@@ -240,6 +240,10 @@ static u64 ath5k_get_tsf(struct ieee80211_hw *hw);
static void ath5k_reset_tsf(struct ieee80211_hw *hw);
static int ath5k_beacon_update(struct ieee80211_hw *hw,
struct sk_buff *skb);
+static void ath5k_bss_info_changed(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *bss_conf,
+ u32 changes);
static struct ieee80211_ops ath5k_hw_ops = {
.tx = ath5k_tx,
@@ -256,6 +260,7 @@ static struct ieee80211_ops ath5k_hw_ops = {
.get_tx_stats = ath5k_get_tx_stats,
.get_tsf = ath5k_get_tsf,
.reset_tsf = ath5k_reset_tsf,
+ .bss_info_changed = ath5k_bss_info_changed,
};
/*
@@ -2942,7 +2947,7 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw,
sc->opmode != NL80211_IFTYPE_MESH_POINT &&
test_bit(ATH_STAT_PROMISC, sc->status))
rfilt |= AR5K_RX_FILTER_PROM;
- if (sc->opmode == NL80211_IFTYPE_STATION ||
+ if ((sc->opmode == NL80211_IFTYPE_STATION && sc->assoc) ||
sc->opmode == NL80211_IFTYPE_ADHOC) {
rfilt |= AR5K_RX_FILTER_BEACON;
}
@@ -3083,4 +3088,32 @@ ath5k_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
end:
return ret;
}
+static void
+set_beacon_filter(struct ieee80211_hw *hw, bool enable)
+{
+ struct ath5k_softc *sc = hw->priv;
+ struct ath5k_hw *ah = sc->ah;
+ u32 rfilt;
+ rfilt = ath5k_hw_get_rx_filter(ah);
+ if (enable)
+ rfilt |= AR5K_RX_FILTER_BEACON;
+ else
+ rfilt &= ~AR5K_RX_FILTER_BEACON;
+ ath5k_hw_set_rx_filter(ah, rfilt);
+ sc->filter_flags = rfilt;
+}
+static void ath5k_bss_info_changed(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *bss_conf,
+ u32 changes)
+{
+ struct ath5k_softc *sc = hw->priv;
+ if (changes & BSS_CHANGED_ASSOC) {
+ mutex_lock(&sc->lock);
+ sc->assoc = bss_conf->assoc;
+ if (sc->opmode == NL80211_IFTYPE_STATION)
+ set_beacon_filter(hw, sc->assoc);
+ mutex_unlock(&sc->lock);
+ }
+}
diff --git a/drivers/net/wireless/ath5k/base.h b/drivers/net/wireless/ath5k/base.h
index 06d1054ca94..facc60ddada 100644
--- a/drivers/net/wireless/ath5k/base.h
+++ b/drivers/net/wireless/ath5k/base.h
@@ -179,6 +179,7 @@ struct ath5k_softc {
struct timer_list calib_tim; /* calibration timer */
int power_level; /* Requested tx power in dbm */
+ bool assoc; /* assocate state */
};
#define ath5k_hw_hasbssidmask(_ah) \
diff --git a/drivers/net/wireless/ath5k/debug.c b/drivers/net/wireless/ath5k/debug.c
index 19980cbd5d5..ccaeb5c219d 100644
--- a/drivers/net/wireless/ath5k/debug.c
+++ b/drivers/net/wireless/ath5k/debug.c
@@ -417,19 +417,19 @@ ath5k_debug_init_device(struct ath5k_softc *sc)
sc->debug.debugfs_phydir = debugfs_create_dir(wiphy_name(sc->hw->wiphy),
ath5k_global_debugfs);
- sc->debug.debugfs_debug = debugfs_create_file("debug", 0666,
+ sc->debug.debugfs_debug = debugfs_create_file("debug", S_IWUSR | S_IRUGO,
sc->debug.debugfs_phydir, sc, &fops_debug);
- sc->debug.debugfs_registers = debugfs_create_file("registers", 0444,
+ sc->debug.debugfs_registers = debugfs_create_file("registers", S_IRUGO,
sc->debug.debugfs_phydir, sc, &fops_registers);
- sc->debug.debugfs_tsf = debugfs_create_file("tsf", 0666,
+ sc->debug.debugfs_tsf = debugfs_create_file("tsf", S_IWUSR | S_IRUGO,
sc->debug.debugfs_phydir, sc, &fops_tsf);
- sc->debug.debugfs_beacon = debugfs_create_file("beacon", 0666,
+ sc->debug.debugfs_beacon = debugfs_create_file("beacon", S_IWUSR | S_IRUGO,
sc->debug.debugfs_phydir, sc, &fops_beacon);
- sc->debug.debugfs_reset = debugfs_create_file("reset", 0222,
+ sc->debug.debugfs_reset = debugfs_create_file("reset", S_IWUSR,
sc->debug.debugfs_phydir, sc, &fops_reset);
}
diff --git a/drivers/net/wireless/ath9k/beacon.c b/drivers/net/wireless/ath9k/beacon.c
index 9e15c30bbc0..4dd1c1bda0f 100644
--- a/drivers/net/wireless/ath9k/beacon.c
+++ b/drivers/net/wireless/ath9k/beacon.c
@@ -170,7 +170,7 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
skb = (struct sk_buff *)bf->bf_mpdu;
if (skb) {
pci_unmap_single(sc->pdev, bf->bf_dmacontext,
- skb_end_pointer(skb) - skb->head,
+ skb->len,
PCI_DMA_TODEVICE);
}
@@ -193,7 +193,7 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
bf->bf_buf_addr = bf->bf_dmacontext =
pci_map_single(sc->pdev, skb->data,
- skb_end_pointer(skb) - skb->head,
+ skb->len,
PCI_DMA_TODEVICE);
skb = ieee80211_get_buffered_bc(sc->hw, avp->av_if_data);
@@ -352,7 +352,7 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id)
if (bf->bf_mpdu != NULL) {
skb = (struct sk_buff *)bf->bf_mpdu;
pci_unmap_single(sc->pdev, bf->bf_dmacontext,
- skb_end_pointer(skb) - skb->head,
+ skb->len,
PCI_DMA_TODEVICE);
dev_kfree_skb_any(skb);
bf->bf_mpdu = NULL;
@@ -412,7 +412,7 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id)
bf->bf_buf_addr = bf->bf_dmacontext =
pci_map_single(sc->pdev, skb->data,
- skb_end_pointer(skb) - skb->head,
+ skb->len,
PCI_DMA_TODEVICE);
bf->bf_mpdu = skb;
@@ -439,7 +439,7 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp)
if (bf->bf_mpdu != NULL) {
struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu;
pci_unmap_single(sc->pdev, bf->bf_dmacontext,
- skb_end_pointer(skb) - skb->head,
+ skb->len,
PCI_DMA_TODEVICE);
dev_kfree_skb_any(skb);
bf->bf_mpdu = NULL;
diff --git a/drivers/net/wireless/ath9k/recv.c b/drivers/net/wireless/ath9k/recv.c
index 4983402af55..504a0444d89 100644
--- a/drivers/net/wireless/ath9k/recv.c
+++ b/drivers/net/wireless/ath9k/recv.c
@@ -49,10 +49,12 @@ static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf)
ASSERT(skb != NULL);
ds->ds_vdata = skb->data;
- /* setup rx descriptors */
+ /* setup rx descriptors. The sc_rxbufsize here tells the harware
+ * how much data it can DMA to us and that we are prepared
+ * to process */
ath9k_hw_setuprxdesc(ah,
ds,
- skb_tailroom(skb), /* buffer size */
+ sc->sc_rxbufsize,
0);
if (sc->sc_rxlink == NULL)
@@ -398,6 +400,13 @@ static struct sk_buff *ath_rxbuf_alloc(struct ath_softc *sc,
* in rx'd frames.
*/
+ /* Note: the kernel can allocate a value greater than
+ * what we ask it to give us. We really only need 4 KB as that
+ * is this hardware supports and in fact we need at least 3849
+ * as that is the MAX AMSDU size this hardware supports.
+ * Unfortunately this means we may get 8 KB here from the
+ * kernel... and that is actually what is observed on some
+ * systems :( */
skb = dev_alloc_skb(len + sc->sc_cachelsz - 1);
if (skb != NULL) {
off = ((unsigned long) skb->data) % sc->sc_cachelsz;
@@ -456,7 +465,7 @@ static int ath_rx_indicate(struct ath_softc *sc,
if (nskb != NULL) {
bf->bf_mpdu = nskb;
bf->bf_buf_addr = pci_map_single(sc->pdev, nskb->data,
- skb_end_pointer(nskb) - nskb->head,
+ sc->sc_rxbufsize,
PCI_DMA_FROMDEVICE);
bf->bf_dmacontext = bf->bf_buf_addr;
ATH_RX_CONTEXT(nskb)->ctx_rxbuf = bf;
@@ -542,7 +551,7 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
bf->bf_mpdu = skb;
bf->bf_buf_addr = pci_map_single(sc->pdev, skb->data,
- skb_end_pointer(skb) - skb->head,
+ sc->sc_rxbufsize,
PCI_DMA_FROMDEVICE);
bf->bf_dmacontext = bf->bf_buf_addr;
ATH_RX_CONTEXT(skb)->ctx_rxbuf = bf;
@@ -1007,7 +1016,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
pci_dma_sync_single_for_cpu(sc->pdev,
bf->bf_buf_addr,
- skb_tailroom(skb),
+ sc->sc_rxbufsize,
PCI_DMA_FROMDEVICE);
pci_unmap_single(sc->pdev,
bf->bf_buf_addr,
diff --git a/drivers/net/wireless/hostap/hostap_wlan.h b/drivers/net/wireless/hostap/hostap_wlan.h
index ffdf4876121..a68f97c3935 100644
--- a/drivers/net/wireless/hostap/hostap_wlan.h
+++ b/drivers/net/wireless/hostap/hostap_wlan.h
@@ -918,9 +918,12 @@ struct hostap_interface {
/*
* TX meta data - stored in skb->cb buffer, so this must not be increased over
- * the 40-byte limit
+ * the 48-byte limit.
+ * THE PADDING THIS STARTS WITH IS A HORRIBLE HACK THAT SHOULD NOT LIVE
+ * TO SEE THE DAY.
*/
struct hostap_skb_tx_data {
+ unsigned int __padding_for_default_qdiscs;
u32 magic; /* HOSTAP_SKB_TX_DATA_MAGIC */
u8 rate; /* transmit rate */
#define HOSTAP_TX_FLAGS_WDS BIT(0)
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
index dcce3542d5a..7a9f901d4ff 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2200.c
@@ -3897,6 +3897,7 @@ static int ipw_disassociate(void *data)
if (!(priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)))
return 0;
ipw_send_disassociate(data, 0);
+ netif_carrier_off(priv->net_dev);
return 1;
}
@@ -10190,6 +10191,9 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb,
u16 remaining_bytes;
int fc;
+ if (!(priv->status & STATUS_ASSOCIATED))
+ goto drop;
+
hdr_len = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
switch (priv->ieee->iw_mode) {
case IW_MODE_ADHOC:
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 8d690a0eb1a..c4c0371c763 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -1384,9 +1384,11 @@ void iwl_rx_handle(struct iwl_priv *priv)
rxq->queue[i] = NULL;
- pci_dma_sync_single_for_cpu(priv->pci_dev, rxb->dma_addr,
- priv->hw_params.rx_buf_size,
- PCI_DMA_FROMDEVICE);
+ dma_sync_single_range_for_cpu(
+ &priv->pci_dev->dev, rxb->real_dma_addr,
+ rxb->aligned_dma_addr - rxb->real_dma_addr,
+ priv->hw_params.rx_buf_size,
+ PCI_DMA_FROMDEVICE);
pkt = (struct iwl_rx_packet *)rxb->skb->data;
/* Reclaim a command buffer only if this packet is a response
@@ -1436,8 +1438,8 @@ void iwl_rx_handle(struct iwl_priv *priv)
rxb->skb = NULL;
}
- pci_unmap_single(priv->pci_dev, rxb->dma_addr,
- priv->hw_params.rx_buf_size,
+ pci_unmap_single(priv->pci_dev, rxb->real_dma_addr,
+ priv->hw_params.rx_buf_size + 256,
PCI_DMA_FROMDEVICE);
spin_lock_irqsave(&rxq->lock, flags);
list_add_tail(&rxb->list, &priv->rxq.rx_used);
@@ -2341,7 +2343,6 @@ static void iwl_bg_alive_start(struct work_struct *data)
mutex_lock(&priv->mutex);
iwl_alive_start(priv);
mutex_unlock(&priv->mutex);
- ieee80211_notify_mac(priv->hw, IEEE80211_NOTIFY_RE_ASSOC);
}
static void iwl4965_bg_rf_kill(struct work_struct *work)
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 4c312c55f90..01a84585133 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -290,6 +290,9 @@ void iwl_clear_stations_table(struct iwl_priv *priv)
priv->num_stations = 0;
memset(priv->stations, 0, sizeof(priv->stations));
+ /* clean ucode key table bit map */
+ priv->ucode_key_table = 0;
+
spin_unlock_irqrestore(&priv->sta_lock, flags);
}
EXPORT_SYMBOL(iwl_clear_stations_table);
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index c018121085e..9966d4e384c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -89,7 +89,8 @@ extern struct iwl_cfg iwl5100_abg_cfg;
#define DEFAULT_LONG_RETRY_LIMIT 4U
struct iwl_rx_mem_buffer {
- dma_addr_t dma_addr;
+ dma_addr_t real_dma_addr;
+ dma_addr_t aligned_dma_addr;
struct sk_buff *skb;
struct list_head list;
};
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index 7cde9d76ff5..0509c16dbe7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -204,7 +204,7 @@ int iwl_rx_queue_restock(struct iwl_priv *priv)
list_del(element);
/* Point to Rx buffer via next RBD in circular buffer */
- rxq->bd[rxq->write] = iwl_dma_addr2rbd_ptr(priv, rxb->dma_addr);
+ rxq->bd[rxq->write] = iwl_dma_addr2rbd_ptr(priv, rxb->aligned_dma_addr);
rxq->queue[rxq->write] = rxb;
rxq->write = (rxq->write + 1) & RX_QUEUE_MASK;
rxq->free_count--;
@@ -251,7 +251,7 @@ void iwl_rx_allocate(struct iwl_priv *priv)
rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
/* Alloc a new receive buffer */
- rxb->skb = alloc_skb(priv->hw_params.rx_buf_size,
+ rxb->skb = alloc_skb(priv->hw_params.rx_buf_size + 256,
__GFP_NOWARN | GFP_ATOMIC);
if (!rxb->skb) {
if (net_ratelimit())
@@ -266,9 +266,17 @@ void iwl_rx_allocate(struct iwl_priv *priv)
list_del(element);
/* Get physical address of RB/SKB */
- rxb->dma_addr =
- pci_map_single(priv->pci_dev, rxb->skb->data,
- priv->hw_params.rx_buf_size, PCI_DMA_FROMDEVICE);
+ rxb->real_dma_addr = pci_map_single(
+ priv->pci_dev,
+ rxb->skb->data,
+ priv->hw_params.rx_buf_size + 256,
+ PCI_DMA_FROMDEVICE);
+ /* dma address must be no more than 36 bits */
+ BUG_ON(rxb->real_dma_addr & ~DMA_BIT_MASK(36));
+ /* and also 256 byte aligned! */
+ rxb->aligned_dma_addr = ALIGN(rxb->real_dma_addr, 256);
+ skb_reserve(rxb->skb, rxb->aligned_dma_addr - rxb->real_dma_addr);
+
list_add_tail(&rxb->list, &rxq->rx_free);
rxq->free_count++;
}
@@ -300,8 +308,8 @@ void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {
if (rxq->pool[i].skb != NULL) {
pci_unmap_single(priv->pci_dev,
- rxq->pool[i].dma_addr,
- priv->hw_params.rx_buf_size,
+ rxq->pool[i].real_dma_addr,
+ priv->hw_params.rx_buf_size + 256,
PCI_DMA_FROMDEVICE);
dev_kfree_skb(rxq->pool[i].skb);
}
@@ -354,8 +362,8 @@ void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
* to an SKB, so we need to unmap and free potential storage */
if (rxq->pool[i].skb != NULL) {
pci_unmap_single(priv->pci_dev,
- rxq->pool[i].dma_addr,
- priv->hw_params.rx_buf_size,
+ rxq->pool[i].real_dma_addr,
+ priv->hw_params.rx_buf_size + 256,
PCI_DMA_FROMDEVICE);
priv->alloc_rxb_skb--;
dev_kfree_skb(rxq->pool[i].skb);
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index 61797f3f8d5..26f7084d301 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -475,7 +475,7 @@ static int iwl_get_free_ucode_key_index(struct iwl_priv *priv)
if (!test_and_set_bit(i, &priv->ucode_key_table))
return i;
- return -1;
+ return WEP_INVALID_OFFSET;
}
int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty)
@@ -620,6 +620,9 @@ static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv,
/* else, we are overriding an existing key => no need to allocated room
* in uCode. */
+ WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
+ "no space for new kew");
+
priv->stations[sta_id].sta.key.key_flags = key_flags;
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
@@ -637,6 +640,7 @@ static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
{
unsigned long flags;
__le16 key_flags = 0;
+ int ret;
key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK);
key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
@@ -664,14 +668,18 @@ static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
/* else, we are overriding an existing key => no need to allocated room
* in uCode. */
+ WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
+ "no space for new kew");
+
priv->stations[sta_id].sta.key.key_flags = key_flags;
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+ ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
+
spin_unlock_irqrestore(&priv->sta_lock, flags);
- IWL_DEBUG_INFO("hwcrypto: modify ucode station key info\n");
- return iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
+ return ret;
}
static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv,
@@ -696,6 +704,9 @@ static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv,
/* else, we are overriding an existing key => no need to allocated room
* in uCode. */
+ WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
+ "no space for new kew");
+
/* This copy is acutally not needed: we get the key with each TX */
memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, 16);
@@ -734,6 +745,13 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv,
return 0;
}
+ if (priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET) {
+ IWL_WARNING("Removing wrong key %d 0x%x\n",
+ keyconf->keyidx, key_flags);
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
+ return 0;
+ }
+
if (!test_and_clear_bit(priv->stations[sta_id].sta.key.key_offset,
&priv->ucode_key_table))
IWL_ERROR("index %d not used in uCode key table.\n",
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 285b53e7e26..45a6b0c3569 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -6012,7 +6012,6 @@ static void iwl3945_bg_alive_start(struct work_struct *data)
mutex_lock(&priv->mutex);
iwl3945_alive_start(priv);
mutex_unlock(&priv->mutex);
- ieee80211_notify_mac(priv->hw, IEEE80211_NOTIFY_RE_ASSOC);
}
static void iwl3945_bg_rf_kill(struct work_struct *work)
diff --git a/drivers/net/wireless/libertas_tf/if_usb.c b/drivers/net/wireless/libertas_tf/if_usb.c
index 1cc03a8dd67..59634c33b1f 100644
--- a/drivers/net/wireless/libertas_tf/if_usb.c
+++ b/drivers/net/wireless/libertas_tf/if_usb.c
@@ -331,7 +331,7 @@ static int __if_usb_submit_rx_urb(struct if_usb_card *cardp,
/* Fill the receive configuration URB and initialise the Rx call back */
usb_fill_bulk_urb(cardp->rx_urb, cardp->udev,
usb_rcvbulkpipe(cardp->udev, cardp->ep_in),
- (void *) (skb->tail),
+ skb_tail_pointer(skb),
MRVDRV_ETH_RX_PACKET_BUFFER_SIZE, callbackfn, cardp);
cardp->rx_urb->transfer_flags |= URB_ZERO_PACKET;
diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c
index 431e3c78bf2..69eb0132593 100644
--- a/drivers/net/wireless/rtl8187_dev.c
+++ b/drivers/net/wireless/rtl8187_dev.c
@@ -48,6 +48,9 @@ static struct usb_device_id rtl8187_table[] __devinitdata = {
{USB_DEVICE(0x03f0, 0xca02), .driver_info = DEVICE_RTL8187},
/* Sitecom */
{USB_DEVICE(0x0df6, 0x000d), .driver_info = DEVICE_RTL8187},
+ {USB_DEVICE(0x0df6, 0x0028), .driver_info = DEVICE_RTL8187B},
+ /* Abocom */
+ {USB_DEVICE(0x13d1, 0xabe6), .driver_info = DEVICE_RTL8187},
{}
};
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index fe1867b25ff..cac732f4047 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -615,7 +615,7 @@ static int filter_ack(struct ieee80211_hw *hw, struct ieee80211_hdr *rx_hdr,
struct ieee80211_hdr *tx_hdr;
tx_hdr = (struct ieee80211_hdr *)skb->data;
- if (likely(!compare_ether_addr(tx_hdr->addr2, rx_hdr->addr1)))
+ if (likely(!memcmp(tx_hdr->addr2, rx_hdr->addr1, ETH_ALEN)))
{
__skb_unlink(skb, q);
tx_status(hw, skb, IEEE80211_TX_STAT_ACK, stats->signal, 1);
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index c6948d8f53f..6d017adc914 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -1785,7 +1785,7 @@ static int __devexit xennet_remove(struct xenbus_device *dev)
return 0;
}
-static struct xenbus_driver netfront = {
+static struct xenbus_driver netfront_driver = {
.name = "vif",
.owner = THIS_MODULE,
.ids = netfront_ids,
@@ -1805,7 +1805,7 @@ static int __init netif_init(void)
printk(KERN_INFO "Initialising Xen virtual ethernet driver.\n");
- return xenbus_register_frontend(&netfront);
+ return xenbus_register_frontend(&netfront_driver);
}
module_init(netif_init);
@@ -1815,7 +1815,7 @@ static void __exit netif_exit(void)
if (xen_initial_domain())
return;
- xenbus_unregister_driver(&netfront);
+ xenbus_unregister_driver(&netfront_driver);
}
module_exit(netif_exit);
diff --git a/drivers/parport/Kconfig b/drivers/parport/Kconfig
index 209b4a464bc..855f389eea4 100644
--- a/drivers/parport/Kconfig
+++ b/drivers/parport/Kconfig
@@ -36,7 +36,7 @@ if PARPORT
config PARPORT_PC
tristate "PC-style hardware"
depends on (!SPARC64 || PCI) && !SPARC32 && !M32R && !FRV && \
- (!M68K || ISA) && !MN10300 && !AVR32
+ (!M68K || ISA) && !MN10300 && !AVR32 && !BLACKFIN
---help---
You should say Y here if you have a PC-style parallel port. All
IBM PC compatible computers and some Alphas have PC-style
diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c
index e2e95b36a60..101ed49a2d1 100644
--- a/drivers/parport/parport_serial.c
+++ b/drivers/parport/parport_serial.c
@@ -70,6 +70,8 @@ static int __devinit netmos_parallel_init(struct pci_dev *dev, struct parport_pc
* parallel ports and <S> is the number of serial ports.
*/
card->numports = (dev->subsystem_device & 0xf0) >> 4;
+ if (card->numports > ARRAY_SIZE(card->addr))
+ card->numports = ARRAY_SIZE(card->addr);
return 0;
}
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h
index f9e244da30a..9bcb6cbd5aa 100644
--- a/drivers/pci/hotplug/acpiphp.h
+++ b/drivers/pci/hotplug/acpiphp.h
@@ -113,7 +113,7 @@ struct acpiphp_slot {
u8 device; /* pci device# */
- u32 sun; /* ACPI _SUN (slot unique number) */
+ unsigned long long sun; /* ACPI _SUN (slot unique number) */
u32 flags; /* see below */
};
diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c
index 95b536a23d2..43c10bd261b 100644
--- a/drivers/pci/hotplug/acpiphp_core.c
+++ b/drivers/pci/hotplug/acpiphp_core.c
@@ -337,7 +337,7 @@ int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot)
slot->hotplug_slot->info->cur_bus_speed = PCI_SPEED_UNKNOWN;
acpiphp_slot->slot = slot;
- snprintf(name, SLOT_NAME_SIZE, "%u", slot->acpi_slot->sun);
+ snprintf(name, SLOT_NAME_SIZE, "%llu", slot->acpi_slot->sun);
retval = pci_hp_register(slot->hotplug_slot,
acpiphp_slot->bridge->pci_bus,
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 955aae4071f..3affc6472e6 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -255,13 +255,13 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
bridge->nr_slots++;
- dbg("found ACPI PCI Hotplug slot %d at PCI %04x:%02x:%02x\n",
+ dbg("found ACPI PCI Hotplug slot %llu at PCI %04x:%02x:%02x\n",
slot->sun, pci_domain_nr(bridge->pci_bus),
bridge->pci_bus->number, slot->device);
retval = acpiphp_register_hotplug_slot(slot);
if (retval) {
if (retval == -EBUSY)
- warn("Slot %d already registered by another "
+ warn("Slot %llu already registered by another "
"hotplug driver\n", slot->sun);
else
warn("acpiphp_register_hotplug_slot failed "
diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c
index c892daae74d..633e743442a 100644
--- a/drivers/pci/hotplug/ibmphp_core.c
+++ b/drivers/pci/hotplug/ibmphp_core.c
@@ -1402,10 +1402,6 @@ static int __init ibmphp_init(void)
goto error;
}
- /* lock ourselves into memory with a module
- * count of -1 so that no one can unload us. */
- module_put(THIS_MODULE);
-
exit:
return rc;
@@ -1423,4 +1419,3 @@ static void __exit ibmphp_exit(void)
}
module_init(ibmphp_init);
-module_exit(ibmphp_exit);
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index 4b23bc39b11..39cf248d24e 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -432,18 +432,19 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
goto err_out_release_ctlr;
}
+ /* Check if slot is occupied */
t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset);
-
- t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */
- if (value && pciehp_force) {
- rc = pciehp_enable_slot(t_slot);
- if (rc) /* -ENODEV: shouldn't happen, but deal with it */
- value = 0;
- }
- if ((POWER_CTRL(ctrl)) && !value) {
- rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/
- if (rc)
- goto err_out_free_ctrl_slot;
+ t_slot->hpc_ops->get_adapter_status(t_slot, &value);
+ if (value) {
+ if (pciehp_force)
+ pciehp_enable_slot(t_slot);
+ } else {
+ /* Power off slot if not occupied */
+ if (POWER_CTRL(ctrl)) {
+ rc = t_slot->hpc_ops->power_off_slot(t_slot);
+ if (rc)
+ goto err_out_free_ctrl_slot;
+ }
}
return 0;
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c
index a2692724b68..5c8baa43ac9 100644
--- a/drivers/pci/intel-iommu.c
+++ b/drivers/pci/intel-iommu.c
@@ -1655,12 +1655,14 @@ int __init init_dmars(void)
iommu->flush.flush_context = __iommu_flush_context;
iommu->flush.flush_iotlb = __iommu_flush_iotlb;
printk(KERN_INFO "IOMMU 0x%Lx: using Register based "
- "invalidation\n", drhd->reg_base_addr);
+ "invalidation\n",
+ (unsigned long long)drhd->reg_base_addr);
} else {
iommu->flush.flush_context = qi_flush_context;
iommu->flush.flush_iotlb = qi_flush_iotlb;
printk(KERN_INFO "IOMMU 0x%Lx: using Queued "
- "invalidation\n", drhd->reg_base_addr);
+ "invalidation\n",
+ (unsigned long long)drhd->reg_base_addr);
}
}
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index b3a63edb690..ae5ec76dca7 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -63,7 +63,7 @@ static acpi_status acpi_run_osc(acpi_handle handle,
union acpi_object in_params[4];
struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
union acpi_object *out_obj;
- u32 osc_dw0, flags = osc_args->capbuf[OSC_QUERY_TYPE];
+ u32 errors, flags = osc_args->capbuf[OSC_QUERY_TYPE];
/* Setting up input parameters */
input.count = 4;
@@ -92,15 +92,16 @@ static acpi_status acpi_run_osc(acpi_handle handle,
status = AE_TYPE;
goto out_kfree;
}
- osc_dw0 = *((u32 *)out_obj->buffer.pointer);
- if (osc_dw0) {
- if (osc_dw0 & OSC_REQUEST_ERROR)
+ /* Need to ignore the bit0 in result code */
+ errors = *((u32 *)out_obj->buffer.pointer) & ~(1 << 0);
+ if (errors) {
+ if (errors & OSC_REQUEST_ERROR)
printk(KERN_DEBUG "_OSC request fails\n");
- if (osc_dw0 & OSC_INVALID_UUID_ERROR)
+ if (errors & OSC_INVALID_UUID_ERROR)
printk(KERN_DEBUG "_OSC invalid UUID\n");
- if (osc_dw0 & OSC_INVALID_REVISION_ERROR)
+ if (errors & OSC_INVALID_REVISION_ERROR)
printk(KERN_DEBUG "_OSC invalid revision\n");
- if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) {
+ if (errors & OSC_CAPABILITIES_MASK_ERROR) {
if (flags & OSC_QUERY_ENABLE)
goto out_success;
printk(KERN_DEBUG "_OSC FW not grant req. control\n");
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 21f2ac639ca..061d1ee0046 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -1832,7 +1832,7 @@ int pci_reset_function(struct pci_dev *dev)
if (!(cap & PCI_EXP_DEVCAP_FLR))
return -ENOTTY;
- if (!dev->msi_enabled && !dev->msix_enabled)
+ if (!dev->msi_enabled && !dev->msix_enabled && dev->irq != 0)
disable_irq(dev->irq);
pci_save_state(dev);
@@ -1841,7 +1841,7 @@ int pci_reset_function(struct pci_dev *dev)
r = pci_execute_reset_function(dev);
pci_restore_state(dev);
- if (!dev->msi_enabled && !dev->msix_enabled)
+ if (!dev->msi_enabled && !dev->msix_enabled && dev->irq != 0)
enable_irq(dev->irq);
return r;
@@ -2042,7 +2042,7 @@ static int __devinit pci_init(void)
return 0;
}
-static int __devinit pci_setup(char *str)
+static int __init pci_setup(char *str)
{
while (str) {
char *k = strchr(str, ',');
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c
index dfc63d01f20..aac7006949f 100644
--- a/drivers/pci/pcie/aer/aerdrv_core.c
+++ b/drivers/pci/pcie/aer/aerdrv_core.c
@@ -252,7 +252,7 @@ static void report_resume(struct pci_dev *dev, void *data)
if (!dev->driver ||
!dev->driver->err_handler ||
- !dev->driver->err_handler->slot_reset)
+ !dev->driver->err_handler->resume)
return;
err_handler = dev->driver->err_handler;
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
index 8f63f4c6b85..9aad608bcf3 100644
--- a/drivers/pci/pcie/aspm.c
+++ b/drivers/pci/pcie/aspm.c
@@ -16,6 +16,7 @@
#include <linux/pm.h>
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/jiffies.h>
#include <linux/pci-aspm.h>
#include "../pci.h"
@@ -161,11 +162,12 @@ static void pcie_check_clock_pm(struct pci_dev *pdev)
*/
static void pcie_aspm_configure_common_clock(struct pci_dev *pdev)
{
- int pos, child_pos;
+ int pos, child_pos, i = 0;
u16 reg16 = 0;
struct pci_dev *child_dev;
int same_clock = 1;
-
+ unsigned long start_jiffies;
+ u16 child_regs[8], parent_reg;
/*
* all functions of a slot should have the same Slot Clock
* Configuration, so just check one function
@@ -191,16 +193,19 @@ static void pcie_aspm_configure_common_clock(struct pci_dev *pdev)
child_pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
pci_read_config_word(child_dev, child_pos + PCI_EXP_LNKCTL,
&reg16);
+ child_regs[i] = reg16;
if (same_clock)
reg16 |= PCI_EXP_LNKCTL_CCC;
else
reg16 &= ~PCI_EXP_LNKCTL_CCC;
pci_write_config_word(child_dev, child_pos + PCI_EXP_LNKCTL,
reg16);
+ i++;
}
/* Configure upstream component */
pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &reg16);
+ parent_reg = reg16;
if (same_clock)
reg16 |= PCI_EXP_LNKCTL_CCC;
else
@@ -212,12 +217,30 @@ static void pcie_aspm_configure_common_clock(struct pci_dev *pdev)
pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16);
/* Wait for link training end */
- while (1) {
+ /* break out after waiting for 1 second */
+ start_jiffies = jiffies;
+ while ((jiffies - start_jiffies) < HZ) {
pci_read_config_word(pdev, pos + PCI_EXP_LNKSTA, &reg16);
if (!(reg16 & PCI_EXP_LNKSTA_LT))
break;
cpu_relax();
}
+ /* training failed -> recover */
+ if ((jiffies - start_jiffies) >= HZ) {
+ dev_printk (KERN_ERR, &pdev->dev, "ASPM: Could not configure"
+ " common clock\n");
+ i = 0;
+ list_for_each_entry(child_dev, &pdev->subordinate->devices,
+ bus_list) {
+ child_pos = pci_find_capability(child_dev,
+ PCI_CAP_ID_EXP);
+ pci_write_config_word(child_dev,
+ child_pos + PCI_EXP_LNKCTL,
+ child_regs[i]);
+ i++;
+ }
+ pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, parent_reg);
+ }
}
/*
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 5049a47030a..5f4f85f56cb 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -22,6 +22,7 @@
#include <linux/delay.h>
#include <linux/acpi.h>
#include <linux/kallsyms.h>
+#include <linux/dmi.h>
#include "pci.h"
int isa_dma_bridge_buggy;
@@ -1828,6 +1829,22 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SERVERWORKS,
PCI_DEVICE_ID_SERVERWORKS_HT1000_PXB,
ht_enable_msi_mapping);
+/* The P5N32-SLI Premium motherboard from Asus has a problem with msi
+ * for the MCP55 NIC. It is not yet determined whether the msi problem
+ * also affects other devices. As for now, turn off msi for this device.
+ */
+static void __devinit nvenet_msi_disable(struct pci_dev *dev)
+{
+ if (dmi_name_in_vendors("P5N32-SLI PREMIUM")) {
+ dev_info(&dev->dev,
+ "Disabling msi for MCP55 NIC on P5N32-SLI Premium\n");
+ dev->no_msi = 1;
+ }
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA,
+ PCI_DEVICE_ID_NVIDIA_NVENET_15,
+ nvenet_msi_disable);
+
static void __devinit nv_msi_ht_cap_quirk(struct pci_dev *dev)
{
struct pci_dev *host_bridge;
diff --git a/drivers/pci/slot.c b/drivers/pci/slot.c
index 4dd1c3e157a..5a8ccb4f604 100644
--- a/drivers/pci/slot.c
+++ b/drivers/pci/slot.c
@@ -253,6 +253,7 @@ placeholder:
__func__, pci_domain_nr(parent), parent->number, slot_nr);
out:
+ kfree(slot_name);
up_write(&pci_bus_sem);
return slot;
err:
diff --git a/drivers/pcmcia/bfin_cf_pcmcia.c b/drivers/pcmcia/bfin_cf_pcmcia.c
index bb7338863fb..b59d4115d20 100644
--- a/drivers/pcmcia/bfin_cf_pcmcia.c
+++ b/drivers/pcmcia/bfin_cf_pcmcia.c
@@ -334,6 +334,6 @@ static void __exit bfin_cf_exit(void)
module_init(bfin_cf_init);
module_exit(bfin_cf_exit);
-MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>")
+MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
MODULE_DESCRIPTION("BFIN CF/PCMCIA Driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c
index dcce9f5d846..4a110b7b267 100644
--- a/drivers/pcmcia/cistpl.c
+++ b/drivers/pcmcia/cistpl.c
@@ -351,10 +351,11 @@ int verify_cis_cache(struct pcmcia_socket *s)
char *buf;
buf = kmalloc(256, GFP_KERNEL);
- if (buf == NULL)
+ if (buf == NULL) {
dev_printk(KERN_WARNING, &s->dev,
"no memory for verifying CIS\n");
return -ENOMEM;
+ }
list_for_each_entry(cis, &s->cis_cache, node) {
int len = cis->len;
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index c68c5d33828..0660ad18258 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -186,12 +186,6 @@ int pcmcia_register_socket(struct pcmcia_socket *socket)
spin_lock_init(&socket->lock);
- if (socket->resource_ops->init) {
- ret = socket->resource_ops->init(socket);
- if (ret)
- return (ret);
- }
-
/* try to obtain a socket number [yes, it gets ugly if we
* register more than 2^sizeof(unsigned int) pcmcia
* sockets... but the socket number is deprecated
@@ -226,7 +220,7 @@ int pcmcia_register_socket(struct pcmcia_socket *socket)
/* set proper values in socket->dev */
dev_set_drvdata(&socket->dev, socket);
socket->dev.class = &pcmcia_socket_class;
- snprintf(socket->dev.bus_id, BUS_ID_SIZE, "pcmcia_socket%u", socket->sock);
+ dev_set_name(&socket->dev, "pcmcia_socket%u", socket->sock);
/* base address = 0, map = 0 */
socket->cis_mem.flags = 0;
@@ -239,6 +233,12 @@ int pcmcia_register_socket(struct pcmcia_socket *socket)
mutex_init(&socket->skt_mutex);
spin_lock_init(&socket->thread_lock);
+ if (socket->resource_ops->init) {
+ ret = socket->resource_ops->init(socket);
+ if (ret)
+ goto err;
+ }
+
tsk = kthread_run(pccardd, socket, "pccardd");
if (IS_ERR(tsk)) {
ret = PTR_ERR(tsk);
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 79566025549..47cab31ff6e 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -622,7 +622,6 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f
{
struct pcmcia_device *p_dev, *tmp_dev;
unsigned long flags;
- int bus_id_len;
s = pcmcia_get_socket(s);
if (!s)
@@ -650,12 +649,12 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f
/* by default don't allow DMA */
p_dev->dma_mask = DMA_MASK_NONE;
p_dev->dev.dma_mask = &p_dev->dma_mask;
- bus_id_len = sprintf (p_dev->dev.bus_id, "%d.%d", p_dev->socket->sock, p_dev->device_no);
-
- p_dev->devname = kmalloc(6 + bus_id_len + 1, GFP_KERNEL);
+ dev_set_name(&p_dev->dev, "%d.%d", p_dev->socket->sock, p_dev->device_no);
+ if (!dev_name(&p_dev->dev))
+ goto err_free;
+ p_dev->devname = kasprintf(GFP_KERNEL, "pcmcia%s", dev_name(&p_dev->dev));
if (!p_dev->devname)
goto err_free;
- sprintf (p_dev->devname, "pcmcia%s", p_dev->dev.bus_id);
ds_dev_dbg(3, &p_dev->dev, "devname is %s\n", p_dev->devname);
spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
@@ -668,6 +667,8 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f
list_for_each_entry(tmp_dev, &s->devices_list, socket_device_list)
if (p_dev->func == tmp_dev->func) {
p_dev->function_config = tmp_dev->function_config;
+ p_dev->io = tmp_dev->io;
+ p_dev->irq = tmp_dev->irq;
kref_get(&p_dev->function_config->ref);
}
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c
index 76d4a98f095..f5d0ba8e22d 100644
--- a/drivers/pcmcia/pcmcia_resource.c
+++ b/drivers/pcmcia/pcmcia_resource.c
@@ -302,9 +302,10 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
/* We only allow changing Vpp1 and Vpp2 to the same value */
if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) &&
(mod->Attributes & CONF_VPP2_CHANGE_VALID)) {
- if (mod->Vpp1 != mod->Vpp2)
+ if (mod->Vpp1 != mod->Vpp2) {
ds_dbg(s, 0, "Vpp1 and Vpp2 must be the same\n");
return -EINVAL;
+ }
s->socket.Vpp = mod->Vpp1;
if (s->ops->set_socket(s, &s->socket)) {
dev_printk(KERN_WARNING, &s->dev,
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c
index 17f4ecf1c0c..9ca22c7aafb 100644
--- a/drivers/pcmcia/rsrc_nonstatic.c
+++ b/drivers/pcmcia/rsrc_nonstatic.c
@@ -71,7 +71,7 @@ static DEFINE_MUTEX(rsrc_mutex);
======================================================================*/
static struct resource *
-make_resource(resource_size_t b, resource_size_t n, int flags, char *name)
+make_resource(resource_size_t b, resource_size_t n, int flags, const char *name)
{
struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL);
@@ -624,7 +624,7 @@ static int nonstatic_adjust_io_region(struct resource *res, unsigned long r_star
static struct resource *nonstatic_find_io_region(unsigned long base, int num,
unsigned long align, struct pcmcia_socket *s)
{
- struct resource *res = make_resource(0, num, IORESOURCE_IO, s->dev.bus_id);
+ struct resource *res = make_resource(0, num, IORESOURCE_IO, dev_name(&s->dev));
struct socket_data *s_data = s->resource_data;
struct pcmcia_align_data data;
unsigned long min = base;
@@ -658,7 +658,7 @@ static struct resource *nonstatic_find_io_region(unsigned long base, int num,
static struct resource * nonstatic_find_mem_region(u_long base, u_long num,
u_long align, int low, struct pcmcia_socket *s)
{
- struct resource *res = make_resource(0, num, IORESOURCE_MEM, s->dev.bus_id);
+ struct resource *res = make_resource(0, num, IORESOURCE_MEM, dev_name(&s->dev));
struct socket_data *s_data = s->resource_data;
struct pcmcia_align_data data;
unsigned long min, max;
diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c
index a926c896475..643a6b98462 100644
--- a/drivers/rapidio/rio-scan.c
+++ b/drivers/rapidio/rio-scan.c
@@ -879,7 +879,7 @@ static void rio_update_route_tables(struct rio_mport *port)
* link, then start recursive peer enumeration. Returns %0 if
* enumeration succeeds or %-EBUSY if enumeration fails.
*/
-int rio_enum_mport(struct rio_mport *mport)
+int __devinit rio_enum_mport(struct rio_mport *mport)
{
struct rio_net *net = NULL;
int rc = 0;
@@ -972,7 +972,7 @@ static void rio_enum_timeout(unsigned long data)
* peer discovery. Returns %0 if discovery succeeds or %-EBUSY
* on failure.
*/
-int rio_disc_mport(struct rio_mport *mport)
+int __devinit rio_disc_mport(struct rio_mport *mport)
{
struct rio_net *net = NULL;
int enum_timeout_flag = 0;
diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c
index 680661abbc4..6395c780008 100644
--- a/drivers/rapidio/rio.c
+++ b/drivers/rapidio/rio.c
@@ -467,7 +467,7 @@ static int __devinit rio_init(void)
device_initcall(rio_init);
-int rio_init_mports(void)
+int __devinit rio_init_mports(void)
{
int rc = 0;
struct rio_mport *port;
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 8abbb2020af..123092d8a98 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -277,6 +277,14 @@ config RTC_DRV_FM3130
This driver can also be built as a module. If so the module
will be called rtc-fm3130.
+config RTC_DRV_RX8581
+ tristate "Epson RX-8581"
+ help
+ If you say yes here you will get support for the Epson RX-8581.
+
+ This driver can also be built as a module. If so the module
+ will be called rtc-rx8581.
+
endif # I2C
comment "SPI RTC drivers"
@@ -302,6 +310,17 @@ config RTC_DRV_DS1305
This driver can also be built as a module. If so, the module
will be called rtc-ds1305.
+config RTC_DRV_DS1390
+ tristate "Dallas/Maxim DS1390/93/94"
+ help
+ If you say yes here you get support for the DS1390/93/94 chips.
+
+ This driver only supports the RTC feature, and not other chip
+ features such as alarms and trickle charging.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-ds1390.
+
config RTC_DRV_MAX6902
tristate "Maxim MAX6902"
help
@@ -468,6 +487,16 @@ config RTC_DRV_V3020
This driver can also be built as a module. If so, the module
will be called rtc-v3020.
+config RTC_DRV_WM8350
+ tristate "Wolfson Microelectronics WM8350 RTC"
+ depends on MFD_WM8350
+ help
+ If you say yes here you will get support for the RTC subsystem
+ of the Wolfson Microelectronics WM8350.
+
+ This driver can also be built as a module. If so, the module
+ will be called "rtc-wm8350".
+
comment "on-CPU RTC drivers"
config RTC_DRV_OMAP
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index e9e8474cc8f..6e79c912bf9 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_RTC_DRV_DS1302) += rtc-ds1302.o
obj-$(CONFIG_RTC_DRV_DS1305) += rtc-ds1305.o
obj-$(CONFIG_RTC_DRV_DS1307) += rtc-ds1307.o
obj-$(CONFIG_RTC_DRV_DS1374) += rtc-ds1374.o
+obj-$(CONFIG_RTC_DRV_DS1390) += rtc-ds1390.o
obj-$(CONFIG_RTC_DRV_DS1511) += rtc-ds1511.o
obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o
obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o
@@ -57,6 +58,7 @@ obj-$(CONFIG_RTC_DRV_R9701) += rtc-r9701.o
obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o
obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o
obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o
+obj-$(CONFIG_RTC_DRV_RX8581) += rtc-rx8581.o
obj-$(CONFIG_RTC_DRV_S35390A) += rtc-s35390a.o
obj-$(CONFIG_RTC_DRV_S3C) += rtc-s3c.o
obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o
@@ -66,4 +68,5 @@ obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o
obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl4030.o
obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o
obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o
+obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o
obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o
diff --git a/drivers/rtc/rtc-ds1390.c b/drivers/rtc/rtc-ds1390.c
new file mode 100644
index 00000000000..599e976bf01
--- /dev/null
+++ b/drivers/rtc/rtc-ds1390.c
@@ -0,0 +1,220 @@
+/*
+ * rtc-ds1390.c -- driver for DS1390/93/94
+ *
+ * Copyright (C) 2008 Mercury IMC Ltd
+ * Written by Mark Jackson <mpfj@mimc.co.uk>
+ *
+ * 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.
+ *
+ * NOTE : Currently this driver only supports the bare minimum for read
+ * and write the RTC. The extra features provided by the chip family
+ * (alarms, trickle charger, different control registers) are unavailable.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+#include <linux/spi/spi.h>
+#include <linux/bcd.h>
+
+#define DS1390_REG_100THS 0x00
+#define DS1390_REG_SECONDS 0x01
+#define DS1390_REG_MINUTES 0x02
+#define DS1390_REG_HOURS 0x03
+#define DS1390_REG_DAY 0x04
+#define DS1390_REG_DATE 0x05
+#define DS1390_REG_MONTH_CENT 0x06
+#define DS1390_REG_YEAR 0x07
+
+#define DS1390_REG_ALARM_100THS 0x08
+#define DS1390_REG_ALARM_SECONDS 0x09
+#define DS1390_REG_ALARM_MINUTES 0x0A
+#define DS1390_REG_ALARM_HOURS 0x0B
+#define DS1390_REG_ALARM_DAY_DATE 0x0C
+
+#define DS1390_REG_CONTROL 0x0D
+#define DS1390_REG_STATUS 0x0E
+#define DS1390_REG_TRICKLE 0x0F
+
+struct ds1390 {
+ struct rtc_device *rtc;
+ u8 txrx_buf[9]; /* cmd + 8 registers */
+};
+
+static void ds1390_set_reg(struct device *dev, unsigned char address,
+ unsigned char data)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct ds1390 *chip = dev_get_drvdata(dev);
+
+ /* Set MSB to indicate write */
+ chip->txrx_buf[0] = address | 0x80;
+ chip->txrx_buf[1] = data;
+
+ /* do the i/o */
+ spi_write_then_read(spi, chip->txrx_buf, 2, NULL, 0);
+}
+
+static int ds1390_get_reg(struct device *dev, unsigned char address,
+ unsigned char *data)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct ds1390 *chip = dev_get_drvdata(dev);
+ int status;
+
+ if (!data)
+ return -EINVAL;
+
+ /* Clear MSB to indicate read */
+ chip->txrx_buf[0] = address & 0x7f;
+ /* do the i/o */
+ status = spi_write_then_read(spi, chip->txrx_buf, 1, chip->txrx_buf, 1);
+ if (status != 0)
+ return status;
+
+ *data = chip->txrx_buf[1];
+
+ return 0;
+}
+
+static int ds1390_get_datetime(struct device *dev, struct rtc_time *dt)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct ds1390 *chip = dev_get_drvdata(dev);
+ int status;
+
+ /* build the message */
+ chip->txrx_buf[0] = DS1390_REG_SECONDS;
+
+ /* do the i/o */
+ status = spi_write_then_read(spi, chip->txrx_buf, 1, chip->txrx_buf, 8);
+ if (status != 0)
+ return status;
+
+ /* The chip sends data in this order:
+ * Seconds, Minutes, Hours, Day, Date, Month / Century, Year */
+ dt->tm_sec = bcd2bin(chip->txrx_buf[0]);
+ dt->tm_min = bcd2bin(chip->txrx_buf[1]);
+ dt->tm_hour = bcd2bin(chip->txrx_buf[2]);
+ dt->tm_wday = bcd2bin(chip->txrx_buf[3]);
+ dt->tm_mday = bcd2bin(chip->txrx_buf[4]);
+ /* mask off century bit */
+ dt->tm_mon = bcd2bin(chip->txrx_buf[5] & 0x7f) - 1;
+ /* adjust for century bit */
+ dt->tm_year = bcd2bin(chip->txrx_buf[6]) + ((chip->txrx_buf[5] & 0x80) ? 100 : 0);
+
+ return rtc_valid_tm(dt);
+}
+
+static int ds1390_set_datetime(struct device *dev, struct rtc_time *dt)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct ds1390 *chip = dev_get_drvdata(dev);
+
+ /* build the message */
+ chip->txrx_buf[0] = DS1390_REG_SECONDS | 0x80;
+ chip->txrx_buf[1] = bin2bcd(dt->tm_sec);
+ chip->txrx_buf[2] = bin2bcd(dt->tm_min);
+ chip->txrx_buf[3] = bin2bcd(dt->tm_hour);
+ chip->txrx_buf[4] = bin2bcd(dt->tm_wday);
+ chip->txrx_buf[5] = bin2bcd(dt->tm_mday);
+ chip->txrx_buf[6] = bin2bcd(dt->tm_mon + 1) |
+ ((dt->tm_year > 99) ? 0x80 : 0x00);
+ chip->txrx_buf[7] = bin2bcd(dt->tm_year % 100);
+
+ /* do the i/o */
+ return spi_write_then_read(spi, chip->txrx_buf, 8, NULL, 0);
+}
+
+static int ds1390_read_time(struct device *dev, struct rtc_time *tm)
+{
+ return ds1390_get_datetime(dev, tm);
+}
+
+static int ds1390_set_time(struct device *dev, struct rtc_time *tm)
+{
+ return ds1390_set_datetime(dev, tm);
+}
+
+static const struct rtc_class_ops ds1390_rtc_ops = {
+ .read_time = ds1390_read_time,
+ .set_time = ds1390_set_time,
+};
+
+static int __devinit ds1390_probe(struct spi_device *spi)
+{
+ struct rtc_device *rtc;
+ unsigned char tmp;
+ struct ds1390 *chip;
+ int res;
+
+ printk(KERN_DEBUG "DS1390 SPI RTC driver\n");
+
+ rtc = rtc_device_register("ds1390",
+ &spi->dev, &ds1390_rtc_ops, THIS_MODULE);
+ if (IS_ERR(rtc)) {
+ printk(KERN_ALERT "RTC : unable to register device\n");
+ return PTR_ERR(rtc);
+ }
+
+ spi->mode = SPI_MODE_3;
+ spi->bits_per_word = 8;
+ spi_setup(spi);
+
+ chip = kzalloc(sizeof *chip, GFP_KERNEL);
+ if (!chip) {
+ printk(KERN_ALERT "RTC : unable to allocate device memory\n");
+ rtc_device_unregister(rtc);
+ return -ENOMEM;
+ }
+ chip->rtc = rtc;
+ dev_set_drvdata(&spi->dev, chip);
+
+ res = ds1390_get_reg(&spi->dev, DS1390_REG_SECONDS, &tmp);
+ if (res) {
+ printk(KERN_ALERT "RTC : unable to read device\n");
+ rtc_device_unregister(rtc);
+ return res;
+ }
+
+ return 0;
+}
+
+static int __devexit ds1390_remove(struct spi_device *spi)
+{
+ struct ds1390 *chip = platform_get_drvdata(spi);
+ struct rtc_device *rtc = chip->rtc;
+
+ if (rtc)
+ rtc_device_unregister(rtc);
+
+ kfree(chip);
+
+ return 0;
+}
+
+static struct spi_driver ds1390_driver = {
+ .driver = {
+ .name = "rtc-ds1390",
+ .owner = THIS_MODULE,
+ },
+ .probe = ds1390_probe,
+ .remove = __devexit_p(ds1390_remove),
+};
+
+static __init int ds1390_init(void)
+{
+ return spi_register_driver(&ds1390_driver);
+}
+module_init(ds1390_init);
+
+static __exit void ds1390_exit(void)
+{
+ spi_unregister_driver(&ds1390_driver);
+}
+module_exit(ds1390_exit);
+
+MODULE_DESCRIPTION("DS1390/93/94 SPI RTC driver");
+MODULE_AUTHOR("Mark Jackson <mpfj@mimc.co.uk>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-ds1672.c b/drivers/rtc/rtc-ds1672.c
index 341d7a5b45a..4e91419e891 100644
--- a/drivers/rtc/rtc-ds1672.c
+++ b/drivers/rtc/rtc-ds1672.c
@@ -209,12 +209,18 @@ static int ds1672_probe(struct i2c_client *client,
return err;
}
+static struct i2c_device_id ds1672_id[] = {
+ { "ds1672", 0 },
+ { }
+};
+
static struct i2c_driver ds1672_driver = {
.driver = {
.name = "rtc-ds1672",
},
.probe = &ds1672_probe,
.remove = &ds1672_remove,
+ .id_table = ds1672_id,
};
static int __init ds1672_init(void)
diff --git a/drivers/rtc/rtc-isl1208.c b/drivers/rtc/rtc-isl1208.c
index 2cd77ab8fc6..054e05294af 100644
--- a/drivers/rtc/rtc-isl1208.c
+++ b/drivers/rtc/rtc-isl1208.c
@@ -328,6 +328,13 @@ isl1208_i2c_set_time(struct i2c_client *client, struct rtc_time const *tm)
int sr;
u8 regs[ISL1208_RTC_SECTION_LEN] = { 0, };
+ /* The clock has an 8 bit wide bcd-coded register (they never learn)
+ * for the year. tm_year is an offset from 1900 and we are interested
+ * in the 2000-2099 range, so any value less than 100 is invalid.
+ */
+ if (tm->tm_year < 100)
+ return -EINVAL;
+
regs[ISL1208_REG_SC] = bin2bcd(tm->tm_sec);
regs[ISL1208_REG_MN] = bin2bcd(tm->tm_min);
regs[ISL1208_REG_HR] = bin2bcd(tm->tm_hour) | ISL1208_REG_HR_MIL;
diff --git a/drivers/rtc/rtc-max6900.c b/drivers/rtc/rtc-max6900.c
index 80782798763..a4f6665ab3c 100644
--- a/drivers/rtc/rtc-max6900.c
+++ b/drivers/rtc/rtc-max6900.c
@@ -247,12 +247,18 @@ max6900_probe(struct i2c_client *client, const struct i2c_device_id *id)
return 0;
}
+static struct i2c_device_id max6900_id[] = {
+ { "max6900", 0 },
+ { }
+};
+
static struct i2c_driver max6900_driver = {
.driver = {
.name = "rtc-max6900",
},
.probe = max6900_probe,
.remove = max6900_remove,
+ .id_table = max6900_id,
};
static int __init max6900_init(void)
diff --git a/drivers/rtc/rtc-rx8581.c b/drivers/rtc/rtc-rx8581.c
new file mode 100644
index 00000000000..c9522f3bc21
--- /dev/null
+++ b/drivers/rtc/rtc-rx8581.c
@@ -0,0 +1,281 @@
+/*
+ * An I2C driver for the Epson RX8581 RTC
+ *
+ * Author: Martyn Welch <martyn.welch@gefanuc.com>
+ * Copyright 2008 GE Fanuc Intelligent Platforms Embedded Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Based on: rtc-pcf8563.c (An I2C driver for the Philips PCF8563 RTC)
+ * Copyright 2005-06 Tower Technologies
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/bcd.h>
+#include <linux/rtc.h>
+#include <linux/log2.h>
+
+#define DRV_VERSION "0.1"
+
+#define RX8581_REG_SC 0x00 /* Second in BCD */
+#define RX8581_REG_MN 0x01 /* Minute in BCD */
+#define RX8581_REG_HR 0x02 /* Hour in BCD */
+#define RX8581_REG_DW 0x03 /* Day of Week */
+#define RX8581_REG_DM 0x04 /* Day of Month in BCD */
+#define RX8581_REG_MO 0x05 /* Month in BCD */
+#define RX8581_REG_YR 0x06 /* Year in BCD */
+#define RX8581_REG_RAM 0x07 /* RAM */
+#define RX8581_REG_AMN 0x08 /* Alarm Min in BCD*/
+#define RX8581_REG_AHR 0x09 /* Alarm Hour in BCD */
+#define RX8581_REG_ADM 0x0A
+#define RX8581_REG_ADW 0x0A
+#define RX8581_REG_TMR0 0x0B
+#define RX8581_REG_TMR1 0x0C
+#define RX8581_REG_EXT 0x0D /* Extension Register */
+#define RX8581_REG_FLAG 0x0E /* Flag Register */
+#define RX8581_REG_CTRL 0x0F /* Control Register */
+
+
+/* Flag Register bit definitions */
+#define RX8581_FLAG_UF 0x20 /* Update */
+#define RX8581_FLAG_TF 0x10 /* Timer */
+#define RX8581_FLAG_AF 0x08 /* Alarm */
+#define RX8581_FLAG_VLF 0x02 /* Voltage Low */
+
+/* Control Register bit definitions */
+#define RX8581_CTRL_UIE 0x20 /* Update Interrupt Enable */
+#define RX8581_CTRL_TIE 0x10 /* Timer Interrupt Enable */
+#define RX8581_CTRL_AIE 0x08 /* Alarm Interrupt Enable */
+#define RX8581_CTRL_STOP 0x02 /* STOP bit */
+#define RX8581_CTRL_RESET 0x01 /* RESET bit */
+
+static struct i2c_driver rx8581_driver;
+
+/*
+ * In the routines that deal directly with the rx8581 hardware, we use
+ * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch.
+ */
+static int rx8581_get_datetime(struct i2c_client *client, struct rtc_time *tm)
+{
+ unsigned char date[7];
+ int data, err;
+
+ /* First we ensure that the "update flag" is not set, we read the
+ * time and date then re-read the "update flag". If the update flag
+ * has been set, we know that the time has changed during the read so
+ * we repeat the whole process again.
+ */
+ data = i2c_smbus_read_byte_data(client, RX8581_REG_FLAG);
+ if (data < 0) {
+ dev_err(&client->dev, "Unable to read device flags\n");
+ return -EIO;
+ }
+
+ do {
+ /* If update flag set, clear it */
+ if (data & RX8581_FLAG_UF) {
+ err = i2c_smbus_write_byte_data(client,
+ RX8581_REG_FLAG, (data & ~RX8581_FLAG_UF));
+ if (err != 0) {
+ dev_err(&client->dev, "Unable to write device "
+ "flags\n");
+ return -EIO;
+ }
+ }
+
+ /* Now read time and date */
+ err = i2c_smbus_read_i2c_block_data(client, RX8581_REG_SC,
+ 7, date);
+ if (err < 0) {
+ dev_err(&client->dev, "Unable to read date\n");
+ return -EIO;
+ }
+
+ /* Check flag register */
+ data = i2c_smbus_read_byte_data(client, RX8581_REG_FLAG);
+ if (data < 0) {
+ dev_err(&client->dev, "Unable to read device flags\n");
+ return -EIO;
+ }
+ } while (data & RX8581_FLAG_UF);
+
+ if (data & RX8581_FLAG_VLF)
+ dev_info(&client->dev,
+ "low voltage detected, date/time is not reliable.\n");
+
+ dev_dbg(&client->dev,
+ "%s: raw data is sec=%02x, min=%02x, hr=%02x, "
+ "wday=%02x, mday=%02x, mon=%02x, year=%02x\n",
+ __func__,
+ date[0], date[1], date[2], date[3], date[4], date[5], date[6]);
+
+ tm->tm_sec = bcd2bin(date[RX8581_REG_SC] & 0x7F);
+ tm->tm_min = bcd2bin(date[RX8581_REG_MN] & 0x7F);
+ tm->tm_hour = bcd2bin(date[RX8581_REG_HR] & 0x3F); /* rtc hr 0-23 */
+ tm->tm_wday = ilog2(date[RX8581_REG_DW] & 0x7F);
+ tm->tm_mday = bcd2bin(date[RX8581_REG_DM] & 0x3F);
+ tm->tm_mon = bcd2bin(date[RX8581_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */
+ tm->tm_year = bcd2bin(date[RX8581_REG_YR]);
+ if (tm->tm_year < 70)
+ tm->tm_year += 100; /* assume we are in 1970...2069 */
+
+
+ dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
+ "mday=%d, mon=%d, year=%d, wday=%d\n",
+ __func__,
+ tm->tm_sec, tm->tm_min, tm->tm_hour,
+ tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
+
+ err = rtc_valid_tm(tm);
+ if (err < 0)
+ dev_err(&client->dev, "retrieved date/time is not valid.\n");
+
+ return err;
+}
+
+static int rx8581_set_datetime(struct i2c_client *client, struct rtc_time *tm)
+{
+ int data, err;
+ unsigned char buf[7];
+
+ dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, "
+ "mday=%d, mon=%d, year=%d, wday=%d\n",
+ __func__,
+ tm->tm_sec, tm->tm_min, tm->tm_hour,
+ tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
+
+ /* hours, minutes and seconds */
+ buf[RX8581_REG_SC] = bin2bcd(tm->tm_sec);
+ buf[RX8581_REG_MN] = bin2bcd(tm->tm_min);
+ buf[RX8581_REG_HR] = bin2bcd(tm->tm_hour);
+
+ buf[RX8581_REG_DM] = bin2bcd(tm->tm_mday);
+
+ /* month, 1 - 12 */
+ buf[RX8581_REG_MO] = bin2bcd(tm->tm_mon + 1);
+
+ /* year and century */
+ buf[RX8581_REG_YR] = bin2bcd(tm->tm_year % 100);
+ buf[RX8581_REG_DW] = (0x1 << tm->tm_wday);
+
+ /* Stop the clock */
+ data = i2c_smbus_read_byte_data(client, RX8581_REG_CTRL);
+ if (data < 0) {
+ dev_err(&client->dev, "Unable to read control register\n");
+ return -EIO;
+ }
+
+ err = i2c_smbus_write_byte_data(client, RX8581_REG_FLAG,
+ (data | RX8581_CTRL_STOP));
+ if (err < 0) {
+ dev_err(&client->dev, "Unable to write control register\n");
+ return -EIO;
+ }
+
+ /* write register's data */
+ err = i2c_smbus_write_i2c_block_data(client, RX8581_REG_SC, 7, buf);
+ if (err < 0) {
+ dev_err(&client->dev, "Unable to write to date registers\n");
+ return -EIO;
+ }
+
+ /* Restart the clock */
+ data = i2c_smbus_read_byte_data(client, RX8581_REG_CTRL);
+ if (data < 0) {
+ dev_err(&client->dev, "Unable to read control register\n");
+ return -EIO;
+ }
+
+ err = i2c_smbus_write_byte_data(client, RX8581_REG_FLAG,
+ (data | ~(RX8581_CTRL_STOP)));
+ if (err != 0) {
+ dev_err(&client->dev, "Unable to write control register\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int rx8581_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ return rx8581_get_datetime(to_i2c_client(dev), tm);
+}
+
+static int rx8581_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ return rx8581_set_datetime(to_i2c_client(dev), tm);
+}
+
+static const struct rtc_class_ops rx8581_rtc_ops = {
+ .read_time = rx8581_rtc_read_time,
+ .set_time = rx8581_rtc_set_time,
+};
+
+static int __devinit rx8581_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct rtc_device *rtc;
+
+ dev_dbg(&client->dev, "%s\n", __func__);
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+ return -ENODEV;
+
+ dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
+
+ rtc = rtc_device_register(rx8581_driver.driver.name,
+ &client->dev, &rx8581_rtc_ops, THIS_MODULE);
+
+ if (IS_ERR(rtc))
+ return PTR_ERR(rtc);
+
+ i2c_set_clientdata(client, rtc);
+
+ return 0;
+}
+
+static int __devexit rx8581_remove(struct i2c_client *client)
+{
+ struct rtc_device *rtc = i2c_get_clientdata(client);
+
+ rtc_device_unregister(rtc);
+
+ return 0;
+}
+
+static const struct i2c_device_id rx8581_id[] = {
+ { "rx8581", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, rx8581_id);
+
+static struct i2c_driver rx8581_driver = {
+ .driver = {
+ .name = "rtc-rx8581",
+ .owner = THIS_MODULE,
+ },
+ .probe = rx8581_probe,
+ .remove = __devexit_p(rx8581_remove),
+ .id_table = rx8581_id,
+};
+
+static int __init rx8581_init(void)
+{
+ return i2c_add_driver(&rx8581_driver);
+}
+
+static void __exit rx8581_exit(void)
+{
+ i2c_del_driver(&rx8581_driver);
+}
+
+MODULE_AUTHOR("Martyn Welch <martyn.welch@gefanuc.com>");
+MODULE_DESCRIPTION("Epson RX-8581 RTC driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
+module_init(rx8581_init);
+module_exit(rx8581_exit);
diff --git a/drivers/rtc/rtc-starfire.c b/drivers/rtc/rtc-starfire.c
index 7ccb0dd700a..5be98bfd7ed 100644
--- a/drivers/rtc/rtc-starfire.c
+++ b/drivers/rtc/rtc-starfire.c
@@ -6,7 +6,6 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
-#include <linux/time.h>
#include <linux/rtc.h>
#include <linux/platform_device.h>
@@ -16,11 +15,6 @@ MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
MODULE_DESCRIPTION("Starfire RTC driver");
MODULE_LICENSE("GPL");
-struct starfire_rtc {
- struct rtc_device *rtc;
- spinlock_t lock;
-};
-
static u32 starfire_get_time(void)
{
static char obp_gettod[32];
@@ -35,64 +29,31 @@ static u32 starfire_get_time(void)
static int starfire_read_time(struct device *dev, struct rtc_time *tm)
{
- struct starfire_rtc *p = dev_get_drvdata(dev);
- unsigned long flags, secs;
-
- spin_lock_irqsave(&p->lock, flags);
- secs = starfire_get_time();
- spin_unlock_irqrestore(&p->lock, flags);
-
- rtc_time_to_tm(secs, tm);
-
- return 0;
-}
-
-static int starfire_set_time(struct device *dev, struct rtc_time *tm)
-{
- unsigned long secs;
- int err;
-
- err = rtc_tm_to_time(tm, &secs);
- if (err)
- return err;
-
- /* Do nothing, time is set using the service processor
- * console on this platform.
- */
- return 0;
+ rtc_time_to_tm(starfire_get_time(), tm);
+ return rtc_valid_tm(tm);
}
static const struct rtc_class_ops starfire_rtc_ops = {
.read_time = starfire_read_time,
- .set_time = starfire_set_time,
};
-static int __devinit starfire_rtc_probe(struct platform_device *pdev)
+static int __init starfire_rtc_probe(struct platform_device *pdev)
{
- struct starfire_rtc *p = kzalloc(sizeof(*p), GFP_KERNEL);
-
- if (!p)
- return -ENOMEM;
+ struct rtc_device *rtc = rtc_device_register("starfire", &pdev->dev,
+ &starfire_rtc_ops, THIS_MODULE);
+ if (IS_ERR(rtc))
+ return PTR_ERR(rtc);
- spin_lock_init(&p->lock);
+ platform_set_drvdata(pdev, rtc);
- p->rtc = rtc_device_register("starfire", &pdev->dev,
- &starfire_rtc_ops, THIS_MODULE);
- if (IS_ERR(p->rtc)) {
- int err = PTR_ERR(p->rtc);
- kfree(p);
- return err;
- }
- platform_set_drvdata(pdev, p);
return 0;
}
-static int __devexit starfire_rtc_remove(struct platform_device *pdev)
+static int __exit starfire_rtc_remove(struct platform_device *pdev)
{
- struct starfire_rtc *p = platform_get_drvdata(pdev);
+ struct rtc_device *rtc = platform_get_drvdata(pdev);
- rtc_device_unregister(p->rtc);
- kfree(p);
+ rtc_device_unregister(rtc);
return 0;
}
@@ -102,13 +63,12 @@ static struct platform_driver starfire_rtc_driver = {
.name = "rtc-starfire",
.owner = THIS_MODULE,
},
- .probe = starfire_rtc_probe,
- .remove = __devexit_p(starfire_rtc_remove),
+ .remove = __exit_p(starfire_rtc_remove),
};
static int __init starfire_rtc_init(void)
{
- return platform_driver_register(&starfire_rtc_driver);
+ return platform_driver_probe(&starfire_rtc_driver, starfire_rtc_probe);
}
static void __exit starfire_rtc_exit(void)
diff --git a/drivers/rtc/rtc-sun4v.c b/drivers/rtc/rtc-sun4v.c
index 2012ccbb4a5..5b2261052a6 100644
--- a/drivers/rtc/rtc-sun4v.c
+++ b/drivers/rtc/rtc-sun4v.c
@@ -1,4 +1,4 @@
-/* rtc-sun4c.c: Hypervisor based RTC for SUN4V systems.
+/* rtc-sun4v.c: Hypervisor based RTC for SUN4V systems.
*
* Copyright (C) 2008 David S. Miller <davem@davemloft.net>
*/
@@ -7,21 +7,11 @@
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/init.h>
-#include <linux/time.h>
#include <linux/rtc.h>
#include <linux/platform_device.h>
#include <asm/hypervisor.h>
-MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
-MODULE_DESCRIPTION("SUN4V RTC driver");
-MODULE_LICENSE("GPL");
-
-struct sun4v_rtc {
- struct rtc_device *rtc;
- spinlock_t lock;
-};
-
static unsigned long hypervisor_get_time(void)
{
unsigned long ret, time;
@@ -45,15 +35,7 @@ retry:
static int sun4v_read_time(struct device *dev, struct rtc_time *tm)
{
- struct sun4v_rtc *p = dev_get_drvdata(dev);
- unsigned long flags, secs;
-
- spin_lock_irqsave(&p->lock, flags);
- secs = hypervisor_get_time();
- spin_unlock_irqrestore(&p->lock, flags);
-
- rtc_time_to_tm(secs, tm);
-
+ rtc_time_to_tm(hypervisor_get_time(), tm);
return 0;
}
@@ -80,19 +62,14 @@ retry:
static int sun4v_set_time(struct device *dev, struct rtc_time *tm)
{
- struct sun4v_rtc *p = dev_get_drvdata(dev);
- unsigned long flags, secs;
+ unsigned long secs;
int err;
err = rtc_tm_to_time(tm, &secs);
if (err)
return err;
- spin_lock_irqsave(&p->lock, flags);
- err = hypervisor_set_time(secs);
- spin_unlock_irqrestore(&p->lock, flags);
-
- return err;
+ return hypervisor_set_time(secs);
}
static const struct rtc_class_ops sun4v_rtc_ops = {
@@ -100,33 +77,22 @@ static const struct rtc_class_ops sun4v_rtc_ops = {
.set_time = sun4v_set_time,
};
-static int __devinit sun4v_rtc_probe(struct platform_device *pdev)
+static int __init sun4v_rtc_probe(struct platform_device *pdev)
{
- struct sun4v_rtc *p = kzalloc(sizeof(*p), GFP_KERNEL);
-
- if (!p)
- return -ENOMEM;
-
- spin_lock_init(&p->lock);
-
- p->rtc = rtc_device_register("sun4v", &pdev->dev,
+ struct rtc_device *rtc = rtc_device_register("sun4v", &pdev->dev,
&sun4v_rtc_ops, THIS_MODULE);
- if (IS_ERR(p->rtc)) {
- int err = PTR_ERR(p->rtc);
- kfree(p);
- return err;
- }
- platform_set_drvdata(pdev, p);
+ if (IS_ERR(rtc))
+ return PTR_ERR(rtc);
+
+ platform_set_drvdata(pdev, rtc);
return 0;
}
-static int __devexit sun4v_rtc_remove(struct platform_device *pdev)
+static int __exit sun4v_rtc_remove(struct platform_device *pdev)
{
- struct sun4v_rtc *p = platform_get_drvdata(pdev);
-
- rtc_device_unregister(p->rtc);
- kfree(p);
+ struct rtc_device *rtc = platform_get_drvdata(pdev);
+ rtc_device_unregister(rtc);
return 0;
}
@@ -135,13 +101,12 @@ static struct platform_driver sun4v_rtc_driver = {
.name = "rtc-sun4v",
.owner = THIS_MODULE,
},
- .probe = sun4v_rtc_probe,
- .remove = __devexit_p(sun4v_rtc_remove),
+ .remove = __exit_p(sun4v_rtc_remove),
};
static int __init sun4v_rtc_init(void)
{
- return platform_driver_register(&sun4v_rtc_driver);
+ return platform_driver_probe(&sun4v_rtc_driver, sun4v_rtc_probe);
}
static void __exit sun4v_rtc_exit(void)
@@ -151,3 +116,7 @@ static void __exit sun4v_rtc_exit(void)
module_init(sun4v_rtc_init);
module_exit(sun4v_rtc_exit);
+
+MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
+MODULE_DESCRIPTION("SUN4V RTC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-twl4030.c b/drivers/rtc/rtc-twl4030.c
index abe87a4d266..01d8da9afdc 100644
--- a/drivers/rtc/rtc-twl4030.c
+++ b/drivers/rtc/rtc-twl4030.c
@@ -337,7 +337,7 @@ static int twl4030_rtc_ioctl(struct device *dev, unsigned int cmd,
}
#else
-#define omap_rtc_ioctl NULL
+#define twl4030_rtc_ioctl NULL
#endif
static irqreturn_t twl4030_rtc_interrupt(int irq, void *rtc)
diff --git a/drivers/rtc/rtc-wm8350.c b/drivers/rtc/rtc-wm8350.c
new file mode 100644
index 00000000000..5c5e3aa9138
--- /dev/null
+++ b/drivers/rtc/rtc-wm8350.c
@@ -0,0 +1,514 @@
+/*
+ * Real Time Clock driver for Wolfson Microelectronics WM8350
+ *
+ * Copyright (C) 2007, 2008 Wolfson Microelectronics PLC.
+ *
+ * Author: Liam Girdwood
+ * linux@wolfsonmicro.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/time.h>
+#include <linux/rtc.h>
+#include <linux/bcd.h>
+#include <linux/interrupt.h>
+#include <linux/ioctl.h>
+#include <linux/completion.h>
+#include <linux/mfd/wm8350/rtc.h>
+#include <linux/mfd/wm8350/core.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+
+#define WM8350_SET_ALM_RETRIES 5
+#define WM8350_SET_TIME_RETRIES 5
+#define WM8350_GET_TIME_RETRIES 5
+
+#define to_wm8350_from_rtc_dev(d) container_of(d, struct wm8350, rtc.pdev.dev)
+
+/*
+ * Read current time and date in RTC
+ */
+static int wm8350_rtc_readtime(struct device *dev, struct rtc_time *tm)
+{
+ struct wm8350 *wm8350 = dev_get_drvdata(dev);
+ u16 time1[4], time2[4];
+ int retries = WM8350_GET_TIME_RETRIES, ret;
+
+ /*
+ * Read the time twice and compare.
+ * If time1 == time2, then time is valid else retry.
+ */
+ do {
+ ret = wm8350_block_read(wm8350, WM8350_RTC_SECONDS_MINUTES,
+ 4, time1);
+ if (ret < 0)
+ return ret;
+ ret = wm8350_block_read(wm8350, WM8350_RTC_SECONDS_MINUTES,
+ 4, time2);
+ if (ret < 0)
+ return ret;
+
+ if (memcmp(time1, time2, sizeof(time1)) == 0) {
+ tm->tm_sec = time1[0] & WM8350_RTC_SECS_MASK;
+
+ tm->tm_min = (time1[0] & WM8350_RTC_MINS_MASK)
+ >> WM8350_RTC_MINS_SHIFT;
+
+ tm->tm_hour = time1[1] & WM8350_RTC_HRS_MASK;
+
+ tm->tm_wday = ((time1[1] >> WM8350_RTC_DAY_SHIFT)
+ & 0x7) - 1;
+
+ tm->tm_mon = ((time1[2] & WM8350_RTC_MTH_MASK)
+ >> WM8350_RTC_MTH_SHIFT) - 1;
+
+ tm->tm_mday = (time1[2] & WM8350_RTC_DATE_MASK);
+
+ tm->tm_year = ((time1[3] & WM8350_RTC_YHUNDREDS_MASK)
+ >> WM8350_RTC_YHUNDREDS_SHIFT) * 100;
+ tm->tm_year += time1[3] & WM8350_RTC_YUNITS_MASK;
+
+ tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon,
+ tm->tm_year);
+ tm->tm_year -= 1900;
+
+ dev_dbg(dev, "Read (%d left): %04x %04x %04x %04x\n",
+ retries,
+ time1[0], time1[1], time1[2], time1[3]);
+
+ return 0;
+ }
+ } while (retries--);
+
+ dev_err(dev, "timed out reading RTC time\n");
+ return -EIO;
+}
+
+/*
+ * Set current time and date in RTC
+ */
+static int wm8350_rtc_settime(struct device *dev, struct rtc_time *tm)
+{
+ struct wm8350 *wm8350 = dev_get_drvdata(dev);
+ u16 time[4];
+ u16 rtc_ctrl;
+ int ret, retries = WM8350_SET_TIME_RETRIES;
+
+ time[0] = tm->tm_sec;
+ time[0] |= tm->tm_min << WM8350_RTC_MINS_SHIFT;
+ time[1] = tm->tm_hour;
+ time[1] |= (tm->tm_wday + 1) << WM8350_RTC_DAY_SHIFT;
+ time[2] = tm->tm_mday;
+ time[2] |= (tm->tm_mon + 1) << WM8350_RTC_MTH_SHIFT;
+ time[3] = ((tm->tm_year + 1900) / 100) << WM8350_RTC_YHUNDREDS_SHIFT;
+ time[3] |= (tm->tm_year + 1900) % 100;
+
+ dev_dbg(dev, "Setting: %04x %04x %04x %04x\n",
+ time[0], time[1], time[2], time[3]);
+
+ /* Set RTC_SET to stop the clock */
+ ret = wm8350_set_bits(wm8350, WM8350_RTC_TIME_CONTROL, WM8350_RTC_SET);
+ if (ret < 0)
+ return ret;
+
+ /* Wait until confirmation of stopping */
+ do {
+ rtc_ctrl = wm8350_reg_read(wm8350, WM8350_RTC_TIME_CONTROL);
+ schedule_timeout_uninterruptible(msecs_to_jiffies(1));
+ } while (retries-- && !(rtc_ctrl & WM8350_RTC_STS));
+
+ if (!retries) {
+ dev_err(dev, "timed out on set confirmation\n");
+ return -EIO;
+ }
+
+ /* Write time to RTC */
+ ret = wm8350_block_write(wm8350, WM8350_RTC_SECONDS_MINUTES, 4, time);
+ if (ret < 0)
+ return ret;
+
+ /* Clear RTC_SET to start the clock */
+ ret = wm8350_clear_bits(wm8350, WM8350_RTC_TIME_CONTROL,
+ WM8350_RTC_SET);
+ return ret;
+}
+
+/*
+ * Read alarm time and date in RTC
+ */
+static int wm8350_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct wm8350 *wm8350 = dev_get_drvdata(dev);
+ struct rtc_time *tm = &alrm->time;
+ u16 time[4];
+ int ret;
+
+ ret = wm8350_block_read(wm8350, WM8350_ALARM_SECONDS_MINUTES, 4, time);
+ if (ret < 0)
+ return ret;
+
+ tm->tm_sec = time[0] & WM8350_RTC_ALMSECS_MASK;
+ if (tm->tm_sec == WM8350_RTC_ALMSECS_MASK)
+ tm->tm_sec = -1;
+
+ tm->tm_min = time[0] & WM8350_RTC_ALMMINS_MASK;
+ if (tm->tm_min == WM8350_RTC_ALMMINS_MASK)
+ tm->tm_min = -1;
+ else
+ tm->tm_min >>= WM8350_RTC_ALMMINS_SHIFT;
+
+ tm->tm_hour = time[1] & WM8350_RTC_ALMHRS_MASK;
+ if (tm->tm_hour == WM8350_RTC_ALMHRS_MASK)
+ tm->tm_hour = -1;
+
+ tm->tm_wday = ((time[1] >> WM8350_RTC_ALMDAY_SHIFT) & 0x7) - 1;
+ if (tm->tm_wday > 7)
+ tm->tm_wday = -1;
+
+ tm->tm_mon = time[2] & WM8350_RTC_ALMMTH_MASK;
+ if (tm->tm_mon == WM8350_RTC_ALMMTH_MASK)
+ tm->tm_mon = -1;
+ else
+ tm->tm_mon = (tm->tm_mon >> WM8350_RTC_ALMMTH_SHIFT) - 1;
+
+ tm->tm_mday = (time[2] & WM8350_RTC_ALMDATE_MASK);
+ if (tm->tm_mday == WM8350_RTC_ALMDATE_MASK)
+ tm->tm_mday = -1;
+
+ tm->tm_year = -1;
+
+ alrm->enabled = !(time[3] & WM8350_RTC_ALMSTS);
+
+ return 0;
+}
+
+static int wm8350_rtc_stop_alarm(struct wm8350 *wm8350)
+{
+ int retries = WM8350_SET_ALM_RETRIES;
+ u16 rtc_ctrl;
+ int ret;
+
+ /* Set RTC_SET to stop the clock */
+ ret = wm8350_set_bits(wm8350, WM8350_RTC_TIME_CONTROL,
+ WM8350_RTC_ALMSET);
+ if (ret < 0)
+ return ret;
+
+ /* Wait until confirmation of stopping */
+ do {
+ rtc_ctrl = wm8350_reg_read(wm8350, WM8350_RTC_TIME_CONTROL);
+ schedule_timeout_uninterruptible(msecs_to_jiffies(1));
+ } while (retries-- && !(rtc_ctrl & WM8350_RTC_ALMSTS));
+
+ if (!(rtc_ctrl & WM8350_RTC_ALMSTS))
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
+static int wm8350_rtc_start_alarm(struct wm8350 *wm8350)
+{
+ int ret;
+ int retries = WM8350_SET_ALM_RETRIES;
+ u16 rtc_ctrl;
+
+ ret = wm8350_clear_bits(wm8350, WM8350_RTC_TIME_CONTROL,
+ WM8350_RTC_ALMSET);
+ if (ret < 0)
+ return ret;
+
+ /* Wait until confirmation */
+ do {
+ rtc_ctrl = wm8350_reg_read(wm8350, WM8350_RTC_TIME_CONTROL);
+ schedule_timeout_uninterruptible(msecs_to_jiffies(1));
+ } while (retries-- && rtc_ctrl & WM8350_RTC_ALMSTS);
+
+ if (rtc_ctrl & WM8350_RTC_ALMSTS)
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
+static int wm8350_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct wm8350 *wm8350 = dev_get_drvdata(dev);
+ struct rtc_time *tm = &alrm->time;
+ u16 time[3];
+ int ret;
+
+ memset(time, 0, sizeof(time));
+
+ if (tm->tm_sec != -1)
+ time[0] |= tm->tm_sec;
+ else
+ time[0] |= WM8350_RTC_ALMSECS_MASK;
+
+ if (tm->tm_min != -1)
+ time[0] |= tm->tm_min << WM8350_RTC_ALMMINS_SHIFT;
+ else
+ time[0] |= WM8350_RTC_ALMMINS_MASK;
+
+ if (tm->tm_hour != -1)
+ time[1] |= tm->tm_hour;
+ else
+ time[1] |= WM8350_RTC_ALMHRS_MASK;
+
+ if (tm->tm_wday != -1)
+ time[1] |= (tm->tm_wday + 1) << WM8350_RTC_ALMDAY_SHIFT;
+ else
+ time[1] |= WM8350_RTC_ALMDAY_MASK;
+
+ if (tm->tm_mday != -1)
+ time[2] |= tm->tm_mday;
+ else
+ time[2] |= WM8350_RTC_ALMDATE_MASK;
+
+ if (tm->tm_mon != -1)
+ time[2] |= (tm->tm_mon + 1) << WM8350_RTC_ALMMTH_SHIFT;
+ else
+ time[2] |= WM8350_RTC_ALMMTH_MASK;
+
+ ret = wm8350_rtc_stop_alarm(wm8350);
+ if (ret < 0)
+ return ret;
+
+ /* Write time to RTC */
+ ret = wm8350_block_write(wm8350, WM8350_ALARM_SECONDS_MINUTES,
+ 3, time);
+ if (ret < 0)
+ return ret;
+
+ if (alrm->enabled)
+ ret = wm8350_rtc_start_alarm(wm8350);
+
+ return ret;
+}
+
+/*
+ * Handle commands from user-space
+ */
+static int wm8350_rtc_ioctl(struct device *dev, unsigned int cmd,
+ unsigned long arg)
+{
+ struct wm8350 *wm8350 = dev_get_drvdata(dev);
+
+ switch (cmd) {
+ case RTC_AIE_OFF:
+ return wm8350_rtc_stop_alarm(wm8350);
+ case RTC_AIE_ON:
+ return wm8350_rtc_start_alarm(wm8350);
+
+ case RTC_UIE_OFF:
+ wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC);
+ break;
+ case RTC_UIE_ON:
+ wm8350_unmask_irq(wm8350, WM8350_IRQ_RTC_SEC);
+ break;
+
+ default:
+ return -ENOIOCTLCMD;
+ }
+
+ return 0;
+}
+
+static void wm8350_rtc_alarm_handler(struct wm8350 *wm8350, int irq,
+ void *data)
+{
+ struct rtc_device *rtc = wm8350->rtc.rtc;
+ int ret;
+
+ rtc_update_irq(rtc, 1, RTC_IRQF | RTC_AF);
+
+ /* Make it one shot */
+ ret = wm8350_set_bits(wm8350, WM8350_RTC_TIME_CONTROL,
+ WM8350_RTC_ALMSET);
+ if (ret != 0) {
+ dev_err(&(wm8350->rtc.pdev->dev),
+ "Failed to disable alarm: %d\n", ret);
+ }
+}
+
+static void wm8350_rtc_update_handler(struct wm8350 *wm8350, int irq,
+ void *data)
+{
+ struct rtc_device *rtc = wm8350->rtc.rtc;
+
+ rtc_update_irq(rtc, 1, RTC_IRQF | RTC_UF);
+}
+
+static const struct rtc_class_ops wm8350_rtc_ops = {
+ .ioctl = wm8350_rtc_ioctl,
+ .read_time = wm8350_rtc_readtime,
+ .set_time = wm8350_rtc_settime,
+ .read_alarm = wm8350_rtc_readalarm,
+ .set_alarm = wm8350_rtc_setalarm,
+};
+
+#ifdef CONFIG_PM
+static int wm8350_rtc_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct wm8350 *wm8350 = dev_get_drvdata(&pdev->dev);
+ int ret = 0;
+ u16 reg;
+
+ reg = wm8350_reg_read(wm8350, WM8350_RTC_TIME_CONTROL);
+
+ if (device_may_wakeup(&wm8350->rtc.pdev->dev) &&
+ reg & WM8350_RTC_ALMSTS) {
+ ret = wm8350_rtc_stop_alarm(wm8350);
+ if (ret != 0)
+ dev_err(&pdev->dev, "Failed to stop RTC alarm: %d\n",
+ ret);
+ }
+
+ return ret;
+}
+
+static int wm8350_rtc_resume(struct platform_device *pdev)
+{
+ struct wm8350 *wm8350 = dev_get_drvdata(&pdev->dev);
+ int ret;
+
+ if (wm8350->rtc.alarm_enabled) {
+ ret = wm8350_rtc_start_alarm(wm8350);
+ if (ret != 0)
+ dev_err(&pdev->dev,
+ "Failed to restart RTC alarm: %d\n", ret);
+ }
+
+ return 0;
+}
+
+#else
+#define wm8350_rtc_suspend NULL
+#define wm8350_rtc_resume NULL
+#endif
+
+static int wm8350_rtc_probe(struct platform_device *pdev)
+{
+ struct wm8350 *wm8350 = platform_get_drvdata(pdev);
+ struct wm8350_rtc *wm_rtc = &wm8350->rtc;
+ int ret = 0;
+ u16 timectl, power5;
+
+ timectl = wm8350_reg_read(wm8350, WM8350_RTC_TIME_CONTROL);
+ if (timectl & WM8350_RTC_BCD) {
+ dev_err(&pdev->dev, "RTC BCD mode not supported\n");
+ return -EINVAL;
+ }
+ if (timectl & WM8350_RTC_12HR) {
+ dev_err(&pdev->dev, "RTC 12 hour mode not supported\n");
+ return -EINVAL;
+ }
+
+ /* enable the RTC if it's not already enabled */
+ power5 = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_5);
+ if (!(power5 & WM8350_RTC_TICK_ENA)) {
+ dev_info(wm8350->dev, "Starting RTC\n");
+
+ wm8350_reg_unlock(wm8350);
+
+ ret = wm8350_set_bits(wm8350, WM8350_POWER_MGMT_5,
+ WM8350_RTC_TICK_ENA);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to enable RTC: %d\n", ret);
+ return ret;
+ }
+
+ wm8350_reg_lock(wm8350);
+ }
+
+ if (timectl & WM8350_RTC_STS) {
+ int retries;
+
+ ret = wm8350_clear_bits(wm8350, WM8350_RTC_TIME_CONTROL,
+ WM8350_RTC_SET);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to start: %d\n", ret);
+ return ret;
+ }
+
+ retries = WM8350_SET_TIME_RETRIES;
+ do {
+ timectl = wm8350_reg_read(wm8350,
+ WM8350_RTC_TIME_CONTROL);
+ } while (timectl & WM8350_RTC_STS && retries--);
+
+ if (retries == 0) {
+ dev_err(&pdev->dev, "failed to start: timeout\n");
+ return -ENODEV;
+ }
+ }
+
+ device_init_wakeup(&pdev->dev, 1);
+
+ wm_rtc->rtc = rtc_device_register("wm8350", &pdev->dev,
+ &wm8350_rtc_ops, THIS_MODULE);
+ if (IS_ERR(wm_rtc->rtc)) {
+ ret = PTR_ERR(wm_rtc->rtc);
+ dev_err(&pdev->dev, "failed to register RTC: %d\n", ret);
+ return ret;
+ }
+
+ wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC);
+ wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_PER);
+
+ wm8350_register_irq(wm8350, WM8350_IRQ_RTC_SEC,
+ wm8350_rtc_update_handler, NULL);
+
+ wm8350_register_irq(wm8350, WM8350_IRQ_RTC_ALM,
+ wm8350_rtc_alarm_handler, NULL);
+ wm8350_unmask_irq(wm8350, WM8350_IRQ_RTC_ALM);
+
+ return 0;
+}
+
+static int __devexit wm8350_rtc_remove(struct platform_device *pdev)
+{
+ struct wm8350 *wm8350 = platform_get_drvdata(pdev);
+ struct wm8350_rtc *wm_rtc = &wm8350->rtc;
+
+ wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC);
+
+ wm8350_free_irq(wm8350, WM8350_IRQ_RTC_SEC);
+ wm8350_free_irq(wm8350, WM8350_IRQ_RTC_ALM);
+
+ rtc_device_unregister(wm_rtc->rtc);
+
+ return 0;
+}
+
+static struct platform_driver wm8350_rtc_driver = {
+ .probe = wm8350_rtc_probe,
+ .remove = __devexit_p(wm8350_rtc_remove),
+ .suspend = wm8350_rtc_suspend,
+ .resume = wm8350_rtc_resume,
+ .driver = {
+ .name = "wm8350-rtc",
+ },
+};
+
+static int __init wm8350_rtc_init(void)
+{
+ return platform_driver_register(&wm8350_rtc_driver);
+}
+module_init(wm8350_rtc_init);
+
+static void __exit wm8350_rtc_exit(void)
+{
+ platform_driver_unregister(&wm8350_rtc_driver);
+}
+module_exit(wm8350_rtc_exit);
+
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_DESCRIPTION("RTC driver for the WM8350");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:wm8350-rtc");
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 4b76fca64a6..363bd1303d2 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -1746,6 +1746,11 @@ restart:
goto restart;
}
+ /* log sense for fatal error */
+ if (cqr->status == DASD_CQR_FAILED) {
+ dasd_log_sense(cqr, &cqr->irb);
+ }
+
/* First of all call extended error reporting. */
if (dasd_eer_enabled(base) &&
cqr->status == DASD_CQR_FAILED) {
diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c
index eb5f1b8bc57..ec9c0bcf66e 100644
--- a/drivers/s390/char/sclp_cmd.c
+++ b/drivers/s390/char/sclp_cmd.c
@@ -324,6 +324,9 @@ static int do_assign_storage(sclp_cmdw_t cmd, u16 rn)
case 0x0120:
break;
default:
+ pr_warning("assign storage failed (cmd=0x%08x, "
+ "response=0x%04x, rn=0x%04x)\n", cmd,
+ sccb->header.response_code, rn);
rc = -EIO;
break;
}
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 4e78c82194b..4e4008325e2 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -874,11 +874,15 @@ void ccw_device_move_to_orphanage(struct work_struct *work)
replacing_cdev = get_disc_ccwdev_by_dev_id(&dev_id, cdev);
if (replacing_cdev) {
sch_attach_disconnected_device(sch, replacing_cdev);
+ /* Release reference from get_disc_ccwdev_by_dev_id() */
+ put_device(&cdev->dev);
return;
}
replacing_cdev = get_orphaned_ccwdev_by_dev_id(css, &dev_id);
if (replacing_cdev) {
sch_attach_orphaned_device(sch, replacing_cdev);
+ /* Release reference from get_orphaned_ccwdev_by_dev_id() */
+ put_device(&cdev->dev);
return;
}
sch_create_and_recog_new_device(sch);
diff --git a/drivers/s390/kvm/kvm_virtio.c b/drivers/s390/kvm/kvm_virtio.c
index ff4a6931bb8..3d442444c61 100644
--- a/drivers/s390/kvm/kvm_virtio.c
+++ b/drivers/s390/kvm/kvm_virtio.c
@@ -322,13 +322,13 @@ static int __init kvm_devices_init(void)
return rc;
}
- rc = vmem_add_mapping(PFN_PHYS(max_pfn), PAGE_SIZE);
+ rc = vmem_add_mapping(real_memory_size, PAGE_SIZE);
if (rc) {
s390_root_dev_unregister(kvm_root);
return rc;
}
- kvm_devices = (void *) PFN_PHYS(max_pfn);
+ kvm_devices = (void *) real_memory_size;
ctl_set_bit(0, 9);
register_external_interrupt(0x2603, kvm_extint_handler);
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 3b56220fb90..3d4e3e3f3fc 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -610,7 +610,8 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn,
atomic_set_mask(status | ZFCP_STATUS_COMMON_REMOVE, &port->status);
atomic_set(&port->refcount, 0);
- dev_set_name(&port->sysfs_device, "0x%016llx", wwpn);
+ dev_set_name(&port->sysfs_device, "0x%016llx",
+ (unsigned long long)wwpn);
port->sysfs_device.parent = &adapter->ccw_device->dev;
port->sysfs_device.release = zfcp_sysfs_port_release;
diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c
index b04038c7478..951a8d409d1 100644
--- a/drivers/s390/scsi/zfcp_ccw.c
+++ b/drivers/s390/scsi/zfcp_ccw.c
@@ -116,7 +116,9 @@ static int zfcp_ccw_set_online(struct ccw_device *ccw_device)
zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, 85,
NULL);
zfcp_erp_wait(adapter);
- goto out;
+ up(&zfcp_data.config_sema);
+ flush_work(&adapter->scan_work);
+ return 0;
out_scsi_register:
zfcp_erp_thread_kill(adapter);
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
index 060f5f2352e..31012d58cfb 100644
--- a/drivers/s390/scsi/zfcp_dbf.c
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -30,7 +30,7 @@ static void zfcp_dbf_hexdump(debug_info_t *dbf, void *to, int to_len,
dump->offset = offset;
dump->size = min(from_len - offset, room);
memcpy(dump->data, from + offset, dump->size);
- debug_event(dbf, level, dump, dump->size);
+ debug_event(dbf, level, dump, dump->size + sizeof(*dump));
}
}
@@ -108,7 +108,7 @@ static int zfcp_dbf_view_header(debug_info_t *id, struct debug_view *view,
t.tv_sec, t.tv_nsec);
zfcp_dbf_out(&p, "cpu", "%02i", entry->id.fields.cpuid);
} else {
- zfcp_dbf_outd(&p, NULL, dump->data, dump->size, dump->offset,
+ zfcp_dbf_outd(&p, "", dump->data, dump->size, dump->offset,
dump->total_size);
if ((dump->offset + dump->size) == dump->total_size)
p += sprintf(p, "\n");
@@ -366,6 +366,7 @@ static void zfcp_hba_dbf_view_response(char **p,
break;
zfcp_dbf_out(p, "scsi_cmnd", "0x%0Lx", r->u.fcp.cmnd);
zfcp_dbf_out(p, "scsi_serial", "0x%016Lx", r->u.fcp.serial);
+ p += sprintf(*p, "\n");
break;
case FSF_QTCB_OPEN_PORT_WITH_DID:
@@ -465,7 +466,8 @@ static int zfcp_hba_dbf_view_format(debug_info_t *id, struct debug_view *view,
else if (strncmp(r->tag, "berr", ZFCP_DBF_TAG_SIZE) == 0)
zfcp_hba_dbf_view_berr(&p, &r->u.berr);
- p += sprintf(p, "\n");
+ if (strncmp(r->tag, "resp", ZFCP_DBF_TAG_SIZE) != 0)
+ p += sprintf(p, "\n");
return p - out_buf;
}
@@ -880,6 +882,7 @@ void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *fsf_req)
struct ct_hdr *hdr = sg_virt(ct->req);
struct zfcp_san_dbf_record *r = &adapter->san_dbf_buf;
struct zfcp_san_dbf_record_ct_request *oct = &r->u.ct_req;
+ int level = 3;
unsigned long flags;
spin_lock_irqsave(&adapter->san_dbf_lock, flags);
@@ -896,9 +899,10 @@ void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *fsf_req)
oct->options = hdr->options;
oct->max_res_size = hdr->max_res_size;
oct->len = min((int)ct->req->length - (int)sizeof(struct ct_hdr),
- ZFCP_DBF_CT_PAYLOAD);
- memcpy(oct->payload, (void *)hdr + sizeof(struct ct_hdr), oct->len);
- debug_event(adapter->san_dbf, 3, r, sizeof(*r));
+ ZFCP_DBF_SAN_MAX_PAYLOAD);
+ debug_event(adapter->san_dbf, level, r, sizeof(*r));
+ zfcp_dbf_hexdump(adapter->san_dbf, r, sizeof(*r), level,
+ (void *)hdr + sizeof(struct ct_hdr), oct->len);
spin_unlock_irqrestore(&adapter->san_dbf_lock, flags);
}
@@ -914,6 +918,7 @@ void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *fsf_req)
struct ct_hdr *hdr = sg_virt(ct->resp);
struct zfcp_san_dbf_record *r = &adapter->san_dbf_buf;
struct zfcp_san_dbf_record_ct_response *rct = &r->u.ct_resp;
+ int level = 3;
unsigned long flags;
spin_lock_irqsave(&adapter->san_dbf_lock, flags);
@@ -929,9 +934,10 @@ void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *fsf_req)
rct->expl = hdr->reason_code_expl;
rct->vendor_unique = hdr->vendor_unique;
rct->len = min((int)ct->resp->length - (int)sizeof(struct ct_hdr),
- ZFCP_DBF_CT_PAYLOAD);
- memcpy(rct->payload, (void *)hdr + sizeof(struct ct_hdr), rct->len);
- debug_event(adapter->san_dbf, 3, r, sizeof(*r));
+ ZFCP_DBF_SAN_MAX_PAYLOAD);
+ debug_event(adapter->san_dbf, level, r, sizeof(*r));
+ zfcp_dbf_hexdump(adapter->san_dbf, r, sizeof(*r), level,
+ (void *)hdr + sizeof(struct ct_hdr), rct->len);
spin_unlock_irqrestore(&adapter->san_dbf_lock, flags);
}
@@ -954,7 +960,7 @@ static void zfcp_san_dbf_event_els(const char *tag, int level,
rec->u.els.ls_code = ls_code;
debug_event(adapter->san_dbf, level, rec, sizeof(*rec));
zfcp_dbf_hexdump(adapter->san_dbf, rec, sizeof(*rec), level,
- buffer, min(buflen, ZFCP_DBF_ELS_MAX_PAYLOAD));
+ buffer, min(buflen, ZFCP_DBF_SAN_MAX_PAYLOAD));
spin_unlock_irqrestore(&adapter->san_dbf_lock, flags);
}
@@ -1008,8 +1014,6 @@ static int zfcp_san_dbf_view_format(debug_info_t *id, struct debug_view *view,
char *out_buf, const char *in_buf)
{
struct zfcp_san_dbf_record *r = (struct zfcp_san_dbf_record *)in_buf;
- char *buffer = NULL;
- int buflen = 0, total = 0;
char *p = out_buf;
if (strncmp(r->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0)
@@ -1029,9 +1033,6 @@ static int zfcp_san_dbf_view_format(debug_info_t *id, struct debug_view *view,
zfcp_dbf_out(&p, "gs_subtype", "0x%02x", ct->gs_subtype);
zfcp_dbf_out(&p, "options", "0x%02x", ct->options);
zfcp_dbf_out(&p, "max_res_size", "0x%04x", ct->max_res_size);
- total = ct->len;
- buffer = ct->payload;
- buflen = min(total, ZFCP_DBF_CT_PAYLOAD);
} else if (strncmp(r->tag, "rctc", ZFCP_DBF_TAG_SIZE) == 0) {
struct zfcp_san_dbf_record_ct_response *ct = &r->u.ct_resp;
zfcp_dbf_out(&p, "cmd_rsp_code", "0x%04x", ct->cmd_rsp_code);
@@ -1039,23 +1040,12 @@ static int zfcp_san_dbf_view_format(debug_info_t *id, struct debug_view *view,
zfcp_dbf_out(&p, "reason_code", "0x%02x", ct->reason_code);
zfcp_dbf_out(&p, "reason_code_expl", "0x%02x", ct->expl);
zfcp_dbf_out(&p, "vendor_unique", "0x%02x", ct->vendor_unique);
- total = ct->len;
- buffer = ct->payload;
- buflen = min(total, ZFCP_DBF_CT_PAYLOAD);
} else if (strncmp(r->tag, "oels", ZFCP_DBF_TAG_SIZE) == 0 ||
strncmp(r->tag, "rels", ZFCP_DBF_TAG_SIZE) == 0 ||
strncmp(r->tag, "iels", ZFCP_DBF_TAG_SIZE) == 0) {
struct zfcp_san_dbf_record_els *els = &r->u.els;
zfcp_dbf_out(&p, "ls_code", "0x%02x", els->ls_code);
- total = els->len;
- buffer = els->payload;
- buflen = min(total, ZFCP_DBF_ELS_PAYLOAD);
}
-
- zfcp_dbf_outd(&p, "payload", buffer, buflen, 0, total);
- if (buflen == total)
- p += sprintf(p, "\n");
-
return p - out_buf;
}
diff --git a/drivers/s390/scsi/zfcp_dbf.h b/drivers/s390/scsi/zfcp_dbf.h
index e8f450801fe..5d6b2dff855 100644
--- a/drivers/s390/scsi/zfcp_dbf.h
+++ b/drivers/s390/scsi/zfcp_dbf.h
@@ -163,8 +163,6 @@ struct zfcp_san_dbf_record_ct_request {
u8 options;
u16 max_res_size;
u32 len;
-#define ZFCP_DBF_CT_PAYLOAD 24
- u8 payload[ZFCP_DBF_CT_PAYLOAD];
} __attribute__ ((packed));
struct zfcp_san_dbf_record_ct_response {
@@ -174,15 +172,11 @@ struct zfcp_san_dbf_record_ct_response {
u8 expl;
u8 vendor_unique;
u32 len;
- u8 payload[ZFCP_DBF_CT_PAYLOAD];
} __attribute__ ((packed));
struct zfcp_san_dbf_record_els {
u8 ls_code;
u32 len;
-#define ZFCP_DBF_ELS_PAYLOAD 32
-#define ZFCP_DBF_ELS_MAX_PAYLOAD 1024
- u8 payload[ZFCP_DBF_ELS_PAYLOAD];
} __attribute__ ((packed));
struct zfcp_san_dbf_record {
@@ -196,6 +190,8 @@ struct zfcp_san_dbf_record {
struct zfcp_san_dbf_record_ct_response ct_resp;
struct zfcp_san_dbf_record_els els;
} u;
+#define ZFCP_DBF_SAN_MAX_PAYLOAD 1024
+ u8 payload[32];
} __attribute__ ((packed));
struct zfcp_scsi_dbf_record {
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index 9040f738ff3..c557ba34e1a 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -472,6 +472,7 @@ static void zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *act)
ZFCP_STATUS_ERP_TIMEDOUT)) {
act->fsf_req->status |= ZFCP_STATUS_FSFREQ_DISMISSED;
zfcp_rec_dbf_event_action(142, act);
+ act->fsf_req->erp_action = NULL;
}
if (act->status & ZFCP_STATUS_ERP_TIMEDOUT)
zfcp_rec_dbf_event_action(143, act);
@@ -719,7 +720,6 @@ static int zfcp_erp_adapter_strategy_generic(struct zfcp_erp_action *act,
goto failed_openfcp;
atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &act->adapter->status);
- schedule_work(&act->adapter->scan_work);
return ZFCP_ERP_SUCCEEDED;
@@ -1185,7 +1185,9 @@ static void zfcp_erp_scsi_scan(struct work_struct *work)
container_of(work, struct zfcp_erp_add_work, work);
struct zfcp_unit *unit = p->unit;
struct fc_rport *rport = unit->port->rport;
- scsi_scan_target(&rport->dev, 0, rport->scsi_target_id,
+
+ if (rport && rport->port_state == FC_PORTSTATE_ONLINE)
+ scsi_scan_target(&rport->dev, 0, rport->scsi_target_id,
scsilun_to_int((struct scsi_lun *)&unit->fcp_lun), 0);
atomic_clear_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status);
zfcp_unit_put(unit);
@@ -1281,6 +1283,8 @@ static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result)
case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
if (result != ZFCP_ERP_SUCCEEDED)
zfcp_erp_rports_del(adapter);
+ else
+ schedule_work(&adapter->scan_work);
zfcp_adapter_put(adapter);
break;
}
diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c
index 1a7c80a77ff..8aab3091a7b 100644
--- a/drivers/s390/scsi/zfcp_fc.c
+++ b/drivers/s390/scsi/zfcp_fc.c
@@ -50,7 +50,8 @@ static int zfcp_wka_port_get(struct zfcp_wka_port *wka_port)
if (mutex_lock_interruptible(&wka_port->mutex))
return -ERESTARTSYS;
- if (wka_port->status != ZFCP_WKA_PORT_ONLINE) {
+ if (wka_port->status == ZFCP_WKA_PORT_OFFLINE ||
+ wka_port->status == ZFCP_WKA_PORT_CLOSING) {
wka_port->status = ZFCP_WKA_PORT_OPENING;
if (zfcp_fsf_open_wka_port(wka_port))
wka_port->status = ZFCP_WKA_PORT_OFFLINE;
@@ -125,8 +126,7 @@ static void _zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req, u32 range,
read_lock_irqsave(&zfcp_data.config_lock, flags);
list_for_each_entry(port, &fsf_req->adapter->port_list_head, list) {
- /* FIXME: ZFCP_STATUS_PORT_DID_DID check is racy */
- if (!(atomic_read(&port->status) & ZFCP_STATUS_PORT_DID_DID))
+ if (!(atomic_read(&port->status) & ZFCP_STATUS_PORT_PHYS_OPEN))
/* Try to connect to unused ports anyway. */
zfcp_erp_port_reopen(port,
ZFCP_STATUS_COMMON_ERP_FAILED,
@@ -610,7 +610,6 @@ int zfcp_scan_ports(struct zfcp_adapter *adapter)
int ret, i;
struct zfcp_gpn_ft *gpn_ft;
- zfcp_erp_wait(adapter); /* wait until adapter is finished with ERP */
if (fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPORT)
return 0;
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 5ae1d497e5e..dc036769040 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -683,6 +683,7 @@ static struct zfcp_fsf_req *zfcp_fsf_alloc_noqtcb(mempool_t *pool)
if (!req)
return NULL;
memset(req, 0, sizeof(*req));
+ req->pool = pool;
return req;
}
@@ -769,28 +770,24 @@ static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_adapter *adapter,
static int zfcp_fsf_req_send(struct zfcp_fsf_req *req)
{
struct zfcp_adapter *adapter = req->adapter;
- struct zfcp_qdio_queue *req_q = &adapter->req_q;
+ unsigned long flags;
int idx;
/* put allocated FSF request into hash table */
- spin_lock(&adapter->req_list_lock);
+ spin_lock_irqsave(&adapter->req_list_lock, flags);
idx = zfcp_reqlist_hash(req->req_id);
list_add_tail(&req->list, &adapter->req_list[idx]);
- spin_unlock(&adapter->req_list_lock);
+ spin_unlock_irqrestore(&adapter->req_list_lock, flags);
- req->qdio_outb_usage = atomic_read(&req_q->count);
+ req->qdio_outb_usage = atomic_read(&adapter->req_q.count);
req->issued = get_clock();
if (zfcp_qdio_send(req)) {
- /* Queues are down..... */
del_timer(&req->timer);
- spin_lock(&adapter->req_list_lock);
- zfcp_reqlist_remove(adapter, req);
- spin_unlock(&adapter->req_list_lock);
- /* undo changes in request queue made for this request */
- atomic_add(req->sbal_number, &req_q->count);
- req_q->first -= req->sbal_number;
- req_q->first += QDIO_MAX_BUFFERS_PER_Q;
- req_q->first %= QDIO_MAX_BUFFERS_PER_Q; /* wrap */
+ spin_lock_irqsave(&adapter->req_list_lock, flags);
+ /* lookup request again, list might have changed */
+ if (zfcp_reqlist_find_safe(adapter, req))
+ zfcp_reqlist_remove(adapter, req);
+ spin_unlock_irqrestore(&adapter->req_list_lock, flags);
zfcp_erp_adapter_reopen(adapter, 0, 116, req);
return -EIO;
}
@@ -933,8 +930,10 @@ struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long old_req_id,
goto out;
req = zfcp_fsf_req_create(adapter, FSF_QTCB_ABORT_FCP_CMND,
req_flags, adapter->pool.fsf_req_abort);
- if (IS_ERR(req))
+ if (IS_ERR(req)) {
+ req = NULL;
goto out;
+ }
if (unlikely(!(atomic_read(&unit->status) &
ZFCP_STATUS_COMMON_UNBLOCKED)))
@@ -1587,6 +1586,7 @@ static void zfcp_fsf_open_wka_port_handler(struct zfcp_fsf_req *req)
wka_port->status = ZFCP_WKA_PORT_OFFLINE;
break;
case FSF_PORT_ALREADY_OPEN:
+ break;
case FSF_GOOD:
wka_port->handle = header->port_handle;
wka_port->status = ZFCP_WKA_PORT_ONLINE;
@@ -2116,18 +2116,21 @@ static inline void zfcp_fsf_trace_latency(struct zfcp_fsf_req *fsf_req)
static void zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *req)
{
- struct scsi_cmnd *scpnt = req->data;
+ struct scsi_cmnd *scpnt;
struct fcp_rsp_iu *fcp_rsp_iu = (struct fcp_rsp_iu *)
&(req->qtcb->bottom.io.fcp_rsp);
u32 sns_len;
char *fcp_rsp_info = (unsigned char *) &fcp_rsp_iu[1];
unsigned long flags;
- if (unlikely(!scpnt))
- return;
-
read_lock_irqsave(&req->adapter->abort_lock, flags);
+ scpnt = req->data;
+ if (unlikely(!scpnt)) {
+ read_unlock_irqrestore(&req->adapter->abort_lock, flags);
+ return;
+ }
+
if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ABORTED)) {
set_host_byte(scpnt, DID_SOFT_ERROR);
set_driver_byte(scpnt, SUGGEST_RETRY);
@@ -2445,8 +2448,10 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_adapter *adapter,
goto out;
req = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND, req_flags,
adapter->pool.fsf_req_scsi);
- if (IS_ERR(req))
+ if (IS_ERR(req)) {
+ req = NULL;
goto out;
+ }
req->status |= ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT;
req->data = unit;
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index ca8f85f3dad..468c880f8b6 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -24,14 +24,10 @@ char *zfcp_get_fcp_sns_info_ptr(struct fcp_rsp_iu *fcp_rsp_iu)
static void zfcp_scsi_slave_destroy(struct scsi_device *sdpnt)
{
struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata;
- WARN_ON(!unit);
- if (unit) {
- atomic_clear_mask(ZFCP_STATUS_UNIT_REGISTERED, &unit->status);
- sdpnt->hostdata = NULL;
- unit->device = NULL;
- zfcp_erp_unit_failed(unit, 12, NULL);
- zfcp_unit_put(unit);
- }
+ atomic_clear_mask(ZFCP_STATUS_UNIT_REGISTERED, &unit->status);
+ unit->device = NULL;
+ zfcp_erp_unit_failed(unit, 12, NULL);
+ zfcp_unit_put(unit);
}
static int zfcp_scsi_slave_configure(struct scsi_device *sdp)
@@ -92,7 +88,7 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
ret = zfcp_fsf_send_fcp_command_task(adapter, unit, scpnt, 0,
ZFCP_REQ_AUTO_CLEANUP);
if (unlikely(ret == -EBUSY))
- zfcp_scsi_command_fail(scpnt, DID_NO_CONNECT);
+ return SCSI_MLQUEUE_DEVICE_BUSY;
else if (unlikely(ret < 0))
return SCSI_MLQUEUE_HOST_BUSY;
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index 9aa301c1ed0..94acbeed4e7 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -175,8 +175,8 @@ static struct aac_driver_ident aac_drivers[] = {
{ aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG | AAC_QUIRK_SCSI_32 }, /* PERC 3/Di (Boxster/PERC3DiB) */
{ aac_rx_init, "aacraid", "ADAPTEC ", "catapult ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG | AAC_QUIRK_SCSI_32 }, /* catapult */
{ aac_rx_init, "aacraid", "ADAPTEC ", "tomcat ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG | AAC_QUIRK_SCSI_32 }, /* tomcat */
- { aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2120S ", 1, AAC_QUIRK_31BIT | AAC_QUIRK_34SG | AAC_QUIRK_SCSI_32 }, /* Adaptec 2120S (Crusader) */
- { aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2200S ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG | AAC_QUIRK_SCSI_32 }, /* Adaptec 2200S (Vulcan) */
+ { aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2120S ", 1, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Adaptec 2120S (Crusader) */
+ { aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2200S ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Adaptec 2200S (Vulcan) */
{ aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2200S ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG | AAC_QUIRK_SCSI_32 }, /* Adaptec 2200S (Vulcan-2m) */
{ aac_rx_init, "aacraid", "Legend ", "Legend S220 ", 1, AAC_QUIRK_31BIT | AAC_QUIRK_34SG | AAC_QUIRK_SCSI_32 }, /* Legend S220 (Legend Crusader) */
{ aac_rx_init, "aacraid", "Legend ", "Legend S230 ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG | AAC_QUIRK_SCSI_32 }, /* Legend S230 (Legend Vulcan) */
@@ -427,8 +427,8 @@ static int aac_slave_configure(struct scsi_device *sdev)
* Firmware has an individual device recovery time typically
* of 35 seconds, give us a margin.
*/
- if (sdev->timeout < (45 * HZ))
- sdev->timeout = 45 * HZ;
+ if (sdev->request_queue->rq_timeout < (45 * HZ))
+ blk_queue_rq_timeout(sdev->request_queue, 45*HZ);
for (cid = 0; cid < aac->maximum_num_containers; ++cid)
if (aac->fsa_dev[cid].valid)
++num_lsu;
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
index 218777bfc14..399fe559e4d 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -13872,8 +13872,10 @@ static int __devinit advansys_board_found(struct Scsi_Host *shost,
advansys_wide_free_mem(boardp);
free_irq(boardp->irq, shost);
err_free_dma:
+#ifdef CONFIG_ISA
if (shost->dma_channel != NO_ISA_DMA)
free_dma(shost->dma_channel);
+#endif
err_free_proc:
kfree(boardp->prtbuf);
err_unmap:
@@ -13894,10 +13896,12 @@ static int advansys_release(struct Scsi_Host *shost)
ASC_DBG(1, "begin\n");
scsi_remove_host(shost);
free_irq(board->irq, shost);
+#ifdef CONFIG_ISA
if (shost->dma_channel != NO_ISA_DMA) {
ASC_DBG(1, "free_dma()\n");
free_dma(shost->dma_channel);
}
+#endif
if (ASC_NARROW_BOARD(board)) {
dma_unmap_single(board->dev,
board->dvc_var.asc_dvc_var.overrun_dma,
diff --git a/drivers/scsi/device_handler/scsi_dh_hp_sw.c b/drivers/scsi/device_handler/scsi_dh_hp_sw.c
index 9aec4ca64e5..f7da7530875 100644
--- a/drivers/scsi/device_handler/scsi_dh_hp_sw.c
+++ b/drivers/scsi/device_handler/scsi_dh_hp_sw.c
@@ -107,6 +107,7 @@ static int hp_sw_tur(struct scsi_device *sdev, struct hp_sw_dh_data *h)
struct request *req;
int ret;
+retry:
req = blk_get_request(sdev->request_queue, WRITE, GFP_NOIO);
if (!req)
return SCSI_DH_RES_TEMP_UNAVAIL;
@@ -121,7 +122,6 @@ static int hp_sw_tur(struct scsi_device *sdev, struct hp_sw_dh_data *h)
memset(req->sense, 0, SCSI_SENSE_BUFFERSIZE);
req->sense_len = 0;
-retry:
ret = blk_execute_rq(req->q, NULL, req, 1);
if (ret == -EIO) {
if (req->sense_len > 0) {
@@ -136,8 +136,10 @@ retry:
h->path_state = HP_SW_PATH_ACTIVE;
ret = SCSI_DH_OK;
}
- if (ret == SCSI_DH_IMM_RETRY)
+ if (ret == SCSI_DH_IMM_RETRY) {
+ blk_put_request(req);
goto retry;
+ }
if (ret == SCSI_DH_DEV_OFFLINED) {
h->path_state = HP_SW_PATH_PASSIVE;
ret = SCSI_DH_OK;
@@ -200,6 +202,7 @@ static int hp_sw_start_stop(struct scsi_device *sdev, struct hp_sw_dh_data *h)
struct request *req;
int ret, retry;
+retry:
req = blk_get_request(sdev->request_queue, WRITE, GFP_NOIO);
if (!req)
return SCSI_DH_RES_TEMP_UNAVAIL;
@@ -216,7 +219,6 @@ static int hp_sw_start_stop(struct scsi_device *sdev, struct hp_sw_dh_data *h)
req->sense_len = 0;
retry = h->retries;
-retry:
ret = blk_execute_rq(req->q, NULL, req, 1);
if (ret == -EIO) {
if (req->sense_len > 0) {
@@ -231,8 +233,10 @@ retry:
ret = SCSI_DH_OK;
if (ret == SCSI_DH_RETRY) {
- if (--retry)
+ if (--retry) {
+ blk_put_request(req);
goto retry;
+ }
ret = SCSI_DH_IO;
}
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index 8aba4fdfb52..6194ed5d02c 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -2445,7 +2445,7 @@ static s32 adpt_i2o_to_scsi(void __iomem *reply, struct scsi_cmnd* cmd)
hba_status = detailed_status >> 8;
// calculate resid for sg
- scsi_set_resid(cmd, scsi_bufflen(cmd) - readl(reply+5));
+ scsi_set_resid(cmd, scsi_bufflen(cmd) - readl(reply+20));
pHba = (adpt_hba*) cmd->device->host->hostdata[0];
@@ -2456,7 +2456,7 @@ static s32 adpt_i2o_to_scsi(void __iomem *reply, struct scsi_cmnd* cmd)
case I2O_SCSI_DSC_SUCCESS:
cmd->result = (DID_OK << 16);
// handle underflow
- if(readl(reply+5) < cmd->underflow ) {
+ if (readl(reply+20) < cmd->underflow) {
cmd->result = (DID_ERROR <<16);
printk(KERN_WARNING"%s: SCSI CMD underflow\n",pHba->name);
}
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index c387c15a212..fb247fdfa2b 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -588,7 +588,7 @@ static struct pci_driver gdth_pci_driver = {
.remove = gdth_pci_remove_one,
};
-static void gdth_pci_remove_one(struct pci_dev *pdev)
+static void __devexit gdth_pci_remove_one(struct pci_dev *pdev)
{
gdth_ha_str *ha = pci_get_drvdata(pdev);
@@ -600,7 +600,7 @@ static void gdth_pci_remove_one(struct pci_dev *pdev)
pci_disable_device(pdev);
}
-static int gdth_pci_init_one(struct pci_dev *pdev,
+static int __devinit gdth_pci_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
ushort vendor = pdev->vendor;
@@ -853,7 +853,7 @@ static int __init gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha)
#endif /* CONFIG_ISA */
#ifdef CONFIG_PCI
-static int gdth_init_pci(struct pci_dev *pdev, gdth_pci_str *pcistr,
+static int __devinit gdth_init_pci(struct pci_dev *pdev, gdth_pci_str *pcistr,
gdth_ha_str *ha)
{
register gdt6_dpram_str __iomem *dp6_ptr;
@@ -1237,7 +1237,7 @@ static int gdth_init_pci(struct pci_dev *pdev, gdth_pci_str *pcistr,
/* controller protocol functions */
-static void __init gdth_enable_int(gdth_ha_str *ha)
+static void __devinit gdth_enable_int(gdth_ha_str *ha)
{
ulong flags;
gdt2_dpram_str __iomem *dp2_ptr;
@@ -1553,7 +1553,7 @@ static int gdth_internal_cmd(gdth_ha_str *ha, unchar service, ushort opcode,
/* search for devices */
-static int __init gdth_search_drives(gdth_ha_str *ha)
+static int __devinit gdth_search_drives(gdth_ha_str *ha)
{
ushort cdev_cnt, i;
int ok;
@@ -4935,7 +4935,7 @@ static int __init gdth_eisa_probe_one(ushort eisa_slot)
#endif /* CONFIG_EISA */
#ifdef CONFIG_PCI
-static int gdth_pci_probe_one(gdth_pci_str *pcistr,
+static int __devinit gdth_pci_probe_one(gdth_pci_str *pcistr,
gdth_ha_str **ha_out)
{
struct Scsi_Host *shp;
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index 87e09f35d3d..6cad1758243 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -1442,7 +1442,7 @@ static int ibmvscsi_slave_configure(struct scsi_device *sdev)
spin_lock_irqsave(shost->host_lock, lock_flags);
if (sdev->type == TYPE_DISK) {
sdev->allow_restart = 1;
- sdev->timeout = 60 * HZ;
+ blk_queue_rq_timeout(sdev->request_queue, 60 * HZ);
}
scsi_adjust_queue_depth(sdev, 0, shost->cmd_per_lun);
spin_unlock_irqrestore(shost->host_lock, lock_flags);
diff --git a/drivers/scsi/ibmvscsi/ibmvstgt.c b/drivers/scsi/ibmvscsi/ibmvstgt.c
index 2a5b29d1217..e2dd6a45924 100644
--- a/drivers/scsi/ibmvscsi/ibmvstgt.c
+++ b/drivers/scsi/ibmvscsi/ibmvstgt.c
@@ -864,21 +864,23 @@ static int ibmvstgt_probe(struct vio_dev *dev, const struct vio_device_id *id)
INIT_WORK(&vport->crq_work, handle_crq);
- err = crq_queue_create(&vport->crq_queue, target);
+ err = scsi_add_host(shost, target->dev);
if (err)
goto free_srp_target;
- err = scsi_add_host(shost, target->dev);
+ err = scsi_tgt_alloc_queue(shost);
if (err)
- goto destroy_queue;
+ goto remove_host;
- err = scsi_tgt_alloc_queue(shost);
+ err = crq_queue_create(&vport->crq_queue, target);
if (err)
- goto destroy_queue;
+ goto free_queue;
return 0;
-destroy_queue:
- crq_queue_destroy(target);
+free_queue:
+ scsi_tgt_free_queue(shost);
+remove_host:
+ scsi_remove_host(shost);
free_srp_target:
srp_target_free(target);
put_host:
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 801c7cf54d2..3fdee7370cc 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -489,12 +489,6 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
if (!__kfifo_get(session->cmdpool.queue,
(void*)&task, sizeof(void*)))
return NULL;
-
- if ((hdr->opcode == (ISCSI_OP_NOOP_OUT | ISCSI_OP_IMMEDIATE)) &&
- hdr->ttt == RESERVED_ITT) {
- conn->ping_task = task;
- conn->last_ping = jiffies;
- }
}
/*
* released in complete pdu for task we expect a response for, and
@@ -703,6 +697,11 @@ static void iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr)
task = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)&hdr, NULL, 0);
if (!task)
iscsi_conn_printk(KERN_ERR, conn, "Could not send nopout\n");
+ else if (!rhdr) {
+ /* only track our nops */
+ conn->ping_task = task;
+ conn->last_ping = jiffies;
+ }
}
static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index 28c9da7d4a5..7dc62deb408 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -4402,6 +4402,10 @@ mega_internal_command(adapter_t *adapter, megacmd_t *mc, mega_passthru *pthru)
scb_t *scb;
int rval;
+ scmd = scsi_allocate_command(GFP_KERNEL);
+ if (!scmd)
+ return -ENOMEM;
+
/*
* The internal commands share one command id and hence are
* serialized. This is so because we want to reserve maximum number of
@@ -4412,12 +4416,11 @@ mega_internal_command(adapter_t *adapter, megacmd_t *mc, mega_passthru *pthru)
scb = &adapter->int_scb;
memset(scb, 0, sizeof(scb_t));
- scmd = &adapter->int_scmd;
- memset(scmd, 0, sizeof(Scsi_Cmnd));
-
sdev = kzalloc(sizeof(struct scsi_device), GFP_KERNEL);
scmd->device = sdev;
+ memset(adapter->int_cdb, 0, sizeof(adapter->int_cdb));
+ scmd->cmnd = adapter->int_cdb;
scmd->device->host = adapter->host;
scmd->host_scribble = (void *)scb;
scmd->cmnd[0] = MEGA_INTERNAL_CMD;
@@ -4456,6 +4459,8 @@ mega_internal_command(adapter_t *adapter, megacmd_t *mc, mega_passthru *pthru)
mutex_unlock(&adapter->int_mtx);
+ scsi_free_command(GFP_KERNEL, scmd);
+
return rval;
}
diff --git a/drivers/scsi/megaraid.h b/drivers/scsi/megaraid.h
index ee70bd4ae4b..795201fa0b4 100644
--- a/drivers/scsi/megaraid.h
+++ b/drivers/scsi/megaraid.h
@@ -888,8 +888,8 @@ typedef struct {
u8 sglen; /* f/w supported scatter-gather list length */
+ unsigned char int_cdb[MAX_COMMAND_SIZE];
scb_t int_scb;
- Scsi_Cmnd int_scmd;
struct mutex int_mtx; /* To synchronize the internal
commands */
struct completion int_waitq; /* wait queue for internal
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
index a454f94623d..17ce7abe17e 100644
--- a/drivers/scsi/megaraid/megaraid_sas.c
+++ b/drivers/scsi/megaraid/megaraid_sas.c
@@ -1016,7 +1016,8 @@ static int megasas_slave_configure(struct scsi_device *sdev)
* The RAID firmware may require extended timeouts.
*/
if (sdev->channel >= MEGASAS_MAX_PD_CHANNELS)
- sdev->timeout = MEGASAS_DEFAULT_CMD_TIMEOUT * HZ;
+ blk_queue_rq_timeout(sdev->request_queue,
+ MEGASAS_DEFAULT_CMD_TIMEOUT * HZ);
return 0;
}
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index f25f41a499e..b97194096d8 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2547,7 +2547,6 @@ typedef struct scsi_qla_host {
uint8_t fcode_revision[16];
uint32_t fw_revision[4];
- uint16_t fdt_odd_index;
uint32_t fdt_wrt_disable;
uint32_t fdt_erase_cmd;
uint32_t fdt_block_size;
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index a470f2d3270..4218f20f5ed 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -140,7 +140,6 @@ int
qla2100_pci_config(scsi_qla_host_t *ha)
{
uint16_t w;
- uint32_t d;
unsigned long flags;
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
@@ -151,10 +150,7 @@ qla2100_pci_config(scsi_qla_host_t *ha)
w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
pci_write_config_word(ha->pdev, PCI_COMMAND, w);
- /* Reset expansion ROM address decode enable */
- pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d);
- d &= ~PCI_ROM_ADDRESS_ENABLE;
- pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d);
+ pci_disable_rom(ha->pdev);
/* Get PCI bus information. */
spin_lock_irqsave(&ha->hardware_lock, flags);
@@ -174,7 +170,6 @@ int
qla2300_pci_config(scsi_qla_host_t *ha)
{
uint16_t w;
- uint32_t d;
unsigned long flags = 0;
uint32_t cnt;
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
@@ -236,10 +231,7 @@ qla2300_pci_config(scsi_qla_host_t *ha)
pci_write_config_byte(ha->pdev, PCI_LATENCY_TIMER, 0x80);
- /* Reset expansion ROM address decode enable */
- pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d);
- d &= ~PCI_ROM_ADDRESS_ENABLE;
- pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d);
+ pci_disable_rom(ha->pdev);
/* Get PCI bus information. */
spin_lock_irqsave(&ha->hardware_lock, flags);
@@ -259,7 +251,6 @@ int
qla24xx_pci_config(scsi_qla_host_t *ha)
{
uint16_t w;
- uint32_t d;
unsigned long flags = 0;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
@@ -281,10 +272,7 @@ qla24xx_pci_config(scsi_qla_host_t *ha)
if (pci_find_capability(ha->pdev, PCI_CAP_ID_EXP))
pcie_set_readrq(ha->pdev, 2048);
- /* Reset expansion ROM address decode enable */
- pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d);
- d &= ~PCI_ROM_ADDRESS_ENABLE;
- pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d);
+ pci_disable_rom(ha->pdev);
ha->chip_revision = ha->pdev->revision;
@@ -306,7 +294,6 @@ int
qla25xx_pci_config(scsi_qla_host_t *ha)
{
uint16_t w;
- uint32_t d;
pci_set_master(ha->pdev);
pci_try_set_mwi(ha->pdev);
@@ -320,10 +307,7 @@ qla25xx_pci_config(scsi_qla_host_t *ha)
if (pci_find_capability(ha->pdev, PCI_CAP_ID_EXP))
pcie_set_readrq(ha->pdev, 2048);
- /* Reset expansion ROM address decode enable */
- pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d);
- d &= ~PCI_ROM_ADDRESS_ENABLE;
- pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d);
+ pci_disable_rom(ha->pdev);
ha->chip_revision = ha->pdev->revision;
@@ -980,7 +964,6 @@ qla2x00_setup_chip(scsi_qla_host_t *ha)
&ha->fw_minor_version,
&ha->fw_subminor_version,
&ha->fw_attributes, &ha->fw_memory_size);
- qla2x00_resize_request_q(ha);
ha->flags.npiv_supported = 0;
if ((IS_QLA24XX(ha) || IS_QLA25XX(ha) ||
IS_QLA84XX(ha)) &&
@@ -992,6 +975,7 @@ qla2x00_setup_chip(scsi_qla_host_t *ha)
ha->max_npiv_vports =
MIN_MULTI_ID_FABRIC - 1;
}
+ qla2x00_resize_request_q(ha);
if (ql2xallocfwdump)
qla2x00_alloc_fw_dump(ha);
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 36bc6851e23..3402746ec12 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -1964,7 +1964,7 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *ha, uint16_t *cur_xchg_cnt,
*cur_iocb_cnt = mcp->mb[7];
if (orig_iocb_cnt)
*orig_iocb_cnt = mcp->mb[10];
- if (max_npiv_vports)
+ if (ha->flags.npiv_supported && max_npiv_vports)
*max_npiv_vports = mcp->mb[11];
}
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 21dd182ad51..35567203ef6 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -728,6 +728,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
if (ha->isp_ops->abort_command(ha, sp)) {
DEBUG2(printk("%s(%ld): abort_command "
"mbx failed.\n", __func__, ha->host_no));
+ ret = FAILED;
} else {
DEBUG3(printk("%s(%ld): abort_command "
"mbx success.\n", __func__, ha->host_no));
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c
index 90a13211717..e4af678eb2d 100644
--- a/drivers/scsi/qla2xxx/qla_sup.c
+++ b/drivers/scsi/qla2xxx/qla_sup.c
@@ -722,6 +722,7 @@ done:
static void
qla2xxx_get_fdt_info(scsi_qla_host_t *ha)
{
+#define FLASH_BLK_SIZE_4K 0x1000
#define FLASH_BLK_SIZE_32K 0x8000
#define FLASH_BLK_SIZE_64K 0x10000
const char *loc, *locations[] = { "MID", "FDT" };
@@ -755,7 +756,6 @@ qla2xxx_get_fdt_info(scsi_qla_host_t *ha)
loc = locations[1];
mid = le16_to_cpu(fdt->man_id);
fid = le16_to_cpu(fdt->id);
- ha->fdt_odd_index = mid == 0x1f;
ha->fdt_wrt_disable = fdt->wrt_disable_bits;
ha->fdt_erase_cmd = flash_conf_to_access_addr(0x0300 | fdt->erase_cmd);
ha->fdt_block_size = le32_to_cpu(fdt->block_size);
@@ -788,8 +788,7 @@ no_flash_data:
ha->fdt_block_size = FLASH_BLK_SIZE_64K;
break;
case 0x1f: /* Atmel 26DF081A. */
- ha->fdt_odd_index = 1;
- ha->fdt_block_size = FLASH_BLK_SIZE_64K;
+ ha->fdt_block_size = FLASH_BLK_SIZE_4K;
ha->fdt_erase_cmd = flash_conf_to_access_addr(0x0320);
ha->fdt_unprotect_sec_cmd = flash_conf_to_access_addr(0x0339);
ha->fdt_protect_sec_cmd = flash_conf_to_access_addr(0x0336);
@@ -801,9 +800,9 @@ no_flash_data:
}
done:
DEBUG2(qla_printk(KERN_DEBUG, ha, "FDT[%s]: (0x%x/0x%x) erase=0x%x "
- "pro=%x upro=%x idx=%d wrtd=0x%x blk=0x%x.\n", loc, mid, fid,
+ "pro=%x upro=%x wrtd=0x%x blk=0x%x.\n", loc, mid, fid,
ha->fdt_erase_cmd, ha->fdt_protect_sec_cmd,
- ha->fdt_unprotect_sec_cmd, ha->fdt_odd_index, ha->fdt_wrt_disable,
+ ha->fdt_unprotect_sec_cmd, ha->fdt_wrt_disable,
ha->fdt_block_size));
}
@@ -987,13 +986,9 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
qla24xx_unprotect_flash(ha);
for (liter = 0; liter < dwords; liter++, faddr++, dwptr++) {
- if (ha->fdt_odd_index) {
- findex = faddr << 2;
- fdata = findex & sec_mask;
- } else {
- findex = faddr;
- fdata = (findex & sec_mask) << 2;
- }
+
+ findex = faddr;
+ fdata = (findex & sec_mask) << 2;
/* Are we at the beginning of a sector? */
if ((findex & rest_addr) == 0) {
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
index be5e299df52..eea6720adf1 100644
--- a/drivers/scsi/qla2xxx/qla_version.h
+++ b/drivers/scsi/qla2xxx/qla_version.h
@@ -7,7 +7,7 @@
/*
* Driver version
*/
-#define QLA2XXX_VERSION "8.02.01-k8"
+#define QLA2XXX_VERSION "8.02.01-k9"
#define QLA_DRIVER_MAJOR_VER 8
#define QLA_DRIVER_MINOR_VER 2
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 94ed262bdf0..edfaf241c5b 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -932,8 +932,7 @@ static int scsi_eh_try_stu(struct scsi_cmnd *scmd)
int i, rtn = NEEDS_RETRY;
for (i = 0; rtn == NEEDS_RETRY && i < 2; i++)
- rtn = scsi_send_eh_cmnd(scmd, stu_command, 6,
- scmd->device->timeout, 0);
+ rtn = scsi_send_eh_cmnd(scmd, stu_command, 6, scmd->device->request_queue->rq_timeout, 0);
if (rtn == SUCCESS)
return 0;
@@ -1340,9 +1339,10 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd)
* LLD/transport was disrupted during processing of the IO.
* The transport class is now blocked/blocking,
* and the transport will decide what to do with the IO
- * based on its timers and recovery capablilities.
+ * based on its timers and recovery capablilities if
+ * there are enough retries.
*/
- return ADD_TO_MLQUEUE;
+ goto maybe_retry;
case DID_TRANSPORT_FAILFAST:
/*
* The transport decided to failfast the IO (most likely
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index f5d3b96890d..148d3af92ae 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -567,15 +567,18 @@ static inline int scsi_host_is_busy(struct Scsi_Host *shost)
*/
static void scsi_run_queue(struct request_queue *q)
{
- struct scsi_device *starved_head = NULL, *sdev = q->queuedata;
+ struct scsi_device *sdev = q->queuedata;
struct Scsi_Host *shost = sdev->host;
+ LIST_HEAD(starved_list);
unsigned long flags;
if (scsi_target(sdev)->single_lun)
scsi_single_lun_run(sdev);
spin_lock_irqsave(shost->host_lock, flags);
- while (!list_empty(&shost->starved_list) && !scsi_host_is_busy(shost)) {
+ list_splice_init(&shost->starved_list, &starved_list);
+
+ while (!list_empty(&starved_list)) {
int flagset;
/*
@@ -588,24 +591,18 @@ static void scsi_run_queue(struct request_queue *q)
* scsi_request_fn must get the host_lock before checking
* or modifying starved_list or starved_entry.
*/
- sdev = list_entry(shost->starved_list.next,
- struct scsi_device, starved_entry);
- /*
- * The *queue_ready functions can add a device back onto the
- * starved list's tail, so we must check for a infinite loop.
- */
- if (sdev == starved_head)
+ if (scsi_host_is_busy(shost))
break;
- if (!starved_head)
- starved_head = sdev;
+ sdev = list_entry(starved_list.next,
+ struct scsi_device, starved_entry);
+ list_del_init(&sdev->starved_entry);
if (scsi_target_is_busy(scsi_target(sdev))) {
list_move_tail(&sdev->starved_entry,
&shost->starved_list);
continue;
}
- list_del_init(&sdev->starved_entry);
spin_unlock(shost->host_lock);
spin_lock(sdev->request_queue->queue_lock);
@@ -621,6 +618,8 @@ static void scsi_run_queue(struct request_queue *q)
spin_lock(shost->host_lock);
}
+ /* put any unprocessed entries back */
+ list_splice(&starved_list, &shost->starved_list);
spin_unlock_irqrestore(shost->host_lock, flags);
blk_run_queue(q);
@@ -649,8 +648,8 @@ static void scsi_requeue_command(struct request_queue *q, struct scsi_cmnd *cmd)
struct request *req = cmd->request;
unsigned long flags;
- scsi_unprep_request(req);
spin_lock_irqsave(q->queue_lock, flags);
+ scsi_unprep_request(req);
blk_requeue_request(q, req);
spin_unlock_irqrestore(q->queue_lock, flags);
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index c9e1242eaf2..5081b3981d3 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -757,7 +757,7 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode,
* access to the device is prohibited.
*/
error = scsi_nonblockable_ioctl(sdp, cmd, p,
- (mode & FMODE_NDELAY_NOW) != 0);
+ (mode & FMODE_NDELAY) != 0);
if (!scsi_block_when_processing_errors(sdp) || !error)
return error;
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index 62b6633e3a9..45b66b98a51 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -521,7 +521,7 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
* if it doesn't recognise the ioctl
*/
ret = scsi_nonblockable_ioctl(sdev, cmd, argp,
- (mode & FMODE_NDELAY_NOW) != 0);
+ (mode & FMODE_NDELAY) != 0);
if (ret != -ENODEV)
return ret;
return scsi_ioctl(sdev, cmd, argp);
diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c
index 3790906a77d..2fa830c0be2 100644
--- a/drivers/scsi/stex.c
+++ b/drivers/scsi/stex.c
@@ -477,7 +477,7 @@ stex_slave_config(struct scsi_device *sdev)
{
sdev->use_10_for_rw = 1;
sdev->use_10_for_ms = 1;
- sdev->timeout = 60 * HZ;
+ blk_queue_rq_timeout(sdev->request_queue, 60 * HZ);
sdev->tagged_supported = 1;
return 0;
diff --git a/drivers/serial/ioc3_serial.c b/drivers/serial/ioc3_serial.c
index 6dd98f9fb89..ae3699d77dd 100644
--- a/drivers/serial/ioc3_serial.c
+++ b/drivers/serial/ioc3_serial.c
@@ -2149,7 +2149,7 @@ out4:
return ret;
}
-static struct ioc3_submodule ioc3uart_submodule = {
+static struct ioc3_submodule ioc3uart_ops = {
.name = "IOC3uart",
.probe = ioc3uart_probe,
.remove = ioc3uart_remove,
@@ -2173,7 +2173,7 @@ static int __devinit ioc3uart_init(void)
__func__);
return ret;
}
- ret = ioc3_register_submodule(&ioc3uart_submodule);
+ ret = ioc3_register_submodule(&ioc3uart_ops);
if (ret)
uart_unregister_driver(&ioc3_uart);
return ret;
@@ -2181,7 +2181,7 @@ static int __devinit ioc3uart_init(void)
static void __devexit ioc3uart_exit(void)
{
- ioc3_unregister_submodule(&ioc3uart_submodule);
+ ioc3_unregister_submodule(&ioc3uart_ops);
uart_unregister_driver(&ioc3_uart);
}
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c
index 6117d3db0b6..28c00c3d58f 100644
--- a/drivers/serial/mpc52xx_uart.c
+++ b/drivers/serial/mpc52xx_uart.c
@@ -591,8 +591,8 @@ mpc52xx_uart_set_termios(struct uart_port *port, struct ktermios *new,
/* Update the per-port timeout */
uart_update_timeout(port, new->c_cflag, baud);
- /* Do our best to flush TX & RX, so we don't loose anything */
- /* But we don't wait indefinitly ! */
+ /* Do our best to flush TX & RX, so we don't lose anything */
+ /* But we don't wait indefinitely ! */
j = 5000000; /* Maximum wait */
/* FIXME Can't receive chars since set_termios might be called at early
* boot for the console, all stuff is not yet ready to receive at that
diff --git a/drivers/serial/s3c2440.c b/drivers/serial/s3c2440.c
index 317d239ab74..29cbb0afef8 100644
--- a/drivers/serial/s3c2440.c
+++ b/drivers/serial/s3c2440.c
@@ -177,5 +177,5 @@ module_exit(s3c2440_serial_exit);
MODULE_DESCRIPTION("Samsung S3C2440,S3C2442 SoC Serial port driver");
MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
-MODULE_LICENSE("GPLi v2");
+MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:s3c2440-uart");
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c
index 5c0f32c7fbf..165fc010978 100644
--- a/drivers/serial/sh-sci.c
+++ b/drivers/serial/sh-sci.c
@@ -144,9 +144,9 @@ static void put_char(struct uart_port *port, char c)
status = sci_in(port, SCxSR);
} while (!(status & SCxSR_TDxE(port)));
- sci_out(port, SCxTDR, c);
sci_in(port, SCxSR); /* Dummy read */
sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port));
+ sci_out(port, SCxTDR, c);
spin_unlock_irqrestore(&port->lock, flags);
}
@@ -478,10 +478,10 @@ static void sci_transmit_chars(struct uart_port *port)
return;
}
- if (port->type == PORT_SCIF)
- count = scif_txroom(port);
- else
+ if (port->type == PORT_SCI)
count = sci_txroom(port);
+ else
+ count = scif_txroom(port);
do {
unsigned char c;
@@ -510,7 +510,7 @@ static void sci_transmit_chars(struct uart_port *port)
} else {
ctrl = sci_in(port, SCSCR);
- if (port->type == PORT_SCIF) {
+ if (port->type != PORT_SCI) {
sci_in(port, SCxSR); /* Dummy read */
sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port));
}
@@ -536,10 +536,10 @@ static inline void sci_receive_chars(struct uart_port *port)
return;
while (1) {
- if (port->type == PORT_SCIF)
- count = scif_rxroom(port);
- else
+ if (port->type == PORT_SCI)
count = sci_rxroom(port);
+ else
+ count = scif_rxroom(port);
/* Don't copy more bytes than there is room for in the buffer */
count = tty_buffer_request_room(tty, count);
@@ -714,7 +714,7 @@ static inline int sci_handle_breaks(struct uart_port *port)
#if defined(SCIF_ORER)
/* XXX: Handle SCIF overrun error */
- if (port->type == PORT_SCIF && (sci_in(port, SCLSR) & SCIF_ORER) != 0) {
+ if (port->type != PORT_SCI && (sci_in(port, SCLSR) & SCIF_ORER) != 0) {
sci_out(port, SCLSR, 0);
if (tty_insert_flip_char(tty, 0, TTY_OVERRUN)) {
copied++;
@@ -1042,7 +1042,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
sci_out(port, SCSCR, 0x00); /* TE=0, RE=0, CKE1=0 */
- if (port->type == PORT_SCIF)
+ if (port->type != PORT_SCI)
sci_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST);
smr_val = sci_in(port, SCSMR) & 3;
@@ -1085,6 +1085,7 @@ static const char *sci_type(struct uart_port *port)
case PORT_SCI: return "sci";
case PORT_SCIF: return "scif";
case PORT_IRDA: return "irda";
+ case PORT_SCIFA: return "scifa";
}
return NULL;
@@ -1112,6 +1113,7 @@ static void sci_config_port(struct uart_port *port, int flags)
s->init_pins = sci_init_pins_sci;
break;
case PORT_SCIF:
+ case PORT_SCIFA:
s->init_pins = sci_init_pins_scif;
break;
case PORT_IRDA:
diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h
index 6163a45f968..9f33b064172 100644
--- a/drivers/serial/sh-sci.h
+++ b/drivers/serial/sh-sci.h
@@ -289,18 +289,18 @@
#define CPU_SCIx_FNS(name, sci_offset, sci_size, scif_offset, scif_size)\
static inline unsigned int sci_##name##_in(struct uart_port *port) \
{ \
- if (port->type == PORT_SCI) { \
- SCI_IN(sci_size, sci_offset) \
- } else { \
- SCI_IN(scif_size, scif_offset); \
+ if (port->type == PORT_SCIF) { \
+ SCI_IN(scif_size, scif_offset) \
+ } else { /* PORT_SCI or PORT_SCIFA */ \
+ SCI_IN(sci_size, sci_offset); \
} \
} \
static inline void sci_##name##_out(struct uart_port *port, unsigned int value) \
{ \
- if (port->type == PORT_SCI) { \
- SCI_OUT(sci_size, sci_offset, value) \
- } else { \
- SCI_OUT(scif_size, scif_offset, value); \
+ if (port->type == PORT_SCIF) { \
+ SCI_OUT(scif_size, scif_offset, value) \
+ } else { /* PORT_SCI or PORT_SCIFA */ \
+ SCI_OUT(sci_size, sci_offset, value); \
} \
}
diff --git a/drivers/serial/uartlite.c b/drivers/serial/uartlite.c
index 6a3f8fb0c9d..3317148a4b9 100644
--- a/drivers/serial/uartlite.c
+++ b/drivers/serial/uartlite.c
@@ -286,8 +286,8 @@ static void ulite_release_port(struct uart_port *port)
static int ulite_request_port(struct uart_port *port)
{
- pr_debug("ulite console: port=%p; port->mapbase=%x\n",
- port, port->mapbase);
+ pr_debug("ulite console: port=%p; port->mapbase=%llx\n",
+ port, (unsigned long long) port->mapbase);
if (!request_mem_region(port->mapbase, ULITE_REGION, "uartlite")) {
dev_err(port->dev, "Memory region busy\n");
diff --git a/drivers/sh/maple/maple.c b/drivers/sh/maple/maple.c
index d1812d32f47..63f0de29aa1 100644
--- a/drivers/sh/maple/maple.c
+++ b/drivers/sh/maple/maple.c
@@ -827,7 +827,7 @@ static int __init maple_bus_init(void)
maple_queue_cache =
kmem_cache_create("maple_queue_cache", 0x400, 0,
- SLAB_POISON|SLAB_HWCACHE_ALIGN, NULL);
+ SLAB_HWCACHE_ALIGN, NULL);
if (!maple_queue_cache)
goto cleanup_bothirqs;
diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c
index 02f9320f3ef..8abae4ad0fa 100644
--- a/drivers/spi/atmel_spi.c
+++ b/drivers/spi/atmel_spi.c
@@ -766,6 +766,7 @@ static int __init atmel_spi_probe(struct platform_device *pdev)
/* Initialize the hardware */
clk_enable(clk);
spi_writel(as, CR, SPI_BIT(SWRST));
+ spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */
spi_writel(as, MR, SPI_BIT(MSTR) | SPI_BIT(MODFDIS));
spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS));
spi_writel(as, CR, SPI_BIT(SPIEN));
@@ -782,6 +783,7 @@ static int __init atmel_spi_probe(struct platform_device *pdev)
out_reset_hw:
spi_writel(as, CR, SPI_BIT(SWRST));
+ spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */
clk_disable(clk);
free_irq(irq, master);
out_unmap_regs:
@@ -805,6 +807,7 @@ static int __exit atmel_spi_remove(struct platform_device *pdev)
spin_lock_irq(&as->lock);
as->stopping = 1;
spi_writel(as, CR, SPI_BIT(SWRST));
+ spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */
spi_readl(as, SR);
spin_unlock_irq(&as->lock);
diff --git a/drivers/spi/au1550_spi.c b/drivers/spi/au1550_spi.c
index 87b73e0169c..b02f25c702f 100644
--- a/drivers/spi/au1550_spi.c
+++ b/drivers/spi/au1550_spi.c
@@ -369,10 +369,23 @@ static int au1550_spi_dma_txrxb(struct spi_device *spi, struct spi_transfer *t)
dma_rx_addr = t->rx_dma;
/*
- * check if buffers are already dma mapped, map them otherwise
+ * check if buffers are already dma mapped, map them otherwise:
+ * - first map the TX buffer, so cache data gets written to memory
+ * - then map the RX buffer, so that cache entries (with
+ * soon-to-be-stale data) get removed
* use rx buffer in place of tx if tx buffer was not provided
* use temp rx buffer (preallocated or realloc to fit) for rx dma
*/
+ if (t->tx_buf) {
+ if (t->tx_dma == 0) { /* if DMA_ADDR_INVALID, map it */
+ dma_tx_addr = dma_map_single(hw->dev,
+ (void *)t->tx_buf,
+ t->len, DMA_TO_DEVICE);
+ if (dma_mapping_error(hw->dev, dma_tx_addr))
+ dev_err(hw->dev, "tx dma map error\n");
+ }
+ }
+
if (t->rx_buf) {
if (t->rx_dma == 0) { /* if DMA_ADDR_INVALID, map it */
dma_rx_addr = dma_map_single(hw->dev,
@@ -396,15 +409,8 @@ static int au1550_spi_dma_txrxb(struct spi_device *spi, struct spi_transfer *t)
dma_sync_single_for_device(hw->dev, dma_rx_addr,
t->len, DMA_FROM_DEVICE);
}
- if (t->tx_buf) {
- if (t->tx_dma == 0) { /* if DMA_ADDR_INVALID, map it */
- dma_tx_addr = dma_map_single(hw->dev,
- (void *)t->tx_buf,
- t->len, DMA_TO_DEVICE);
- if (dma_mapping_error(hw->dev, dma_tx_addr))
- dev_err(hw->dev, "tx dma map error\n");
- }
- } else {
+
+ if (!t->tx_buf) {
dma_sync_single_for_device(hw->dev, dma_rx_addr,
t->len, DMA_BIDIRECTIONAL);
hw->tx = hw->rx;
diff --git a/drivers/spi/mpc52xx_psc_spi.c b/drivers/spi/mpc52xx_psc_spi.c
index 0debe11b67b..3b97803e1d1 100644
--- a/drivers/spi/mpc52xx_psc_spi.c
+++ b/drivers/spi/mpc52xx_psc_spi.c
@@ -142,6 +142,7 @@ static int mpc52xx_psc_spi_transfer_rxtx(struct spi_device *spi,
unsigned rfalarm;
unsigned send_at_once = MPC52xx_PSC_BUFSIZE;
unsigned recv_at_once;
+ int last_block = 0;
if (!t->tx_buf && !t->rx_buf && t->len)
return -EINVAL;
@@ -151,15 +152,17 @@ static int mpc52xx_psc_spi_transfer_rxtx(struct spi_device *spi,
while (rb < t->len) {
if (t->len - rb > MPC52xx_PSC_BUFSIZE) {
rfalarm = MPC52xx_PSC_RFALARM;
+ last_block = 0;
} else {
send_at_once = t->len - sb;
rfalarm = MPC52xx_PSC_BUFSIZE - (t->len - rb);
+ last_block = 1;
}
dev_dbg(&spi->dev, "send %d bytes...\n", send_at_once);
for (; send_at_once; sb++, send_at_once--) {
/* set EOF flag before the last word is sent */
- if (send_at_once == 1)
+ if (send_at_once == 1 && last_block)
out_8(&psc->ircr2, 0x01);
if (tx_buf)
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c
index dae87b1a4c6..cf12f2d84be 100644
--- a/drivers/spi/pxa2xx_spi.c
+++ b/drivers/spi/pxa2xx_spi.c
@@ -352,21 +352,21 @@ static int map_dma_buffers(struct driver_data *drv_data)
} else
drv_data->tx_map_len = drv_data->len;
- /* Stream map the rx buffer */
- drv_data->rx_dma = dma_map_single(dev, drv_data->rx,
- drv_data->rx_map_len,
- DMA_FROM_DEVICE);
- if (dma_mapping_error(dev, drv_data->rx_dma))
- return 0;
-
- /* Stream map the tx buffer */
+ /* Stream map the tx buffer. Always do DMA_TO_DEVICE first
+ * so we flush the cache *before* invalidating it, in case
+ * the tx and rx buffers overlap.
+ */
drv_data->tx_dma = dma_map_single(dev, drv_data->tx,
- drv_data->tx_map_len,
- DMA_TO_DEVICE);
+ drv_data->tx_map_len, DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, drv_data->tx_dma))
+ return 0;
- if (dma_mapping_error(dev, drv_data->tx_dma)) {
- dma_unmap_single(dev, drv_data->rx_dma,
+ /* Stream map the rx buffer */
+ drv_data->rx_dma = dma_map_single(dev, drv_data->rx,
drv_data->rx_map_len, DMA_FROM_DEVICE);
+ if (dma_mapping_error(dev, drv_data->rx_dma)) {
+ dma_unmap_single(dev, drv_data->tx_dma,
+ drv_data->tx_map_len, DMA_TO_DEVICE);
return 0;
}
diff --git a/drivers/spi/spi_imx.c b/drivers/spi/spi_imx.c
index 61ba147e384..269a55ec52e 100644
--- a/drivers/spi/spi_imx.c
+++ b/drivers/spi/spi_imx.c
@@ -506,20 +506,6 @@ static int map_dma_buffers(struct driver_data *drv_data)
if (!IS_DMA_ALIGNED(drv_data->rx) || !IS_DMA_ALIGNED(drv_data->tx))
return -1;
- /* NULL rx means write-only transfer and no map needed
- since rx DMA will not be used */
- if (drv_data->rx) {
- buf = drv_data->rx;
- drv_data->rx_dma = dma_map_single(
- dev,
- buf,
- drv_data->len,
- DMA_FROM_DEVICE);
- if (dma_mapping_error(dev, drv_data->rx_dma))
- return -1;
- drv_data->rx_dma_needs_unmap = 1;
- }
-
if (drv_data->tx == NULL) {
/* Read only message --> use drv_data->dummy_dma_buf for dummy
writes to achive reads */
@@ -533,18 +519,31 @@ static int map_dma_buffers(struct driver_data *drv_data)
buf,
drv_data->tx_map_len,
DMA_TO_DEVICE);
- if (dma_mapping_error(dev, drv_data->tx_dma)) {
- if (drv_data->rx_dma) {
- dma_unmap_single(dev,
- drv_data->rx_dma,
- drv_data->len,
- DMA_FROM_DEVICE);
- drv_data->rx_dma_needs_unmap = 0;
- }
+ if (dma_mapping_error(dev, drv_data->tx_dma))
return -1;
- }
drv_data->tx_dma_needs_unmap = 1;
+ /* NULL rx means write-only transfer and no map needed
+ * since rx DMA will not be used */
+ if (drv_data->rx) {
+ buf = drv_data->rx;
+ drv_data->rx_dma = dma_map_single(dev,
+ buf,
+ drv_data->len,
+ DMA_FROM_DEVICE);
+ if (dma_mapping_error(dev, drv_data->rx_dma)) {
+ if (drv_data->tx_dma) {
+ dma_unmap_single(dev,
+ drv_data->tx_dma,
+ drv_data->tx_map_len,
+ DMA_TO_DEVICE);
+ drv_data->tx_dma_needs_unmap = 0;
+ }
+ return -1;
+ }
+ drv_data->rx_dma_needs_unmap = 1;
+ }
+
return 0;
}
@@ -1457,7 +1456,7 @@ static int __init spi_imx_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct spi_imx_master *platform_info;
struct spi_master *master;
- struct driver_data *drv_data = NULL;
+ struct driver_data *drv_data;
struct resource *res;
int irq, status = 0;
@@ -1468,14 +1467,6 @@ static int __init spi_imx_probe(struct platform_device *pdev)
goto err_no_pdata;
}
- drv_data->clk = clk_get(&pdev->dev, "perclk2");
- if (IS_ERR(drv_data->clk)) {
- dev_err(&pdev->dev, "probe - cannot get get\n");
- status = PTR_ERR(drv_data->clk);
- goto err_no_clk;
- }
- clk_enable(drv_data->clk);
-
/* Allocate master with space for drv_data */
master = spi_alloc_master(dev, sizeof(struct driver_data));
if (!master) {
@@ -1496,6 +1487,14 @@ static int __init spi_imx_probe(struct platform_device *pdev)
drv_data->dummy_dma_buf = SPI_DUMMY_u32;
+ drv_data->clk = clk_get(&pdev->dev, "perclk2");
+ if (IS_ERR(drv_data->clk)) {
+ dev_err(&pdev->dev, "probe - cannot get clock\n");
+ status = PTR_ERR(drv_data->clk);
+ goto err_no_clk;
+ }
+ clk_enable(drv_data->clk);
+
/* Find and map resources */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
@@ -1631,12 +1630,13 @@ err_no_iomap:
kfree(drv_data->ioarea);
err_no_iores:
- spi_master_put(master);
-
-err_no_pdata:
clk_disable(drv_data->clk);
clk_put(drv_data->clk);
+
err_no_clk:
+ spi_master_put(master);
+
+err_no_pdata:
err_no_mem:
return status;
}
diff --git a/drivers/spi/spi_s3c24xx_gpio.c b/drivers/spi/spi_s3c24xx_gpio.c
index cc1f647f579..f2447a5476b 100644
--- a/drivers/spi/spi_s3c24xx_gpio.c
+++ b/drivers/spi/spi_s3c24xx_gpio.c
@@ -34,7 +34,7 @@ struct s3c2410_spigpio {
static inline struct s3c2410_spigpio *spidev_to_sg(struct spi_device *spi)
{
- return spi->controller_data;
+ return spi_master_get_devdata(spi->master);
}
static inline void setsck(struct spi_device *dev, int on)
@@ -118,6 +118,7 @@ static int s3c2410_spigpio_probe(struct platform_device *dev)
/* setup spi bitbang adaptor */
sp->bitbang.master = spi_master_get(master);
sp->bitbang.master->bus_num = info->bus_num;
+ sp->bitbang.master->num_chipselect = info->num_chipselect;
sp->bitbang.chipselect = s3c2410_spigpio_chipselect;
sp->bitbang.txrx_word[SPI_MODE_0] = s3c2410_spigpio_txrx_mode0;
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index 89a43755a45..5d869c4d3eb 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -597,7 +597,9 @@ static int spidev_probe(struct spi_device *spi)
}
mutex_unlock(&device_list_lock);
- if (status != 0)
+ if (status == 0)
+ spi_set_drvdata(spi, spidev);
+ else
kfree(spidev);
return status;
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index c95b286a123..5d457c96bd7 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -22,6 +22,8 @@ menuconfig STAGING
If in doubt, say N here.
+if STAGING
+
config STAGING_EXCLUDE_BUILD
bool "Exclude Staging drivers from being built" if STAGING
default y
@@ -62,3 +64,4 @@ source "drivers/staging/at76_usb/Kconfig"
source "drivers/staging/poch/Kconfig"
endif # !STAGING_EXCLUDE_BUILD
+endif # STAGING
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 20104443081..d50a99f70ae 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -158,16 +158,12 @@ static int acm_wb_is_avail(struct acm *acm)
}
/*
- * Finish write.
+ * Finish write. Caller must hold acm->write_lock
*/
static void acm_write_done(struct acm *acm, struct acm_wb *wb)
{
- unsigned long flags;
-
- spin_lock_irqsave(&acm->write_lock, flags);
wb->use = 0;
acm->transmitting--;
- spin_unlock_irqrestore(&acm->write_lock, flags);
}
/*
@@ -482,6 +478,7 @@ static void acm_write_bulk(struct urb *urb)
{
struct acm_wb *wb = urb->context;
struct acm *acm = wb->instance;
+ unsigned long flags;
if (verbose || urb->status
|| (urb->actual_length != urb->transfer_buffer_length))
@@ -490,7 +487,9 @@ static void acm_write_bulk(struct urb *urb)
urb->transfer_buffer_length,
urb->status);
+ spin_lock_irqsave(&acm->write_lock, flags);
acm_write_done(acm, wb);
+ spin_unlock_irqrestore(&acm->write_lock, flags);
if (ACM_READY(acm))
schedule_work(&acm->work);
else
diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c
index 8e74657f106..43a863c5cc4 100644
--- a/drivers/usb/class/usbtmc.c
+++ b/drivers/usb/class/usbtmc.c
@@ -51,6 +51,7 @@ static struct usb_device_id usbtmc_devices[] = {
{ USB_INTERFACE_INFO(USB_CLASS_APP_SPEC, 3, 0), },
{ 0, } /* terminating entry */
};
+MODULE_DEVICE_TABLE(usb, usbtmc_devices);
/*
* This structure is the capabilities for the device
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 3d7793d9303..8c081308b0e 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -279,7 +279,9 @@ static int usb_unbind_interface(struct device *dev)
* altsetting means creating new endpoint device entries).
* When either of these happens, defer the Set-Interface.
*/
- if (!error && intf->dev.power.status == DPM_ON)
+ if (intf->cur_altsetting->desc.bAlternateSetting == 0)
+ ; /* Already in altsetting 0 so skip Set-Interface */
+ else if (!error && intf->dev.power.status == DPM_ON)
usb_set_interface(udev, intf->altsetting[0].
desc.bInterfaceNumber, 0);
else
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 887738577b2..6d1048faf08 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -1091,6 +1091,7 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
continue;
dev_dbg(&dev->dev, "unregistering interface %s\n",
dev_name(&interface->dev));
+ interface->unregistering = 1;
usb_remove_sysfs_intf_files(interface);
device_del(&interface->dev);
}
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index f66fba11fbd..4fb65fdc9dc 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -840,7 +840,7 @@ int usb_create_sysfs_intf_files(struct usb_interface *intf)
struct usb_host_interface *alt = intf->cur_altsetting;
int retval;
- if (intf->sysfs_files_created)
+ if (intf->sysfs_files_created || intf->unregistering)
return 0;
/* The interface string may be present in some altsettings
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index 4342bd9c3bb..1f68af9db3f 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -85,8 +85,8 @@ EXPORT_SYMBOL_GPL(usb_alloc_urb);
* Must be called when a user of a urb is finished with it. When the last user
* of the urb calls this function, the memory of the urb is freed.
*
- * Note: The transfer buffer associated with the urb is not freed, that must be
- * done elsewhere.
+ * Note: The transfer buffer associated with the urb is not freed unless the
+ * URB_FREE_BUFFER transfer flag is set.
*/
void usb_free_urb(struct urb *urb)
{
diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c
index 5ee1590b8e9..c1d34df0b15 100644
--- a/drivers/usb/gadget/f_acm.c
+++ b/drivers/usb/gadget/f_acm.c
@@ -463,7 +463,11 @@ static int acm_cdc_notify(struct f_acm *acm, u8 type, u16 value,
notify->wLength = cpu_to_le16(length);
memcpy(buf, data, length);
+ /* ep_queue() can complete immediately if it fills the fifo... */
+ spin_unlock(&acm->lock);
status = usb_ep_queue(ep, req, GFP_ATOMIC);
+ spin_lock(&acm->lock);
+
if (status < 0) {
ERROR(acm->port.func.config->cdev,
"acm ttyGS%d can't notify serial state, %d\n",
diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c
index 659b3d9671c..3a8bb53fc47 100644
--- a/drivers/usb/gadget/f_rndis.c
+++ b/drivers/usb/gadget/f_rndis.c
@@ -172,7 +172,6 @@ static struct usb_interface_descriptor rndis_data_intf __initdata = {
.bDescriptorType = USB_DT_INTERFACE,
/* .bInterfaceNumber = DYNAMIC */
- .bAlternateSetting = 1,
.bNumEndpoints = 2,
.bInterfaceClass = USB_CLASS_CDC_DATA,
.bInterfaceSubClass = 0,
@@ -303,7 +302,7 @@ static void rndis_response_available(void *_rndis)
__le32 *data = req->buf;
int status;
- if (atomic_inc_return(&rndis->notify_count))
+ if (atomic_inc_return(&rndis->notify_count) != 1)
return;
/* Send RNDIS RESPONSE_AVAILABLE notification; a
@@ -652,6 +651,8 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
fs_in_desc.bEndpointAddress;
hs_out_desc.bEndpointAddress =
fs_out_desc.bEndpointAddress;
+ hs_notify_desc.bEndpointAddress =
+ fs_notify_desc.bEndpointAddress;
/* copy descriptors, and track endpoint copies */
f->hs_descriptors = usb_copy_descriptors(eth_hs_function);
@@ -663,6 +664,8 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
f->hs_descriptors, &hs_in_desc);
rndis->hs.out = usb_find_endpoint(eth_hs_function,
f->hs_descriptors, &hs_out_desc);
+ rndis->hs.notify = usb_find_endpoint(eth_hs_function,
+ f->hs_descriptors, &hs_notify_desc);
}
rndis->port.open = rndis_open;
diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c
index 1fe8b44787b..b3408ff39fb 100644
--- a/drivers/usb/gadget/fsl_qe_udc.c
+++ b/drivers/usb/gadget/fsl_qe_udc.c
@@ -2363,6 +2363,9 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
nuke(loop_ep, -ESHUTDOWN);
spin_unlock_irqrestore(&udc_controller->lock, flags);
+ /* report disconnect; the controller is already quiesced */
+ driver->disconnect(&udc_controller->gadget);
+
/* unbind gadget and unhook driver. */
driver->unbind(&udc_controller->gadget);
udc_controller->gadget.dev.driver = NULL;
diff --git a/drivers/usb/gadget/fsl_usb2_udc.c b/drivers/usb/gadget/fsl_usb2_udc.c
index 091bb55c9aa..f3c6703cffd 100644
--- a/drivers/usb/gadget/fsl_usb2_udc.c
+++ b/drivers/usb/gadget/fsl_usb2_udc.c
@@ -1836,6 +1836,9 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
nuke(loop_ep, -ESHUTDOWN);
spin_unlock_irqrestore(&udc_controller->lock, flags);
+ /* report disconnect; the controller is already quiesced */
+ driver->disconnect(&udc_controller->gadget);
+
/* unbind gadget and unhook driver. */
driver->unbind(&udc_controller->gadget);
udc_controller->gadget.dev.driver = NULL;
diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c
index da6e93c201d..2dbc0db0b46 100644
--- a/drivers/usb/gadget/pxa25x_udc.c
+++ b/drivers/usb/gadget/pxa25x_udc.c
@@ -141,7 +141,11 @@ static int is_vbus_present(void)
if (mach->gpio_vbus) {
int value = gpio_get_value(mach->gpio_vbus);
- return mach->gpio_vbus_inverted ? !value : value;
+
+ if (mach->gpio_vbus_inverted)
+ return !value;
+ else
+ return !!value;
}
if (mach->udc_is_connected)
return mach->udc_is_connected();
@@ -982,7 +986,7 @@ static int pxa25x_udc_vbus_session(struct usb_gadget *_gadget, int is_active)
struct pxa25x_udc *udc;
udc = container_of(_gadget, struct pxa25x_udc, gadget);
- udc->vbus = (is_active != 0);
+ udc->vbus = is_active;
DMSG("vbus %s\n", is_active ? "supplied" : "inactive");
pullup(udc);
return 0;
@@ -1399,12 +1403,8 @@ lubbock_vbus_irq(int irq, void *_dev)
static irqreturn_t udc_vbus_irq(int irq, void *_dev)
{
struct pxa25x_udc *dev = _dev;
- int vbus = gpio_get_value(dev->mach->gpio_vbus);
- if (dev->mach->gpio_vbus_inverted)
- vbus = !vbus;
-
- pxa25x_udc_vbus_session(&dev->gadget, vbus);
+ pxa25x_udc_vbus_session(&dev->gadget, is_vbus_present());
return IRQ_HANDLED;
}
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 56f592dc0b3..f3a75a929e0 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -110,29 +110,18 @@ config USB_ISP116X_HCD
config USB_ISP1760_HCD
tristate "ISP 1760 HCD support"
- depends on USB && EXPERIMENTAL
+ depends on USB && EXPERIMENTAL && (PCI || PPC_OF)
---help---
The ISP1760 chip is a USB 2.0 host controller.
This driver does not support isochronous transfers or OTG.
+ This USB controller is usually attached to a non-DMA-Master
+ capable bus. NXP's eval kit brings this chip on PCI card
+ where the chip itself is behind a PLB to simulate such
+ a bus.
To compile this driver as a module, choose M here: the
- module will be called isp1760-hcd.
-
-config USB_ISP1760_PCI
- bool "Support for the PCI bus"
- depends on USB_ISP1760_HCD && PCI
- ---help---
- Enables support for the device present on the PCI bus.
- This should only be required if you happen to have the eval kit from
- NXP and you are going to test it.
-
-config USB_ISP1760_OF
- bool "Support for the OF platform bus"
- depends on USB_ISP1760_HCD && PPC_OF
- ---help---
- Enables support for the device present on the PowerPC
- OpenFirmware platform bus.
+ module will be called isp1760.
config USB_OHCI_HCD
tristate "OHCI HCD support"
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 15a803b206b..4725d15d096 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -643,7 +643,7 @@ static int ehci_run (struct usb_hcd *hcd)
static irqreturn_t ehci_irq (struct usb_hcd *hcd)
{
struct ehci_hcd *ehci = hcd_to_ehci (hcd);
- u32 status, pcd_status = 0, cmd;
+ u32 status, masked_status, pcd_status = 0, cmd;
int bh;
spin_lock (&ehci->lock);
@@ -656,14 +656,14 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
goto dead;
}
- status &= INTR_MASK;
- if (!status) { /* irq sharing? */
+ masked_status = status & INTR_MASK;
+ if (!masked_status) { /* irq sharing? */
spin_unlock(&ehci->lock);
return IRQ_NONE;
}
/* clear (just) interrupts */
- ehci_writel(ehci, status, &ehci->regs->status);
+ ehci_writel(ehci, masked_status, &ehci->regs->status);
cmd = ehci_readl(ehci, &ehci->regs->command);
bh = 0;
@@ -734,18 +734,17 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
/* PCI errors [4.15.2.4] */
if (unlikely ((status & STS_FATAL) != 0)) {
+ ehci_err(ehci, "fatal error\n");
dbg_cmd(ehci, "fatal", cmd);
dbg_status(ehci, "fatal", status);
- if (status & STS_HALT) {
- ehci_err (ehci, "fatal error\n");
+ ehci_halt(ehci);
dead:
- ehci_reset (ehci);
- ehci_writel(ehci, 0, &ehci->regs->configured_flag);
- /* generic layer kills/unlinks all urbs, then
- * uses ehci_stop to clean up the rest
- */
- bh = 1;
- }
+ ehci_reset(ehci);
+ ehci_writel(ehci, 0, &ehci->regs->configured_flag);
+ /* generic layer kills/unlinks all urbs, then
+ * uses ehci_stop to clean up the rest
+ */
+ bh = 1;
}
if (bh)
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index c46a58f9181..36864f95844 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -66,6 +66,8 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
+ struct pci_dev *p_smbus;
+ u8 rev;
u32 temp;
int retval;
@@ -166,6 +168,28 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
pci_write_config_byte(pdev, 0x4b, tmp | 0x20);
}
break;
+ case PCI_VENDOR_ID_ATI:
+ /* SB600 and old version of SB700 have a bug in EHCI controller,
+ * which causes usb devices lose response in some cases.
+ */
+ if ((pdev->device == 0x4386) || (pdev->device == 0x4396)) {
+ p_smbus = pci_get_device(PCI_VENDOR_ID_ATI,
+ PCI_DEVICE_ID_ATI_SBX00_SMBUS,
+ NULL);
+ if (!p_smbus)
+ break;
+ rev = p_smbus->revision;
+ if ((pdev->device == 0x4386) || (rev == 0x3a)
+ || (rev == 0x3b)) {
+ u8 tmp;
+ ehci_info(ehci, "applying AMD SB600/SB700 USB "
+ "freeze workaround\n");
+ pci_read_config_byte(pdev, 0x53, &tmp);
+ pci_write_config_byte(pdev, 0x53, tmp | (1<<3));
+ }
+ pci_dev_put(p_smbus);
+ }
+ break;
}
ehci_reset(ehci);
diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c
index 0eba894bcb0..9c9da35abc6 100644
--- a/drivers/usb/host/ehci-ps3.c
+++ b/drivers/usb/host/ehci-ps3.c
@@ -205,6 +205,7 @@ static int ps3_ehci_remove(struct ps3_system_bus_device *dev)
tmp = hcd->irq;
+ ehci_shutdown(hcd);
usb_remove_hcd(hcd);
ps3_system_bus_set_driver_data(dev, NULL);
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index 4a0c5a78b2e..a081ee65bde 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -918,7 +918,7 @@ iso_stream_init (
*/
stream->usecs = HS_USECS_ISO (maxp);
bandwidth = stream->usecs * 8;
- bandwidth /= 1 << (interval - 1);
+ bandwidth /= interval;
} else {
u32 addr;
@@ -951,7 +951,7 @@ iso_stream_init (
} else
stream->raw_mask = smask_out [hs_transfers - 1];
bandwidth = stream->usecs + stream->c_usecs;
- bandwidth /= 1 << (interval + 2);
+ bandwidth /= interval << 3;
/* stream->splits gets created from raw_mask later */
stream->address = cpu_to_hc32(ehci, addr);
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index b11798d17ae..c7d4b5a06bd 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -183,16 +183,14 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action)
* the async ring; just the I/O watchdog. Note that if a
* SHRINK were pending, OFF would never be requested.
*/
- enum ehci_timer_action oldactions = ehci->actions;
+ if (timer_pending(&ehci->watchdog)
+ && ((BIT(TIMER_ASYNC_SHRINK) | BIT(TIMER_ASYNC_OFF))
+ & ehci->actions))
+ return;
if (!test_and_set_bit (action, &ehci->actions)) {
unsigned long t;
- if (timer_pending(&ehci->watchdog)
- && ((BIT(TIMER_ASYNC_SHRINK) | BIT(TIMER_ASYNC_OFF))
- & oldactions))
- return;
-
switch (action) {
case TIMER_IO_WATCHDOG:
t = EHCI_IO_JIFFIES;
@@ -208,7 +206,7 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action)
t = DIV_ROUND_UP(EHCI_SHRINK_FRAMES * HZ, 1000) + 1;
break;
}
- mod_timer(&ehci->watchdog, round_jiffies(t + jiffies));
+ mod_timer(&ehci->watchdog, t + jiffies);
}
}
diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c
index af849f59613..b87ca7cf4b3 100644
--- a/drivers/usb/host/isp1760-if.c
+++ b/drivers/usb/host/isp1760-if.c
@@ -14,16 +14,16 @@
#include "../core/hcd.h"
#include "isp1760-hcd.h"
-#ifdef CONFIG_USB_ISP1760_OF
+#ifdef CONFIG_PPC_OF
#include <linux/of.h>
#include <linux/of_platform.h>
#endif
-#ifdef CONFIG_USB_ISP1760_PCI
+#ifdef CONFIG_PCI
#include <linux/pci.h>
#endif
-#ifdef CONFIG_USB_ISP1760_OF
+#ifdef CONFIG_PPC_OF
static int of_isp1760_probe(struct of_device *dev,
const struct of_device_id *match)
{
@@ -128,7 +128,7 @@ static struct of_platform_driver isp1760_of_driver = {
};
#endif
-#ifdef CONFIG_USB_ISP1760_PCI
+#ifdef CONFIG_PCI
static u32 nxp_pci_io_base;
static u32 iolength;
static u32 pci_mem_phy0;
@@ -288,28 +288,28 @@ static struct pci_driver isp1761_pci_driver = {
static int __init isp1760_init(void)
{
- int ret = -ENODEV;
+ int ret;
init_kmem_once();
-#ifdef CONFIG_USB_ISP1760_OF
+#ifdef CONFIG_PPC_OF
ret = of_register_platform_driver(&isp1760_of_driver);
if (ret) {
deinit_kmem_cache();
return ret;
}
#endif
-#ifdef CONFIG_USB_ISP1760_PCI
+#ifdef CONFIG_PCI
ret = pci_register_driver(&isp1761_pci_driver);
if (ret)
goto unreg_of;
#endif
return ret;
-#ifdef CONFIG_USB_ISP1760_PCI
+#ifdef CONFIG_PCI
unreg_of:
#endif
-#ifdef CONFIG_USB_ISP1760_OF
+#ifdef CONFIG_PPC_OF
of_unregister_platform_driver(&isp1760_of_driver);
#endif
deinit_kmem_cache();
@@ -319,10 +319,10 @@ module_init(isp1760_init);
static void __exit isp1760_exit(void)
{
-#ifdef CONFIG_USB_ISP1760_OF
+#ifdef CONFIG_PPC_OF
of_unregister_platform_driver(&isp1760_of_driver);
#endif
-#ifdef CONFIG_USB_ISP1760_PCI
+#ifdef CONFIG_PCI
pci_unregister_driver(&isp1761_pci_driver);
#endif
deinit_kmem_cache();
diff --git a/drivers/usb/host/ohci-ps3.c b/drivers/usb/host/ohci-ps3.c
index 2089d8a46c4..3c1a3b5f89f 100644
--- a/drivers/usb/host/ohci-ps3.c
+++ b/drivers/usb/host/ohci-ps3.c
@@ -192,7 +192,7 @@ fail_start:
return result;
}
-static int ps3_ohci_remove (struct ps3_system_bus_device *dev)
+static int ps3_ohci_remove(struct ps3_system_bus_device *dev)
{
unsigned int tmp;
struct usb_hcd *hcd =
@@ -205,6 +205,7 @@ static int ps3_ohci_remove (struct ps3_system_bus_device *dev)
tmp = hcd->irq;
+ ohci_shutdown(hcd);
usb_remove_hcd(hcd);
ps3_system_bus_set_driver_data(dev, NULL);
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
index c18d8790c41..2376f24f3c8 100644
--- a/drivers/usb/host/r8a66597-hcd.c
+++ b/drivers/usb/host/r8a66597-hcd.c
@@ -1763,11 +1763,12 @@ static void r8a66597_timer(unsigned long _r8a66597)
{
struct r8a66597 *r8a66597 = (struct r8a66597 *)_r8a66597;
unsigned long flags;
+ int port;
spin_lock_irqsave(&r8a66597->lock, flags);
- r8a66597_root_hub_control(r8a66597, 0);
- r8a66597_root_hub_control(r8a66597, 1);
+ for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++)
+ r8a66597_root_hub_control(r8a66597, port);
spin_unlock_irqrestore(&r8a66597->lock, flags);
}
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c
index 69c34a58e20..b4ec716de7d 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.c
+++ b/drivers/usb/misc/sisusbvga/sisusb.c
@@ -3270,6 +3270,7 @@ static struct usb_device_id sisusb_table [] = {
{ USB_DEVICE(0x0711, 0x0900) },
{ USB_DEVICE(0x0711, 0x0901) },
{ USB_DEVICE(0x0711, 0x0902) },
+ { USB_DEVICE(0x0711, 0x0903) },
{ USB_DEVICE(0x0711, 0x0918) },
{ USB_DEVICE(0x182d, 0x021c) },
{ USB_DEVICE(0x182d, 0x0269) },
diff --git a/drivers/usb/misc/vstusb.c b/drivers/usb/misc/vstusb.c
index 8648470c81c..63dff9ba73c 100644
--- a/drivers/usb/misc/vstusb.c
+++ b/drivers/usb/misc/vstusb.c
@@ -620,7 +620,7 @@ static long vstusb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
__func__);
retval = -EFAULT;
} else {
- dev_dbg(&dev->dev, "%s: recv %d bytes from pipe %d\n",
+ dev_dbg(&dev->dev, "%s: recv %zd bytes from pipe %d\n",
__func__, usb_data.count, usb_data.pipe);
}
diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c
index c9de3f027aa..e06810aef2d 100644
--- a/drivers/usb/mon/mon_bin.c
+++ b/drivers/usb/mon/mon_bin.c
@@ -687,7 +687,10 @@ static ssize_t mon_bin_read(struct file *file, char __user *buf,
}
if (rp->b_read >= sizeof(struct mon_bin_hdr)) {
- step_len = min(nbytes, (size_t)ep->len_cap);
+ step_len = ep->len_cap;
+ step_len -= rp->b_read - sizeof(struct mon_bin_hdr);
+ if (step_len > nbytes)
+ step_len = nbytes;
offset = rp->b_out + PKT_SIZE;
offset += rp->b_read - sizeof(struct mon_bin_hdr);
if (offset >= rp->b_size)
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 4a35745b30b..5280dba9b1f 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -114,8 +114,8 @@
-unsigned debug;
-module_param(debug, uint, S_IRUGO | S_IWUSR);
+unsigned musb_debug;
+module_param(musb_debug, uint, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Debug message level. Default = 0");
#define DRIVER_AUTHOR "Mentor Graphics, Texas Instruments, Nokia"
@@ -2248,7 +2248,7 @@ static int __init musb_init(void)
"host"
#endif
", debug=%d\n",
- musb_driver_name, debug);
+ musb_driver_name, musb_debug);
return platform_driver_probe(&musb_driver, musb_probe);
}
diff --git a/drivers/usb/musb/musb_debug.h b/drivers/usb/musb/musb_debug.h
index 4d2794441b1..9fc1db44c72 100644
--- a/drivers/usb/musb/musb_debug.h
+++ b/drivers/usb/musb/musb_debug.h
@@ -48,11 +48,11 @@
__func__, __LINE__ , ## args); \
} } while (0)
-extern unsigned debug;
+extern unsigned musb_debug;
static inline int _dbg_level(unsigned l)
{
- return debug >= l;
+ return musb_debug >= l;
}
#define DBG(level, fmt, args...) xprintk(level, KERN_DEBUG, fmt, ## args)
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index 3133990f04e..cc64462d4c4 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -378,6 +378,19 @@ musb_giveback(struct musb_qh *qh, struct urb *urb, int status)
switch (qh->type) {
+ case USB_ENDPOINT_XFER_CONTROL:
+ case USB_ENDPOINT_XFER_BULK:
+ /* fifo policy for these lists, except that NAKing
+ * should rotate a qh to the end (for fairness).
+ */
+ if (qh->mux == 1) {
+ head = qh->ring.prev;
+ list_del(&qh->ring);
+ kfree(qh);
+ qh = first_qh(head);
+ break;
+ }
+
case USB_ENDPOINT_XFER_ISOC:
case USB_ENDPOINT_XFER_INT:
/* this is where periodic bandwidth should be
@@ -388,17 +401,6 @@ musb_giveback(struct musb_qh *qh, struct urb *urb, int status)
kfree(qh);
qh = NULL;
break;
-
- case USB_ENDPOINT_XFER_CONTROL:
- case USB_ENDPOINT_XFER_BULK:
- /* fifo policy for these lists, except that NAKing
- * should rotate a qh to the end (for fairness).
- */
- head = qh->ring.prev;
- list_del(&qh->ring);
- kfree(qh);
- qh = first_qh(head);
- break;
}
}
return qh;
@@ -1507,10 +1509,29 @@ void musb_host_rx(struct musb *musb, u8 epnum)
musb_writew(hw_ep->regs, MUSB_RXCSR, val);
#ifdef CONFIG_USB_INVENTRA_DMA
+ if (usb_pipeisoc(pipe)) {
+ struct usb_iso_packet_descriptor *d;
+
+ d = urb->iso_frame_desc + qh->iso_idx;
+ d->actual_length = xfer_len;
+
+ /* even if there was an error, we did the dma
+ * for iso_frame_desc->length
+ */
+ if (d->status != EILSEQ && d->status != -EOVERFLOW)
+ d->status = 0;
+
+ if (++qh->iso_idx >= urb->number_of_packets)
+ done = true;
+ else
+ done = false;
+
+ } else {
/* done if urb buffer is full or short packet is recd */
done = (urb->actual_length + xfer_len >=
urb->transfer_buffer_length
|| dma->actual_len < qh->maxpacket);
+ }
/* send IN token for next packet, without AUTOREQ */
if (!done) {
@@ -1547,7 +1568,8 @@ void musb_host_rx(struct musb *musb, u8 epnum)
if (dma) {
struct dma_controller *c;
u16 rx_count;
- int ret;
+ int ret, length;
+ dma_addr_t buf;
rx_count = musb_readw(epio, MUSB_RXCOUNT);
@@ -1560,6 +1582,35 @@ void musb_host_rx(struct musb *musb, u8 epnum)
c = musb->dma_controller;
+ if (usb_pipeisoc(pipe)) {
+ int status = 0;
+ struct usb_iso_packet_descriptor *d;
+
+ d = urb->iso_frame_desc + qh->iso_idx;
+
+ if (iso_err) {
+ status = -EILSEQ;
+ urb->error_count++;
+ }
+ if (rx_count > d->length) {
+ if (status == 0) {
+ status = -EOVERFLOW;
+ urb->error_count++;
+ }
+ DBG(2, "** OVERFLOW %d into %d\n",\
+ rx_count, d->length);
+
+ length = d->length;
+ } else
+ length = rx_count;
+ d->status = status;
+ buf = urb->transfer_dma + d->offset;
+ } else {
+ length = rx_count;
+ buf = urb->transfer_dma +
+ urb->actual_length;
+ }
+
dma->desired_mode = 0;
#ifdef USE_MODE1
/* because of the issue below, mode 1 will
@@ -1571,6 +1622,12 @@ void musb_host_rx(struct musb *musb, u8 epnum)
urb->actual_length)
> qh->maxpacket)
dma->desired_mode = 1;
+ if (rx_count < hw_ep->max_packet_sz_rx) {
+ length = rx_count;
+ dma->bDesiredMode = 0;
+ } else {
+ length = urb->transfer_buffer_length;
+ }
#endif
/* Disadvantage of using mode 1:
@@ -1608,12 +1665,7 @@ void musb_host_rx(struct musb *musb, u8 epnum)
*/
ret = c->channel_program(
dma, qh->maxpacket,
- dma->desired_mode,
- urb->transfer_dma
- + urb->actual_length,
- (dma->desired_mode == 0)
- ? rx_count
- : urb->transfer_buffer_length);
+ dma->desired_mode, buf, length);
if (!ret) {
c->channel_release(dma);
@@ -1631,19 +1683,6 @@ void musb_host_rx(struct musb *musb, u8 epnum)
}
}
- if (dma && usb_pipeisoc(pipe)) {
- struct usb_iso_packet_descriptor *d;
- int iso_stat = status;
-
- d = urb->iso_frame_desc + qh->iso_idx;
- d->actual_length += xfer_len;
- if (iso_err) {
- iso_stat = -EILSEQ;
- urb->error_count++;
- }
- d->status = iso_stat;
- }
-
finish:
urb->actual_length += xfer_len;
qh->offset += xfer_len;
@@ -1671,22 +1710,9 @@ static int musb_schedule(
struct list_head *head = NULL;
/* use fixed hardware for control and bulk */
- switch (qh->type) {
- case USB_ENDPOINT_XFER_CONTROL:
+ if (qh->type == USB_ENDPOINT_XFER_CONTROL) {
head = &musb->control;
hw_ep = musb->control_ep;
- break;
- case USB_ENDPOINT_XFER_BULK:
- hw_ep = musb->bulk_ep;
- if (is_in)
- head = &musb->in_bulk;
- else
- head = &musb->out_bulk;
- break;
- }
- if (head) {
- idle = list_empty(head);
- list_add_tail(&qh->ring, head);
goto success;
}
@@ -1725,19 +1751,34 @@ static int musb_schedule(
else
diff = hw_ep->max_packet_sz_tx - qh->maxpacket;
- if (diff > 0 && best_diff > diff) {
+ if (diff >= 0 && best_diff > diff) {
best_diff = diff;
best_end = epnum;
}
}
- if (best_end < 0)
+ /* use bulk reserved ep1 if no other ep is free */
+ if (best_end < 0 && qh->type == USB_ENDPOINT_XFER_BULK) {
+ hw_ep = musb->bulk_ep;
+ if (is_in)
+ head = &musb->in_bulk;
+ else
+ head = &musb->out_bulk;
+ goto success;
+ } else if (best_end < 0) {
return -ENOSPC;
+ }
idle = 1;
+ qh->mux = 0;
hw_ep = musb->endpoints + best_end;
musb->periodic[best_end] = qh;
DBG(4, "qh %p periodic slot %d\n", qh, best_end);
success:
+ if (head) {
+ idle = list_empty(head);
+ list_add_tail(&qh->ring, head);
+ qh->mux = 1;
+ }
qh->hw_ep = hw_ep;
qh->hep->hcpriv = qh;
if (idle)
@@ -2015,11 +2056,13 @@ static int musb_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
sched = &musb->control;
break;
case USB_ENDPOINT_XFER_BULK:
- if (usb_pipein(urb->pipe))
- sched = &musb->in_bulk;
- else
- sched = &musb->out_bulk;
- break;
+ if (qh->mux == 1) {
+ if (usb_pipein(urb->pipe))
+ sched = &musb->in_bulk;
+ else
+ sched = &musb->out_bulk;
+ break;
+ }
default:
/* REVISIT when we get a schedule tree, periodic
* transfers won't always be at the head of a
@@ -2067,11 +2110,13 @@ musb_h_disable(struct usb_hcd *hcd, struct usb_host_endpoint *hep)
sched = &musb->control;
break;
case USB_ENDPOINT_XFER_BULK:
- if (is_in)
- sched = &musb->in_bulk;
- else
- sched = &musb->out_bulk;
- break;
+ if (qh->mux == 1) {
+ if (is_in)
+ sched = &musb->in_bulk;
+ else
+ sched = &musb->out_bulk;
+ break;
+ }
default:
/* REVISIT when we get a schedule tree, periodic transfers
* won't always be at the head of a singleton queue...
diff --git a/drivers/usb/musb/musb_host.h b/drivers/usb/musb/musb_host.h
index 77bcdb9d5b3..0b7fbcd2196 100644
--- a/drivers/usb/musb/musb_host.h
+++ b/drivers/usb/musb/musb_host.h
@@ -53,6 +53,7 @@ struct musb_qh {
struct list_head ring; /* of musb_qh */
/* struct musb_qh *next; */ /* for periodic tree */
+ u8 mux; /* qh multiplexed to hw_ep */
unsigned offset; /* in urb->transfer_buffer */
unsigned segsize; /* current xfer fragment */
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index 9d2dcb121c5..ce6c162920f 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -53,7 +53,9 @@ static void musb_do_idle(unsigned long _musb)
{
struct musb *musb = (void *)_musb;
unsigned long flags;
+#ifdef CONFIG_USB_MUSB_HDRC_HCD
u8 power;
+#endif
u8 devctl;
devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c
index b73b036f3d7..ee8fca92a4a 100644
--- a/drivers/usb/musb/tusb6010.c
+++ b/drivers/usb/musb/tusb6010.c
@@ -605,7 +605,7 @@ void musb_platform_set_mode(struct musb *musb, u8 musb_mode)
if (musb->board_mode != MUSB_OTG) {
ERR("Changing mode currently only supported in OTG mode\n");
- return;
+ return -EINVAL;
}
otg_stat = musb_readl(tbase, TUSB_DEV_OTG_STAT);
diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c
index 5b20de130e0..5b95009d2fb 100644
--- a/drivers/usb/serial/console.c
+++ b/drivers/usb/serial/console.c
@@ -135,6 +135,7 @@ static int usb_console_setup(struct console *co, char *options)
err("no more memory");
goto reset_open_count;
}
+ kref_init(&tty->kref);
termios = kzalloc(sizeof(*termios), GFP_KERNEL);
if (!termios) {
retval = -ENOMEM;
diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c
index 8008d0bc80a..cfaf1f08553 100644
--- a/drivers/usb/serial/cp2101.c
+++ b/drivers/usb/serial/cp2101.c
@@ -56,6 +56,7 @@ static void cp2101_shutdown(struct usb_serial *);
static int debug;
static struct usb_device_id id_table [] = {
+ { USB_DEVICE(0x0471, 0x066A) }, /* AKTAKOM ACE-1001 cable */
{ USB_DEVICE(0x0489, 0xE000) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */
{ USB_DEVICE(0x08e6, 0x5501) }, /* Gemalto Prox-PU/CU contactless smartcard reader */
{ USB_DEVICE(0x0FCF, 0x1003) }, /* Dynastream ANT development board */
@@ -67,6 +68,7 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(0x10C4, 0x800A) }, /* SPORTident BSM7-D-USB main station */
{ USB_DEVICE(0x10C4, 0x803B) }, /* Pololu USB-serial converter */
{ USB_DEVICE(0x10C4, 0x8053) }, /* Enfora EDG1228 */
+ { USB_DEVICE(0x10C4, 0x8054) }, /* Enfora GSM2228 */
{ USB_DEVICE(0x10C4, 0x8066) }, /* Argussoft In-System Programmer */
{ USB_DEVICE(0x10C4, 0x807A) }, /* Crumb128 board */
{ USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */
@@ -85,6 +87,7 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */
{ USB_DEVICE(0x10c4, 0x8293) }, /* Telegesys ETRX2USB */
{ USB_DEVICE(0x10C4, 0x8341) }, /* Siemens MC35PU GPRS Modem */
+ { USB_DEVICE(0x10C4, 0x83A8) }, /* Amber Wireless AMB2560 */
{ USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
{ USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
{ USB_DEVICE(0x10C4, 0xF001) }, /* Elan Digital Systems USBscope50 */
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 51d7bdea286..fb6f2933b01 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -143,6 +143,7 @@ static struct ftdi_sio_quirk ftdi_HE_TIRA1_quirk = {
static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_AMC232_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_CANUSB_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_CANDAPTER_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_0_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_1_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_2_PID) },
@@ -166,6 +167,7 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_OPENDCC_PID) },
{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) },
{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_SPROG_II) },
{ USB_DEVICE(FTDI_VID, FTDI_XF_632_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_XF_634_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_XF_547_PID) },
@@ -1498,7 +1500,7 @@ static int ftdi_open(struct tty_struct *tty,
priv->interface, buf, 0, WDR_TIMEOUT);
/* Termios defaults are set by usb_serial_init. We don't change
- port->tty->termios - this would loose speed settings, etc.
+ port->tty->termios - this would lose speed settings, etc.
This is same behaviour as serial.c/rs_open() - Kuba */
/* ftdi_set_termios will send usb control messages */
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index 07a3992abad..373ee09975b 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -40,6 +40,9 @@
/* AlphaMicro Components AMC-232USB01 device */
#define FTDI_AMC232_PID 0xFF00 /* Product Id */
+/* www.candapter.com Ewert Energy Systems CANdapter device */
+#define FTDI_CANDAPTER_PID 0x9F80 /* Product Id */
+
/* SCS HF Radio Modems PID's (http://www.scs-ptc.com) */
/* the VID is the standard ftdi vid (FTDI_VID) */
#define FTDI_SCS_DEVICE_0_PID 0xD010 /* SCS PTC-IIusb */
@@ -75,6 +78,9 @@
/* OpenDCC (www.opendcc.de) product id */
#define FTDI_OPENDCC_PID 0xBFD8
+/* Sprog II (Andrew Crosland's SprogII DCC interface) */
+#define FTDI_SPROG_II 0xF0C8
+
/* www.crystalfontz.com devices - thanx for providing free devices for evaluation ! */
/* they use the ftdi chipset for the USB interface and the vendor id is the same */
#define FTDI_XF_632_PID 0xFC08 /* 632: 16x2 Character Display */
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index bd07eaa300b..809697b3c7f 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -160,6 +160,11 @@ static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *po
#define NOVATELWIRELESS_VENDOR_ID 0x1410
+/* YISO PRODUCTS */
+
+#define YISO_VENDOR_ID 0x0EAB
+#define YISO_PRODUCT_U893 0xC893
+
/* MERLIN EVDO PRODUCTS */
#define NOVATELWIRELESS_PRODUCT_V640 0x1100
#define NOVATELWIRELESS_PRODUCT_V620 0x1110
@@ -219,6 +224,7 @@ static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *po
#define ONDA_VENDOR_ID 0x19d2
#define ONDA_PRODUCT_MSA501HS 0x0001
#define ONDA_PRODUCT_ET502HS 0x0002
+#define ONDA_PRODUCT_MT503HS 0x0200
#define BANDRICH_VENDOR_ID 0x1A8D
#define BANDRICH_PRODUCT_C100_1 0x1002
@@ -408,6 +414,41 @@ static struct usb_device_id option_ids[] = {
{ USB_DEVICE(AXESSTEL_VENDOR_ID, AXESSTEL_PRODUCT_MV110H) },
{ USB_DEVICE(ONDA_VENDOR_ID, ONDA_PRODUCT_MSA501HS) },
{ USB_DEVICE(ONDA_VENDOR_ID, ONDA_PRODUCT_ET502HS) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0003) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0004) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0005) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0006) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0007) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0008) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0009) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x000a) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x000b) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x000c) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x000d) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x000e) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x000f) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0010) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0011) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0012) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0013) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0014) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0015) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0016) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0017) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0018) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0019) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0020) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0021) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0022) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0023) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0024) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0025) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0026) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0027) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0028) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0029) },
+ { USB_DEVICE(ONDA_VENDOR_ID, ONDA_PRODUCT_MT503HS) },
+ { USB_DEVICE(YISO_VENDOR_ID, YISO_PRODUCT_U893) },
{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_1) },
{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_2) },
{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1004) },
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 491c8857b64..1aed584be5e 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -91,6 +91,8 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(WS002IN_VENDOR_ID, WS002IN_PRODUCT_ID) },
{ USB_DEVICE(COREGA_VENDOR_ID, COREGA_PRODUCT_ID) },
{ USB_DEVICE(YCCABLE_VENDOR_ID, YCCABLE_PRODUCT_ID) },
+ { USB_DEVICE(SUPERIAL_VENDOR_ID, SUPERIAL_PRODUCT_ID) },
+ { USB_DEVICE(HP_VENDOR_ID, HP_LD220_PRODUCT_ID) },
{ } /* Terminating entry */
};
diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h
index a3bd039c78e..54974f446a8 100644
--- a/drivers/usb/serial/pl2303.h
+++ b/drivers/usb/serial/pl2303.h
@@ -110,3 +110,11 @@
/* Y.C. Cable U.S.A., Inc - USB to RS-232 */
#define YCCABLE_VENDOR_ID 0x05ad
#define YCCABLE_PRODUCT_ID 0x0fba
+
+/* "Superial" USB - Serial */
+#define SUPERIAL_VENDOR_ID 0x5372
+#define SUPERIAL_PRODUCT_ID 0x2303
+
+/* Hewlett-Packard LD220-HP POS Pole Display */
+#define HP_VENDOR_ID 0x03f0
+#define HP_LD220_PRODUCT_ID 0x3524
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index 31c42d1cae1..01d0c70d60e 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -16,56 +16,6 @@
* For questions or problems with this driver, contact Texas Instruments
* technical support, or Al Borchers <alborchers@steinerpoint.com>, or
* Peter Berger <pberger@brimson.com>.
- *
- * This driver needs this hotplug script in /etc/hotplug/usb/ti_usb_3410_5052
- * or in /etc/hotplug.d/usb/ti_usb_3410_5052.hotplug to set the device
- * configuration.
- *
- * #!/bin/bash
- *
- * BOOT_CONFIG=1
- * ACTIVE_CONFIG=2
- *
- * if [[ "$ACTION" != "add" ]]
- * then
- * exit
- * fi
- *
- * CONFIG_PATH=/sys${DEVPATH%/?*}/bConfigurationValue
- *
- * if [[ 0`cat $CONFIG_PATH` -ne $BOOT_CONFIG ]]
- * then
- * exit
- * fi
- *
- * PRODUCT=${PRODUCT%/?*} # delete version
- * VENDOR_ID=`printf "%d" 0x${PRODUCT%/?*}`
- * PRODUCT_ID=`printf "%d" 0x${PRODUCT#*?/}`
- *
- * PARAM_PATH=/sys/module/ti_usb_3410_5052/parameters
- *
- * function scan() {
- * s=$1
- * shift
- * for i
- * do
- * if [[ $s -eq $i ]]
- * then
- * return 0
- * fi
- * done
- * return 1
- * }
- *
- * IFS=$IFS,
- *
- * if (scan $VENDOR_ID 1105 `cat $PARAM_PATH/vendor_3410` &&
- * scan $PRODUCT_ID 13328 `cat $PARAM_PATH/product_3410`) ||
- * (scan $VENDOR_ID 1105 `cat $PARAM_PATH/vendor_5052` &&
- * scan $PRODUCT_ID 20562 20818 20570 20575 `cat $PARAM_PATH/product_5052`)
- * then
- * echo $ACTIVE_CONFIG > $CONFIG_PATH
- * fi
*/
#include <linux/kernel.h>
@@ -457,9 +407,10 @@ static int ti_startup(struct usb_serial *serial)
goto free_tdev;
}
- /* the second configuration must be set (in sysfs by hotplug script) */
+ /* the second configuration must be set */
if (dev->actconfig->desc.bConfigurationValue == TI_BOOT_CONFIG) {
- status = -ENODEV;
+ status = usb_driver_set_configuration(dev, TI_ACTIVE_CONFIG);
+ status = status ? status : -ENODEV;
goto free_tdev;
}
diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
index 3d9249632ae..c68b738900b 100644
--- a/drivers/usb/storage/Kconfig
+++ b/drivers/usb/storage/Kconfig
@@ -2,8 +2,8 @@
# USB Storage driver configuration
#
-comment "NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'"
-comment "may also be needed; see USB_STORAGE Help for more information"
+comment "NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;"
+comment "see USB_STORAGE Help for more information"
depends on USB
config USB_STORAGE
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index fb9e20e624c..bfcc1fe8251 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -167,6 +167,27 @@ UNUSUAL_DEV( 0x0421, 0x005d, 0x0001, 0x0600,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_CAPACITY ),
+/* Reported by Ozan Sener <themgzzy@gmail.com> */
+UNUSUAL_DEV( 0x0421, 0x0060, 0x0551, 0x0551,
+ "Nokia",
+ "3500c",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_FIX_CAPACITY ),
+
+/* Reported by CSECSY Laszlo <boobaa@frugalware.org> */
+UNUSUAL_DEV( 0x0421, 0x0063, 0x0001, 0x0601,
+ "Nokia",
+ "Nokia 3109c",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_FIX_CAPACITY ),
+
+/* Patch for Nokia 5310 capacity */
+UNUSUAL_DEV( 0x0421, 0x006a, 0x0000, 0x0701,
+ "Nokia",
+ "5310",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_FIX_CAPACITY ),
+
/* Reported by Mario Rettig <mariorettig@web.de> */
UNUSUAL_DEV( 0x0421, 0x042e, 0x0100, 0x0100,
"Nokia",
@@ -233,14 +254,14 @@ UNUSUAL_DEV( 0x0421, 0x0495, 0x0370, 0x0370,
US_FL_MAX_SECTORS_64 ),
/* Reported by Cedric Godin <cedric@belbone.be> */
-UNUSUAL_DEV( 0x0421, 0x04b9, 0x0551, 0x0551,
+UNUSUAL_DEV( 0x0421, 0x04b9, 0x0500, 0x0551,
"Nokia",
"5300",
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_CAPACITY ),
/* Reported by Richard Nauber <RichardNauber@web.de> */
-UNUSUAL_DEV( 0x0421, 0x04fa, 0x0601, 0x0601,
+UNUSUAL_DEV( 0x0421, 0x04fa, 0x0550, 0x0660,
"Nokia",
"6300",
US_SC_DEVICE, US_PR_DEVICE, NULL,
@@ -253,6 +274,14 @@ UNUSUAL_DEV( 0x0421, 0x006a, 0x0000, 0x0591,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_CAPACITY ),
+/* Submitted by Ricky Wong Yung Fei <evilbladewarrior@gmail.com> */
+/* Nokia 7610 Supernova - Too many sectors reported in usb storage mode */
+UNUSUAL_DEV( 0x0421, 0x00f5, 0x0000, 0x0470,
+ "Nokia",
+ "7610 Supernova",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_FIX_CAPACITY ),
+
/* Reported by Olaf Hering <olh@suse.de> from novell bug #105878 */
UNUSUAL_DEV( 0x0424, 0x0fdc, 0x0210, 0x0210,
"SMSC",
@@ -303,6 +332,18 @@ UNUSUAL_DEV( 0x045a, 0x5210, 0x0101, 0x0101,
US_SC_SCSI, US_PR_KARMA, rio_karma_init, 0),
#endif
+/* Reported by Tamas Kerecsen <kerecsen@bigfoot.com>
+ * Obviously the PROM has not been customized by the VAR;
+ * the Vendor and Product string descriptors are:
+ * Generic Mass Storage (PROTOTYPE--Remember to change idVendor)
+ * Generic Manufacturer (PROTOTYPE--Remember to change idVendor)
+ */
+UNUSUAL_DEV( 0x045e, 0xffff, 0x0000, 0x0000,
+ "Mitac",
+ "GPS",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_MAX_SECTORS_64 ),
+
/*
* This virtual floppy is found in Sun equipment (x4600, x4200m2, etc.)
* Reported by Pete Zaitcev <zaitcev@redhat.com>
@@ -362,6 +403,13 @@ UNUSUAL_DEV( 0x04b0, 0x0401, 0x0200, 0x0200,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_CAPACITY),
+/* Reported by Tobias Kunze Briseno <t-linux@fictive.com> */
+UNUSUAL_DEV( 0x04b0, 0x0403, 0x0200, 0x0200,
+ "NIKON",
+ "NIKON DSC D2H",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_FIX_CAPACITY),
+
/* Reported by Milinevsky Dmitry <niam.niam@gmail.com> */
UNUSUAL_DEV( 0x04b0, 0x0409, 0x0100, 0x0100,
"NIKON",
@@ -418,6 +466,13 @@ UNUSUAL_DEV( 0x04b0, 0x0417, 0x0100, 0x0100,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_CAPACITY),
+/* Reported by paul ready <lxtwin@homecall.co.uk> */
+UNUSUAL_DEV( 0x04b0, 0x0419, 0x0100, 0x0200,
+ "NIKON",
+ "NIKON DSC D300",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_FIX_CAPACITY),
+
/* Reported by Doug Maxey (dwm@austin.ibm.com) */
UNUSUAL_DEV( 0x04b3, 0x4001, 0x0110, 0x0110,
"IBM",
@@ -1258,6 +1313,13 @@ UNUSUAL_DEV( 0x0839, 0x000a, 0x0001, 0x0001,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_INQUIRY),
+/* Reported by Luciano Rocha <luciano@eurotux.com> */
+UNUSUAL_DEV( 0x0840, 0x0082, 0x0001, 0x0001,
+ "Argosy",
+ "Storage",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_FIX_CAPACITY),
+
/* Entry and supporting patch by Theodore Kilgore <kilgota@auburn.edu>.
* Flag will support Bulk devices which use a standards-violating 32-byte
* Command Block Wrapper. Here, the "DC2MEGA" cameras (several brands) with
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
index f8d0a57a07c..9a577a800db 100644
--- a/drivers/video/atmel_lcdfb.c
+++ b/drivers/video/atmel_lcdfb.c
@@ -132,7 +132,7 @@ static void init_backlight(struct atmel_lcdfb_info *sinfo)
bl = backlight_device_register("backlight", &sinfo->pdev->dev,
sinfo, &atmel_lcdc_bl_ops);
- if (IS_ERR(sinfo->backlight)) {
+ if (IS_ERR(bl)) {
dev_err(&sinfo->pdev->dev, "error %ld on backlight register\n",
PTR_ERR(bl));
return;
diff --git a/drivers/video/aty/radeon_accel.c b/drivers/video/aty/radeon_accel.c
index 8718f7349d6..a469a3d6edc 100644
--- a/drivers/video/aty/radeon_accel.c
+++ b/drivers/video/aty/radeon_accel.c
@@ -5,61 +5,61 @@
* --dte
*/
-#define FLUSH_CACHE_WORKAROUND 1
-
-void radeon_fifo_update_and_wait(struct radeonfb_info *rinfo, int entries)
+static void radeon_fixup_offset(struct radeonfb_info *rinfo)
{
- int i;
+ u32 local_base;
+
+ /* *** Ugly workaround *** */
+ /*
+ * On some platforms, the video memory is mapped at 0 in radeon chip space
+ * (like PPCs) by the firmware. X will always move it up so that it's seen
+ * by the chip to be at the same address as the PCI BAR.
+ * That means that when switching back from X, there is a mismatch between
+ * the offsets programmed into the engine. This means that potentially,
+ * accel operations done before radeonfb has a chance to re-init the engine
+ * will have incorrect offsets, and potentially trash system memory !
+ *
+ * The correct fix is for fbcon to never call any accel op before the engine
+ * has properly been re-initialized (by a call to set_var), but this is a
+ * complex fix. This workaround in the meantime, called before every accel
+ * operation, makes sure the offsets are in sync.
+ */
- for (i=0; i<2000000; i++) {
- rinfo->fifo_free = INREG(RBBM_STATUS) & 0x7f;
- if (rinfo->fifo_free >= entries)
- return;
- udelay(10);
- }
- printk(KERN_ERR "radeonfb: FIFO Timeout !\n");
- /* XXX Todo: attempt to reset the engine */
-}
+ radeon_fifo_wait (1);
+ local_base = INREG(MC_FB_LOCATION) << 16;
+ if (local_base == rinfo->fb_local_base)
+ return;
-static inline void radeon_fifo_wait(struct radeonfb_info *rinfo, int entries)
-{
- if (entries <= rinfo->fifo_free)
- rinfo->fifo_free -= entries;
- else
- radeon_fifo_update_and_wait(rinfo, entries);
-}
+ rinfo->fb_local_base = local_base;
-static inline void radeonfb_set_creg(struct radeonfb_info *rinfo, u32 reg,
- u32 *cache, u32 new_val)
-{
- if (new_val == *cache)
- return;
- *cache = new_val;
- radeon_fifo_wait(rinfo, 1);
- OUTREG(reg, new_val);
+ radeon_fifo_wait (3);
+ OUTREG(DEFAULT_PITCH_OFFSET, (rinfo->pitch << 0x16) |
+ (rinfo->fb_local_base >> 10));
+ OUTREG(DST_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10));
+ OUTREG(SRC_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10));
}
static void radeonfb_prim_fillrect(struct radeonfb_info *rinfo,
const struct fb_fillrect *region)
{
- radeonfb_set_creg(rinfo, DP_GUI_MASTER_CNTL, &rinfo->dp_gui_mc_cache,
- rinfo->dp_gui_mc_base | GMC_BRUSH_SOLID_COLOR | ROP3_P);
- radeonfb_set_creg(rinfo, DP_CNTL, &rinfo->dp_cntl_cache,
- DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM);
- radeonfb_set_creg(rinfo, DP_BRUSH_FRGD_CLR, &rinfo->dp_brush_fg_cache,
- region->color);
-
- /* Ensure the dst cache is flushed and the engine idle before
- * issuing the operation.
- *
- * This works around engine lockups on some cards
- */
-#if FLUSH_CACHE_WORKAROUND
- radeon_fifo_wait(rinfo, 2);
+ radeon_fifo_wait(4);
+
+ OUTREG(DP_GUI_MASTER_CNTL,
+ rinfo->dp_gui_master_cntl /* contains, like GMC_DST_32BPP */
+ | GMC_BRUSH_SOLID_COLOR
+ | ROP3_P);
+ if (radeon_get_dstbpp(rinfo->depth) != DST_8BPP)
+ OUTREG(DP_BRUSH_FRGD_CLR, rinfo->pseudo_palette[region->color]);
+ else
+ OUTREG(DP_BRUSH_FRGD_CLR, region->color);
+ OUTREG(DP_WRITE_MSK, 0xffffffff);
+ OUTREG(DP_CNTL, (DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM));
+
+ radeon_fifo_wait(2);
OUTREG(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL);
OUTREG(WAIT_UNTIL, (WAIT_2D_IDLECLEAN | WAIT_DMA_GUI_IDLE));
-#endif
- radeon_fifo_wait(rinfo, 2);
+
+ radeon_fifo_wait(2);
OUTREG(DST_Y_X, (region->dy << 16) | region->dx);
OUTREG(DST_WIDTH_HEIGHT, (region->width << 16) | region->height);
}
@@ -70,14 +70,15 @@ void radeonfb_fillrect(struct fb_info *info, const struct fb_fillrect *region)
struct fb_fillrect modded;
int vxres, vyres;
- WARN_ON(rinfo->gfx_mode);
- if (info->state != FBINFO_STATE_RUNNING || rinfo->gfx_mode)
+ if (info->state != FBINFO_STATE_RUNNING)
return;
if (info->flags & FBINFO_HWACCEL_DISABLED) {
cfb_fillrect(info, region);
return;
}
+ radeon_fixup_offset(rinfo);
+
vxres = info->var.xres_virtual;
vyres = info->var.yres_virtual;
@@ -90,10 +91,6 @@ void radeonfb_fillrect(struct fb_info *info, const struct fb_fillrect *region)
if(modded.dx + modded.width > vxres) modded.width = vxres - modded.dx;
if(modded.dy + modded.height > vyres) modded.height = vyres - modded.dy;
- if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
- info->fix.visual == FB_VISUAL_DIRECTCOLOR )
- modded.color = ((u32 *) (info->pseudo_palette))[region->color];
-
radeonfb_prim_fillrect(rinfo, &modded);
}
@@ -112,22 +109,22 @@ static void radeonfb_prim_copyarea(struct radeonfb_info *rinfo,
if ( xdir < 0 ) { sx += w-1; dx += w-1; }
if ( ydir < 0 ) { sy += h-1; dy += h-1; }
- radeonfb_set_creg(rinfo, DP_GUI_MASTER_CNTL, &rinfo->dp_gui_mc_cache,
- rinfo->dp_gui_mc_base |
- GMC_BRUSH_NONE |
- GMC_SRC_DATATYPE_COLOR |
- ROP3_S |
- DP_SRC_SOURCE_MEMORY);
- radeonfb_set_creg(rinfo, DP_CNTL, &rinfo->dp_cntl_cache,
- (xdir>=0 ? DST_X_LEFT_TO_RIGHT : 0) |
- (ydir>=0 ? DST_Y_TOP_TO_BOTTOM : 0));
-
-#if FLUSH_CACHE_WORKAROUND
- radeon_fifo_wait(rinfo, 2);
+ radeon_fifo_wait(3);
+ OUTREG(DP_GUI_MASTER_CNTL,
+ rinfo->dp_gui_master_cntl /* i.e. GMC_DST_32BPP */
+ | GMC_BRUSH_NONE
+ | GMC_SRC_DSTCOLOR
+ | ROP3_S
+ | DP_SRC_SOURCE_MEMORY );
+ OUTREG(DP_WRITE_MSK, 0xffffffff);
+ OUTREG(DP_CNTL, (xdir>=0 ? DST_X_LEFT_TO_RIGHT : 0)
+ | (ydir>=0 ? DST_Y_TOP_TO_BOTTOM : 0));
+
+ radeon_fifo_wait(2);
OUTREG(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL);
OUTREG(WAIT_UNTIL, (WAIT_2D_IDLECLEAN | WAIT_DMA_GUI_IDLE));
-#endif
- radeon_fifo_wait(rinfo, 3);
+
+ radeon_fifo_wait(3);
OUTREG(SRC_Y_X, (sy << 16) | sx);
OUTREG(DST_Y_X, (dy << 16) | dx);
OUTREG(DST_HEIGHT_WIDTH, (h << 16) | w);
@@ -146,14 +143,15 @@ void radeonfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
modded.width = area->width;
modded.height = area->height;
- WARN_ON(rinfo->gfx_mode);
- if (info->state != FBINFO_STATE_RUNNING || rinfo->gfx_mode)
+ if (info->state != FBINFO_STATE_RUNNING)
return;
if (info->flags & FBINFO_HWACCEL_DISABLED) {
cfb_copyarea(info, area);
return;
}
+ radeon_fixup_offset(rinfo);
+
vxres = info->var.xres_virtual;
vyres = info->var.yres_virtual;
@@ -170,112 +168,13 @@ void radeonfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
radeonfb_prim_copyarea(rinfo, &modded);
}
-static void radeonfb_prim_imageblit(struct radeonfb_info *rinfo,
- const struct fb_image *image,
- u32 fg, u32 bg)
-{
- unsigned int src_bytes, dwords;
- u32 *bits;
-
- radeonfb_set_creg(rinfo, DP_GUI_MASTER_CNTL, &rinfo->dp_gui_mc_cache,
- rinfo->dp_gui_mc_base |
- GMC_BRUSH_NONE |
- GMC_SRC_DATATYPE_MONO_FG_BG |
- ROP3_S |
- GMC_BYTE_ORDER_MSB_TO_LSB |
- DP_SRC_SOURCE_HOST_DATA);
- radeonfb_set_creg(rinfo, DP_CNTL, &rinfo->dp_cntl_cache,
- DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM);
- radeonfb_set_creg(rinfo, DP_SRC_FRGD_CLR, &rinfo->dp_src_fg_cache, fg);
- radeonfb_set_creg(rinfo, DP_SRC_BKGD_CLR, &rinfo->dp_src_bg_cache, bg);
-
- radeon_fifo_wait(rinfo, 1);
- OUTREG(DST_Y_X, (image->dy << 16) | image->dx);
-
- /* Ensure the dst cache is flushed and the engine idle before
- * issuing the operation.
- *
- * This works around engine lockups on some cards
- */
-#if FLUSH_CACHE_WORKAROUND
- radeon_fifo_wait(rinfo, 2);
- OUTREG(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL);
- OUTREG(WAIT_UNTIL, (WAIT_2D_IDLECLEAN | WAIT_DMA_GUI_IDLE));
-#endif
-
- /* X here pads width to a multiple of 32 and uses the clipper to
- * adjust the result. Is that really necessary ? Things seem to
- * work ok for me without that and the doco doesn't seem to imply
- * there is such a restriction.
- */
- OUTREG(DST_WIDTH_HEIGHT, (image->width << 16) | image->height);
-
- src_bytes = (((image->width * image->depth) + 7) / 8) * image->height;
- dwords = (src_bytes + 3) / 4;
- bits = (u32*)(image->data);
-
- while(dwords >= 8) {
- radeon_fifo_wait(rinfo, 8);
-#if BITS_PER_LONG == 64
- __raw_writeq(*((u64 *)(bits)), rinfo->mmio_base + HOST_DATA0);
- __raw_writeq(*((u64 *)(bits+2)), rinfo->mmio_base + HOST_DATA2);
- __raw_writeq(*((u64 *)(bits+4)), rinfo->mmio_base + HOST_DATA4);
- __raw_writeq(*((u64 *)(bits+6)), rinfo->mmio_base + HOST_DATA6);
- bits += 8;
-#else
- __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA0);
- __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA1);
- __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA2);
- __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA3);
- __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA4);
- __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA5);
- __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA6);
- __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA7);
-#endif
- dwords -= 8;
- }
- while(dwords--) {
- radeon_fifo_wait(rinfo, 1);
- __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA0);
- }
-}
-
void radeonfb_imageblit(struct fb_info *info, const struct fb_image *image)
{
struct radeonfb_info *rinfo = info->par;
- u32 fg, bg;
-
- WARN_ON(rinfo->gfx_mode);
- if (info->state != FBINFO_STATE_RUNNING || rinfo->gfx_mode)
- return;
- if (!image->width || !image->height)
+ if (info->state != FBINFO_STATE_RUNNING)
return;
-
- /* We only do 1 bpp color expansion for now */
- if (info->flags & FBINFO_HWACCEL_DISABLED || image->depth != 1)
- goto fallback;
-
- /* Fallback if running out of the screen. We may do clipping
- * in the future */
- if ((image->dx + image->width) > info->var.xres_virtual ||
- (image->dy + image->height) > info->var.yres_virtual)
- goto fallback;
-
- if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
- info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
- fg = ((u32*)(info->pseudo_palette))[image->fg_color];
- bg = ((u32*)(info->pseudo_palette))[image->bg_color];
- } else {
- fg = image->fg_color;
- bg = image->bg_color;
- }
-
- radeonfb_prim_imageblit(rinfo, image, fg, bg);
- return;
-
- fallback:
- radeon_engine_idle(rinfo);
+ radeon_engine_idle();
cfb_imageblit(info, image);
}
@@ -286,8 +185,7 @@ int radeonfb_sync(struct fb_info *info)
if (info->state != FBINFO_STATE_RUNNING)
return 0;
-
- radeon_engine_idle(rinfo);
+ radeon_engine_idle();
return 0;
}
@@ -363,10 +261,9 @@ void radeonfb_engine_init (struct radeonfb_info *rinfo)
/* disable 3D engine */
OUTREG(RB3D_CNTL, 0);
- rinfo->fifo_free = 0;
radeonfb_engine_reset(rinfo);
- radeon_fifo_wait(rinfo, 1);
+ radeon_fifo_wait (1);
if (IS_R300_VARIANT(rinfo)) {
OUTREG(RB2D_DSTCACHE_MODE, INREG(RB2D_DSTCACHE_MODE) |
RB2D_DC_AUTOFLUSH_ENABLE |
@@ -380,7 +277,7 @@ void radeonfb_engine_init (struct radeonfb_info *rinfo)
OUTREG(RB2D_DSTCACHE_MODE, 0);
}
- radeon_fifo_wait(rinfo, 3);
+ radeon_fifo_wait (3);
/* We re-read MC_FB_LOCATION from card as it can have been
* modified by XFree drivers (ouch !)
*/
@@ -391,57 +288,41 @@ void radeonfb_engine_init (struct radeonfb_info *rinfo)
OUTREG(DST_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10));
OUTREG(SRC_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10));
- radeon_fifo_wait(rinfo, 1);
-#ifdef __BIG_ENDIAN
+ radeon_fifo_wait (1);
+#if defined(__BIG_ENDIAN)
OUTREGP(DP_DATATYPE, HOST_BIG_ENDIAN_EN, ~HOST_BIG_ENDIAN_EN);
#else
OUTREGP(DP_DATATYPE, 0, ~HOST_BIG_ENDIAN_EN);
#endif
- radeon_fifo_wait(rinfo, 2);
+ radeon_fifo_wait (2);
OUTREG(DEFAULT_SC_TOP_LEFT, 0);
OUTREG(DEFAULT_SC_BOTTOM_RIGHT, (DEFAULT_SC_RIGHT_MAX |
DEFAULT_SC_BOTTOM_MAX));
- /* set default DP_GUI_MASTER_CNTL */
temp = radeon_get_dstbpp(rinfo->depth);
- rinfo->dp_gui_mc_base = ((temp << 8) | GMC_CLR_CMP_CNTL_DIS);
+ rinfo->dp_gui_master_cntl = ((temp << 8) | GMC_CLR_CMP_CNTL_DIS);
- rinfo->dp_gui_mc_cache = rinfo->dp_gui_mc_base |
- GMC_BRUSH_SOLID_COLOR |
- GMC_SRC_DATATYPE_COLOR;
- radeon_fifo_wait(rinfo, 1);
- OUTREG(DP_GUI_MASTER_CNTL, rinfo->dp_gui_mc_cache);
+ radeon_fifo_wait (1);
+ OUTREG(DP_GUI_MASTER_CNTL, (rinfo->dp_gui_master_cntl |
+ GMC_BRUSH_SOLID_COLOR |
+ GMC_SRC_DATATYPE_COLOR));
+ radeon_fifo_wait (7);
/* clear line drawing regs */
- radeon_fifo_wait(rinfo, 2);
OUTREG(DST_LINE_START, 0);
OUTREG(DST_LINE_END, 0);
- /* set brush and source color regs */
- rinfo->dp_brush_fg_cache = 0xffffffff;
- rinfo->dp_brush_bg_cache = 0x00000000;
- rinfo->dp_src_fg_cache = 0xffffffff;
- rinfo->dp_src_bg_cache = 0x00000000;
- radeon_fifo_wait(rinfo, 4);
- OUTREG(DP_BRUSH_FRGD_CLR, rinfo->dp_brush_fg_cache);
- OUTREG(DP_BRUSH_BKGD_CLR, rinfo->dp_brush_bg_cache);
- OUTREG(DP_SRC_FRGD_CLR, rinfo->dp_src_fg_cache);
- OUTREG(DP_SRC_BKGD_CLR, rinfo->dp_src_bg_cache);
-
- /* Default direction */
- rinfo->dp_cntl_cache = DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM;
- radeon_fifo_wait(rinfo, 1);
- OUTREG(DP_CNTL, rinfo->dp_cntl_cache);
+ /* set brush color regs */
+ OUTREG(DP_BRUSH_FRGD_CLR, 0xffffffff);
+ OUTREG(DP_BRUSH_BKGD_CLR, 0x00000000);
+
+ /* set source color regs */
+ OUTREG(DP_SRC_FRGD_CLR, 0xffffffff);
+ OUTREG(DP_SRC_BKGD_CLR, 0x00000000);
/* default write mask */
- radeon_fifo_wait(rinfo, 1);
OUTREG(DP_WRITE_MSK, 0xffffffff);
- /* Default to no swapping of host data */
- radeon_fifo_wait(rinfo, 1);
- OUTREG(RBBM_GUICNTL, RBBM_GUICNTL_HOST_DATA_SWAP_NONE);
-
- /* Make sure it's settled */
- radeon_engine_idle(rinfo);
+ radeon_engine_idle ();
}
diff --git a/drivers/video/aty/radeon_backlight.c b/drivers/video/aty/radeon_backlight.c
index f343ba83f0a..1a056adb61c 100644
--- a/drivers/video/aty/radeon_backlight.c
+++ b/drivers/video/aty/radeon_backlight.c
@@ -66,7 +66,7 @@ static int radeon_bl_update_status(struct backlight_device *bd)
level = bd->props.brightness;
del_timer_sync(&rinfo->lvds_timer);
- radeon_engine_idle(rinfo);
+ radeon_engine_idle();
lvds_gen_cntl = INREG(LVDS_GEN_CNTL);
if (level > 0) {
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index 9a5821c65eb..d0f1a7fc2c9 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -852,6 +852,7 @@ static int radeonfb_pan_display (struct fb_var_screeninfo *var,
if (rinfo->asleep)
return 0;
+ radeon_fifo_wait(2);
OUTREG(CRTC_OFFSET, ((var->yoffset * var->xres_virtual + var->xoffset)
* var->bits_per_pixel / 8) & ~7);
return 0;
@@ -881,6 +882,7 @@ static int radeonfb_ioctl (struct fb_info *info, unsigned int cmd,
if (rc)
return rc;
+ radeon_fifo_wait(2);
if (value & 0x01) {
tmp = INREG(LVDS_GEN_CNTL);
@@ -938,7 +940,7 @@ int radeon_screen_blank(struct radeonfb_info *rinfo, int blank, int mode_switch)
if (rinfo->lock_blank)
return 0;
- radeon_engine_idle(rinfo);
+ radeon_engine_idle();
val = INREG(CRTC_EXT_CNTL);
val &= ~(CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS |
@@ -1046,7 +1048,7 @@ static int radeonfb_blank (int blank, struct fb_info *info)
if (rinfo->asleep)
return 0;
-
+
return radeon_screen_blank(rinfo, blank, 0);
}
@@ -1072,6 +1074,8 @@ static int radeon_setcolreg (unsigned regno, unsigned red, unsigned green,
pindex = regno;
if (!rinfo->asleep) {
+ radeon_fifo_wait(9);
+
if (rinfo->bpp == 16) {
pindex = regno * 8;
@@ -1240,6 +1244,8 @@ static void radeon_write_pll_regs(struct radeonfb_info *rinfo, struct radeon_reg
{
int i;
+ radeon_fifo_wait(20);
+
/* Workaround from XFree */
if (rinfo->is_mobility) {
/* A temporal workaround for the occational blanking on certain laptop
@@ -1335,7 +1341,7 @@ static void radeon_lvds_timer_func(unsigned long data)
{
struct radeonfb_info *rinfo = (struct radeonfb_info *)data;
- radeon_engine_idle(rinfo);
+ radeon_engine_idle();
OUTREG(LVDS_GEN_CNTL, rinfo->pending_lvds_gen_cntl);
}
@@ -1353,11 +1359,10 @@ void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode,
if (nomodeset)
return;
- radeon_engine_idle(rinfo);
-
if (!regs_only)
radeon_screen_blank(rinfo, FB_BLANK_NORMAL, 0);
+ radeon_fifo_wait(31);
for (i=0; i<10; i++)
OUTREG(common_regs[i].reg, common_regs[i].val);
@@ -1385,6 +1390,7 @@ void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode,
radeon_write_pll_regs(rinfo, mode);
if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) {
+ radeon_fifo_wait(10);
OUTREG(FP_CRTC_H_TOTAL_DISP, mode->fp_crtc_h_total_disp);
OUTREG(FP_CRTC_V_TOTAL_DISP, mode->fp_crtc_v_total_disp);
OUTREG(FP_H_SYNC_STRT_WID, mode->fp_h_sync_strt_wid);
@@ -1399,6 +1405,7 @@ void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode,
if (!regs_only)
radeon_screen_blank(rinfo, FB_BLANK_UNBLANK, 0);
+ radeon_fifo_wait(2);
OUTPLL(VCLK_ECP_CNTL, mode->vclk_ecp_cntl);
return;
@@ -1549,7 +1556,7 @@ static int radeonfb_set_par(struct fb_info *info)
/* We always want engine to be idle on a mode switch, even
* if we won't actually change the mode
*/
- radeon_engine_idle(rinfo);
+ radeon_engine_idle();
hSyncStart = mode->xres + mode->right_margin;
hSyncEnd = hSyncStart + mode->hsync_len;
@@ -1844,6 +1851,7 @@ static int radeonfb_set_par(struct fb_info *info)
return 0;
}
+
static struct fb_ops radeonfb_ops = {
.owner = THIS_MODULE,
.fb_check_var = radeonfb_check_var,
@@ -1867,7 +1875,6 @@ static int __devinit radeon_set_fbinfo (struct radeonfb_info *rinfo)
info->par = rinfo;
info->pseudo_palette = rinfo->pseudo_palette;
info->flags = FBINFO_DEFAULT
- | FBINFO_HWACCEL_IMAGEBLIT
| FBINFO_HWACCEL_COPYAREA
| FBINFO_HWACCEL_FILLRECT
| FBINFO_HWACCEL_XPAN
@@ -1999,6 +2006,7 @@ static void radeon_identify_vram(struct radeonfb_info *rinfo)
u32 tom = INREG(NB_TOM);
tmp = ((((tom >> 16) - (tom & 0xffff) + 1) << 6) * 1024);
+ radeon_fifo_wait(6);
OUTREG(MC_FB_LOCATION, tom);
OUTREG(DISPLAY_BASE_ADDR, (tom & 0xffff) << 16);
OUTREG(CRTC2_DISPLAY_BASE_ADDR, (tom & 0xffff) << 16);
diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c
index 3df5015f1d1..675abdafc2d 100644
--- a/drivers/video/aty/radeon_pm.c
+++ b/drivers/video/aty/radeon_pm.c
@@ -2653,9 +2653,9 @@ int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg)
if (!(info->flags & FBINFO_HWACCEL_DISABLED)) {
/* Make sure engine is reset */
- radeon_engine_idle(rinfo);
+ radeon_engine_idle();
radeonfb_engine_reset(rinfo);
- radeon_engine_idle(rinfo);
+ radeon_engine_idle();
}
/* Blank display and LCD */
@@ -2767,7 +2767,7 @@ int radeonfb_pci_resume(struct pci_dev *pdev)
rinfo->asleep = 0;
} else
- radeon_engine_idle(rinfo);
+ radeon_engine_idle();
/* Restore display & engine */
radeon_write_mode (rinfo, &rinfo->state, 1);
diff --git a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h
index ea0b5b47aca..3ea1b00fdd2 100644
--- a/drivers/video/aty/radeonfb.h
+++ b/drivers/video/aty/radeonfb.h
@@ -336,15 +336,7 @@ struct radeonfb_info {
int mon2_type;
u8 *mon2_EDID;
- /* accel bits */
- u32 dp_gui_mc_base;
- u32 dp_gui_mc_cache;
- u32 dp_cntl_cache;
- u32 dp_brush_fg_cache;
- u32 dp_brush_bg_cache;
- u32 dp_src_fg_cache;
- u32 dp_src_bg_cache;
- u32 fifo_free;
+ u32 dp_gui_master_cntl;
struct pll_info pll;
@@ -356,7 +348,6 @@ struct radeonfb_info {
int lock_blank;
int dynclk;
int no_schedule;
- int gfx_mode;
enum radeon_pm_mode pm_mode;
reinit_function_ptr reinit_func;
@@ -401,14 +392,8 @@ static inline void _radeon_msleep(struct radeonfb_info *rinfo, unsigned long ms)
#define OUTREG8(addr,val) writeb(val, (rinfo->mmio_base)+addr)
#define INREG16(addr) readw((rinfo->mmio_base)+addr)
#define OUTREG16(addr,val) writew(val, (rinfo->mmio_base)+addr)
-
-#ifdef CONFIG_PPC
-#define INREG(addr) ({ eieio(); ld_le32(rinfo->mmio_base+(addr)); })
-#define OUTREG(addr,val) do { eieio(); st_le32(rinfo->mmio_base+(addr),(val)); } while(0)
-#else
#define INREG(addr) readl((rinfo->mmio_base)+addr)
#define OUTREG(addr,val) writel(val, (rinfo->mmio_base)+addr)
-#endif
static inline void _OUTREGP(struct radeonfb_info *rinfo, u32 addr,
u32 val, u32 mask)
@@ -550,7 +535,17 @@ static inline u32 radeon_get_dstbpp(u16 depth)
* 2D Engine helper routines
*/
-extern void radeon_fifo_update_and_wait(struct radeonfb_info *rinfo, int entries);
+static inline void _radeon_fifo_wait(struct radeonfb_info *rinfo, int entries)
+{
+ int i;
+
+ for (i=0; i<2000000; i++) {
+ if ((INREG(RBBM_STATUS) & 0x7f) >= entries)
+ return;
+ udelay(1);
+ }
+ printk(KERN_ERR "radeonfb: FIFO Timeout !\n");
+}
static inline void radeon_engine_flush (struct radeonfb_info *rinfo)
{
@@ -563,7 +558,7 @@ static inline void radeon_engine_flush (struct radeonfb_info *rinfo)
/* Ensure FIFO is empty, ie, make sure the flush commands
* has reached the cache
*/
- radeon_fifo_update_and_wait(rinfo, 64);
+ _radeon_fifo_wait (rinfo, 64);
/* Wait for the flush to complete */
for (i=0; i < 2000000; i++) {
@@ -575,12 +570,12 @@ static inline void radeon_engine_flush (struct radeonfb_info *rinfo)
}
-static inline void radeon_engine_idle(struct radeonfb_info *rinfo)
+static inline void _radeon_engine_idle(struct radeonfb_info *rinfo)
{
int i;
/* ensure FIFO is empty before waiting for idle */
- radeon_fifo_update_and_wait (rinfo, 64);
+ _radeon_fifo_wait (rinfo, 64);
for (i=0; i<2000000; i++) {
if (((INREG(RBBM_STATUS) & GUI_ACTIVE)) == 0) {
@@ -593,6 +588,8 @@ static inline void radeon_engine_idle(struct radeonfb_info *rinfo)
}
+#define radeon_engine_idle() _radeon_engine_idle(rinfo)
+#define radeon_fifo_wait(entries) _radeon_fifo_wait(rinfo,entries)
#define radeon_msleep(ms) _radeon_msleep(rinfo,ms)
@@ -622,7 +619,6 @@ extern void radeonfb_imageblit(struct fb_info *p, const struct fb_image *image);
extern int radeonfb_sync(struct fb_info *info);
extern void radeonfb_engine_init (struct radeonfb_info *rinfo);
extern void radeonfb_engine_reset(struct radeonfb_info *rinfo);
-extern void radeon_fixup_mem_offset(struct radeonfb_info *rinfo);
/* Other functions */
extern int radeon_screen_blank(struct radeonfb_info *rinfo, int blank, int mode_switch);
diff --git a/drivers/video/backlight/da903x.c b/drivers/video/backlight/da903x.c
index 242c3825016..93bb4340cc6 100644
--- a/drivers/video/backlight/da903x.c
+++ b/drivers/video/backlight/da903x.c
@@ -119,6 +119,7 @@ static int da903x_backlight_probe(struct platform_device *pdev)
default:
dev_err(&pdev->dev, "invalid backlight device ID(%d)\n",
pdev->id);
+ kfree(data);
return -EINVAL;
}
@@ -130,6 +131,7 @@ static int da903x_backlight_probe(struct platform_device *pdev)
data, &da903x_backlight_ops);
if (IS_ERR(bl)) {
dev_err(&pdev->dev, "failed to register backlight\n");
+ kfree(data);
return PTR_ERR(bl);
}
diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c
index 8e1731d3b22..680e57b616c 100644
--- a/drivers/video/backlight/lcd.c
+++ b/drivers/video/backlight/lcd.c
@@ -42,10 +42,13 @@ static int fb_notifier_callback(struct notifier_block *self,
mutex_lock(&ld->ops_lock);
if (!ld->ops->check_fb || ld->ops->check_fb(ld, evdata->info)) {
- if (event == FB_EVENT_BLANK)
- ld->ops->set_power(ld, *(int *)evdata->data);
- else
- ld->ops->set_mode(ld, evdata->data);
+ if (event == FB_EVENT_BLANK) {
+ if (ld->ops->set_power)
+ ld->ops->set_power(ld, *(int *)evdata->data);
+ } else {
+ if (ld->ops->set_mode)
+ ld->ops->set_mode(ld, evdata->data);
+ }
}
mutex_unlock(&ld->ops_lock);
return 0;
diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c
index 8a8760230bc..a2aa6ddffbe 100644
--- a/drivers/video/cirrusfb.c
+++ b/drivers/video/cirrusfb.c
@@ -2462,8 +2462,7 @@ static int __init cirrusfb_init(void)
#ifndef MODULE
static int __init cirrusfb_setup(char *options) {
- char *this_opt, s[32];
- int i;
+ char *this_opt;
DPRINTK("ENTER\n");
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index b92947d62ad..0b2adefe9e3 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -2389,16 +2389,13 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch)
if (!fbcon_is_inactive(vc, info)) {
if (ops->blank_state != blank) {
- int ret = 1;
-
ops->blank_state = blank;
fbcon_cursor(vc, blank ? CM_ERASE : CM_DRAW);
ops->cursor_flash = (!blank);
- if (info->fbops->fb_blank)
- ret = info->fbops->fb_blank(blank, info);
- if (ret)
- fbcon_generic_blank(vc, info, blank);
+ if (!(info->flags & FBINFO_MISC_USEREVENT))
+ if (fb_blank(info, blank))
+ fbcon_generic_blank(vc, info, blank);
}
if (!blank)
@@ -3534,12 +3531,18 @@ static void fbcon_exit(void)
softback_buf = 0UL;
for (i = 0; i < FB_MAX; i++) {
+ int pending;
+
mapped = 0;
info = registered_fb[i];
if (info == NULL)
continue;
+ pending = cancel_work_sync(&info->queue);
+ DPRINTK("fbcon: %s pending work\n", (pending ? "canceled" :
+ "no"));
+
for (j = first_fb_vc; j <= last_fb_vc; j++) {
if (con2fb_map[j] == i)
mapped = 1;
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 1d5ae39cb27..3c65b0d6761 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -230,7 +230,7 @@ static void fb_set_logo_directpalette(struct fb_info *info,
greenshift = info->var.green.offset;
blueshift = info->var.blue.offset;
- for (i = 32; i < logo->clutsize; i++)
+ for (i = 32; i < 32 + logo->clutsize; i++)
palette[i] = i << redshift | i << greenshift | i << blueshift;
}
diff --git a/drivers/video/macfb.c b/drivers/video/macfb.c
index b790ddff76f..ee380d5f341 100644
--- a/drivers/video/macfb.c
+++ b/drivers/video/macfb.c
@@ -164,7 +164,6 @@ static struct fb_var_screeninfo macfb_defined = {
};
static struct fb_fix_screeninfo macfb_fix = {
- .id = "Macintosh ",
.type = FB_TYPE_PACKED_PIXELS,
.accel = FB_ACCEL_NONE,
};
@@ -760,22 +759,22 @@ static int __init macfb_init(void)
switch(ndev->dr_hw) {
case NUBUS_DRHW_APPLE_MDC:
- strcat( macfb_fix.id, "Display Card" );
+ strcpy(macfb_fix.id, "Mac Disp. Card");
macfb_setpalette = mdc_setpalette;
macfb_defined.activate = FB_ACTIVATE_NOW;
break;
case NUBUS_DRHW_APPLE_TFB:
- strcat( macfb_fix.id, "Toby" );
+ strcpy(macfb_fix.id, "Toby");
macfb_setpalette = toby_setpalette;
macfb_defined.activate = FB_ACTIVATE_NOW;
break;
case NUBUS_DRHW_APPLE_JET:
- strcat( macfb_fix.id, "Jet");
+ strcpy(macfb_fix.id, "Jet");
macfb_setpalette = jet_setpalette;
macfb_defined.activate = FB_ACTIVATE_NOW;
break;
default:
- strcat( macfb_fix.id, "Generic NuBus" );
+ strcpy(macfb_fix.id, "Generic NuBus");
break;
}
}
@@ -786,21 +785,11 @@ static int __init macfb_init(void)
if (!video_is_nubus)
switch( mac_bi_data.id )
{
- /* These don't have onboard video. Eventually, we may
- be able to write separate framebuffer drivers for
- them (tobyfb.c, hiresfb.c, etc, etc) */
- case MAC_MODEL_II:
- case MAC_MODEL_IIX:
- case MAC_MODEL_IICX:
- case MAC_MODEL_IIFX:
- strcat( macfb_fix.id, "Generic NuBus" );
- break;
-
/* Valkyrie Quadras */
case MAC_MODEL_Q630:
/* I'm not sure about this one */
case MAC_MODEL_P588:
- strcat( macfb_fix.id, "Valkyrie built-in" );
+ strcpy(macfb_fix.id, "Valkyrie");
macfb_setpalette = valkyrie_setpalette;
macfb_defined.activate = FB_ACTIVATE_NOW;
valkyrie_cmap_regs = ioremap(DAC_BASE, 0x1000);
@@ -823,7 +812,7 @@ static int __init macfb_init(void)
case MAC_MODEL_Q700:
case MAC_MODEL_Q900:
case MAC_MODEL_Q950:
- strcat( macfb_fix.id, "DAFB built-in" );
+ strcpy(macfb_fix.id, "DAFB");
macfb_setpalette = dafb_setpalette;
macfb_defined.activate = FB_ACTIVATE_NOW;
dafb_cmap_regs = ioremap(DAFB_BASE, 0x1000);
@@ -831,7 +820,7 @@ static int __init macfb_init(void)
/* LC II uses the V8 framebuffer */
case MAC_MODEL_LCII:
- strcat( macfb_fix.id, "V8 built-in" );
+ strcpy(macfb_fix.id, "V8");
macfb_setpalette = v8_brazil_setpalette;
macfb_defined.activate = FB_ACTIVATE_NOW;
v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000);
@@ -843,7 +832,7 @@ static int __init macfb_init(void)
case MAC_MODEL_IIVI:
case MAC_MODEL_IIVX:
case MAC_MODEL_P600:
- strcat( macfb_fix.id, "Brazil built-in" );
+ strcpy(macfb_fix.id, "Brazil");
macfb_setpalette = v8_brazil_setpalette;
macfb_defined.activate = FB_ACTIVATE_NOW;
v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000);
@@ -860,7 +849,7 @@ static int __init macfb_init(void)
case MAC_MODEL_P460:
macfb_setpalette = v8_brazil_setpalette;
macfb_defined.activate = FB_ACTIVATE_NOW;
- strcat( macfb_fix.id, "Sonora built-in" );
+ strcpy(macfb_fix.id, "Sonora");
v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000);
break;
@@ -871,7 +860,7 @@ static int __init macfb_init(void)
case MAC_MODEL_IISI:
macfb_setpalette = rbv_setpalette;
macfb_defined.activate = FB_ACTIVATE_NOW;
- strcat( macfb_fix.id, "RBV built-in" );
+ strcpy(macfb_fix.id, "RBV");
rbv_cmap_regs = ioremap(DAC_BASE, 0x1000);
break;
@@ -880,7 +869,7 @@ static int __init macfb_init(void)
case MAC_MODEL_C660:
macfb_setpalette = civic_setpalette;
macfb_defined.activate = FB_ACTIVATE_NOW;
- strcat( macfb_fix.id, "Civic built-in" );
+ strcpy(macfb_fix.id, "Civic");
civic_cmap_regs = ioremap(CIVIC_BASE, 0x1000);
break;
@@ -901,7 +890,7 @@ static int __init macfb_init(void)
v8_brazil_cmap_regs =
ioremap(DAC_BASE, 0x1000);
}
- strcat( macfb_fix.id, "LC built-in" );
+ strcpy(macfb_fix.id, "LC");
break;
/* We think this may be like the LC II */
case MAC_MODEL_CCL:
@@ -911,18 +900,18 @@ static int __init macfb_init(void)
v8_brazil_cmap_regs =
ioremap(DAC_BASE, 0x1000);
}
- strcat( macfb_fix.id, "Color Classic built-in" );
+ strcpy(macfb_fix.id, "Color Classic");
break;
/* And we *do* mean "weirdos" */
case MAC_MODEL_TV:
- strcat( macfb_fix.id, "Mac TV built-in" );
+ strcpy(macfb_fix.id, "Mac TV");
break;
/* These don't have colour, so no need to worry */
case MAC_MODEL_SE30:
case MAC_MODEL_CLII:
- strcat( macfb_fix.id, "Monochrome built-in" );
+ strcpy(macfb_fix.id, "Monochrome");
break;
/* Powerbooks are particularly difficult. Many of
@@ -935,7 +924,7 @@ static int __init macfb_init(void)
case MAC_MODEL_PB140:
case MAC_MODEL_PB145:
case MAC_MODEL_PB170:
- strcat( macfb_fix.id, "DDC built-in" );
+ strcpy(macfb_fix.id, "DDC");
break;
/* Internal is GSC, External (if present) is ViSC */
@@ -945,13 +934,13 @@ static int __init macfb_init(void)
case MAC_MODEL_PB180:
case MAC_MODEL_PB210:
case MAC_MODEL_PB230:
- strcat( macfb_fix.id, "GSC built-in" );
+ strcpy(macfb_fix.id, "GSC");
break;
/* Internal is TIM, External is ViSC */
case MAC_MODEL_PB165C:
case MAC_MODEL_PB180C:
- strcat( macfb_fix.id, "TIM built-in" );
+ strcpy(macfb_fix.id, "TIM");
break;
/* Internal is CSC, External is Keystone+Ariel. */
@@ -963,12 +952,12 @@ static int __init macfb_init(void)
case MAC_MODEL_PB280C:
macfb_setpalette = csc_setpalette;
macfb_defined.activate = FB_ACTIVATE_NOW;
- strcat( macfb_fix.id, "CSC built-in" );
+ strcpy(macfb_fix.id, "CSC");
csc_cmap_regs = ioremap(CSC_BASE, 0x1000);
break;
default:
- strcat( macfb_fix.id, "Unknown/Unsupported built-in" );
+ strcpy(macfb_fix.id, "Unknown");
break;
}
@@ -978,16 +967,23 @@ static int __init macfb_init(void)
fb_info.pseudo_palette = pseudo_palette;
fb_info.flags = FBINFO_DEFAULT;
- fb_alloc_cmap(&fb_info.cmap, video_cmap_len, 0);
+ err = fb_alloc_cmap(&fb_info.cmap, video_cmap_len, 0);
+ if (err)
+ goto fail_unmap;
err = register_framebuffer(&fb_info);
- if (!err)
- printk("fb%d: %s frame buffer device\n",
- fb_info.node, fb_info.fix.id);
- else {
- iounmap(fb_info.screen_base);
- iounmap_macfb();
- }
+ if (err)
+ goto fail_dealloc;
+
+ printk("fb%d: %s frame buffer device\n",
+ fb_info.node, fb_info.fix.id);
+ return 0;
+
+fail_dealloc:
+ fb_dealloc_cmap(&fb_info.cmap);
+fail_unmap:
+ iounmap(fb_info.screen_base);
+ iounmap_macfb();
return err;
}
diff --git a/drivers/video/mb862xx/mb862xxfb.c b/drivers/video/mb862xx/mb862xxfb.c
index 38718d95fbb..fb64234a382 100644
--- a/drivers/video/mb862xx/mb862xxfb.c
+++ b/drivers/video/mb862xx/mb862xxfb.c
@@ -927,9 +927,9 @@ static int __devinit mb862xx_pci_probe(struct pci_dev *pdev,
}
dev_dbg(dev, "fb phys 0x%llx 0x%lx\n",
- (u64)par->fb_base_phys, (ulong)par->mapped_vram);
+ (unsigned long long)par->fb_base_phys, (ulong)par->mapped_vram);
dev_dbg(dev, "mmio phys 0x%llx 0x%lx\n",
- (u64)par->mmio_base_phys, (ulong)par->mmio_len);
+ (unsigned long long)par->mmio_base_phys, (ulong)par->mmio_len);
if (mb862xx_pci_gdc_init(par))
goto io_unmap;
diff --git a/drivers/video/omap/Makefile b/drivers/video/omap/Makefile
index 99da8b6d2c3..ed13889c116 100644
--- a/drivers/video/omap/Makefile
+++ b/drivers/video/omap/Makefile
@@ -23,7 +23,6 @@ objs-y$(CONFIG_MACH_OMAP_PALMZ71) += lcd_palmz71.o
objs-$(CONFIG_ARCH_OMAP16XX)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1610.o
objs-$(CONFIG_ARCH_OMAP15XX)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1510.o
objs-y$(CONFIG_MACH_OMAP_OSK) += lcd_osk.o
-objs-y$(CONFIG_MACH_SX1) += lcd_sx1.o
omapfb-objs := $(objs-yy)
diff --git a/drivers/video/omap/lcd_sx1.c b/drivers/video/omap/lcd_sx1.c
deleted file mode 100644
index e55de201b8f..00000000000
--- a/drivers/video/omap/lcd_sx1.c
+++ /dev/null
@@ -1,327 +0,0 @@
-/*
- * LCD panel support for the Siemens SX1 mobile phone
- *
- * Current version : Vovan888@gmail.com, great help from FCA00000
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-
-#include <mach/gpio.h>
-#include <mach/omapfb.h>
-#include <mach/mcbsp.h>
-#include <mach/mux.h>
-
-/*
- * OMAP310 GPIO registers
- */
-#define GPIO_DATA_INPUT 0xfffce000
-#define GPIO_DATA_OUTPUT 0xfffce004
-#define GPIO_DIR_CONTROL 0xfffce008
-#define GPIO_INT_CONTROL 0xfffce00c
-#define GPIO_INT_MASK 0xfffce010
-#define GPIO_INT_STATUS 0xfffce014
-#define GPIO_PIN_CONTROL 0xfffce018
-
-
-#define A_LCD_SSC_RD 3
-#define A_LCD_SSC_SD 7
-#define _A_LCD_RESET 9
-#define _A_LCD_SSC_CS 12
-#define _A_LCD_SSC_A0 13
-
-#define DSP_REG 0xE1017024
-
-const unsigned char INIT_1[12] = {
- 0x1C, 0x02, 0x88, 0x00, 0x1E, 0xE0, 0x00, 0xDC, 0x00, 0x02, 0x00
-};
-
-const unsigned char INIT_2[127] = {
- 0x15, 0x00, 0x29, 0x00, 0x3E, 0x00, 0x51, 0x00,
- 0x65, 0x00, 0x7A, 0x00, 0x8D, 0x00, 0xA1, 0x00,
- 0xB6, 0x00, 0xC7, 0x00, 0xD8, 0x00, 0xEB, 0x00,
- 0xFB, 0x00, 0x0B, 0x01, 0x1B, 0x01, 0x27, 0x01,
- 0x34, 0x01, 0x41, 0x01, 0x4C, 0x01, 0x55, 0x01,
- 0x5F, 0x01, 0x68, 0x01, 0x70, 0x01, 0x78, 0x01,
- 0x7E, 0x01, 0x86, 0x01, 0x8C, 0x01, 0x94, 0x01,
- 0x9B, 0x01, 0xA1, 0x01, 0xA4, 0x01, 0xA9, 0x01,
- 0xAD, 0x01, 0xB2, 0x01, 0xB7, 0x01, 0xBC, 0x01,
- 0xC0, 0x01, 0xC4, 0x01, 0xC8, 0x01, 0xCB, 0x01,
- 0xCF, 0x01, 0xD2, 0x01, 0xD5, 0x01, 0xD8, 0x01,
- 0xDB, 0x01, 0xE0, 0x01, 0xE3, 0x01, 0xE6, 0x01,
- 0xE8, 0x01, 0xEB, 0x01, 0xEE, 0x01, 0xF1, 0x01,
- 0xF3, 0x01, 0xF8, 0x01, 0xF9, 0x01, 0xFC, 0x01,
- 0x00, 0x02, 0x03, 0x02, 0x07, 0x02, 0x09, 0x02,
- 0x0E, 0x02, 0x13, 0x02, 0x1C, 0x02, 0x00
-};
-
-const unsigned char INIT_3[15] = {
- 0x14, 0x26, 0x33, 0x3D, 0x45, 0x4D, 0x53, 0x59,
- 0x5E, 0x63, 0x67, 0x6D, 0x71, 0x78, 0xFF
-};
-
-static void epson_sendbyte(int flag, unsigned char byte)
-{
- int i, shifter = 0x80;
-
- if (!flag)
- gpio_set_value(_A_LCD_SSC_A0, 0);
- mdelay(2);
- gpio_set_value(A_LCD_SSC_RD, 1);
-
- gpio_set_value(A_LCD_SSC_SD, flag);
-
- OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2200);
- OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2202);
- for (i = 0; i < 8; i++) {
- OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2200);
- gpio_set_value(A_LCD_SSC_SD, shifter & byte);
- OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2202);
- shifter >>= 1;
- }
- gpio_set_value(_A_LCD_SSC_A0, 1);
-}
-
-static void init_system(void)
-{
- omap_mcbsp_request(OMAP_MCBSP3);
- omap_mcbsp_stop(OMAP_MCBSP3);
-}
-
-static void setup_GPIO(void)
-{
- /* new wave */
- gpio_request(A_LCD_SSC_RD, "lcd_ssc_rd");
- gpio_request(A_LCD_SSC_SD, "lcd_ssc_sd");
- gpio_request(_A_LCD_RESET, "lcd_reset");
- gpio_request(_A_LCD_SSC_CS, "lcd_ssc_cs");
- gpio_request(_A_LCD_SSC_A0, "lcd_ssc_a0");
-
- /* set GPIOs to output, with initial data */
- gpio_direction_output(A_LCD_SSC_RD, 1);
- gpio_direction_output(A_LCD_SSC_SD, 0);
- gpio_direction_output(_A_LCD_RESET, 0);
- gpio_direction_output(_A_LCD_SSC_CS, 1);
- gpio_direction_output(_A_LCD_SSC_A0, 1);
-}
-
-static void display_init(void)
-{
- int i;
-
- omap_cfg_reg(MCBSP3_CLKX);
-
- mdelay(2);
- setup_GPIO();
- mdelay(2);
-
- /* reset LCD */
- gpio_set_value(A_LCD_SSC_SD, 1);
- epson_sendbyte(0, 0x25);
-
- gpio_set_value(_A_LCD_RESET, 0);
- mdelay(10);
- gpio_set_value(_A_LCD_RESET, 1);
-
- gpio_set_value(_A_LCD_SSC_CS, 1);
- mdelay(2);
- gpio_set_value(_A_LCD_SSC_CS, 0);
-
- /* init LCD, phase 1 */
- epson_sendbyte(0, 0xCA);
- for (i = 0; i < 10; i++)
- epson_sendbyte(1, INIT_1[i]);
- gpio_set_value(_A_LCD_SSC_CS, 1);
- gpio_set_value(_A_LCD_SSC_CS, 0);
-
- /* init LCD phase 2 */
- epson_sendbyte(0, 0xCB);
- for (i = 0; i < 125; i++)
- epson_sendbyte(1, INIT_2[i]);
- gpio_set_value(_A_LCD_SSC_CS, 1);
- gpio_set_value(_A_LCD_SSC_CS, 0);
-
- /* init LCD phase 2a */
- epson_sendbyte(0, 0xCC);
- for (i = 0; i < 14; i++)
- epson_sendbyte(1, INIT_3[i]);
- gpio_set_value(_A_LCD_SSC_CS, 1);
- gpio_set_value(_A_LCD_SSC_CS, 0);
-
- /* init LCD phase 3 */
- epson_sendbyte(0, 0xBC);
- epson_sendbyte(1, 0x08);
- gpio_set_value(_A_LCD_SSC_CS, 1);
- gpio_set_value(_A_LCD_SSC_CS, 0);
-
- /* init LCD phase 4 */
- epson_sendbyte(0, 0x07);
- epson_sendbyte(1, 0x05);
- gpio_set_value(_A_LCD_SSC_CS, 1);
- gpio_set_value(_A_LCD_SSC_CS, 0);
-
- /* init LCD phase 5 */
- epson_sendbyte(0, 0x94);
- gpio_set_value(_A_LCD_SSC_CS, 1);
- gpio_set_value(_A_LCD_SSC_CS, 0);
-
- /* init LCD phase 6 */
- epson_sendbyte(0, 0xC6);
- epson_sendbyte(1, 0x80);
- gpio_set_value(_A_LCD_SSC_CS, 1);
- mdelay(100); /* used to be 1000 */
- gpio_set_value(_A_LCD_SSC_CS, 0);
-
- /* init LCD phase 7 */
- epson_sendbyte(0, 0x16);
- epson_sendbyte(1, 0x02);
- epson_sendbyte(1, 0x00);
- epson_sendbyte(1, 0xB1);
- epson_sendbyte(1, 0x00);
- gpio_set_value(_A_LCD_SSC_CS, 1);
- gpio_set_value(_A_LCD_SSC_CS, 0);
-
- /* init LCD phase 8 */
- epson_sendbyte(0, 0x76);
- epson_sendbyte(1, 0x00);
- epson_sendbyte(1, 0x00);
- epson_sendbyte(1, 0xDB);
- epson_sendbyte(1, 0x00);
- gpio_set_value(_A_LCD_SSC_CS, 1);
- gpio_set_value(_A_LCD_SSC_CS, 0);
-
- /* init LCD phase 9 */
- epson_sendbyte(0, 0xAF);
- gpio_set_value(_A_LCD_SSC_CS, 1);
-}
-
-static int sx1_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
-{
- return 0;
-}
-
-static void sx1_panel_cleanup(struct lcd_panel *panel)
-{
-}
-
-static void sx1_panel_disable(struct lcd_panel *panel)
-{
- printk(KERN_INFO "SX1: LCD panel disable\n");
- sx1_setmmipower(0);
- gpio_set_value(_A_LCD_SSC_CS, 1);
-
- epson_sendbyte(0, 0x25);
- gpio_set_value(_A_LCD_SSC_CS, 0);
-
- epson_sendbyte(0, 0xAE);
- gpio_set_value(_A_LCD_SSC_CS, 1);
- mdelay(100);
- gpio_set_value(_A_LCD_SSC_CS, 0);
-
- epson_sendbyte(0, 0x95);
- gpio_set_value(_A_LCD_SSC_CS, 1);
-}
-
-static int sx1_panel_enable(struct lcd_panel *panel)
-{
- printk(KERN_INFO "lcd_sx1: LCD panel enable\n");
- init_system();
- display_init();
-
- sx1_setmmipower(1);
- sx1_setbacklight(0x18);
- sx1_setkeylight (0x06);
- return 0;
-}
-
-
-static unsigned long sx1_panel_get_caps(struct lcd_panel *panel)
-{
- return 0;
-}
-
-struct lcd_panel sx1_panel = {
- .name = "sx1",
- .config = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC |
- OMAP_LCDC_INV_HSYNC | OMAP_LCDC_INV_PIX_CLOCK |
- OMAP_LCDC_INV_OUTPUT_EN,
-
- .x_res = 176,
- .y_res = 220,
- .data_lines = 16,
- .bpp = 16,
- .hsw = 5,
- .hfp = 5,
- .hbp = 5,
- .vsw = 2,
- .vfp = 1,
- .vbp = 1,
- .pixel_clock = 1500,
-
- .init = sx1_panel_init,
- .cleanup = sx1_panel_cleanup,
- .enable = sx1_panel_enable,
- .disable = sx1_panel_disable,
- .get_caps = sx1_panel_get_caps,
-};
-
-static int sx1_panel_probe(struct platform_device *pdev)
-{
- omapfb_register_panel(&sx1_panel);
- return 0;
-}
-
-static int sx1_panel_remove(struct platform_device *pdev)
-{
- return 0;
-}
-
-static int sx1_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
-{
- return 0;
-}
-
-static int sx1_panel_resume(struct platform_device *pdev)
-{
- return 0;
-}
-
-struct platform_driver sx1_panel_driver = {
- .probe = sx1_panel_probe,
- .remove = sx1_panel_remove,
- .suspend = sx1_panel_suspend,
- .resume = sx1_panel_resume,
- .driver = {
- .name = "lcd_sx1",
- .owner = THIS_MODULE,
- },
-};
-
-static int sx1_panel_drv_init(void)
-{
- return platform_driver_register(&sx1_panel_driver);
-}
-
-static void sx1_panel_drv_cleanup(void)
-{
- platform_driver_unregister(&sx1_panel_driver);
-}
-
-module_init(sx1_panel_drv_init);
-module_exit(sx1_panel_drv_cleanup);
diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c
index 5a5e407dc45..1a49519dafa 100644
--- a/drivers/video/omap/omapfb_main.c
+++ b/drivers/video/omap/omapfb_main.c
@@ -392,7 +392,7 @@ static void set_fb_fix(struct fb_info *fbi)
int bpp;
rg = &plane->fbdev->mem_desc.region[plane->idx];
- fbi->screen_base = (char __iomem *)rg->vaddr;
+ fbi->screen_base = rg->vaddr;
fix->smem_start = rg->paddr;
fix->smem_len = rg->size;
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index 97204497d9f..cc59c52e110 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -804,6 +804,9 @@ static int pxafb_smart_thread(void *arg)
static int pxafb_smart_init(struct pxafb_info *fbi)
{
+ if (!(fbi->lccr0 | LCCR0_LCDT))
+ return 0;
+
fbi->smart_thread = kthread_run(pxafb_smart_thread, fbi,
"lcd_refresh");
if (IS_ERR(fbi->smart_thread)) {
@@ -1372,7 +1375,7 @@ static void pxafb_decode_mach_info(struct pxafb_info *fbi,
fbi->cmap_inverse = inf->cmap_inverse;
fbi->cmap_static = inf->cmap_static;
- switch (lcd_conn & 0xf) {
+ switch (lcd_conn & LCD_TYPE_MASK) {
case LCD_TYPE_MONO_STN:
fbi->lccr0 = LCCR0_CMS;
break;
diff --git a/drivers/video/tmiofb.c b/drivers/video/tmiofb.c
index 2a380011e9b..7baf2dd12d5 100644
--- a/drivers/video/tmiofb.c
+++ b/drivers/video/tmiofb.c
@@ -222,6 +222,9 @@ static irqreturn_t tmiofb_irq(int irq, void *__info)
unsigned int bbisc = tmio_ioread16(par->lcr + LCR_BBISC);
+ tmio_iowrite16(bbisc, par->lcr + LCR_BBISC);
+
+#ifdef CONFIG_FB_TMIO_ACCELL
/*
* We were in polling mode and now we got correct irq.
* Switch back to IRQ-based sync of command FIFO
@@ -231,9 +234,6 @@ static irqreturn_t tmiofb_irq(int irq, void *__info)
par->use_polling = false;
}
- tmio_iowrite16(bbisc, par->lcr + LCR_BBISC);
-
-#ifdef CONFIG_FB_TMIO_ACCELL
if (bbisc & 1)
wake_up(&par->wait_acc);
#endif
@@ -938,7 +938,9 @@ static void tmiofb_dump_regs(struct platform_device *dev)
static int tmiofb_suspend(struct platform_device *dev, pm_message_t state)
{
struct fb_info *info = platform_get_drvdata(dev);
+#ifdef CONFIG_FB_TMIO_ACCELL
struct tmiofb_par *par = info->par;
+#endif
struct mfd_cell *cell = dev->dev.platform_data;
int retval = 0;
@@ -950,12 +952,14 @@ static int tmiofb_suspend(struct platform_device *dev, pm_message_t state)
info->fbops->fb_sync(info);
+#ifdef CONFIG_FB_TMIO_ACCELL
/*
* The fb should be usable even if interrupts are disabled (and they are
* during suspend/resume). Switch temporary to forced polling.
*/
printk(KERN_INFO "tmiofb: switching to polling\n");
par->use_polling = true;
+#endif
tmiofb_hw_stop(dev);
if (cell->suspend)
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c
index 0132eae06f5..73ac754ad80 100644
--- a/drivers/video/via/viafbdev.c
+++ b/drivers/video/via/viafbdev.c
@@ -2036,30 +2036,30 @@ static int viafb_vt1636_proc_write(struct file *file,
return count;
}
-static void viafb_init_proc(struct proc_dir_entry *viafb_entry)
+static void viafb_init_proc(struct proc_dir_entry **viafb_entry)
{
struct proc_dir_entry *entry;
- viafb_entry = proc_mkdir("viafb", NULL);
+ *viafb_entry = proc_mkdir("viafb", NULL);
if (viafb_entry) {
- entry = create_proc_entry("dvp0", 0, viafb_entry);
+ entry = create_proc_entry("dvp0", 0, *viafb_entry);
if (entry) {
entry->owner = THIS_MODULE;
entry->read_proc = viafb_dvp0_proc_read;
entry->write_proc = viafb_dvp0_proc_write;
}
- entry = create_proc_entry("dvp1", 0, viafb_entry);
+ entry = create_proc_entry("dvp1", 0, *viafb_entry);
if (entry) {
entry->owner = THIS_MODULE;
entry->read_proc = viafb_dvp1_proc_read;
entry->write_proc = viafb_dvp1_proc_write;
}
- entry = create_proc_entry("dfph", 0, viafb_entry);
+ entry = create_proc_entry("dfph", 0, *viafb_entry);
if (entry) {
entry->owner = THIS_MODULE;
entry->read_proc = viafb_dfph_proc_read;
entry->write_proc = viafb_dfph_proc_write;
}
- entry = create_proc_entry("dfpl", 0, viafb_entry);
+ entry = create_proc_entry("dfpl", 0, *viafb_entry);
if (entry) {
entry->owner = THIS_MODULE;
entry->read_proc = viafb_dfpl_proc_read;
@@ -2068,7 +2068,7 @@ static void viafb_init_proc(struct proc_dir_entry *viafb_entry)
if (VT1636_LVDS == viaparinfo->chip_info->lvds_chip_info.
lvds_chip_name || VT1636_LVDS ==
viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) {
- entry = create_proc_entry("vt1636", 0, viafb_entry);
+ entry = create_proc_entry("vt1636", 0, *viafb_entry);
if (entry) {
entry->owner = THIS_MODULE;
entry->read_proc = viafb_vt1636_proc_read;
@@ -2087,6 +2087,7 @@ static void viafb_remove_proc(struct proc_dir_entry *viafb_entry)
remove_proc_entry("dfpl", viafb_entry);
remove_proc_entry("vt1636", viafb_entry);
remove_proc_entry("vt1625", viafb_entry);
+ remove_proc_entry("viafb", NULL);
}
static int __devinit via_pci_probe(void)
@@ -2348,7 +2349,7 @@ static int __devinit via_pci_probe(void)
viafbinfo->node, viafbinfo->fix.id, default_var.xres,
default_var.yres, default_var.bits_per_pixel);
- viafb_init_proc(viaparinfo->proc_entry);
+ viafb_init_proc(&viaparinfo->proc_entry);
viafb_init_dac(IGA2);
return 0;
}
diff --git a/drivers/video/xen-fbfront.c b/drivers/video/xen-fbfront.c
index a463b3dd837..2493f05e9f6 100644
--- a/drivers/video/xen-fbfront.c
+++ b/drivers/video/xen-fbfront.c
@@ -668,7 +668,7 @@ static struct xenbus_device_id xenfb_ids[] = {
{ "" }
};
-static struct xenbus_driver xenfb = {
+static struct xenbus_driver xenfb_driver = {
.name = "vfb",
.owner = THIS_MODULE,
.ids = xenfb_ids,
@@ -687,12 +687,12 @@ static int __init xenfb_init(void)
if (xen_initial_domain())
return -ENODEV;
- return xenbus_register_frontend(&xenfb);
+ return xenbus_register_frontend(&xenfb_driver);
}
static void __exit xenfb_cleanup(void)
{
- xenbus_unregister_driver(&xenfb);
+ xenbus_unregister_driver(&xenfb_driver);
}
module_init(xenfb_init);
diff --git a/drivers/video/xilinxfb.c b/drivers/video/xilinxfb.c
index 5da3d2423cc..40a3a2afbfe 100644
--- a/drivers/video/xilinxfb.c
+++ b/drivers/video/xilinxfb.c
@@ -298,8 +298,9 @@ static int xilinxfb_assign(struct device *dev, unsigned long physaddr,
/* Put a banner in the log (for DEBUG) */
dev_dbg(dev, "regs: phys=%lx, virt=%p\n", physaddr, drvdata->regs);
- dev_dbg(dev, "fb: phys=%p, virt=%p, size=%x\n",
- (void*)drvdata->fb_phys, drvdata->fb_virt, fbsize);
+ dev_dbg(dev, "fb: phys=%llx, virt=%p, size=%x\n",
+ (unsigned long long) drvdata->fb_phys, drvdata->fb_virt,
+ fbsize);
return 0; /* success */
diff --git a/drivers/w1/masters/Kconfig b/drivers/w1/masters/Kconfig
index c4493091c65..90616822cd2 100644
--- a/drivers/w1/masters/Kconfig
+++ b/drivers/w1/masters/Kconfig
@@ -36,7 +36,7 @@ config W1_MASTER_DS2482
config W1_MASTER_DS1WM
tristate "Maxim DS1WM 1-wire busmaster"
- depends on W1 && ARM
+ depends on W1 && ARM && HAVE_CLK
help
Say Y here to enable the DS1WM 1-wire driver, such as that
in HP iPAQ devices like h5xxx, h2200, and ASIC3-based like
@@ -52,5 +52,12 @@ config W1_MASTER_GPIO
This support is also available as a module. If so, the module
will be called w1-gpio.ko.
+config HDQ_MASTER_OMAP
+ tristate "OMAP HDQ driver"
+ depends on ARCH_OMAP2430 || ARCH_OMAP34XX
+ help
+ Say Y here if you want support for the 1-wire or HDQ Interface
+ on an OMAP processor.
+
endmenu
diff --git a/drivers/w1/masters/Makefile b/drivers/w1/masters/Makefile
index 1420b5bbdda..bc4714a75f3 100644
--- a/drivers/w1/masters/Makefile
+++ b/drivers/w1/masters/Makefile
@@ -7,3 +7,4 @@ obj-$(CONFIG_W1_MASTER_DS2490) += ds2490.o
obj-$(CONFIG_W1_MASTER_DS2482) += ds2482.o
obj-$(CONFIG_W1_MASTER_DS1WM) += ds1wm.o
obj-$(CONFIG_W1_MASTER_GPIO) += w1-gpio.o
+obj-$(CONFIG_HDQ_MASTER_OMAP) += omap_hdq.o
diff --git a/drivers/w1/masters/omap_hdq.c b/drivers/w1/masters/omap_hdq.c
new file mode 100644
index 00000000000..c973889110c
--- /dev/null
+++ b/drivers/w1/masters/omap_hdq.c
@@ -0,0 +1,725 @@
+/*
+ * drivers/w1/masters/omap_hdq.c
+ *
+ * Copyright (C) 2007 Texas Instruments, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <asm/irq.h>
+#include <mach/hardware.h>
+
+#include "../w1.h"
+#include "../w1_int.h"
+
+#define MOD_NAME "OMAP_HDQ:"
+
+#define OMAP_HDQ_REVISION 0x00
+#define OMAP_HDQ_TX_DATA 0x04
+#define OMAP_HDQ_RX_DATA 0x08
+#define OMAP_HDQ_CTRL_STATUS 0x0c
+#define OMAP_HDQ_CTRL_STATUS_INTERRUPTMASK (1<<6)
+#define OMAP_HDQ_CTRL_STATUS_CLOCKENABLE (1<<5)
+#define OMAP_HDQ_CTRL_STATUS_GO (1<<4)
+#define OMAP_HDQ_CTRL_STATUS_INITIALIZATION (1<<2)
+#define OMAP_HDQ_CTRL_STATUS_DIR (1<<1)
+#define OMAP_HDQ_CTRL_STATUS_MODE (1<<0)
+#define OMAP_HDQ_INT_STATUS 0x10
+#define OMAP_HDQ_INT_STATUS_TXCOMPLETE (1<<2)
+#define OMAP_HDQ_INT_STATUS_RXCOMPLETE (1<<1)
+#define OMAP_HDQ_INT_STATUS_TIMEOUT (1<<0)
+#define OMAP_HDQ_SYSCONFIG 0x14
+#define OMAP_HDQ_SYSCONFIG_SOFTRESET (1<<1)
+#define OMAP_HDQ_SYSCONFIG_AUTOIDLE (1<<0)
+#define OMAP_HDQ_SYSSTATUS 0x18
+#define OMAP_HDQ_SYSSTATUS_RESETDONE (1<<0)
+
+#define OMAP_HDQ_FLAG_CLEAR 0
+#define OMAP_HDQ_FLAG_SET 1
+#define OMAP_HDQ_TIMEOUT (HZ/5)
+
+#define OMAP_HDQ_MAX_USER 4
+
+static DECLARE_WAIT_QUEUE_HEAD(hdq_wait_queue);
+static int w1_id;
+
+struct hdq_data {
+ struct device *dev;
+ void __iomem *hdq_base;
+ /* lock status update */
+ struct mutex hdq_mutex;
+ int hdq_usecount;
+ struct clk *hdq_ick;
+ struct clk *hdq_fck;
+ u8 hdq_irqstatus;
+ /* device lock */
+ spinlock_t hdq_spinlock;
+ /*
+ * Used to control the call to omap_hdq_get and omap_hdq_put.
+ * HDQ Protocol: Write the CMD|REG_address first, followed by
+ * the data wrire or read.
+ */
+ int init_trans;
+};
+
+static int __init omap_hdq_probe(struct platform_device *pdev);
+static int omap_hdq_remove(struct platform_device *pdev);
+
+static struct platform_driver omap_hdq_driver = {
+ .probe = omap_hdq_probe,
+ .remove = omap_hdq_remove,
+ .driver = {
+ .name = "omap_hdq",
+ },
+};
+
+static u8 omap_w1_read_byte(void *_hdq);
+static void omap_w1_write_byte(void *_hdq, u8 byte);
+static u8 omap_w1_reset_bus(void *_hdq);
+static void omap_w1_search_bus(void *_hdq, struct w1_master *master_dev,
+ u8 search_type, w1_slave_found_callback slave_found);
+
+
+static struct w1_bus_master omap_w1_master = {
+ .read_byte = omap_w1_read_byte,
+ .write_byte = omap_w1_write_byte,
+ .reset_bus = omap_w1_reset_bus,
+ .search = omap_w1_search_bus,
+};
+
+/* HDQ register I/O routines */
+static inline u8 hdq_reg_in(struct hdq_data *hdq_data, u32 offset)
+{
+ return __raw_readb(hdq_data->hdq_base + offset);
+}
+
+static inline void hdq_reg_out(struct hdq_data *hdq_data, u32 offset, u8 val)
+{
+ __raw_writeb(val, hdq_data->hdq_base + offset);
+}
+
+static inline u8 hdq_reg_merge(struct hdq_data *hdq_data, u32 offset,
+ u8 val, u8 mask)
+{
+ u8 new_val = (__raw_readb(hdq_data->hdq_base + offset) & ~mask)
+ | (val & mask);
+ __raw_writeb(new_val, hdq_data->hdq_base + offset);
+
+ return new_val;
+}
+
+/*
+ * Wait for one or more bits in flag change.
+ * HDQ_FLAG_SET: wait until any bit in the flag is set.
+ * HDQ_FLAG_CLEAR: wait until all bits in the flag are cleared.
+ * return 0 on success and -ETIMEDOUT in the case of timeout.
+ */
+static int hdq_wait_for_flag(struct hdq_data *hdq_data, u32 offset,
+ u8 flag, u8 flag_set, u8 *status)
+{
+ int ret = 0;
+ unsigned long timeout = jiffies + OMAP_HDQ_TIMEOUT;
+
+ if (flag_set == OMAP_HDQ_FLAG_CLEAR) {
+ /* wait for the flag clear */
+ while (((*status = hdq_reg_in(hdq_data, offset)) & flag)
+ && time_before(jiffies, timeout)) {
+ schedule_timeout_uninterruptible(1);
+ }
+ if (*status & flag)
+ ret = -ETIMEDOUT;
+ } else if (flag_set == OMAP_HDQ_FLAG_SET) {
+ /* wait for the flag set */
+ while (!((*status = hdq_reg_in(hdq_data, offset)) & flag)
+ && time_before(jiffies, timeout)) {
+ schedule_timeout_uninterruptible(1);
+ }
+ if (!(*status & flag))
+ ret = -ETIMEDOUT;
+ } else
+ return -EINVAL;
+
+ return ret;
+}
+
+/* write out a byte and fill *status with HDQ_INT_STATUS */
+static int hdq_write_byte(struct hdq_data *hdq_data, u8 val, u8 *status)
+{
+ int ret;
+ u8 tmp_status;
+ unsigned long irqflags;
+
+ *status = 0;
+
+ spin_lock_irqsave(&hdq_data->hdq_spinlock, irqflags);
+ /* clear interrupt flags via a dummy read */
+ hdq_reg_in(hdq_data, OMAP_HDQ_INT_STATUS);
+ /* ISR loads it with new INT_STATUS */
+ hdq_data->hdq_irqstatus = 0;
+ spin_unlock_irqrestore(&hdq_data->hdq_spinlock, irqflags);
+
+ hdq_reg_out(hdq_data, OMAP_HDQ_TX_DATA, val);
+
+ /* set the GO bit */
+ hdq_reg_merge(hdq_data, OMAP_HDQ_CTRL_STATUS, OMAP_HDQ_CTRL_STATUS_GO,
+ OMAP_HDQ_CTRL_STATUS_DIR | OMAP_HDQ_CTRL_STATUS_GO);
+ /* wait for the TXCOMPLETE bit */
+ ret = wait_event_timeout(hdq_wait_queue,
+ hdq_data->hdq_irqstatus, OMAP_HDQ_TIMEOUT);
+ if (ret == 0) {
+ dev_dbg(hdq_data->dev, "TX wait elapsed\n");
+ goto out;
+ }
+
+ *status = hdq_data->hdq_irqstatus;
+ /* check irqstatus */
+ if (!(*status & OMAP_HDQ_INT_STATUS_TXCOMPLETE)) {
+ dev_dbg(hdq_data->dev, "timeout waiting for"
+ "TXCOMPLETE/RXCOMPLETE, %x", *status);
+ ret = -ETIMEDOUT;
+ goto out;
+ }
+
+ /* wait for the GO bit return to zero */
+ ret = hdq_wait_for_flag(hdq_data, OMAP_HDQ_CTRL_STATUS,
+ OMAP_HDQ_CTRL_STATUS_GO,
+ OMAP_HDQ_FLAG_CLEAR, &tmp_status);
+ if (ret) {
+ dev_dbg(hdq_data->dev, "timeout waiting GO bit"
+ "return to zero, %x", tmp_status);
+ }
+
+out:
+ return ret;
+}
+
+/* HDQ Interrupt service routine */
+static irqreturn_t hdq_isr(int irq, void *_hdq)
+{
+ struct hdq_data *hdq_data = _hdq;
+ unsigned long irqflags;
+
+ spin_lock_irqsave(&hdq_data->hdq_spinlock, irqflags);
+ hdq_data->hdq_irqstatus = hdq_reg_in(hdq_data, OMAP_HDQ_INT_STATUS);
+ spin_unlock_irqrestore(&hdq_data->hdq_spinlock, irqflags);
+ dev_dbg(hdq_data->dev, "hdq_isr: %x", hdq_data->hdq_irqstatus);
+
+ if (hdq_data->hdq_irqstatus &
+ (OMAP_HDQ_INT_STATUS_TXCOMPLETE | OMAP_HDQ_INT_STATUS_RXCOMPLETE
+ | OMAP_HDQ_INT_STATUS_TIMEOUT)) {
+ /* wake up sleeping process */
+ wake_up(&hdq_wait_queue);
+ }
+
+ return IRQ_HANDLED;
+}
+
+/* HDQ Mode: always return success */
+static u8 omap_w1_reset_bus(void *_hdq)
+{
+ return 0;
+}
+
+/* W1 search callback function */
+static void omap_w1_search_bus(void *_hdq, struct w1_master *master_dev,
+ u8 search_type, w1_slave_found_callback slave_found)
+{
+ u64 module_id, rn_le, cs, id;
+
+ if (w1_id)
+ module_id = w1_id;
+ else
+ module_id = 0x1;
+
+ rn_le = cpu_to_le64(module_id);
+ /*
+ * HDQ might not obey truly the 1-wire spec.
+ * So calculate CRC based on module parameter.
+ */
+ cs = w1_calc_crc8((u8 *)&rn_le, 7);
+ id = (cs << 56) | module_id;
+
+ slave_found(master_dev, id);
+}
+
+static int _omap_hdq_reset(struct hdq_data *hdq_data)
+{
+ int ret;
+ u8 tmp_status;
+
+ hdq_reg_out(hdq_data, OMAP_HDQ_SYSCONFIG, OMAP_HDQ_SYSCONFIG_SOFTRESET);
+ /*
+ * Select HDQ mode & enable clocks.
+ * It is observed that INT flags can't be cleared via a read and GO/INIT
+ * won't return to zero if interrupt is disabled. So we always enable
+ * interrupt.
+ */
+ hdq_reg_out(hdq_data, OMAP_HDQ_CTRL_STATUS,
+ OMAP_HDQ_CTRL_STATUS_CLOCKENABLE |
+ OMAP_HDQ_CTRL_STATUS_INTERRUPTMASK);
+
+ /* wait for reset to complete */
+ ret = hdq_wait_for_flag(hdq_data, OMAP_HDQ_SYSSTATUS,
+ OMAP_HDQ_SYSSTATUS_RESETDONE, OMAP_HDQ_FLAG_SET, &tmp_status);
+ if (ret)
+ dev_dbg(hdq_data->dev, "timeout waiting HDQ reset, %x",
+ tmp_status);
+ else {
+ hdq_reg_out(hdq_data, OMAP_HDQ_CTRL_STATUS,
+ OMAP_HDQ_CTRL_STATUS_CLOCKENABLE |
+ OMAP_HDQ_CTRL_STATUS_INTERRUPTMASK);
+ hdq_reg_out(hdq_data, OMAP_HDQ_SYSCONFIG,
+ OMAP_HDQ_SYSCONFIG_AUTOIDLE);
+ }
+
+ return ret;
+}
+
+/* Issue break pulse to the device */
+static int omap_hdq_break(struct hdq_data *hdq_data)
+{
+ int ret = 0;
+ u8 tmp_status;
+ unsigned long irqflags;
+
+ ret = mutex_lock_interruptible(&hdq_data->hdq_mutex);
+ if (ret < 0) {
+ dev_dbg(hdq_data->dev, "Could not acquire mutex\n");
+ ret = -EINTR;
+ goto rtn;
+ }
+
+ spin_lock_irqsave(&hdq_data->hdq_spinlock, irqflags);
+ /* clear interrupt flags via a dummy read */
+ hdq_reg_in(hdq_data, OMAP_HDQ_INT_STATUS);
+ /* ISR loads it with new INT_STATUS */
+ hdq_data->hdq_irqstatus = 0;
+ spin_unlock_irqrestore(&hdq_data->hdq_spinlock, irqflags);
+
+ /* set the INIT and GO bit */
+ hdq_reg_merge(hdq_data, OMAP_HDQ_CTRL_STATUS,
+ OMAP_HDQ_CTRL_STATUS_INITIALIZATION | OMAP_HDQ_CTRL_STATUS_GO,
+ OMAP_HDQ_CTRL_STATUS_DIR | OMAP_HDQ_CTRL_STATUS_INITIALIZATION |
+ OMAP_HDQ_CTRL_STATUS_GO);
+
+ /* wait for the TIMEOUT bit */
+ ret = wait_event_timeout(hdq_wait_queue,
+ hdq_data->hdq_irqstatus, OMAP_HDQ_TIMEOUT);
+ if (ret == 0) {
+ dev_dbg(hdq_data->dev, "break wait elapsed\n");
+ ret = -EINTR;
+ goto out;
+ }
+
+ tmp_status = hdq_data->hdq_irqstatus;
+ /* check irqstatus */
+ if (!(tmp_status & OMAP_HDQ_INT_STATUS_TIMEOUT)) {
+ dev_dbg(hdq_data->dev, "timeout waiting for TIMEOUT, %x",
+ tmp_status);
+ ret = -ETIMEDOUT;
+ goto out;
+ }
+ /*
+ * wait for both INIT and GO bits rerurn to zero.
+ * zero wait time expected for interrupt mode.
+ */
+ ret = hdq_wait_for_flag(hdq_data, OMAP_HDQ_CTRL_STATUS,
+ OMAP_HDQ_CTRL_STATUS_INITIALIZATION |
+ OMAP_HDQ_CTRL_STATUS_GO, OMAP_HDQ_FLAG_CLEAR,
+ &tmp_status);
+ if (ret)
+ dev_dbg(hdq_data->dev, "timeout waiting INIT&GO bits"
+ "return to zero, %x", tmp_status);
+
+out:
+ mutex_unlock(&hdq_data->hdq_mutex);
+rtn:
+ return ret;
+}
+
+static int hdq_read_byte(struct hdq_data *hdq_data, u8 *val)
+{
+ int ret = 0;
+ u8 status;
+ unsigned long timeout = jiffies + OMAP_HDQ_TIMEOUT;
+
+ ret = mutex_lock_interruptible(&hdq_data->hdq_mutex);
+ if (ret < 0) {
+ ret = -EINTR;
+ goto rtn;
+ }
+
+ if (!hdq_data->hdq_usecount) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (!(hdq_data->hdq_irqstatus & OMAP_HDQ_INT_STATUS_RXCOMPLETE)) {
+ hdq_reg_merge(hdq_data, OMAP_HDQ_CTRL_STATUS,
+ OMAP_HDQ_CTRL_STATUS_DIR | OMAP_HDQ_CTRL_STATUS_GO,
+ OMAP_HDQ_CTRL_STATUS_DIR | OMAP_HDQ_CTRL_STATUS_GO);
+ /*
+ * The RX comes immediately after TX. It
+ * triggers another interrupt before we
+ * sleep. So we have to wait for RXCOMPLETE bit.
+ */
+ while (!(hdq_data->hdq_irqstatus
+ & OMAP_HDQ_INT_STATUS_RXCOMPLETE)
+ && time_before(jiffies, timeout)) {
+ schedule_timeout_uninterruptible(1);
+ }
+ hdq_reg_merge(hdq_data, OMAP_HDQ_CTRL_STATUS, 0,
+ OMAP_HDQ_CTRL_STATUS_DIR);
+ status = hdq_data->hdq_irqstatus;
+ /* check irqstatus */
+ if (!(status & OMAP_HDQ_INT_STATUS_RXCOMPLETE)) {
+ dev_dbg(hdq_data->dev, "timeout waiting for"
+ "RXCOMPLETE, %x", status);
+ ret = -ETIMEDOUT;
+ goto out;
+ }
+ }
+ /* the data is ready. Read it in! */
+ *val = hdq_reg_in(hdq_data, OMAP_HDQ_RX_DATA);
+out:
+ mutex_unlock(&hdq_data->hdq_mutex);
+rtn:
+ return 0;
+
+}
+
+/* Enable clocks and set the controller to HDQ mode */
+static int omap_hdq_get(struct hdq_data *hdq_data)
+{
+ int ret = 0;
+
+ ret = mutex_lock_interruptible(&hdq_data->hdq_mutex);
+ if (ret < 0) {
+ ret = -EINTR;
+ goto rtn;
+ }
+
+ if (OMAP_HDQ_MAX_USER == hdq_data->hdq_usecount) {
+ dev_dbg(hdq_data->dev, "attempt to exceed the max use count");
+ ret = -EINVAL;
+ goto out;
+ } else {
+ hdq_data->hdq_usecount++;
+ try_module_get(THIS_MODULE);
+ if (1 == hdq_data->hdq_usecount) {
+ if (clk_enable(hdq_data->hdq_ick)) {
+ dev_dbg(hdq_data->dev, "Can not enable ick\n");
+ ret = -ENODEV;
+ goto clk_err;
+ }
+ if (clk_enable(hdq_data->hdq_fck)) {
+ dev_dbg(hdq_data->dev, "Can not enable fck\n");
+ clk_disable(hdq_data->hdq_ick);
+ ret = -ENODEV;
+ goto clk_err;
+ }
+
+ /* make sure HDQ is out of reset */
+ if (!(hdq_reg_in(hdq_data, OMAP_HDQ_SYSSTATUS) &
+ OMAP_HDQ_SYSSTATUS_RESETDONE)) {
+ ret = _omap_hdq_reset(hdq_data);
+ if (ret)
+ /* back up the count */
+ hdq_data->hdq_usecount--;
+ } else {
+ /* select HDQ mode & enable clocks */
+ hdq_reg_out(hdq_data, OMAP_HDQ_CTRL_STATUS,
+ OMAP_HDQ_CTRL_STATUS_CLOCKENABLE |
+ OMAP_HDQ_CTRL_STATUS_INTERRUPTMASK);
+ hdq_reg_out(hdq_data, OMAP_HDQ_SYSCONFIG,
+ OMAP_HDQ_SYSCONFIG_AUTOIDLE);
+ hdq_reg_in(hdq_data, OMAP_HDQ_INT_STATUS);
+ }
+ }
+ }
+
+clk_err:
+ clk_put(hdq_data->hdq_ick);
+ clk_put(hdq_data->hdq_fck);
+out:
+ mutex_unlock(&hdq_data->hdq_mutex);
+rtn:
+ return ret;
+}
+
+/* Disable clocks to the module */
+static int omap_hdq_put(struct hdq_data *hdq_data)
+{
+ int ret = 0;
+
+ ret = mutex_lock_interruptible(&hdq_data->hdq_mutex);
+ if (ret < 0)
+ return -EINTR;
+
+ if (0 == hdq_data->hdq_usecount) {
+ dev_dbg(hdq_data->dev, "attempt to decrement use count"
+ "when it is zero");
+ ret = -EINVAL;
+ } else {
+ hdq_data->hdq_usecount--;
+ module_put(THIS_MODULE);
+ if (0 == hdq_data->hdq_usecount) {
+ clk_disable(hdq_data->hdq_ick);
+ clk_disable(hdq_data->hdq_fck);
+ }
+ }
+ mutex_unlock(&hdq_data->hdq_mutex);
+
+ return ret;
+}
+
+/* Read a byte of data from the device */
+static u8 omap_w1_read_byte(void *_hdq)
+{
+ struct hdq_data *hdq_data = _hdq;
+ u8 val = 0;
+ int ret;
+
+ ret = hdq_read_byte(hdq_data, &val);
+ if (ret) {
+ ret = mutex_lock_interruptible(&hdq_data->hdq_mutex);
+ if (ret < 0) {
+ dev_dbg(hdq_data->dev, "Could not acquire mutex\n");
+ return -EINTR;
+ }
+ hdq_data->init_trans = 0;
+ mutex_unlock(&hdq_data->hdq_mutex);
+ omap_hdq_put(hdq_data);
+ return -1;
+ }
+
+ /* Write followed by a read, release the module */
+ if (hdq_data->init_trans) {
+ ret = mutex_lock_interruptible(&hdq_data->hdq_mutex);
+ if (ret < 0) {
+ dev_dbg(hdq_data->dev, "Could not acquire mutex\n");
+ return -EINTR;
+ }
+ hdq_data->init_trans = 0;
+ mutex_unlock(&hdq_data->hdq_mutex);
+ omap_hdq_put(hdq_data);
+ }
+
+ return val;
+}
+
+/* Write a byte of data to the device */
+static void omap_w1_write_byte(void *_hdq, u8 byte)
+{
+ struct hdq_data *hdq_data = _hdq;
+ int ret;
+ u8 status;
+
+ /* First write to initialize the transfer */
+ if (hdq_data->init_trans == 0)
+ omap_hdq_get(hdq_data);
+
+ ret = mutex_lock_interruptible(&hdq_data->hdq_mutex);
+ if (ret < 0) {
+ dev_dbg(hdq_data->dev, "Could not acquire mutex\n");
+ return;
+ }
+ hdq_data->init_trans++;
+ mutex_unlock(&hdq_data->hdq_mutex);
+
+ ret = hdq_write_byte(hdq_data, byte, &status);
+ if (ret == 0) {
+ dev_dbg(hdq_data->dev, "TX failure:Ctrl status %x\n", status);
+ return;
+ }
+
+ /* Second write, data transfered. Release the module */
+ if (hdq_data->init_trans > 1) {
+ omap_hdq_put(hdq_data);
+ ret = mutex_lock_interruptible(&hdq_data->hdq_mutex);
+ if (ret < 0) {
+ dev_dbg(hdq_data->dev, "Could not acquire mutex\n");
+ return;
+ }
+ hdq_data->init_trans = 0;
+ mutex_unlock(&hdq_data->hdq_mutex);
+ }
+
+ return;
+}
+
+static int __init omap_hdq_probe(struct platform_device *pdev)
+{
+ struct hdq_data *hdq_data;
+ struct resource *res;
+ int ret, irq;
+ u8 rev;
+
+ hdq_data = kmalloc(sizeof(*hdq_data), GFP_KERNEL);
+ if (!hdq_data) {
+ dev_dbg(&pdev->dev, "unable to allocate memory\n");
+ ret = -ENOMEM;
+ goto err_kmalloc;
+ }
+
+ hdq_data->dev = &pdev->dev;
+ platform_set_drvdata(pdev, hdq_data);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_dbg(&pdev->dev, "unable to get resource\n");
+ ret = -ENXIO;
+ goto err_resource;
+ }
+
+ hdq_data->hdq_base = ioremap(res->start, SZ_4K);
+ if (!hdq_data->hdq_base) {
+ dev_dbg(&pdev->dev, "ioremap failed\n");
+ ret = -EINVAL;
+ goto err_ioremap;
+ }
+
+ /* get interface & functional clock objects */
+ hdq_data->hdq_ick = clk_get(&pdev->dev, "hdq_ick");
+ hdq_data->hdq_fck = clk_get(&pdev->dev, "hdq_fck");
+
+ if (IS_ERR(hdq_data->hdq_ick) || IS_ERR(hdq_data->hdq_fck)) {
+ dev_dbg(&pdev->dev, "Can't get HDQ clock objects\n");
+ if (IS_ERR(hdq_data->hdq_ick)) {
+ ret = PTR_ERR(hdq_data->hdq_ick);
+ goto err_clk;
+ }
+ if (IS_ERR(hdq_data->hdq_fck)) {
+ ret = PTR_ERR(hdq_data->hdq_fck);
+ clk_put(hdq_data->hdq_ick);
+ goto err_clk;
+ }
+ }
+
+ hdq_data->hdq_usecount = 0;
+ mutex_init(&hdq_data->hdq_mutex);
+
+ if (clk_enable(hdq_data->hdq_ick)) {
+ dev_dbg(&pdev->dev, "Can not enable ick\n");
+ ret = -ENODEV;
+ goto err_intfclk;
+ }
+
+ if (clk_enable(hdq_data->hdq_fck)) {
+ dev_dbg(&pdev->dev, "Can not enable fck\n");
+ ret = -ENODEV;
+ goto err_fnclk;
+ }
+
+ rev = hdq_reg_in(hdq_data, OMAP_HDQ_REVISION);
+ dev_info(&pdev->dev, "OMAP HDQ Hardware Rev %c.%c. Driver in %s mode\n",
+ (rev >> 4) + '0', (rev & 0x0f) + '0', "Interrupt");
+
+ spin_lock_init(&hdq_data->hdq_spinlock);
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ ret = -ENXIO;
+ goto err_irq;
+ }
+
+ ret = request_irq(irq, hdq_isr, IRQF_DISABLED, "omap_hdq", hdq_data);
+ if (ret < 0) {
+ dev_dbg(&pdev->dev, "could not request irq\n");
+ goto err_irq;
+ }
+
+ omap_hdq_break(hdq_data);
+
+ /* don't clock the HDQ until it is needed */
+ clk_disable(hdq_data->hdq_ick);
+ clk_disable(hdq_data->hdq_fck);
+
+ omap_w1_master.data = hdq_data;
+
+ ret = w1_add_master_device(&omap_w1_master);
+ if (ret) {
+ dev_dbg(&pdev->dev, "Failure in registering w1 master\n");
+ goto err_w1;
+ }
+
+ return 0;
+
+err_w1:
+err_irq:
+ clk_disable(hdq_data->hdq_fck);
+
+err_fnclk:
+ clk_disable(hdq_data->hdq_ick);
+
+err_intfclk:
+ clk_put(hdq_data->hdq_ick);
+ clk_put(hdq_data->hdq_fck);
+
+err_clk:
+ iounmap(hdq_data->hdq_base);
+
+err_ioremap:
+err_resource:
+ platform_set_drvdata(pdev, NULL);
+ kfree(hdq_data);
+
+err_kmalloc:
+ return ret;
+
+}
+
+static int omap_hdq_remove(struct platform_device *pdev)
+{
+ struct hdq_data *hdq_data = platform_get_drvdata(pdev);
+
+ mutex_lock(&hdq_data->hdq_mutex);
+
+ if (hdq_data->hdq_usecount) {
+ dev_dbg(&pdev->dev, "removed when use count is not zero\n");
+ return -EBUSY;
+ }
+
+ mutex_unlock(&hdq_data->hdq_mutex);
+
+ /* remove module dependency */
+ clk_put(hdq_data->hdq_ick);
+ clk_put(hdq_data->hdq_fck);
+ free_irq(INT_24XX_HDQ_IRQ, hdq_data);
+ platform_set_drvdata(pdev, NULL);
+ iounmap(hdq_data->hdq_base);
+ kfree(hdq_data);
+
+ return 0;
+}
+
+static int __init
+omap_hdq_init(void)
+{
+ return platform_driver_register(&omap_hdq_driver);
+}
+module_init(omap_hdq_init);
+
+static void __exit
+omap_hdq_exit(void)
+{
+ platform_driver_unregister(&omap_hdq_driver);
+}
+module_exit(omap_hdq_exit);
+
+module_param(w1_id, int, S_IRUSR);
+MODULE_PARM_DESC(w1_id, "1-wire id for the slave detection");
+
+MODULE_AUTHOR("Texas Instruments");
+MODULE_DESCRIPTION("HDQ driver Library");
+MODULE_LICENSE("GPL");
diff --git a/drivers/w1/slaves/Kconfig b/drivers/w1/slaves/Kconfig
index 3df29a122f8..8d0b1fb1e52 100644
--- a/drivers/w1/slaves/Kconfig
+++ b/drivers/w1/slaves/Kconfig
@@ -44,4 +44,11 @@ config W1_SLAVE_DS2760
If you are unsure, say N.
+config W1_SLAVE_BQ27000
+ tristate "BQ27000 slave support"
+ depends on W1
+ help
+ Say Y here if you want to use a hdq
+ bq27000 slave support.
+
endmenu
diff --git a/drivers/w1/slaves/Makefile b/drivers/w1/slaves/Makefile
index a8eb7524df1..990f400b6d2 100644
--- a/drivers/w1/slaves/Makefile
+++ b/drivers/w1/slaves/Makefile
@@ -6,4 +6,4 @@ obj-$(CONFIG_W1_SLAVE_THERM) += w1_therm.o
obj-$(CONFIG_W1_SLAVE_SMEM) += w1_smem.o
obj-$(CONFIG_W1_SLAVE_DS2433) += w1_ds2433.o
obj-$(CONFIG_W1_SLAVE_DS2760) += w1_ds2760.o
-
+obj-$(CONFIG_W1_SLAVE_BQ27000) += w1_bq27000.o
diff --git a/drivers/w1/slaves/w1_bq27000.c b/drivers/w1/slaves/w1_bq27000.c
new file mode 100644
index 00000000000..8f4c91f6c68
--- /dev/null
+++ b/drivers/w1/slaves/w1_bq27000.c
@@ -0,0 +1,123 @@
+/*
+ * drivers/w1/slaves/w1_bq27000.c
+ *
+ * Copyright (C) 2007 Texas Instruments, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+
+#include "../w1.h"
+#include "../w1_int.h"
+#include "../w1_family.h"
+
+#define HDQ_CMD_READ (0)
+#define HDQ_CMD_WRITE (1<<7)
+
+static int F_ID;
+
+void w1_bq27000_write(struct device *dev, u8 buf, u8 reg)
+{
+ struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
+
+ if (!dev) {
+ pr_info("Could not obtain slave dev ptr\n");
+ return;
+ }
+
+ w1_write_8(sl->master, HDQ_CMD_WRITE | reg);
+ w1_write_8(sl->master, buf);
+}
+EXPORT_SYMBOL(w1_bq27000_write);
+
+int w1_bq27000_read(struct device *dev, u8 reg)
+{
+ u8 val;
+ struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
+
+ if (!dev)
+ return 0;
+
+ w1_write_8(sl->master, HDQ_CMD_READ | reg);
+ val = w1_read_8(sl->master);
+
+ return val;
+}
+EXPORT_SYMBOL(w1_bq27000_read);
+
+static int w1_bq27000_add_slave(struct w1_slave *sl)
+{
+ int ret;
+ int id = 1;
+ struct platform_device *pdev;
+
+ pdev = platform_device_alloc("bq27000-battery", id);
+ if (!pdev) {
+ ret = -ENOMEM;
+ return ret;
+ }
+ pdev->dev.parent = &sl->dev;
+
+ ret = platform_device_add(pdev);
+ if (ret)
+ goto pdev_add_failed;
+
+ dev_set_drvdata(&sl->dev, pdev);
+
+ goto success;
+
+pdev_add_failed:
+ platform_device_unregister(pdev);
+success:
+ return ret;
+}
+
+static void w1_bq27000_remove_slave(struct w1_slave *sl)
+{
+ struct platform_device *pdev = dev_get_drvdata(&sl->dev);
+
+ platform_device_unregister(pdev);
+}
+
+static struct w1_family_ops w1_bq27000_fops = {
+ .add_slave = w1_bq27000_add_slave,
+ .remove_slave = w1_bq27000_remove_slave,
+};
+
+static struct w1_family w1_bq27000_family = {
+ .fid = 1,
+ .fops = &w1_bq27000_fops,
+};
+
+static int __init w1_bq27000_init(void)
+{
+ if (F_ID)
+ w1_bq27000_family.fid = F_ID;
+
+ return w1_register_family(&w1_bq27000_family);
+}
+
+static void __exit w1_bq27000_exit(void)
+{
+ w1_unregister_family(&w1_bq27000_family);
+}
+
+
+module_init(w1_bq27000_init);
+module_exit(w1_bq27000_exit);
+
+module_param(F_ID, int, S_IRUSR);
+MODULE_PARM_DESC(F_ID, "1-wire slave FID for BQ device");
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Texas Instruments Ltd");
+MODULE_DESCRIPTION("HDQ/1-wire slave driver bq27000 battery monitor chip");
diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h
index cdaa6fffbfc..97304bd83ec 100644
--- a/drivers/w1/w1.h
+++ b/drivers/w1/w1.h
@@ -206,6 +206,7 @@ void w1_slave_detach(struct w1_slave *sl);
u8 w1_triplet(struct w1_master *dev, int bdir);
void w1_write_8(struct w1_master *, u8);
+u8 w1_read_8(struct w1_master *);
int w1_reset_bus(struct w1_master *);
u8 w1_calc_crc8(u8 *, int);
void w1_write_block(struct w1_master *, const u8 *, int);
diff --git a/drivers/w1/w1_io.c b/drivers/w1/w1_io.c
index f4f82f1f486..5139c25ca96 100644
--- a/drivers/w1/w1_io.c
+++ b/drivers/w1/w1_io.c
@@ -217,7 +217,7 @@ u8 w1_triplet(struct w1_master *dev, int bdir)
* @param dev the master device
* @return the byte read
*/
-static u8 w1_read_8(struct w1_master * dev)
+u8 w1_read_8(struct w1_master *dev)
{
int i;
u8 res = 0;
@@ -230,6 +230,7 @@ static u8 w1_read_8(struct w1_master * dev)
return res;
}
+EXPORT_SYMBOL_GPL(w1_read_8);
/**
* Writes a series of bytes.
@@ -355,7 +356,9 @@ int w1_reset_select_slave(struct w1_slave *sl)
w1_write_8(sl->master, W1_SKIP_ROM);
else {
u8 match[9] = {W1_MATCH_ROM, };
- memcpy(&match[1], (u8 *)&sl->reg_num, 8);
+ u64 rn = le64_to_cpu(*((u64*)&sl->reg_num));
+
+ memcpy(&match[1], &rn, 8);
w1_write_block(sl->master, match, 9);
}
return 0;
diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c
index a3765e0be4a..763c1ea5dce 100644
--- a/drivers/watchdog/hpwdt.c
+++ b/drivers/watchdog/hpwdt.c
@@ -40,6 +40,7 @@
#include <linux/bootmem.h>
#include <linux/slab.h>
#include <asm/desc.h>
+#include <asm/cacheflush.h>
#define PCI_BIOS32_SD_VALUE 0x5F32335F /* "_32_" */
#define CRU_BIOS_SIGNATURE_VALUE 0x55524324
@@ -394,6 +395,8 @@ static void __devinit dmi_find_cru(const struct dmi_header *dm)
smbios_cru64_ptr->double_offset;
cru_rom_addr = ioremap(cru_physical_address,
smbios_cru64_ptr->double_length);
+ set_memory_x((unsigned long)cru_rom_addr & PAGE_MASK,
+ smbios_cru64_ptr->double_length >> PAGE_SHIFT);
}
}
}
@@ -482,7 +485,7 @@ static int hpwdt_pretimeout(struct notifier_block *nb, unsigned long ulReason,
"Management Log for details.\n");
}
- return NOTIFY_STOP;
+ return NOTIFY_OK;
}
/*
diff --git a/drivers/watchdog/iTCO_vendor_support.c b/drivers/watchdog/iTCO_vendor_support.c
index ca344a85eb9..2474ebca88f 100644
--- a/drivers/watchdog/iTCO_vendor_support.c
+++ b/drivers/watchdog/iTCO_vendor_support.c
@@ -1,7 +1,7 @@
/*
* intel TCO vendor specific watchdog driver support
*
- * (c) Copyright 2006 Wim Van Sebroeck <wim@iguana.be>.
+ * (c) Copyright 2006-2008 Wim Van Sebroeck <wim@iguana.be>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -19,8 +19,7 @@
/* Module and version information */
#define DRV_NAME "iTCO_vendor_support"
-#define DRV_VERSION "1.01"
-#define DRV_RELDATE "11-Nov-2006"
+#define DRV_VERSION "1.02"
#define PFX DRV_NAME ": "
/* Includes */
@@ -78,24 +77,6 @@ MODULE_PARM_DESC(vendorsupport, "iTCO vendor specific support mode, default=0 (n
* 20.6 seconds.
*/
-static void supermicro_old_pre_start(unsigned long acpibase)
-{
- unsigned long val32;
-
- val32 = inl(SMI_EN);
- val32 &= 0xffffdfff; /* Turn off SMI clearing watchdog */
- outl(val32, SMI_EN); /* Needed to activate watchdog */
-}
-
-static void supermicro_old_pre_stop(unsigned long acpibase)
-{
- unsigned long val32;
-
- val32 = inl(SMI_EN);
- val32 &= 0x00002000; /* Turn on SMI clearing watchdog */
- outl(val32, SMI_EN); /* Needed to deactivate watchdog */
-}
-
static void supermicro_old_pre_keepalive(unsigned long acpibase)
{
/* Reload TCO Timer (done in iTCO_wdt_keepalive) + */
@@ -247,18 +228,14 @@ static void supermicro_new_pre_set_heartbeat(unsigned int heartbeat)
void iTCO_vendor_pre_start(unsigned long acpibase,
unsigned int heartbeat)
{
- if (vendorsupport == SUPERMICRO_OLD_BOARD)
- supermicro_old_pre_start(acpibase);
- else if (vendorsupport == SUPERMICRO_NEW_BOARD)
+ if (vendorsupport == SUPERMICRO_NEW_BOARD)
supermicro_new_pre_start(heartbeat);
}
EXPORT_SYMBOL(iTCO_vendor_pre_start);
void iTCO_vendor_pre_stop(unsigned long acpibase)
{
- if (vendorsupport == SUPERMICRO_OLD_BOARD)
- supermicro_old_pre_stop(acpibase);
- else if (vendorsupport == SUPERMICRO_NEW_BOARD)
+ if (vendorsupport == SUPERMICRO_NEW_BOARD)
supermicro_new_pre_stop();
}
EXPORT_SYMBOL(iTCO_vendor_pre_stop);
diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c
index bfb93bc2ca9..5b395a4ddfd 100644
--- a/drivers/watchdog/iTCO_wdt.c
+++ b/drivers/watchdog/iTCO_wdt.c
@@ -1,7 +1,7 @@
/*
* intel TCO Watchdog Driver (Used in i82801 and i6300ESB chipsets)
*
- * (c) Copyright 2006-2007 Wim Van Sebroeck <wim@iguana.be>.
+ * (c) Copyright 2006-2008 Wim Van Sebroeck <wim@iguana.be>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -20,34 +20,41 @@
* 82801BAM (ICH2-M) : document number 290687-002, 298242-027,
* 82801CA (ICH3-S) : document number 290733-003, 290739-013,
* 82801CAM (ICH3-M) : document number 290716-001, 290718-007,
- * 82801DB (ICH4) : document number 290744-001, 290745-020,
- * 82801DBM (ICH4-M) : document number 252337-001, 252663-005,
+ * 82801DB (ICH4) : document number 290744-001, 290745-025,
+ * 82801DBM (ICH4-M) : document number 252337-001, 252663-008,
* 82801E (C-ICH) : document number 273599-001, 273645-002,
- * 82801EB (ICH5) : document number 252516-001, 252517-003,
- * 82801ER (ICH5R) : document number 252516-001, 252517-003,
- * 82801FB (ICH6) : document number 301473-002, 301474-007,
- * 82801FR (ICH6R) : document number 301473-002, 301474-007,
- * 82801FBM (ICH6-M) : document number 301473-002, 301474-007,
- * 82801FW (ICH6W) : document number 301473-001, 301474-007,
- * 82801FRW (ICH6RW) : document number 301473-001, 301474-007,
- * 82801GB (ICH7) : document number 307013-002, 307014-009,
- * 82801GR (ICH7R) : document number 307013-002, 307014-009,
- * 82801GDH (ICH7DH) : document number 307013-002, 307014-009,
- * 82801GBM (ICH7-M) : document number 307013-002, 307014-009,
- * 82801GHM (ICH7-M DH) : document number 307013-002, 307014-009,
- * 82801HB (ICH8) : document number 313056-003, 313057-009,
- * 82801HR (ICH8R) : document number 313056-003, 313057-009,
- * 82801HBM (ICH8M) : document number 313056-003, 313057-009,
- * 82801HH (ICH8DH) : document number 313056-003, 313057-009,
- * 82801HO (ICH8DO) : document number 313056-003, 313057-009,
- * 82801HEM (ICH8M-E) : document number 313056-003, 313057-009,
- * 82801IB (ICH9) : document number 316972-001, 316973-006,
- * 82801IR (ICH9R) : document number 316972-001, 316973-006,
- * 82801IH (ICH9DH) : document number 316972-001, 316973-006,
- * 82801IO (ICH9DO) : document number 316972-001, 316973-006,
- * 6300ESB (6300ESB) : document number 300641-003, 300884-010,
- * 631xESB (631xESB) : document number 313082-001, 313075-005,
- * 632xESB (632xESB) : document number 313082-001, 313075-005
+ * 82801EB (ICH5) : document number 252516-001, 252517-028,
+ * 82801ER (ICH5R) : document number 252516-001, 252517-028,
+ * 6300ESB (6300ESB) : document number 300641-004, 300884-013,
+ * 82801FB (ICH6) : document number 301473-002, 301474-026,
+ * 82801FR (ICH6R) : document number 301473-002, 301474-026,
+ * 82801FBM (ICH6-M) : document number 301473-002, 301474-026,
+ * 82801FW (ICH6W) : document number 301473-001, 301474-026,
+ * 82801FRW (ICH6RW) : document number 301473-001, 301474-026,
+ * 631xESB (631xESB) : document number 313082-001, 313075-006,
+ * 632xESB (632xESB) : document number 313082-001, 313075-006,
+ * 82801GB (ICH7) : document number 307013-003, 307014-024,
+ * 82801GR (ICH7R) : document number 307013-003, 307014-024,
+ * 82801GDH (ICH7DH) : document number 307013-003, 307014-024,
+ * 82801GBM (ICH7-M) : document number 307013-003, 307014-024,
+ * 82801GHM (ICH7-M DH) : document number 307013-003, 307014-024,
+ * 82801GU (ICH7-U) : document number 307013-003, 307014-024,
+ * 82801HB (ICH8) : document number 313056-003, 313057-017,
+ * 82801HR (ICH8R) : document number 313056-003, 313057-017,
+ * 82801HBM (ICH8M) : document number 313056-003, 313057-017,
+ * 82801HH (ICH8DH) : document number 313056-003, 313057-017,
+ * 82801HO (ICH8DO) : document number 313056-003, 313057-017,
+ * 82801HEM (ICH8M-E) : document number 313056-003, 313057-017,
+ * 82801IB (ICH9) : document number 316972-004, 316973-012,
+ * 82801IR (ICH9R) : document number 316972-004, 316973-012,
+ * 82801IH (ICH9DH) : document number 316972-004, 316973-012,
+ * 82801IO (ICH9DO) : document number 316972-004, 316973-012,
+ * 82801IBM (ICH9M) : document number 316972-004, 316973-012,
+ * 82801IEM (ICH9M-E) : document number 316972-004, 316973-012,
+ * 82801JIB (ICH10) : document number 319973-002, 319974-002,
+ * 82801JIR (ICH10R) : document number 319973-002, 319974-002,
+ * 82801JD (ICH10D) : document number 319973-002, 319974-002,
+ * 82801JDO (ICH10DO) : document number 319973-002, 319974-002
*/
/*
@@ -56,8 +63,7 @@
/* Module and version information */
#define DRV_NAME "iTCO_wdt"
-#define DRV_VERSION "1.03"
-#define DRV_RELDATE "30-Apr-2008"
+#define DRV_VERSION "1.04"
#define PFX DRV_NAME ": "
/* Includes */
@@ -96,19 +102,26 @@ enum iTCO_chipsets {
TCO_ICH6, /* ICH6 & ICH6R */
TCO_ICH6M, /* ICH6-M */
TCO_ICH6W, /* ICH6W & ICH6RW */
+ TCO_631XESB, /* 631xESB/632xESB */
TCO_ICH7, /* ICH7 & ICH7R */
- TCO_ICH7M, /* ICH7-M */
+ TCO_ICH7DH, /* ICH7DH */
+ TCO_ICH7M, /* ICH7-M & ICH7-U */
TCO_ICH7MDH, /* ICH7-M DH */
TCO_ICH8, /* ICH8 & ICH8R */
- TCO_ICH8ME, /* ICH8M-E */
TCO_ICH8DH, /* ICH8DH */
TCO_ICH8DO, /* ICH8DO */
TCO_ICH8M, /* ICH8M */
+ TCO_ICH8ME, /* ICH8M-E */
TCO_ICH9, /* ICH9 */
TCO_ICH9R, /* ICH9R */
TCO_ICH9DH, /* ICH9DH */
TCO_ICH9DO, /* ICH9DO */
- TCO_631XESB, /* 631xESB/632xESB */
+ TCO_ICH9M, /* ICH9M */
+ TCO_ICH9ME, /* ICH9M-E */
+ TCO_ICH10, /* ICH10 */
+ TCO_ICH10R, /* ICH10R */
+ TCO_ICH10D, /* ICH10D */
+ TCO_ICH10DO, /* ICH10DO */
};
static struct {
@@ -129,19 +142,26 @@ static struct {
{"ICH6 or ICH6R", 2},
{"ICH6-M", 2},
{"ICH6W or ICH6RW", 2},
+ {"631xESB/632xESB", 2},
{"ICH7 or ICH7R", 2},
- {"ICH7-M", 2},
+ {"ICH7DH", 2},
+ {"ICH7-M or ICH7-U", 2},
{"ICH7-M DH", 2},
{"ICH8 or ICH8R", 2},
- {"ICH8M-E", 2},
{"ICH8DH", 2},
{"ICH8DO", 2},
{"ICH8M", 2},
+ {"ICH8M-E", 2},
{"ICH9", 2},
{"ICH9R", 2},
{"ICH9DH", 2},
{"ICH9DO", 2},
- {"631xESB/632xESB", 2},
+ {"ICH9M", 2},
+ {"ICH9M-E", 2},
+ {"ICH10", 2},
+ {"ICH10R", 2},
+ {"ICH10D", 2},
+ {"ICH10DO", 2},
{NULL, 0}
};
@@ -175,18 +195,6 @@ static struct pci_device_id iTCO_wdt_pci_tbl[] = {
{ ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH6_0, TCO_ICH6)},
{ ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH6_1, TCO_ICH6M)},
{ ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH6_2, TCO_ICH6W)},
- { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_0, TCO_ICH7)},
- { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_1, TCO_ICH7M)},
- { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_31, TCO_ICH7MDH)},
- { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_0, TCO_ICH8)},
- { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_1, TCO_ICH8ME)},
- { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_2, TCO_ICH8DH)},
- { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_3, TCO_ICH8DO)},
- { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_4, TCO_ICH8M)},
- { ITCO_PCI_DEVICE(0x2918, TCO_ICH9)},
- { ITCO_PCI_DEVICE(0x2916, TCO_ICH9R)},
- { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH9_2, TCO_ICH9DH)},
- { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH9_4, TCO_ICH9DO)},
{ ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ESB2_0, TCO_631XESB)},
{ ITCO_PCI_DEVICE(0x2671, TCO_631XESB)},
{ ITCO_PCI_DEVICE(0x2672, TCO_631XESB)},
@@ -203,6 +211,25 @@ static struct pci_device_id iTCO_wdt_pci_tbl[] = {
{ ITCO_PCI_DEVICE(0x267d, TCO_631XESB)},
{ ITCO_PCI_DEVICE(0x267e, TCO_631XESB)},
{ ITCO_PCI_DEVICE(0x267f, TCO_631XESB)},
+ { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_0, TCO_ICH7)},
+ { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_30, TCO_ICH7DH)},
+ { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_1, TCO_ICH7M)},
+ { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_31, TCO_ICH7MDH)},
+ { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_0, TCO_ICH8)},
+ { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_2, TCO_ICH8DH)},
+ { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_3, TCO_ICH8DO)},
+ { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_4, TCO_ICH8M)},
+ { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_1, TCO_ICH8ME)},
+ { ITCO_PCI_DEVICE(0x2918, TCO_ICH9)},
+ { ITCO_PCI_DEVICE(0x2916, TCO_ICH9R)},
+ { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH9_2, TCO_ICH9DH)},
+ { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH9_4, TCO_ICH9DO)},
+ { ITCO_PCI_DEVICE(0x2919, TCO_ICH9M)},
+ { ITCO_PCI_DEVICE(0x2917, TCO_ICH9ME)},
+ { ITCO_PCI_DEVICE(0x3a18, TCO_ICH10)},
+ { ITCO_PCI_DEVICE(0x3a16, TCO_ICH10R)},
+ { ITCO_PCI_DEVICE(0x3a1a, TCO_ICH10D)},
+ { ITCO_PCI_DEVICE(0x3a14, TCO_ICH10DO)},
{ 0, }, /* End of list */
};
MODULE_DEVICE_TABLE(pci, iTCO_wdt_pci_tbl);
@@ -311,6 +338,7 @@ static int iTCO_wdt_unset_NO_REBOOT_bit(void)
static int iTCO_wdt_start(void)
{
unsigned int val;
+ unsigned long val32;
spin_lock(&iTCO_wdt_private.io_lock);
@@ -323,6 +351,18 @@ static int iTCO_wdt_start(void)
return -EIO;
}
+ /* Bit 13: TCO_EN -> 0 = Disables TCO logic generating an SMI# */
+ val32 = inl(SMI_EN);
+ val32 &= 0xffffdfff; /* Turn off SMI clearing watchdog */
+ outl(val32, SMI_EN);
+
+ /* Force the timer to its reload value by writing to the TCO_RLD
+ register */
+ if (iTCO_wdt_private.iTCO_version == 2)
+ outw(0x01, TCO_RLD);
+ else if (iTCO_wdt_private.iTCO_version == 1)
+ outb(0x01, TCO_RLD);
+
/* Bit 11: TCO Timer Halt -> 0 = The TCO timer is enabled to count */
val = inw(TCO1_CNT);
val &= 0xf7ff;
@@ -338,6 +378,7 @@ static int iTCO_wdt_start(void)
static int iTCO_wdt_stop(void)
{
unsigned int val;
+ unsigned long val32;
spin_lock(&iTCO_wdt_private.io_lock);
@@ -349,6 +390,11 @@ static int iTCO_wdt_stop(void)
outw(val, TCO1_CNT);
val = inw(TCO1_CNT);
+ /* Bit 13: TCO_EN -> 1 = Enables the TCO logic to generate SMI# */
+ val32 = inl(SMI_EN);
+ val32 |= 0x00002000;
+ outl(val32, SMI_EN);
+
/* Set the NO_REBOOT bit to prevent later reboots, just for sure */
iTCO_wdt_set_NO_REBOOT_bit();
@@ -459,7 +505,6 @@ static int iTCO_wdt_open(struct inode *inode, struct file *file)
/*
* Reload and activate timer
*/
- iTCO_wdt_keepalive();
iTCO_wdt_start();
return nonseekable_open(inode, file);
}
@@ -604,7 +649,6 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
int ret;
u32 base_address;
unsigned long RCBA;
- unsigned long val32;
/*
* Find the ACPI/PM base I/O address which is the base
@@ -644,17 +688,13 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
/* Set the NO_REBOOT bit to prevent later reboots, just for sure */
iTCO_wdt_set_NO_REBOOT_bit();
- /* Set the TCO_EN bit in SMI_EN register */
+ /* The TCO logic uses the TCO_EN bit in the SMI_EN register */
if (!request_region(SMI_EN, 4, "iTCO_wdt")) {
printk(KERN_ERR PFX
"I/O address 0x%04lx already in use\n", SMI_EN);
ret = -EIO;
goto out;
}
- val32 = inl(SMI_EN);
- val32 &= 0xffffdfff; /* Turn off SMI clearing watchdog */
- outl(val32, SMI_EN);
- release_region(SMI_EN, 4);
/* The TCO I/O registers reside in a 32-byte range pointed to
by the TCOBASE value */
@@ -662,7 +702,7 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
printk(KERN_ERR PFX "I/O address 0x%04lx already in use\n",
TCOBASE);
ret = -EIO;
- goto out;
+ goto unreg_smi_en;
}
printk(KERN_INFO PFX
@@ -672,8 +712,9 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
TCOBASE);
/* Clear out the (probably old) status */
- outb(0, TCO1_STS);
- outb(3, TCO2_STS);
+ outb(8, TCO1_STS); /* Clear the Time Out Status bit */
+ outb(2, TCO2_STS); /* Clear SECOND_TO_STS bit */
+ outb(4, TCO2_STS); /* Clear BOOT_STS bit */
/* Make sure the watchdog is not running */
iTCO_wdt_stop();
@@ -701,6 +742,8 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
unreg_region:
release_region(TCOBASE, 0x20);
+unreg_smi_en:
+ release_region(SMI_EN, 4);
out:
if (iTCO_wdt_private.iTCO_version == 2)
iounmap(iTCO_wdt_private.gcs);
@@ -718,6 +761,7 @@ static void __devexit iTCO_wdt_cleanup(void)
/* Deregister */
misc_deregister(&iTCO_wdt_miscdev);
release_region(TCOBASE, 0x20);
+ release_region(SMI_EN, 4);
if (iTCO_wdt_private.iTCO_version == 2)
iounmap(iTCO_wdt_private.gcs);
pci_dev_put(iTCO_wdt_private.pdev);
@@ -782,8 +826,8 @@ static int __init iTCO_wdt_init_module(void)
{
int err;
- printk(KERN_INFO PFX "Intel TCO WatchDog Timer Driver v%s (%s)\n",
- DRV_VERSION, DRV_RELDATE);
+ printk(KERN_INFO PFX "Intel TCO WatchDog Timer Driver v%s\n",
+ DRV_VERSION);
err = platform_driver_register(&iTCO_wdt_driver);
if (err)
diff --git a/drivers/watchdog/mtx-1_wdt.c b/drivers/watchdog/mtx-1_wdt.c
index b4b7b0a4c11..3acce623f20 100644
--- a/drivers/watchdog/mtx-1_wdt.c
+++ b/drivers/watchdog/mtx-1_wdt.c
@@ -98,6 +98,8 @@ static void mtx1_wdt_reset(void)
static void mtx1_wdt_start(void)
{
+ unsigned long flags;
+
spin_lock_irqsave(&mtx1_wdt_device.lock, flags);
if (!mtx1_wdt_device.queue) {
mtx1_wdt_device.queue = 1;
@@ -110,6 +112,8 @@ static void mtx1_wdt_start(void)
static int mtx1_wdt_stop(void)
{
+ unsigned long flags;
+
spin_lock_irqsave(&mtx1_wdt_device.lock, flags);
if (mtx1_wdt_device.queue) {
mtx1_wdt_device.queue = 0;
diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c
index a0fb5eac407..526c191e84e 100644
--- a/drivers/xen/balloon.c
+++ b/drivers/xen/balloon.c
@@ -122,14 +122,7 @@ static struct timer_list balloon_timer;
static void scrub_page(struct page *page)
{
#ifdef CONFIG_XEN_SCRUB_PAGES
- if (PageHighMem(page)) {
- void *v = kmap(page);
- clear_page(v);
- kunmap(v);
- } else {
- void *v = page_address(page);
- clear_page(v);
- }
+ clear_highpage(page);
#endif
}
diff --git a/fs/9p/fid.c b/fs/9p/fid.c
index 3031e3233dd..2a983d49d19 100644
--- a/fs/9p/fid.c
+++ b/fs/9p/fid.c
@@ -45,7 +45,7 @@ int v9fs_fid_add(struct dentry *dentry, struct p9_fid *fid)
struct v9fs_dentry *dent;
P9_DPRINTK(P9_DEBUG_VFS, "fid %d dentry %s\n",
- fid->fid, dentry->d_iname);
+ fid->fid, dentry->d_name.name);
dent = dentry->d_fsdata;
if (!dent) {
@@ -79,7 +79,7 @@ static struct p9_fid *v9fs_fid_find(struct dentry *dentry, u32 uid, int any)
struct p9_fid *fid, *ret;
P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p) uid %d any %d\n",
- dentry->d_iname, dentry, uid, any);
+ dentry->d_name.name, dentry, uid, any);
dent = (struct v9fs_dentry *) dentry->d_fsdata;
ret = NULL;
if (dent) {
diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c
index 24eb01087b6..332b5ff02fe 100644
--- a/fs/9p/v9fs.c
+++ b/fs/9p/v9fs.c
@@ -160,7 +160,7 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses)
v9ses->flags |= V9FS_ACCESS_ANY;
else {
v9ses->flags |= V9FS_ACCESS_SINGLE;
- v9ses->uid = simple_strtol(s, &e, 10);
+ v9ses->uid = simple_strtoul(s, &e, 10);
if (*e != '\0')
v9ses->uid = ~0;
}
diff --git a/fs/9p/vfs_dentry.c b/fs/9p/vfs_dentry.c
index f9534f18df0..06dcc7c4f23 100644
--- a/fs/9p/vfs_dentry.c
+++ b/fs/9p/vfs_dentry.c
@@ -52,7 +52,8 @@
static int v9fs_dentry_delete(struct dentry *dentry)
{
- P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
+ P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_name.name,
+ dentry);
return 1;
}
@@ -69,7 +70,8 @@ static int v9fs_dentry_delete(struct dentry *dentry)
static int v9fs_cached_dentry_delete(struct dentry *dentry)
{
struct inode *inode = dentry->d_inode;
- P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
+ P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_name.name,
+ dentry);
if(!inode)
return 1;
@@ -88,7 +90,8 @@ void v9fs_dentry_release(struct dentry *dentry)
struct v9fs_dentry *dent;
struct p9_fid *temp, *current_fid;
- P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
+ P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_name.name,
+ dentry);
dent = dentry->d_fsdata;
if (dent) {
list_for_each_entry_safe(current_fid, temp, &dent->fidlist,
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 8314d3f43b7..2dfcf5487ef 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -963,7 +963,8 @@ static int v9fs_vfs_readlink(struct dentry *dentry, char __user * buffer,
if (buflen > PATH_MAX)
buflen = PATH_MAX;
- P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
+ P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_name.name,
+ dentry);
retval = v9fs_readlink(dentry, link, buflen);
@@ -1022,7 +1023,8 @@ v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, void *p)
{
char *s = nd_get_link(nd);
- P9_DPRINTK(P9_DEBUG_VFS, " %s %s\n", dentry->d_name.name, s);
+ P9_DPRINTK(P9_DEBUG_VFS, " %s %s\n", dentry->d_name.name,
+ IS_ERR(s) ? "<error>" : s);
if (!IS_ERR(s))
__putname(s);
}
diff --git a/fs/block_dev.c b/fs/block_dev.c
index db831efbdbb..99e0ae1a4c7 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -1135,12 +1135,15 @@ static int blkdev_open(struct inode * inode, struct file * filp)
if (res)
return res;
- if (!(filp->f_mode & FMODE_EXCL))
- return 0;
+ if (filp->f_mode & FMODE_EXCL) {
+ res = bd_claim(bdev, filp);
+ if (res)
+ goto out_blkdev_put;
+ }
- if (!(res = bd_claim(bdev, filp)))
- return 0;
+ return 0;
+ out_blkdev_put:
blkdev_put(bdev, filp->f_mode);
return res;
}
@@ -1203,8 +1206,16 @@ static long block_ioctl(struct file *file, unsigned cmd, unsigned long arg)
{
struct block_device *bdev = I_BDEV(file->f_mapping->host);
fmode_t mode = file->f_mode;
+
+ /*
+ * O_NDELAY can be altered using fcntl(.., F_SETFL, ..), so we have
+ * to updated it before every ioctl.
+ */
if (file->f_flags & O_NDELAY)
- mode |= FMODE_NDELAY_NOW;
+ mode |= FMODE_NDELAY;
+ else
+ mode &= ~FMODE_NDELAY;
+
return blkdev_ioctl(bdev, mode, cmd, arg);
}
diff --git a/fs/buffer.c b/fs/buffer.c
index 6569fda5cfe..10179cfa115 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -878,6 +878,7 @@ void invalidate_inode_buffers(struct inode *inode)
spin_unlock(&buffer_mapping->private_lock);
}
}
+EXPORT_SYMBOL(invalidate_inode_buffers);
/*
* Remove any clean buffers from the inode's buffer list. This is called
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 8855331b2fb..e078b7aea14 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -8,7 +8,11 @@ handling fcntl(F_SETLEASE). Convert cifs to using blocking tcp
sends, and also let tcp autotune the socket send and receive buffers.
This reduces the number of EAGAIN errors returned by TCP/IP in
high stress workloads (and the number of retries on socket writes
-when sending large SMBWriteX requests).
+when sending large SMBWriteX requests). Fix case in which a portion of
+data can in some cases not get written to the file on the server before the
+file is closed. Fix DFS parsing to properly handle path consumed field,
+and to handle certain codepage conversions better. Fix mount and
+umount race that can cause oops in mount or umount or reconnect.
Version 1.54
------------
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index 69a12aae91d..490e34bbf27 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -107,12 +107,13 @@ void cifs_dump_mids(struct TCP_Server_Info *server)
#ifdef CONFIG_PROC_FS
static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
{
- struct list_head *tmp;
- struct list_head *tmp1;
+ struct list_head *tmp1, *tmp2, *tmp3;
struct mid_q_entry *mid_entry;
+ struct TCP_Server_Info *server;
struct cifsSesInfo *ses;
struct cifsTconInfo *tcon;
- int i;
+ int i, j;
+ __u32 dev_type;
seq_puts(m,
"Display Internal CIFS Data Structures for Debugging\n"
@@ -122,46 +123,78 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
seq_printf(m, "Servers:");
i = 0;
- read_lock(&GlobalSMBSeslock);
- list_for_each(tmp, &GlobalSMBSessionList) {
+ read_lock(&cifs_tcp_ses_lock);
+ list_for_each(tmp1, &cifs_tcp_ses_list) {
+ server = list_entry(tmp1, struct TCP_Server_Info,
+ tcp_ses_list);
i++;
- ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
- if ((ses->serverDomain == NULL) || (ses->serverOS == NULL) ||
- (ses->serverNOS == NULL)) {
- seq_printf(m, "\nentry for %s not fully "
- "displayed\n\t", ses->serverName);
- } else {
- seq_printf(m,
- "\n%d) Name: %s Domain: %s Mounts: %d OS:"
- " %s \n\tNOS: %s\tCapability: 0x%x\n\tSMB"
+ list_for_each(tmp2, &server->smb_ses_list) {
+ ses = list_entry(tmp2, struct cifsSesInfo,
+ smb_ses_list);
+ if ((ses->serverDomain == NULL) ||
+ (ses->serverOS == NULL) ||
+ (ses->serverNOS == NULL)) {
+ seq_printf(m, "\n%d) entry for %s not fully "
+ "displayed\n\t", i, ses->serverName);
+ } else {
+ seq_printf(m,
+ "\n%d) Name: %s Domain: %s Uses: %d OS:"
+ " %s\n\tNOS: %s\tCapability: 0x%x\n\tSMB"
" session status: %d\t",
i, ses->serverName, ses->serverDomain,
- atomic_read(&ses->inUse),
- ses->serverOS, ses->serverNOS,
+ ses->ses_count, ses->serverOS, ses->serverNOS,
ses->capabilities, ses->status);
- }
- if (ses->server) {
+ }
seq_printf(m, "TCP status: %d\n\tLocal Users To "
- "Server: %d SecMode: 0x%x Req On Wire: %d",
- ses->server->tcpStatus,
- atomic_read(&ses->server->socketUseCount),
- ses->server->secMode,
- atomic_read(&ses->server->inFlight));
+ "Server: %d SecMode: 0x%x Req On Wire: %d",
+ server->tcpStatus, server->srv_count,
+ server->secMode,
+ atomic_read(&server->inFlight));
#ifdef CONFIG_CIFS_STATS2
seq_printf(m, " In Send: %d In MaxReq Wait: %d",
- atomic_read(&ses->server->inSend),
- atomic_read(&ses->server->num_waiters));
+ atomic_read(&server->inSend),
+ atomic_read(&server->num_waiters));
#endif
- seq_puts(m, "\nMIDs:\n");
+ seq_puts(m, "\n\tShares:");
+ j = 0;
+ list_for_each(tmp3, &ses->tcon_list) {
+ tcon = list_entry(tmp3, struct cifsTconInfo,
+ tcon_list);
+ ++j;
+ dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType);
+ seq_printf(m, "\n\t%d) %s Mounts: %d ", j,
+ tcon->treeName, tcon->tc_count);
+ if (tcon->nativeFileSystem) {
+ seq_printf(m, "Type: %s ",
+ tcon->nativeFileSystem);
+ }
+ seq_printf(m, "DevInfo: 0x%x Attributes: 0x%x"
+ "\nPathComponentMax: %d Status: 0x%d",
+ le32_to_cpu(tcon->fsDevInfo.DeviceCharacteristics),
+ le32_to_cpu(tcon->fsAttrInfo.Attributes),
+ le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength),
+ tcon->tidStatus);
+ if (dev_type == FILE_DEVICE_DISK)
+ seq_puts(m, " type: DISK ");
+ else if (dev_type == FILE_DEVICE_CD_ROM)
+ seq_puts(m, " type: CDROM ");
+ else
+ seq_printf(m, " type: %d ", dev_type);
+
+ if (tcon->need_reconnect)
+ seq_puts(m, "\tDISCONNECTED ");
+ seq_putc(m, '\n');
+ }
+
+ seq_puts(m, "\n\tMIDs:\n");
spin_lock(&GlobalMid_Lock);
- list_for_each(tmp1, &ses->server->pending_mid_q) {
- mid_entry = list_entry(tmp1, struct
- mid_q_entry,
+ list_for_each(tmp3, &server->pending_mid_q) {
+ mid_entry = list_entry(tmp3, struct mid_q_entry,
qhead);
- seq_printf(m, "State: %d com: %d pid:"
+ seq_printf(m, "\tState: %d com: %d pid:"
" %d tsk: %p mid %d\n",
mid_entry->midState,
(int)mid_entry->command,
@@ -171,44 +204,8 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
}
spin_unlock(&GlobalMid_Lock);
}
-
- }
- read_unlock(&GlobalSMBSeslock);
- seq_putc(m, '\n');
-
- seq_puts(m, "Shares:");
-
- i = 0;
- read_lock(&GlobalSMBSeslock);
- list_for_each(tmp, &GlobalTreeConnectionList) {
- __u32 dev_type;
- i++;
- tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
- dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType);
- seq_printf(m, "\n%d) %s Uses: %d ", i,
- tcon->treeName, atomic_read(&tcon->useCount));
- if (tcon->nativeFileSystem) {
- seq_printf(m, "Type: %s ",
- tcon->nativeFileSystem);
- }
- seq_printf(m, "DevInfo: 0x%x Attributes: 0x%x"
- "\nPathComponentMax: %d Status: %d",
- le32_to_cpu(tcon->fsDevInfo.DeviceCharacteristics),
- le32_to_cpu(tcon->fsAttrInfo.Attributes),
- le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength),
- tcon->tidStatus);
- if (dev_type == FILE_DEVICE_DISK)
- seq_puts(m, " type: DISK ");
- else if (dev_type == FILE_DEVICE_CD_ROM)
- seq_puts(m, " type: CDROM ");
- else
- seq_printf(m, " type: %d ", dev_type);
-
- if (tcon->tidStatus == CifsNeedReconnect)
- seq_puts(m, "\tDISCONNECTED ");
}
- read_unlock(&GlobalSMBSeslock);
-
+ read_unlock(&cifs_tcp_ses_lock);
seq_putc(m, '\n');
/* BB add code to dump additional info such as TCP session info now */
@@ -234,7 +231,9 @@ static ssize_t cifs_stats_proc_write(struct file *file,
{
char c;
int rc;
- struct list_head *tmp;
+ struct list_head *tmp1, *tmp2, *tmp3;
+ struct TCP_Server_Info *server;
+ struct cifsSesInfo *ses;
struct cifsTconInfo *tcon;
rc = get_user(c, buffer);
@@ -242,33 +241,42 @@ static ssize_t cifs_stats_proc_write(struct file *file,
return rc;
if (c == '1' || c == 'y' || c == 'Y' || c == '0') {
- read_lock(&GlobalSMBSeslock);
#ifdef CONFIG_CIFS_STATS2
atomic_set(&totBufAllocCount, 0);
atomic_set(&totSmBufAllocCount, 0);
#endif /* CONFIG_CIFS_STATS2 */
- list_for_each(tmp, &GlobalTreeConnectionList) {
- tcon = list_entry(tmp, struct cifsTconInfo,
- cifsConnectionList);
- atomic_set(&tcon->num_smbs_sent, 0);
- atomic_set(&tcon->num_writes, 0);
- atomic_set(&tcon->num_reads, 0);
- atomic_set(&tcon->num_oplock_brks, 0);
- atomic_set(&tcon->num_opens, 0);
- atomic_set(&tcon->num_closes, 0);
- atomic_set(&tcon->num_deletes, 0);
- atomic_set(&tcon->num_mkdirs, 0);
- atomic_set(&tcon->num_rmdirs, 0);
- atomic_set(&tcon->num_renames, 0);
- atomic_set(&tcon->num_t2renames, 0);
- atomic_set(&tcon->num_ffirst, 0);
- atomic_set(&tcon->num_fnext, 0);
- atomic_set(&tcon->num_fclose, 0);
- atomic_set(&tcon->num_hardlinks, 0);
- atomic_set(&tcon->num_symlinks, 0);
- atomic_set(&tcon->num_locks, 0);
+ read_lock(&cifs_tcp_ses_lock);
+ list_for_each(tmp1, &cifs_tcp_ses_list) {
+ server = list_entry(tmp1, struct TCP_Server_Info,
+ tcp_ses_list);
+ list_for_each(tmp2, &server->smb_ses_list) {
+ ses = list_entry(tmp2, struct cifsSesInfo,
+ smb_ses_list);
+ list_for_each(tmp3, &ses->tcon_list) {
+ tcon = list_entry(tmp3,
+ struct cifsTconInfo,
+ tcon_list);
+ atomic_set(&tcon->num_smbs_sent, 0);
+ atomic_set(&tcon->num_writes, 0);
+ atomic_set(&tcon->num_reads, 0);
+ atomic_set(&tcon->num_oplock_brks, 0);
+ atomic_set(&tcon->num_opens, 0);
+ atomic_set(&tcon->num_closes, 0);
+ atomic_set(&tcon->num_deletes, 0);
+ atomic_set(&tcon->num_mkdirs, 0);
+ atomic_set(&tcon->num_rmdirs, 0);
+ atomic_set(&tcon->num_renames, 0);
+ atomic_set(&tcon->num_t2renames, 0);
+ atomic_set(&tcon->num_ffirst, 0);
+ atomic_set(&tcon->num_fnext, 0);
+ atomic_set(&tcon->num_fclose, 0);
+ atomic_set(&tcon->num_hardlinks, 0);
+ atomic_set(&tcon->num_symlinks, 0);
+ atomic_set(&tcon->num_locks, 0);
+ }
+ }
}
- read_unlock(&GlobalSMBSeslock);
+ read_unlock(&cifs_tcp_ses_lock);
}
return count;
@@ -277,7 +285,9 @@ static ssize_t cifs_stats_proc_write(struct file *file,
static int cifs_stats_proc_show(struct seq_file *m, void *v)
{
int i;
- struct list_head *tmp;
+ struct list_head *tmp1, *tmp2, *tmp3;
+ struct TCP_Server_Info *server;
+ struct cifsSesInfo *ses;
struct cifsTconInfo *tcon;
seq_printf(m,
@@ -306,44 +316,55 @@ static int cifs_stats_proc_show(struct seq_file *m, void *v)
GlobalCurrentXid, GlobalMaxActiveXid);
i = 0;
- read_lock(&GlobalSMBSeslock);
- list_for_each(tmp, &GlobalTreeConnectionList) {
- i++;
- tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
- seq_printf(m, "\n%d) %s", i, tcon->treeName);
- if (tcon->tidStatus == CifsNeedReconnect)
- seq_puts(m, "\tDISCONNECTED ");
- seq_printf(m, "\nSMBs: %d Oplock Breaks: %d",
- atomic_read(&tcon->num_smbs_sent),
- atomic_read(&tcon->num_oplock_brks));
- seq_printf(m, "\nReads: %d Bytes: %lld",
- atomic_read(&tcon->num_reads),
- (long long)(tcon->bytes_read));
- seq_printf(m, "\nWrites: %d Bytes: %lld",
- atomic_read(&tcon->num_writes),
- (long long)(tcon->bytes_written));
- seq_printf(m,
- "\nLocks: %d HardLinks: %d Symlinks: %d",
- atomic_read(&tcon->num_locks),
- atomic_read(&tcon->num_hardlinks),
- atomic_read(&tcon->num_symlinks));
-
- seq_printf(m, "\nOpens: %d Closes: %d Deletes: %d",
- atomic_read(&tcon->num_opens),
- atomic_read(&tcon->num_closes),
- atomic_read(&tcon->num_deletes));
- seq_printf(m, "\nMkdirs: %d Rmdirs: %d",
- atomic_read(&tcon->num_mkdirs),
- atomic_read(&tcon->num_rmdirs));
- seq_printf(m, "\nRenames: %d T2 Renames %d",
- atomic_read(&tcon->num_renames),
- atomic_read(&tcon->num_t2renames));
- seq_printf(m, "\nFindFirst: %d FNext %d FClose %d",
- atomic_read(&tcon->num_ffirst),
- atomic_read(&tcon->num_fnext),
- atomic_read(&tcon->num_fclose));
+ read_lock(&cifs_tcp_ses_lock);
+ list_for_each(tmp1, &cifs_tcp_ses_list) {
+ server = list_entry(tmp1, struct TCP_Server_Info,
+ tcp_ses_list);
+ list_for_each(tmp2, &server->smb_ses_list) {
+ ses = list_entry(tmp2, struct cifsSesInfo,
+ smb_ses_list);
+ list_for_each(tmp3, &ses->tcon_list) {
+ tcon = list_entry(tmp3,
+ struct cifsTconInfo,
+ tcon_list);
+ i++;
+ seq_printf(m, "\n%d) %s", i, tcon->treeName);
+ if (tcon->need_reconnect)
+ seq_puts(m, "\tDISCONNECTED ");
+ seq_printf(m, "\nSMBs: %d Oplock Breaks: %d",
+ atomic_read(&tcon->num_smbs_sent),
+ atomic_read(&tcon->num_oplock_brks));
+ seq_printf(m, "\nReads: %d Bytes: %lld",
+ atomic_read(&tcon->num_reads),
+ (long long)(tcon->bytes_read));
+ seq_printf(m, "\nWrites: %d Bytes: %lld",
+ atomic_read(&tcon->num_writes),
+ (long long)(tcon->bytes_written));
+ seq_printf(m, "\nLocks: %d HardLinks: %d "
+ "Symlinks: %d",
+ atomic_read(&tcon->num_locks),
+ atomic_read(&tcon->num_hardlinks),
+ atomic_read(&tcon->num_symlinks));
+ seq_printf(m, "\nOpens: %d Closes: %d"
+ "Deletes: %d",
+ atomic_read(&tcon->num_opens),
+ atomic_read(&tcon->num_closes),
+ atomic_read(&tcon->num_deletes));
+ seq_printf(m, "\nMkdirs: %d Rmdirs: %d",
+ atomic_read(&tcon->num_mkdirs),
+ atomic_read(&tcon->num_rmdirs));
+ seq_printf(m, "\nRenames: %d T2 Renames %d",
+ atomic_read(&tcon->num_renames),
+ atomic_read(&tcon->num_t2renames));
+ seq_printf(m, "\nFindFirst: %d FNext %d "
+ "FClose %d",
+ atomic_read(&tcon->num_ffirst),
+ atomic_read(&tcon->num_fnext),
+ atomic_read(&tcon->num_fclose));
+ }
+ }
}
- read_unlock(&GlobalSMBSeslock);
+ read_unlock(&cifs_tcp_ses_lock);
seq_putc(m, '\n');
return 0;
diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c
index d2c8eef84f3..e1c18362ba4 100644
--- a/fs/cifs/cifs_dfs_ref.c
+++ b/fs/cifs/cifs_dfs_ref.c
@@ -106,7 +106,8 @@ static char *cifs_get_share_name(const char *node_name)
/**
* compose_mount_options - creates mount options for refferral
* @sb_mountdata: parent/root DFS mount options (template)
- * @ref_unc: refferral server UNC
+ * @dentry: point where we are going to mount
+ * @ref: server's referral
* @devname: pointer for saving device name
*
* creates mount options for submount based on template options sb_mountdata
@@ -116,7 +117,8 @@ static char *cifs_get_share_name(const char *node_name)
* Caller is responcible for freeing retunrned value if it is not error.
*/
static char *compose_mount_options(const char *sb_mountdata,
- const char *ref_unc,
+ struct dentry *dentry,
+ const struct dfs_info3_param *ref,
char **devname)
{
int rc;
@@ -126,11 +128,12 @@ static char *compose_mount_options(const char *sb_mountdata,
char *srvIP = NULL;
char sep = ',';
int off, noff;
+ char *fullpath;
if (sb_mountdata == NULL)
return ERR_PTR(-EINVAL);
- *devname = cifs_get_share_name(ref_unc);
+ *devname = cifs_get_share_name(ref->node_name);
rc = dns_resolve_server_name_to_ip(*devname, &srvIP);
if (rc != 0) {
cERROR(1, ("%s: Failed to resolve server part of %s to IP",
@@ -138,7 +141,12 @@ static char *compose_mount_options(const char *sb_mountdata,
mountdata = ERR_PTR(rc);
goto compose_mount_options_out;
}
- md_len = strlen(sb_mountdata) + strlen(srvIP) + strlen(ref_unc) + 3;
+ /* md_len = strlen(...) + 12 for 'sep+prefixpath='
+ * assuming that we have 'unc=' and 'ip=' in
+ * the original sb_mountdata
+ */
+ md_len = strlen(sb_mountdata) + strlen(srvIP) +
+ strlen(ref->node_name) + 12;
mountdata = kzalloc(md_len+1, GFP_KERNEL);
if (mountdata == NULL) {
mountdata = ERR_PTR(-ENOMEM);
@@ -152,41 +160,56 @@ static char *compose_mount_options(const char *sb_mountdata,
strncpy(mountdata, sb_mountdata, 5);
off += 5;
}
- while ((tkn_e = strchr(sb_mountdata+off, sep))) {
- noff = (tkn_e - (sb_mountdata+off)) + 1;
- if (strnicmp(sb_mountdata+off, "unc=", 4) == 0) {
+
+ do {
+ tkn_e = strchr(sb_mountdata + off, sep);
+ if (tkn_e == NULL)
+ noff = strlen(sb_mountdata + off);
+ else
+ noff = tkn_e - (sb_mountdata + off) + 1;
+
+ if (strnicmp(sb_mountdata + off, "unc=", 4) == 0) {
off += noff;
continue;
}
- if (strnicmp(sb_mountdata+off, "ip=", 3) == 0) {
+ if (strnicmp(sb_mountdata + off, "ip=", 3) == 0) {
off += noff;
continue;
}
- if (strnicmp(sb_mountdata+off, "prefixpath=", 3) == 0) {
+ if (strnicmp(sb_mountdata + off, "prefixpath=", 11) == 0) {
off += noff;
continue;
}
- strncat(mountdata, sb_mountdata+off, noff);
+ strncat(mountdata, sb_mountdata + off, noff);
off += noff;
- }
- strcat(mountdata, sb_mountdata+off);
+ } while (tkn_e);
+ strcat(mountdata, sb_mountdata + off);
mountdata[md_len] = '\0';
/* copy new IP and ref share name */
- strcat(mountdata, ",ip=");
+ if (mountdata[strlen(mountdata) - 1] != sep)
+ strncat(mountdata, &sep, 1);
+ strcat(mountdata, "ip=");
strcat(mountdata, srvIP);
- strcat(mountdata, ",unc=");
+ strncat(mountdata, &sep, 1);
+ strcat(mountdata, "unc=");
strcat(mountdata, *devname);
/* find & copy prefixpath */
- tkn_e = strchr(ref_unc+2, '\\');
- if (tkn_e) {
- tkn_e = strchr(tkn_e+1, '\\');
- if (tkn_e) {
- strcat(mountdata, ",prefixpath=");
- strcat(mountdata, tkn_e+1);
- }
+ tkn_e = strchr(ref->node_name + 2, '\\');
+ if (tkn_e == NULL) /* invalid unc, missing share name*/
+ goto compose_mount_options_out;
+
+ fullpath = build_path_from_dentry(dentry);
+ tkn_e = strchr(tkn_e + 1, '\\');
+ if (tkn_e || strlen(fullpath) - (ref->path_consumed)) {
+ strncat(mountdata, &sep, 1);
+ strcat(mountdata, "prefixpath=");
+ if (tkn_e)
+ strcat(mountdata, tkn_e + 1);
+ strcat(mountdata, fullpath + (ref->path_consumed));
}
+ kfree(fullpath);
/*cFYI(1,("%s: parent mountdata: %s", __func__,sb_mountdata));*/
/*cFYI(1, ("%s: submount mountdata: %s", __func__, mountdata ));*/
@@ -198,7 +221,7 @@ compose_mount_options_out:
static struct vfsmount *cifs_dfs_do_refmount(const struct vfsmount *mnt_parent,
- struct dentry *dentry, char *ref_unc)
+ struct dentry *dentry, const struct dfs_info3_param *ref)
{
struct cifs_sb_info *cifs_sb;
struct vfsmount *mnt;
@@ -207,7 +230,7 @@ static struct vfsmount *cifs_dfs_do_refmount(const struct vfsmount *mnt_parent,
cifs_sb = CIFS_SB(dentry->d_inode->i_sb);
mountdata = compose_mount_options(cifs_sb->mountdata,
- ref_unc, &devname);
+ dentry, ref, &devname);
if (IS_ERR(mountdata))
return (struct vfsmount *)mountdata;
@@ -310,7 +333,7 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd)
}
mnt = cifs_dfs_do_refmount(nd->path.mnt,
nd->path.dentry,
- referrals[i].node_name);
+ referrals + i);
cFYI(1, ("%s: cifs_dfs_do_refmount:%s , mnt:%p",
__func__,
referrals[i].node_name, mnt));
diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c
index fcee9298b62..0ab2fb5afef 100644
--- a/fs/cifs/cifs_spnego.c
+++ b/fs/cifs/cifs_spnego.c
@@ -73,8 +73,8 @@ struct key_type cifs_spnego_key_type = {
* strlen(";sec=ntlmsspi") */
#define MAX_MECH_STR_LEN 13
-/* max possible addr len eg FEDC:BA98:7654:3210:FEDC:BA98:7654:3210/60 */
-#define MAX_IPV6_ADDR_LEN 42
+/* max possible addr len eg FEDC:BA98:7654:3210:FEDC:BA98:7654:3210/128 */
+#define MAX_IPV6_ADDR_LEN 43
/* strlen of "host=" */
#define HOST_KEY_LEN 5
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index ac5915d61dc..d9cf467309e 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -514,10 +514,11 @@ static void cifs_umount_begin(struct super_block *sb)
tcon = cifs_sb->tcon;
if (tcon == NULL)
return;
- down(&tcon->tconSem);
- if (atomic_read(&tcon->useCount) == 1)
+
+ read_lock(&cifs_tcp_ses_lock);
+ if (tcon->tc_count == 1)
tcon->tidStatus = CifsExiting;
- up(&tcon->tconSem);
+ read_unlock(&cifs_tcp_ses_lock);
/* cancel_brl_requests(tcon); */ /* BB mark all brl mids as exiting */
/* cancel_notify_requests(tcon); */
@@ -1013,7 +1014,7 @@ static int cifs_oplock_thread(void *dummyarg)
not bother sending an oplock release if session
to server still is disconnected since oplock
already released by the server in that case */
- if (pTcon->tidStatus != CifsNeedReconnect) {
+ if (!pTcon->need_reconnect) {
rc = CIFSSMBLock(0, pTcon, netfid,
0 /* len */ , 0 /* offset */, 0,
0, LOCKING_ANDX_OPLOCK_RELEASE,
@@ -1031,24 +1032,24 @@ static int cifs_oplock_thread(void *dummyarg)
static int cifs_dnotify_thread(void *dummyarg)
{
struct list_head *tmp;
- struct cifsSesInfo *ses;
+ struct TCP_Server_Info *server;
do {
if (try_to_freeze())
continue;
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(15*HZ);
- read_lock(&GlobalSMBSeslock);
/* check if any stuck requests that need
to be woken up and wakeq so the
thread can wake up and error out */
- list_for_each(tmp, &GlobalSMBSessionList) {
- ses = list_entry(tmp, struct cifsSesInfo,
- cifsSessionList);
- if (ses->server && atomic_read(&ses->server->inFlight))
- wake_up_all(&ses->server->response_q);
+ read_lock(&cifs_tcp_ses_lock);
+ list_for_each(tmp, &cifs_tcp_ses_list) {
+ server = list_entry(tmp, struct TCP_Server_Info,
+ tcp_ses_list);
+ if (atomic_read(&server->inFlight))
+ wake_up_all(&server->response_q);
}
- read_unlock(&GlobalSMBSeslock);
+ read_unlock(&cifs_tcp_ses_lock);
} while (!kthread_should_stop());
return 0;
@@ -1059,9 +1060,7 @@ init_cifs(void)
{
int rc = 0;
cifs_proc_init();
-/* INIT_LIST_HEAD(&GlobalServerList);*/ /* BB not implemented yet */
- INIT_LIST_HEAD(&GlobalSMBSessionList);
- INIT_LIST_HEAD(&GlobalTreeConnectionList);
+ INIT_LIST_HEAD(&cifs_tcp_ses_list);
INIT_LIST_HEAD(&GlobalOplock_Q);
#ifdef CONFIG_CIFS_EXPERIMENTAL
INIT_LIST_HEAD(&GlobalDnotifyReqList);
@@ -1089,6 +1088,7 @@ init_cifs(void)
GlobalMaxActiveXid = 0;
memset(Local_System_Name, 0, 15);
rwlock_init(&GlobalSMBSeslock);
+ rwlock_init(&cifs_tcp_ses_lock);
spin_lock_init(&GlobalMid_Lock);
if (cifs_max_pending < 2) {
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 1cb1189f24e..c57c0565547 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -85,8 +85,7 @@ enum securityEnum {
};
enum protocolEnum {
- IPV4 = 0,
- IPV6,
+ TCP = 0,
SCTP
/* Netbios frames protocol not supported at this time */
};
@@ -122,6 +121,9 @@ struct cifs_cred {
*/
struct TCP_Server_Info {
+ struct list_head tcp_ses_list;
+ struct list_head smb_ses_list;
+ int srv_count; /* reference counter */
/* 15 character server name + 0x20 16th byte indicating type = srv */
char server_RFC1001_name[SERVER_NAME_LEN_WITH_NULL];
char unicode_server_Name[SERVER_NAME_LEN_WITH_NULL * 2];
@@ -143,7 +145,6 @@ struct TCP_Server_Info {
bool svlocal:1; /* local server or remote */
bool noblocksnd; /* use blocking sendmsg */
bool noautotune; /* do not autotune send buf sizes */
- atomic_t socketUseCount; /* number of open cifs sessions on socket */
atomic_t inFlight; /* number of requests on the wire to server */
#ifdef CONFIG_CIFS_STATS2
atomic_t inSend; /* requests trying to send */
@@ -194,13 +195,14 @@ struct cifsUidInfo {
* Session structure. One of these for each uid session with a particular host
*/
struct cifsSesInfo {
- struct list_head cifsSessionList;
+ struct list_head smb_ses_list;
+ struct list_head tcon_list;
struct semaphore sesSem;
#if 0
struct cifsUidInfo *uidInfo; /* pointer to user info */
#endif
struct TCP_Server_Info *server; /* pointer to server info */
- atomic_t inUse; /* # of mounts (tree connections) on this ses */
+ int ses_count; /* reference counter */
enum statusEnum status;
unsigned overrideSecFlg; /* if non-zero override global sec flags */
__u16 ipc_tid; /* special tid for connection to IPC share */
@@ -216,6 +218,7 @@ struct cifsSesInfo {
char userName[MAX_USERNAME_SIZE + 1];
char *domainName;
char *password;
+ bool need_reconnect:1; /* connection reset, uid now invalid */
};
/* no more than one of the following three session flags may be set */
#define CIFS_SES_NT4 1
@@ -230,16 +233,15 @@ struct cifsSesInfo {
* session
*/
struct cifsTconInfo {
- struct list_head cifsConnectionList;
+ struct list_head tcon_list;
+ int tc_count;
struct list_head openFileList;
- struct semaphore tconSem;
struct cifsSesInfo *ses; /* pointer to session associated with */
char treeName[MAX_TREE_SIZE + 1]; /* UNC name of resource in ASCII */
char *nativeFileSystem;
__u16 tid; /* The 2 byte tree id */
__u16 Flags; /* optional support bits */
enum statusEnum tidStatus;
- atomic_t useCount; /* how many explicit/implicit mounts to share */
#ifdef CONFIG_CIFS_STATS
atomic_t num_smbs_sent;
atomic_t num_writes;
@@ -288,6 +290,7 @@ struct cifsTconInfo {
bool unix_ext:1; /* if false disable Linux extensions to CIFS protocol
for this mount even if server would support */
bool local_lease:1; /* check leases (only) on local system not remote */
+ bool need_reconnect:1; /* connection reset, tid now invalid */
/* BB add field for back pointer to sb struct(s)? */
};
@@ -588,22 +591,30 @@ require use of the stronger protocol */
#endif
/*
- * The list of servers that did not respond with NT LM 0.12.
- * This list helps improve performance and eliminate the messages indicating
- * that we had a communications error talking to the server in this list.
+ * the list of TCP_Server_Info structures, ie each of the sockets
+ * connecting our client to a distinct server (ip address), is
+ * chained together by cifs_tcp_ses_list. The list of all our SMB
+ * sessions (and from that the tree connections) can be found
+ * by iterating over cifs_tcp_ses_list
*/
-/* Feature not supported */
-/* GLOBAL_EXTERN struct servers_not_supported *NotSuppList; */
+GLOBAL_EXTERN struct list_head cifs_tcp_ses_list;
/*
- * The following is a hash table of all the users we know about.
+ * This lock protects the cifs_tcp_ses_list, the list of smb sessions per
+ * tcp session, and the list of tcon's per smb session. It also protects
+ * the reference counters for the server, smb session, and tcon. Finally,
+ * changes to the tcon->tidStatus should be done while holding this lock.
*/
-GLOBAL_EXTERN struct smbUidInfo *GlobalUidList[UID_HASH];
+GLOBAL_EXTERN rwlock_t cifs_tcp_ses_lock;
-/* GLOBAL_EXTERN struct list_head GlobalServerList; BB not implemented yet */
-GLOBAL_EXTERN struct list_head GlobalSMBSessionList;
-GLOBAL_EXTERN struct list_head GlobalTreeConnectionList;
-GLOBAL_EXTERN rwlock_t GlobalSMBSeslock; /* protects list inserts on 3 above */
+/*
+ * This lock protects the cifs_file->llist and cifs_file->flist
+ * list operations, and updates to some flags (cifs_file->invalidHandle)
+ * It will be moved to either use the tcon->stat_lock or equivalent later.
+ * If cifs_tcp_ses_lock and the lock below are both needed to be held, then
+ * the cifs_tcp_ses_lock must be grabbed first and released last.
+ */
+GLOBAL_EXTERN rwlock_t GlobalSMBSeslock;
GLOBAL_EXTERN struct list_head GlobalOplock_Q;
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index d5eac48fc41..6d51696dc76 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -190,10 +190,10 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
/* need to prevent multiple threads trying to
simultaneously reconnect the same SMB session */
down(&tcon->ses->sesSem);
- if (tcon->ses->status == CifsNeedReconnect)
+ if (tcon->ses->need_reconnect)
rc = cifs_setup_session(0, tcon->ses,
nls_codepage);
- if (!rc && (tcon->tidStatus == CifsNeedReconnect)) {
+ if (!rc && (tcon->need_reconnect)) {
mark_open_files_invalid(tcon);
rc = CIFSTCon(0, tcon->ses, tcon->treeName,
tcon, nls_codepage);
@@ -337,10 +337,10 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
/* need to prevent multiple threads trying to
simultaneously reconnect the same SMB session */
down(&tcon->ses->sesSem);
- if (tcon->ses->status == CifsNeedReconnect)
+ if (tcon->ses->need_reconnect)
rc = cifs_setup_session(0, tcon->ses,
nls_codepage);
- if (!rc && (tcon->tidStatus == CifsNeedReconnect)) {
+ if (!rc && (tcon->need_reconnect)) {
mark_open_files_invalid(tcon);
rc = CIFSTCon(0, tcon->ses, tcon->treeName,
tcon, nls_codepage);
@@ -664,8 +664,9 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
rc = -EIO;
goto neg_err_exit;
}
-
- if (server->socketUseCount.counter > 1) {
+ read_lock(&cifs_tcp_ses_lock);
+ if (server->srv_count > 1) {
+ read_unlock(&cifs_tcp_ses_lock);
if (memcmp(server->server_GUID,
pSMBr->u.extended_response.
GUID, 16) != 0) {
@@ -674,9 +675,11 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
pSMBr->u.extended_response.GUID,
16);
}
- } else
+ } else {
+ read_unlock(&cifs_tcp_ses_lock);
memcpy(server->server_GUID,
pSMBr->u.extended_response.GUID, 16);
+ }
if (count == 16) {
server->secType = RawNTLMSSP;
@@ -739,50 +742,31 @@ CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
int rc = 0;
cFYI(1, ("In tree disconnect"));
- /*
- * If last user of the connection and
- * connection alive - disconnect it
- * If this is the last connection on the server session disconnect it
- * (and inside session disconnect we should check if tcp socket needs
- * to be freed and kernel thread woken up).
- */
- if (tcon)
- down(&tcon->tconSem);
- else
- return -EIO;
- atomic_dec(&tcon->useCount);
- if (atomic_read(&tcon->useCount) > 0) {
- up(&tcon->tconSem);
- return -EBUSY;
- }
+ /* BB: do we need to check this? These should never be NULL. */
+ if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
+ return -EIO;
- /* No need to return error on this operation if tid invalidated and
- closed on server already e.g. due to tcp session crashing */
- if (tcon->tidStatus == CifsNeedReconnect) {
- up(&tcon->tconSem);
+ /*
+ * No need to return error on this operation if tid invalidated and
+ * closed on server already e.g. due to tcp session crashing. Also,
+ * the tcon is no longer on the list, so no need to take lock before
+ * checking this.
+ */
+ if (tcon->need_reconnect)
return 0;
- }
- if ((tcon->ses == NULL) || (tcon->ses->server == NULL)) {
- up(&tcon->tconSem);
- return -EIO;
- }
rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
(void **)&smb_buffer);
- if (rc) {
- up(&tcon->tconSem);
+ if (rc)
return rc;
- }
rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0);
if (rc)
cFYI(1, ("Tree disconnect failed %d", rc));
- up(&tcon->tconSem);
-
/* No need to return error on this operation if tid invalidated and
- closed on server already e.g. due to tcp session crashing */
+ closed on server already e.g. due to tcp session crashing */
if (rc == -EAGAIN)
rc = 0;
@@ -796,43 +780,36 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
int rc = 0;
cFYI(1, ("In SMBLogoff for session disconnect"));
- if (ses)
- down(&ses->sesSem);
- else
+
+ /*
+ * BB: do we need to check validity of ses and server? They should
+ * always be valid since we have an active reference. If not, that
+ * should probably be a BUG()
+ */
+ if (!ses || !ses->server)
return -EIO;
- atomic_dec(&ses->inUse);
- if (atomic_read(&ses->inUse) > 0) {
- up(&ses->sesSem);
- return -EBUSY;
- }
+ down(&ses->sesSem);
+ if (ses->need_reconnect)
+ goto session_already_dead; /* no need to send SMBlogoff if uid
+ already closed due to reconnect */
rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
if (rc) {
up(&ses->sesSem);
return rc;
}
- if (ses->server) {
- pSMB->hdr.Mid = GetNextMid(ses->server);
+ pSMB->hdr.Mid = GetNextMid(ses->server);
- if (ses->server->secMode &
+ if (ses->server->secMode &
(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
- }
pSMB->hdr.Uid = ses->Suid;
pSMB->AndXCommand = 0xFF;
rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0);
- if (ses->server) {
- atomic_dec(&ses->server->socketUseCount);
- if (atomic_read(&ses->server->socketUseCount) == 0) {
- spin_lock(&GlobalMid_Lock);
- ses->server->tcpStatus = CifsExiting;
- spin_unlock(&GlobalMid_Lock);
- rc = -ESHUTDOWN;
- }
- }
+session_already_dead:
up(&ses->sesSem);
/* if session dead then we do not need to do ulogoff,
@@ -3922,6 +3899,27 @@ GetInodeNumOut:
return rc;
}
+/* computes length of UCS string converted to host codepage
+ * @src: UCS string
+ * @maxlen: length of the input string in UCS characters
+ * (not in bytes)
+ *
+ * return: size of input string in host codepage
+ */
+static int hostlen_fromUCS(const __le16 *src, const int maxlen,
+ const struct nls_table *nls_codepage) {
+ int i;
+ int hostlen = 0;
+ char to[4];
+ int charlen;
+ for (i = 0; (i < maxlen) && src[i]; ++i) {
+ charlen = nls_codepage->uni2char(le16_to_cpu(src[i]),
+ to, NLS_MAX_CHARSET_SIZE);
+ hostlen += charlen > 0 ? charlen : 1;
+ }
+ return hostlen;
+}
+
/* parses DFS refferal V3 structure
* caller is responsible for freeing target_nodes
* returns:
@@ -3932,7 +3930,8 @@ static int
parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
unsigned int *num_of_nodes,
struct dfs_info3_param **target_nodes,
- const struct nls_table *nls_codepage)
+ const struct nls_table *nls_codepage, int remap,
+ const char *searchName)
{
int i, rc = 0;
char *data_end;
@@ -3983,7 +3982,18 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
struct dfs_info3_param *node = (*target_nodes)+i;
node->flags = le16_to_cpu(pSMBr->DFSFlags);
- node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
+ if (is_unicode) {
+ __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
+ GFP_KERNEL);
+ cifsConvertToUCS((__le16 *) tmp, searchName,
+ PATH_MAX, nls_codepage, remap);
+ node->path_consumed = hostlen_fromUCS(tmp,
+ le16_to_cpu(pSMBr->PathConsumed)/2,
+ nls_codepage);
+ kfree(tmp);
+ } else
+ node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
+
node->server_type = le16_to_cpu(ref->ServerType);
node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
@@ -4116,7 +4126,8 @@ getDFSRetry:
/* parse returned result into more usable form */
rc = parse_DFS_referrals(pSMBr, num_of_nodes,
- target_nodes, nls_codepage);
+ target_nodes, nls_codepage, remap,
+ searchName);
GetDFSRefExit:
cifs_buf_release(pSMB);
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index e9f9248cb3f..c7d34171458 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -124,7 +124,7 @@ static int
cifs_reconnect(struct TCP_Server_Info *server)
{
int rc = 0;
- struct list_head *tmp;
+ struct list_head *tmp, *tmp2;
struct cifsSesInfo *ses;
struct cifsTconInfo *tcon;
struct mid_q_entry *mid_entry;
@@ -144,23 +144,17 @@ cifs_reconnect(struct TCP_Server_Info *server)
/* before reconnecting the tcp session, mark the smb session (uid)
and the tid bad so they are not used until reconnected */
- read_lock(&GlobalSMBSeslock);
- list_for_each(tmp, &GlobalSMBSessionList) {
- ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
- if (ses->server) {
- if (ses->server == server) {
- ses->status = CifsNeedReconnect;
- ses->ipc_tid = 0;
- }
+ read_lock(&cifs_tcp_ses_lock);
+ list_for_each(tmp, &server->smb_ses_list) {
+ ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list);
+ ses->need_reconnect = true;
+ ses->ipc_tid = 0;
+ list_for_each(tmp2, &ses->tcon_list) {
+ tcon = list_entry(tmp2, struct cifsTconInfo, tcon_list);
+ tcon->need_reconnect = true;
}
- /* else tcp and smb sessions need reconnection */
- }
- list_for_each(tmp, &GlobalTreeConnectionList) {
- tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
- if ((tcon->ses) && (tcon->ses->server == server))
- tcon->tidStatus = CifsNeedReconnect;
}
- read_unlock(&GlobalSMBSeslock);
+ read_unlock(&cifs_tcp_ses_lock);
/* do not want to be sending data on a socket we are freeing */
down(&server->tcpSem);
if (server->ssocket) {
@@ -193,7 +187,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
while ((server->tcpStatus != CifsExiting) &&
(server->tcpStatus != CifsGood)) {
try_to_freeze();
- if (server->protocolType == IPV6) {
+ if (server->addr.sockAddr6.sin6_family == AF_INET6) {
rc = ipv6_connect(&server->addr.sockAddr6,
&server->ssocket, server->noautotune);
} else {
@@ -417,9 +411,14 @@ incomplete_rcv:
msleep(1); /* minimum sleep to prevent looping
allowing socket to clear and app threads to set
tcpStatus CifsNeedReconnect if server hung */
- if (pdu_length < 4)
+ if (pdu_length < 4) {
+ iov.iov_base = (4 - pdu_length) +
+ (char *)smb_buffer;
+ iov.iov_len = pdu_length;
+ smb_msg.msg_control = NULL;
+ smb_msg.msg_controllen = 0;
goto incomplete_rcv;
- else
+ } else
continue;
} else if (length <= 0) {
if (server->tcpStatus == CifsNew) {
@@ -654,6 +653,11 @@ multi_t2_fnd:
}
} /* end while !EXITING */
+ /* take it off the list, if it's not already */
+ write_lock(&cifs_tcp_ses_lock);
+ list_del_init(&server->tcp_ses_list);
+ write_unlock(&cifs_tcp_ses_lock);
+
spin_lock(&GlobalMid_Lock);
server->tcpStatus = CifsExiting;
spin_unlock(&GlobalMid_Lock);
@@ -686,29 +690,29 @@ multi_t2_fnd:
if (smallbuf) /* no sense logging a debug message if NULL */
cifs_small_buf_release(smallbuf);
- read_lock(&GlobalSMBSeslock);
+ /*
+ * BB: we shouldn't have to do any of this. It shouldn't be
+ * possible to exit from the thread with active SMB sessions
+ */
+ read_lock(&cifs_tcp_ses_lock);
if (list_empty(&server->pending_mid_q)) {
/* loop through server session structures attached to this and
mark them dead */
- list_for_each(tmp, &GlobalSMBSessionList) {
- ses =
- list_entry(tmp, struct cifsSesInfo,
- cifsSessionList);
- if (ses->server == server) {
- ses->status = CifsExiting;
- ses->server = NULL;
- }
+ list_for_each(tmp, &server->smb_ses_list) {
+ ses = list_entry(tmp, struct cifsSesInfo,
+ smb_ses_list);
+ ses->status = CifsExiting;
+ ses->server = NULL;
}
- read_unlock(&GlobalSMBSeslock);
+ read_unlock(&cifs_tcp_ses_lock);
} else {
/* although we can not zero the server struct pointer yet,
since there are active requests which may depnd on them,
mark the corresponding SMB sessions as exiting too */
- list_for_each(tmp, &GlobalSMBSessionList) {
+ list_for_each(tmp, &server->smb_ses_list) {
ses = list_entry(tmp, struct cifsSesInfo,
- cifsSessionList);
- if (ses->server == server)
- ses->status = CifsExiting;
+ smb_ses_list);
+ ses->status = CifsExiting;
}
spin_lock(&GlobalMid_Lock);
@@ -723,7 +727,7 @@ multi_t2_fnd:
}
}
spin_unlock(&GlobalMid_Lock);
- read_unlock(&GlobalSMBSeslock);
+ read_unlock(&cifs_tcp_ses_lock);
/* 1/8th of sec is more than enough time for them to exit */
msleep(125);
}
@@ -745,14 +749,13 @@ multi_t2_fnd:
if there are any pointing to this (e.g
if a crazy root user tried to kill cifsd
kernel thread explicitly this might happen) */
- write_lock(&GlobalSMBSeslock);
- list_for_each(tmp, &GlobalSMBSessionList) {
- ses = list_entry(tmp, struct cifsSesInfo,
- cifsSessionList);
- if (ses->server == server)
- ses->server = NULL;
+ /* BB: This shouldn't be necessary, see above */
+ read_lock(&cifs_tcp_ses_lock);
+ list_for_each(tmp, &server->smb_ses_list) {
+ ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list);
+ ses->server = NULL;
}
- write_unlock(&GlobalSMBSeslock);
+ read_unlock(&cifs_tcp_ses_lock);
kfree(server->hostname);
task_to_wake = xchg(&server->tsk, NULL);
@@ -1352,94 +1355,158 @@ cifs_parse_mount_options(char *options, const char *devname,
return 0;
}
-static struct cifsSesInfo *
-cifs_find_tcp_session(struct in_addr *target_ip_addr,
- struct in6_addr *target_ip6_addr,
- char *userName, struct TCP_Server_Info **psrvTcp)
+static struct TCP_Server_Info *
+cifs_find_tcp_session(struct sockaddr *addr)
{
struct list_head *tmp;
- struct cifsSesInfo *ses;
-
- *psrvTcp = NULL;
+ struct TCP_Server_Info *server;
+ struct sockaddr_in *addr4 = (struct sockaddr_in *) addr;
+ struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) addr;
+
+ write_lock(&cifs_tcp_ses_lock);
+ list_for_each(tmp, &cifs_tcp_ses_list) {
+ server = list_entry(tmp, struct TCP_Server_Info,
+ tcp_ses_list);
+ /*
+ * the demux thread can exit on its own while still in CifsNew
+ * so don't accept any sockets in that state. Since the
+ * tcpStatus never changes back to CifsNew it's safe to check
+ * for this without a lock.
+ */
+ if (server->tcpStatus == CifsNew)
+ continue;
- read_lock(&GlobalSMBSeslock);
- list_for_each(tmp, &GlobalSMBSessionList) {
- ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
- if (!ses->server)
+ if (addr->sa_family == AF_INET &&
+ (addr4->sin_addr.s_addr !=
+ server->addr.sockAddr.sin_addr.s_addr))
+ continue;
+ else if (addr->sa_family == AF_INET6 &&
+ memcmp(&server->addr.sockAddr6.sin6_addr,
+ &addr6->sin6_addr, sizeof(addr6->sin6_addr)))
continue;
- if (target_ip_addr &&
- ses->server->addr.sockAddr.sin_addr.s_addr != target_ip_addr->s_addr)
- continue;
- else if (target_ip6_addr &&
- memcmp(&ses->server->addr.sockAddr6.sin6_addr,
- target_ip6_addr, sizeof(*target_ip6_addr)))
- continue;
- /* BB lock server and tcp session; increment use count here?? */
+ ++server->srv_count;
+ write_unlock(&cifs_tcp_ses_lock);
+ cFYI(1, ("Existing tcp session with server found"));
+ return server;
+ }
+ write_unlock(&cifs_tcp_ses_lock);
+ return NULL;
+}
- /* found a match on the TCP session */
- *psrvTcp = ses->server;
+static void
+cifs_put_tcp_session(struct TCP_Server_Info *server)
+{
+ struct task_struct *task;
- /* BB check if reconnection needed */
- if (strncmp(ses->userName, userName, MAX_USERNAME_SIZE) == 0) {
- read_unlock(&GlobalSMBSeslock);
- /* Found exact match on both TCP and
- SMB sessions */
- return ses;
- }
- /* else tcp and smb sessions need reconnection */
+ write_lock(&cifs_tcp_ses_lock);
+ if (--server->srv_count > 0) {
+ write_unlock(&cifs_tcp_ses_lock);
+ return;
}
- read_unlock(&GlobalSMBSeslock);
- return NULL;
+ list_del_init(&server->tcp_ses_list);
+ write_unlock(&cifs_tcp_ses_lock);
+
+ spin_lock(&GlobalMid_Lock);
+ server->tcpStatus = CifsExiting;
+ spin_unlock(&GlobalMid_Lock);
+
+ task = xchg(&server->tsk, NULL);
+ if (task)
+ force_sig(SIGKILL, task);
}
-static struct cifsTconInfo *
-find_unc(__be32 new_target_ip_addr, char *uncName, char *userName)
+static struct cifsSesInfo *
+cifs_find_smb_ses(struct TCP_Server_Info *server, char *username)
{
struct list_head *tmp;
- struct cifsTconInfo *tcon;
- __be32 old_ip;
-
- read_lock(&GlobalSMBSeslock);
+ struct cifsSesInfo *ses;
- list_for_each(tmp, &GlobalTreeConnectionList) {
- cFYI(1, ("Next tcon"));
- tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
- if (!tcon->ses || !tcon->ses->server)
+ write_lock(&cifs_tcp_ses_lock);
+ list_for_each(tmp, &server->smb_ses_list) {
+ ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list);
+ if (strncmp(ses->userName, username, MAX_USERNAME_SIZE))
continue;
- old_ip = tcon->ses->server->addr.sockAddr.sin_addr.s_addr;
- cFYI(1, ("old ip addr: %x == new ip %x ?",
- old_ip, new_target_ip_addr));
+ ++ses->ses_count;
+ write_unlock(&cifs_tcp_ses_lock);
+ return ses;
+ }
+ write_unlock(&cifs_tcp_ses_lock);
+ return NULL;
+}
- if (old_ip != new_target_ip_addr)
- continue;
+static void
+cifs_put_smb_ses(struct cifsSesInfo *ses)
+{
+ int xid;
+ struct TCP_Server_Info *server = ses->server;
- /* BB lock tcon, server, tcp session and increment use count? */
- /* found a match on the TCP session */
- /* BB check if reconnection needed */
- cFYI(1, ("IP match, old UNC: %s new: %s",
- tcon->treeName, uncName));
+ write_lock(&cifs_tcp_ses_lock);
+ if (--ses->ses_count > 0) {
+ write_unlock(&cifs_tcp_ses_lock);
+ return;
+ }
- if (strncmp(tcon->treeName, uncName, MAX_TREE_SIZE))
- continue;
+ list_del_init(&ses->smb_ses_list);
+ write_unlock(&cifs_tcp_ses_lock);
- cFYI(1, ("and old usr: %s new: %s",
- tcon->treeName, uncName));
+ if (ses->status == CifsGood) {
+ xid = GetXid();
+ CIFSSMBLogoff(xid, ses);
+ _FreeXid(xid);
+ }
+ sesInfoFree(ses);
+ cifs_put_tcp_session(server);
+}
- if (strncmp(tcon->ses->userName, userName, MAX_USERNAME_SIZE))
+static struct cifsTconInfo *
+cifs_find_tcon(struct cifsSesInfo *ses, const char *unc)
+{
+ struct list_head *tmp;
+ struct cifsTconInfo *tcon;
+
+ write_lock(&cifs_tcp_ses_lock);
+ list_for_each(tmp, &ses->tcon_list) {
+ tcon = list_entry(tmp, struct cifsTconInfo, tcon_list);
+ if (tcon->tidStatus == CifsExiting)
+ continue;
+ if (strncmp(tcon->treeName, unc, MAX_TREE_SIZE))
continue;
- /* matched smb session (user name) */
- read_unlock(&GlobalSMBSeslock);
+ ++tcon->tc_count;
+ write_unlock(&cifs_tcp_ses_lock);
return tcon;
}
-
- read_unlock(&GlobalSMBSeslock);
+ write_unlock(&cifs_tcp_ses_lock);
return NULL;
}
+static void
+cifs_put_tcon(struct cifsTconInfo *tcon)
+{
+ int xid;
+ struct cifsSesInfo *ses = tcon->ses;
+
+ write_lock(&cifs_tcp_ses_lock);
+ if (--tcon->tc_count > 0) {
+ write_unlock(&cifs_tcp_ses_lock);
+ return;
+ }
+
+ list_del_init(&tcon->tcon_list);
+ write_unlock(&cifs_tcp_ses_lock);
+
+ xid = GetXid();
+ CIFSSMBTDis(xid, tcon);
+ _FreeXid(xid);
+
+ DeleteTconOplockQEntries(tcon);
+ tconInfoFree(tcon);
+ cifs_put_smb_ses(ses);
+}
+
int
get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path,
const struct nls_table *nls_codepage, unsigned int *pnum_referrals,
@@ -1876,14 +1943,90 @@ convert_delimiter(char *path, char delim)
}
}
-static void
-kill_cifsd(struct TCP_Server_Info *server)
+static void setup_cifs_sb(struct smb_vol *pvolume_info,
+ struct cifs_sb_info *cifs_sb)
{
- struct task_struct *task;
-
- task = xchg(&server->tsk, NULL);
- if (task)
- force_sig(SIGKILL, task);
+ if (pvolume_info->rsize > CIFSMaxBufSize) {
+ cERROR(1, ("rsize %d too large, using MaxBufSize",
+ pvolume_info->rsize));
+ cifs_sb->rsize = CIFSMaxBufSize;
+ } else if ((pvolume_info->rsize) &&
+ (pvolume_info->rsize <= CIFSMaxBufSize))
+ cifs_sb->rsize = pvolume_info->rsize;
+ else /* default */
+ cifs_sb->rsize = CIFSMaxBufSize;
+
+ if (pvolume_info->wsize > PAGEVEC_SIZE * PAGE_CACHE_SIZE) {
+ cERROR(1, ("wsize %d too large, using 4096 instead",
+ pvolume_info->wsize));
+ cifs_sb->wsize = 4096;
+ } else if (pvolume_info->wsize)
+ cifs_sb->wsize = pvolume_info->wsize;
+ else
+ cifs_sb->wsize = min_t(const int,
+ PAGEVEC_SIZE * PAGE_CACHE_SIZE,
+ 127*1024);
+ /* old default of CIFSMaxBufSize was too small now
+ that SMB Write2 can send multiple pages in kvec.
+ RFC1001 does not describe what happens when frame
+ bigger than 128K is sent so use that as max in
+ conjunction with 52K kvec constraint on arch with 4K
+ page size */
+
+ if (cifs_sb->rsize < 2048) {
+ cifs_sb->rsize = 2048;
+ /* Windows ME may prefer this */
+ cFYI(1, ("readsize set to minimum: 2048"));
+ }
+ /* calculate prepath */
+ cifs_sb->prepath = pvolume_info->prepath;
+ if (cifs_sb->prepath) {
+ cifs_sb->prepathlen = strlen(cifs_sb->prepath);
+ /* we can not convert the / to \ in the path
+ separators in the prefixpath yet because we do not
+ know (until reset_cifs_unix_caps is called later)
+ whether POSIX PATH CAP is available. We normalize
+ the / to \ after reset_cifs_unix_caps is called */
+ pvolume_info->prepath = NULL;
+ } else
+ cifs_sb->prepathlen = 0;
+ cifs_sb->mnt_uid = pvolume_info->linux_uid;
+ cifs_sb->mnt_gid = pvolume_info->linux_gid;
+ cifs_sb->mnt_file_mode = pvolume_info->file_mode;
+ cifs_sb->mnt_dir_mode = pvolume_info->dir_mode;
+ cFYI(1, ("file mode: 0x%x dir mode: 0x%x",
+ cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode));
+
+ if (pvolume_info->noperm)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
+ if (pvolume_info->setuids)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
+ if (pvolume_info->server_ino)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
+ if (pvolume_info->remap)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
+ if (pvolume_info->no_xattr)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
+ if (pvolume_info->sfu_emul)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
+ if (pvolume_info->nobrl)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
+ if (pvolume_info->cifs_acl)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
+ if (pvolume_info->override_uid)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
+ if (pvolume_info->override_gid)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
+ if (pvolume_info->dynperm)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
+ if (pvolume_info->direct_io) {
+ cFYI(1, ("mounting share using direct i/o"));
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
+ }
+
+ if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
+ cERROR(1, ("mount option dynperm ignored if cifsacl "
+ "mount option supported"));
}
int
@@ -1892,13 +2035,12 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
{
int rc = 0;
int xid;
- int address_type = AF_INET;
struct socket *csocket = NULL;
- struct sockaddr_in sin_server;
- struct sockaddr_in6 sin_server6;
+ struct sockaddr addr;
+ struct sockaddr_in *sin_server = (struct sockaddr_in *) &addr;
+ struct sockaddr_in6 *sin_server6 = (struct sockaddr_in6 *) &addr;
struct smb_vol volume_info;
struct cifsSesInfo *pSesInfo = NULL;
- struct cifsSesInfo *existingCifsSes = NULL;
struct cifsTconInfo *tcon = NULL;
struct TCP_Server_Info *srvTcp = NULL;
@@ -1906,6 +2048,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
/* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */
+ memset(&addr, 0, sizeof(struct sockaddr));
memset(&volume_info, 0, sizeof(struct smb_vol));
if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
rc = -EINVAL;
@@ -1928,16 +2071,16 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
if (volume_info.UNCip && volume_info.UNC) {
rc = cifs_inet_pton(AF_INET, volume_info.UNCip,
- &sin_server.sin_addr.s_addr);
+ &sin_server->sin_addr.s_addr);
if (rc <= 0) {
/* not ipv4 address, try ipv6 */
rc = cifs_inet_pton(AF_INET6, volume_info.UNCip,
- &sin_server6.sin6_addr.in6_u);
+ &sin_server6->sin6_addr.in6_u);
if (rc > 0)
- address_type = AF_INET6;
+ addr.sa_family = AF_INET6;
} else {
- address_type = AF_INET;
+ addr.sa_family = AF_INET;
}
if (rc <= 0) {
@@ -1977,41 +2120,25 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
}
}
- if (address_type == AF_INET)
- existingCifsSes = cifs_find_tcp_session(&sin_server.sin_addr,
- NULL /* no ipv6 addr */,
- volume_info.username, &srvTcp);
- else if (address_type == AF_INET6) {
- cFYI(1, ("looking for ipv6 address"));
- existingCifsSes = cifs_find_tcp_session(NULL /* no ipv4 addr */,
- &sin_server6.sin6_addr,
- volume_info.username, &srvTcp);
- } else {
- rc = -EINVAL;
- goto out;
- }
-
- if (srvTcp) {
- cFYI(1, ("Existing tcp session with server found"));
- } else { /* create socket */
- if (volume_info.port)
- sin_server.sin_port = htons(volume_info.port);
- else
- sin_server.sin_port = 0;
- if (address_type == AF_INET6) {
+ srvTcp = cifs_find_tcp_session(&addr);
+ if (!srvTcp) { /* create socket */
+ if (addr.sa_family == AF_INET6) {
cFYI(1, ("attempting ipv6 connect"));
/* BB should we allow ipv6 on port 139? */
/* other OS never observed in Wild doing 139 with v6 */
- rc = ipv6_connect(&sin_server6, &csocket,
+ sin_server6->sin6_port = htons(volume_info.port);
+ rc = ipv6_connect(sin_server6, &csocket,
volume_info.noblocksnd);
- } else
- rc = ipv4_connect(&sin_server, &csocket,
+ } else {
+ sin_server->sin_port = htons(volume_info.port);
+ rc = ipv4_connect(sin_server, &csocket,
volume_info.source_rfc1001_name,
volume_info.target_rfc1001_name,
volume_info.noblocksnd,
volume_info.noautotune);
+ }
if (rc < 0) {
- cERROR(1, ("Error connecting to IPv4 socket. "
+ cERROR(1, ("Error connecting to socket. "
"Aborting operation"));
if (csocket != NULL)
sock_release(csocket);
@@ -2026,12 +2153,15 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
} else {
srvTcp->noblocksnd = volume_info.noblocksnd;
srvTcp->noautotune = volume_info.noautotune;
- memcpy(&srvTcp->addr.sockAddr, &sin_server,
- sizeof(struct sockaddr_in));
+ if (addr.sa_family == AF_INET6)
+ memcpy(&srvTcp->addr.sockAddr6, sin_server6,
+ sizeof(struct sockaddr_in6));
+ else
+ memcpy(&srvTcp->addr.sockAddr, sin_server,
+ sizeof(struct sockaddr_in));
atomic_set(&srvTcp->inFlight, 0);
/* BB Add code for ipv6 case too */
srvTcp->ssocket = csocket;
- srvTcp->protocolType = IPV4;
srvTcp->hostname = extract_hostname(volume_info.UNC);
if (IS_ERR(srvTcp->hostname)) {
rc = PTR_ERR(srvTcp->hostname);
@@ -2061,15 +2191,28 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
memcpy(srvTcp->server_RFC1001_name,
volume_info.target_rfc1001_name, 16);
srvTcp->sequence_number = 0;
+ INIT_LIST_HEAD(&srvTcp->tcp_ses_list);
+ INIT_LIST_HEAD(&srvTcp->smb_ses_list);
+ ++srvTcp->srv_count;
+ write_lock(&cifs_tcp_ses_lock);
+ list_add(&srvTcp->tcp_ses_list,
+ &cifs_tcp_ses_list);
+ write_unlock(&cifs_tcp_ses_lock);
}
}
- if (existingCifsSes) {
- pSesInfo = existingCifsSes;
+ pSesInfo = cifs_find_smb_ses(srvTcp, volume_info.username);
+ if (pSesInfo) {
cFYI(1, ("Existing smb sess found (status=%d)",
pSesInfo->status));
+ /*
+ * The existing SMB session already has a reference to srvTcp,
+ * so we can put back the extra one we got before
+ */
+ cifs_put_tcp_session(srvTcp);
+
down(&pSesInfo->sesSem);
- if (pSesInfo->status == CifsNeedReconnect) {
+ if (pSesInfo->need_reconnect) {
cFYI(1, ("Session needs reconnect"));
rc = cifs_setup_session(xid, pSesInfo,
cifs_sb->local_nls);
@@ -2078,187 +2221,101 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
} else if (!rc) {
cFYI(1, ("Existing smb sess not found"));
pSesInfo = sesInfoAlloc();
- if (pSesInfo == NULL)
+ if (pSesInfo == NULL) {
rc = -ENOMEM;
- else {
- pSesInfo->server = srvTcp;
- sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
- NIPQUAD(sin_server.sin_addr.s_addr));
- }
+ goto mount_fail_check;
+ }
+
+ /* new SMB session uses our srvTcp ref */
+ pSesInfo->server = srvTcp;
+ sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
+ NIPQUAD(sin_server->sin_addr.s_addr));
+
+ write_lock(&cifs_tcp_ses_lock);
+ list_add(&pSesInfo->smb_ses_list, &srvTcp->smb_ses_list);
+ write_unlock(&cifs_tcp_ses_lock);
+
+ /* volume_info.password freed at unmount */
+ if (volume_info.password) {
+ pSesInfo->password = volume_info.password;
+ /* set to NULL to prevent freeing on exit */
+ volume_info.password = NULL;
+ }
+ if (volume_info.username)
+ strncpy(pSesInfo->userName, volume_info.username,
+ MAX_USERNAME_SIZE);
+ if (volume_info.domainname) {
+ int len = strlen(volume_info.domainname);
+ pSesInfo->domainName = kmalloc(len + 1, GFP_KERNEL);
+ if (pSesInfo->domainName)
+ strcpy(pSesInfo->domainName,
+ volume_info.domainname);
+ }
+ pSesInfo->linux_uid = volume_info.linux_uid;
+ pSesInfo->overrideSecFlg = volume_info.secFlg;
+ down(&pSesInfo->sesSem);
- if (!rc) {
- /* volume_info.password freed at unmount */
- if (volume_info.password) {
- pSesInfo->password = volume_info.password;
- /* set to NULL to prevent freeing on exit */
- volume_info.password = NULL;
- }
- if (volume_info.username)
- strncpy(pSesInfo->userName,
- volume_info.username,
- MAX_USERNAME_SIZE);
- if (volume_info.domainname) {
- int len = strlen(volume_info.domainname);
- pSesInfo->domainName =
- kmalloc(len + 1, GFP_KERNEL);
- if (pSesInfo->domainName)
- strcpy(pSesInfo->domainName,
- volume_info.domainname);
- }
- pSesInfo->linux_uid = volume_info.linux_uid;
- pSesInfo->overrideSecFlg = volume_info.secFlg;
- down(&pSesInfo->sesSem);
- /* BB FIXME need to pass vol->secFlgs BB */
- rc = cifs_setup_session(xid, pSesInfo,
- cifs_sb->local_nls);
- up(&pSesInfo->sesSem);
- if (!rc)
- atomic_inc(&srvTcp->socketUseCount);
- }
+ /* BB FIXME need to pass vol->secFlgs BB */
+ rc = cifs_setup_session(xid, pSesInfo,
+ cifs_sb->local_nls);
+ up(&pSesInfo->sesSem);
}
/* search for existing tcon to this server share */
if (!rc) {
- if (volume_info.rsize > CIFSMaxBufSize) {
- cERROR(1, ("rsize %d too large, using MaxBufSize",
- volume_info.rsize));
- cifs_sb->rsize = CIFSMaxBufSize;
- } else if ((volume_info.rsize) &&
- (volume_info.rsize <= CIFSMaxBufSize))
- cifs_sb->rsize = volume_info.rsize;
- else /* default */
- cifs_sb->rsize = CIFSMaxBufSize;
-
- if (volume_info.wsize > PAGEVEC_SIZE * PAGE_CACHE_SIZE) {
- cERROR(1, ("wsize %d too large, using 4096 instead",
- volume_info.wsize));
- cifs_sb->wsize = 4096;
- } else if (volume_info.wsize)
- cifs_sb->wsize = volume_info.wsize;
- else
- cifs_sb->wsize =
- min_t(const int, PAGEVEC_SIZE * PAGE_CACHE_SIZE,
- 127*1024);
- /* old default of CIFSMaxBufSize was too small now
- that SMB Write2 can send multiple pages in kvec.
- RFC1001 does not describe what happens when frame
- bigger than 128K is sent so use that as max in
- conjunction with 52K kvec constraint on arch with 4K
- page size */
-
- if (cifs_sb->rsize < 2048) {
- cifs_sb->rsize = 2048;
- /* Windows ME may prefer this */
- cFYI(1, ("readsize set to minimum: 2048"));
- }
- /* calculate prepath */
- cifs_sb->prepath = volume_info.prepath;
- if (cifs_sb->prepath) {
- cifs_sb->prepathlen = strlen(cifs_sb->prepath);
- /* we can not convert the / to \ in the path
- separators in the prefixpath yet because we do not
- know (until reset_cifs_unix_caps is called later)
- whether POSIX PATH CAP is available. We normalize
- the / to \ after reset_cifs_unix_caps is called */
- volume_info.prepath = NULL;
- } else
- cifs_sb->prepathlen = 0;
- cifs_sb->mnt_uid = volume_info.linux_uid;
- cifs_sb->mnt_gid = volume_info.linux_gid;
- cifs_sb->mnt_file_mode = volume_info.file_mode;
- cifs_sb->mnt_dir_mode = volume_info.dir_mode;
- cFYI(1, ("file mode: 0x%x dir mode: 0x%x",
- cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode));
-
- if (volume_info.noperm)
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
- if (volume_info.setuids)
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
- if (volume_info.server_ino)
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
- if (volume_info.remap)
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
- if (volume_info.no_xattr)
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
- if (volume_info.sfu_emul)
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
- if (volume_info.nobrl)
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
- if (volume_info.cifs_acl)
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
- if (volume_info.override_uid)
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
- if (volume_info.override_gid)
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
- if (volume_info.dynperm)
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
- if (volume_info.direct_io) {
- cFYI(1, ("mounting share using direct i/o"));
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
- }
+ setup_cifs_sb(&volume_info, cifs_sb);
- if ((volume_info.cifs_acl) && (volume_info.dynperm))
- cERROR(1, ("mount option dynperm ignored if cifsacl "
- "mount option supported"));
-
- tcon =
- find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
- volume_info.username);
+ tcon = cifs_find_tcon(pSesInfo, volume_info.UNC);
if (tcon) {
cFYI(1, ("Found match on UNC path"));
- /* we can have only one retry value for a connection
- to a share so for resources mounted more than once
- to the same server share the last value passed in
- for the retry flag is used */
- tcon->retry = volume_info.retry;
- tcon->nocase = volume_info.nocase;
- tcon->local_lease = volume_info.local_lease;
+ /* existing tcon already has a reference */
+ cifs_put_smb_ses(pSesInfo);
if (tcon->seal != volume_info.seal)
cERROR(1, ("transport encryption setting "
"conflicts with existing tid"));
} else {
tcon = tconInfoAlloc();
- if (tcon == NULL)
+ if (tcon == NULL) {
rc = -ENOMEM;
- else {
- /* check for null share name ie connecting to
- * dfs root */
-
- /* BB check if this works for exactly length
- * three strings */
- if ((strchr(volume_info.UNC + 3, '\\') == NULL)
- && (strchr(volume_info.UNC + 3, '/') ==
- NULL)) {
-/* rc = connect_to_dfs_path(xid, pSesInfo,
- "", cifs_sb->local_nls,
- cifs_sb->mnt_cifs_flags &
- CIFS_MOUNT_MAP_SPECIAL_CHR);*/
- cFYI(1, ("DFS root not supported"));
- rc = -ENODEV;
- goto out;
- } else {
- /* BB Do we need to wrap sesSem around
- * this TCon call and Unix SetFS as
- * we do on SessSetup and reconnect? */
- rc = CIFSTCon(xid, pSesInfo,
- volume_info.UNC,
- tcon, cifs_sb->local_nls);
- cFYI(1, ("CIFS Tcon rc = %d", rc));
- if (volume_info.nodfs) {
- tcon->Flags &=
- ~SMB_SHARE_IS_IN_DFS;
- cFYI(1, ("DFS disabled (%d)",
- tcon->Flags));
- }
- }
- if (!rc) {
- atomic_inc(&pSesInfo->inUse);
- tcon->retry = volume_info.retry;
- tcon->nocase = volume_info.nocase;
- tcon->seal = volume_info.seal;
+ goto mount_fail_check;
+ }
+ tcon->ses = pSesInfo;
+
+ /* check for null share name ie connect to dfs root */
+ if ((strchr(volume_info.UNC + 3, '\\') == NULL)
+ && (strchr(volume_info.UNC + 3, '/') == NULL)) {
+ /* rc = connect_to_dfs_path(...) */
+ cFYI(1, ("DFS root not supported"));
+ rc = -ENODEV;
+ goto mount_fail_check;
+ } else {
+ /* BB Do we need to wrap sesSem around
+ * this TCon call and Unix SetFS as
+ * we do on SessSetup and reconnect? */
+ rc = CIFSTCon(xid, pSesInfo, volume_info.UNC,
+ tcon, cifs_sb->local_nls);
+ cFYI(1, ("CIFS Tcon rc = %d", rc));
+ if (volume_info.nodfs) {
+ tcon->Flags &= ~SMB_SHARE_IS_IN_DFS;
+ cFYI(1, ("DFS disabled (%d)",
+ tcon->Flags));
}
}
- }
+ if (rc)
+ goto mount_fail_check;
+ tcon->seal = volume_info.seal;
+ write_lock(&cifs_tcp_ses_lock);
+ list_add(&tcon->tcon_list, &pSesInfo->tcon_list);
+ write_unlock(&cifs_tcp_ses_lock);
+ }
+
+ /* we can have only one retry value for a connection
+ to a share so for resources mounted more than once
+ to the same server share the last value passed in
+ for the retry flag is used */
+ tcon->retry = volume_info.retry;
+ tcon->nocase = volume_info.nocase;
+ tcon->local_lease = volume_info.local_lease;
}
if (pSesInfo) {
if (pSesInfo->capabilities & CAP_LARGE_FILES) {
@@ -2270,80 +2327,49 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
/* BB FIXME fix time_gran to be larger for LANMAN sessions */
sb->s_time_gran = 100;
-/* on error free sesinfo and tcon struct if needed */
+mount_fail_check:
+ /* on error free sesinfo and tcon struct if needed */
if (rc) {
- /* if session setup failed, use count is zero but
- we still need to free cifsd thread */
- if (atomic_read(&srvTcp->socketUseCount) == 0) {
- spin_lock(&GlobalMid_Lock);
- srvTcp->tcpStatus = CifsExiting;
- spin_unlock(&GlobalMid_Lock);
- kill_cifsd(srvTcp);
- }
- /* If find_unc succeeded then rc == 0 so we can not end */
- if (tcon) /* up accidently freeing someone elses tcon struct */
- tconInfoFree(tcon);
- if (existingCifsSes == NULL) {
- if (pSesInfo) {
- if ((pSesInfo->server) &&
- (pSesInfo->status == CifsGood)) {
- int temp_rc;
- temp_rc = CIFSSMBLogoff(xid, pSesInfo);
- /* if the socketUseCount is now zero */
- if ((temp_rc == -ESHUTDOWN) &&
- (pSesInfo->server))
- kill_cifsd(pSesInfo->server);
- } else {
- cFYI(1, ("No session or bad tcon"));
- if (pSesInfo->server) {
- spin_lock(&GlobalMid_Lock);
- srvTcp->tcpStatus = CifsExiting;
- spin_unlock(&GlobalMid_Lock);
- kill_cifsd(pSesInfo->server);
- }
- }
- sesInfoFree(pSesInfo);
- /* pSesInfo = NULL; */
- }
- }
- } else {
- atomic_inc(&tcon->useCount);
- cifs_sb->tcon = tcon;
- tcon->ses = pSesInfo;
-
- /* do not care if following two calls succeed - informational */
- if (!tcon->ipc) {
- CIFSSMBQFSDeviceInfo(xid, tcon);
- CIFSSMBQFSAttributeInfo(xid, tcon);
- }
-
- /* tell server which Unix caps we support */
- if (tcon->ses->capabilities & CAP_UNIX)
- /* reset of caps checks mount to see if unix extensions
- disabled for just this mount */
- reset_cifs_unix_caps(xid, tcon, sb, &volume_info);
+ /* If find_unc succeeded then rc == 0 so we can not end */
+ /* up accidently freeing someone elses tcon struct */
+ if (tcon)
+ cifs_put_tcon(tcon);
+ else if (pSesInfo)
+ cifs_put_smb_ses(pSesInfo);
else
- tcon->unix_ext = 0; /* server does not support them */
+ cifs_put_tcp_session(srvTcp);
+ goto out;
+ }
+ cifs_sb->tcon = tcon;
- /* convert forward to back slashes in prepath here if needed */
- if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) == 0)
- convert_delimiter(cifs_sb->prepath,
- CIFS_DIR_SEP(cifs_sb));
+ /* do not care if following two calls succeed - informational */
+ if (!tcon->ipc) {
+ CIFSSMBQFSDeviceInfo(xid, tcon);
+ CIFSSMBQFSAttributeInfo(xid, tcon);
+ }
- if ((tcon->unix_ext == 0) && (cifs_sb->rsize > (1024 * 127))) {
- cifs_sb->rsize = 1024 * 127;
- cFYI(DBG2,
- ("no very large read support, rsize now 127K"));
- }
- if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X))
- cifs_sb->wsize = min(cifs_sb->wsize,
- (tcon->ses->server->maxBuf -
- MAX_CIFS_HDR_SIZE));
- if (!(tcon->ses->capabilities & CAP_LARGE_READ_X))
- cifs_sb->rsize = min(cifs_sb->rsize,
- (tcon->ses->server->maxBuf -
- MAX_CIFS_HDR_SIZE));
+ /* tell server which Unix caps we support */
+ if (tcon->ses->capabilities & CAP_UNIX)
+ /* reset of caps checks mount to see if unix extensions
+ disabled for just this mount */
+ reset_cifs_unix_caps(xid, tcon, sb, &volume_info);
+ else
+ tcon->unix_ext = 0; /* server does not support them */
+
+ /* convert forward to back slashes in prepath here if needed */
+ if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) == 0)
+ convert_delimiter(cifs_sb->prepath, CIFS_DIR_SEP(cifs_sb));
+
+ if ((tcon->unix_ext == 0) && (cifs_sb->rsize > (1024 * 127))) {
+ cifs_sb->rsize = 1024 * 127;
+ cFYI(DBG2, ("no very large read support, rsize now 127K"));
}
+ if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X))
+ cifs_sb->wsize = min(cifs_sb->wsize,
+ (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE));
+ if (!(tcon->ses->capabilities & CAP_LARGE_READ_X))
+ cifs_sb->rsize = min(cifs_sb->rsize,
+ (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE));
/* volume_info.password is freed above when existing session found
(in which case it is not needed anymore) but when new sesion is created
@@ -3513,6 +3539,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
/* above now done in SendReceive */
if ((rc == 0) && (tcon != NULL)) {
tcon->tidStatus = CifsGood;
+ tcon->need_reconnect = false;
tcon->tid = smb_buffer_response->Tid;
bcc_ptr = pByteArea(smb_buffer_response);
length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
@@ -3584,48 +3611,17 @@ int
cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
{
int rc = 0;
- int xid;
- struct cifsSesInfo *ses = NULL;
char *tmp;
- xid = GetXid();
-
- if (cifs_sb->tcon) {
- ses = cifs_sb->tcon->ses; /* save ptr to ses before delete tcon!*/
- rc = CIFSSMBTDis(xid, cifs_sb->tcon);
- if (rc == -EBUSY) {
- FreeXid(xid);
- return 0;
- }
- DeleteTconOplockQEntries(cifs_sb->tcon);
- tconInfoFree(cifs_sb->tcon);
- if ((ses) && (ses->server)) {
- /* save off task so we do not refer to ses later */
- cFYI(1, ("About to do SMBLogoff "));
- rc = CIFSSMBLogoff(xid, ses);
- if (rc == -EBUSY) {
- FreeXid(xid);
- return 0;
- } else if (rc == -ESHUTDOWN) {
- cFYI(1, ("Waking up socket by sending signal"));
- if (ses->server)
- kill_cifsd(ses->server);
- rc = 0;
- } /* else - we have an smb session
- left on this socket do not kill cifsd */
- } else
- cFYI(1, ("No session or bad tcon"));
- }
+ if (cifs_sb->tcon)
+ cifs_put_tcon(cifs_sb->tcon);
cifs_sb->tcon = NULL;
tmp = cifs_sb->prepath;
cifs_sb->prepathlen = 0;
cifs_sb->prepath = NULL;
kfree(tmp);
- if (ses)
- sesInfoFree(ses);
- FreeXid(xid);
return rc;
}
@@ -3741,6 +3737,7 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
cFYI(1, ("CIFS Session Established successfully"));
spin_lock(&GlobalMid_Lock);
pSesInfo->status = CifsGood;
+ pSesInfo->need_reconnect = false;
spin_unlock(&GlobalMid_Lock);
}
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index ead1a3bb025..f0a81e631ae 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -488,12 +488,13 @@ int cifs_close(struct inode *inode, struct file *file)
pTcon = cifs_sb->tcon;
if (pSMBFile) {
struct cifsLockInfo *li, *tmp;
-
+ write_lock(&GlobalSMBSeslock);
pSMBFile->closePend = true;
if (pTcon) {
/* no sense reconnecting to close a file that is
already closed */
- if (pTcon->tidStatus != CifsNeedReconnect) {
+ if (!pTcon->need_reconnect) {
+ write_unlock(&GlobalSMBSeslock);
timeout = 2;
while ((atomic_read(&pSMBFile->wrtPending) != 0)
&& (timeout <= 2048)) {
@@ -510,12 +511,15 @@ int cifs_close(struct inode *inode, struct file *file)
timeout *= 4;
}
if (atomic_read(&pSMBFile->wrtPending))
- cERROR(1,
- ("close with pending writes"));
- rc = CIFSSMBClose(xid, pTcon,
+ cERROR(1, ("close with pending write"));
+ if (!pTcon->need_reconnect &&
+ !pSMBFile->invalidHandle)
+ rc = CIFSSMBClose(xid, pTcon,
pSMBFile->netfid);
- }
- }
+ } else
+ write_unlock(&GlobalSMBSeslock);
+ } else
+ write_unlock(&GlobalSMBSeslock);
/* Delete any outstanding lock records.
We'll lose them when the file is closed anyway. */
@@ -587,15 +591,18 @@ int cifs_closedir(struct inode *inode, struct file *file)
pTcon = cifs_sb->tcon;
cFYI(1, ("Freeing private data in close dir"));
+ write_lock(&GlobalSMBSeslock);
if (!pCFileStruct->srch_inf.endOfSearch &&
!pCFileStruct->invalidHandle) {
pCFileStruct->invalidHandle = true;
+ write_unlock(&GlobalSMBSeslock);
rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid);
cFYI(1, ("Closing uncompleted readdir with rc %d",
rc));
/* not much we can do if it fails anyway, ignore rc */
rc = 0;
- }
+ } else
+ write_unlock(&GlobalSMBSeslock);
ptmp = pCFileStruct->srch_inf.ntwrk_buf_start;
if (ptmp) {
cFYI(1, ("closedir free smb buf in srch struct"));
@@ -1404,7 +1411,10 @@ retry:
if ((wbc->nr_to_write -= n_iov) <= 0)
done = 1;
index = next;
- }
+ } else
+ /* Need to re-find the pages we skipped */
+ index = pvec.pages[0]->index + 1;
+
pagevec_release(&pvec);
}
if (!scanned && !done) {
@@ -1465,7 +1475,11 @@ static int cifs_write_end(struct file *file, struct address_space *mapping,
cFYI(1, ("write_end for page %p from pos %lld with %d bytes",
page, pos, copied));
- if (!PageUptodate(page) && copied == PAGE_CACHE_SIZE)
+ if (PageChecked(page)) {
+ if (copied == len)
+ SetPageUptodate(page);
+ ClearPageChecked(page);
+ } else if (!PageUptodate(page) && copied == PAGE_CACHE_SIZE)
SetPageUptodate(page);
if (!PageUptodate(page)) {
@@ -2052,39 +2066,70 @@ static int cifs_write_begin(struct file *file, struct address_space *mapping,
{
pgoff_t index = pos >> PAGE_CACHE_SHIFT;
loff_t offset = pos & (PAGE_CACHE_SIZE - 1);
+ loff_t page_start = pos & PAGE_MASK;
+ loff_t i_size;
+ struct page *page;
+ int rc = 0;
cFYI(1, ("write_begin from %lld len %d", (long long)pos, len));
- *pagep = __grab_cache_page(mapping, index);
- if (!*pagep)
- return -ENOMEM;
-
- if (PageUptodate(*pagep))
- return 0;
+ page = __grab_cache_page(mapping, index);
+ if (!page) {
+ rc = -ENOMEM;
+ goto out;
+ }
- /* If we are writing a full page it will be up to date,
- no need to read from the server */
- if (len == PAGE_CACHE_SIZE && flags & AOP_FLAG_UNINTERRUPTIBLE)
- return 0;
+ if (PageUptodate(page))
+ goto out;
- if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
- int rc;
+ /*
+ * If we write a full page it will be up to date, no need to read from
+ * the server. If the write is short, we'll end up doing a sync write
+ * instead.
+ */
+ if (len == PAGE_CACHE_SIZE)
+ goto out;
- /* might as well read a page, it is fast enough */
- rc = cifs_readpage_worker(file, *pagep, &offset);
+ /*
+ * optimize away the read when we have an oplock, and we're not
+ * expecting to use any of the data we'd be reading in. That
+ * is, when the page lies beyond the EOF, or straddles the EOF
+ * and the write will cover all of the existing data.
+ */
+ if (CIFS_I(mapping->host)->clientCanCacheRead) {
+ i_size = i_size_read(mapping->host);
+ if (page_start >= i_size ||
+ (offset == 0 && (pos + len) >= i_size)) {
+ zero_user_segments(page, 0, offset,
+ offset + len,
+ PAGE_CACHE_SIZE);
+ /*
+ * PageChecked means that the parts of the page
+ * to which we're not writing are considered up
+ * to date. Once the data is copied to the
+ * page, it can be set uptodate.
+ */
+ SetPageChecked(page);
+ goto out;
+ }
+ }
- /* we do not need to pass errors back
- e.g. if we do not have read access to the file
- because cifs_write_end will attempt synchronous writes
- -- shaggy */
+ if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
+ /*
+ * might as well read a page, it is fast enough. If we get
+ * an error, we don't need to return it. cifs_write_end will
+ * do a sync write instead since PG_uptodate isn't set.
+ */
+ cifs_readpage_worker(file, page, &page_start);
} else {
/* we could try using another file handle if there is one -
but how would we lock it to prevent close of that handle
racing with this read? In any case
this will be written out by write_end so is fine */
}
-
- return 0;
+out:
+ *pagep = page;
+ return rc;
}
const struct address_space_operations cifs_addr_ops = {
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 88786ba02d2..9ee3f689c2b 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -75,12 +75,12 @@ sesInfoAlloc(void)
ret_buf = kzalloc(sizeof(struct cifsSesInfo), GFP_KERNEL);
if (ret_buf) {
- write_lock(&GlobalSMBSeslock);
atomic_inc(&sesInfoAllocCount);
ret_buf->status = CifsNew;
- list_add(&ret_buf->cifsSessionList, &GlobalSMBSessionList);
+ ++ret_buf->ses_count;
+ INIT_LIST_HEAD(&ret_buf->smb_ses_list);
+ INIT_LIST_HEAD(&ret_buf->tcon_list);
init_MUTEX(&ret_buf->sesSem);
- write_unlock(&GlobalSMBSeslock);
}
return ret_buf;
}
@@ -93,10 +93,7 @@ sesInfoFree(struct cifsSesInfo *buf_to_free)
return;
}
- write_lock(&GlobalSMBSeslock);
atomic_dec(&sesInfoAllocCount);
- list_del(&buf_to_free->cifsSessionList);
- write_unlock(&GlobalSMBSeslock);
kfree(buf_to_free->serverOS);
kfree(buf_to_free->serverDomain);
kfree(buf_to_free->serverNOS);
@@ -111,17 +108,14 @@ tconInfoAlloc(void)
struct cifsTconInfo *ret_buf;
ret_buf = kzalloc(sizeof(struct cifsTconInfo), GFP_KERNEL);
if (ret_buf) {
- write_lock(&GlobalSMBSeslock);
atomic_inc(&tconInfoAllocCount);
- list_add(&ret_buf->cifsConnectionList,
- &GlobalTreeConnectionList);
ret_buf->tidStatus = CifsNew;
+ ++ret_buf->tc_count;
INIT_LIST_HEAD(&ret_buf->openFileList);
- init_MUTEX(&ret_buf->tconSem);
+ INIT_LIST_HEAD(&ret_buf->tcon_list);
#ifdef CONFIG_CIFS_STATS
spin_lock_init(&ret_buf->stat_lock);
#endif
- write_unlock(&GlobalSMBSeslock);
}
return ret_buf;
}
@@ -133,10 +127,7 @@ tconInfoFree(struct cifsTconInfo *buf_to_free)
cFYI(1, ("Null buffer passed to tconInfoFree"));
return;
}
- write_lock(&GlobalSMBSeslock);
atomic_dec(&tconInfoAllocCount);
- list_del(&buf_to_free->cifsConnectionList);
- write_unlock(&GlobalSMBSeslock);
kfree(buf_to_free->nativeFileSystem);
kfree(buf_to_free);
}
@@ -350,9 +341,9 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
if (current->fsuid != treeCon->ses->linux_uid) {
cFYI(1, ("Multiuser mode and UID "
"did not match tcon uid"));
- read_lock(&GlobalSMBSeslock);
- list_for_each(temp_item, &GlobalSMBSessionList) {
- ses = list_entry(temp_item, struct cifsSesInfo, cifsSessionList);
+ read_lock(&cifs_tcp_ses_lock);
+ list_for_each(temp_item, &treeCon->ses->server->smb_ses_list) {
+ ses = list_entry(temp_item, struct cifsSesInfo, smb_ses_list);
if (ses->linux_uid == current->fsuid) {
if (ses->server == treeCon->ses->server) {
cFYI(1, ("found matching uid substitute right smb_uid"));
@@ -364,7 +355,7 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
}
}
}
- read_unlock(&GlobalSMBSeslock);
+ read_unlock(&cifs_tcp_ses_lock);
}
}
}
@@ -497,9 +488,10 @@ bool
is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
{
struct smb_com_lock_req *pSMB = (struct smb_com_lock_req *)buf;
- struct list_head *tmp;
- struct list_head *tmp1;
+ struct list_head *tmp, *tmp1, *tmp2;
+ struct cifsSesInfo *ses;
struct cifsTconInfo *tcon;
+ struct cifsInodeInfo *pCifsInode;
struct cifsFileInfo *netfile;
cFYI(1, ("Checking for oplock break or dnotify response"));
@@ -554,42 +546,45 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
return false;
/* look up tcon based on tid & uid */
- read_lock(&GlobalSMBSeslock);
- list_for_each(tmp, &GlobalTreeConnectionList) {
- tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
- if ((tcon->tid == buf->Tid) && (srv == tcon->ses->server)) {
+ read_lock(&cifs_tcp_ses_lock);
+ list_for_each(tmp, &srv->smb_ses_list) {
+ ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list);
+ list_for_each(tmp1, &ses->tcon_list) {
+ tcon = list_entry(tmp1, struct cifsTconInfo, tcon_list);
+ if (tcon->tid != buf->Tid)
+ continue;
+
cifs_stats_inc(&tcon->num_oplock_brks);
- list_for_each(tmp1, &tcon->openFileList) {
- netfile = list_entry(tmp1, struct cifsFileInfo,
+ write_lock(&GlobalSMBSeslock);
+ list_for_each(tmp2, &tcon->openFileList) {
+ netfile = list_entry(tmp2, struct cifsFileInfo,
tlist);
- if (pSMB->Fid == netfile->netfid) {
- struct cifsInodeInfo *pCifsInode;
- read_unlock(&GlobalSMBSeslock);
- cFYI(1,
- ("file id match, oplock break"));
- pCifsInode =
- CIFS_I(netfile->pInode);
- pCifsInode->clientCanCacheAll = false;
- if (pSMB->OplockLevel == 0)
- pCifsInode->clientCanCacheRead
- = false;
- pCifsInode->oplockPending = true;
- AllocOplockQEntry(netfile->pInode,
- netfile->netfid,
- tcon);
- cFYI(1,
- ("about to wake up oplock thread"));
- if (oplockThread)
- wake_up_process(oplockThread);
- return true;
- }
+ if (pSMB->Fid != netfile->netfid)
+ continue;
+
+ write_unlock(&GlobalSMBSeslock);
+ read_unlock(&cifs_tcp_ses_lock);
+ cFYI(1, ("file id match, oplock break"));
+ pCifsInode = CIFS_I(netfile->pInode);
+ pCifsInode->clientCanCacheAll = false;
+ if (pSMB->OplockLevel == 0)
+ pCifsInode->clientCanCacheRead = false;
+ pCifsInode->oplockPending = true;
+ AllocOplockQEntry(netfile->pInode,
+ netfile->netfid, tcon);
+ cFYI(1, ("about to wake up oplock thread"));
+ if (oplockThread)
+ wake_up_process(oplockThread);
+
+ return true;
}
- read_unlock(&GlobalSMBSeslock);
+ write_unlock(&GlobalSMBSeslock);
+ read_unlock(&cifs_tcp_ses_lock);
cFYI(1, ("No matching file for oplock break"));
return true;
}
}
- read_unlock(&GlobalSMBSeslock);
+ read_unlock(&cifs_tcp_ses_lock);
cFYI(1, ("Can not process oplock break for non-existent connection"));
return true;
}
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 58d57299f2a..9f51f9bf029 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -741,11 +741,14 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
(index_to_find < first_entry_in_buffer)) {
/* close and restart search */
cFYI(1, ("search backing up - close and restart search"));
+ write_lock(&GlobalSMBSeslock);
if (!cifsFile->srch_inf.endOfSearch &&
!cifsFile->invalidHandle) {
cifsFile->invalidHandle = true;
+ write_unlock(&GlobalSMBSeslock);
CIFSFindClose(xid, pTcon, cifsFile->netfid);
- }
+ } else
+ write_unlock(&GlobalSMBSeslock);
if (cifsFile->srch_inf.ntwrk_buf_start) {
cFYI(1, ("freeing SMB ff cache buf on search rewind"));
if (cifsFile->srch_inf.smallBuf)
diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c
index d910501de6d..8d86b7960f0 100644
--- a/fs/dlm/lockspace.c
+++ b/fs/dlm/lockspace.c
@@ -812,7 +812,7 @@ int dlm_release_lockspace(void *lockspace, int force)
error = release_lockspace(ls, force);
if (!error)
ls_count--;
- else if (!ls_count)
+ if (!ls_count)
threads_stop();
mutex_unlock(&ls_lock);
diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c
index e22bc396134..0d713b69194 100644
--- a/fs/ecryptfs/keystore.c
+++ b/fs/ecryptfs/keystore.c
@@ -1037,17 +1037,14 @@ static int
decrypt_passphrase_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok,
struct ecryptfs_crypt_stat *crypt_stat)
{
- struct scatterlist dst_sg;
- struct scatterlist src_sg;
+ struct scatterlist dst_sg[2];
+ struct scatterlist src_sg[2];
struct mutex *tfm_mutex;
struct blkcipher_desc desc = {
.flags = CRYPTO_TFM_REQ_MAY_SLEEP
};
int rc = 0;
- sg_init_table(&dst_sg, 1);
- sg_init_table(&src_sg, 1);
-
if (unlikely(ecryptfs_verbosity > 0)) {
ecryptfs_printk(
KERN_DEBUG, "Session key encryption key (size [%d]):\n",
@@ -1066,8 +1063,8 @@ decrypt_passphrase_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok,
}
rc = virt_to_scatterlist(auth_tok->session_key.encrypted_key,
auth_tok->session_key.encrypted_key_size,
- &src_sg, 1);
- if (rc != 1) {
+ src_sg, 2);
+ if (rc < 1 || rc > 2) {
printk(KERN_ERR "Internal error whilst attempting to convert "
"auth_tok->session_key.encrypted_key to scatterlist; "
"expected rc = 1; got rc = [%d]. "
@@ -1079,8 +1076,8 @@ decrypt_passphrase_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok,
auth_tok->session_key.encrypted_key_size;
rc = virt_to_scatterlist(auth_tok->session_key.decrypted_key,
auth_tok->session_key.decrypted_key_size,
- &dst_sg, 1);
- if (rc != 1) {
+ dst_sg, 2);
+ if (rc < 1 || rc > 2) {
printk(KERN_ERR "Internal error whilst attempting to convert "
"auth_tok->session_key.decrypted_key to scatterlist; "
"expected rc = 1; got rc = [%d]\n", rc);
@@ -1096,7 +1093,7 @@ decrypt_passphrase_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok,
rc = -EINVAL;
goto out;
}
- rc = crypto_blkcipher_decrypt(&desc, &dst_sg, &src_sg,
+ rc = crypto_blkcipher_decrypt(&desc, dst_sg, src_sg,
auth_tok->session_key.encrypted_key_size);
mutex_unlock(tfm_mutex);
if (unlikely(rc)) {
@@ -1539,8 +1536,8 @@ write_tag_3_packet(char *dest, size_t *remaining_bytes,
size_t i;
size_t encrypted_session_key_valid = 0;
char session_key_encryption_key[ECRYPTFS_MAX_KEY_BYTES];
- struct scatterlist dst_sg;
- struct scatterlist src_sg;
+ struct scatterlist dst_sg[2];
+ struct scatterlist src_sg[2];
struct mutex *tfm_mutex = NULL;
u8 cipher_code;
size_t packet_size_length;
@@ -1619,8 +1616,8 @@ write_tag_3_packet(char *dest, size_t *remaining_bytes,
ecryptfs_dump_hex(session_key_encryption_key, 16);
}
rc = virt_to_scatterlist(crypt_stat->key, key_rec->enc_key_size,
- &src_sg, 1);
- if (rc != 1) {
+ src_sg, 2);
+ if (rc < 1 || rc > 2) {
ecryptfs_printk(KERN_ERR, "Error generating scatterlist "
"for crypt_stat session key; expected rc = 1; "
"got rc = [%d]. key_rec->enc_key_size = [%d]\n",
@@ -1629,8 +1626,8 @@ write_tag_3_packet(char *dest, size_t *remaining_bytes,
goto out;
}
rc = virt_to_scatterlist(key_rec->enc_key, key_rec->enc_key_size,
- &dst_sg, 1);
- if (rc != 1) {
+ dst_sg, 2);
+ if (rc < 1 || rc > 2) {
ecryptfs_printk(KERN_ERR, "Error generating scatterlist "
"for crypt_stat encrypted session key; "
"expected rc = 1; got rc = [%d]. "
@@ -1651,7 +1648,7 @@ write_tag_3_packet(char *dest, size_t *remaining_bytes,
rc = 0;
ecryptfs_printk(KERN_DEBUG, "Encrypting [%d] bytes of the key\n",
crypt_stat->key_size);
- rc = crypto_blkcipher_encrypt(&desc, &dst_sg, &src_sg,
+ rc = crypto_blkcipher_encrypt(&desc, dst_sg, src_sg,
(*key_rec).enc_key_size);
mutex_unlock(tfm_mutex);
if (rc) {
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index aec5c13f634..96355d50534 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -102,6 +102,8 @@
#define EP_UNACTIVE_PTR ((void *) -1L)
+#define EP_ITEM_COST (sizeof(struct epitem) + sizeof(struct eppoll_entry))
+
struct epoll_filefd {
struct file *file;
int fd;
@@ -200,6 +202,9 @@ struct eventpoll {
* holding ->lock.
*/
struct epitem *ovflist;
+
+ /* The user that created the eventpoll descriptor */
+ struct user_struct *user;
};
/* Wait structure used by the poll hooks */
@@ -227,9 +232,17 @@ struct ep_pqueue {
};
/*
+ * Configuration options available inside /proc/sys/fs/epoll/
+ */
+/* Maximum number of epoll devices, per user */
+static int max_user_instances __read_mostly;
+/* Maximum number of epoll watched descriptors, per user */
+static int max_user_watches __read_mostly;
+
+/*
* This mutex is used to serialize ep_free() and eventpoll_release_file().
*/
-static struct mutex epmutex;
+static DEFINE_MUTEX(epmutex);
/* Safe wake up implementation */
static struct poll_safewake psw;
@@ -240,6 +253,33 @@ static struct kmem_cache *epi_cache __read_mostly;
/* Slab cache used to allocate "struct eppoll_entry" */
static struct kmem_cache *pwq_cache __read_mostly;
+#ifdef CONFIG_SYSCTL
+
+#include <linux/sysctl.h>
+
+static int zero;
+
+ctl_table epoll_table[] = {
+ {
+ .procname = "max_user_instances",
+ .data = &max_user_instances,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_minmax,
+ .extra1 = &zero,
+ },
+ {
+ .procname = "max_user_watches",
+ .data = &max_user_watches,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_minmax,
+ .extra1 = &zero,
+ },
+ { .ctl_name = 0 }
+};
+#endif /* CONFIG_SYSCTL */
+
/* Setup the structure that is used as key for the RB tree */
static inline void ep_set_ffd(struct epoll_filefd *ffd,
@@ -402,6 +442,8 @@ static int ep_remove(struct eventpoll *ep, struct epitem *epi)
/* At this point it is safe to free the eventpoll item */
kmem_cache_free(epi_cache, epi);
+ atomic_dec(&ep->user->epoll_watches);
+
DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_remove(%p, %p)\n",
current, ep, file));
@@ -449,6 +491,8 @@ static void ep_free(struct eventpoll *ep)
mutex_unlock(&epmutex);
mutex_destroy(&ep->mtx);
+ atomic_dec(&ep->user->epoll_devs);
+ free_uid(ep->user);
kfree(ep);
}
@@ -532,10 +576,19 @@ void eventpoll_release_file(struct file *file)
static int ep_alloc(struct eventpoll **pep)
{
- struct eventpoll *ep = kzalloc(sizeof(*ep), GFP_KERNEL);
+ int error;
+ struct user_struct *user;
+ struct eventpoll *ep;
- if (!ep)
- return -ENOMEM;
+ user = get_current_user();
+ error = -EMFILE;
+ if (unlikely(atomic_read(&user->epoll_devs) >=
+ max_user_instances))
+ goto free_uid;
+ error = -ENOMEM;
+ ep = kzalloc(sizeof(*ep), GFP_KERNEL);
+ if (unlikely(!ep))
+ goto free_uid;
spin_lock_init(&ep->lock);
mutex_init(&ep->mtx);
@@ -544,12 +597,17 @@ static int ep_alloc(struct eventpoll **pep)
INIT_LIST_HEAD(&ep->rdllist);
ep->rbr = RB_ROOT;
ep->ovflist = EP_UNACTIVE_PTR;
+ ep->user = user;
*pep = ep;
DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_alloc() ep=%p\n",
current, ep));
return 0;
+
+free_uid:
+ free_uid(user);
+ return error;
}
/*
@@ -703,9 +761,11 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
struct epitem *epi;
struct ep_pqueue epq;
- error = -ENOMEM;
+ if (unlikely(atomic_read(&ep->user->epoll_watches) >=
+ max_user_watches))
+ return -ENOSPC;
if (!(epi = kmem_cache_alloc(epi_cache, GFP_KERNEL)))
- goto error_return;
+ return -ENOMEM;
/* Item initialization follow here ... */
INIT_LIST_HEAD(&epi->rdllink);
@@ -735,6 +795,7 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
* install process. Namely an allocation for a wait queue failed due
* high memory pressure.
*/
+ error = -ENOMEM;
if (epi->nwait < 0)
goto error_unregister;
@@ -765,6 +826,8 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
spin_unlock_irqrestore(&ep->lock, flags);
+ atomic_inc(&ep->user->epoll_watches);
+
/* We have to call this outside the lock */
if (pwake)
ep_poll_safewake(&psw, &ep->poll_wait);
@@ -789,7 +852,7 @@ error_unregister:
spin_unlock_irqrestore(&ep->lock, flags);
kmem_cache_free(epi_cache, epi);
-error_return:
+
return error;
}
@@ -1078,6 +1141,7 @@ asmlinkage long sys_epoll_create1(int flags)
flags & O_CLOEXEC);
if (fd < 0)
ep_free(ep);
+ atomic_inc(&ep->user->epoll_devs);
error_return:
DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d) = %d\n",
@@ -1299,7 +1363,12 @@ asmlinkage long sys_epoll_pwait(int epfd, struct epoll_event __user *events,
static int __init eventpoll_init(void)
{
- mutex_init(&epmutex);
+ struct sysinfo si;
+
+ si_meminfo(&si);
+ max_user_instances = 128;
+ max_user_watches = (((si.totalram - si.totalhigh) / 32) << PAGE_SHIFT) /
+ EP_ITEM_COST;
/* Initialize the structure used to perform safe poll wait head wake ups */
ep_poll_safewake_init(&psw);
diff --git a/fs/exec.c b/fs/exec.c
index 4e834f16d9d..ec5df9a3831 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1159,6 +1159,7 @@ EXPORT_SYMBOL(remove_arg_zero);
*/
int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
{
+ unsigned int depth = bprm->recursion_depth;
int try,retval;
struct linux_binfmt *fmt;
#ifdef __alpha__
@@ -1219,8 +1220,15 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
continue;
read_unlock(&binfmt_lock);
retval = fn(bprm, regs);
+ /*
+ * Restore the depth counter to its starting value
+ * in this call, so we don't have to rely on every
+ * load_binary function to restore it on return.
+ */
+ bprm->recursion_depth = depth;
if (retval >= 0) {
- tracehook_report_exec(fmt, bprm, regs);
+ if (depth == 0)
+ tracehook_report_exec(fmt, bprm, regs);
put_binfmt(fmt);
allow_write_access(bprm->file);
if (bprm->file)
diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c
index 80246bad1b7..890e0182881 100644
--- a/fs/exportfs/expfs.c
+++ b/fs/exportfs/expfs.c
@@ -367,6 +367,8 @@ struct dentry *exportfs_decode_fh(struct vfsmount *mnt, struct fid *fid,
* Try to get any dentry for the given file handle from the filesystem.
*/
result = nop->fh_to_dentry(mnt->mnt_sb, fid, fh_len, fileid_type);
+ if (!result)
+ result = ERR_PTR(-ESTALE);
if (IS_ERR(result))
return result;
@@ -420,6 +422,8 @@ struct dentry *exportfs_decode_fh(struct vfsmount *mnt, struct fid *fid,
target_dir = nop->fh_to_parent(mnt->mnt_sb, fid,
fh_len, fileid_type);
+ if (!target_dir)
+ goto err_result;
err = PTR_ERR(target_dir);
if (IS_ERR(target_dir))
goto err_result;
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 5dec6d1356c..f6c94f232ec 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -2375,12 +2375,9 @@ int ext3_force_commit(struct super_block *sb)
/*
* Ext3 always journals updates to the superblock itself, so we don't
* have to propagate any other updates to the superblock on disk at this
- * point. Just start an async writeback to get the buffers on their way
- * to the disk.
- *
- * This implicitly triggers the writebehind on sync().
+ * point. (We can probably nuke this function altogether, and remove
+ * any mention to sb->s_dirt in all of fs/ext3; eventual cleanup...)
*/
-
static void ext3_write_super (struct super_block * sb)
{
if (mutex_trylock(&sb->s_lock) != 0)
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index d2003cdc36a..db35cfdb3c8 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -609,8 +609,8 @@ int ext4_has_free_blocks(struct ext4_sb_info *sbi, s64 nblocks)
if (free_blocks - (nblocks + root_blocks + dirty_blocks) <
EXT4_FREEBLOCKS_WATERMARK) {
- free_blocks = percpu_counter_sum(fbc);
- dirty_blocks = percpu_counter_sum(dbc);
+ free_blocks = percpu_counter_sum_positive(fbc);
+ dirty_blocks = percpu_counter_sum_positive(dbc);
if (dirty_blocks < 0) {
printk(KERN_CRIT "Dirty block accounting "
"went wrong %lld\n",
diff --git a/fs/fcntl.c b/fs/fcntl.c
index ac4f7db9f13..549daf8005f 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -19,6 +19,7 @@
#include <linux/signal.h>
#include <linux/rcupdate.h>
#include <linux/pid_namespace.h>
+#include <linux/smp_lock.h>
#include <asm/poll.h>
#include <asm/siginfo.h>
@@ -175,6 +176,11 @@ static int setfl(int fd, struct file * filp, unsigned long arg)
if (error)
return error;
+ /*
+ * We still need a lock here for now to keep multiple FASYNC calls
+ * from racing with each other.
+ */
+ lock_kernel();
if ((arg ^ filp->f_flags) & FASYNC) {
if (filp->f_op && filp->f_op->fasync) {
error = filp->f_op->fasync(fd, filp, (arg & FASYNC) != 0);
@@ -185,6 +191,7 @@ static int setfl(int fd, struct file * filp, unsigned long arg)
filp->f_flags = (arg & SETFL_MASK) | (filp->f_flags & ~SETFL_MASK);
out:
+ unlock_kernel();
return error;
}
diff --git a/fs/hostfs/hostfs.h b/fs/hostfs/hostfs.h
index 6ae9011b95e..2f34f8f2134 100644
--- a/fs/hostfs/hostfs.h
+++ b/fs/hostfs/hostfs.h
@@ -81,7 +81,7 @@ extern int do_rmdir(const char *file);
extern int do_mknod(const char *file, int mode, unsigned int major,
unsigned int minor);
extern int link_file(const char *from, const char *to);
-extern int do_readlink(char *file, char *buf, int size);
+extern int hostfs_do_readlink(char *file, char *buf, int size);
extern int rename_file(char *from, char *to);
extern int do_statfs(char *root, long *bsize_out, long long *blocks_out,
long long *bfree_out, long long *bavail_out,
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index 7f34f4385de..3a31451ac17 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -168,7 +168,7 @@ static char *follow_link(char *link)
if (name == NULL)
goto out;
- n = do_readlink(link, name, len);
+ n = hostfs_do_readlink(link, name, len);
if (n < len)
break;
len *= 2;
@@ -943,7 +943,7 @@ int hostfs_link_readpage(struct file *file, struct page *page)
name = inode_name(page->mapping->host, 0);
if (name == NULL)
return -ENOMEM;
- err = do_readlink(name, buffer, PAGE_CACHE_SIZE);
+ err = hostfs_do_readlink(name, buffer, PAGE_CACHE_SIZE);
kfree(name);
if (err == PAGE_CACHE_SIZE)
err = -E2BIG;
diff --git a/fs/hostfs/hostfs_user.c b/fs/hostfs/hostfs_user.c
index 53fd0a67c11..b79424f9328 100644
--- a/fs/hostfs/hostfs_user.c
+++ b/fs/hostfs/hostfs_user.c
@@ -377,7 +377,7 @@ int link_file(const char *to, const char *from)
return 0;
}
-int do_readlink(char *file, char *buf, int size)
+int hostfs_do_readlink(char *file, char *buf, int size)
{
int n;
diff --git a/fs/inotify.c b/fs/inotify.c
index 690e72595e6..dae3f28f30d 100644
--- a/fs/inotify.c
+++ b/fs/inotify.c
@@ -106,6 +106,20 @@ void get_inotify_watch(struct inotify_watch *watch)
}
EXPORT_SYMBOL_GPL(get_inotify_watch);
+int pin_inotify_watch(struct inotify_watch *watch)
+{
+ struct super_block *sb = watch->inode->i_sb;
+ spin_lock(&sb_lock);
+ if (sb->s_count >= S_BIAS) {
+ atomic_inc(&sb->s_active);
+ spin_unlock(&sb_lock);
+ atomic_inc(&watch->count);
+ return 1;
+ }
+ spin_unlock(&sb_lock);
+ return 0;
+}
+
/**
* put_inotify_watch - decrements the ref count on a given watch. cleans up
* watch references if the count reaches zero. inotify_watch is freed by
@@ -124,6 +138,13 @@ void put_inotify_watch(struct inotify_watch *watch)
}
EXPORT_SYMBOL_GPL(put_inotify_watch);
+void unpin_inotify_watch(struct inotify_watch *watch)
+{
+ struct super_block *sb = watch->inode->i_sb;
+ put_inotify_watch(watch);
+ deactivate_super(sb);
+}
+
/*
* inotify_handle_get_wd - returns the next WD for use by the given handle
*
@@ -407,11 +428,13 @@ void inotify_unmount_inodes(struct list_head *list)
watches = &inode->inotify_watches;
list_for_each_entry_safe(watch, next_w, watches, i_list) {
struct inotify_handle *ih= watch->ih;
+ get_inotify_watch(watch);
mutex_lock(&ih->mutex);
ih->in_ops->handle_event(watch, watch->wd, IN_UNMOUNT, 0,
NULL, NULL);
inotify_remove_watch_locked(ih, watch);
mutex_unlock(&ih->mutex);
+ put_inotify_watch(watch);
}
mutex_unlock(&inode->inotify_mutex);
iput(inode);
@@ -479,6 +502,112 @@ void inotify_init_watch(struct inotify_watch *watch)
}
EXPORT_SYMBOL_GPL(inotify_init_watch);
+/*
+ * Watch removals suck violently. To kick the watch out we need (in this
+ * order) inode->inotify_mutex and ih->mutex. That's fine if we have
+ * a hold on inode; however, for all other cases we need to make damn sure
+ * we don't race with umount. We can *NOT* just grab a reference to a
+ * watch - inotify_unmount_inodes() will happily sail past it and we'll end
+ * with reference to inode potentially outliving its superblock. Ideally
+ * we just want to grab an active reference to superblock if we can; that
+ * will make sure we won't go into inotify_umount_inodes() until we are
+ * done. Cleanup is just deactivate_super(). However, that leaves a messy
+ * case - what if we *are* racing with umount() and active references to
+ * superblock can't be acquired anymore? We can bump ->s_count, grab
+ * ->s_umount, which will almost certainly wait until the superblock is shut
+ * down and the watch in question is pining for fjords. That's fine, but
+ * there is a problem - we might have hit the window between ->s_active
+ * getting to 0 / ->s_count - below S_BIAS (i.e. the moment when superblock
+ * is past the point of no return and is heading for shutdown) and the
+ * moment when deactivate_super() acquires ->s_umount. We could just do
+ * drop_super() yield() and retry, but that's rather antisocial and this
+ * stuff is luser-triggerable. OTOH, having grabbed ->s_umount and having
+ * found that we'd got there first (i.e. that ->s_root is non-NULL) we know
+ * that we won't race with inotify_umount_inodes(). So we could grab a
+ * reference to watch and do the rest as above, just with drop_super() instead
+ * of deactivate_super(), right? Wrong. We had to drop ih->mutex before we
+ * could grab ->s_umount. So the watch could've been gone already.
+ *
+ * That still can be dealt with - we need to save watch->wd, do idr_find()
+ * and compare its result with our pointer. If they match, we either have
+ * the damn thing still alive or we'd lost not one but two races at once,
+ * the watch had been killed and a new one got created with the same ->wd
+ * at the same address. That couldn't have happened in inotify_destroy(),
+ * but inotify_rm_wd() could run into that. Still, "new one got created"
+ * is not a problem - we have every right to kill it or leave it alone,
+ * whatever's more convenient.
+ *
+ * So we can use idr_find(...) == watch && watch->inode->i_sb == sb as
+ * "grab it and kill it" check. If it's been our original watch, we are
+ * fine, if it's a newcomer - nevermind, just pretend that we'd won the
+ * race and kill the fscker anyway; we are safe since we know that its
+ * superblock won't be going away.
+ *
+ * And yes, this is far beyond mere "not very pretty"; so's the entire
+ * concept of inotify to start with.
+ */
+
+/**
+ * pin_to_kill - pin the watch down for removal
+ * @ih: inotify handle
+ * @watch: watch to kill
+ *
+ * Called with ih->mutex held, drops it. Possible return values:
+ * 0 - nothing to do, it has died
+ * 1 - remove it, drop the reference and deactivate_super()
+ * 2 - remove it, drop the reference and drop_super(); we tried hard to avoid
+ * that variant, since it involved a lot of PITA, but that's the best that
+ * could've been done.
+ */
+static int pin_to_kill(struct inotify_handle *ih, struct inotify_watch *watch)
+{
+ struct super_block *sb = watch->inode->i_sb;
+ s32 wd = watch->wd;
+
+ spin_lock(&sb_lock);
+ if (sb->s_count >= S_BIAS) {
+ atomic_inc(&sb->s_active);
+ spin_unlock(&sb_lock);
+ get_inotify_watch(watch);
+ mutex_unlock(&ih->mutex);
+ return 1; /* the best outcome */
+ }
+ sb->s_count++;
+ spin_unlock(&sb_lock);
+ mutex_unlock(&ih->mutex); /* can't grab ->s_umount under it */
+ down_read(&sb->s_umount);
+ if (likely(!sb->s_root)) {
+ /* fs is already shut down; the watch is dead */
+ drop_super(sb);
+ return 0;
+ }
+ /* raced with the final deactivate_super() */
+ mutex_lock(&ih->mutex);
+ if (idr_find(&ih->idr, wd) != watch || watch->inode->i_sb != sb) {
+ /* the watch is dead */
+ mutex_unlock(&ih->mutex);
+ drop_super(sb);
+ return 0;
+ }
+ /* still alive or freed and reused with the same sb and wd; kill */
+ get_inotify_watch(watch);
+ mutex_unlock(&ih->mutex);
+ return 2;
+}
+
+static void unpin_and_kill(struct inotify_watch *watch, int how)
+{
+ struct super_block *sb = watch->inode->i_sb;
+ put_inotify_watch(watch);
+ switch (how) {
+ case 1:
+ deactivate_super(sb);
+ break;
+ case 2:
+ drop_super(sb);
+ }
+}
+
/**
* inotify_destroy - clean up and destroy an inotify instance
* @ih: inotify handle
@@ -490,11 +619,15 @@ void inotify_destroy(struct inotify_handle *ih)
* pretty. We cannot do a simple iteration over the list, because we
* do not know the inode until we iterate to the watch. But we need to
* hold inode->inotify_mutex before ih->mutex. The following works.
+ *
+ * AV: it had to become even uglier to start working ;-/
*/
while (1) {
struct inotify_watch *watch;
struct list_head *watches;
+ struct super_block *sb;
struct inode *inode;
+ int how;
mutex_lock(&ih->mutex);
watches = &ih->watches;
@@ -503,8 +636,10 @@ void inotify_destroy(struct inotify_handle *ih)
break;
}
watch = list_first_entry(watches, struct inotify_watch, h_list);
- get_inotify_watch(watch);
- mutex_unlock(&ih->mutex);
+ sb = watch->inode->i_sb;
+ how = pin_to_kill(ih, watch);
+ if (!how)
+ continue;
inode = watch->inode;
mutex_lock(&inode->inotify_mutex);
@@ -518,7 +653,7 @@ void inotify_destroy(struct inotify_handle *ih)
mutex_unlock(&ih->mutex);
mutex_unlock(&inode->inotify_mutex);
- put_inotify_watch(watch);
+ unpin_and_kill(watch, how);
}
/* free this handle: the put matching the get in inotify_init() */
@@ -719,7 +854,9 @@ void inotify_evict_watch(struct inotify_watch *watch)
int inotify_rm_wd(struct inotify_handle *ih, u32 wd)
{
struct inotify_watch *watch;
+ struct super_block *sb;
struct inode *inode;
+ int how;
mutex_lock(&ih->mutex);
watch = idr_find(&ih->idr, wd);
@@ -727,9 +864,12 @@ int inotify_rm_wd(struct inotify_handle *ih, u32 wd)
mutex_unlock(&ih->mutex);
return -EINVAL;
}
- get_inotify_watch(watch);
+ sb = watch->inode->i_sb;
+ how = pin_to_kill(ih, watch);
+ if (!how)
+ return 0;
+
inode = watch->inode;
- mutex_unlock(&ih->mutex);
mutex_lock(&inode->inotify_mutex);
mutex_lock(&ih->mutex);
@@ -740,7 +880,7 @@ int inotify_rm_wd(struct inotify_handle *ih, u32 wd)
mutex_unlock(&ih->mutex);
mutex_unlock(&inode->inotify_mutex);
- put_inotify_watch(watch);
+ unpin_and_kill(watch, how);
return 0;
}
diff --git a/fs/ioctl.c b/fs/ioctl.c
index d152856c371..43e8b2c0664 100644
--- a/fs/ioctl.c
+++ b/fs/ioctl.c
@@ -400,11 +400,9 @@ static int ioctl_fioasync(unsigned int fd, struct file *filp,
/* Did FASYNC state change ? */
if ((flag ^ filp->f_flags) & FASYNC) {
- if (filp->f_op && filp->f_op->fasync) {
- lock_kernel();
+ if (filp->f_op && filp->f_op->fasync)
error = filp->f_op->fasync(fd, filp, on);
- unlock_kernel();
- } else
+ else
error = -ENOTTY;
}
if (error)
@@ -440,11 +438,17 @@ int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd,
break;
case FIONBIO:
+ /* BKL needed to avoid races tweaking f_flags */
+ lock_kernel();
error = ioctl_fionbio(filp, argp);
+ unlock_kernel();
break;
case FIOASYNC:
+ /* BKL needed to avoid races tweaking f_flags */
+ lock_kernel();
error = ioctl_fioasync(fd, filp, argp);
+ unlock_kernel();
break;
case FIOQSIZE:
diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index 9fd8889097b..70fc63a1727 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -167,7 +167,8 @@ static struct nlm_host *nlm_lookup_host(struct nlm_lookup_host_info *ni)
continue;
if (host->h_server != ni->server)
continue;
- if (!nlm_cmp_addr(nlm_srcaddr(host), ni->src_sap))
+ if (ni->server &&
+ !nlm_cmp_addr(nlm_srcaddr(host), ni->src_sap))
continue;
/* Move to head of hash chain. */
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index c631a83931c..56b076736b5 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -181,6 +181,7 @@ lockd(void *vrqstp)
}
flush_signals(current);
cancel_delayed_work_sync(&grace_period_end);
+ locks_end_grace(&lockd_manager);
if (nlmsvc_ops)
nlmsvc_invalidate_all();
nlm_shutdown_hosts();
diff --git a/fs/namei.c b/fs/namei.c
index 09ce58e49e7..d34e0f9681c 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1378,7 +1378,7 @@ static int may_delete(struct inode *dir,struct dentry *victim,int isdir)
if (IS_APPEND(dir))
return -EPERM;
if (check_sticky(dir, victim->d_inode)||IS_APPEND(victim->d_inode)||
- IS_IMMUTABLE(victim->d_inode))
+ IS_IMMUTABLE(victim->d_inode) || IS_SWAPFILE(victim->d_inode))
return -EPERM;
if (isdir) {
if (!S_ISDIR(victim->d_inode->i_mode))
diff --git a/fs/namespace.c b/fs/namespace.c
index cce46702d33..65b3dc844c8 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1815,8 +1815,8 @@ static void shrink_submounts(struct vfsmount *mnt, struct list_head *umounts)
while (!list_empty(&graveyard)) {
m = list_first_entry(&graveyard, struct vfsmount,
mnt_expire);
- touch_mnt_namespace(mnt->mnt_ns);
- umount_tree(mnt, 1, umounts);
+ touch_mnt_namespace(m->mnt_ns);
+ umount_tree(m, 1, umounts);
}
}
}
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index bb93946ace2..b79ec930d9f 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -225,12 +225,12 @@ nfsd4_list_rec_dir(struct dentry *dir, recdir_func *f)
return 0;
nfs4_save_user(&uid, &gid);
+ INIT_LIST_HEAD(dentries);
filp = dentry_open(dget(dir), mntget(rec_dir.mnt), O_RDONLY);
status = PTR_ERR(filp);
if (IS_ERR(filp))
goto out;
- INIT_LIST_HEAD(dentries);
status = vfs_readdir(filp, nfsd4_build_dentrylist, &dla);
fput(filp);
while (!list_empty(dentries)) {
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index b0bebc552a1..1a052ac2bde 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -3261,6 +3261,7 @@ nfs4_state_shutdown(void)
{
cancel_rearming_delayed_workqueue(laundry_wq, &laundromat_work);
destroy_workqueue(laundry_wq);
+ locks_end_grace(&nfsd4_manager);
nfs4_lock_state();
nfs4_release_reclaim();
__nfs4_state_shutdown();
diff --git a/fs/ntfs/debug.h b/fs/ntfs/debug.h
index 5e6724c1afd..2142b1c68b6 100644
--- a/fs/ntfs/debug.h
+++ b/fs/ntfs/debug.h
@@ -30,7 +30,8 @@
extern int debug_msgs;
-#if 0 /* Fool kernel-doc since it doesn't do macros yet */
+extern void __ntfs_debug(const char *file, int line, const char *function,
+ const char *format, ...) __attribute__ ((format (printf, 4, 5)));
/**
* ntfs_debug - write a debug level message to syslog
* @f: a printf format string containing the message
@@ -39,11 +40,6 @@ extern int debug_msgs;
* ntfs_debug() writes a DEBUG level message to the syslog but only if the
* driver was compiled with -DDEBUG. Otherwise, the call turns into a NOP.
*/
-static void ntfs_debug(const char *f, ...);
-#endif
-
-extern void __ntfs_debug (const char *file, int line, const char *function,
- const char *format, ...) __attribute__ ((format (printf, 4, 5)));
#define ntfs_debug(f, a...) \
__ntfs_debug(__FILE__, __LINE__, __func__, f, ##a)
diff --git a/fs/ocfs2/buffer_head_io.c b/fs/ocfs2/buffer_head_io.c
index 7e947c67246..3a178ec48d7 100644
--- a/fs/ocfs2/buffer_head_io.c
+++ b/fs/ocfs2/buffer_head_io.c
@@ -112,7 +112,7 @@ int ocfs2_read_blocks_sync(struct ocfs2_super *osb, u64 block,
bh = bhs[i];
if (buffer_jbd(bh)) {
- mlog(ML_ERROR,
+ mlog(ML_BH_IO,
"trying to sync read a jbd "
"managed bh (blocknr = %llu), skipping\n",
(unsigned long long)bh->b_blocknr);
@@ -147,15 +147,10 @@ int ocfs2_read_blocks_sync(struct ocfs2_super *osb, u64 block,
for (i = nr; i > 0; i--) {
bh = bhs[i - 1];
- if (buffer_jbd(bh)) {
- mlog(ML_ERROR,
- "the journal got the buffer while it was "
- "locked for io! (blocknr = %llu)\n",
- (unsigned long long)bh->b_blocknr);
- BUG();
- }
+ /* No need to wait on the buffer if it's managed by JBD. */
+ if (!buffer_jbd(bh))
+ wait_on_buffer(bh);
- wait_on_buffer(bh);
if (!buffer_uptodate(bh)) {
/* Status won't be cleared from here on out,
* so we can safely record this and loop back
@@ -251,8 +246,6 @@ int ocfs2_read_blocks(struct inode *inode, u64 block, int nr,
ignore_cache = 1;
}
- /* XXX: Can we ever get this and *not* have the cached
- * flag set? */
if (buffer_jbd(bh)) {
if (ignore_cache)
mlog(ML_BH_IO, "trying to sync read a jbd "
diff --git a/fs/ocfs2/dlm/dlmfs.c b/fs/ocfs2/dlm/dlmfs.c
index 533a789c3ef..ba962d71b34 100644
--- a/fs/ocfs2/dlm/dlmfs.c
+++ b/fs/ocfs2/dlm/dlmfs.c
@@ -608,8 +608,10 @@ static int __init init_dlmfs_fs(void)
0, (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|
SLAB_MEM_SPREAD),
dlmfs_init_once);
- if (!dlmfs_inode_cache)
+ if (!dlmfs_inode_cache) {
+ status = -ENOMEM;
goto bail;
+ }
cleanup_inode = 1;
user_dlm_worker = create_singlethread_workqueue("user_dlm");
diff --git a/fs/ocfs2/dlm/userdlm.h b/fs/ocfs2/dlm/userdlm.h
index 39ec2773849..0c3cc03c61f 100644
--- a/fs/ocfs2/dlm/userdlm.h
+++ b/fs/ocfs2/dlm/userdlm.h
@@ -33,7 +33,7 @@
#include <linux/workqueue.h>
/* user_lock_res->l_flags flags. */
-#define USER_LOCK_ATTACHED (0x00000001) /* have we initialized
+#define USER_LOCK_ATTACHED (0x00000001) /* we have initialized
* the lvb */
#define USER_LOCK_BUSY (0x00000002) /* we are currently in
* dlm_lock */
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
index ec684426034..6e6cc0a2e5f 100644
--- a/fs/ocfs2/dlmglue.c
+++ b/fs/ocfs2/dlmglue.c
@@ -2841,9 +2841,8 @@ static void ocfs2_unlock_ast(void *opaque, int error)
lockres_clear_flags(lockres, OCFS2_LOCK_BUSY);
lockres->l_unlock_action = OCFS2_UNLOCK_INVALID;
- spin_unlock_irqrestore(&lockres->l_lock, flags);
-
wake_up(&lockres->l_event);
+ spin_unlock_irqrestore(&lockres->l_lock, flags);
mlog_exit_void();
}
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h
index fef7ece3237..3fed9e3d899 100644
--- a/fs/ocfs2/ocfs2.h
+++ b/fs/ocfs2/ocfs2.h
@@ -85,7 +85,7 @@ enum ocfs2_unlock_action {
};
/* ocfs2_lock_res->l_flags flags. */
-#define OCFS2_LOCK_ATTACHED (0x00000001) /* have we initialized
+#define OCFS2_LOCK_ATTACHED (0x00000001) /* we have initialized
* the lvb */
#define OCFS2_LOCK_BUSY (0x00000002) /* we are currently in
* dlm_lock */
diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h
index 5f180cf7abb..5e0c0d0aef7 100644
--- a/fs/ocfs2/ocfs2_fs.h
+++ b/fs/ocfs2/ocfs2_fs.h
@@ -86,7 +86,8 @@
#define OCFS2_CLEAR_INCOMPAT_FEATURE(sb,mask) \
OCFS2_SB(sb)->s_feature_incompat &= ~(mask)
-#define OCFS2_FEATURE_COMPAT_SUPP OCFS2_FEATURE_COMPAT_BACKUP_SB
+#define OCFS2_FEATURE_COMPAT_SUPP (OCFS2_FEATURE_COMPAT_BACKUP_SB \
+ | OCFS2_FEATURE_COMPAT_JBD2_SB)
#define OCFS2_FEATURE_INCOMPAT_SUPP (OCFS2_FEATURE_INCOMPAT_LOCAL_MOUNT \
| OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC \
| OCFS2_FEATURE_INCOMPAT_INLINE_DATA \
@@ -153,6 +154,11 @@
#define OCFS2_FEATURE_COMPAT_BACKUP_SB 0x0001
/*
+ * The filesystem will correctly handle journal feature bits.
+ */
+#define OCFS2_FEATURE_COMPAT_JBD2_SB 0x0002
+
+/*
* Unwritten extents support.
*/
#define OCFS2_FEATURE_RO_COMPAT_UNWRITTEN 0x0001
diff --git a/fs/ocfs2/stack_user.c b/fs/ocfs2/stack_user.c
index faec2d87935..9b76d41a8ac 100644
--- a/fs/ocfs2/stack_user.c
+++ b/fs/ocfs2/stack_user.c
@@ -740,6 +740,9 @@ static int user_dlm_lock_status(union ocfs2_dlm_lksb *lksb)
static void *user_dlm_lvb(union ocfs2_dlm_lksb *lksb)
{
+ if (!lksb->lksb_fsdlm.sb_lvbptr)
+ lksb->lksb_fsdlm.sb_lvbptr = (char *)lksb +
+ sizeof(struct dlm_lksb);
return (void *)(lksb->lksb_fsdlm.sb_lvbptr);
}
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
index 054e2efb0b7..74d7367ade1 100644
--- a/fs/ocfs2/xattr.c
+++ b/fs/ocfs2/xattr.c
@@ -2645,9 +2645,9 @@ static int ocfs2_xattr_update_xattr_search(struct inode *inode,
return ret;
}
- i = xs->here - old_xh->xh_entries;
- xs->here = &xs->header->xh_entries[i];
}
+ i = xs->here - old_xh->xh_entries;
+ xs->here = &xs->header->xh_entries[i];
}
return ret;
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index 633f7a0ebb2..6d5b213b8a9 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -348,8 +348,8 @@ static ssize_t whole_disk_show(struct device *dev,
static DEVICE_ATTR(whole_disk, S_IRUSR | S_IRGRP | S_IROTH,
whole_disk_show, NULL);
-int add_partition(struct gendisk *disk, int partno,
- sector_t start, sector_t len, int flags)
+struct hd_struct *add_partition(struct gendisk *disk, int partno,
+ sector_t start, sector_t len, int flags)
{
struct hd_struct *p;
dev_t devt = MKDEV(0, 0);
@@ -361,15 +361,15 @@ int add_partition(struct gendisk *disk, int partno,
err = disk_expand_part_tbl(disk, partno);
if (err)
- return err;
+ return ERR_PTR(err);
ptbl = disk->part_tbl;
if (ptbl->part[partno])
- return -EBUSY;
+ return ERR_PTR(-EBUSY);
p = kzalloc(sizeof(*p), GFP_KERNEL);
if (!p)
- return -ENOMEM;
+ return ERR_PTR(-EBUSY);
if (!init_part_stats(p)) {
err = -ENOMEM;
@@ -395,7 +395,7 @@ int add_partition(struct gendisk *disk, int partno,
err = blk_alloc_devt(p, &devt);
if (err)
- goto out_free;
+ goto out_free_stats;
pdev->devt = devt;
/* delay uevent until 'holders' subdir is created */
@@ -424,18 +424,20 @@ int add_partition(struct gendisk *disk, int partno,
if (!ddev->uevent_suppress)
kobject_uevent(&pdev->kobj, KOBJ_ADD);
- return 0;
+ return p;
+out_free_stats:
+ free_part_stats(p);
out_free:
kfree(p);
- return err;
+ return ERR_PTR(err);
out_del:
kobject_put(p->holder_dir);
device_del(pdev);
out_put:
put_device(pdev);
blk_free_devt(devt);
- return err;
+ return ERR_PTR(err);
}
/* Not exported, helper to add_disk(). */
@@ -566,15 +568,16 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev)
disk->disk_name, p, (unsigned long long) size);
size = get_capacity(disk) - from;
}
- res = add_partition(disk, p, from, size, state->parts[p].flags);
- if (res) {
- printk(KERN_ERR " %s: p%d could not be added: %d\n",
- disk->disk_name, p, -res);
+ part = add_partition(disk, p, from, size,
+ state->parts[p].flags);
+ if (IS_ERR(part)) {
+ printk(KERN_ERR " %s: p%d could not be added: %ld\n",
+ disk->disk_name, p, -PTR_ERR(part));
continue;
}
#ifdef CONFIG_BLK_DEV_MD
if (state->parts[p].flags & ADDPART_FLAG_RAID)
- md_autodetect_dev(bdev->bd_dev+p);
+ md_autodetect_dev(part_to_dev(part)->devt);
#endif
}
kfree(state);
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 486cf3fe713..d4677603c88 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -371,7 +371,7 @@ static int lstats_show_proc(struct seq_file *m, void *v)
task->latency_record[i].time,
task->latency_record[i].max);
for (q = 0; q < LT_BACKTRACEDEPTH; q++) {
- char sym[KSYM_NAME_LEN];
+ char sym[KSYM_SYMBOL_LEN];
char *c;
if (!task->latency_record[i].backtrace[q])
break;
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index 94fcfff6863..06ed10b7da9 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -31,6 +31,7 @@ static struct inode *proc_sys_make_inode(struct super_block *sb,
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
inode->i_flags |= S_PRIVATE; /* tell selinux to ignore this inode */
inode->i_mode = table->mode;
+ inode->i_uid = inode->i_gid = 0;
if (!table->child) {
inode->i_mode |= S_IFREG;
inode->i_op = &proc_sys_inode_operations;
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index b770c095e45..3a8bdd7f575 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -557,9 +557,9 @@ static u64 swap_pte_to_pagemap_entry(pte_t pte)
return swp_type(e) | (swp_offset(e) << MAX_SWAPFILES_SHIFT);
}
-static unsigned long pte_to_pagemap_entry(pte_t pte)
+static u64 pte_to_pagemap_entry(pte_t pte)
{
- unsigned long pme = 0;
+ u64 pme = 0;
if (is_swap_pte(pte))
pme = PM_PFRAME(swap_pte_to_pagemap_entry(pte))
| PM_PSHIFT(PAGE_SHIFT) | PM_SWAP;
diff --git a/fs/ubifs/commit.c b/fs/ubifs/commit.c
index 0a6aa2cc78f..b49884c8c10 100644
--- a/fs/ubifs/commit.c
+++ b/fs/ubifs/commit.c
@@ -234,8 +234,8 @@ int ubifs_bg_thread(void *info)
int err;
struct ubifs_info *c = info;
- ubifs_msg("background thread \"%s\" started, PID %d",
- c->bgt_name, current->pid);
+ dbg_msg("background thread \"%s\" started, PID %d",
+ c->bgt_name, current->pid);
set_freezable();
while (1) {
diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c
index 7186400750e..510ffa0bbda 100644
--- a/fs/ubifs/debug.c
+++ b/fs/ubifs/debug.c
@@ -101,21 +101,24 @@ static void sprintf_key(const struct ubifs_info *c, const union ubifs_key *key,
if (c->key_fmt == UBIFS_SIMPLE_KEY_FMT) {
switch (type) {
case UBIFS_INO_KEY:
- sprintf(p, "(%lu, %s)", key_inum(c, key),
+ sprintf(p, "(%lu, %s)", (unsigned long)key_inum(c, key),
get_key_type(type));
break;
case UBIFS_DENT_KEY:
case UBIFS_XENT_KEY:
- sprintf(p, "(%lu, %s, %#08x)", key_inum(c, key),
+ sprintf(p, "(%lu, %s, %#08x)",
+ (unsigned long)key_inum(c, key),
get_key_type(type), key_hash(c, key));
break;
case UBIFS_DATA_KEY:
- sprintf(p, "(%lu, %s, %u)", key_inum(c, key),
+ sprintf(p, "(%lu, %s, %u)",
+ (unsigned long)key_inum(c, key),
get_key_type(type), key_block(c, key));
break;
case UBIFS_TRUN_KEY:
sprintf(p, "(%lu, %s)",
- key_inum(c, key), get_key_type(type));
+ (unsigned long)key_inum(c, key),
+ get_key_type(type));
break;
default:
sprintf(p, "(bad key type: %#08x, %#08x)",
@@ -364,8 +367,8 @@ void dbg_dump_node(const struct ubifs_info *c, const void *node)
le32_to_cpu(mst->ihead_lnum));
printk(KERN_DEBUG "\tihead_offs %u\n",
le32_to_cpu(mst->ihead_offs));
- printk(KERN_DEBUG "\tindex_size %u\n",
- le32_to_cpu(mst->index_size));
+ printk(KERN_DEBUG "\tindex_size %llu\n",
+ (unsigned long long)le64_to_cpu(mst->index_size));
printk(KERN_DEBUG "\tlpt_lnum %u\n",
le32_to_cpu(mst->lpt_lnum));
printk(KERN_DEBUG "\tlpt_offs %u\n",
@@ -1589,7 +1592,7 @@ static struct fsck_inode *add_inode(struct ubifs_info *c,
if (inum > c->highest_inum) {
ubifs_err("too high inode number, max. is %lu",
- c->highest_inum);
+ (unsigned long)c->highest_inum);
return ERR_PTR(-EINVAL);
}
@@ -1668,16 +1671,18 @@ static struct fsck_inode *read_add_inode(struct ubifs_info *c,
ino_key_init(c, &key, inum);
err = ubifs_lookup_level0(c, &key, &znode, &n);
if (!err) {
- ubifs_err("inode %lu not found in index", inum);
+ ubifs_err("inode %lu not found in index", (unsigned long)inum);
return ERR_PTR(-ENOENT);
} else if (err < 0) {
- ubifs_err("error %d while looking up inode %lu", err, inum);
+ ubifs_err("error %d while looking up inode %lu",
+ err, (unsigned long)inum);
return ERR_PTR(err);
}
zbr = &znode->zbranch[n];
if (zbr->len < UBIFS_INO_NODE_SZ) {
- ubifs_err("bad node %lu node length %d", inum, zbr->len);
+ ubifs_err("bad node %lu node length %d",
+ (unsigned long)inum, zbr->len);
return ERR_PTR(-EINVAL);
}
@@ -1697,7 +1702,7 @@ static struct fsck_inode *read_add_inode(struct ubifs_info *c,
kfree(ino);
if (IS_ERR(fscki)) {
ubifs_err("error %ld while adding inode %lu node",
- PTR_ERR(fscki), inum);
+ PTR_ERR(fscki), (unsigned long)inum);
return fscki;
}
@@ -1786,7 +1791,8 @@ static int check_leaf(struct ubifs_info *c, struct ubifs_zbranch *zbr,
if (IS_ERR(fscki)) {
err = PTR_ERR(fscki);
ubifs_err("error %d while processing data node and "
- "trying to find inode node %lu", err, inum);
+ "trying to find inode node %lu",
+ err, (unsigned long)inum);
goto out_dump;
}
@@ -1819,7 +1825,8 @@ static int check_leaf(struct ubifs_info *c, struct ubifs_zbranch *zbr,
if (IS_ERR(fscki)) {
err = PTR_ERR(fscki);
ubifs_err("error %d while processing entry node and "
- "trying to find inode node %lu", err, inum);
+ "trying to find inode node %lu",
+ err, (unsigned long)inum);
goto out_dump;
}
@@ -1832,7 +1839,7 @@ static int check_leaf(struct ubifs_info *c, struct ubifs_zbranch *zbr,
err = PTR_ERR(fscki);
ubifs_err("error %d while processing entry node and "
"trying to find parent inode node %lu",
- err, inum);
+ err, (unsigned long)inum);
goto out_dump;
}
@@ -1923,7 +1930,8 @@ static int check_inodes(struct ubifs_info *c, struct fsck_data *fsckd)
fscki->references != 1) {
ubifs_err("directory inode %lu has %d "
"direntries which refer it, but "
- "should be 1", fscki->inum,
+ "should be 1",
+ (unsigned long)fscki->inum,
fscki->references);
goto out_dump;
}
@@ -1931,27 +1939,29 @@ static int check_inodes(struct ubifs_info *c, struct fsck_data *fsckd)
fscki->references != 0) {
ubifs_err("root inode %lu has non-zero (%d) "
"direntries which refer it",
- fscki->inum, fscki->references);
+ (unsigned long)fscki->inum,
+ fscki->references);
goto out_dump;
}
if (fscki->calc_sz != fscki->size) {
ubifs_err("directory inode %lu size is %lld, "
"but calculated size is %lld",
- fscki->inum, fscki->size,
- fscki->calc_sz);
+ (unsigned long)fscki->inum,
+ fscki->size, fscki->calc_sz);
goto out_dump;
}
if (fscki->calc_cnt != fscki->nlink) {
ubifs_err("directory inode %lu nlink is %d, "
"but calculated nlink is %d",
- fscki->inum, fscki->nlink,
- fscki->calc_cnt);
+ (unsigned long)fscki->inum,
+ fscki->nlink, fscki->calc_cnt);
goto out_dump;
}
} else {
if (fscki->references != fscki->nlink) {
ubifs_err("inode %lu nlink is %d, but "
- "calculated nlink is %d", fscki->inum,
+ "calculated nlink is %d",
+ (unsigned long)fscki->inum,
fscki->nlink, fscki->references);
goto out_dump;
}
@@ -1959,20 +1969,21 @@ static int check_inodes(struct ubifs_info *c, struct fsck_data *fsckd)
if (fscki->xattr_sz != fscki->calc_xsz) {
ubifs_err("inode %lu has xattr size %u, but "
"calculated size is %lld",
- fscki->inum, fscki->xattr_sz,
+ (unsigned long)fscki->inum, fscki->xattr_sz,
fscki->calc_xsz);
goto out_dump;
}
if (fscki->xattr_cnt != fscki->calc_xcnt) {
ubifs_err("inode %lu has %u xattrs, but "
- "calculated count is %lld", fscki->inum,
+ "calculated count is %lld",
+ (unsigned long)fscki->inum,
fscki->xattr_cnt, fscki->calc_xcnt);
goto out_dump;
}
if (fscki->xattr_nms != fscki->calc_xnms) {
ubifs_err("inode %lu has xattr names' size %u, but "
"calculated names' size is %lld",
- fscki->inum, fscki->xattr_nms,
+ (unsigned long)fscki->inum, fscki->xattr_nms,
fscki->calc_xnms);
goto out_dump;
}
@@ -1985,11 +1996,12 @@ out_dump:
ino_key_init(c, &key, fscki->inum);
err = ubifs_lookup_level0(c, &key, &znode, &n);
if (!err) {
- ubifs_err("inode %lu not found in index", fscki->inum);
+ ubifs_err("inode %lu not found in index",
+ (unsigned long)fscki->inum);
return -ENOENT;
} else if (err < 0) {
ubifs_err("error %d while looking up inode %lu",
- err, fscki->inum);
+ err, (unsigned long)fscki->inum);
return err;
}
@@ -2007,7 +2019,7 @@ out_dump:
}
ubifs_msg("dump of the inode %lu sitting in LEB %d:%d",
- fscki->inum, zbr->lnum, zbr->offs);
+ (unsigned long)fscki->inum, zbr->lnum, zbr->offs);
dbg_dump_node(c, ino);
kfree(ino);
return -EINVAL;
diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
index 526c01ec800..0422c98e179 100644
--- a/fs/ubifs/dir.c
+++ b/fs/ubifs/dir.c
@@ -161,7 +161,7 @@ struct inode *ubifs_new_inode(struct ubifs_info *c, const struct inode *dir,
return ERR_PTR(-EINVAL);
}
ubifs_warn("running out of inode numbers (current %lu, max %d)",
- c->highest_inum, INUM_WATERMARK);
+ (unsigned long)c->highest_inum, INUM_WATERMARK);
}
inode->i_ino = ++c->highest_inum;
@@ -428,7 +428,8 @@ static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir)
dbg_gen("feed '%s', ino %llu, new f_pos %#x",
dent->name, (unsigned long long)le64_to_cpu(dent->inum),
key_hash_flash(c, &dent->key));
- ubifs_assert(dent->ch.sqnum > ubifs_inode(dir)->creat_sqnum);
+ ubifs_assert(le64_to_cpu(dent->ch.sqnum) >
+ ubifs_inode(dir)->creat_sqnum);
nm.len = le16_to_cpu(dent->nlen);
over = filldir(dirent, dent->name, nm.len, file->f_pos,
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
index 51cf511d44d..2624411d975 100644
--- a/fs/ubifs/file.c
+++ b/fs/ubifs/file.c
@@ -72,7 +72,7 @@ static int read_block(struct inode *inode, void *addr, unsigned int block,
return err;
}
- ubifs_assert(dn->ch.sqnum > ubifs_inode(inode)->creat_sqnum);
+ ubifs_assert(le64_to_cpu(dn->ch.sqnum) > ubifs_inode(inode)->creat_sqnum);
len = le32_to_cpu(dn->size);
if (len <= 0 || len > UBIFS_BLOCK_SIZE)
@@ -626,7 +626,7 @@ static int populate_page(struct ubifs_info *c, struct page *page,
dn = bu->buf + (bu->zbranch[nn].offs - offs);
- ubifs_assert(dn->ch.sqnum >
+ ubifs_assert(le64_to_cpu(dn->ch.sqnum) >
ubifs_inode(inode)->creat_sqnum);
len = le32_to_cpu(dn->size);
@@ -691,32 +691,22 @@ out_err:
/**
* ubifs_do_bulk_read - do bulk-read.
* @c: UBIFS file-system description object
- * @page1: first page
+ * @bu: bulk-read information
+ * @page1: first page to read
*
* This function returns %1 if the bulk-read is done, otherwise %0 is returned.
*/
-static int ubifs_do_bulk_read(struct ubifs_info *c, struct page *page1)
+static int ubifs_do_bulk_read(struct ubifs_info *c, struct bu_info *bu,
+ struct page *page1)
{
pgoff_t offset = page1->index, end_index;
struct address_space *mapping = page1->mapping;
struct inode *inode = mapping->host;
struct ubifs_inode *ui = ubifs_inode(inode);
- struct bu_info *bu;
int err, page_idx, page_cnt, ret = 0, n = 0;
+ int allocate = bu->buf ? 0 : 1;
loff_t isize;
- bu = kmalloc(sizeof(struct bu_info), GFP_NOFS);
- if (!bu)
- return 0;
-
- bu->buf_len = c->bulk_read_buf_size;
- bu->buf = kmalloc(bu->buf_len, GFP_NOFS);
- if (!bu->buf)
- goto out_free;
-
- data_key_init(c, &bu->key, inode->i_ino,
- offset << UBIFS_BLOCKS_PER_PAGE_SHIFT);
-
err = ubifs_tnc_get_bu_keys(c, bu);
if (err)
goto out_warn;
@@ -735,12 +725,25 @@ static int ubifs_do_bulk_read(struct ubifs_info *c, struct page *page1)
* together. If all the pages were like this, bulk-read would
* reduce performance, so we turn it off for a while.
*/
- ui->read_in_a_row = 0;
- ui->bulk_read = 0;
- goto out_free;
+ goto out_bu_off;
}
if (bu->cnt) {
+ if (allocate) {
+ /*
+ * Allocate bulk-read buffer depending on how many data
+ * nodes we are going to read.
+ */
+ bu->buf_len = bu->zbranch[bu->cnt - 1].offs +
+ bu->zbranch[bu->cnt - 1].len -
+ bu->zbranch[0].offs;
+ ubifs_assert(bu->buf_len > 0);
+ ubifs_assert(bu->buf_len <= c->leb_size);
+ bu->buf = kmalloc(bu->buf_len, GFP_NOFS | __GFP_NOWARN);
+ if (!bu->buf)
+ goto out_bu_off;
+ }
+
err = ubifs_tnc_bulk_read(c, bu);
if (err)
goto out_warn;
@@ -779,13 +782,17 @@ static int ubifs_do_bulk_read(struct ubifs_info *c, struct page *page1)
ui->last_page_read = offset + page_idx - 1;
out_free:
- kfree(bu->buf);
- kfree(bu);
+ if (allocate)
+ kfree(bu->buf);
return ret;
out_warn:
ubifs_warn("ignoring error %d and skipping bulk-read", err);
goto out_free;
+
+out_bu_off:
+ ui->read_in_a_row = ui->bulk_read = 0;
+ goto out_free;
}
/**
@@ -803,18 +810,20 @@ static int ubifs_bulk_read(struct page *page)
struct ubifs_info *c = inode->i_sb->s_fs_info;
struct ubifs_inode *ui = ubifs_inode(inode);
pgoff_t index = page->index, last_page_read = ui->last_page_read;
- int ret = 0;
+ struct bu_info *bu;
+ int err = 0, allocated = 0;
ui->last_page_read = index;
-
if (!c->bulk_read)
return 0;
+
/*
- * Bulk-read is protected by ui_mutex, but it is an optimization, so
- * don't bother if we cannot lock the mutex.
+ * Bulk-read is protected by @ui->ui_mutex, but it is an optimization,
+ * so don't bother if we cannot lock the mutex.
*/
if (!mutex_trylock(&ui->ui_mutex))
return 0;
+
if (index != last_page_read + 1) {
/* Turn off bulk-read if we stop reading sequentially */
ui->read_in_a_row = 1;
@@ -822,6 +831,7 @@ static int ubifs_bulk_read(struct page *page)
ui->bulk_read = 0;
goto out_unlock;
}
+
if (!ui->bulk_read) {
ui->read_in_a_row += 1;
if (ui->read_in_a_row < 3)
@@ -829,10 +839,35 @@ static int ubifs_bulk_read(struct page *page)
/* Three reads in a row, so switch on bulk-read */
ui->bulk_read = 1;
}
- ret = ubifs_do_bulk_read(c, page);
+
+ /*
+ * If possible, try to use pre-allocated bulk-read information, which
+ * is protected by @c->bu_mutex.
+ */
+ if (mutex_trylock(&c->bu_mutex))
+ bu = &c->bu;
+ else {
+ bu = kmalloc(sizeof(struct bu_info), GFP_NOFS | __GFP_NOWARN);
+ if (!bu)
+ goto out_unlock;
+
+ bu->buf = NULL;
+ allocated = 1;
+ }
+
+ bu->buf_len = c->max_bu_buf_len;
+ data_key_init(c, &bu->key, inode->i_ino,
+ page->index << UBIFS_BLOCKS_PER_PAGE_SHIFT);
+ err = ubifs_do_bulk_read(c, bu, page);
+
+ if (!allocated)
+ mutex_unlock(&c->bu_mutex);
+ else
+ kfree(bu);
+
out_unlock:
mutex_unlock(&ui->ui_mutex);
- return ret;
+ return err;
}
static int ubifs_readpage(struct file *file, struct page *page)
diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c
index 22993f867d1..f91b745908e 100644
--- a/fs/ubifs/journal.c
+++ b/fs/ubifs/journal.c
@@ -690,8 +690,9 @@ int ubifs_jnl_write_data(struct ubifs_info *c, const struct inode *inode,
int dlen = UBIFS_DATA_NODE_SZ + UBIFS_BLOCK_SIZE * WORST_COMPR_FACTOR;
struct ubifs_inode *ui = ubifs_inode(inode);
- dbg_jnl("ino %lu, blk %u, len %d, key %s", key_inum(c, key),
- key_block(c, key), len, DBGKEY(key));
+ dbg_jnl("ino %lu, blk %u, len %d, key %s",
+ (unsigned long)key_inum(c, key), key_block(c, key), len,
+ DBGKEY(key));
ubifs_assert(len <= UBIFS_BLOCK_SIZE);
data = kmalloc(dlen, GFP_NOFS);
@@ -1128,7 +1129,8 @@ int ubifs_jnl_truncate(struct ubifs_info *c, const struct inode *inode,
ino_t inum = inode->i_ino;
unsigned int blk;
- dbg_jnl("ino %lu, size %lld -> %lld", inum, old_size, new_size);
+ dbg_jnl("ino %lu, size %lld -> %lld",
+ (unsigned long)inum, old_size, new_size);
ubifs_assert(!ui->data_len);
ubifs_assert(S_ISREG(inode->i_mode));
ubifs_assert(mutex_is_locked(&ui->ui_mutex));
diff --git a/fs/ubifs/key.h b/fs/ubifs/key.h
index 9ee65086f62..3f1f16bc25c 100644
--- a/fs/ubifs/key.h
+++ b/fs/ubifs/key.h
@@ -345,7 +345,7 @@ static inline int key_type_flash(const struct ubifs_info *c, const void *k)
{
const union ubifs_key *key = k;
- return le32_to_cpu(key->u32[1]) >> UBIFS_S_KEY_BLOCK_BITS;
+ return le32_to_cpu(key->j32[1]) >> UBIFS_S_KEY_BLOCK_BITS;
}
/**
@@ -416,7 +416,7 @@ static inline unsigned int key_block_flash(const struct ubifs_info *c,
{
const union ubifs_key *key = k;
- return le32_to_cpu(key->u32[1]) & UBIFS_S_KEY_BLOCK_MASK;
+ return le32_to_cpu(key->j32[1]) & UBIFS_S_KEY_BLOCK_MASK;
}
/**
diff --git a/fs/ubifs/lpt_commit.c b/fs/ubifs/lpt_commit.c
index eed5a0025d6..a41434b4278 100644
--- a/fs/ubifs/lpt_commit.c
+++ b/fs/ubifs/lpt_commit.c
@@ -571,8 +571,6 @@ static struct ubifs_pnode *next_pnode(struct ubifs_info *c,
/* We assume here that LEB zero is never an LPT LEB */
if (nnode->nbranch[iip].lnum)
return ubifs_get_pnode(c, nnode, iip);
- else
- return NULL;
}
/* Go up while can't go right */
diff --git a/fs/ubifs/orphan.c b/fs/ubifs/orphan.c
index 02d3462f4d3..9bd5a43d452 100644
--- a/fs/ubifs/orphan.c
+++ b/fs/ubifs/orphan.c
@@ -105,7 +105,7 @@ int ubifs_add_orphan(struct ubifs_info *c, ino_t inum)
list_add_tail(&orphan->list, &c->orph_list);
list_add_tail(&orphan->new_list, &c->orph_new);
spin_unlock(&c->orphan_lock);
- dbg_gen("ino %lu", inum);
+ dbg_gen("ino %lu", (unsigned long)inum);
return 0;
}
@@ -132,14 +132,16 @@ void ubifs_delete_orphan(struct ubifs_info *c, ino_t inum)
else {
if (o->dnext) {
spin_unlock(&c->orphan_lock);
- dbg_gen("deleted twice ino %lu", inum);
+ dbg_gen("deleted twice ino %lu",
+ (unsigned long)inum);
return;
}
if (o->cnext) {
o->dnext = c->orph_dnext;
c->orph_dnext = o;
spin_unlock(&c->orphan_lock);
- dbg_gen("delete later ino %lu", inum);
+ dbg_gen("delete later ino %lu",
+ (unsigned long)inum);
return;
}
rb_erase(p, &c->orph_tree);
@@ -151,12 +153,12 @@ void ubifs_delete_orphan(struct ubifs_info *c, ino_t inum)
}
spin_unlock(&c->orphan_lock);
kfree(o);
- dbg_gen("inum %lu", inum);
+ dbg_gen("inum %lu", (unsigned long)inum);
return;
}
}
spin_unlock(&c->orphan_lock);
- dbg_err("missing orphan ino %lu", inum);
+ dbg_err("missing orphan ino %lu", (unsigned long)inum);
dbg_dump_stack();
}
@@ -448,7 +450,7 @@ static void erase_deleted(struct ubifs_info *c)
rb_erase(&orphan->rb, &c->orph_tree);
list_del(&orphan->list);
c->tot_orphans -= 1;
- dbg_gen("deleting orphan ino %lu", orphan->inum);
+ dbg_gen("deleting orphan ino %lu", (unsigned long)orphan->inum);
kfree(orphan);
}
c->orph_dnext = NULL;
@@ -536,8 +538,8 @@ static int insert_dead_orphan(struct ubifs_info *c, ino_t inum)
list_add_tail(&orphan->list, &c->orph_list);
orphan->dnext = c->orph_dnext;
c->orph_dnext = orphan;
- dbg_mnt("ino %lu, new %d, tot %d",
- inum, c->new_orphans, c->tot_orphans);
+ dbg_mnt("ino %lu, new %d, tot %d", (unsigned long)inum,
+ c->new_orphans, c->tot_orphans);
return 0;
}
@@ -609,7 +611,8 @@ static int do_kill_orphans(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
n = (le32_to_cpu(orph->ch.len) - UBIFS_ORPH_NODE_SZ) >> 3;
for (i = 0; i < n; i++) {
inum = le64_to_cpu(orph->inos[i]);
- dbg_rcvry("deleting orphaned inode %lu", inum);
+ dbg_rcvry("deleting orphaned inode %lu",
+ (unsigned long)inum);
err = ubifs_tnc_remove_ino(c, inum);
if (err)
return err;
@@ -840,8 +843,8 @@ static int dbg_orphan_check(struct ubifs_info *c, struct ubifs_zbranch *zbr,
if (inum != ci->last_ino) {
/* Lowest node type is the inode node, so it comes first */
if (key_type(c, &zbr->key) != UBIFS_INO_KEY)
- ubifs_err("found orphan node ino %lu, type %d", inum,
- key_type(c, &zbr->key));
+ ubifs_err("found orphan node ino %lu, type %d",
+ (unsigned long)inum, key_type(c, &zbr->key));
ci->last_ino = inum;
ci->tot_inos += 1;
err = ubifs_tnc_read_node(c, zbr, ci->node);
@@ -853,7 +856,8 @@ static int dbg_orphan_check(struct ubifs_info *c, struct ubifs_zbranch *zbr,
/* Must be recorded as an orphan */
if (!dbg_find_check_orphan(&ci->root, inum) &&
!dbg_find_orphan(c, inum)) {
- ubifs_err("missing orphan, ino %lu", inum);
+ ubifs_err("missing orphan, ino %lu",
+ (unsigned long)inum);
ci->missing += 1;
}
}
diff --git a/fs/ubifs/recovery.c b/fs/ubifs/recovery.c
index 77d26c141cf..90acac603e6 100644
--- a/fs/ubifs/recovery.c
+++ b/fs/ubifs/recovery.c
@@ -168,12 +168,12 @@ static int write_rcvrd_mst_node(struct ubifs_info *c,
struct ubifs_mst_node *mst)
{
int err = 0, lnum = UBIFS_MST_LNUM, sz = c->mst_node_alsz;
- uint32_t save_flags;
+ __le32 save_flags;
dbg_rcvry("recovery");
save_flags = mst->flags;
- mst->flags = cpu_to_le32(le32_to_cpu(mst->flags) | UBIFS_MST_RCVRY);
+ mst->flags |= cpu_to_le32(UBIFS_MST_RCVRY);
ubifs_prepare_node(c, mst, UBIFS_MST_NODE_SZ, 1);
err = ubi_leb_change(c->ubi, lnum, mst, sz, UBI_SHORTTERM);
@@ -1435,13 +1435,13 @@ static int fix_size_in_place(struct ubifs_info *c, struct size_entry *e)
err = ubi_leb_change(c->ubi, lnum, c->sbuf, len, UBI_UNKNOWN);
if (err)
goto out;
- dbg_rcvry("inode %lu at %d:%d size %lld -> %lld ", e->inum, lnum, offs,
- i_size, e->d_size);
+ dbg_rcvry("inode %lu at %d:%d size %lld -> %lld ",
+ (unsigned long)e->inum, lnum, offs, i_size, e->d_size);
return 0;
out:
ubifs_warn("inode %lu failed to fix size %lld -> %lld error %d",
- e->inum, e->i_size, e->d_size, err);
+ (unsigned long)e->inum, e->i_size, e->d_size, err);
return err;
}
@@ -1472,7 +1472,8 @@ int ubifs_recover_size(struct ubifs_info *c)
return err;
if (err == -ENOENT) {
/* Remove data nodes that have no inode */
- dbg_rcvry("removing ino %lu", e->inum);
+ dbg_rcvry("removing ino %lu",
+ (unsigned long)e->inum);
err = ubifs_tnc_remove_ino(c, e->inum);
if (err)
return err;
@@ -1493,8 +1494,8 @@ int ubifs_recover_size(struct ubifs_info *c)
return PTR_ERR(inode);
if (inode->i_size < e->d_size) {
dbg_rcvry("ino %lu size %lld -> %lld",
- e->inum, e->d_size,
- inode->i_size);
+ (unsigned long)e->inum,
+ e->d_size, inode->i_size);
inode->i_size = e->d_size;
ubifs_inode(inode)->ui_size = e->d_size;
e->inode = inode;
diff --git a/fs/ubifs/replay.c b/fs/ubifs/replay.c
index 7399692af85..21f7d047c30 100644
--- a/fs/ubifs/replay.c
+++ b/fs/ubifs/replay.c
@@ -1065,7 +1065,7 @@ int ubifs_replay_journal(struct ubifs_info *c)
ubifs_assert(c->bud_bytes <= c->max_bud_bytes || c->need_recovery);
dbg_mnt("finished, log head LEB %d:%d, max_sqnum %llu, "
"highest_inum %lu", c->lhead_lnum, c->lhead_offs, c->max_sqnum,
- c->highest_inum);
+ (unsigned long)c->highest_inum);
out:
destroy_replay_tree(c);
destroy_bud_list(c);
diff --git a/fs/ubifs/sb.c b/fs/ubifs/sb.c
index 2bf753b3888..0f392351dc5 100644
--- a/fs/ubifs/sb.c
+++ b/fs/ubifs/sb.c
@@ -81,6 +81,7 @@ static int create_default_filesystem(struct ubifs_info *c)
int lpt_lebs, lpt_first, orph_lebs, big_lpt, ino_waste, sup_flags = 0;
int min_leb_cnt = UBIFS_MIN_LEB_CNT;
uint64_t tmp64, main_bytes;
+ __le64 tmp_le64;
/* Some functions called from here depend on the @c->key_len filed */
c->key_len = UBIFS_SK_LEN;
@@ -295,10 +296,10 @@ static int create_default_filesystem(struct ubifs_info *c)
ino->ch.node_type = UBIFS_INO_NODE;
ino->creat_sqnum = cpu_to_le64(++c->max_sqnum);
ino->nlink = cpu_to_le32(2);
- tmp = cpu_to_le64(CURRENT_TIME_SEC.tv_sec);
- ino->atime_sec = tmp;
- ino->ctime_sec = tmp;
- ino->mtime_sec = tmp;
+ tmp_le64 = cpu_to_le64(CURRENT_TIME_SEC.tv_sec);
+ ino->atime_sec = tmp_le64;
+ ino->ctime_sec = tmp_le64;
+ ino->mtime_sec = tmp_le64;
ino->atime_nsec = 0;
ino->ctime_nsec = 0;
ino->mtime_nsec = 0;
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index 8780efbf40a..d80b2aef42b 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -36,6 +36,12 @@
#include <linux/mount.h>
#include "ubifs.h"
+/*
+ * Maximum amount of memory we may 'kmalloc()' without worrying that we are
+ * allocating too much.
+ */
+#define UBIFS_KMALLOC_OK (128*1024)
+
/* Slab cache for UBIFS inodes */
struct kmem_cache *ubifs_inode_slab;
@@ -561,18 +567,11 @@ static int init_constants_early(struct ubifs_info *c)
* calculations when reporting free space.
*/
c->leb_overhead = c->leb_size % UBIFS_MAX_DATA_NODE_SZ;
- /* Buffer size for bulk-reads */
- c->bulk_read_buf_size = UBIFS_MAX_BULK_READ * UBIFS_MAX_DATA_NODE_SZ;
- if (c->bulk_read_buf_size > c->leb_size)
- c->bulk_read_buf_size = c->leb_size;
- if (c->bulk_read_buf_size > 128 * 1024) {
- /* Check if we can kmalloc more than 128KiB */
- void *try = kmalloc(c->bulk_read_buf_size, GFP_KERNEL);
- kfree(try);
- if (!try)
- c->bulk_read_buf_size = 128 * 1024;
- }
+ /* Buffer size for bulk-reads */
+ c->max_bu_buf_len = UBIFS_MAX_BULK_READ * UBIFS_MAX_DATA_NODE_SZ;
+ if (c->max_bu_buf_len > c->leb_size)
+ c->max_bu_buf_len = c->leb_size;
return 0;
}
@@ -992,6 +991,34 @@ static void destroy_journal(struct ubifs_info *c)
}
/**
+ * bu_init - initialize bulk-read information.
+ * @c: UBIFS file-system description object
+ */
+static void bu_init(struct ubifs_info *c)
+{
+ ubifs_assert(c->bulk_read == 1);
+
+ if (c->bu.buf)
+ return; /* Already initialized */
+
+again:
+ c->bu.buf = kmalloc(c->max_bu_buf_len, GFP_KERNEL | __GFP_NOWARN);
+ if (!c->bu.buf) {
+ if (c->max_bu_buf_len > UBIFS_KMALLOC_OK) {
+ c->max_bu_buf_len = UBIFS_KMALLOC_OK;
+ goto again;
+ }
+
+ /* Just disable bulk-read */
+ ubifs_warn("Cannot allocate %d bytes of memory for bulk-read, "
+ "disabling it", c->max_bu_buf_len);
+ c->mount_opts.bulk_read = 1;
+ c->bulk_read = 0;
+ return;
+ }
+}
+
+/**
* mount_ubifs - mount UBIFS file-system.
* @c: UBIFS file-system description object
*
@@ -1059,6 +1086,13 @@ static int mount_ubifs(struct ubifs_info *c)
goto out_free;
}
+ if (c->bulk_read == 1)
+ bu_init(c);
+
+ /*
+ * We have to check all CRCs, even for data nodes, when we mount the FS
+ * (specifically, when we are replaying).
+ */
c->always_chk_crc = 1;
err = ubifs_read_superblock(c);
@@ -1289,6 +1323,7 @@ out_cbuf:
out_dereg:
dbg_failure_mode_deregistration(c);
out_free:
+ kfree(c->bu.buf);
vfree(c->ileb_buf);
vfree(c->sbuf);
kfree(c->bottom_up_buf);
@@ -1325,10 +1360,11 @@ static void ubifs_umount(struct ubifs_info *c)
kfree(c->cbuf);
kfree(c->rcvrd_mst_node);
kfree(c->mst_node);
+ kfree(c->bu.buf);
+ vfree(c->ileb_buf);
vfree(c->sbuf);
kfree(c->bottom_up_buf);
UBIFS_DBG(vfree(c->dbg_buf));
- vfree(c->ileb_buf);
dbg_failure_mode_deregistration(c);
}
@@ -1626,6 +1662,7 @@ static int ubifs_remount_fs(struct super_block *sb, int *flags, char *data)
ubifs_err("invalid or unknown remount parameter");
return err;
}
+
if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY)) {
err = ubifs_remount_rw(c);
if (err)
@@ -1633,6 +1670,14 @@ static int ubifs_remount_fs(struct super_block *sb, int *flags, char *data)
} else if (!(sb->s_flags & MS_RDONLY) && (*flags & MS_RDONLY))
ubifs_remount_ro(c);
+ if (c->bulk_read == 1)
+ bu_init(c);
+ else {
+ dbg_gen("disable bulk-read");
+ kfree(c->bu.buf);
+ c->bu.buf = NULL;
+ }
+
return 0;
}
@@ -1723,6 +1768,7 @@ static int ubifs_fill_super(struct super_block *sb, void *data, int silent)
mutex_init(&c->log_mutex);
mutex_init(&c->mst_mutex);
mutex_init(&c->umount_mutex);
+ mutex_init(&c->bu_mutex);
init_waitqueue_head(&c->cmt_wq);
c->buds = RB_ROOT;
c->old_idx = RB_ROOT;
diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c
index d27fd918b9c..6eef5344a14 100644
--- a/fs/ubifs/tnc.c
+++ b/fs/ubifs/tnc.c
@@ -1501,7 +1501,12 @@ out:
* @bu: bulk-read parameters and results
*
* Lookup consecutive data node keys for the same inode that reside
- * consecutively in the same LEB.
+ * consecutively in the same LEB. This function returns zero in case of success
+ * and a negative error code in case of failure.
+ *
+ * Note, if the bulk-read buffer length (@bu->buf_len) is known, this function
+ * makes sure bulk-read nodes fit the buffer. Otherwise, this function prepares
+ * maxumum possible amount of nodes for bulk-read.
*/
int ubifs_tnc_get_bu_keys(struct ubifs_info *c, struct bu_info *bu)
{
@@ -2677,7 +2682,7 @@ int ubifs_tnc_remove_ino(struct ubifs_info *c, ino_t inum)
struct ubifs_dent_node *xent, *pxent = NULL;
struct qstr nm = { .name = NULL };
- dbg_tnc("ino %lu", inum);
+ dbg_tnc("ino %lu", (unsigned long)inum);
/*
* Walk all extended attribute entries and remove them together with
@@ -2697,7 +2702,8 @@ int ubifs_tnc_remove_ino(struct ubifs_info *c, ino_t inum)
}
xattr_inum = le64_to_cpu(xent->inum);
- dbg_tnc("xent '%s', ino %lu", xent->name, xattr_inum);
+ dbg_tnc("xent '%s', ino %lu", xent->name,
+ (unsigned long)xattr_inum);
nm.name = xent->name;
nm.len = le16_to_cpu(xent->nlen);
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index a7bd32fa15b..46b172560a0 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -753,7 +753,7 @@ struct ubifs_znode {
};
/**
- * struct bu_info - bulk-read information
+ * struct bu_info - bulk-read information.
* @key: first data node key
* @zbranch: zbranches of data nodes to bulk read
* @buf: buffer to read into
@@ -969,7 +969,10 @@ struct ubifs_mount_opts {
* @mst_node: master node
* @mst_offs: offset of valid master node
* @mst_mutex: protects the master node area, @mst_node, and @mst_offs
- * @bulk_read_buf_size: buffer size for bulk-reads
+ *
+ * @max_bu_buf_len: maximum bulk-read buffer length
+ * @bu_mutex: protects the pre-allocated bulk-read buffer and @c->bu
+ * @bu: pre-allocated bulk-read information
*
* @log_lebs: number of logical eraseblocks in the log
* @log_bytes: log size in bytes
@@ -1217,7 +1220,10 @@ struct ubifs_info {
struct ubifs_mst_node *mst_node;
int mst_offs;
struct mutex mst_mutex;
- int bulk_read_buf_size;
+
+ int max_bu_buf_len;
+ struct mutex bu_mutex;
+ struct bu_info bu;
int log_lebs;
long long log_bytes;
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index 6e74b117aaf..30ebde490f7 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -106,6 +106,7 @@ void udf_clear_inode(struct inode *inode)
udf_truncate_tail_extent(inode);
unlock_kernel();
write_inode_now(inode, 0);
+ invalidate_inode_buffers(inode);
}
iinfo = UDF_I(inode);
kfree(iinfo->i_ext.i_data);
diff --git a/fs/xfs/xfs_rename.c b/fs/xfs/xfs_rename.c
index d700dacdb10..c903130be7f 100644
--- a/fs/xfs/xfs_rename.c
+++ b/fs/xfs/xfs_rename.c
@@ -212,7 +212,7 @@ xfs_rename(
if (unlikely((target_dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) &&
(target_dp->i_d.di_projid != src_ip->i_d.di_projid))) {
error = XFS_ERROR(EXDEV);
- xfs_rename_unlock4(inodes, XFS_ILOCK_SHARED);
+ xfs_rename_unlock4(inodes, XFS_ILOCK_EXCL);
xfs_trans_cancel(tp, cancel_flags);
goto std_return;
}
diff --git a/include/acpi/acoutput.h b/include/acpi/acoutput.h
index 09d33c7740f..db8852d8bcf 100644
--- a/include/acpi/acoutput.h
+++ b/include/acpi/acoutput.h
@@ -172,7 +172,7 @@
/* Defaults for debug_level, debug and normal */
-#define ACPI_DEBUG_DEFAULT (ACPI_LV_INIT | ACPI_LV_DEBUG_OBJECT)
+#define ACPI_DEBUG_DEFAULT (ACPI_LV_INFO)
#define ACPI_NORMAL_DEFAULT (ACPI_LV_INIT | ACPI_LV_DEBUG_OBJECT)
#define ACPI_DEBUG_ALL (ACPI_LV_AML_DISASSEMBLE | ACPI_LV_ALL_EXCEPTIONS | ACPI_LV_ALL)
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index 54a279e44c9..e9f6574930e 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -380,6 +380,8 @@ struct acpi_bus_type {
int register_acpi_bus_type(struct acpi_bus_type *);
int unregister_acpi_bus_type(struct acpi_bus_type *);
struct device *acpi_get_physical_device(acpi_handle);
+struct device *acpi_get_physical_pci_device(acpi_handle);
+
/* helper */
acpi_handle acpi_get_child(acpi_handle, acpi_integer);
acpi_handle acpi_get_pci_rootbridge_handle(unsigned int, unsigned int);
diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h
index cf04c6011c2..5fc1bb0f4a9 100644
--- a/include/acpi/acpi_drivers.h
+++ b/include/acpi/acpi_drivers.h
@@ -31,8 +31,24 @@
#define ACPI_MAX_STRING 80
+/*
+ * Please update drivers/acpi/debug.c and Documentation/acpi/debug.txt
+ * if you add to this list.
+ */
#define ACPI_BUS_COMPONENT 0x00010000
+#define ACPI_AC_COMPONENT 0x00020000
+#define ACPI_BATTERY_COMPONENT 0x00040000
+#define ACPI_BUTTON_COMPONENT 0x00080000
+#define ACPI_SBS_COMPONENT 0x00100000
+#define ACPI_FAN_COMPONENT 0x00200000
+#define ACPI_PCI_COMPONENT 0x00400000
+#define ACPI_POWER_COMPONENT 0x00800000
+#define ACPI_CONTAINER_COMPONENT 0x01000000
#define ACPI_SYSTEM_COMPONENT 0x02000000
+#define ACPI_THERMAL_COMPONENT 0x04000000
+#define ACPI_MEMORY_DEVICE_COMPONENT 0x08000000
+#define ACPI_VIDEO_COMPONENT 0x10000000
+#define ACPI_PROCESSOR_COMPONENT 0x20000000
/*
* _HID definitions
@@ -41,6 +57,7 @@
*/
#define ACPI_POWER_HID "LNXPOWER"
+#define ACPI_PROCESSOR_OBJECT_HID "ACPI_CPU"
#define ACPI_PROCESSOR_HID "ACPI0007"
#define ACPI_SYSTEM_HID "LNXSYSTM"
#define ACPI_THERMAL_HID "LNXTHERM"
@@ -54,7 +71,6 @@
PCI
-------------------------------------------------------------------------- */
-#define ACPI_PCI_COMPONENT 0x00400000
/* ACPI PCI Interrupt Link (pci_link.c) */
@@ -86,7 +102,6 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_device *device, int domain,
Power Resource
-------------------------------------------------------------------------- */
-#ifdef CONFIG_ACPI_POWER
int acpi_device_sleep_wake(struct acpi_device *dev,
int enable, int sleep_state, int dev_state);
int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state);
@@ -94,15 +109,12 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev);
int acpi_power_get_inferred_state(struct acpi_device *device);
int acpi_power_transition(struct acpi_device *device, int state);
extern int acpi_power_nocheck;
-#endif
/* --------------------------------------------------------------------------
Embedded Controller
-------------------------------------------------------------------------- */
-#ifdef CONFIG_ACPI_EC
int acpi_ec_ecdt_probe(void);
int acpi_boot_ec_enable(void);
-#endif
/* --------------------------------------------------------------------------
Processor
diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h
index 94d94e126e9..33bc0e3b195 100644
--- a/include/acpi/acpixf.h
+++ b/include/acpi/acpixf.h
@@ -252,9 +252,9 @@ acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status);
acpi_status acpi_set_gpe_type(acpi_handle gpe_device, u32 gpe_number, u8 type);
-acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags);
+acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number);
-acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags);
+acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number);
acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags);
diff --git a/include/acpi/acpredef.h b/include/acpi/acpredef.h
index 619fb75f886..16a9ca9a66e 100644
--- a/include/acpi/acpredef.h
+++ b/include/acpi/acpredef.h
@@ -167,7 +167,7 @@ static const union acpi_predefined_info predefined_names[] = {
{.info = {"_BFS", 1, 0}},
{.info = {"_BIF", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER,
9,
- ACPI_RTYPE_STRING, 4, 0}}, /* fixed (9 Int),(4 Str) */
+ ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER, 4, 0}}, /* fixed (9 Int),(4 Str) */
{.info = {"_BLT", 3, 0}},
{.info = {"_BMC", 1, 0}},
{.info = {"_BMD", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 5, 0, 0, 0}}, /* fixed (5 Int) */
@@ -346,7 +346,7 @@ static const union acpi_predefined_info predefined_names[] = {
/* Acpi 1.0 defined _WAK with no return value. Later, it was changed to return a package */
- {.info = {"_WAK", 1, ACPI_RTYPE_NONE | ACPI_RTYPE_PACKAGE}},
+ {.info = {"_WAK", 1, ACPI_RTYPE_NONE | ACPI_RTYPE_INTEGER | ACPI_RTYPE_PACKAGE}},
{.ret_info = {ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 2, 0, 0, 0}}, /* fixed (2 Int), but is optional */
{.ret_info = {0, 0, 0, 0, 0, 0}} /* Table terminator */
};
diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h
index e8936ab5962..7220361790b 100644
--- a/include/acpi/actypes.h
+++ b/include/acpi/actypes.h
@@ -525,6 +525,7 @@ typedef u32 acpi_event_status;
#define ACPI_EVENT_FLAG_ENABLED (acpi_event_status) 0x01
#define ACPI_EVENT_FLAG_WAKE_ENABLED (acpi_event_status) 0x02
#define ACPI_EVENT_FLAG_SET (acpi_event_status) 0x04
+#define ACPI_EVENT_FLAG_HANDLE (acpi_event_status) 0x08
/*
* General Purpose Events (GPE)
diff --git a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h
index 029c8c06c15..0515e754449 100644
--- a/include/acpi/platform/aclinux.h
+++ b/include/acpi/platform/aclinux.h
@@ -141,6 +141,10 @@ static inline void *acpi_os_acquire_object(acpi_cache_t * cache)
/*
* We need to show where it is safe to preempt execution of ACPICA
*/
-#define ACPI_PREEMPTION_POINT() cond_resched()
+#define ACPI_PREEMPTION_POINT() \
+ do { \
+ if (!irqs_disabled()) \
+ cond_resched(); \
+ } while (0)
#endif /* __ACLINUX_H__ */
diff --git a/include/asm-generic/atomic.h b/include/asm-generic/atomic.h
index 4ec0a296bde..7abdaa91ccd 100644
--- a/include/asm-generic/atomic.h
+++ b/include/asm-generic/atomic.h
@@ -251,7 +251,7 @@ static inline long atomic_long_add_unless(atomic_long_t *l, long a, long u)
#define atomic_long_cmpxchg(l, old, new) \
(atomic_cmpxchg((atomic_t *)(l), (old), (new)))
#define atomic_long_xchg(v, new) \
- (atomic_xchg((atomic_t *)(l), (new)))
+ (atomic_xchg((atomic_t *)(v), (new)))
#endif /* BITS_PER_LONG == 64 */
diff --git a/include/asm-generic/audit_write.h b/include/asm-generic/audit_write.h
index f10d367fb2a..c5f1c2c920e 100644
--- a/include/asm-generic/audit_write.h
+++ b/include/asm-generic/audit_write.h
@@ -1,6 +1,8 @@
#include <asm-generic/audit_dir_write.h>
__NR_acct,
+#ifdef __NR_swapon
__NR_swapon,
+#endif
__NR_quotactl,
__NR_truncate,
#ifdef __NR_truncate64
diff --git a/include/asm-mn10300/uaccess.h b/include/asm-mn10300/uaccess.h
index 46b9b647f3c..8a3a4dd5576 100644
--- a/include/asm-mn10300/uaccess.h
+++ b/include/asm-mn10300/uaccess.h
@@ -266,7 +266,7 @@ extern int __get_user_unknown(void);
" .section .fixup,\"ax\" \n" \
"4: \n" \
" mov %5,%0 \n" \
- " jmp 2b \n" \
+ " jmp 3b \n" \
" .previous \n" \
" .section __ex_table,\"a\"\n" \
" .balign 4 \n" \
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 28c7f1679d4..d5e8e5c8954 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -1151,6 +1151,7 @@ extern u32 drm_vblank_count(struct drm_device *dev, int crtc);
extern void drm_handle_vblank(struct drm_device *dev, int crtc);
extern int drm_vblank_get(struct drm_device *dev, int crtc);
extern void drm_vblank_put(struct drm_device *dev, int crtc);
+extern void drm_vblank_cleanup(struct drm_device *dev);
/* Modesetting support */
extern int drm_modeset_ctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index fd6a452b0ce..fba8051fb29 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -163,8 +163,6 @@ struct acpi_pci_driver {
int acpi_pci_register_driver(struct acpi_pci_driver *driver);
void acpi_pci_unregister_driver(struct acpi_pci_driver *driver);
-#ifdef CONFIG_ACPI_EC
-
extern int ec_read(u8 addr, u8 *val);
extern int ec_write(u8 addr, u8 val);
extern int ec_transaction(u8 command,
@@ -172,8 +170,6 @@ extern int ec_transaction(u8 command,
u8 *rdata, unsigned rdata_len,
int force_poll);
-#endif /*CONFIG_ACPI_EC*/
-
#if defined(CONFIG_ACPI_WMI) || defined(CONFIG_ACPI_WMI_MODULE)
typedef void (*wmi_notify_handler) (u32 value, void *context);
@@ -194,6 +190,50 @@ extern bool wmi_has_guid(const char *guid);
#endif /* CONFIG_ACPI_WMI */
+#define ACPI_VIDEO_OUTPUT_SWITCHING 0x0001
+#define ACPI_VIDEO_DEVICE_POSTING 0x0002
+#define ACPI_VIDEO_ROM_AVAILABLE 0x0004
+#define ACPI_VIDEO_BACKLIGHT 0x0008
+#define ACPI_VIDEO_BACKLIGHT_FORCE_VENDOR 0x0010
+#define ACPI_VIDEO_BACKLIGHT_FORCE_VIDEO 0x0020
+#define ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VENDOR 0x0040
+#define ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VIDEO 0x0080
+#define ACPI_VIDEO_BACKLIGHT_DMI_VENDOR 0x0100
+#define ACPI_VIDEO_BACKLIGHT_DMI_VIDEO 0x0200
+#define ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VENDOR 0x0400
+#define ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VIDEO 0x0800
+
+#if defined(CONFIG_ACPI_VIDEO) || defined(CONFIG_ACPI_VIDEO_MODULE)
+
+extern long acpi_video_get_capabilities(acpi_handle graphics_dev_handle);
+extern long acpi_is_video_device(struct acpi_device *device);
+extern int acpi_video_backlight_support(void);
+extern int acpi_video_display_switch_support(void);
+
+#else
+
+static inline long acpi_video_get_capabilities(acpi_handle graphics_dev_handle)
+{
+ return 0;
+}
+
+static inline long acpi_is_video_device(struct acpi_device *device)
+{
+ return 0;
+}
+
+static inline int acpi_video_backlight_support(void)
+{
+ return 0;
+}
+
+static inline int acpi_video_display_switch_support(void)
+{
+ return 0;
+}
+
+#endif /* defined(CONFIG_ACPI_VIDEO) || defined(CONFIG_ACPI_VIDEO_MODULE) */
+
extern int acpi_blacklisted(void);
#ifdef CONFIG_DMI
extern void acpi_dmi_osi_linux(int enable, const struct dmi_system_id *d);
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 6272a395d43..8f0672d13eb 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -391,6 +391,7 @@ extern int audit_classify_arch(int arch);
#ifdef CONFIG_AUDITSYSCALL
/* These are defined in auditsc.c */
/* Public API */
+extern void audit_finish_fork(struct task_struct *child);
extern int audit_alloc(struct task_struct *task);
extern void audit_free(struct task_struct *task);
extern void audit_syscall_entry(int arch,
@@ -434,7 +435,7 @@ static inline void audit_ptrace(struct task_struct *t)
/* Private API (for audit.c only) */
extern unsigned int audit_serial(void);
-extern void auditsc_get_stamp(struct audit_context *ctx,
+extern int auditsc_get_stamp(struct audit_context *ctx,
struct timespec *t, unsigned int *serial);
extern int audit_set_loginuid(struct task_struct *task, uid_t loginuid);
#define audit_get_loginuid(t) ((t)->loginuid)
@@ -504,6 +505,7 @@ static inline int audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat)
extern int audit_n_rules;
extern int audit_signals;
#else
+#define audit_finish_fork(t)
#define audit_alloc(t) ({ 0; })
#define audit_free(t) do { ; } while (0)
#define audit_syscall_entry(ta,a,b,c,d,e) do { ; } while (0)
@@ -516,7 +518,7 @@ extern int audit_signals;
#define audit_inode(n,d) do { ; } while (0)
#define audit_inode_child(d,i,p) do { ; } while (0)
#define audit_core_dumps(i) do { ; } while (0)
-#define auditsc_get_stamp(c,t,s) do { BUG(); } while (0)
+#define auditsc_get_stamp(c,t,s) (0)
#define audit_get_loginuid(t) (-1)
#define audit_get_sessionid(t) (-1)
#define audit_log_task_context(b) do { ; } while (0)
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index a135256b272..031a315c050 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -662,6 +662,7 @@ extern unsigned long blk_max_low_pfn, blk_max_pfn;
* default timeout for SG_IO if none specified
*/
#define BLK_DEFAULT_SG_TIMEOUT (60 * HZ)
+#define BLK_MIN_SG_TIMEOUT (7 * HZ)
#ifdef CONFIG_BOUNCE
extern int init_emergency_isa_pool(void);
@@ -786,6 +787,8 @@ static inline void blk_run_address_space(struct address_space *mapping)
blk_run_backing_dev(mapping->backing_dev_info, NULL);
}
+extern void blkdev_dequeue_request(struct request *req);
+
/*
* blk_end_request() and friends.
* __blk_end_request() and end_request() must be called with
@@ -820,11 +823,6 @@ extern void blk_update_request(struct request *rq, int error,
extern unsigned int blk_rq_bytes(struct request *rq);
extern unsigned int blk_rq_cur_bytes(struct request *rq);
-static inline void blkdev_dequeue_request(struct request *req)
-{
- elv_dequeue_request(req->q, req);
-}
-
/*
* Access functions for manipulating queue properties
*/
@@ -921,6 +919,8 @@ extern void blk_set_cmd_filter_defaults(struct blk_cmd_filter *filter);
#define MAX_SEGMENT_SIZE 65536
+#define BLK_SEG_BOUNDARY_MASK 0xFFFFFFFFUL
+
#define blkdev_entry_to_request(entry) list_entry((entry), struct request, queuelist)
static inline int queue_hardsect_size(struct request_queue *q)
diff --git a/include/linux/c2port.h b/include/linux/c2port.h
new file mode 100644
index 00000000000..7b5a2388ba6
--- /dev/null
+++ b/include/linux/c2port.h
@@ -0,0 +1,65 @@
+/*
+ * Silicon Labs C2 port Linux support
+ *
+ * Copyright (c) 2007 Rodolfo Giometti <giometti@linux.it>
+ * Copyright (c) 2007 Eurotech S.p.A. <info@eurotech.it>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation
+ */
+
+#include <linux/device.h>
+
+#define C2PORT_NAME_LEN 32
+
+/*
+ * C2 port basic structs
+ */
+
+/* Main struct */
+struct c2port_ops;
+struct c2port_device {
+ unsigned int access:1;
+ unsigned int flash_access:1;
+
+ int id;
+ char name[C2PORT_NAME_LEN];
+ struct c2port_ops *ops;
+ struct mutex mutex; /* prevent races during read/write */
+
+ struct device *dev;
+
+ void *private_data;
+};
+
+/* Basic operations */
+struct c2port_ops {
+ /* Flash layout */
+ unsigned short block_size; /* flash block size in bytes */
+ unsigned short blocks_num; /* flash blocks number */
+
+ /* Enable or disable the access to C2 port */
+ void (*access)(struct c2port_device *dev, int status);
+
+ /* Set C2D data line as input/output */
+ void (*c2d_dir)(struct c2port_device *dev, int dir);
+
+ /* Read/write C2D data line */
+ int (*c2d_get)(struct c2port_device *dev);
+ void (*c2d_set)(struct c2port_device *dev, int status);
+
+ /* Write C2CK clock line */
+ void (*c2ck_set)(struct c2port_device *dev, int status);
+};
+
+/*
+ * Exported functions
+ */
+
+#define to_class_dev(obj) container_of((obj), struct class_device, kobj)
+#define to_c2port_device(obj) container_of((obj), struct c2port_device, class)
+
+extern struct c2port_device *c2port_device_register(char *name,
+ struct c2port_ops *ops, void *devdata);
+extern void c2port_device_unregister(struct c2port_device *dev);
diff --git a/include/linux/can/core.h b/include/linux/can/core.h
index e9ca210ffa5..f50785ad478 100644
--- a/include/linux/can/core.h
+++ b/include/linux/can/core.h
@@ -19,7 +19,7 @@
#include <linux/skbuff.h>
#include <linux/netdevice.h>
-#define CAN_VERSION "20071116"
+#define CAN_VERSION "20081130"
/* increment this number each time you change some user-space interface */
#define CAN_ABI_VERSION "8"
diff --git a/include/linux/compat.h b/include/linux/compat.h
index f061a1ea1b7..e88f3ecf38b 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -252,12 +252,10 @@ extern int compat_ptrace_request(struct task_struct *child,
compat_long_t request,
compat_ulong_t addr, compat_ulong_t data);
-#ifdef __ARCH_WANT_COMPAT_SYS_PTRACE
extern long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
compat_ulong_t addr, compat_ulong_t data);
asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid,
compat_long_t addr, compat_long_t data);
-#endif /* __ARCH_WANT_COMPAT_SYS_PTRACE */
/*
* epoll (fs/eventpoll.c) compat bits follow ...
diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h
index 2691926fb50..8e540d32c9f 100644
--- a/include/linux/cpuset.h
+++ b/include/linux/cpuset.h
@@ -74,8 +74,6 @@ static inline int cpuset_do_slab_mem_spread(void)
return current->flags & PF_SPREAD_SLAB;
}
-extern void cpuset_track_online_nodes(void);
-
extern int current_cpuset_is_being_rebound(void);
extern void rebuild_sched_domains(void);
@@ -151,8 +149,6 @@ static inline int cpuset_do_slab_mem_spread(void)
return 0;
}
-static inline void cpuset_track_online_nodes(void) {}
-
static inline int current_cpuset_is_being_rebound(void)
{
return 0;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 0dcdd9458f4..4a853ef6fd3 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -63,23 +63,24 @@ extern int dir_notify_enable;
#define MAY_ACCESS 16
#define MAY_OPEN 32
-#define FMODE_READ ((__force fmode_t)1)
-#define FMODE_WRITE ((__force fmode_t)2)
-
-/* Internal kernel extensions */
-#define FMODE_LSEEK ((__force fmode_t)4)
-#define FMODE_PREAD ((__force fmode_t)8)
-#define FMODE_PWRITE FMODE_PREAD /* These go hand in hand */
-
-/* File is being opened for execution. Primary users of this flag are
- distributed filesystems that can use it to achieve correct ETXTBUSY
- behavior for cross-node execution/opening_for_writing of files */
-#define FMODE_EXEC ((__force fmode_t)16)
-
-#define FMODE_NDELAY ((__force fmode_t)32)
-#define FMODE_EXCL ((__force fmode_t)64)
+/* file is open for reading */
+#define FMODE_READ ((__force fmode_t)1)
+/* file is open for writing */
+#define FMODE_WRITE ((__force fmode_t)2)
+/* file is seekable */
+#define FMODE_LSEEK ((__force fmode_t)4)
+/* file can be accessed using pread/pwrite */
+#define FMODE_PREAD ((__force fmode_t)8)
+#define FMODE_PWRITE FMODE_PREAD /* These go hand in hand */
+/* File is opened for execution with sys_execve / sys_uselib */
+#define FMODE_EXEC ((__force fmode_t)16)
+/* File is opened with O_NDELAY (only set for block devices) */
+#define FMODE_NDELAY ((__force fmode_t)32)
+/* File is opened with O_EXCL (only set for block devices) */
+#define FMODE_EXCL ((__force fmode_t)64)
+/* File is opened using open(.., 3, ..) and is writeable only for ioctls
+ (specialy hack for floppy.c) */
#define FMODE_WRITE_IOCTL ((__force fmode_t)128)
-#define FMODE_NDELAY_NOW ((__force fmode_t)256)
#define RW_MASK 1
#define RWA_MASK 2
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index 703eb53cfa2..9c5bc6be2b0 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -6,6 +6,7 @@
#include <linux/ktime.h>
#include <linux/init.h>
#include <linux/types.h>
+#include <linux/module.h>
#include <linux/kallsyms.h>
#ifdef CONFIG_FUNCTION_TRACER
@@ -231,7 +232,7 @@ ftrace_init_module(unsigned long *start, unsigned long *end) { }
struct boot_trace {
pid_t caller;
- char func[KSYM_NAME_LEN];
+ char func[KSYM_SYMBOL_LEN];
int result;
unsigned long long duration; /* usecs */
ktime_t calltime;
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index e439e6aed83..3df7742ce24 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -522,7 +522,9 @@ extern char *disk_name (struct gendisk *hd, int partno, char *buf);
extern int disk_expand_part_tbl(struct gendisk *disk, int target);
extern int rescan_partitions(struct gendisk *disk, struct block_device *bdev);
-extern int __must_check add_partition(struct gendisk *, int, sector_t, sector_t, int);
+extern struct hd_struct * __must_check add_partition(struct gendisk *disk,
+ int partno, sector_t start,
+ sector_t len, int flags);
extern void delete_partition(struct gendisk *, int);
extern void printk_all_partitions(void);
diff --git a/include/linux/highmem.h b/include/linux/highmem.h
index 7dcbc82f3b7..13875ce9112 100644
--- a/include/linux/highmem.h
+++ b/include/linux/highmem.h
@@ -63,12 +63,14 @@ static inline void *kmap_atomic(struct page *page, enum km_type idx)
#endif /* CONFIG_HIGHMEM */
/* when CONFIG_HIGHMEM is not set these will be plain clear/copy_page */
+#ifndef clear_user_highpage
static inline void clear_user_highpage(struct page *page, unsigned long vaddr)
{
void *addr = kmap_atomic(page, KM_USER0);
clear_user_page(addr, vaddr, page);
kunmap_atomic(addr, KM_USER0);
}
+#endif
#ifndef __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
/**
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
index 07e510a3b00..3eba43878dc 100644
--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -46,9 +46,6 @@ enum hrtimer_restart {
* hrtimer callback modes:
*
* HRTIMER_CB_SOFTIRQ: Callback must run in softirq context
- * HRTIMER_CB_IRQSAFE: Callback may run in hardirq context
- * HRTIMER_CB_IRQSAFE_NO_RESTART: Callback may run in hardirq context and
- * does not restart the timer
* HRTIMER_CB_IRQSAFE_PERCPU: Callback must run in hardirq context
* Special mode for tick emulation and
* scheduler timer. Such timers are per
@@ -61,8 +58,6 @@ enum hrtimer_restart {
*/
enum hrtimer_cb_mode {
HRTIMER_CB_SOFTIRQ,
- HRTIMER_CB_IRQSAFE,
- HRTIMER_CB_IRQSAFE_NO_RESTART,
HRTIMER_CB_IRQSAFE_PERCPU,
HRTIMER_CB_IRQSAFE_UNLOCKED,
};
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 54525be4b5f..010fb26a157 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -1296,6 +1296,13 @@ extern int __ide_pci_register_driver(struct pci_driver *driver, struct module *o
#define ide_pci_register_driver(d) pci_register_driver(d)
#endif
+static inline int ide_pci_is_in_compatibility_mode(struct pci_dev *dev)
+{
+ if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 5) != 5)
+ return 1;
+ return 0;
+}
+
void ide_pci_setup_ports(struct pci_dev *, const struct ide_port_info *, int,
hw_regs_t *, hw_regs_t **);
void ide_setup_pci_noise(struct pci_dev *, const struct ide_port_info *);
@@ -1375,6 +1382,7 @@ enum {
IDE_HFLAG_IO_32BIT = (1 << 24),
/* unmask IRQs */
IDE_HFLAG_UNMASK_IRQS = (1 << 25),
+ IDE_HFLAG_BROKEN_ALTSTATUS = (1 << 26),
/* serialize ports if DMA is possible (for sl82c105) */
IDE_HFLAG_SERIALIZE_DMA = (1 << 27),
/* force host out of "simplex" mode */
diff --git a/include/linux/idr.h b/include/linux/idr.h
index fa035f96f2a..dd846df8cd3 100644
--- a/include/linux/idr.h
+++ b/include/linux/idr.h
@@ -52,13 +52,14 @@ struct idr_layer {
unsigned long bitmap; /* A zero bit means "space here" */
struct idr_layer *ary[1<<IDR_BITS];
int count; /* When zero, we can release it */
+ int layer; /* distance from leaf */
struct rcu_head rcu_head;
};
struct idr {
struct idr_layer *top;
struct idr_layer *id_free;
- int layers;
+ int layers; /* only valid without concurrent changes */
int id_free_cnt;
spinlock_t lock;
};
diff --git a/include/linux/inotify.h b/include/linux/inotify.h
index bd578578a8b..37ea2894b3c 100644
--- a/include/linux/inotify.h
+++ b/include/linux/inotify.h
@@ -134,6 +134,8 @@ extern void inotify_remove_watch_locked(struct inotify_handle *,
struct inotify_watch *);
extern void get_inotify_watch(struct inotify_watch *);
extern void put_inotify_watch(struct inotify_watch *);
+extern int pin_inotify_watch(struct inotify_watch *);
+extern void unpin_inotify_watch(struct inotify_watch *);
#else
@@ -228,6 +230,15 @@ static inline void put_inotify_watch(struct inotify_watch *watch)
{
}
+extern inline int pin_inotify_watch(struct inotify_watch *watch)
+{
+ return 0;
+}
+
+extern inline void unpin_inotify_watch(struct inotify_watch *watch)
+{
+}
+
#endif /* CONFIG_INOTIFY */
#endif /* __KERNEL __ */
diff --git a/include/linux/input.h b/include/linux/input.h
index b86fb5581ce..9a6355f74db 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -238,6 +238,7 @@ struct input_absinfo {
#define KEY_KPEQUAL 117
#define KEY_KPPLUSMINUS 118
#define KEY_PAUSE 119
+#define KEY_SCALE 120 /* AL Compiz Scale (Expose) */
#define KEY_KPCOMMA 121
#define KEY_HANGEUL 122
@@ -322,6 +323,7 @@ struct input_absinfo {
#define KEY_PAUSECD 201
#define KEY_PROG3 202
#define KEY_PROG4 203
+#define KEY_DASHBOARD 204 /* AL Dashboard */
#define KEY_SUSPEND 205
#define KEY_CLOSE 206 /* AC Close */
#define KEY_PLAY 207
@@ -657,6 +659,8 @@ struct input_absinfo {
#define SW_RADIO SW_RFKILL_ALL /* deprecated */
#define SW_MICROPHONE_INSERT 0x04 /* set = inserted */
#define SW_DOCK 0x05 /* set = plugged into dock */
+#define SW_LINEOUT_INSERT 0x06 /* set = inserted */
+#define SW_JACK_PHYSICAL_INSERT 0x07 /* set = mechanical switch set */
#define SW_MAX 0x0f
#define SW_CNT (SW_MAX+1)
diff --git a/include/linux/irq.h b/include/linux/irq.h
index d058c57be02..3dddfa703eb 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -63,7 +63,8 @@ typedef void (*irq_flow_handler_t)(unsigned int irq,
#define IRQ_MOVE_PENDING 0x00200000 /* need to re-target IRQ destination */
#define IRQ_NO_BALANCING 0x00400000 /* IRQ is excluded from balancing */
#define IRQ_SPURIOUS_DISABLED 0x00800000 /* IRQ was disabled by the spurious trap */
-#define IRQ_MOVE_PCNTXT 0x01000000 /* IRQ migration from process context */
+#define IRQ_MOVE_PCNTXT 0x01000000 /* IRQ migration from process context */
+#define IRQ_AFFINITY_SET 0x02000000 /* IRQ affinity was set from userspace*/
#ifdef CONFIG_IRQ_PER_CPU
# define CHECK_IRQ_PER_CPU(var) ((var) & IRQ_PER_CPU)
@@ -130,7 +131,7 @@ struct irq_chip {
/**
* struct irq_desc - interrupt descriptor
- *
+ * @irq: interrupt number for this descriptor
* @handle_irq: highlevel irq-events handler [if NULL, __do_IRQ()]
* @chip: low level interrupt hardware access
* @msi_desc: MSI descriptor
@@ -149,7 +150,6 @@ struct irq_chip {
* @cpu: cpu index useful for balancing
* @pending_mask: pending rebalanced interrupts
* @dir: /proc/irq/ procfs entry
- * @affinity_entry: /proc/irq/smp_affinity procfs entry on SMP
* @name: flow handler name for /proc/interrupts output
*/
struct irq_desc {
@@ -210,7 +210,6 @@ extern int setup_irq(unsigned int irq, struct irqaction *new);
#ifdef CONFIG_GENERIC_PENDING_IRQ
-void set_pending_irq(unsigned int irq, cpumask_t mask);
void move_native_irq(int irq);
void move_masked_irq(int irq);
@@ -228,10 +227,6 @@ static inline void move_masked_irq(int irq)
{
}
-static inline void set_pending_irq(unsigned int irq, cpumask_t mask)
-{
-}
-
#endif /* CONFIG_GENERIC_PENDING_IRQ */
#else /* CONFIG_SMP */
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index fba141d3ca0..dc7e0d0a647 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -318,32 +318,36 @@ static inline char *pack_hex_byte(char *buf, u8 byte)
return buf;
}
-#define pr_emerg(fmt, arg...) \
- printk(KERN_EMERG fmt, ##arg)
-#define pr_alert(fmt, arg...) \
- printk(KERN_ALERT fmt, ##arg)
-#define pr_crit(fmt, arg...) \
- printk(KERN_CRIT fmt, ##arg)
-#define pr_err(fmt, arg...) \
- printk(KERN_ERR fmt, ##arg)
-#define pr_warning(fmt, arg...) \
- printk(KERN_WARNING fmt, ##arg)
-#define pr_notice(fmt, arg...) \
- printk(KERN_NOTICE fmt, ##arg)
-#define pr_info(fmt, arg...) \
- printk(KERN_INFO fmt, ##arg)
+#ifndef pr_fmt
+#define pr_fmt(fmt) fmt
+#endif
+
+#define pr_emerg(fmt, ...) \
+ printk(KERN_EMERG pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_alert(fmt, ...) \
+ printk(KERN_ALERT pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_crit(fmt, ...) \
+ printk(KERN_CRIT pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_err(fmt, ...) \
+ printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_warning(fmt, ...) \
+ printk(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_notice(fmt, ...) \
+ printk(KERN_NOTICE pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_info(fmt, ...) \
+ printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)
/* If you are writing a driver, please use dev_dbg instead */
#if defined(CONFIG_DYNAMIC_PRINTK_DEBUG)
#define pr_debug(fmt, ...) do { \
- dynamic_pr_debug(fmt, ##__VA_ARGS__); \
+ dynamic_pr_debug(pr_fmt(fmt), ##__VA_ARGS__); \
} while (0)
#elif defined(DEBUG)
-#define pr_debug(fmt, arg...) \
- printk(KERN_DEBUG fmt, ##arg)
+#define pr_debug(fmt, ...) \
+ printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
#else
-#define pr_debug(fmt, arg...) \
- ({ if (0) printk(KERN_DEBUG fmt, ##arg); 0; })
+#define pr_debug(fmt, ...) \
+ ({ if (0) printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); 0; })
#endif
/*
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 59b0f1c807b..ed3f26eb5df 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -375,6 +375,7 @@ enum {
ATA_HORKAGE_BRIDGE_OK = (1 << 10), /* no bridge limits */
ATA_HORKAGE_ATAPI_MOD16_DMA = (1 << 11), /* use ATAPI DMA for commands
not multiple of 16 bytes */
+ ATA_HORKAGE_FIRMWARE_WARN = (1 << 12), /* firwmare update warning */
/* DMA mask for user DMA control: User visible values; DO NOT
renumber */
diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h
index 331e5f1c2d8..29aec6e1002 100644
--- a/include/linux/lockdep.h
+++ b/include/linux/lockdep.h
@@ -331,10 +331,11 @@ static inline void lockdep_on(void)
# define lock_set_subclass(l, s, i) do { } while (0)
# define lockdep_init() do { } while (0)
# define lockdep_info() do { } while (0)
-# define lockdep_init_map(lock, name, key, sub) do { (void)(key); } while (0)
+# define lockdep_init_map(lock, name, key, sub) \
+ do { (void)(name); (void)(key); } while (0)
# define lockdep_set_class(lock, key) do { (void)(key); } while (0)
# define lockdep_set_class_and_name(lock, key, name) \
- do { (void)(key); } while (0)
+ do { (void)(key); (void)(name); } while (0)
#define lockdep_set_class_and_subclass(lock, key, sub) \
do { (void)(key); } while (0)
#define lockdep_set_subclass(lock, sub) do { } while (0)
diff --git a/include/linux/memory.h b/include/linux/memory.h
index 2f5f8a5ef2a..36c82c9e6ea 100644
--- a/include/linux/memory.h
+++ b/include/linux/memory.h
@@ -91,7 +91,7 @@ extern int memory_notify(unsigned long val, void *v);
#ifdef CONFIG_MEMORY_HOTPLUG
#define hotplug_memory_notifier(fn, pri) { \
- static struct notifier_block fn##_mem_nb = \
+ static __meminitdata struct notifier_block fn##_mem_nb =\
{ .notifier_call = fn, .priority = pri }; \
register_memory_notifier(&fn##_mem_nb); \
}
diff --git a/include/linux/mfd/wm8350/audio.h b/include/linux/mfd/wm8350/audio.h
index 217bb22ebb8..af95a1d2f3a 100644
--- a/include/linux/mfd/wm8350/audio.h
+++ b/include/linux/mfd/wm8350/audio.h
@@ -1,7 +1,7 @@
/*
* audio.h -- Audio Driver for Wolfson WM8350 PMIC
*
- * Copyright 2007 Wolfson Microelectronics PLC
+ * Copyright 2007, 2008 Wolfson Microelectronics PLC
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -70,9 +70,9 @@
#define WM8350_CODEC_ISEL_0_5 3 /* x0.5 */
#define WM8350_VMID_OFF 0
-#define WM8350_VMID_500K 1
-#define WM8350_VMID_100K 2
-#define WM8350_VMID_10K 3
+#define WM8350_VMID_300K 1
+#define WM8350_VMID_50K 2
+#define WM8350_VMID_5K 3
/*
* R40 (0x28) - Clock Control 1
@@ -591,8 +591,38 @@
#define WM8350_IRQ_CODEC_MICSCD 41
#define WM8350_IRQ_CODEC_MICD 42
+/*
+ * WM8350 Platform data.
+ *
+ * This must be initialised per platform for best audio performance.
+ * Please see WM8350 datasheet for information.
+ */
+struct wm8350_audio_platform_data {
+ int vmid_discharge_msecs; /* VMID --> OFF discharge time */
+ int drain_msecs; /* OFF drain time */
+ int cap_discharge_msecs; /* Cap ON (from OFF) discharge time */
+ int vmid_charge_msecs; /* vmid power up time */
+ u32 vmid_s_curve:2; /* vmid enable s curve speed */
+ u32 dis_out4:2; /* out4 discharge speed */
+ u32 dis_out3:2; /* out3 discharge speed */
+ u32 dis_out2:2; /* out2 discharge speed */
+ u32 dis_out1:2; /* out1 discharge speed */
+ u32 vroi_out4:1; /* out4 tie off */
+ u32 vroi_out3:1; /* out3 tie off */
+ u32 vroi_out2:1; /* out2 tie off */
+ u32 vroi_out1:1; /* out1 tie off */
+ u32 vroi_enable:1; /* enable tie off */
+ u32 codec_current_on:2; /* current level ON */
+ u32 codec_current_standby:2; /* current level STANDBY */
+ u32 codec_current_charge:2; /* codec current @ vmid charge */
+};
+
+struct snd_soc_codec;
+
struct wm8350_codec {
struct platform_device *pdev;
+ struct snd_soc_codec *codec;
+ struct wm8350_audio_platform_data *platform_data;
};
#endif
diff --git a/include/linux/mfd/wm8350/rtc.h b/include/linux/mfd/wm8350/rtc.h
index dfda69e9f44..24add2bef6c 100644
--- a/include/linux/mfd/wm8350/rtc.h
+++ b/include/linux/mfd/wm8350/rtc.h
@@ -261,6 +261,8 @@
struct wm8350_rtc {
struct platform_device *pdev;
+ struct rtc_device *rtc;
+ int alarm_enabled; /* used over suspend/resume */
};
#endif
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index bd9977b8949..371086fd946 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -179,6 +179,7 @@ struct mlx4_caps {
int num_ports;
int vl_cap[MLX4_MAX_PORTS + 1];
int ib_mtu_cap[MLX4_MAX_PORTS + 1];
+ __be32 ib_port_def_cap[MLX4_MAX_PORTS + 1];
u64 def_mac[MLX4_MAX_PORTS + 1];
int eth_mtu_cap[MLX4_MAX_PORTS + 1];
int gid_table_len[MLX4_MAX_PORTS + 1];
diff --git a/include/linux/net.h b/include/linux/net.h
index 6dc14a24004..4515efae4c3 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -40,7 +40,7 @@
#define SYS_GETSOCKOPT 15 /* sys_getsockopt(2) */
#define SYS_SENDMSG 16 /* sys_sendmsg(2) */
#define SYS_RECVMSG 17 /* sys_recvmsg(2) */
-#define SYS_PACCEPT 18 /* sys_paccept(2) */
+#define SYS_ACCEPT4 18 /* sys_accept4(2) */
typedef enum {
SS_FREE = 0, /* not allocated */
@@ -100,7 +100,7 @@ enum sock_type {
* remaining bits are used as flags. */
#define SOCK_TYPE_MASK 0xf
-/* Flags for socket, socketpair, paccept */
+/* Flags for socket, socketpair, accept4 */
#define SOCK_CLOEXEC O_CLOEXEC
#ifndef SOCK_NONBLOCK
#define SOCK_NONBLOCK O_NONBLOCK
@@ -223,8 +223,6 @@ extern int sock_map_fd(struct socket *sock, int flags);
extern struct socket *sockfd_lookup(int fd, int *err);
#define sockfd_put(sock) fput(sock->file)
extern int net_ratelimit(void);
-extern long do_accept(int fd, struct sockaddr __user *upeer_sockaddr,
- int __user *upeer_addrlen, int flags);
#define net_random() random32()
#define net_srandom(seed) srandom32((__force u32)seed)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 9d77b1d7dca..e26f5495289 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -319,6 +319,7 @@ enum
{
NAPI_STATE_SCHED, /* Poll is scheduled */
NAPI_STATE_DISABLE, /* Disable pending */
+ NAPI_STATE_NPSVC, /* Netpoll - don't dequeue from poll_list */
};
extern void __napi_schedule(struct napi_struct *n);
@@ -1497,6 +1498,12 @@ static inline void netif_rx_complete(struct net_device *dev,
{
unsigned long flags;
+ /*
+ * don't let napi dequeue from the cpu poll list
+ * just in case its running on a different cpu
+ */
+ if (unlikely(test_bit(NAPI_STATE_NPSVC, &napi->state)))
+ return;
local_irq_save(flags);
__netif_rx_complete(dev, napi);
local_irq_restore(flags);
diff --git a/include/linux/netfilter/nfnetlink_conntrack.h b/include/linux/netfilter/nfnetlink_conntrack.h
index c19595c8930..29fe9ea1d34 100644
--- a/include/linux/netfilter/nfnetlink_conntrack.h
+++ b/include/linux/netfilter/nfnetlink_conntrack.h
@@ -141,6 +141,7 @@ enum ctattr_protonat {
#define CTA_PROTONAT_MAX (__CTA_PROTONAT_MAX - 1)
enum ctattr_natseq {
+ CTA_NAT_SEQ_UNSPEC,
CTA_NAT_SEQ_CORRECTION_POS,
CTA_NAT_SEQ_OFFSET_BEFORE,
CTA_NAT_SEQ_OFFSET_AFTER,
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
index be41b609c88..e52ce475d19 100644
--- a/include/linux/netfilter/x_tables.h
+++ b/include/linux/netfilter/x_tables.h
@@ -251,7 +251,7 @@ struct xt_target_param {
*/
struct xt_tgchk_param {
const char *table;
- void *entryinfo;
+ const void *entryinfo;
const struct xt_target *target;
void *targinfo;
unsigned int hook_mask;
diff --git a/include/linux/page_cgroup.h b/include/linux/page_cgroup.h
index f546ad6fc02..1e6d34bfa09 100644
--- a/include/linux/page_cgroup.h
+++ b/include/linux/page_cgroup.h
@@ -17,7 +17,7 @@ struct page_cgroup {
struct list_head lru; /* per cgroup LRU list */
};
-void __init pgdat_page_cgroup_init(struct pglist_data *pgdat);
+void __meminit pgdat_page_cgroup_init(struct pglist_data *pgdat);
void __init page_cgroup_init(void);
struct page_cgroup *lookup_page_cgroup(struct page *page);
@@ -91,7 +91,7 @@ static inline void unlock_page_cgroup(struct page_cgroup *pc)
#else /* CONFIG_CGROUP_MEM_RES_CTLR */
struct page_cgroup;
-static inline void pgdat_page_cgroup_init(struct pglist_data *pgdat)
+static inline void __meminit pgdat_page_cgroup_init(struct pglist_data *pgdat)
{
}
diff --git a/include/linux/ratelimit.h b/include/linux/ratelimit.h
index 18a5b9ba9d4..00044b85645 100644
--- a/include/linux/ratelimit.h
+++ b/include/linux/ratelimit.h
@@ -17,11 +17,4 @@ struct ratelimit_state {
struct ratelimit_state name = {interval, burst,}
extern int __ratelimit(struct ratelimit_state *rs);
-
-static inline int ratelimit(void)
-{
- static DEFINE_RATELIMIT_STATE(rs, DEFAULT_RATELIMIT_INTERVAL,
- DEFAULT_RATELIMIT_BURST);
- return __ratelimit(&rs);
-}
#endif
diff --git a/include/linux/ring_buffer.h b/include/linux/ring_buffer.h
index 536b0ca46a0..e097c2e6b6d 100644
--- a/include/linux/ring_buffer.h
+++ b/include/linux/ring_buffer.h
@@ -120,6 +120,9 @@ unsigned long ring_buffer_overruns(struct ring_buffer *buffer);
u64 ring_buffer_time_stamp(int cpu);
void ring_buffer_normalize_time_stamp(int cpu, u64 *ts);
+void tracing_on(void);
+void tracing_off(void);
+
enum ring_buffer_flags {
RB_FL_OVERWRITE = 1 << 0,
};
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 644ffbda17c..55e30d11447 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -630,6 +630,10 @@ struct user_struct {
atomic_t inotify_watches; /* How many inotify watches does this user have? */
atomic_t inotify_devs; /* How many inotify devs does this user have opened? */
#endif
+#ifdef CONFIG_EPOLL
+ atomic_t epoll_devs; /* The number of epoll descriptors currently open */
+ atomic_t epoll_watches; /* The number of file descriptors currently watched */
+#endif
#ifdef CONFIG_POSIX_MQUEUE
/* protected by mq_lock */
unsigned long mq_bytes; /* How many bytes can be allocated to mqueue? */
diff --git a/include/linux/security.h b/include/linux/security.h
index c13f1cec9ab..e3d4ecda267 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1818,17 +1818,21 @@ static inline int security_settime(struct timespec *ts, struct timezone *tz)
static inline int security_vm_enough_memory(long pages)
{
+ WARN_ON(current->mm == NULL);
return cap_vm_enough_memory(current->mm, pages);
}
-static inline int security_vm_enough_memory_kern(long pages)
+static inline int security_vm_enough_memory_mm(struct mm_struct *mm, long pages)
{
- return cap_vm_enough_memory(current->mm, pages);
+ WARN_ON(mm == NULL);
+ return cap_vm_enough_memory(mm, pages);
}
-static inline int security_vm_enough_memory_mm(struct mm_struct *mm, long pages)
+static inline int security_vm_enough_memory_kern(long pages)
{
- return cap_vm_enough_memory(mm, pages);
+ /* If current->mm is a kernel thread then we will pass NULL,
+ for this specific case that is fine */
+ return cap_vm_enough_memory(current->mm, pages);
}
static inline int security_bprm_alloc(struct linux_binprm *bprm)
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index e27f216361f..4e4f1277f3b 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -155,6 +155,9 @@
#define PORT_SC26XX 82
+/* SH-SCI */
+#define PORT_SCIFA 83
+
#ifdef __KERNEL__
#include <linux/compiler.h>
diff --git a/include/linux/slab.h b/include/linux/slab.h
index ba965c84ae0..000da12b5cf 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -23,6 +23,34 @@
#define SLAB_CACHE_DMA 0x00004000UL /* Use GFP_DMA memory */
#define SLAB_STORE_USER 0x00010000UL /* DEBUG: Store the last owner for bug hunting */
#define SLAB_PANIC 0x00040000UL /* Panic if kmem_cache_create() fails */
+/*
+ * SLAB_DESTROY_BY_RCU - **WARNING** READ THIS!
+ *
+ * This delays freeing the SLAB page by a grace period, it does _NOT_
+ * delay object freeing. This means that if you do kmem_cache_free()
+ * that memory location is free to be reused at any time. Thus it may
+ * be possible to see another object there in the same RCU grace period.
+ *
+ * This feature only ensures the memory location backing the object
+ * stays valid, the trick to using this is relying on an independent
+ * object validation pass. Something like:
+ *
+ * rcu_read_lock()
+ * again:
+ * obj = lockless_lookup(key);
+ * if (obj) {
+ * if (!try_get_ref(obj)) // might fail for free objects
+ * goto again;
+ *
+ * if (obj->key != key) { // not the object we expected
+ * put_ref(obj);
+ * goto again;
+ * }
+ * }
+ * rcu_read_unlock();
+ *
+ * See also the comment on struct slab_rcu in mm/slab.c.
+ */
#define SLAB_DESTROY_BY_RCU 0x00080000UL /* Defer freeing slabs to RCU */
#define SLAB_MEM_SPREAD 0x00100000UL /* Spread some memory over cpuset */
#define SLAB_TRACE 0x00200000UL /* Trace allocations and frees */
diff --git a/include/linux/smp.h b/include/linux/smp.h
index 3f9a60043a9..6e7ba16ff45 100644
--- a/include/linux/smp.h
+++ b/include/linux/smp.h
@@ -146,6 +146,8 @@ static inline void smp_send_reschedule(int cpu) { }
})
#define smp_call_function_mask(mask, func, info, wait) \
(up_smp_call_function(func, info))
+#define smp_call_function_many(mask, func, info, wait) \
+ (up_smp_call_function(func, info))
static inline void init_call_single_data(void)
{
}
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index d6ff145919c..04fb47bfb92 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -410,8 +410,7 @@ asmlinkage long sys_getsockopt(int fd, int level, int optname,
asmlinkage long sys_bind(int, struct sockaddr __user *, int);
asmlinkage long sys_connect(int, struct sockaddr __user *, int);
asmlinkage long sys_accept(int, struct sockaddr __user *, int __user *);
-asmlinkage long sys_paccept(int, struct sockaddr __user *, int __user *,
- const __user sigset_t *, size_t, int);
+asmlinkage long sys_accept4(int, struct sockaddr __user *, int __user *, int);
asmlinkage long sys_getsockname(int, struct sockaddr __user *, int __user *);
asmlinkage long sys_getpeername(int, struct sockaddr __user *, int __user *);
asmlinkage long sys_send(int, void __user *, size_t, unsigned);
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 8fa973bede5..f72aa51f7bc 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -108,6 +108,7 @@ enum usb_interface_condition {
* (in probe()), bound to a driver, or unbinding (in disconnect())
* @is_active: flag set when the interface is bound and not suspended.
* @sysfs_files_created: sysfs attributes exist
+ * @unregistering: flag set when the interface is being unregistered
* @needs_remote_wakeup: flag set when the driver requires remote-wakeup
* capability during autosuspend.
* @needs_altsetting0: flag set when a set-interface request for altsetting 0
@@ -163,6 +164,7 @@ struct usb_interface {
enum usb_interface_condition condition; /* state of binding */
unsigned is_active:1; /* the interface is not suspended */
unsigned sysfs_files_created:1; /* the sysfs attributes exist */
+ unsigned unregistering:1; /* unregistration is in progress */
unsigned needs_remote_wakeup:1; /* driver requires remote wakeup */
unsigned needs_altsetting0:1; /* switch to altsetting 0 is pending */
unsigned needs_binding:1; /* needs delayed unbind/rebind */
diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h
index 73a2f4eb1f7..9b42baed390 100644
--- a/include/linux/usb/ch9.h
+++ b/include/linux/usb/ch9.h
@@ -158,8 +158,12 @@ struct usb_ctrlrequest {
* (rarely) accepted by SET_DESCRIPTOR.
*
* Note that all multi-byte values here are encoded in little endian
- * byte order "on the wire". But when exposed through Linux-USB APIs,
- * they've been converted to cpu byte order.
+ * byte order "on the wire". Within the kernel and when exposed
+ * through the Linux-USB APIs, they are not converted to cpu byte
+ * order; it is the responsibility of the client code to do this.
+ * The single exception is when device and configuration descriptors (but
+ * not other descriptors) are read from usbfs (i.e. /proc/bus/usb/BBB/DDD);
+ * in this case the fields are converted to host endianness by the kernel.
*/
/*
diff --git a/include/net/af_unix.h b/include/net/af_unix.h
index c29ff1da8a1..1614d78c60e 100644
--- a/include/net/af_unix.h
+++ b/include/net/af_unix.h
@@ -9,6 +9,7 @@
extern void unix_inflight(struct file *fp);
extern void unix_notinflight(struct file *fp);
extern void unix_gc(void);
+extern void wait_for_unix_gc(void);
#define UNIX_HASH_SIZE 256
diff --git a/include/net/irda/irda_device.h b/include/net/irda/irda_device.h
index 3025ae17ddb..94c852d47d0 100644
--- a/include/net/irda/irda_device.h
+++ b/include/net/irda/irda_device.h
@@ -135,9 +135,11 @@ struct dongle_reg {
/*
* Per-packet information we need to hide inside sk_buff
- * (must not exceed 48 bytes, check with struct sk_buff)
+ * (must not exceed 48 bytes, check with struct sk_buff)
+ * The default_qdisc_pad field is a temporary hack.
*/
struct irda_skb_cb {
+ unsigned int default_qdisc_pad;
magic_t magic; /* Be sure that we can trust the information */
__u32 next_speed; /* The Speed to be set *after* this frame */
__u16 mtt; /* Minimum turn around time */
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 8856e2d60e9..73d81bc6aa7 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -74,14 +74,6 @@
*/
/**
- * enum ieee80211_notification_type - Low level driver notification
- * @IEEE80211_NOTIFY_RE_ASSOC: start the re-association sequence
- */
-enum ieee80211_notification_types {
- IEEE80211_NOTIFY_RE_ASSOC,
-};
-
-/**
* struct ieee80211_ht_bss_info - describing BSS's HT characteristics
*
* This structure describes most essential parameters needed
@@ -1798,18 +1790,6 @@ void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, const u8 *ra,
u16 tid);
/**
- * ieee80211_notify_mac - low level driver notification
- * @hw: pointer as obtained from ieee80211_alloc_hw().
- * @notif_type: enum ieee80211_notification_types
- *
- * This function must be called by low level driver to inform mac80211 of
- * low level driver status change or force mac80211 to re-assoc for low
- * level driver internal error that require re-assoc.
- */
-void ieee80211_notify_mac(struct ieee80211_hw *hw,
- enum ieee80211_notification_types notif_type);
-
-/**
* ieee80211_find_sta - find a station
*
* @hw: pointer as obtained from ieee80211_alloc_hw()
diff --git a/include/net/request_sock.h b/include/net/request_sock.h
index cac811e51f6..c7190846e12 100644
--- a/include/net/request_sock.h
+++ b/include/net/request_sock.h
@@ -31,6 +31,7 @@ struct request_sock_ops {
int family;
int obj_size;
struct kmem_cache *slab;
+ char *slab_name;
int (*rtx_syn_ack)(struct sock *sk,
struct request_sock *req);
void (*send_ack)(struct sock *sk, struct sk_buff *skb,
diff --git a/include/net/sock.h b/include/net/sock.h
index c04f9e18ea2..2f47107f6d0 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -815,7 +815,7 @@ static inline void sk_wmem_free_skb(struct sock *sk, struct sk_buff *skb)
*/
#define sock_lock_init_class_and_name(sk, sname, skey, name, key) \
do { \
- sk->sk_lock.owned = 0; \
+ sk->sk_lock.owned = 0; \
init_waitqueue_head(&sk->sk_lock.wq); \
spin_lock_init(&(sk)->sk_lock.slock); \
debug_check_no_locks_freed((void *)&(sk)->sk_lock, \
diff --git a/include/net/timewait_sock.h b/include/net/timewait_sock.h
index 1e1ee3253fd..97c3b14da55 100644
--- a/include/net/timewait_sock.h
+++ b/include/net/timewait_sock.h
@@ -16,6 +16,7 @@
struct timewait_sock_ops {
struct kmem_cache *twsk_slab;
+ char *twsk_slab_name;
unsigned int twsk_obj_size;
int (*twsk_unique)(struct sock *sk,
struct sock *sktw, void *twp);
diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
index 49d8913c4f8..6e04e6fe79c 100644
--- a/include/scsi/scsi_transport_fc.h
+++ b/include/scsi/scsi_transport_fc.h
@@ -357,7 +357,7 @@ struct fc_rport { /* aka fc_starget_attrs */
/* bit field values for struct fc_rport "flags" field: */
#define FC_RPORT_DEVLOSS_PENDING 0x01
#define FC_RPORT_SCAN_PENDING 0x02
-#define FC_RPORT_FAST_FAIL_TIMEDOUT 0x03
+#define FC_RPORT_FAST_FAIL_TIMEDOUT 0x04
#define dev_to_rport(d) \
container_of(d, struct fc_rport, dev)
diff --git a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h
index 9c309daf492..251fc1cd500 100644
--- a/include/sound/ac97_codec.h
+++ b/include/sound/ac97_codec.h
@@ -281,10 +281,12 @@
/* specific - Analog Devices */
#define AC97_AD_TEST 0x5a /* test register */
#define AC97_AD_TEST2 0x5c /* undocumented test register 2 */
+#define AC97_AD_HPFD_SHIFT 12 /* High Pass Filter Disable */
#define AC97_AD_CODEC_CFG 0x70 /* codec configuration */
#define AC97_AD_JACK_SPDIF 0x72 /* Jack Sense & S/PDIF */
#define AC97_AD_SERIAL_CFG 0x74 /* Serial Configuration */
#define AC97_AD_MISC 0x76 /* Misc Control Bits */
+#define AC97_AD_VREFD_SHIFT 2 /* V_REFOUT Disable (AD1888) */
/* specific - Cirrus Logic */
#define AC97_CSR_ACMODE 0x5e /* AC Mode Register */
diff --git a/include/sound/asound.h b/include/sound/asound.h
index 2c4dc908a54..1c02ed1d7c4 100644
--- a/include/sound/asound.h
+++ b/include/sound/asound.h
@@ -575,6 +575,7 @@ enum {
#define SNDRV_TIMER_GLOBAL_SYSTEM 0
#define SNDRV_TIMER_GLOBAL_RTC 1
#define SNDRV_TIMER_GLOBAL_HPET 2
+#define SNDRV_TIMER_GLOBAL_HRTIMER 3
/* info flags */
#define SNDRV_TIMER_FLG_SLAVE (1<<0) /* cannot be controlled */
diff --git a/include/sound/core.h b/include/sound/core.h
index 1508c4ec1ba..f632484bc74 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -353,7 +353,7 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...)
* snd_printk - printk wrapper
* @fmt: format string
*
- * Works like print() but prints the file and the line of the caller
+ * Works like printk() but prints the file and the line of the caller
* when configured with CONFIG_SND_VERBOSE_PRINTK.
*/
#define snd_printk(fmt, args...) \
@@ -380,18 +380,40 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...)
printk(fmt ,##args)
#endif
+/**
+ * snd_BUG - give a BUG warning message and stack trace
+ *
+ * Calls WARN() if CONFIG_SND_DEBUG is set.
+ * Ignored when CONFIG_SND_DEBUG is not set.
+ */
#define snd_BUG() WARN(1, "BUG?\n")
+
+/**
+ * snd_BUG_ON - debugging check macro
+ * @cond: condition to evaluate
+ *
+ * When CONFIG_SND_DEBUG is set, this macro evaluates the given condition,
+ * and call WARN() and returns the value if it's non-zero.
+ *
+ * When CONFIG_SND_DEBUG is not set, this just returns zero, and the given
+ * condition is ignored.
+ *
+ * NOTE: the argument won't be evaluated at all when CONFIG_SND_DEBUG=n.
+ * Thus, don't put any statement that influences on the code behavior,
+ * such as pre/post increment, to the argument of this macro.
+ * If you want to evaluate and give a warning, use standard WARN_ON().
+ */
#define snd_BUG_ON(cond) WARN((cond), "BUG? (%s)\n", __stringify(cond))
#else /* !CONFIG_SND_DEBUG */
#define snd_printd(fmt, args...) do { } while (0)
#define snd_BUG() do { } while (0)
-static inline int __snd_bug_on(void)
+static inline int __snd_bug_on(int cond)
{
return 0;
}
-#define snd_BUG_ON(cond) __snd_bug_on() /* always false */
+#define snd_BUG_ON(cond) __snd_bug_on(0 && (cond)) /* always false */
#endif /* CONFIG_SND_DEBUG */
diff --git a/include/sound/jack.h b/include/sound/jack.h
index b1b2b8b59ad..2e0315cdd0d 100644
--- a/include/sound/jack.h
+++ b/include/sound/jack.h
@@ -35,6 +35,8 @@ enum snd_jack_types {
SND_JACK_HEADPHONE = 0x0001,
SND_JACK_MICROPHONE = 0x0002,
SND_JACK_HEADSET = SND_JACK_HEADPHONE | SND_JACK_MICROPHONE,
+ SND_JACK_LINEOUT = 0x0004,
+ SND_JACK_MECHANICAL = 0x0008, /* If detected separately */
};
struct snd_jack {
diff --git a/include/sound/l3.h b/include/sound/l3.h
new file mode 100644
index 00000000000..423a08f0f1b
--- /dev/null
+++ b/include/sound/l3.h
@@ -0,0 +1,18 @@
+#ifndef _L3_H_
+#define _L3_H_ 1
+
+struct l3_pins {
+ void (*setdat)(int);
+ void (*setclk)(int);
+ void (*setmode)(int);
+ int data_hold;
+ int data_setup;
+ int clock_high;
+ int mode_hold;
+ int mode;
+ int mode_setup;
+};
+
+int l3_write(struct l3_pins *adap, u8 addr, u8 *data, int len);
+
+#endif
diff --git a/include/sound/s3c24xx_uda134x.h b/include/sound/s3c24xx_uda134x.h
new file mode 100644
index 00000000000..33df4cb909d
--- /dev/null
+++ b/include/sound/s3c24xx_uda134x.h
@@ -0,0 +1,14 @@
+#ifndef _S3C24XX_UDA134X_H_
+#define _S3C24XX_UDA134X_H_ 1
+
+#include <sound/uda134x.h>
+
+struct s3c24xx_uda134x_platform_data {
+ int l3_clk;
+ int l3_mode;
+ int l3_data;
+ void (*power) (int);
+ int model;
+};
+
+#endif
diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h
new file mode 100644
index 00000000000..24247f76360
--- /dev/null
+++ b/include/sound/soc-dai.h
@@ -0,0 +1,231 @@
+/*
+ * linux/sound/soc-dai.h -- ALSA SoC Layer
+ *
+ * Copyright: 2005-2008 Wolfson Microelectronics. PLC.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Digital Audio Interface (DAI) API.
+ */
+
+#ifndef __LINUX_SND_SOC_DAI_H
+#define __LINUX_SND_SOC_DAI_H
+
+
+#include <linux/list.h>
+
+struct snd_pcm_substream;
+
+/*
+ * DAI hardware audio formats.
+ *
+ * Describes the physical PCM data formating and clocking. Add new formats
+ * to the end.
+ */
+#define SND_SOC_DAIFMT_I2S 0 /* I2S mode */
+#define SND_SOC_DAIFMT_RIGHT_J 1 /* Right Justified mode */
+#define SND_SOC_DAIFMT_LEFT_J 2 /* Left Justified mode */
+#define SND_SOC_DAIFMT_DSP_A 3 /* L data msb after FRM LRC */
+#define SND_SOC_DAIFMT_DSP_B 4 /* L data msb during FRM LRC */
+#define SND_SOC_DAIFMT_AC97 5 /* AC97 */
+
+/* left and right justified also known as MSB and LSB respectively */
+#define SND_SOC_DAIFMT_MSB SND_SOC_DAIFMT_LEFT_J
+#define SND_SOC_DAIFMT_LSB SND_SOC_DAIFMT_RIGHT_J
+
+/*
+ * DAI Clock gating.
+ *
+ * DAI bit clocks can be be gated (disabled) when not the DAI is not
+ * sending or receiving PCM data in a frame. This can be used to save power.
+ */
+#define SND_SOC_DAIFMT_CONT (0 << 4) /* continuous clock */
+#define SND_SOC_DAIFMT_GATED (1 << 4) /* clock is gated */
+
+/*
+ * DAI Left/Right Clocks.
+ *
+ * Specifies whether the DAI can support different samples for similtanious
+ * playback and capture. This usually requires a seperate physical frame
+ * clock for playback and capture.
+ */
+#define SND_SOC_DAIFMT_SYNC (0 << 5) /* Tx FRM = Rx FRM */
+#define SND_SOC_DAIFMT_ASYNC (1 << 5) /* Tx FRM ~ Rx FRM */
+
+/*
+ * TDM
+ *
+ * Time Division Multiplexing. Allows PCM data to be multplexed with other
+ * data on the DAI.
+ */
+#define SND_SOC_DAIFMT_TDM (1 << 6)
+
+/*
+ * DAI hardware signal inversions.
+ *
+ * Specifies whether the DAI can also support inverted clocks for the specified
+ * format.
+ */
+#define SND_SOC_DAIFMT_NB_NF (0 << 8) /* normal bit clock + frame */
+#define SND_SOC_DAIFMT_NB_IF (1 << 8) /* normal bclk + inv frm */
+#define SND_SOC_DAIFMT_IB_NF (2 << 8) /* invert bclk + nor frm */
+#define SND_SOC_DAIFMT_IB_IF (3 << 8) /* invert bclk + frm */
+
+/*
+ * DAI hardware clock masters.
+ *
+ * This is wrt the codec, the inverse is true for the interface
+ * i.e. if the codec is clk and frm master then the interface is
+ * clk and frame slave.
+ */
+#define SND_SOC_DAIFMT_CBM_CFM (0 << 12) /* codec clk & frm master */
+#define SND_SOC_DAIFMT_CBS_CFM (1 << 12) /* codec clk slave & frm master */
+#define SND_SOC_DAIFMT_CBM_CFS (2 << 12) /* codec clk master & frame slave */
+#define SND_SOC_DAIFMT_CBS_CFS (3 << 12) /* codec clk & frm slave */
+
+#define SND_SOC_DAIFMT_FORMAT_MASK 0x000f
+#define SND_SOC_DAIFMT_CLOCK_MASK 0x00f0
+#define SND_SOC_DAIFMT_INV_MASK 0x0f00
+#define SND_SOC_DAIFMT_MASTER_MASK 0xf000
+
+/*
+ * Master Clock Directions
+ */
+#define SND_SOC_CLOCK_IN 0
+#define SND_SOC_CLOCK_OUT 1
+
+struct snd_soc_dai_ops;
+struct snd_soc_dai;
+struct snd_ac97_bus_ops;
+
+/* Digital Audio Interface registration */
+int snd_soc_register_dai(struct snd_soc_dai *dai);
+void snd_soc_unregister_dai(struct snd_soc_dai *dai);
+int snd_soc_register_dais(struct snd_soc_dai *dai, size_t count);
+void snd_soc_unregister_dais(struct snd_soc_dai *dai, size_t count);
+
+/* Digital Audio Interface clocking API.*/
+int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
+ unsigned int freq, int dir);
+
+int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai,
+ int div_id, int div);
+
+int snd_soc_dai_set_pll(struct snd_soc_dai *dai,
+ int pll_id, unsigned int freq_in, unsigned int freq_out);
+
+/* Digital Audio interface formatting */
+int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt);
+
+int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
+ unsigned int mask, int slots);
+
+int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate);
+
+/* Digital Audio Interface mute */
+int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute);
+
+/*
+ * Digital Audio Interface.
+ *
+ * Describes the Digital Audio Interface in terms of it's ALSA, DAI and AC97
+ * operations an capabilities. Codec and platfom drivers will register a this
+ * structure for every DAI they have.
+ *
+ * This structure covers the clocking, formating and ALSA operations for each
+ * interface a
+ */
+struct snd_soc_dai_ops {
+ /*
+ * DAI clocking configuration, all optional.
+ * Called by soc_card drivers, normally in their hw_params.
+ */
+ int (*set_sysclk)(struct snd_soc_dai *dai,
+ int clk_id, unsigned int freq, int dir);
+ int (*set_pll)(struct snd_soc_dai *dai,
+ int pll_id, unsigned int freq_in, unsigned int freq_out);
+ int (*set_clkdiv)(struct snd_soc_dai *dai, int div_id, int div);
+
+ /*
+ * DAI format configuration
+ * Called by soc_card drivers, normally in their hw_params.
+ */
+ int (*set_fmt)(struct snd_soc_dai *dai, unsigned int fmt);
+ int (*set_tdm_slot)(struct snd_soc_dai *dai,
+ unsigned int mask, int slots);
+ int (*set_tristate)(struct snd_soc_dai *dai, int tristate);
+
+ /*
+ * DAI digital mute - optional.
+ * Called by soc-core to minimise any pops.
+ */
+ int (*digital_mute)(struct snd_soc_dai *dai, int mute);
+
+ /*
+ * ALSA PCM audio operations - all optional.
+ * Called by soc-core during audio PCM operations.
+ */
+ int (*startup)(struct snd_pcm_substream *,
+ struct snd_soc_dai *);
+ void (*shutdown)(struct snd_pcm_substream *,
+ struct snd_soc_dai *);
+ int (*hw_params)(struct snd_pcm_substream *,
+ struct snd_pcm_hw_params *, struct snd_soc_dai *);
+ int (*hw_free)(struct snd_pcm_substream *,
+ struct snd_soc_dai *);
+ int (*prepare)(struct snd_pcm_substream *,
+ struct snd_soc_dai *);
+ int (*trigger)(struct snd_pcm_substream *, int,
+ struct snd_soc_dai *);
+};
+
+/*
+ * Digital Audio Interface runtime data.
+ *
+ * Holds runtime data for a DAI.
+ */
+struct snd_soc_dai {
+ /* DAI description */
+ char *name;
+ unsigned int id;
+ int ac97_control;
+
+ struct device *dev;
+
+ /* DAI callbacks */
+ int (*probe)(struct platform_device *pdev,
+ struct snd_soc_dai *dai);
+ void (*remove)(struct platform_device *pdev,
+ struct snd_soc_dai *dai);
+ int (*suspend)(struct snd_soc_dai *dai);
+ int (*resume)(struct snd_soc_dai *dai);
+
+ /* ops */
+ struct snd_soc_dai_ops ops;
+
+ /* DAI capabilities */
+ struct snd_soc_pcm_stream capture;
+ struct snd_soc_pcm_stream playback;
+
+ /* DAI runtime info */
+ struct snd_pcm_runtime *runtime;
+ struct snd_soc_codec *codec;
+ unsigned int active;
+ unsigned char pop_wait:1;
+ void *dma_data;
+
+ /* DAI private data */
+ void *private_data;
+
+ /* parent codec/platform */
+ union {
+ struct snd_soc_codec *codec;
+ struct snd_soc_platform *platform;
+ };
+
+ struct list_head list;
+};
+
+#endif
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h
index ca699a3017f..7ee2f70ca42 100644
--- a/include/sound/soc-dapm.h
+++ b/include/sound/soc-dapm.h
@@ -221,8 +221,6 @@ int snd_soc_dapm_new_controls(struct snd_soc_codec *codec,
int num);
/* dapm path setup */
-int __deprecated snd_soc_dapm_connect_input(struct snd_soc_codec *codec,
- const char *sink_name, const char *control_name, const char *src_name);
int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec);
void snd_soc_dapm_free(struct snd_soc_device *socdev);
int snd_soc_dapm_add_routes(struct snd_soc_codec *codec,
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 5e0189876af..f86e455d382 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -21,8 +21,6 @@
#include <sound/control.h>
#include <sound/ac97_codec.h>
-#define SND_SOC_VERSION "0.13.2"
-
/*
* Convenience kcontrol builders
*/
@@ -145,105 +143,31 @@ enum snd_soc_bias_level {
SND_SOC_BIAS_OFF,
};
-/*
- * Digital Audio Interface (DAI) types
- */
-#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
- */
-#define SND_SOC_DAIFMT_I2S 0 /* I2S mode */
-#define SND_SOC_DAIFMT_RIGHT_J 1 /* Right justified mode */
-#define SND_SOC_DAIFMT_LEFT_J 2 /* Left Justified mode */
-#define SND_SOC_DAIFMT_DSP_A 3 /* L data msb after FRM or LRC */
-#define SND_SOC_DAIFMT_DSP_B 4 /* L data msb during FRM or LRC */
-#define SND_SOC_DAIFMT_AC97 5 /* AC97 */
-
-#define SND_SOC_DAIFMT_MSB SND_SOC_DAIFMT_LEFT_J
-#define SND_SOC_DAIFMT_LSB SND_SOC_DAIFMT_RIGHT_J
-
-/*
- * DAI Gating
- */
-#define SND_SOC_DAIFMT_CONT (0 << 4) /* continuous clock */
-#define SND_SOC_DAIFMT_GATED (1 << 4) /* clock is gated when not Tx/Rx */
-
-/*
- * DAI Sync
- * Synchronous LR (Left Right) clocks and Frame signals.
- */
-#define SND_SOC_DAIFMT_SYNC (0 << 5) /* Tx FRM = Rx FRM */
-#define SND_SOC_DAIFMT_ASYNC (1 << 5) /* Tx FRM ~ Rx FRM */
-
-/*
- * TDM
- */
-#define SND_SOC_DAIFMT_TDM (1 << 6)
-
-/*
- * DAI hardware signal inversions
- */
-#define SND_SOC_DAIFMT_NB_NF (0 << 8) /* normal bclk + frm */
-#define SND_SOC_DAIFMT_NB_IF (1 << 8) /* normal bclk + inv frm */
-#define SND_SOC_DAIFMT_IB_NF (2 << 8) /* invert bclk + nor frm */
-#define SND_SOC_DAIFMT_IB_IF (3 << 8) /* invert bclk + frm */
-
-/*
- * DAI hardware clock masters
- * This is wrt the codec, the inverse is true for the interface
- * i.e. if the codec is clk and frm master then the interface is
- * clk and frame slave.
- */
-#define SND_SOC_DAIFMT_CBM_CFM (0 << 12) /* codec clk & frm master */
-#define SND_SOC_DAIFMT_CBS_CFM (1 << 12) /* codec clk slave & frm master */
-#define SND_SOC_DAIFMT_CBM_CFS (2 << 12) /* codec clk master & frame slave */
-#define SND_SOC_DAIFMT_CBS_CFS (3 << 12) /* codec clk & frm slave */
-
-#define SND_SOC_DAIFMT_FORMAT_MASK 0x000f
-#define SND_SOC_DAIFMT_CLOCK_MASK 0x00f0
-#define SND_SOC_DAIFMT_INV_MASK 0x0f00
-#define SND_SOC_DAIFMT_MASTER_MASK 0xf000
-
-
-/*
- * Master Clock Directions
- */
-#define SND_SOC_CLOCK_IN 0
-#define SND_SOC_CLOCK_OUT 1
-
-/*
- * AC97 codec ID's bitmask
- */
-#define SND_SOC_DAI_AC97_ID0 (1 << 0)
-#define SND_SOC_DAI_AC97_ID1 (1 << 1)
-#define SND_SOC_DAI_AC97_ID2 (1 << 2)
-#define SND_SOC_DAI_AC97_ID3 (1 << 3)
-
struct snd_soc_device;
struct snd_soc_pcm_stream;
struct snd_soc_ops;
struct snd_soc_dai_mode;
struct snd_soc_pcm_runtime;
struct snd_soc_dai;
+struct snd_soc_platform;
struct snd_soc_codec;
-struct snd_soc_machine_config;
struct soc_enum;
struct snd_soc_ac97_ops;
-struct snd_soc_clock_info;
typedef int (*hw_write_t)(void *,const char* ,int);
typedef int (*hw_read_t)(void *,char* ,int);
extern struct snd_ac97_bus_ops soc_ac97_ops;
+int snd_soc_register_platform(struct snd_soc_platform *platform);
+void snd_soc_unregister_platform(struct snd_soc_platform *platform);
+int snd_soc_register_codec(struct snd_soc_codec *codec);
+void snd_soc_unregister_codec(struct snd_soc_codec *codec);
+
/* pcm <-> DAI connect */
void snd_soc_free_pcms(struct snd_soc_device *socdev);
int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid);
-int snd_soc_register_card(struct snd_soc_device *socdev);
+int snd_soc_init_card(struct snd_soc_device *socdev);
/* set runtime hw params */
int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream,
@@ -263,27 +187,6 @@ int snd_soc_new_ac97_codec(struct snd_soc_codec *codec,
struct snd_ac97_bus_ops *ops, int num);
void snd_soc_free_ac97_codec(struct snd_soc_codec *codec);
-/* Digital Audio Interface clocking API.*/
-int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
- unsigned int freq, int dir);
-
-int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai,
- int div_id, int div);
-
-int snd_soc_dai_set_pll(struct snd_soc_dai *dai,
- int pll_id, unsigned int freq_in, unsigned int freq_out);
-
-/* Digital Audio interface formatting */
-int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt);
-
-int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
- unsigned int mask, int slots);
-
-int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate);
-
-/* Digital Audio Interface mute */
-int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute);
-
/*
*Controls
*/
@@ -341,66 +244,14 @@ struct snd_soc_ops {
int (*trigger)(struct snd_pcm_substream *, int);
};
-/* ASoC DAI ops */
-struct snd_soc_dai_ops {
- /* DAI clocking configuration */
- int (*set_sysclk)(struct snd_soc_dai *dai,
- int clk_id, unsigned int freq, int dir);
- int (*set_pll)(struct snd_soc_dai *dai,
- int pll_id, unsigned int freq_in, unsigned int freq_out);
- int (*set_clkdiv)(struct snd_soc_dai *dai, int div_id, int div);
-
- /* DAI format configuration */
- int (*set_fmt)(struct snd_soc_dai *dai, unsigned int fmt);
- int (*set_tdm_slot)(struct snd_soc_dai *dai,
- unsigned int mask, int slots);
- int (*set_tristate)(struct snd_soc_dai *dai, int tristate);
-
- /* digital mute */
- int (*digital_mute)(struct snd_soc_dai *dai, int mute);
-};
-
-/* SoC DAI (Digital Audio Interface) */
-struct snd_soc_dai {
- /* DAI description */
- char *name;
- unsigned int id;
- unsigned char type;
-
- /* DAI callbacks */
- int (*probe)(struct platform_device *pdev,
- struct snd_soc_dai *dai);
- void (*remove)(struct platform_device *pdev,
- struct snd_soc_dai *dai);
- int (*suspend)(struct platform_device *pdev,
- struct snd_soc_dai *dai);
- int (*resume)(struct platform_device *pdev,
- struct snd_soc_dai *dai);
-
- /* ops */
- struct snd_soc_ops ops;
- struct snd_soc_dai_ops dai_ops;
-
- /* DAI capabilities */
- struct snd_soc_pcm_stream capture;
- struct snd_soc_pcm_stream playback;
-
- /* DAI runtime info */
- struct snd_pcm_runtime *runtime;
- struct snd_soc_codec *codec;
- unsigned int active;
- unsigned char pop_wait:1;
- void *dma_data;
-
- /* DAI private data */
- void *private_data;
-};
-
/* SoC Audio Codec */
struct snd_soc_codec {
char *name;
struct module *owner;
struct mutex mutex;
+ struct device *dev;
+
+ struct list_head list;
/* callbacks */
int (*set_bias_level)(struct snd_soc_codec *,
@@ -426,6 +277,7 @@ struct snd_soc_codec {
short reg_cache_step;
/* dapm */
+ u32 pop_time;
struct list_head dapm_widgets;
struct list_head dapm_paths;
enum snd_soc_bias_level bias_level;
@@ -435,6 +287,11 @@ struct snd_soc_codec {
/* codec DAI's */
struct snd_soc_dai *dai;
unsigned int num_dai;
+
+#ifdef CONFIG_DEBUG_FS
+ struct dentry *debugfs_reg;
+ struct dentry *debugfs_pop_time;
+#endif
};
/* codec device */
@@ -448,13 +305,12 @@ struct snd_soc_codec_device {
/* SoC platform interface */
struct snd_soc_platform {
char *name;
+ struct list_head list;
int (*probe)(struct platform_device *pdev);
int (*remove)(struct platform_device *pdev);
- int (*suspend)(struct platform_device *pdev,
- struct snd_soc_dai *dai);
- int (*resume)(struct platform_device *pdev,
- struct snd_soc_dai *dai);
+ int (*suspend)(struct snd_soc_dai *dai);
+ int (*resume)(struct snd_soc_dai *dai);
/* pcm creation and destruction */
int (*pcm_new)(struct snd_card *, struct snd_soc_dai *,
@@ -484,9 +340,14 @@ struct snd_soc_dai_link {
struct snd_pcm *pcm;
};
-/* SoC machine */
-struct snd_soc_machine {
+/* SoC card */
+struct snd_soc_card {
char *name;
+ struct device *dev;
+
+ struct list_head list;
+
+ int instantiated;
int (*probe)(struct platform_device *pdev);
int (*remove)(struct platform_device *pdev);
@@ -499,23 +360,26 @@ struct snd_soc_machine {
int (*resume_post)(struct platform_device *pdev);
/* callbacks */
- int (*set_bias_level)(struct snd_soc_machine *,
+ int (*set_bias_level)(struct snd_soc_card *,
enum snd_soc_bias_level level);
/* CPU <--> Codec DAI links */
struct snd_soc_dai_link *dai_link;
int num_links;
+
+ struct snd_soc_device *socdev;
+
+ struct snd_soc_platform *platform;
+ struct delayed_work delayed_work;
+ struct work_struct deferred_resume_work;
};
/* SoC Device - the audio subsystem */
struct snd_soc_device {
struct device *dev;
- struct snd_soc_machine *machine;
- struct snd_soc_platform *platform;
+ struct snd_soc_card *card;
struct snd_soc_codec *codec;
struct snd_soc_codec_device *codec_dev;
- struct delayed_work delayed_work;
- struct work_struct deferred_resume_work;
void *codec_data;
};
@@ -542,4 +406,6 @@ struct soc_enum {
void *dapm;
};
+#include <sound/soc-dai.h>
+
#endif
diff --git a/include/sound/uda134x.h b/include/sound/uda134x.h
new file mode 100644
index 00000000000..475ef8bb7dc
--- /dev/null
+++ b/include/sound/uda134x.h
@@ -0,0 +1,26 @@
+/*
+ * uda134x.h -- UDA134x ALSA SoC Codec driver
+ *
+ * Copyright 2007 Dension Audio Systems Ltd.
+ * Author: Zoltan Devai
+ *
+ * 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 _UDA134X_H
+#define _UDA134X_H
+
+#include <sound/l3.h>
+
+struct uda134x_platform_data {
+ struct l3_pins l3;
+ void (*power) (int);
+ int model;
+#define UDA134X_UDA1340 1
+#define UDA134X_UDA1341 2
+#define UDA134X_UDA1344 3
+};
+
+#endif /* _UDA134X_H */
diff --git a/include/sound/version.h b/include/sound/version.h
index 4aafeda8863..2b48237e23b 100644
--- a/include/sound/version.h
+++ b/include/sound/version.h
@@ -1,3 +1,3 @@
/* include/version.h */
-#define CONFIG_SND_VERSION "1.0.18rc3"
+#define CONFIG_SND_VERSION "1.0.18a"
#define CONFIG_SND_DATE ""
diff --git a/include/video/atmel_lcdc.h b/include/video/atmel_lcdc.h
index 6ad87f48599..0c864db1a46 100644
--- a/include/video/atmel_lcdc.h
+++ b/include/video/atmel_lcdc.h
@@ -38,7 +38,7 @@ struct atmel_lcdfb_info {
spinlock_t lock;
struct fb_info *info;
void __iomem *mmio;
- unsigned long irq_base;
+ int irq_base;
struct work_struct task;
unsigned int guard_time;
diff --git a/include/video/radeon.h b/include/video/radeon.h
index d5dcaf154ba..1cd09cc5b16 100644
--- a/include/video/radeon.h
+++ b/include/video/radeon.h
@@ -525,9 +525,6 @@
#define CRTC_DISPLAY_DIS (1 << 10)
#define CRTC_CRT_ON (1 << 15)
-/* DSTCACHE_MODE bits constants */
-#define RB2D_DC_AUTOFLUSH_ENABLE (1 << 8)
-#define RB2D_DC_DC_DISABLE_IGNORE_PE (1 << 17)
/* DSTCACHE_CTLSTAT bit constants */
#define RB2D_DC_FLUSH_2D (1 << 0)
@@ -869,10 +866,15 @@
#define GMC_DST_16BPP_YVYU422 0x00000c00
#define GMC_DST_32BPP_AYUV444 0x00000e00
#define GMC_DST_16BPP_ARGB4444 0x00000f00
+#define GMC_SRC_MONO 0x00000000
+#define GMC_SRC_MONO_LBKGD 0x00001000
+#define GMC_SRC_DSTCOLOR 0x00003000
#define GMC_BYTE_ORDER_MSB_TO_LSB 0x00000000
#define GMC_BYTE_ORDER_LSB_TO_MSB 0x00004000
#define GMC_DP_CONVERSION_TEMP_9300 0x00008000
#define GMC_DP_CONVERSION_TEMP_6500 0x00000000
+#define GMC_DP_SRC_RECT 0x02000000
+#define GMC_DP_SRC_HOST 0x03000000
#define GMC_DP_SRC_HOST_BYTEALIGN 0x04000000
#define GMC_3D_FCN_EN_CLR 0x00000000
#define GMC_3D_FCN_EN_SET 0x08000000
@@ -883,9 +885,6 @@
#define GMC_WRITE_MASK_LEAVE 0x00000000
#define GMC_WRITE_MASK_SET 0x40000000
#define GMC_CLR_CMP_CNTL_DIS (1 << 28)
-#define GMC_SRC_DATATYPE_MASK (3 << 12)
-#define GMC_SRC_DATATYPE_MONO_FG_BG (0 << 12)
-#define GMC_SRC_DATATYPE_MONO_FG_LA (1 << 12)
#define GMC_SRC_DATATYPE_COLOR (3 << 12)
#define ROP3_S 0x00cc0000
#define ROP3_SRCCOPY 0x00cc0000
@@ -894,7 +893,6 @@
#define DP_SRC_SOURCE_MASK (7 << 24)
#define GMC_BRUSH_NONE (15 << 4)
#define DP_SRC_SOURCE_MEMORY (2 << 24)
-#define DP_SRC_SOURCE_HOST_DATA (3 << 24)
#define GMC_BRUSH_SOLIDCOLOR 0x000000d0
/* DP_MIX bit constants */
@@ -980,12 +978,6 @@
#define DISP_PWR_MAN_TV_ENABLE_RST (1 << 25)
#define DISP_PWR_MAN_AUTO_PWRUP_EN (1 << 26)
-/* RBBM_GUICNTL constants */
-#define RBBM_GUICNTL_HOST_DATA_SWAP_NONE (0 << 0)
-#define RBBM_GUICNTL_HOST_DATA_SWAP_16BIT (1 << 0)
-#define RBBM_GUICNTL_HOST_DATA_SWAP_32BIT (2 << 0)
-#define RBBM_GUICNTL_HOST_DATA_SWAP_HDW (3 << 0)
-
/* masks */
#define CONFIG_MEMSIZE_MASK 0x1f000000
diff --git a/init/Kconfig b/init/Kconfig
index 86b00c53fad..f763762d544 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -354,7 +354,7 @@ config RT_GROUP_SCHED
setting below. If enabled, it will also make it impossible to
schedule realtime tasks for non-root users until you allocate
realtime bandwidth for them.
- See Documentation/sched-rt-group.txt for more information.
+ See Documentation/scheduler/sched-rt-group.txt for more information.
choice
depends on GROUP_SCHED
@@ -771,8 +771,7 @@ config SLAB
help
The regular slab allocator that is established and known to work
well in all environments. It organizes cache hot objects in
- per cpu and per node queues. SLAB is the default choice for
- a slab allocator.
+ per cpu and per node queues.
config SLUB
bool "SLUB (Unqueued Allocator)"
@@ -781,7 +780,8 @@ config SLUB
instead of managing queues of cached objects (SLAB approach).
Per cpu caching is realized using slabs of objects instead
of queues of objects. SLUB can use memory efficiently
- and has enhanced diagnostics.
+ and has enhanced diagnostics. SLUB is the default choice for
+ a slab allocator.
config SLOB
depends on EMBEDDED
diff --git a/ipc/util.c b/ipc/util.c
index 49b3ea615dc..361fd1c96fc 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -266,9 +266,17 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
if (ids->in_use >= size)
return -ENOSPC;
+ spin_lock_init(&new->lock);
+ new->deleted = 0;
+ rcu_read_lock();
+ spin_lock(&new->lock);
+
err = idr_get_new(&ids->ipcs_idr, new, &id);
- if (err)
+ if (err) {
+ spin_unlock(&new->lock);
+ rcu_read_unlock();
return err;
+ }
ids->in_use++;
@@ -280,10 +288,6 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
ids->seq = 0;
new->id = ipc_buildid(id, new->seq);
- spin_lock_init(&new->lock);
- new->deleted = 0;
- rcu_read_lock();
- spin_lock(&new->lock);
return id;
}
diff --git a/kernel/Makefile b/kernel/Makefile
index 9a3ec66a9d8..19fad003b19 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -11,8 +11,6 @@ obj-y = sched.o fork.o exec_domain.o panic.o printk.o \
hrtimer.o rwsem.o nsproxy.o srcu.o semaphore.o \
notifier.o ksysfs.o pm_qos_params.o sched_clock.o
-CFLAGS_REMOVE_sched.o = -mno-spe
-
ifdef CONFIG_FUNCTION_TRACER
# Do not trace debug files and internal ftrace files
CFLAGS_REMOVE_lockdep.o = -pg
@@ -21,7 +19,7 @@ CFLAGS_REMOVE_mutex-debug.o = -pg
CFLAGS_REMOVE_rtmutex-debug.o = -pg
CFLAGS_REMOVE_cgroup-debug.o = -pg
CFLAGS_REMOVE_sched_clock.o = -pg
-CFLAGS_REMOVE_sched.o = -mno-spe -pg
+CFLAGS_REMOVE_sched.o = -pg
endif
obj-$(CONFIG_FREEZER) += freezer.o
diff --git a/kernel/audit.c b/kernel/audit.c
index 4414e93d875..ce6d8ea3131 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -61,8 +61,11 @@
#include "audit.h"
-/* No auditing will take place until audit_initialized != 0.
+/* No auditing will take place until audit_initialized == AUDIT_INITIALIZED.
* (Initialization happens after skb_init is called.) */
+#define AUDIT_DISABLED -1
+#define AUDIT_UNINITIALIZED 0
+#define AUDIT_INITIALIZED 1
static int audit_initialized;
#define AUDIT_OFF 0
@@ -965,6 +968,9 @@ static int __init audit_init(void)
{
int i;
+ if (audit_initialized == AUDIT_DISABLED)
+ return 0;
+
printk(KERN_INFO "audit: initializing netlink socket (%s)\n",
audit_default ? "enabled" : "disabled");
audit_sock = netlink_kernel_create(&init_net, NETLINK_AUDIT, 0,
@@ -976,7 +982,7 @@ static int __init audit_init(void)
skb_queue_head_init(&audit_skb_queue);
skb_queue_head_init(&audit_skb_hold_queue);
- audit_initialized = 1;
+ audit_initialized = AUDIT_INITIALIZED;
audit_enabled = audit_default;
audit_ever_enabled |= !!audit_default;
@@ -999,13 +1005,21 @@ __initcall(audit_init);
static int __init audit_enable(char *str)
{
audit_default = !!simple_strtol(str, NULL, 0);
- printk(KERN_INFO "audit: %s%s\n",
- audit_default ? "enabled" : "disabled",
- audit_initialized ? "" : " (after initialization)");
- if (audit_initialized) {
+ if (!audit_default)
+ audit_initialized = AUDIT_DISABLED;
+
+ printk(KERN_INFO "audit: %s", audit_default ? "enabled" : "disabled");
+
+ if (audit_initialized == AUDIT_INITIALIZED) {
audit_enabled = audit_default;
audit_ever_enabled |= !!audit_default;
+ } else if (audit_initialized == AUDIT_UNINITIALIZED) {
+ printk(" (after initialization)");
+ } else {
+ printk(" (until reboot)");
}
+ printk("\n");
+
return 1;
}
@@ -1107,9 +1121,7 @@ unsigned int audit_serial(void)
static inline void audit_get_stamp(struct audit_context *ctx,
struct timespec *t, unsigned int *serial)
{
- if (ctx)
- auditsc_get_stamp(ctx, t, serial);
- else {
+ if (!ctx || !auditsc_get_stamp(ctx, t, serial)) {
*t = CURRENT_TIME;
*serial = audit_serial();
}
@@ -1146,7 +1158,7 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
int reserve;
unsigned long timeout_start = jiffies;
- if (!audit_initialized)
+ if (audit_initialized != AUDIT_INITIALIZED)
return NULL;
if (unlikely(audit_filter_type(type)))
diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c
index 8ba0e0d934f..8b509441f49 100644
--- a/kernel/audit_tree.c
+++ b/kernel/audit_tree.c
@@ -24,6 +24,7 @@ struct audit_chunk {
struct list_head trees; /* with root here */
int dead;
int count;
+ atomic_long_t refs;
struct rcu_head head;
struct node {
struct list_head list;
@@ -56,7 +57,8 @@ static LIST_HEAD(prune_list);
* tree is refcounted; one reference for "some rules on rules_list refer to
* it", one for each chunk with pointer to it.
*
- * chunk is refcounted by embedded inotify_watch.
+ * chunk is refcounted by embedded inotify_watch + .refs (non-zero refcount
+ * of watch contributes 1 to .refs).
*
* node.index allows to get from node.list to containing chunk.
* MSB of that sucker is stolen to mark taggings that we might have to
@@ -121,6 +123,7 @@ static struct audit_chunk *alloc_chunk(int count)
INIT_LIST_HEAD(&chunk->hash);
INIT_LIST_HEAD(&chunk->trees);
chunk->count = count;
+ atomic_long_set(&chunk->refs, 1);
for (i = 0; i < count; i++) {
INIT_LIST_HEAD(&chunk->owners[i].list);
chunk->owners[i].index = i;
@@ -129,9 +132,8 @@ static struct audit_chunk *alloc_chunk(int count)
return chunk;
}
-static void __free_chunk(struct rcu_head *rcu)
+static void free_chunk(struct audit_chunk *chunk)
{
- struct audit_chunk *chunk = container_of(rcu, struct audit_chunk, head);
int i;
for (i = 0; i < chunk->count; i++) {
@@ -141,14 +143,16 @@ static void __free_chunk(struct rcu_head *rcu)
kfree(chunk);
}
-static inline void free_chunk(struct audit_chunk *chunk)
+void audit_put_chunk(struct audit_chunk *chunk)
{
- call_rcu(&chunk->head, __free_chunk);
+ if (atomic_long_dec_and_test(&chunk->refs))
+ free_chunk(chunk);
}
-void audit_put_chunk(struct audit_chunk *chunk)
+static void __put_chunk(struct rcu_head *rcu)
{
- put_inotify_watch(&chunk->watch);
+ struct audit_chunk *chunk = container_of(rcu, struct audit_chunk, head);
+ audit_put_chunk(chunk);
}
enum {HASH_SIZE = 128};
@@ -176,7 +180,7 @@ struct audit_chunk *audit_tree_lookup(const struct inode *inode)
list_for_each_entry_rcu(p, list, hash) {
if (p->watch.inode == inode) {
- get_inotify_watch(&p->watch);
+ atomic_long_inc(&p->refs);
return p;
}
}
@@ -194,17 +198,49 @@ int audit_tree_match(struct audit_chunk *chunk, struct audit_tree *tree)
/* tagging and untagging inodes with trees */
-static void untag_chunk(struct audit_chunk *chunk, struct node *p)
+static struct audit_chunk *find_chunk(struct node *p)
+{
+ int index = p->index & ~(1U<<31);
+ p -= index;
+ return container_of(p, struct audit_chunk, owners[0]);
+}
+
+static void untag_chunk(struct node *p)
{
+ struct audit_chunk *chunk = find_chunk(p);
struct audit_chunk *new;
struct audit_tree *owner;
int size = chunk->count - 1;
int i, j;
+ if (!pin_inotify_watch(&chunk->watch)) {
+ /*
+ * Filesystem is shutting down; all watches are getting
+ * evicted, just take it off the node list for this
+ * tree and let the eviction logics take care of the
+ * rest.
+ */
+ owner = p->owner;
+ if (owner->root == chunk) {
+ list_del_init(&owner->same_root);
+ owner->root = NULL;
+ }
+ list_del_init(&p->list);
+ p->owner = NULL;
+ put_tree(owner);
+ return;
+ }
+
+ spin_unlock(&hash_lock);
+
+ /*
+ * pin_inotify_watch() succeeded, so the watch won't go away
+ * from under us.
+ */
mutex_lock(&chunk->watch.inode->inotify_mutex);
if (chunk->dead) {
mutex_unlock(&chunk->watch.inode->inotify_mutex);
- return;
+ goto out;
}
owner = p->owner;
@@ -221,7 +257,7 @@ static void untag_chunk(struct audit_chunk *chunk, struct node *p)
inotify_evict_watch(&chunk->watch);
mutex_unlock(&chunk->watch.inode->inotify_mutex);
put_inotify_watch(&chunk->watch);
- return;
+ goto out;
}
new = alloc_chunk(size);
@@ -263,7 +299,7 @@ static void untag_chunk(struct audit_chunk *chunk, struct node *p)
inotify_evict_watch(&chunk->watch);
mutex_unlock(&chunk->watch.inode->inotify_mutex);
put_inotify_watch(&chunk->watch);
- return;
+ goto out;
Fallback:
// do the best we can
@@ -277,6 +313,9 @@ Fallback:
put_tree(owner);
spin_unlock(&hash_lock);
mutex_unlock(&chunk->watch.inode->inotify_mutex);
+out:
+ unpin_inotify_watch(&chunk->watch);
+ spin_lock(&hash_lock);
}
static int create_chunk(struct inode *inode, struct audit_tree *tree)
@@ -387,13 +426,6 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree)
return 0;
}
-static struct audit_chunk *find_chunk(struct node *p)
-{
- int index = p->index & ~(1U<<31);
- p -= index;
- return container_of(p, struct audit_chunk, owners[0]);
-}
-
static void kill_rules(struct audit_tree *tree)
{
struct audit_krule *rule, *next;
@@ -431,17 +463,10 @@ static void prune_one(struct audit_tree *victim)
spin_lock(&hash_lock);
while (!list_empty(&victim->chunks)) {
struct node *p;
- struct audit_chunk *chunk;
p = list_entry(victim->chunks.next, struct node, list);
- chunk = find_chunk(p);
- get_inotify_watch(&chunk->watch);
- spin_unlock(&hash_lock);
-
- untag_chunk(chunk, p);
- put_inotify_watch(&chunk->watch);
- spin_lock(&hash_lock);
+ untag_chunk(p);
}
spin_unlock(&hash_lock);
put_tree(victim);
@@ -469,7 +494,6 @@ static void trim_marked(struct audit_tree *tree)
while (!list_empty(&tree->chunks)) {
struct node *node;
- struct audit_chunk *chunk;
node = list_entry(tree->chunks.next, struct node, list);
@@ -477,14 +501,7 @@ static void trim_marked(struct audit_tree *tree)
if (!(node->index & (1U<<31)))
break;
- chunk = find_chunk(node);
- get_inotify_watch(&chunk->watch);
- spin_unlock(&hash_lock);
-
- untag_chunk(chunk, node);
-
- put_inotify_watch(&chunk->watch);
- spin_lock(&hash_lock);
+ untag_chunk(node);
}
if (!tree->root && !tree->goner) {
tree->goner = 1;
@@ -878,7 +895,7 @@ static void handle_event(struct inotify_watch *watch, u32 wd, u32 mask,
static void destroy_watch(struct inotify_watch *watch)
{
struct audit_chunk *chunk = container_of(watch, struct audit_chunk, watch);
- free_chunk(chunk);
+ call_rcu(&chunk->head, __put_chunk);
}
static const struct inotify_operations rtree_inotify_ops = {
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index b7d354e2b0e..9fd85a4640a 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -1094,8 +1094,8 @@ static void audit_inotify_unregister(struct list_head *in_list)
list_for_each_entry_safe(p, n, in_list, ilist) {
list_del(&p->ilist);
inotify_rm_watch(audit_ih, &p->wdata);
- /* the put matching the get in audit_do_del_rule() */
- put_inotify_watch(&p->wdata);
+ /* the unpin matching the pin in audit_do_del_rule() */
+ unpin_inotify_watch(&p->wdata);
}
}
@@ -1389,9 +1389,13 @@ static inline int audit_del_rule(struct audit_entry *entry,
/* Put parent on the inotify un-registration
* list. Grab a reference before releasing
* audit_filter_mutex, to be released in
- * audit_inotify_unregister(). */
- list_add(&parent->ilist, &inotify_list);
- get_inotify_watch(&parent->wdata);
+ * audit_inotify_unregister().
+ * If filesystem is going away, just leave
+ * the sucker alone, eviction will take
+ * care of it.
+ */
+ if (pin_inotify_watch(&parent->wdata))
+ list_add(&parent->ilist, &inotify_list);
}
}
}
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index cf5bc2f5f9c..2a3f0afc4d2 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -1459,7 +1459,6 @@ void audit_free(struct task_struct *tsk)
/**
* audit_syscall_entry - fill in an audit record at syscall entry
- * @tsk: task being audited
* @arch: architecture type
* @major: major syscall type (function)
* @a1: additional syscall register 1
@@ -1548,9 +1547,25 @@ void audit_syscall_entry(int arch, int major,
context->ppid = 0;
}
+void audit_finish_fork(struct task_struct *child)
+{
+ struct audit_context *ctx = current->audit_context;
+ struct audit_context *p = child->audit_context;
+ if (!p || !ctx || !ctx->auditable)
+ return;
+ p->arch = ctx->arch;
+ p->major = ctx->major;
+ memcpy(p->argv, ctx->argv, sizeof(ctx->argv));
+ p->ctime = ctx->ctime;
+ p->dummy = ctx->dummy;
+ p->auditable = ctx->auditable;
+ p->in_syscall = ctx->in_syscall;
+ p->filterkey = kstrdup(ctx->filterkey, GFP_KERNEL);
+ p->ppid = current->pid;
+}
+
/**
* audit_syscall_exit - deallocate audit context after a system call
- * @tsk: task being audited
* @valid: success/failure flag
* @return_code: syscall return value
*
@@ -1942,15 +1957,18 @@ EXPORT_SYMBOL_GPL(__audit_inode_child);
*
* Also sets the context as auditable.
*/
-void auditsc_get_stamp(struct audit_context *ctx,
+int auditsc_get_stamp(struct audit_context *ctx,
struct timespec *t, unsigned int *serial)
{
+ if (!ctx->in_syscall)
+ return 0;
if (!ctx->serial)
ctx->serial = audit_serial();
t->tv_sec = ctx->ctime.tv_sec;
t->tv_nsec = ctx->ctime.tv_nsec;
*serial = ctx->serial;
ctx->auditable = 1;
+ return 1;
}
/* global counter which is incremented every time something logs in */
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 358e77564e6..2606d0fb4e5 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -702,7 +702,7 @@ static int rebind_subsystems(struct cgroupfs_root *root,
* any child cgroups exist. This is theoretically supportable
* but involves complex error handling, so it's being left until
* later */
- if (!list_empty(&cgrp->children))
+ if (root->number_of_cgroups > 1)
return -EBUSY;
/* Process each subsystem */
@@ -1024,7 +1024,7 @@ static int cgroup_get_sb(struct file_system_type *fs_type,
if (ret == -EBUSY) {
mutex_unlock(&cgroup_mutex);
mutex_unlock(&inode->i_mutex);
- goto drop_new_super;
+ goto free_cg_links;
}
/* EBUSY should be the only error here */
@@ -1073,10 +1073,11 @@ static int cgroup_get_sb(struct file_system_type *fs_type,
return simple_set_mnt(mnt, sb);
+ free_cg_links:
+ free_cg_links(&tmp_cg_links);
drop_new_super:
up_write(&sb->s_umount);
deactivate_super(sb);
- free_cg_links(&tmp_cg_links);
return ret;
}
@@ -2039,10 +2040,13 @@ int cgroupstats_build(struct cgroupstats *stats, struct dentry *dentry)
struct cgroup *cgrp;
struct cgroup_iter it;
struct task_struct *tsk;
+
/*
- * Validate dentry by checking the superblock operations
+ * Validate dentry by checking the superblock operations,
+ * and make sure it's a directory.
*/
- if (dentry->d_sb->s_op != &cgroup_ops)
+ if (dentry->d_sb->s_op != &cgroup_ops ||
+ !S_ISDIR(dentry->d_inode->i_mode))
goto err;
ret = 0;
@@ -2472,10 +2476,7 @@ static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry)
mutex_unlock(&cgroup_mutex);
return -EBUSY;
}
-
- parent = cgrp->parent;
- root = cgrp->root;
- sb = root->sb;
+ mutex_unlock(&cgroup_mutex);
/*
* Call pre_destroy handlers of subsys. Notify subsystems
@@ -2483,7 +2484,14 @@ static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry)
*/
cgroup_call_pre_destroy(cgrp);
- if (cgroup_has_css_refs(cgrp)) {
+ mutex_lock(&cgroup_mutex);
+ parent = cgrp->parent;
+ root = cgrp->root;
+ sb = root->sb;
+
+ if (atomic_read(&cgrp->count)
+ || !list_empty(&cgrp->children)
+ || cgroup_has_css_refs(cgrp)) {
mutex_unlock(&cgroup_mutex);
return -EBUSY;
}
@@ -2927,9 +2935,6 @@ int cgroup_clone(struct task_struct *tsk, struct cgroup_subsys *subsys,
again:
root = subsys->root;
if (root == &rootnode) {
- printk(KERN_INFO
- "Not cloning cgroup for unused subsystem %s\n",
- subsys->name);
mutex_unlock(&cgroup_mutex);
return 0;
}
diff --git a/kernel/cgroup_freezer.c b/kernel/cgroup_freezer.c
index 7fa476f01d0..fb249e2bcad 100644
--- a/kernel/cgroup_freezer.c
+++ b/kernel/cgroup_freezer.c
@@ -184,9 +184,20 @@ static void freezer_fork(struct cgroup_subsys *ss, struct task_struct *task)
{
struct freezer *freezer;
- task_lock(task);
+ /*
+ * No lock is needed, since the task isn't on tasklist yet,
+ * so it can't be moved to another cgroup, which means the
+ * freezer won't be removed and will be valid during this
+ * function call.
+ */
freezer = task_freezer(task);
- task_unlock(task);
+
+ /*
+ * The root cgroup is non-freezable, so we can skip the
+ * following check.
+ */
+ if (!freezer->css.cgroup->parent)
+ return;
spin_lock_irq(&freezer->lock);
BUG_ON(freezer->state == CGROUP_FROZEN);
@@ -331,7 +342,7 @@ static int freezer_write(struct cgroup *cgroup,
else if (strcmp(buffer, freezer_state_strs[CGROUP_FROZEN]) == 0)
goal_state = CGROUP_FROZEN;
else
- return -EIO;
+ return -EINVAL;
if (!cgroup_lock_live_group(cgroup))
return -ENODEV;
@@ -350,6 +361,8 @@ static struct cftype files[] = {
static int freezer_populate(struct cgroup_subsys *ss, struct cgroup *cgroup)
{
+ if (!cgroup->parent)
+ return 0;
return cgroup_add_files(cgroup, ss, files, ARRAY_SIZE(files));
}
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 5a732c5ef08..8ea32e8d68b 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -462,7 +462,7 @@ out:
* It must be called by the arch code on the new cpu, before the new cpu
* enables interrupts and before the "boot" cpu returns from __cpu_up().
*/
-void notify_cpu_starting(unsigned int cpu)
+void __cpuinit notify_cpu_starting(unsigned int cpu)
{
unsigned long val = CPU_STARTING;
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index 3e00526f52e..96c0ba13b8c 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -36,6 +36,7 @@
#include <linux/list.h>
#include <linux/mempolicy.h>
#include <linux/mm.h>
+#include <linux/memory.h>
#include <linux/module.h>
#include <linux/mount.h>
#include <linux/namei.h>
@@ -584,10 +585,9 @@ static int generate_sched_domains(cpumask_t **domains,
int i, j, k; /* indices for partition finding loops */
cpumask_t *doms; /* resulting partition; i.e. sched domains */
struct sched_domain_attr *dattr; /* attributes for custom domains */
- int ndoms; /* number of sched domains in result */
+ int ndoms = 0; /* number of sched domains in result */
int nslot; /* next empty doms[] cpumask_t slot */
- ndoms = 0;
doms = NULL;
dattr = NULL;
csa = NULL;
@@ -674,10 +674,8 @@ restart:
* Convert <csn, csa> to <ndoms, doms> and populate cpu masks.
*/
doms = kmalloc(ndoms * sizeof(cpumask_t), GFP_KERNEL);
- if (!doms) {
- ndoms = 0;
+ if (!doms)
goto done;
- }
/*
* The rest of the code, including the scheduler, can deal with
@@ -732,6 +730,13 @@ restart:
done:
kfree(csa);
+ /*
+ * Fallback to the default domain if kmalloc() failed.
+ * See comments in partition_sched_domains().
+ */
+ if (doms == NULL)
+ ndoms = 1;
+
*domains = doms;
*attributes = dattr;
return ndoms;
@@ -2011,12 +2016,23 @@ static int cpuset_track_online_cpus(struct notifier_block *unused_nb,
* Call this routine anytime after node_states[N_HIGH_MEMORY] changes.
* See also the previous routine cpuset_track_online_cpus().
*/
-void cpuset_track_online_nodes(void)
+static int cpuset_track_online_nodes(struct notifier_block *self,
+ unsigned long action, void *arg)
{
cgroup_lock();
- top_cpuset.mems_allowed = node_states[N_HIGH_MEMORY];
- scan_for_empty_cpusets(&top_cpuset);
+ switch (action) {
+ case MEM_ONLINE:
+ top_cpuset.mems_allowed = node_states[N_HIGH_MEMORY];
+ break;
+ case MEM_OFFLINE:
+ top_cpuset.mems_allowed = node_states[N_HIGH_MEMORY];
+ scan_for_empty_cpusets(&top_cpuset);
+ break;
+ default:
+ break;
+ }
cgroup_unlock();
+ return NOTIFY_OK;
}
#endif
@@ -2032,6 +2048,7 @@ void __init cpuset_init_smp(void)
top_cpuset.mems_allowed = node_states[N_HIGH_MEMORY];
hotcpu_notifier(cpuset_track_online_cpus, 0);
+ hotplug_memory_notifier(cpuset_track_online_nodes, 10);
}
/**
diff --git a/kernel/exit.c b/kernel/exit.c
index ae2b92be5fa..2d8be7ebb0f 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -40,7 +40,6 @@
#include <linux/cn_proc.h>
#include <linux/mutex.h>
#include <linux/futex.h>
-#include <linux/compat.h>
#include <linux/pipe_fs_i.h>
#include <linux/audit.h> /* for audit_free() */
#include <linux/resource.h>
@@ -1059,14 +1058,6 @@ NORET_TYPE void do_exit(long code)
exit_itimers(tsk->signal);
}
acct_collect(code, group_dead);
-#ifdef CONFIG_FUTEX
- if (unlikely(tsk->robust_list))
- exit_robust_list(tsk);
-#ifdef CONFIG_COMPAT
- if (unlikely(tsk->compat_robust_list))
- compat_exit_robust_list(tsk);
-#endif
-#endif
if (group_dead)
tty_audit_exit();
if (unlikely(tsk->audit_context))
diff --git a/kernel/fork.c b/kernel/fork.c
index f6083561dfe..495da2e9a8b 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -40,6 +40,7 @@
#include <linux/jiffies.h>
#include <linux/tracehook.h>
#include <linux/futex.h>
+#include <linux/compat.h>
#include <linux/task_io_accounting_ops.h>
#include <linux/rcupdate.h>
#include <linux/ptrace.h>
@@ -314,17 +315,20 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
file = tmp->vm_file;
if (file) {
struct inode *inode = file->f_path.dentry->d_inode;
+ struct address_space *mapping = file->f_mapping;
+
get_file(file);
if (tmp->vm_flags & VM_DENYWRITE)
atomic_dec(&inode->i_writecount);
-
- /* insert tmp into the share list, just after mpnt */
- spin_lock(&file->f_mapping->i_mmap_lock);
+ spin_lock(&mapping->i_mmap_lock);
+ if (tmp->vm_flags & VM_SHARED)
+ mapping->i_mmap_writable++;
tmp->vm_truncate_count = mpnt->vm_truncate_count;
- flush_dcache_mmap_lock(file->f_mapping);
+ flush_dcache_mmap_lock(mapping);
+ /* insert tmp into the share list, just after mpnt */
vma_prio_tree_add(tmp, mpnt);
- flush_dcache_mmap_unlock(file->f_mapping);
- spin_unlock(&file->f_mapping->i_mmap_lock);
+ flush_dcache_mmap_unlock(mapping);
+ spin_unlock(&mapping->i_mmap_lock);
}
/*
@@ -519,6 +523,16 @@ void mm_release(struct task_struct *tsk, struct mm_struct *mm)
{
struct completion *vfork_done = tsk->vfork_done;
+ /* Get rid of any futexes when releasing the mm */
+#ifdef CONFIG_FUTEX
+ if (unlikely(tsk->robust_list))
+ exit_robust_list(tsk);
+#ifdef CONFIG_COMPAT
+ if (unlikely(tsk->compat_robust_list))
+ compat_exit_robust_list(tsk);
+#endif
+#endif
+
/* Get rid of any cached register state */
deactivate_mm(tsk, mm);
@@ -1387,6 +1401,7 @@ long do_fork(unsigned long clone_flags,
init_completion(&vfork);
}
+ audit_finish_fork(p);
tracehook_report_clone(trace, regs, clone_flags, nr, p);
/*
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index 95d3949f2ae..47e63349d1b 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -664,14 +664,6 @@ static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer,
/* Timer is expired, act upon the callback mode */
switch(timer->cb_mode) {
- case HRTIMER_CB_IRQSAFE_NO_RESTART:
- debug_hrtimer_deactivate(timer);
- /*
- * We can call the callback from here. No restart
- * happens, so no danger of recursion
- */
- BUG_ON(timer->function(timer) != HRTIMER_NORESTART);
- return 1;
case HRTIMER_CB_IRQSAFE_PERCPU:
case HRTIMER_CB_IRQSAFE_UNLOCKED:
/*
@@ -683,7 +675,6 @@ static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer,
*/
debug_hrtimer_deactivate(timer);
return 1;
- case HRTIMER_CB_IRQSAFE:
case HRTIMER_CB_SOFTIRQ:
/*
* Move everything else into the softirq pending list !
diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h
index c9767e64198..64c1c7253da 100644
--- a/kernel/irq/internals.h
+++ b/kernel/irq/internals.h
@@ -25,6 +25,8 @@ static inline void unregister_handler_proc(unsigned int irq,
struct irqaction *action) { }
#endif
+extern int irq_select_affinity_usr(unsigned int irq);
+
/*
* Debugging printout:
*/
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index c498a1b8c62..801addda3c4 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -82,24 +82,27 @@ int irq_can_set_affinity(unsigned int irq)
int irq_set_affinity(unsigned int irq, cpumask_t cpumask)
{
struct irq_desc *desc = irq_to_desc(irq);
+ unsigned long flags;
if (!desc->chip->set_affinity)
return -EINVAL;
+ spin_lock_irqsave(&desc->lock, flags);
+
#ifdef CONFIG_GENERIC_PENDING_IRQ
if (desc->status & IRQ_MOVE_PCNTXT || desc->status & IRQ_DISABLED) {
- unsigned long flags;
-
- spin_lock_irqsave(&desc->lock, flags);
desc->affinity = cpumask;
desc->chip->set_affinity(irq, cpumask);
- spin_unlock_irqrestore(&desc->lock, flags);
- } else
- set_pending_irq(irq, cpumask);
+ } else {
+ desc->status |= IRQ_MOVE_PENDING;
+ desc->pending_mask = cpumask;
+ }
#else
desc->affinity = cpumask;
desc->chip->set_affinity(irq, cpumask);
#endif
+ desc->status |= IRQ_AFFINITY_SET;
+ spin_unlock_irqrestore(&desc->lock, flags);
return 0;
}
@@ -107,24 +110,59 @@ int irq_set_affinity(unsigned int irq, cpumask_t cpumask)
/*
* Generic version of the affinity autoselector.
*/
-int irq_select_affinity(unsigned int irq)
+int do_irq_select_affinity(unsigned int irq, struct irq_desc *desc)
{
cpumask_t mask;
- struct irq_desc *desc;
if (!irq_can_set_affinity(irq))
return 0;
cpus_and(mask, cpu_online_map, irq_default_affinity);
- desc = irq_to_desc(irq);
+ /*
+ * Preserve an userspace affinity setup, but make sure that
+ * one of the targets is online.
+ */
+ if (desc->status & (IRQ_AFFINITY_SET | IRQ_NO_BALANCING)) {
+ if (cpus_intersects(desc->affinity, cpu_online_map))
+ mask = desc->affinity;
+ else
+ desc->status &= ~IRQ_AFFINITY_SET;
+ }
+
desc->affinity = mask;
desc->chip->set_affinity(irq, mask);
return 0;
}
+#else
+static inline int do_irq_select_affinity(unsigned int irq, struct irq_desc *d)
+{
+ return irq_select_affinity(irq);
+}
#endif
+/*
+ * Called when affinity is set via /proc/irq
+ */
+int irq_select_affinity_usr(unsigned int irq)
+{
+ struct irq_desc *desc = irq_to_desc(irq);
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&desc->lock, flags);
+ ret = do_irq_select_affinity(irq, desc);
+ spin_unlock_irqrestore(&desc->lock, flags);
+
+ return ret;
+}
+
+#else
+static inline int do_irq_select_affinity(int irq, struct irq_desc *desc)
+{
+ return 0;
+}
#endif
/**
@@ -327,7 +365,7 @@ int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
* IRQF_TRIGGER_* but the PIC does not support multiple
* flow-types?
*/
- pr_warning("No set_type function for IRQ %d (%s)\n", irq,
+ pr_debug("No set_type function for IRQ %d (%s)\n", irq,
chip ? (chip->name ? : "unknown") : "unknown");
return 0;
}
@@ -445,8 +483,12 @@ __setup_irq(unsigned int irq, struct irq_desc * desc, struct irqaction *new)
/* Undo nested disables: */
desc->depth = 1;
+ /* Exclude IRQ from balancing if requested */
+ if (new->flags & IRQF_NOBALANCING)
+ desc->status |= IRQ_NO_BALANCING;
+
/* Set default affinity mask once everything is setup */
- irq_select_affinity(irq);
+ do_irq_select_affinity(irq, desc);
} else if ((new->flags & IRQF_TRIGGER_MASK)
&& (new->flags & IRQF_TRIGGER_MASK)
@@ -459,10 +501,6 @@ __setup_irq(unsigned int irq, struct irq_desc * desc, struct irqaction *new)
*p = new;
- /* Exclude IRQ from balancing */
- if (new->flags & IRQF_NOBALANCING)
- desc->status |= IRQ_NO_BALANCING;
-
/* Reset broken irq detection when installing new handler */
desc->irq_count = 0;
desc->irqs_unhandled = 0;
diff --git a/kernel/irq/migration.c b/kernel/irq/migration.c
index 90b920d3f52..9db681d9581 100644
--- a/kernel/irq/migration.c
+++ b/kernel/irq/migration.c
@@ -1,17 +1,6 @@
#include <linux/irq.h>
-void set_pending_irq(unsigned int irq, cpumask_t mask)
-{
- struct irq_desc *desc = irq_to_desc(irq);
- unsigned long flags;
-
- spin_lock_irqsave(&desc->lock, flags);
- desc->status |= IRQ_MOVE_PENDING;
- desc->pending_mask = mask;
- spin_unlock_irqrestore(&desc->lock, flags);
-}
-
void move_masked_irq(int irq)
{
struct irq_desc *desc = irq_to_desc(irq);
diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c
index 4d161c70ba5..d257e7d6a8a 100644
--- a/kernel/irq/proc.c
+++ b/kernel/irq/proc.c
@@ -62,7 +62,7 @@ static ssize_t irq_affinity_proc_write(struct file *file,
if (!cpus_intersects(new_value, cpu_online_map))
/* Special case for empty set - allow the architecture
code to set default SMP affinity. */
- return irq_select_affinity(irq) ? -EINVAL : count;
+ return irq_select_affinity_usr(irq) ? -EINVAL : count;
irq_set_affinity(irq, new_value);
diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c
index 5072cf1685a..7b8b0f21a5b 100644
--- a/kernel/kallsyms.c
+++ b/kernel/kallsyms.c
@@ -304,17 +304,24 @@ int sprint_symbol(char *buffer, unsigned long address)
char *modname;
const char *name;
unsigned long offset, size;
- char namebuf[KSYM_NAME_LEN];
+ int len;
- name = kallsyms_lookup(address, &size, &offset, &modname, namebuf);
+ name = kallsyms_lookup(address, &size, &offset, &modname, buffer);
if (!name)
return sprintf(buffer, "0x%lx", address);
+ if (name != buffer)
+ strcpy(buffer, name);
+ len = strlen(buffer);
+ buffer += len;
+
if (modname)
- return sprintf(buffer, "%s+%#lx/%#lx [%s]", name, offset,
- size, modname);
+ len += sprintf(buffer, "+%#lx/%#lx [%s]",
+ offset, size, modname);
else
- return sprintf(buffer, "%s+%#lx/%#lx", name, offset, size);
+ len += sprintf(buffer, "+%#lx/%#lx", offset, size);
+
+ return len;
}
/* Look up a kernel symbol and print it to the kernel messages. */
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 8b57a2597f2..9f8a3f25259 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -72,7 +72,7 @@ static bool kprobe_enabled;
DEFINE_MUTEX(kprobe_mutex); /* Protects kprobe_table */
static DEFINE_PER_CPU(struct kprobe *, kprobe_instance) = NULL;
static struct {
- spinlock_t lock ____cacheline_aligned;
+ spinlock_t lock ____cacheline_aligned_in_smp;
} kretprobe_table_locks[KPROBE_TABLE_SIZE];
static spinlock_t *kretprobe_table_lock_ptr(unsigned long hash)
@@ -613,30 +613,37 @@ static int __kprobes __register_kprobe(struct kprobe *p,
return -EINVAL;
p->addr = addr;
- if (!kernel_text_address((unsigned long) p->addr) ||
- in_kprobes_functions((unsigned long) p->addr))
+ preempt_disable();
+ if (!__kernel_text_address((unsigned long) p->addr) ||
+ in_kprobes_functions((unsigned long) p->addr)) {
+ preempt_enable();
return -EINVAL;
+ }
p->mod_refcounted = 0;
/*
* Check if are we probing a module.
*/
- probed_mod = module_text_address((unsigned long) p->addr);
+ probed_mod = __module_text_address((unsigned long) p->addr);
if (probed_mod) {
- struct module *calling_mod = module_text_address(called_from);
+ struct module *calling_mod;
+ calling_mod = __module_text_address(called_from);
/*
* We must allow modules to probe themself and in this case
* avoid incrementing the module refcount, so as to allow
* unloading of self probing modules.
*/
if (calling_mod && calling_mod != probed_mod) {
- if (unlikely(!try_module_get(probed_mod)))
+ if (unlikely(!try_module_get(probed_mod))) {
+ preempt_enable();
return -EINVAL;
+ }
p->mod_refcounted = 1;
} else
probed_mod = NULL;
}
+ preempt_enable();
p->nmissed = 0;
INIT_LIST_HEAD(&p->list);
@@ -718,6 +725,10 @@ static void __kprobes __unregister_kprobe_bottom(struct kprobe *p)
struct kprobe *old_p;
if (p->mod_refcounted) {
+ /*
+ * Since we've already incremented refcount,
+ * we don't need to disable preemption.
+ */
mod = module_text_address((unsigned long)p->addr);
if (mod)
module_put(mod);
diff --git a/kernel/latencytop.c b/kernel/latencytop.c
index 5e7b45c5692..449db466bdb 100644
--- a/kernel/latencytop.c
+++ b/kernel/latencytop.c
@@ -191,7 +191,7 @@ static int lstats_show(struct seq_file *m, void *v)
latency_record[i].time,
latency_record[i].max);
for (q = 0; q < LT_BACKTRACEDEPTH; q++) {
- char sym[KSYM_NAME_LEN];
+ char sym[KSYM_SYMBOL_LEN];
char *c;
if (!latency_record[i].backtrace[q])
break;
diff --git a/kernel/lockdep.c b/kernel/lockdep.c
index 06e157119d2..46a404173db 100644
--- a/kernel/lockdep.c
+++ b/kernel/lockdep.c
@@ -3276,10 +3276,10 @@ void __init lockdep_info(void)
{
printk("Lock dependency validator: Copyright (c) 2006 Red Hat, Inc., Ingo Molnar\n");
- printk("... MAX_LOCKDEP_SUBCLASSES: %lu\n", MAX_LOCKDEP_SUBCLASSES);
+ printk("... MAX_LOCKDEP_SUBCLASSES: %lu\n", MAX_LOCKDEP_SUBCLASSES);
printk("... MAX_LOCK_DEPTH: %lu\n", MAX_LOCK_DEPTH);
printk("... MAX_LOCKDEP_KEYS: %lu\n", MAX_LOCKDEP_KEYS);
- printk("... CLASSHASH_SIZE: %lu\n", CLASSHASH_SIZE);
+ printk("... CLASSHASH_SIZE: %lu\n", CLASSHASH_SIZE);
printk("... MAX_LOCKDEP_ENTRIES: %lu\n", MAX_LOCKDEP_ENTRIES);
printk("... MAX_LOCKDEP_CHAINS: %lu\n", MAX_LOCKDEP_CHAINS);
printk("... CHAINHASH_SIZE: %lu\n", CHAINHASH_SIZE);
diff --git a/kernel/panic.c b/kernel/panic.c
index 6513aac8e99..4d5088355bf 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -167,6 +167,7 @@ static const struct tnt tnts[] = {
* 'M' - System experienced a machine check exception.
* 'B' - System has hit bad_page.
* 'U' - Userspace-defined naughtiness.
+ * 'D' - Kernel has oopsed before
* 'A' - ACPI table overridden.
* 'W' - Taint on warning.
* 'C' - modules from drivers/staging are loaded.
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c
index 153dcb2639c..4e5288a831d 100644
--- a/kernel/posix-cpu-timers.c
+++ b/kernel/posix-cpu-timers.c
@@ -311,7 +311,7 @@ static int cpu_clock_sample_group(const clockid_t which_clock,
struct task_cputime cputime;
thread_group_cputime(p, &cputime);
- switch (which_clock) {
+ switch (CPUCLOCK_WHICH(which_clock)) {
default:
return -EINVAL;
case CPUCLOCK_PROF:
@@ -1308,9 +1308,10 @@ static inline int task_cputime_expired(const struct task_cputime *sample,
*/
static inline int fastpath_timer_check(struct task_struct *tsk)
{
- struct signal_struct *sig = tsk->signal;
+ struct signal_struct *sig;
- if (unlikely(!sig))
+ /* tsk == current, ensure it is safe to use ->signal/sighand */
+ if (unlikely(tsk->exit_state))
return 0;
if (!task_cputime_zero(&tsk->cputime_expires)) {
@@ -1323,6 +1324,8 @@ static inline int fastpath_timer_check(struct task_struct *tsk)
if (task_cputime_expired(&task_sample, &tsk->cputime_expires))
return 1;
}
+
+ sig = tsk->signal;
if (!task_cputime_zero(&sig->cputime_expires)) {
struct task_cputime group_sample;
diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c
index 5e79c662294..a140e44eebb 100644
--- a/kernel/posix-timers.c
+++ b/kernel/posix-timers.c
@@ -197,6 +197,11 @@ static int common_timer_create(struct k_itimer *new_timer)
return 0;
}
+static int no_timer_create(struct k_itimer *new_timer)
+{
+ return -EOPNOTSUPP;
+}
+
/*
* Return nonzero if we know a priori this clockid_t value is bogus.
*/
@@ -248,6 +253,7 @@ static __init int init_posix_timers(void)
.clock_getres = hrtimer_get_res,
.clock_get = posix_get_monotonic_raw,
.clock_set = do_posix_clock_nosettime,
+ .timer_create = no_timer_create,
};
register_posix_clock(CLOCK_REALTIME, &clock_realtime);
diff --git a/kernel/power/main.c b/kernel/power/main.c
index 19122cf6d82..b8f7ce9473e 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -174,7 +174,7 @@ static void suspend_test_finish(const char *label)
* has some performance issues. The stack dump of a WARN_ON
* is more likely to get the right attention than a printk...
*/
- WARN_ON(msec > (TEST_SUSPEND_SECONDS * 1000));
+ WARN(msec > (TEST_SUSPEND_SECONDS * 1000), "Component: %s\n", label);
}
#else
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index b7713b53d07..6da14358537 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -633,7 +633,7 @@ void swsusp_close(fmode_t mode)
return;
}
- blkdev_put(resume_bdev, mode); /* move up */
+ blkdev_put(resume_bdev, mode);
}
static int swsusp_header_init(void)
diff --git a/kernel/profile.c b/kernel/profile.c
index 9830a037d8d..dc41827fbfe 100644
--- a/kernel/profile.c
+++ b/kernel/profile.c
@@ -351,7 +351,7 @@ out:
put_cpu();
}
-static int __devinit profile_cpu_callback(struct notifier_block *info,
+static int __cpuinit profile_cpu_callback(struct notifier_block *info,
unsigned long action, void *__cpu)
{
int node, cpu = (unsigned long)__cpu;
@@ -544,7 +544,7 @@ static const struct file_operations proc_profile_operations = {
};
#ifdef CONFIG_SMP
-static void __init profile_nop(void *unused)
+static inline void profile_nop(void *unused)
{
}
@@ -596,7 +596,7 @@ out_cleanup:
#define create_hash_tables() ({ 0; })
#endif
-int create_proc_profile(void)
+int __ref create_proc_profile(void) /* false positive from hotcpu_notifier */
{
struct proc_dir_entry *entry;
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 1e68e4c39e2..4c8bcd7dd8e 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -612,7 +612,7 @@ int generic_ptrace_pokedata(struct task_struct *tsk, long addr, long data)
return (copied == sizeof(data)) ? 0 : -EIO;
}
-#if defined CONFIG_COMPAT && defined __ARCH_WANT_COMPAT_SYS_PTRACE
+#if defined CONFIG_COMPAT
#include <linux/compat.h>
int compat_ptrace_request(struct task_struct *child, compat_long_t request,
@@ -709,4 +709,4 @@ asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid,
unlock_kernel();
return ret;
}
-#endif /* CONFIG_COMPAT && __ARCH_WANT_COMPAT_SYS_PTRACE */
+#endif /* CONFIG_COMPAT */
diff --git a/kernel/relay.c b/kernel/relay.c
index 8d13a7855c0..09ac2008f77 100644
--- a/kernel/relay.c
+++ b/kernel/relay.c
@@ -400,7 +400,7 @@ void relay_reset(struct rchan *chan)
}
mutex_lock(&relay_channels_mutex);
- for_each_online_cpu(i)
+ for_each_possible_cpu(i)
if (chan->buf[i])
__relay_reset(chan->buf[i], 0);
mutex_unlock(&relay_channels_mutex);
@@ -611,10 +611,9 @@ struct rchan *relay_open(const char *base_filename,
return chan;
free_bufs:
- for_each_online_cpu(i) {
- if (!chan->buf[i])
- break;
- relay_close_buf(chan->buf[i]);
+ for_each_possible_cpu(i) {
+ if (chan->buf[i])
+ relay_close_buf(chan->buf[i]);
}
kref_put(&chan->kref, relay_destroy_channel);
@@ -1318,12 +1317,9 @@ static ssize_t relay_file_splice_read(struct file *in,
if (ret < 0)
break;
else if (!ret) {
- if (spliced)
- break;
- if (flags & SPLICE_F_NONBLOCK) {
+ if (flags & SPLICE_F_NONBLOCK)
ret = -EAGAIN;
- break;
- }
+ break;
}
*ppos += ret;
diff --git a/kernel/sched.c b/kernel/sched.c
index 50a21f96467..e4bb1dd7b30 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -1453,9 +1453,12 @@ static int task_hot(struct task_struct *p, u64 now, struct sched_domain *sd);
static unsigned long cpu_avg_load_per_task(int cpu)
{
struct rq *rq = cpu_rq(cpu);
+ unsigned long nr_running = ACCESS_ONCE(rq->nr_running);
- if (rq->nr_running)
- rq->avg_load_per_task = rq->load.weight / rq->nr_running;
+ if (nr_running)
+ rq->avg_load_per_task = rq->load.weight / nr_running;
+ else
+ rq->avg_load_per_task = 0;
return rq->avg_load_per_task;
}
@@ -5868,6 +5871,8 @@ void __cpuinit init_idle(struct task_struct *idle, int cpu)
struct rq *rq = cpu_rq(cpu);
unsigned long flags;
+ spin_lock_irqsave(&rq->lock, flags);
+
__sched_fork(idle);
idle->se.exec_start = sched_clock();
@@ -5875,7 +5880,6 @@ void __cpuinit init_idle(struct task_struct *idle, int cpu)
idle->cpus_allowed = cpumask_of_cpu(cpu);
__set_task_cpu(idle, cpu);
- spin_lock_irqsave(&rq->lock, flags);
rq->curr = rq->idle = idle;
#if defined(CONFIG_SMP) && defined(__ARCH_WANT_UNLOCKED_CTXSW)
idle->oncpu = 1;
@@ -6583,7 +6587,9 @@ migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu)
req = list_entry(rq->migration_queue.next,
struct migration_req, list);
list_del_init(&req->list);
+ spin_unlock_irq(&rq->lock);
complete(&req->done);
+ spin_lock_irq(&rq->lock);
}
spin_unlock_irq(&rq->lock);
break;
@@ -7786,13 +7792,14 @@ static int dattrs_equal(struct sched_domain_attr *cur, int idx_cur,
*
* The passed in 'doms_new' should be kmalloc'd. This routine takes
* ownership of it and will kfree it when done with it. If the caller
- * failed the kmalloc call, then it can pass in doms_new == NULL,
- * and partition_sched_domains() will fallback to the single partition
- * 'fallback_doms', it also forces the domains to be rebuilt.
+ * failed the kmalloc call, then it can pass in doms_new == NULL &&
+ * ndoms_new == 1, and partition_sched_domains() will fallback to
+ * the single partition 'fallback_doms', it also forces the domains
+ * to be rebuilt.
*
- * If doms_new==NULL it will be replaced with cpu_online_map.
- * ndoms_new==0 is a special case for destroying existing domains.
- * It will not create the default domain.
+ * If doms_new == NULL it will be replaced with cpu_online_map.
+ * ndoms_new == 0 is a special case for destroying existing domains,
+ * and it will not create the default domain.
*
* Call with hotplug lock held
*/
diff --git a/kernel/sched_clock.c b/kernel/sched_clock.c
index 81787248b60..e8ab096ddfe 100644
--- a/kernel/sched_clock.c
+++ b/kernel/sched_clock.c
@@ -118,13 +118,13 @@ static u64 __update_sched_clock(struct sched_clock_data *scd, u64 now)
/*
* scd->clock = clamp(scd->tick_gtod + delta,
- * max(scd->tick_gtod, scd->clock),
- * max(scd->clock, scd->tick_gtod + TICK_NSEC));
+ * max(scd->tick_gtod, scd->clock),
+ * scd->tick_gtod + TICK_NSEC);
*/
clock = scd->tick_gtod + delta;
min_clock = wrap_max(scd->tick_gtod, scd->clock);
- max_clock = wrap_max(scd->clock, scd->tick_gtod + TICK_NSEC);
+ max_clock = scd->tick_gtod + TICK_NSEC;
clock = wrap_max(clock, min_clock);
clock = wrap_min(clock, max_clock);
diff --git a/kernel/sched_debug.c b/kernel/sched_debug.c
index 48ecc51e770..26ed8e3d1c1 100644
--- a/kernel/sched_debug.c
+++ b/kernel/sched_debug.c
@@ -423,10 +423,11 @@ void proc_sched_show_task(struct task_struct *p, struct seq_file *m)
#undef __P
{
+ unsigned int this_cpu = raw_smp_processor_id();
u64 t0, t1;
- t0 = sched_clock();
- t1 = sched_clock();
+ t0 = cpu_clock(this_cpu);
+ t1 = cpu_clock(this_cpu);
SEQ_printf(m, "%-35s:%21Ld\n",
"clock-delta", (long long)(t1-t0));
}
diff --git a/kernel/sched_stats.h b/kernel/sched_stats.h
index ee71bec1da6..7dbf72a2b02 100644
--- a/kernel/sched_stats.h
+++ b/kernel/sched_stats.h
@@ -298,9 +298,11 @@ static inline void account_group_user_time(struct task_struct *tsk,
{
struct signal_struct *sig;
- sig = tsk->signal;
- if (unlikely(!sig))
+ /* tsk == current, ensure it is safe to use ->signal */
+ if (unlikely(tsk->exit_state))
return;
+
+ sig = tsk->signal;
if (sig->cputime.totals) {
struct task_cputime *times;
@@ -325,9 +327,11 @@ static inline void account_group_system_time(struct task_struct *tsk,
{
struct signal_struct *sig;
- sig = tsk->signal;
- if (unlikely(!sig))
+ /* tsk == current, ensure it is safe to use ->signal */
+ if (unlikely(tsk->exit_state))
return;
+
+ sig = tsk->signal;
if (sig->cputime.totals) {
struct task_cputime *times;
@@ -353,8 +357,11 @@ static inline void account_group_exec_runtime(struct task_struct *tsk,
struct signal_struct *sig;
sig = tsk->signal;
+ /* see __exit_signal()->task_rq_unlock_wait() */
+ barrier();
if (unlikely(!sig))
return;
+
if (sig->cputime.totals) {
struct task_cputime *times;
diff --git a/kernel/softlockup.c b/kernel/softlockup.c
index 3953e4aed73..dc0b3be6b7d 100644
--- a/kernel/softlockup.c
+++ b/kernel/softlockup.c
@@ -188,7 +188,7 @@ static void check_hung_task(struct task_struct *t, unsigned long now)
if ((long)(now - t->last_switch_timestamp) <
sysctl_hung_task_timeout_secs)
return;
- if (sysctl_hung_task_warnings < 0)
+ if (!sysctl_hung_task_warnings)
return;
sysctl_hung_task_warnings--;
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index 9bc4c00872c..24e8ceacc38 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -112,7 +112,7 @@ static int chill(void *unused)
int __stop_machine(int (*fn)(void *), void *data, const cpumask_t *cpus)
{
struct work_struct *sm_work;
- int i;
+ int i, ret;
/* Set up initial state. */
mutex_lock(&lock);
@@ -137,8 +137,9 @@ int __stop_machine(int (*fn)(void *), void *data, const cpumask_t *cpus)
/* This will release the thread on our CPU. */
put_cpu();
flush_workqueue(stop_machine_wq);
+ ret = active.fnret;
mutex_unlock(&lock);
- return active.fnret;
+ return ret;
}
int stop_machine(int (*fn)(void *), void *data, const cpumask_t *cpus)
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index a77b27b11b0..e14a2328170 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -31,7 +31,7 @@ cond_syscall(sys_socketpair);
cond_syscall(sys_bind);
cond_syscall(sys_listen);
cond_syscall(sys_accept);
-cond_syscall(sys_paccept);
+cond_syscall(sys_accept4);
cond_syscall(sys_connect);
cond_syscall(sys_getsockname);
cond_syscall(sys_getpeername);
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 9d048fa2d90..3d56fe7570d 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -176,6 +176,9 @@ extern struct ctl_table random_table[];
#ifdef CONFIG_INOTIFY_USER
extern struct ctl_table inotify_table[];
#endif
+#ifdef CONFIG_EPOLL
+extern struct ctl_table epoll_table[];
+#endif
#ifdef HAVE_ARCH_PICK_MMAP_LAYOUT
int sysctl_legacy_va_layout;
@@ -1325,6 +1328,13 @@ static struct ctl_table fs_table[] = {
.child = inotify_table,
},
#endif
+#ifdef CONFIG_EPOLL
+ {
+ .procname = "epoll",
+ .mode = 0555,
+ .child = epoll_table,
+ },
+#endif
#endif
{
.ctl_name = KERN_SETUID_DUMPABLE,
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index e7acfb482a6..fa05e88aa76 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -518,6 +518,28 @@ void update_wall_time(void)
/* correct the clock when NTP error is too big */
clocksource_adjust(offset);
+ /*
+ * Since in the loop above, we accumulate any amount of time
+ * in xtime_nsec over a second into xtime.tv_sec, its possible for
+ * xtime_nsec to be fairly small after the loop. Further, if we're
+ * slightly speeding the clocksource up in clocksource_adjust(),
+ * its possible the required corrective factor to xtime_nsec could
+ * cause it to underflow.
+ *
+ * Now, we cannot simply roll the accumulated second back, since
+ * the NTP subsystem has been notified via second_overflow. So
+ * instead we push xtime_nsec forward by the amount we underflowed,
+ * and add that amount into the error.
+ *
+ * We'll correct this error next time through this function, when
+ * xtime_nsec is not as small.
+ */
+ if (unlikely((s64)clock->xtime_nsec < 0)) {
+ s64 neg = -(s64)clock->xtime_nsec;
+ clock->xtime_nsec = 0;
+ clock->error += neg << (NTP_SCALE_SHIFT - clock->shift);
+ }
+
/* store full nanoseconds into xtime after rounding it up and
* add the remainder to the error difference.
*/
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 4a39d24568c..78db083390f 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -185,7 +185,6 @@ enum {
};
static int ftrace_filtered;
-static int tracing_on;
static LIST_HEAD(ftrace_new_addrs);
@@ -327,96 +326,89 @@ ftrace_record_ip(unsigned long ip)
static int
__ftrace_replace_code(struct dyn_ftrace *rec,
- unsigned char *old, unsigned char *new, int enable)
+ unsigned char *nop, int enable)
{
unsigned long ip, fl;
+ unsigned char *call, *old, *new;
ip = rec->ip;
- if (ftrace_filtered && enable) {
+ /*
+ * If this record is not to be traced and
+ * it is not enabled then do nothing.
+ *
+ * If this record is not to be traced and
+ * it is enabled then disabled it.
+ *
+ */
+ if (rec->flags & FTRACE_FL_NOTRACE) {
+ if (rec->flags & FTRACE_FL_ENABLED)
+ rec->flags &= ~FTRACE_FL_ENABLED;
+ else
+ return 0;
+
+ } else if (ftrace_filtered && enable) {
/*
- * If filtering is on:
- *
- * If this record is set to be filtered and
- * is enabled then do nothing.
- *
- * If this record is set to be filtered and
- * it is not enabled, enable it.
- *
- * If this record is not set to be filtered
- * and it is not enabled do nothing.
- *
- * If this record is set not to trace then
- * do nothing.
- *
- * If this record is set not to trace and
- * it is enabled then disable it.
- *
- * If this record is not set to be filtered and
- * it is enabled, disable it.
+ * Filtering is on:
*/
- fl = rec->flags & (FTRACE_FL_FILTER | FTRACE_FL_NOTRACE |
- FTRACE_FL_ENABLED);
+ fl = rec->flags & (FTRACE_FL_FILTER | FTRACE_FL_ENABLED);
- if ((fl == (FTRACE_FL_FILTER | FTRACE_FL_ENABLED)) ||
- (fl == (FTRACE_FL_FILTER | FTRACE_FL_NOTRACE)) ||
- !fl || (fl == FTRACE_FL_NOTRACE))
+ /* Record is filtered and enabled, do nothing */
+ if (fl == (FTRACE_FL_FILTER | FTRACE_FL_ENABLED))
return 0;
- /*
- * If it is enabled disable it,
- * otherwise enable it!
- */
- if (fl & FTRACE_FL_ENABLED) {
- /* swap new and old */
- new = old;
- old = ftrace_call_replace(ip, FTRACE_ADDR);
+ /* Record is not filtered and is not enabled do nothing */
+ if (!fl)
+ return 0;
+
+ /* Record is not filtered but enabled, disable it */
+ if (fl == FTRACE_FL_ENABLED)
rec->flags &= ~FTRACE_FL_ENABLED;
- } else {
- new = ftrace_call_replace(ip, FTRACE_ADDR);
+ else
+ /* Otherwise record is filtered but not enabled, enable it */
rec->flags |= FTRACE_FL_ENABLED;
- }
} else {
+ /* Disable or not filtered */
if (enable) {
- /*
- * If this record is set not to trace and is
- * not enabled, do nothing.
- */
- fl = rec->flags & (FTRACE_FL_NOTRACE | FTRACE_FL_ENABLED);
- if (fl == FTRACE_FL_NOTRACE)
- return 0;
-
- new = ftrace_call_replace(ip, FTRACE_ADDR);
- } else
- old = ftrace_call_replace(ip, FTRACE_ADDR);
-
- if (enable) {
+ /* if record is enabled, do nothing */
if (rec->flags & FTRACE_FL_ENABLED)
return 0;
+
rec->flags |= FTRACE_FL_ENABLED;
+
} else {
+
+ /* if record is not enabled do nothing */
if (!(rec->flags & FTRACE_FL_ENABLED))
return 0;
+
rec->flags &= ~FTRACE_FL_ENABLED;
}
}
+ call = ftrace_call_replace(ip, FTRACE_ADDR);
+
+ if (rec->flags & FTRACE_FL_ENABLED) {
+ old = nop;
+ new = call;
+ } else {
+ old = call;
+ new = nop;
+ }
+
return ftrace_modify_code(ip, old, new);
}
static void ftrace_replace_code(int enable)
{
int i, failed;
- unsigned char *new = NULL, *old = NULL;
+ unsigned char *nop = NULL;
struct dyn_ftrace *rec;
struct ftrace_page *pg;
- if (enable)
- old = ftrace_nop_replace();
- else
- new = ftrace_nop_replace();
+ nop = ftrace_nop_replace();
for (pg = ftrace_pages_start; pg; pg = pg->next) {
for (i = 0; i < pg->index; i++) {
@@ -434,7 +426,7 @@ static void ftrace_replace_code(int enable)
unfreeze_record(rec);
}
- failed = __ftrace_replace_code(rec, old, new, enable);
+ failed = __ftrace_replace_code(rec, nop, enable);
if (failed && (rec->flags & FTRACE_FL_CONVERTED)) {
rec->flags |= FTRACE_FL_FAILED;
if ((system_state == SYSTEM_BOOTING) ||
@@ -506,13 +498,10 @@ static int __ftrace_modify_code(void *data)
{
int *command = data;
- if (*command & FTRACE_ENABLE_CALLS) {
+ if (*command & FTRACE_ENABLE_CALLS)
ftrace_replace_code(1);
- tracing_on = 1;
- } else if (*command & FTRACE_DISABLE_CALLS) {
+ else if (*command & FTRACE_DISABLE_CALLS)
ftrace_replace_code(0);
- tracing_on = 0;
- }
if (*command & FTRACE_UPDATE_TRACE_FUNC)
ftrace_update_ftrace_func(ftrace_trace_function);
@@ -538,8 +527,7 @@ static void ftrace_startup(void)
mutex_lock(&ftrace_start_lock);
ftrace_start++;
- if (ftrace_start == 1)
- command |= FTRACE_ENABLE_CALLS;
+ command |= FTRACE_ENABLE_CALLS;
if (saved_ftrace_func != ftrace_trace_function) {
saved_ftrace_func = ftrace_trace_function;
@@ -677,7 +665,7 @@ static int __init ftrace_dyn_table_alloc(unsigned long num_to_init)
cnt = num_to_init / ENTRIES_PER_PAGE;
pr_info("ftrace: allocating %ld entries in %d pages\n",
- num_to_init, cnt);
+ num_to_init, cnt + 1);
for (i = 0; i < cnt; i++) {
pg->next = (void *)get_zeroed_page(GFP_KERNEL);
@@ -738,6 +726,9 @@ t_next(struct seq_file *m, void *v, loff_t *pos)
((iter->flags & FTRACE_ITER_FAILURES) &&
!(rec->flags & FTRACE_FL_FAILED)) ||
+ ((iter->flags & FTRACE_ITER_FILTER) &&
+ !(rec->flags & FTRACE_FL_FILTER)) ||
+
((iter->flags & FTRACE_ITER_NOTRACE) &&
!(rec->flags & FTRACE_FL_NOTRACE))) {
rec = NULL;
@@ -757,13 +748,11 @@ static void *t_start(struct seq_file *m, loff_t *pos)
void *p = NULL;
loff_t l = -1;
- if (*pos != iter->pos) {
- for (p = t_next(m, p, &l); p && l < *pos; p = t_next(m, p, &l))
- ;
- } else {
- l = *pos;
- p = t_next(m, p, &l);
- }
+ if (*pos > iter->pos)
+ *pos = iter->pos;
+
+ l = *pos;
+ p = t_next(m, p, &l);
return p;
}
@@ -774,15 +763,21 @@ static void t_stop(struct seq_file *m, void *p)
static int t_show(struct seq_file *m, void *v)
{
+ struct ftrace_iterator *iter = m->private;
struct dyn_ftrace *rec = v;
char str[KSYM_SYMBOL_LEN];
+ int ret = 0;
if (!rec)
return 0;
kallsyms_lookup(rec->ip, NULL, NULL, NULL, str);
- seq_printf(m, "%s\n", str);
+ ret = seq_printf(m, "%s\n", str);
+ if (ret < 0) {
+ iter->pos--;
+ iter->idx--;
+ }
return 0;
}
@@ -808,7 +803,7 @@ ftrace_avail_open(struct inode *inode, struct file *file)
return -ENOMEM;
iter->pg = ftrace_pages_start;
- iter->pos = -1;
+ iter->pos = 0;
ret = seq_open(file, &show_ftrace_seq_ops);
if (!ret) {
@@ -895,7 +890,7 @@ ftrace_regex_open(struct inode *inode, struct file *file, int enable)
if (file->f_mode & FMODE_READ) {
iter->pg = ftrace_pages_start;
- iter->pos = -1;
+ iter->pos = 0;
iter->flags = enable ? FTRACE_ITER_FILTER :
FTRACE_ITER_NOTRACE;
@@ -1186,7 +1181,7 @@ ftrace_regex_release(struct inode *inode, struct file *file, int enable)
mutex_lock(&ftrace_sysctl_lock);
mutex_lock(&ftrace_start_lock);
- if (iter->filtered && ftrace_start && ftrace_enabled)
+ if (ftrace_start && ftrace_enabled)
ftrace_run_update_code(FTRACE_ENABLE_CALLS);
mutex_unlock(&ftrace_start_lock);
mutex_unlock(&ftrace_sysctl_lock);
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index 2f76193c348..668bbb5ef2b 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -16,14 +16,49 @@
#include <linux/list.h>
#include <linux/fs.h>
+#include "trace.h"
+
+/* Global flag to disable all recording to ring buffers */
+static int ring_buffers_off __read_mostly;
+
+/**
+ * tracing_on - enable all tracing buffers
+ *
+ * This function enables all tracing buffers that may have been
+ * disabled with tracing_off.
+ */
+void tracing_on(void)
+{
+ ring_buffers_off = 0;
+}
+
+/**
+ * tracing_off - turn off all tracing buffers
+ *
+ * This function stops all tracing buffers from recording data.
+ * It does not disable any overhead the tracers themselves may
+ * be causing. This function simply causes all recording to
+ * the ring buffers to fail.
+ */
+void tracing_off(void)
+{
+ ring_buffers_off = 1;
+}
+
/* Up this if you want to test the TIME_EXTENTS and normalization */
#define DEBUG_SHIFT 0
/* FIXME!!! */
u64 ring_buffer_time_stamp(int cpu)
{
+ u64 time;
+
+ preempt_disable_notrace();
/* shift to debug/test normalization and TIME_EXTENTS */
- return sched_clock() << DEBUG_SHIFT;
+ time = sched_clock() << DEBUG_SHIFT;
+ preempt_enable_notrace();
+
+ return time;
}
void ring_buffer_normalize_time_stamp(int cpu, u64 *ts)
@@ -503,6 +538,12 @@ int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size)
LIST_HEAD(pages);
int i, cpu;
+ /*
+ * Always succeed at resizing a non-existent buffer:
+ */
+ if (!buffer)
+ return size;
+
size = DIV_ROUND_UP(size, BUF_PAGE_SIZE);
size *= BUF_PAGE_SIZE;
buffer_size = buffer->pages * BUF_PAGE_SIZE;
@@ -576,6 +617,7 @@ int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size)
list_del_init(&page->list);
free_buffer_page(page);
}
+ mutex_unlock(&buffer->mutex);
return -ENOMEM;
}
@@ -1133,6 +1175,9 @@ ring_buffer_lock_reserve(struct ring_buffer *buffer,
struct ring_buffer_event *event;
int cpu, resched;
+ if (ring_buffers_off)
+ return NULL;
+
if (atomic_read(&buffer->record_disabled))
return NULL;
@@ -1170,7 +1215,7 @@ ring_buffer_lock_reserve(struct ring_buffer *buffer,
out:
if (resched)
- preempt_enable_notrace();
+ preempt_enable_no_resched_notrace();
else
preempt_enable_notrace();
return NULL;
@@ -1249,6 +1294,9 @@ int ring_buffer_write(struct ring_buffer *buffer,
int ret = -EBUSY;
int cpu, resched;
+ if (ring_buffers_off)
+ return -EBUSY;
+
if (atomic_read(&buffer->record_disabled))
return -EBUSY;
@@ -2070,3 +2118,69 @@ int ring_buffer_swap_cpu(struct ring_buffer *buffer_a,
return 0;
}
+static ssize_t
+rb_simple_read(struct file *filp, char __user *ubuf,
+ size_t cnt, loff_t *ppos)
+{
+ int *p = filp->private_data;
+ char buf[64];
+ int r;
+
+ /* !ring_buffers_off == tracing_on */
+ r = sprintf(buf, "%d\n", !*p);
+
+ return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
+}
+
+static ssize_t
+rb_simple_write(struct file *filp, const char __user *ubuf,
+ size_t cnt, loff_t *ppos)
+{
+ int *p = filp->private_data;
+ char buf[64];
+ long val;
+ int ret;
+
+ if (cnt >= sizeof(buf))
+ return -EINVAL;
+
+ if (copy_from_user(&buf, ubuf, cnt))
+ return -EFAULT;
+
+ buf[cnt] = 0;
+
+ ret = strict_strtoul(buf, 10, &val);
+ if (ret < 0)
+ return ret;
+
+ /* !ring_buffers_off == tracing_on */
+ *p = !val;
+
+ (*ppos)++;
+
+ return cnt;
+}
+
+static struct file_operations rb_simple_fops = {
+ .open = tracing_open_generic,
+ .read = rb_simple_read,
+ .write = rb_simple_write,
+};
+
+
+static __init int rb_init_debugfs(void)
+{
+ struct dentry *d_tracer;
+ struct dentry *entry;
+
+ d_tracer = tracing_init_dentry();
+
+ entry = debugfs_create_file("tracing_on", 0644, d_tracer,
+ &ring_buffers_off, &rb_simple_fops);
+ if (!entry)
+ pr_warning("Could not create debugfs 'tracing_on' entry\n");
+
+ return 0;
+}
+
+fs_initcall(rb_init_debugfs);
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 697eda36b86..d86e3252f30 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -1936,6 +1936,7 @@ __tracing_open(struct inode *inode, struct file *file, int *ret)
ring_buffer_read_finish(iter->buffer_iter[cpu]);
}
mutex_unlock(&trace_types_lock);
+ kfree(iter);
return ERR_PTR(-ENOMEM);
}
diff --git a/kernel/trace/trace_mmiotrace.c b/kernel/trace/trace_mmiotrace.c
index f28484618ff..e62cbf78eab 100644
--- a/kernel/trace/trace_mmiotrace.c
+++ b/kernel/trace/trace_mmiotrace.c
@@ -18,12 +18,14 @@ struct header_iter {
static struct trace_array *mmio_trace_array;
static bool overrun_detected;
+static unsigned long prev_overruns;
static void mmio_reset_data(struct trace_array *tr)
{
int cpu;
overrun_detected = false;
+ prev_overruns = 0;
tr->time_start = ftrace_now(tr->cpu);
for_each_online_cpu(cpu)
@@ -128,16 +130,12 @@ static void mmio_close(struct trace_iterator *iter)
static unsigned long count_overruns(struct trace_iterator *iter)
{
- int cpu;
unsigned long cnt = 0;
-/* FIXME: */
-#if 0
- for_each_online_cpu(cpu) {
- cnt += iter->overrun[cpu];
- iter->overrun[cpu] = 0;
- }
-#endif
- (void)cpu;
+ unsigned long over = ring_buffer_overruns(iter->tr->buffer);
+
+ if (over > prev_overruns)
+ cnt = over - prev_overruns;
+ prev_overruns = over;
return cnt;
}
diff --git a/kernel/trace/trace_stack.c b/kernel/trace/trace_stack.c
index be682b62fe5..3bdb44bde4b 100644
--- a/kernel/trace/trace_stack.c
+++ b/kernel/trace/trace_stack.c
@@ -184,11 +184,16 @@ static struct file_operations stack_max_size_fops = {
static void *
t_next(struct seq_file *m, void *v, loff_t *pos)
{
- long i = (long)m->private;
+ long i;
(*pos)++;
- i++;
+ if (v == SEQ_START_TOKEN)
+ i = 0;
+ else {
+ i = *(long *)v;
+ i++;
+ }
if (i >= max_stack_trace.nr_entries ||
stack_dump_trace[i] == ULONG_MAX)
@@ -201,12 +206,15 @@ t_next(struct seq_file *m, void *v, loff_t *pos)
static void *t_start(struct seq_file *m, loff_t *pos)
{
- void *t = &m->private;
+ void *t = SEQ_START_TOKEN;
loff_t l = 0;
local_irq_disable();
__raw_spin_lock(&max_stack_lock);
+ if (*pos == 0)
+ return SEQ_START_TOKEN;
+
for (; t && l < *pos; t = t_next(m, t, &l))
;
@@ -235,10 +243,10 @@ static int trace_lookup_stack(struct seq_file *m, long i)
static int t_show(struct seq_file *m, void *v)
{
- long i = *(long *)v;
+ long i;
int size;
- if (i < 0) {
+ if (v == SEQ_START_TOKEN) {
seq_printf(m, " Depth Size Location"
" (%d entries)\n"
" ----- ---- --------\n",
@@ -246,6 +254,8 @@ static int t_show(struct seq_file *m, void *v)
return 0;
}
+ i = *(long *)v;
+
if (i >= max_stack_trace.nr_entries ||
stack_dump_trace[i] == ULONG_MAX)
return 0;
@@ -275,10 +285,6 @@ static int stack_trace_open(struct inode *inode, struct file *file)
int ret;
ret = seq_open(file, &stack_trace_seq_ops);
- if (!ret) {
- struct seq_file *m = file->private_data;
- m->private = (void *)-1;
- }
return ret;
}
diff --git a/lib/dynamic_printk.c b/lib/dynamic_printk.c
index d83660fd6fd..8e30295e856 100644
--- a/lib/dynamic_printk.c
+++ b/lib/dynamic_printk.c
@@ -135,7 +135,7 @@ int unregister_dynamic_debug_module(char *mod_name)
nr_entries--;
out:
up(&debug_list_mutex);
- return 0;
+ return ret;
}
EXPORT_SYMBOL_GPL(unregister_dynamic_debug_module);
@@ -289,7 +289,7 @@ static ssize_t pr_debug_write(struct file *file, const char __user *buf,
dynamic_enabled = DYNAMIC_ENABLED_SOME;
err = 0;
printk(KERN_DEBUG
- "debugging enabled for module %s",
+ "debugging enabled for module %s\n",
elem->name);
} else if (!value && (elem->enable == 1)) {
elem->enable = 0;
@@ -309,7 +309,7 @@ static ssize_t pr_debug_write(struct file *file, const char __user *buf,
err = 0;
printk(KERN_DEBUG
"debugging disabled for module "
- "%s", elem->name);
+ "%s\n", elem->name);
}
}
}
diff --git a/lib/idr.c b/lib/idr.c
index e728c7fccc4..1c4f9281f41 100644
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -185,6 +185,7 @@ static int sub_alloc(struct idr *idp, int *starting_id, struct idr_layer **pa)
new = get_from_free_list(idp);
if (!new)
return -1;
+ new->layer = l-1;
rcu_assign_pointer(p->ary[m], new);
p->count++;
}
@@ -210,6 +211,7 @@ build_up:
if (unlikely(!p)) {
if (!(p = get_from_free_list(idp)))
return -1;
+ p->layer = 0;
layers = 1;
}
/*
@@ -218,8 +220,14 @@ build_up:
*/
while ((layers < (MAX_LEVEL - 1)) && (id >= (1 << (layers*IDR_BITS)))) {
layers++;
- if (!p->count)
+ if (!p->count) {
+ /* special case: if the tree is currently empty,
+ * then we grow the tree by moving the top node
+ * upwards.
+ */
+ p->layer++;
continue;
+ }
if (!(new = get_from_free_list(idp))) {
/*
* The allocation failed. If we built part of
@@ -237,6 +245,7 @@ build_up:
}
new->ary[0] = p;
new->count = 1;
+ new->layer = layers-1;
if (p->bitmap == IDR_FULL)
__set_bit(0, &new->bitmap);
p = new;
@@ -493,17 +502,21 @@ void *idr_find(struct idr *idp, int id)
int n;
struct idr_layer *p;
- n = idp->layers * IDR_BITS;
p = rcu_dereference(idp->top);
+ if (!p)
+ return NULL;
+ n = (p->layer+1) * IDR_BITS;
/* Mask off upper bits we don't use for the search. */
id &= MAX_ID_MASK;
if (id >= (1 << n))
return NULL;
+ BUG_ON(n == 0);
while (n > 0 && p) {
n -= IDR_BITS;
+ BUG_ON(n != p->layer*IDR_BITS);
p = rcu_dereference(p->ary[(id >> n) & IDR_MASK]);
}
return((void *)p);
@@ -582,8 +595,11 @@ void *idr_replace(struct idr *idp, void *ptr, int id)
int n;
struct idr_layer *p, *old_p;
- n = idp->layers * IDR_BITS;
p = idp->top;
+ if (!p)
+ return ERR_PTR(-EINVAL);
+
+ n = (p->layer+1) * IDR_BITS;
id &= MAX_ID_MASK;
diff --git a/lib/percpu_counter.c b/lib/percpu_counter.c
index a8663890a88..b255b939bc1 100644
--- a/lib/percpu_counter.c
+++ b/lib/percpu_counter.c
@@ -62,10 +62,7 @@ s64 __percpu_counter_sum(struct percpu_counter *fbc)
for_each_online_cpu(cpu) {
s32 *pcount = per_cpu_ptr(fbc->counters, cpu);
ret += *pcount;
- *pcount = 0;
}
- fbc->count = ret;
-
spin_unlock(&fbc->lock);
return ret;
}
@@ -104,13 +101,13 @@ void percpu_counter_destroy(struct percpu_counter *fbc)
if (!fbc->counters)
return;
- free_percpu(fbc->counters);
- fbc->counters = NULL;
#ifdef CONFIG_HOTPLUG_CPU
mutex_lock(&percpu_counters_lock);
list_del(&fbc->list);
mutex_unlock(&percpu_counters_lock);
#endif
+ free_percpu(fbc->counters);
+ fbc->counters = NULL;
}
EXPORT_SYMBOL(percpu_counter_destroy);
diff --git a/lib/scatterlist.c b/lib/scatterlist.c
index 8d2688ff135..b7b449dafbe 100644
--- a/lib/scatterlist.c
+++ b/lib/scatterlist.c
@@ -395,7 +395,7 @@ void sg_miter_stop(struct sg_mapping_iter *miter)
WARN_ON(!irqs_disabled());
kunmap_atomic(miter->addr, KM_BIO_SRC_IRQ);
} else
- kunmap(miter->addr);
+ kunmap(miter->page);
miter->page = NULL;
miter->addr = NULL;
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 78330c37a61..5f6c629a924 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -467,9 +467,13 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t size,
dma_addr_t dev_addr;
void *ret;
int order = get_order(size);
+ u64 dma_mask = DMA_32BIT_MASK;
+
+ if (hwdev && hwdev->coherent_dma_mask)
+ dma_mask = hwdev->coherent_dma_mask;
ret = (void *)__get_free_pages(flags, order);
- if (ret && address_needs_mapping(hwdev, virt_to_bus(ret), size)) {
+ if (ret && !is_buffer_dma_capable(dma_mask, virt_to_bus(ret), size)) {
/*
* The allocated memory isn't reachable by the device.
* Fall back on swiotlb_map_single().
@@ -493,9 +497,9 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t size,
dev_addr = virt_to_bus(ret);
/* Confirm address can be DMA'd by device */
- if (address_needs_mapping(hwdev, dev_addr, size)) {
+ if (!is_buffer_dma_capable(dma_mask, dev_addr, size)) {
printk("hwdev DMA mask = 0x%016Lx, dev_addr = 0x%016Lx\n",
- (unsigned long long)*hwdev->dma_mask,
+ (unsigned long long)dma_mask,
(unsigned long long)dev_addr);
/* DMA_TO_DEVICE to avoid memcpy in unmap_single */
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index f2e574dbc30..801c08b046e 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -176,6 +176,9 @@ int bdi_register(struct backing_dev_info *bdi, struct device *parent,
int ret = 0;
struct device *dev;
+ if (bdi->dev) /* The driver needs to use separate queues per device */
+ goto exit;
+
va_start(args, fmt);
dev = device_create_vargs(bdi_class, parent, MKDEV(0, 0), bdi, fmt, args);
va_end(args);
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index d143ab67be4..6058b53dcb8 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -1796,6 +1796,7 @@ void unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start,
static int unmap_ref_private(struct mm_struct *mm, struct vm_area_struct *vma,
struct page *page, unsigned long address)
{
+ struct hstate *h = hstate_vma(vma);
struct vm_area_struct *iter_vma;
struct address_space *mapping;
struct prio_tree_iter iter;
@@ -1805,7 +1806,7 @@ static int unmap_ref_private(struct mm_struct *mm, struct vm_area_struct *vma,
* vm_pgoff is in PAGE_SIZE units, hence the different calculation
* from page cache lookup which is in HPAGE_SIZE units.
*/
- address = address & huge_page_mask(hstate_vma(vma));
+ address = address & huge_page_mask(h);
pgoff = ((address - vma->vm_start) >> PAGE_SHIFT)
+ (vma->vm_pgoff >> PAGE_SHIFT);
mapping = (struct address_space *)page_private(page);
@@ -1824,7 +1825,7 @@ static int unmap_ref_private(struct mm_struct *mm, struct vm_area_struct *vma,
*/
if (!is_vma_resv_set(iter_vma, HPAGE_RESV_OWNER))
unmap_hugepage_range(iter_vma,
- address, address + HPAGE_SIZE,
+ address, address + huge_page_size(h),
page);
}
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 6837a101437..b1737118546 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -22,7 +22,6 @@
#include <linux/highmem.h>
#include <linux/vmalloc.h>
#include <linux/ioport.h>
-#include <linux/cpuset.h>
#include <linux/delay.h>
#include <linux/migrate.h>
#include <linux/page-isolation.h>
@@ -190,7 +189,7 @@ static void grow_pgdat_span(struct pglist_data *pgdat, unsigned long start_pfn,
pgdat->node_start_pfn;
}
-static int __add_zone(struct zone *zone, unsigned long phys_start_pfn)
+static int __meminit __add_zone(struct zone *zone, unsigned long phys_start_pfn)
{
struct pglist_data *pgdat = zone->zone_pgdat;
int nr_pages = PAGES_PER_SECTION;
@@ -217,7 +216,7 @@ static int __add_zone(struct zone *zone, unsigned long phys_start_pfn)
return 0;
}
-static int __add_section(struct zone *zone, unsigned long phys_start_pfn)
+static int __meminit __add_section(struct zone *zone, unsigned long phys_start_pfn)
{
int nr_pages = PAGES_PER_SECTION;
int ret;
@@ -274,7 +273,7 @@ static int __remove_section(struct zone *zone, struct mem_section *ms)
* call this function after deciding the zone to which to
* add the new pages.
*/
-int __add_pages(struct zone *zone, unsigned long phys_start_pfn,
+int __ref __add_pages(struct zone *zone, unsigned long phys_start_pfn,
unsigned long nr_pages)
{
unsigned long i;
@@ -471,7 +470,8 @@ static void rollback_node_hotadd(int nid, pg_data_t *pgdat)
}
-int add_memory(int nid, u64 start, u64 size)
+/* we are OK calling __meminit stuff here - we have CONFIG_MEMORY_HOTPLUG */
+int __ref add_memory(int nid, u64 start, u64 size)
{
pg_data_t *pgdat = NULL;
int new_pgdat = 0;
@@ -498,8 +498,6 @@ int add_memory(int nid, u64 start, u64 size)
/* we online node here. we can't roll back from here. */
node_set_online(nid);
- cpuset_track_online_nodes();
-
if (new_pgdat) {
ret = register_one_node(nid);
/*
diff --git a/mm/migrate.c b/mm/migrate.c
index 385db89f0c3..037b0967c1e 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -522,15 +522,12 @@ static int writeout(struct address_space *mapping, struct page *page)
remove_migration_ptes(page, page);
rc = mapping->a_ops->writepage(page, &wbc);
- if (rc < 0)
- /* I/O Error writing */
- return -EIO;
if (rc != AOP_WRITEPAGE_ACTIVATE)
/* unlocked. Relock */
lock_page(page);
- return -EAGAIN;
+ return (rc < 0) ? -EIO : -EAGAIN;
}
/*
@@ -990,25 +987,18 @@ out:
/*
* Determine the nodes of an array of pages and store it in an array of status.
*/
-static int do_pages_stat(struct mm_struct *mm, unsigned long nr_pages,
- const void __user * __user *pages,
- int __user *status)
+static void do_pages_stat_array(struct mm_struct *mm, unsigned long nr_pages,
+ const void __user **pages, int *status)
{
unsigned long i;
- int err;
down_read(&mm->mmap_sem);
for (i = 0; i < nr_pages; i++) {
- const void __user *p;
- unsigned long addr;
+ unsigned long addr = (unsigned long)(*pages);
struct vm_area_struct *vma;
struct page *page;
-
- err = -EFAULT;
- if (get_user(p, pages+i))
- goto out;
- addr = (unsigned long) p;
+ int err = -EFAULT;
vma = find_vma(mm, addr);
if (!vma)
@@ -1027,12 +1017,52 @@ static int do_pages_stat(struct mm_struct *mm, unsigned long nr_pages,
err = page_to_nid(page);
set_status:
- put_user(err, status+i);
+ *status = err;
+
+ pages++;
+ status++;
+ }
+
+ up_read(&mm->mmap_sem);
+}
+
+/*
+ * Determine the nodes of a user array of pages and store it in
+ * a user array of status.
+ */
+static int do_pages_stat(struct mm_struct *mm, unsigned long nr_pages,
+ const void __user * __user *pages,
+ int __user *status)
+{
+#define DO_PAGES_STAT_CHUNK_NR 16
+ const void __user *chunk_pages[DO_PAGES_STAT_CHUNK_NR];
+ int chunk_status[DO_PAGES_STAT_CHUNK_NR];
+ unsigned long i, chunk_nr = DO_PAGES_STAT_CHUNK_NR;
+ int err;
+
+ for (i = 0; i < nr_pages; i += chunk_nr) {
+ if (chunk_nr + i > nr_pages)
+ chunk_nr = nr_pages - i;
+
+ err = copy_from_user(chunk_pages, &pages[i],
+ chunk_nr * sizeof(*chunk_pages));
+ if (err) {
+ err = -EFAULT;
+ goto out;
+ }
+
+ do_pages_stat_array(mm, chunk_nr, chunk_pages, chunk_status);
+
+ err = copy_to_user(&status[i], chunk_status,
+ chunk_nr * sizeof(*chunk_status));
+ if (err) {
+ err = -EFAULT;
+ goto out;
+ }
}
err = 0;
out:
- up_read(&mm->mmap_sem);
return err;
}
diff --git a/mm/mlock.c b/mm/mlock.c
index 008ea70b7af..1ada366570c 100644
--- a/mm/mlock.c
+++ b/mm/mlock.c
@@ -66,14 +66,10 @@ void __clear_page_mlock(struct page *page)
putback_lru_page(page);
} else {
/*
- * Page not on the LRU yet. Flush all pagevecs and retry.
+ * We lost the race. the page already moved to evictable list.
*/
- lru_add_drain_all();
- if (!isolate_lru_page(page))
- putback_lru_page(page);
- else if (PageUnevictable(page))
+ if (PageUnevictable(page))
count_vm_event(UNEVICTABLE_PGSTRANDED);
-
}
}
@@ -166,7 +162,7 @@ static long __mlock_vma_pages_range(struct vm_area_struct *vma,
unsigned long addr = start;
struct page *pages[16]; /* 16 gives a reasonable batch */
int nr_pages = (end - start) / PAGE_SIZE;
- int ret;
+ int ret = 0;
int gup_flags = 0;
VM_BUG_ON(start & ~PAGE_MASK);
@@ -187,8 +183,6 @@ static long __mlock_vma_pages_range(struct vm_area_struct *vma,
if (vma->vm_flags & VM_WRITE)
gup_flags |= GUP_FLAGS_WRITE;
- lru_add_drain_all(); /* push cached pages to LRU */
-
while (nr_pages > 0) {
int i;
@@ -251,8 +245,6 @@ static long __mlock_vma_pages_range(struct vm_area_struct *vma,
ret = 0;
}
- lru_add_drain_all(); /* to update stats */
-
return ret; /* count entire vma as locked_vm */
}
@@ -546,6 +538,8 @@ asmlinkage long sys_mlock(unsigned long start, size_t len)
if (!can_do_mlock())
return -EPERM;
+ lru_add_drain_all(); /* flush pagevec */
+
down_write(&current->mm->mmap_sem);
len = PAGE_ALIGN(len + (start & ~PAGE_MASK));
start &= PAGE_MASK;
@@ -612,6 +606,8 @@ asmlinkage long sys_mlockall(int flags)
if (!can_do_mlock())
goto out;
+ lru_add_drain_all(); /* flush pagevec */
+
down_write(&current->mm->mmap_sem);
lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur;
diff --git a/mm/mmap.c b/mm/mmap.c
index de14ac21e5b..d4855a682ab 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1704,7 +1704,7 @@ find_extend_vma(struct mm_struct *mm, unsigned long addr)
vma = find_vma_prev(mm, addr, &prev);
if (vma && (vma->vm_start <= addr))
return vma;
- if (expand_stack(prev, addr))
+ if (!prev || expand_stack(prev, addr))
return NULL;
if (prev->vm_flags & VM_LOCKED) {
if (mlock_vma_pages_range(prev, addr, prev->vm_end) < 0)
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 54069e64e3a..d8ac0147456 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -1561,6 +1561,10 @@ nofail_alloc:
/* We now go into synchronous reclaim */
cpuset_memory_pressure_bump();
+ /*
+ * The task's cpuset might have expanded its set of allowable nodes
+ */
+ cpuset_update_task_memory_state();
p->flags |= PF_MEMALLOC;
reclaim_state.reclaimed_slab = 0;
p->reclaim_state = &reclaim_state;
diff --git a/mm/page_cgroup.c b/mm/page_cgroup.c
index f59d797dc5a..ab27ff75051 100644
--- a/mm/page_cgroup.c
+++ b/mm/page_cgroup.c
@@ -21,7 +21,7 @@ static unsigned long total_usage;
#if !defined(CONFIG_SPARSEMEM)
-void __init pgdat_page_cgroup_init(struct pglist_data *pgdat)
+void __meminit pgdat_page_cgroup_init(struct pglist_data *pgdat)
{
pgdat->node_page_cgroup = NULL;
}
@@ -49,6 +49,9 @@ static int __init alloc_node_page_cgroup(int nid)
start_pfn = NODE_DATA(nid)->node_start_pfn;
nr_pages = NODE_DATA(nid)->node_spanned_pages;
+ if (!nr_pages)
+ return 0;
+
table_size = sizeof(struct page_cgroup) * nr_pages;
base = __alloc_bootmem_node_nopanic(NODE_DATA(nid),
@@ -97,7 +100,8 @@ struct page_cgroup *lookup_page_cgroup(struct page *page)
return section->page_cgroup + pfn;
}
-int __meminit init_section_page_cgroup(unsigned long pfn)
+/* __alloc_bootmem...() is protected by !slab_available() */
+int __init_refok init_section_page_cgroup(unsigned long pfn)
{
struct mem_section *section;
struct page_cgroup *base, *pc;
@@ -106,19 +110,29 @@ int __meminit init_section_page_cgroup(unsigned long pfn)
section = __pfn_to_section(pfn);
- if (section->page_cgroup)
- return 0;
-
- nid = page_to_nid(pfn_to_page(pfn));
-
- table_size = sizeof(struct page_cgroup) * PAGES_PER_SECTION;
- if (slab_is_available()) {
- base = kmalloc_node(table_size, GFP_KERNEL, nid);
- if (!base)
- base = vmalloc_node(table_size, nid);
- } else {
- base = __alloc_bootmem_node_nopanic(NODE_DATA(nid), table_size,
+ if (!section->page_cgroup) {
+ nid = page_to_nid(pfn_to_page(pfn));
+ table_size = sizeof(struct page_cgroup) * PAGES_PER_SECTION;
+ if (slab_is_available()) {
+ base = kmalloc_node(table_size, GFP_KERNEL, nid);
+ if (!base)
+ base = vmalloc_node(table_size, nid);
+ } else {
+ base = __alloc_bootmem_node_nopanic(NODE_DATA(nid),
+ table_size,
PAGE_SIZE, __pa(MAX_DMA_ADDRESS));
+ }
+ } else {
+ /*
+ * We don't have to allocate page_cgroup again, but
+ * address of memmap may be changed. So, we have to initialize
+ * again.
+ */
+ base = section->page_cgroup + pfn;
+ table_size = 0;
+ /* check address of memmap is changed or not. */
+ if (base->page == pfn_to_page(pfn))
+ return 0;
}
if (!base) {
@@ -158,14 +172,14 @@ void __free_page_cgroup(unsigned long pfn)
}
}
-int online_page_cgroup(unsigned long start_pfn,
+int __meminit online_page_cgroup(unsigned long start_pfn,
unsigned long nr_pages,
int nid)
{
unsigned long start, end, pfn;
int fail = 0;
- start = start_pfn & (PAGES_PER_SECTION - 1);
+ start = start_pfn & ~(PAGES_PER_SECTION - 1);
end = ALIGN(start_pfn + nr_pages, PAGES_PER_SECTION);
for (pfn = start; !fail && pfn < end; pfn += PAGES_PER_SECTION) {
@@ -183,12 +197,12 @@ int online_page_cgroup(unsigned long start_pfn,
return -ENOMEM;
}
-int offline_page_cgroup(unsigned long start_pfn,
+int __meminit offline_page_cgroup(unsigned long start_pfn,
unsigned long nr_pages, int nid)
{
unsigned long start, end, pfn;
- start = start_pfn & (PAGES_PER_SECTION - 1);
+ start = start_pfn & ~(PAGES_PER_SECTION - 1);
end = ALIGN(start_pfn + nr_pages, PAGES_PER_SECTION);
for (pfn = start; pfn < end; pfn += PAGES_PER_SECTION)
@@ -197,7 +211,7 @@ int offline_page_cgroup(unsigned long start_pfn,
}
-static int page_cgroup_callback(struct notifier_block *self,
+static int __meminit page_cgroup_callback(struct notifier_block *self,
unsigned long action, void *arg)
{
struct memory_notify *mn = arg;
@@ -207,18 +221,23 @@ static int page_cgroup_callback(struct notifier_block *self,
ret = online_page_cgroup(mn->start_pfn,
mn->nr_pages, mn->status_change_nid);
break;
- case MEM_CANCEL_ONLINE:
case MEM_OFFLINE:
offline_page_cgroup(mn->start_pfn,
mn->nr_pages, mn->status_change_nid);
break;
+ case MEM_CANCEL_ONLINE:
case MEM_GOING_OFFLINE:
break;
case MEM_ONLINE:
case MEM_CANCEL_OFFLINE:
break;
}
- ret = notifier_from_errno(ret);
+
+ if (ret)
+ ret = notifier_from_errno(ret);
+ else
+ ret = NOTIFY_OK;
+
return ret;
}
@@ -248,7 +267,7 @@ void __init page_cgroup_init(void)
" want\n");
}
-void __init pgdat_page_cgroup_init(struct pglist_data *pgdat)
+void __meminit pgdat_page_cgroup_init(struct pglist_data *pgdat)
{
return;
}
diff --git a/mm/slob.c b/mm/slob.c
index cb675d12679..bf7e8fc3aed 100644
--- a/mm/slob.c
+++ b/mm/slob.c
@@ -535,7 +535,7 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size,
struct kmem_cache *c;
c = slob_alloc(sizeof(struct kmem_cache),
- flags, ARCH_KMALLOC_MINALIGN, -1);
+ GFP_KERNEL, ARCH_KMALLOC_MINALIGN, -1);
if (c) {
c->name = name;
diff --git a/mm/slub.c b/mm/slub.c
index 7ad489af956..a2cd47d89e0 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -2931,8 +2931,10 @@ static int slab_memory_callback(struct notifier_block *self,
case MEM_CANCEL_OFFLINE:
break;
}
-
- ret = notifier_from_errno(ret);
+ if (ret)
+ ret = notifier_from_errno(ret);
+ else
+ ret = NOTIFY_OK;
return ret;
}
@@ -3595,7 +3597,7 @@ static int list_locations(struct kmem_cache *s, char *buf,
for (i = 0; i < t.count; i++) {
struct location *l = &t.loc[i];
- if (len > PAGE_SIZE - 100)
+ if (len > PAGE_SIZE - KSYM_SYMBOL_LEN - 100)
break;
len += sprintf(buf + len, "%7ld ", l->count);
diff --git a/mm/sparse.c b/mm/sparse.c
index 39db301b920..083f5b63e7a 100644
--- a/mm/sparse.c
+++ b/mm/sparse.c
@@ -570,7 +570,7 @@ static void free_section_usemap(struct page *memmap, unsigned long *usemap)
* set. If this is <=0, then that means that the passed-in
* map was not consumed and must be freed.
*/
-int sparse_add_one_section(struct zone *zone, unsigned long start_pfn,
+int __meminit sparse_add_one_section(struct zone *zone, unsigned long start_pfn,
int nr_pages)
{
unsigned long section_nr = pfn_to_section_nr(start_pfn);
diff --git a/mm/swap.c b/mm/swap.c
index 2152e48a7b8..b135ec90cde 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -299,7 +299,6 @@ void lru_add_drain(void)
put_cpu();
}
-#if defined(CONFIG_NUMA) || defined(CONFIG_UNEVICTABLE_LRU)
static void lru_add_drain_per_cpu(struct work_struct *dummy)
{
lru_add_drain();
@@ -313,18 +312,6 @@ int lru_add_drain_all(void)
return schedule_on_each_cpu(lru_add_drain_per_cpu);
}
-#else
-
-/*
- * Returns 0 for success
- */
-int lru_add_drain_all(void)
-{
- lru_add_drain();
- return 0;
-}
-#endif
-
/*
* Batched page_cache_release(). Decrement the reference count on all the
* passed pages. If it fell to zero then remove the page from the LRU and
@@ -445,6 +432,7 @@ void ____pagevec_lru_add(struct pagevec *pvec, enum lru_list lru)
for (i = 0; i < pagevec_count(pvec); i++) {
struct page *page = pvec->pages[i];
struct zone *pagezone = page_zone(page);
+ int file;
if (pagezone != zone) {
if (zone)
@@ -456,8 +444,12 @@ void ____pagevec_lru_add(struct pagevec *pvec, enum lru_list lru)
VM_BUG_ON(PageUnevictable(page));
VM_BUG_ON(PageLRU(page));
SetPageLRU(page);
- if (is_active_lru(lru))
+ file = is_file_lru(lru);
+ zone->recent_scanned[file]++;
+ if (is_active_lru(lru)) {
SetPageActive(page);
+ zone->recent_rotated[file]++;
+ }
add_page_to_lru_list(zone, page, lru);
}
if (zone)
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index ba6b0f5f7fa..1ddb77ba399 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -77,7 +77,6 @@ static void vunmap_page_range(unsigned long addr, unsigned long end)
BUG_ON(addr >= end);
pgd = pgd_offset_k(addr);
- flush_cache_vunmap(addr, end);
do {
next = pgd_addr_end(addr, end);
if (pgd_none_or_clear_bad(pgd))
@@ -324,14 +323,14 @@ static struct vmap_area *alloc_vmap_area(unsigned long size,
BUG_ON(size & ~PAGE_MASK);
- addr = ALIGN(vstart, align);
-
va = kmalloc_node(sizeof(struct vmap_area),
gfp_mask & GFP_RECLAIM_MASK, node);
if (unlikely(!va))
return ERR_PTR(-ENOMEM);
retry:
+ addr = ALIGN(vstart, align);
+
spin_lock(&vmap_area_lock);
/* XXX: could have a last_hole cache */
n = vmap_area_root.rb_node;
@@ -362,7 +361,7 @@ retry:
goto found;
}
- while (addr + size >= first->va_start && addr + size <= vend) {
+ while (addr + size > first->va_start && addr + size <= vend) {
addr = ALIGN(first->va_end + PAGE_SIZE, align);
n = rb_next(&first->rb_node);
@@ -522,24 +521,45 @@ static void __purge_vmap_area_lazy(unsigned long *start, unsigned long *end,
}
/*
+ * Kick off a purge of the outstanding lazy areas. Don't bother if somebody
+ * is already purging.
+ */
+static void try_purge_vmap_area_lazy(void)
+{
+ unsigned long start = ULONG_MAX, end = 0;
+
+ __purge_vmap_area_lazy(&start, &end, 0, 0);
+}
+
+/*
* Kick off a purge of the outstanding lazy areas.
*/
static void purge_vmap_area_lazy(void)
{
unsigned long start = ULONG_MAX, end = 0;
- __purge_vmap_area_lazy(&start, &end, 0, 0);
+ __purge_vmap_area_lazy(&start, &end, 1, 0);
}
/*
- * Free and unmap a vmap area
+ * Free and unmap a vmap area, caller ensuring flush_cache_vunmap had been
+ * called for the correct range previously.
*/
-static void free_unmap_vmap_area(struct vmap_area *va)
+static void free_unmap_vmap_area_noflush(struct vmap_area *va)
{
va->flags |= VM_LAZY_FREE;
atomic_add((va->va_end - va->va_start) >> PAGE_SHIFT, &vmap_lazy_nr);
if (unlikely(atomic_read(&vmap_lazy_nr) > lazy_max_pages()))
- purge_vmap_area_lazy();
+ try_purge_vmap_area_lazy();
+}
+
+/*
+ * Free and unmap a vmap area
+ */
+static void free_unmap_vmap_area(struct vmap_area *va)
+{
+ flush_cache_vunmap(va->va_start, va->va_end);
+ free_unmap_vmap_area_noflush(va);
}
static struct vmap_area *find_vmap_area(unsigned long addr)
@@ -723,7 +743,7 @@ static void free_vmap_block(struct vmap_block *vb)
spin_unlock(&vmap_block_tree_lock);
BUG_ON(tmp != vb);
- free_unmap_vmap_area(vb->va);
+ free_unmap_vmap_area_noflush(vb->va);
call_rcu(&vb->rcu_head, rcu_free_vb);
}
@@ -785,6 +805,9 @@ static void vb_free(const void *addr, unsigned long size)
BUG_ON(size & ~PAGE_MASK);
BUG_ON(size > PAGE_SIZE*VMAP_MAX_ALLOC);
+
+ flush_cache_vunmap((unsigned long)addr, (unsigned long)addr + size);
+
order = get_order(size);
offset = (unsigned long)addr & (VMAP_BLOCK_SIZE - 1);
@@ -1694,7 +1717,7 @@ static int s_show(struct seq_file *m, void *p)
v->addr, v->addr + v->size, v->size);
if (v->caller) {
- char buff[2 * KSYM_NAME_LEN];
+ char buff[KSYM_SYMBOL_LEN];
seq_putc(m, ' ');
sprint_symbol(buff, (unsigned long)v->caller);
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 3b5860294bb..62e7f62fb55 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -623,6 +623,8 @@ static unsigned long shrink_page_list(struct list_head *page_list,
* Try to allocate it some swap space here.
*/
if (PageAnon(page) && !PageSwapCache(page)) {
+ if (!(sc->gfp_mask & __GFP_IO))
+ goto keep_locked;
switch (try_to_munlock(page)) {
case SWAP_FAIL: /* shouldn't happen */
case SWAP_AGAIN:
@@ -634,6 +636,7 @@ static unsigned long shrink_page_list(struct list_head *page_list,
}
if (!add_to_swap(page, GFP_ATOMIC))
goto activate_locked;
+ may_enter_fs = 1;
}
#endif /* CONFIG_SWAP */
@@ -1245,6 +1248,7 @@ static void shrink_active_list(unsigned long nr_pages, struct zone *zone,
list_add(&page->lru, &l_inactive);
}
+ spin_lock_irq(&zone->lru_lock);
/*
* Count referenced pages from currently used mappings as
* rotated, even though they are moved to the inactive list.
@@ -1260,7 +1264,6 @@ static void shrink_active_list(unsigned long nr_pages, struct zone *zone,
pgmoved = 0;
lru = LRU_BASE + file * LRU_FILE;
- spin_lock_irq(&zone->lru_lock);
while (!list_empty(&l_inactive)) {
page = lru_to_page(&l_inactive);
prefetchw_prev_lru_page(page, &l_inactive, flags);
@@ -1386,9 +1389,9 @@ static void get_scan_ratio(struct zone *zone, struct scan_control *sc,
file_prio = 200 - sc->swappiness;
/*
- * anon recent_rotated[0]
- * %anon = 100 * ----------- / ----------------- * IO cost
- * anon + file rotate_sum
+ * The amount of pressure on anon vs file pages is inversely
+ * proportional to the fraction of recently scanned pages on
+ * each list that were recently referenced and in active use.
*/
ap = (anon_prio + 1) * (zone->recent_scanned[0] + 1);
ap /= zone->recent_rotated[0] + 1;
@@ -2368,39 +2371,6 @@ int page_evictable(struct page *page, struct vm_area_struct *vma)
return 1;
}
-static void show_page_path(struct page *page)
-{
- char buf[256];
- if (page_is_file_cache(page)) {
- struct address_space *mapping = page->mapping;
- struct dentry *dentry;
- pgoff_t pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT);
-
- spin_lock(&mapping->i_mmap_lock);
- dentry = d_find_alias(mapping->host);
- printk(KERN_INFO "rescued: %s %lu\n",
- dentry_path(dentry, buf, 256), pgoff);
- spin_unlock(&mapping->i_mmap_lock);
- } else {
-#if defined(CONFIG_MM_OWNER) && defined(CONFIG_MMU)
- struct anon_vma *anon_vma;
- struct vm_area_struct *vma;
-
- anon_vma = page_lock_anon_vma(page);
- if (!anon_vma)
- return;
-
- list_for_each_entry(vma, &anon_vma->head, anon_vma_node) {
- printk(KERN_INFO "rescued: anon %s\n",
- vma->vm_mm->owner->comm);
- break;
- }
- page_unlock_anon_vma(anon_vma);
-#endif
- }
-}
-
-
/**
* check_move_unevictable_page - check page for evictability and move to appropriate zone lru list
* @page: page to check evictability and move to appropriate lru list
@@ -2421,8 +2391,6 @@ retry:
if (page_evictable(page, NULL)) {
enum lru_list l = LRU_INACTIVE_ANON + page_is_file_cache(page);
- show_page_path(page);
-
__dec_zone_state(zone, NR_UNEVICTABLE);
list_move(&page->lru, &zone->lru[l].list);
__inc_zone_state(zone, NR_INACTIVE_ANON + l);
diff --git a/net/9p/Kconfig b/net/9p/Kconfig
index c42c0c400bf..0663f99e977 100644
--- a/net/9p/Kconfig
+++ b/net/9p/Kconfig
@@ -13,22 +13,24 @@ menuconfig NET_9P
If unsure, say N.
+if NET_9P
+
config NET_9P_VIRTIO
- depends on NET_9P && EXPERIMENTAL && VIRTIO
+ depends on EXPERIMENTAL && VIRTIO
tristate "9P Virtio Transport (Experimental)"
help
This builds support for a transports between
guest partitions and a host partition.
config NET_9P_RDMA
- depends on NET_9P && INFINIBAND && EXPERIMENTAL
+ depends on INET && INFINIBAND && EXPERIMENTAL
tristate "9P RDMA Transport (Experimental)"
help
- This builds support for a RDMA transport.
+ This builds support for an RDMA transport.
config NET_9P_DEBUG
bool "Debug information"
- depends on NET_9P
help
Say Y if you want the 9P subsystem to log debug information.
+endif
diff --git a/net/atm/svc.c b/net/atm/svc.c
index de1e4f2f3a4..8fb54dc870b 100644
--- a/net/atm/svc.c
+++ b/net/atm/svc.c
@@ -293,7 +293,10 @@ static int svc_listen(struct socket *sock,int backlog)
error = -EINVAL;
goto out;
}
- vcc_insert_socket(sk);
+ if (test_bit(ATM_VF_LISTEN, &vcc->flags)) {
+ error = -EADDRINUSE;
+ goto out;
+ }
set_bit(ATM_VF_WAITING, &vcc->flags);
prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
sigd_enq(vcc,as_listen,NULL,NULL,&vcc->local);
@@ -307,6 +310,7 @@ static int svc_listen(struct socket *sock,int backlog)
goto out;
}
set_bit(ATM_VF_LISTEN,&vcc->flags);
+ vcc_insert_socket(sk);
sk->sk_max_ack_backlog = backlog > 0 ? backlog : ATM_BACKLOG_DEFAULT;
error = -sk->sk_err;
out:
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index ba537fae0a4..ce68e046d96 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -1786,8 +1786,6 @@ static inline void rfcomm_accept_connection(struct rfcomm_session *s)
if (err < 0)
return;
- __module_get(nsock->ops->owner);
-
/* Set our callbacks */
nsock->sk->sk_data_ready = rfcomm_l2data_ready;
nsock->sk->sk_state_change = rfcomm_l2state_change;
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index fa5cda4e552..45f61c348e3 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -101,6 +101,18 @@ static inline __be16 pppoe_proto(const struct sk_buff *skb)
pppoe_proto(skb) == htons(PPP_IPV6) && \
brnf_filter_pppoe_tagged)
+static void fake_update_pmtu(struct dst_entry *dst, u32 mtu)
+{
+}
+
+static struct dst_ops fake_dst_ops = {
+ .family = AF_INET,
+ .protocol = __constant_htons(ETH_P_IP),
+ .update_pmtu = fake_update_pmtu,
+ .entry_size = sizeof(struct rtable),
+ .entries = ATOMIC_INIT(0),
+};
+
/*
* Initialize bogus route table used to keep netfilter happy.
* Currently, we fill in the PMTU entry because netfilter
@@ -117,6 +129,7 @@ void br_netfilter_rtable_init(struct net_bridge *br)
rt->u.dst.path = &rt->u.dst;
rt->u.dst.metrics[RTAX_MTU - 1] = 1500;
rt->u.dst.flags = DST_NOXFRM;
+ rt->u.dst.ops = &fake_dst_ops;
}
static inline struct rtable *bridge_parent_rtable(const struct net_device *dev)
diff --git a/net/can/af_can.c b/net/can/af_can.c
index 7d4d2b3c137..3dadb338add 100644
--- a/net/can/af_can.c
+++ b/net/can/af_can.c
@@ -319,23 +319,52 @@ static struct dev_rcv_lists *find_dev_rcv_lists(struct net_device *dev)
return n ? d : NULL;
}
+/**
+ * find_rcv_list - determine optimal filterlist inside device filter struct
+ * @can_id: pointer to CAN identifier of a given can_filter
+ * @mask: pointer to CAN mask of a given can_filter
+ * @d: pointer to the device filter struct
+ *
+ * Description:
+ * Returns the optimal filterlist to reduce the filter handling in the
+ * receive path. This function is called by service functions that need
+ * to register or unregister a can_filter in the filter lists.
+ *
+ * A filter matches in general, when
+ *
+ * <received_can_id> & mask == can_id & mask
+ *
+ * so every bit set in the mask (even CAN_EFF_FLAG, CAN_RTR_FLAG) describe
+ * relevant bits for the filter.
+ *
+ * The filter can be inverted (CAN_INV_FILTER bit set in can_id) or it can
+ * filter for error frames (CAN_ERR_FLAG bit set in mask). For error frames
+ * there is a special filterlist and a special rx path filter handling.
+ *
+ * Return:
+ * Pointer to optimal filterlist for the given can_id/mask pair.
+ * Constistency checked mask.
+ * Reduced can_id to have a preprocessed filter compare value.
+ */
static struct hlist_head *find_rcv_list(canid_t *can_id, canid_t *mask,
struct dev_rcv_lists *d)
{
canid_t inv = *can_id & CAN_INV_FILTER; /* save flag before masking */
- /* filter error frames */
+ /* filter for error frames in extra filterlist */
if (*mask & CAN_ERR_FLAG) {
- /* clear CAN_ERR_FLAG in list entry */
+ /* clear CAN_ERR_FLAG in filter entry */
*mask &= CAN_ERR_MASK;
return &d->rx[RX_ERR];
}
- /* ensure valid values in can_mask */
- if (*mask & CAN_EFF_FLAG)
- *mask &= (CAN_EFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG);
- else
- *mask &= (CAN_SFF_MASK | CAN_RTR_FLAG);
+ /* with cleared CAN_ERR_FLAG we have a simple mask/value filterpair */
+
+#define CAN_EFF_RTR_FLAGS (CAN_EFF_FLAG | CAN_RTR_FLAG)
+
+ /* ensure valid values in can_mask for 'SFF only' frame filtering */
+ if ((*mask & CAN_EFF_FLAG) && !(*can_id & CAN_EFF_FLAG))
+ *mask &= (CAN_SFF_MASK | CAN_EFF_RTR_FLAGS);
/* reduce condition testing at receive time */
*can_id &= *mask;
@@ -348,15 +377,19 @@ static struct hlist_head *find_rcv_list(canid_t *can_id, canid_t *mask,
if (!(*mask))
return &d->rx[RX_ALL];
- /* use extra filterset for the subscription of exactly *ONE* can_id */
- if (*can_id & CAN_EFF_FLAG) {
- if (*mask == (CAN_EFF_MASK | CAN_EFF_FLAG)) {
- /* RFC: a use-case for hash-tables in the future? */
- return &d->rx[RX_EFF];
+ /* extra filterlists for the subscription of a single non-RTR can_id */
+ if (((*mask & CAN_EFF_RTR_FLAGS) == CAN_EFF_RTR_FLAGS)
+ && !(*can_id & CAN_RTR_FLAG)) {
+
+ if (*can_id & CAN_EFF_FLAG) {
+ if (*mask == (CAN_EFF_MASK | CAN_EFF_RTR_FLAGS)) {
+ /* RFC: a future use-case for hash-tables? */
+ return &d->rx[RX_EFF];
+ }
+ } else {
+ if (*mask == (CAN_SFF_MASK | CAN_EFF_RTR_FLAGS))
+ return &d->rx_sff[*can_id];
}
- } else {
- if (*mask == CAN_SFF_MASK)
- return &d->rx_sff[*can_id];
}
/* default: filter via can_id/can_mask */
@@ -589,7 +622,10 @@ static int can_rcv_filter(struct dev_rcv_lists *d, struct sk_buff *skb)
}
}
- /* check CAN_ID specific entries */
+ /* check filterlists for single non-RTR can_ids */
+ if (can_id & CAN_RTR_FLAG)
+ return matches;
+
if (can_id & CAN_EFF_FLAG) {
hlist_for_each_entry_rcu(r, n, &d->rx[RX_EFF], list) {
if (r->can_id == can_id) {
diff --git a/net/can/bcm.c b/net/can/bcm.c
index d0dd382001e..da0d426c0ce 100644
--- a/net/can/bcm.c
+++ b/net/can/bcm.c
@@ -64,10 +64,11 @@
#define BCM_CAN_DLC_MASK 0x0F /* clean private flags in can_dlc by masking */
/* get best masking value for can_rx_register() for a given single can_id */
-#define REGMASK(id) ((id & CAN_RTR_FLAG) | ((id & CAN_EFF_FLAG) ? \
- (CAN_EFF_MASK | CAN_EFF_FLAG) : CAN_SFF_MASK))
+#define REGMASK(id) ((id & CAN_EFF_FLAG) ? \
+ (CAN_EFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG) : \
+ (CAN_SFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG))
-#define CAN_BCM_VERSION "20080415"
+#define CAN_BCM_VERSION CAN_VERSION
static __initdata const char banner[] = KERN_INFO
"can: broadcast manager protocol (rev " CAN_BCM_VERSION ")\n";
diff --git a/net/compat.c b/net/compat.c
index 67fb6a3834a..a3a2ba0fac0 100644
--- a/net/compat.c
+++ b/net/compat.c
@@ -226,14 +226,14 @@ int put_cmsg_compat(struct msghdr *kmsg, int level, int type, int len, void *dat
return 0; /* XXX: return error? check spec. */
}
- if (level == SOL_SOCKET && type == SO_TIMESTAMP) {
+ if (level == SOL_SOCKET && type == SCM_TIMESTAMP) {
struct timeval *tv = (struct timeval *)data;
ctv.tv_sec = tv->tv_sec;
ctv.tv_usec = tv->tv_usec;
data = &ctv;
len = sizeof(ctv);
}
- if (level == SOL_SOCKET && type == SO_TIMESTAMPNS) {
+ if (level == SOL_SOCKET && type == SCM_TIMESTAMPNS) {
struct timespec *ts = (struct timespec *)data;
cts.tv_sec = ts->tv_sec;
cts.tv_nsec = ts->tv_nsec;
@@ -725,7 +725,7 @@ EXPORT_SYMBOL(compat_mc_getsockopt);
static unsigned char nas[19]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
AL(3),AL(3),AL(4),AL(4),AL(4),AL(6),
AL(6),AL(2),AL(5),AL(5),AL(3),AL(3),
- AL(6)};
+ AL(4)};
#undef AL
asmlinkage long compat_sys_sendmsg(int fd, struct compat_msghdr __user *msg, unsigned flags)
@@ -738,52 +738,13 @@ asmlinkage long compat_sys_recvmsg(int fd, struct compat_msghdr __user *msg, uns
return sys_recvmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT);
}
-asmlinkage long compat_sys_paccept(int fd, struct sockaddr __user *upeer_sockaddr,
- int __user *upeer_addrlen,
- const compat_sigset_t __user *sigmask,
- compat_size_t sigsetsize, int flags)
-{
- compat_sigset_t ss32;
- sigset_t ksigmask, sigsaved;
- int ret;
-
- if (sigmask) {
- if (sigsetsize != sizeof(compat_sigset_t))
- return -EINVAL;
- if (copy_from_user(&ss32, sigmask, sizeof(ss32)))
- return -EFAULT;
- sigset_from_compat(&ksigmask, &ss32);
-
- sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
- sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
- }
-
- ret = do_accept(fd, upeer_sockaddr, upeer_addrlen, flags);
-
- if (ret == -ERESTARTNOHAND) {
- /*
- * Don't restore the signal mask yet. Let do_signal() deliver
- * the signal on the way back to userspace, before the signal
- * mask is restored.
- */
- if (sigmask) {
- memcpy(&current->saved_sigmask, &sigsaved,
- sizeof(sigsaved));
- set_restore_sigmask();
- }
- } else if (sigmask)
- sigprocmask(SIG_SETMASK, &sigsaved, NULL);
-
- return ret;
-}
-
asmlinkage long compat_sys_socketcall(int call, u32 __user *args)
{
int ret;
u32 a[6];
u32 a0, a1;
- if (call < SYS_SOCKET || call > SYS_PACCEPT)
+ if (call < SYS_SOCKET || call > SYS_ACCEPT4)
return -EINVAL;
if (copy_from_user(a, args, nas[call]))
return -EFAULT;
@@ -804,7 +765,7 @@ asmlinkage long compat_sys_socketcall(int call, u32 __user *args)
ret = sys_listen(a0, a1);
break;
case SYS_ACCEPT:
- ret = do_accept(a0, compat_ptr(a1), compat_ptr(a[2]), 0);
+ ret = sys_accept4(a0, compat_ptr(a1), compat_ptr(a[2]), 0);
break;
case SYS_GETSOCKNAME:
ret = sys_getsockname(a0, compat_ptr(a1), compat_ptr(a[2]));
@@ -844,9 +805,8 @@ asmlinkage long compat_sys_socketcall(int call, u32 __user *args)
case SYS_RECVMSG:
ret = compat_sys_recvmsg(a0, compat_ptr(a1), a[2]);
break;
- case SYS_PACCEPT:
- ret = compat_sys_paccept(a0, compat_ptr(a1), compat_ptr(a[2]),
- compat_ptr(a[3]), a[4], a[5]);
+ case SYS_ACCEPT4:
+ ret = sys_accept4(a0, compat_ptr(a1), compat_ptr(a[2]), a[3]);
break;
default:
ret = -EINVAL;
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 6c7af390be0..dadac6281f2 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -133,9 +133,11 @@ static int poll_one_napi(struct netpoll_info *npinfo,
npinfo->rx_flags |= NETPOLL_RX_DROP;
atomic_inc(&trapped);
+ set_bit(NAPI_STATE_NPSVC, &napi->state);
work = napi->poll(napi, budget);
+ clear_bit(NAPI_STATE_NPSVC, &napi->state);
atomic_dec(&trapped);
npinfo->rx_flags &= ~NETPOLL_RX_DROP;
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index a47f5bad110..8997e912aaa 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -1973,13 +1973,7 @@ static void pktgen_setup_inject(struct pktgen_dev *pkt_dev)
/* make sure that we don't pick a non-existing transmit queue */
ntxq = pkt_dev->odev->real_num_tx_queues;
- if (ntxq > num_online_cpus() && (pkt_dev->flags & F_QUEUE_MAP_CPU)) {
- printk(KERN_WARNING "pktgen: WARNING: QUEUE_MAP_CPU "
- "disabled because CPU count (%d) exceeds number "
- "of tx queues (%d) on %s\n", num_online_cpus(), ntxq,
- pkt_dev->odev->name);
- pkt_dev->flags &= ~F_QUEUE_MAP_CPU;
- }
+
if (ntxq <= pkt_dev->queue_map_min) {
printk(KERN_WARNING "pktgen: WARNING: Requested "
"queue_map_min (zero-based) (%d) exceeds valid range "
@@ -2202,6 +2196,7 @@ static void set_cur_queue_map(struct pktgen_dev *pkt_dev)
}
pkt_dev->cur_queue_map = t;
}
+ pkt_dev->cur_queue_map = pkt_dev->cur_queue_map % pkt_dev->odev->real_num_tx_queues;
}
/* Increment/randomize headers according to flags and current values
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 31f29d2989f..4dfb6b4d455 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -878,7 +878,9 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
if (ifm->ifi_change)
flags = (flags & ifm->ifi_change) |
(dev->flags & ~ifm->ifi_change);
- dev_change_flags(dev, flags);
+ err = dev_change_flags(dev, flags);
+ if (err < 0)
+ goto errout;
}
if (tb[IFLA_TXQLEN])
diff --git a/net/core/scm.c b/net/core/scm.c
index ab242cc1acc..b12303dd39d 100644
--- a/net/core/scm.c
+++ b/net/core/scm.c
@@ -75,7 +75,6 @@ static int scm_fp_copy(struct cmsghdr *cmsg, struct scm_fp_list **fplp)
if (!fpl)
return -ENOMEM;
*fplp = fpl;
- INIT_LIST_HEAD(&fpl->list);
fpl->count = 0;
}
fpp = &fpl->fp[fpl->count];
@@ -301,7 +300,6 @@ struct scm_fp_list *scm_fp_dup(struct scm_fp_list *fpl)
new_fpl = kmalloc(sizeof(*fpl), GFP_KERNEL);
if (new_fpl) {
- INIT_LIST_HEAD(&new_fpl->list);
for (i=fpl->count-1; i>=0; i--)
get_file(fpl->fp[i]);
memcpy(new_fpl, fpl, sizeof(*fpl));
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index d49ef8301b5..65f7757465b 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -149,7 +149,7 @@ void skb_under_panic(struct sk_buff *skb, int sz, void *here)
void skb_truesize_bug(struct sk_buff *skb)
{
- printk(KERN_ERR "SKB BUG: Invalid truesize (%u) "
+ WARN(net_ratelimit(), KERN_ERR "SKB BUG: Invalid truesize (%u) "
"len=%u, sizeof(sk_buff)=%Zd\n",
skb->truesize, skb->len, sizeof(struct sk_buff));
}
diff --git a/net/core/sock.c b/net/core/sock.c
index 5e2a3132a8c..edf7220889a 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -136,7 +136,6 @@
static struct lock_class_key af_family_keys[AF_MAX];
static struct lock_class_key af_family_slock_keys[AF_MAX];
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
/*
* Make lock validator output more readable. (we pre-construct these
* strings build-time, so that runtime initialization of socket
@@ -187,7 +186,6 @@ static const char *af_family_clock_key_strings[AF_MAX+1] = {
"clock-AF_RXRPC" , "clock-AF_ISDN" , "clock-AF_PHONET" ,
"clock-AF_MAX"
};
-#endif
/*
* sk_callback_lock locking rules are per-address-family,
@@ -2037,9 +2035,6 @@ static inline void release_proto_idx(struct proto *prot)
int proto_register(struct proto *prot, int alloc_slab)
{
- char *request_sock_slab_name = NULL;
- char *timewait_sock_slab_name;
-
if (alloc_slab) {
prot->slab = kmem_cache_create(prot->name, prot->obj_size, 0,
SLAB_HWCACHE_ALIGN, NULL);
@@ -2053,12 +2048,12 @@ int proto_register(struct proto *prot, int alloc_slab)
if (prot->rsk_prot != NULL) {
static const char mask[] = "request_sock_%s";
- request_sock_slab_name = kmalloc(strlen(prot->name) + sizeof(mask) - 1, GFP_KERNEL);
- if (request_sock_slab_name == NULL)
+ prot->rsk_prot->slab_name = kmalloc(strlen(prot->name) + sizeof(mask) - 1, GFP_KERNEL);
+ if (prot->rsk_prot->slab_name == NULL)
goto out_free_sock_slab;
- sprintf(request_sock_slab_name, mask, prot->name);
- prot->rsk_prot->slab = kmem_cache_create(request_sock_slab_name,
+ sprintf(prot->rsk_prot->slab_name, mask, prot->name);
+ prot->rsk_prot->slab = kmem_cache_create(prot->rsk_prot->slab_name,
prot->rsk_prot->obj_size, 0,
SLAB_HWCACHE_ALIGN, NULL);
@@ -2072,14 +2067,14 @@ int proto_register(struct proto *prot, int alloc_slab)
if (prot->twsk_prot != NULL) {
static const char mask[] = "tw_sock_%s";
- timewait_sock_slab_name = kmalloc(strlen(prot->name) + sizeof(mask) - 1, GFP_KERNEL);
+ prot->twsk_prot->twsk_slab_name = kmalloc(strlen(prot->name) + sizeof(mask) - 1, GFP_KERNEL);
- if (timewait_sock_slab_name == NULL)
+ if (prot->twsk_prot->twsk_slab_name == NULL)
goto out_free_request_sock_slab;
- sprintf(timewait_sock_slab_name, mask, prot->name);
+ sprintf(prot->twsk_prot->twsk_slab_name, mask, prot->name);
prot->twsk_prot->twsk_slab =
- kmem_cache_create(timewait_sock_slab_name,
+ kmem_cache_create(prot->twsk_prot->twsk_slab_name,
prot->twsk_prot->twsk_obj_size,
0, SLAB_HWCACHE_ALIGN,
NULL);
@@ -2095,14 +2090,14 @@ int proto_register(struct proto *prot, int alloc_slab)
return 0;
out_free_timewait_sock_slab_name:
- kfree(timewait_sock_slab_name);
+ kfree(prot->twsk_prot->twsk_slab_name);
out_free_request_sock_slab:
if (prot->rsk_prot && prot->rsk_prot->slab) {
kmem_cache_destroy(prot->rsk_prot->slab);
prot->rsk_prot->slab = NULL;
}
out_free_request_sock_slab_name:
- kfree(request_sock_slab_name);
+ kfree(prot->rsk_prot->slab_name);
out_free_sock_slab:
kmem_cache_destroy(prot->slab);
prot->slab = NULL;
@@ -2125,18 +2120,14 @@ void proto_unregister(struct proto *prot)
}
if (prot->rsk_prot != NULL && prot->rsk_prot->slab != NULL) {
- const char *name = kmem_cache_name(prot->rsk_prot->slab);
-
kmem_cache_destroy(prot->rsk_prot->slab);
- kfree(name);
+ kfree(prot->rsk_prot->slab_name);
prot->rsk_prot->slab = NULL;
}
if (prot->twsk_prot != NULL && prot->twsk_prot->twsk_slab != NULL) {
- const char *name = kmem_cache_name(prot->twsk_prot->twsk_slab);
-
kmem_cache_destroy(prot->twsk_prot->twsk_slab);
- kfree(name);
+ kfree(prot->twsk_prot->twsk_slab_name);
prot->twsk_prot->twsk_slab = NULL;
}
}
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 1fbff5fa424..1aa2dc9e380 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1117,6 +1117,7 @@ int inet_sk_rebuild_header(struct sock *sk)
},
},
.proto = sk->sk_protocol,
+ .flags = inet_sk_flowi_flags(sk),
.uli_u = {
.ports = {
.sport = inet->sport,
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index 861978a4f1a..cfb38ac9d69 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -209,9 +209,17 @@ static int ip_local_deliver_finish(struct sk_buff *skb)
hash = protocol & (MAX_INET_PROTOS - 1);
ipprot = rcu_dereference(inet_protos[hash]);
- if (ipprot != NULL && (net == &init_net || ipprot->netns_ok)) {
+ if (ipprot != NULL) {
int ret;
+ if (!net_eq(net, &init_net) && !ipprot->netns_ok) {
+ if (net_ratelimit())
+ printk("%s: proto %d isn't netns-ready\n",
+ __func__, protocol);
+ kfree_skb(skb);
+ goto out;
+ }
+
if (!ipprot->no_policy) {
if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
kfree_skb(skb);
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index b42e082cc17..25924b1eb2e 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -1945,13 +1945,14 @@ int __init ip_mr_init(void)
goto proc_cache_fail;
#endif
return 0;
-reg_notif_fail:
- kmem_cache_destroy(mrt_cachep);
#ifdef CONFIG_PROC_FS
-proc_vif_fail:
- unregister_netdevice_notifier(&ip_mr_notifier);
proc_cache_fail:
proc_net_remove(&init_net, "ip_mr_vif");
+proc_vif_fail:
+ unregister_netdevice_notifier(&ip_mr_notifier);
#endif
+reg_notif_fail:
+ del_timer(&ipmr_expire_timer);
+ kmem_cache_destroy(mrt_cachep);
return err;
}
diff --git a/net/ipv4/netfilter/nf_nat_rule.c b/net/ipv4/netfilter/nf_nat_rule.c
index bea54a68510..8d489e746b2 100644
--- a/net/ipv4/netfilter/nf_nat_rule.c
+++ b/net/ipv4/netfilter/nf_nat_rule.c
@@ -61,7 +61,7 @@ static struct
static struct xt_table nat_table = {
.name = "nat",
.valid_hooks = NAT_VALID_HOOKS,
- .lock = __RW_LOCK_UNLOCKED(__nat_table.lock),
+ .lock = __RW_LOCK_UNLOCKED(nat_table.lock),
.me = THIS_MODULE,
.af = AF_INET,
};
diff --git a/net/ipv4/tcp_htcp.c b/net/ipv4/tcp_htcp.c
index af99776146f..937549b8a92 100644
--- a/net/ipv4/tcp_htcp.c
+++ b/net/ipv4/tcp_htcp.c
@@ -69,9 +69,12 @@ static u32 htcp_cwnd_undo(struct sock *sk)
const struct tcp_sock *tp = tcp_sk(sk);
struct htcp *ca = inet_csk_ca(sk);
- ca->last_cong = ca->undo_last_cong;
- ca->maxRTT = ca->undo_maxRTT;
- ca->old_maxB = ca->undo_old_maxB;
+ if (ca->undo_last_cong) {
+ ca->last_cong = ca->undo_last_cong;
+ ca->maxRTT = ca->undo_maxRTT;
+ ca->old_maxB = ca->undo_old_maxB;
+ ca->undo_last_cong = 0;
+ }
return max(tp->snd_cwnd, (tp->snd_ssthresh << 7) / ca->beta);
}
@@ -268,7 +271,10 @@ static void htcp_state(struct sock *sk, u8 new_state)
case TCP_CA_Open:
{
struct htcp *ca = inet_csk_ca(sk);
- ca->last_cong = jiffies;
+ if (ca->undo_last_cong) {
+ ca->last_cong = jiffies;
+ ca->undo_last_cong = 0;
+ }
}
break;
case TCP_CA_CWR:
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index ba85d883189..fe3b4bdfd25 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -1028,10 +1028,6 @@ unsigned int tcp_sync_mss(struct sock *sk, u32 pmtu)
/* Compute the current effective MSS, taking SACKs and IP options,
* and even PMTU discovery events into account.
- *
- * LARGESEND note: !tcp_urg_mode is overkill, only frames up to snd_up
- * cannot be large. However, taking into account rare use of URG, this
- * is not a big flaw.
*/
unsigned int tcp_current_mss(struct sock *sk, int large_allowed)
{
@@ -1046,7 +1042,7 @@ unsigned int tcp_current_mss(struct sock *sk, int large_allowed)
mss_now = tp->mss_cache;
- if (large_allowed && sk_can_gso(sk) && !tcp_urg_mode(tp))
+ if (large_allowed && sk_can_gso(sk))
doing_tso = 1;
if (dst) {
@@ -1516,6 +1512,10 @@ static int tcp_mtu_probe(struct sock *sk)
* send_head. This happens as incoming acks open up the remote
* window for us.
*
+ * LARGESEND note: !tcp_urg_mode is overkill, only frames between
+ * snd_up-64k-mss .. snd_up cannot be large. However, taking into
+ * account rare use of URG, this is not a big flaw.
+ *
* Returns 1, if no segments are in flight and we have queued segments, but
* cannot send anything now because of SWS or another problem.
*/
@@ -1567,7 +1567,7 @@ static int tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle)
}
limit = mss_now;
- if (tso_segs > 1)
+ if (tso_segs > 1 && !tcp_urg_mode(tp))
limit = tcp_mss_split_point(sk, skb, mss_now,
cwnd_quota);
@@ -1616,6 +1616,7 @@ void __tcp_push_pending_frames(struct sock *sk, unsigned int cur_mss,
*/
void tcp_push_one(struct sock *sk, unsigned int mss_now)
{
+ struct tcp_sock *tp = tcp_sk(sk);
struct sk_buff *skb = tcp_send_head(sk);
unsigned int tso_segs, cwnd_quota;
@@ -1630,7 +1631,7 @@ void tcp_push_one(struct sock *sk, unsigned int mss_now)
BUG_ON(!tso_segs);
limit = mss_now;
- if (tso_segs > 1)
+ if (tso_segs > 1 && !tcp_urg_mode(tp))
limit = tcp_mss_split_point(sk, skb, mss_now,
cwnd_quota);
diff --git a/net/ipv4/tcp_vegas.c b/net/ipv4/tcp_vegas.c
index 14504dada11..a453aac91bd 100644
--- a/net/ipv4/tcp_vegas.c
+++ b/net/ipv4/tcp_vegas.c
@@ -40,18 +40,14 @@
#include "tcp_vegas.h"
-/* Default values of the Vegas variables, in fixed-point representation
- * with V_PARAM_SHIFT bits to the right of the binary point.
- */
-#define V_PARAM_SHIFT 1
-static int alpha = 2<<V_PARAM_SHIFT;
-static int beta = 4<<V_PARAM_SHIFT;
-static int gamma = 1<<V_PARAM_SHIFT;
+static int alpha = 2;
+static int beta = 4;
+static int gamma = 1;
module_param(alpha, int, 0644);
-MODULE_PARM_DESC(alpha, "lower bound of packets in network (scale by 2)");
+MODULE_PARM_DESC(alpha, "lower bound of packets in network");
module_param(beta, int, 0644);
-MODULE_PARM_DESC(beta, "upper bound of packets in network (scale by 2)");
+MODULE_PARM_DESC(beta, "upper bound of packets in network");
module_param(gamma, int, 0644);
MODULE_PARM_DESC(gamma, "limit on increase (scale by 2)");
@@ -172,49 +168,13 @@ static void tcp_vegas_cong_avoid(struct sock *sk, u32 ack, u32 in_flight)
return;
}
- /* The key players are v_beg_snd_una and v_beg_snd_nxt.
- *
- * These are so named because they represent the approximate values
- * of snd_una and snd_nxt at the beginning of the current RTT. More
- * precisely, they represent the amount of data sent during the RTT.
- * At the end of the RTT, when we receive an ACK for v_beg_snd_nxt,
- * we will calculate that (v_beg_snd_nxt - v_beg_snd_una) outstanding
- * bytes of data have been ACKed during the course of the RTT, giving
- * an "actual" rate of:
- *
- * (v_beg_snd_nxt - v_beg_snd_una) / (rtt duration)
- *
- * Unfortunately, v_beg_snd_una is not exactly equal to snd_una,
- * because delayed ACKs can cover more than one segment, so they
- * don't line up nicely with the boundaries of RTTs.
- *
- * Another unfortunate fact of life is that delayed ACKs delay the
- * advance of the left edge of our send window, so that the number
- * of bytes we send in an RTT is often less than our cwnd will allow.
- * So we keep track of our cwnd separately, in v_beg_snd_cwnd.
- */
-
if (after(ack, vegas->beg_snd_nxt)) {
/* Do the Vegas once-per-RTT cwnd adjustment. */
- u32 old_wnd, old_snd_cwnd;
-
-
- /* Here old_wnd is essentially the window of data that was
- * sent during the previous RTT, and has all
- * been acknowledged in the course of the RTT that ended
- * with the ACK we just received. Likewise, old_snd_cwnd
- * is the cwnd during the previous RTT.
- */
- old_wnd = (vegas->beg_snd_nxt - vegas->beg_snd_una) /
- tp->mss_cache;
- old_snd_cwnd = vegas->beg_snd_cwnd;
/* Save the extent of the current window so we can use this
* at the end of the next RTT.
*/
- vegas->beg_snd_una = vegas->beg_snd_nxt;
vegas->beg_snd_nxt = tp->snd_nxt;
- vegas->beg_snd_cwnd = tp->snd_cwnd;
/* We do the Vegas calculations only if we got enough RTT
* samples that we can be reasonably sure that we got
@@ -252,22 +212,14 @@ static void tcp_vegas_cong_avoid(struct sock *sk, u32 ack, u32 in_flight)
*
* This is:
* (actual rate in segments) * baseRTT
- * We keep it as a fixed point number with
- * V_PARAM_SHIFT bits to the right of the binary point.
*/
- target_cwnd = ((u64)old_wnd * vegas->baseRTT);
- target_cwnd <<= V_PARAM_SHIFT;
- do_div(target_cwnd, rtt);
+ target_cwnd = tp->snd_cwnd * vegas->baseRTT / rtt;
/* Calculate the difference between the window we had,
* and the window we would like to have. This quantity
* is the "Diff" from the Arizona Vegas papers.
- *
- * Again, this is a fixed point number with
- * V_PARAM_SHIFT bits to the right of the binary
- * point.
*/
- diff = (old_wnd << V_PARAM_SHIFT) - target_cwnd;
+ diff = tp->snd_cwnd * (rtt-vegas->baseRTT) / vegas->baseRTT;
if (diff > gamma && tp->snd_ssthresh > 2 ) {
/* Going too fast. Time to slow down
@@ -282,16 +234,13 @@ static void tcp_vegas_cong_avoid(struct sock *sk, u32 ack, u32 in_flight)
* truncation robs us of full link
* utilization.
*/
- tp->snd_cwnd = min(tp->snd_cwnd,
- ((u32)target_cwnd >>
- V_PARAM_SHIFT)+1);
+ tp->snd_cwnd = min(tp->snd_cwnd, (u32)target_cwnd+1);
} else if (tp->snd_cwnd <= tp->snd_ssthresh) {
/* Slow start. */
tcp_slow_start(tp);
} else {
/* Congestion avoidance. */
- u32 next_snd_cwnd;
/* Figure out where we would like cwnd
* to be.
@@ -300,32 +249,25 @@ static void tcp_vegas_cong_avoid(struct sock *sk, u32 ack, u32 in_flight)
/* The old window was too fast, so
* we slow down.
*/
- next_snd_cwnd = old_snd_cwnd - 1;
+ tp->snd_cwnd--;
} else if (diff < alpha) {
/* We don't have enough extra packets
* in the network, so speed up.
*/
- next_snd_cwnd = old_snd_cwnd + 1;
+ tp->snd_cwnd++;
} else {
/* Sending just as fast as we
* should be.
*/
- next_snd_cwnd = old_snd_cwnd;
}
-
- /* Adjust cwnd upward or downward, toward the
- * desired value.
- */
- if (next_snd_cwnd > tp->snd_cwnd)
- tp->snd_cwnd++;
- else if (next_snd_cwnd < tp->snd_cwnd)
- tp->snd_cwnd--;
}
if (tp->snd_cwnd < 2)
tp->snd_cwnd = 2;
else if (tp->snd_cwnd > tp->snd_cwnd_clamp)
tp->snd_cwnd = tp->snd_cwnd_clamp;
+
+ tp->snd_ssthresh = tcp_current_ssthresh(sk);
}
/* Wipe the slate clean for the next RTT. */
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index cf02701ced4..98c1fd09be8 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -633,6 +633,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
.saddr = saddr,
.tos = tos } },
.proto = sk->sk_protocol,
+ .flags = inet_sk_flowi_flags(sk),
.uli_u = { .ports =
{ .sport = inet->sport,
.dport = dport } } };
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index 410046a8cc9..e44deb8d4df 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -661,6 +661,11 @@ int datagram_send_ctl(struct net *net,
switch (rthdr->type) {
#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
case IPV6_SRCRT_TYPE_2:
+ if (rthdr->hdrlen != 2 ||
+ rthdr->segments_left != 1) {
+ err = -EINVAL;
+ goto exit_f;
+ }
break;
#endif
default:
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 52a7eb0e2c2..0524769632e 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -224,7 +224,7 @@ static struct file_operations ip6mr_vif_fops = {
.open = ip6mr_vif_open,
.read = seq_read,
.llseek = seq_lseek,
- .release = seq_release,
+ .release = seq_release_private,
};
static void *ipmr_mfc_seq_start(struct seq_file *seq, loff_t *pos)
@@ -338,7 +338,7 @@ static struct file_operations ip6mr_mfc_fops = {
.open = ipmr_mfc_open,
.read = seq_read,
.llseek = seq_lseek,
- .release = seq_release,
+ .release = seq_release_private,
};
#endif
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index 4e5eac301f9..2aa294be0c7 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -366,11 +366,16 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
}
/* routing header option needs extra check */
+ retv = -EINVAL;
if (optname == IPV6_RTHDR && opt && opt->srcrt) {
struct ipv6_rt_hdr *rthdr = opt->srcrt;
switch (rthdr->type) {
#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
case IPV6_SRCRT_TYPE_2:
+ if (rthdr->hdrlen != 2 ||
+ rthdr->segments_left != 1)
+ goto sticky_done;
+
break;
#endif
default:
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 172438320ee..d0f54d18e19 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -912,8 +912,13 @@ static void ndisc_recv_na(struct sk_buff *skb)
is invalid, but ndisc specs say nothing
about it. It could be misconfiguration, or
an smart proxy agent tries to help us :-)
+
+ We should not print the error if NA has been
+ received from loopback - it is just our own
+ unsolicited advertisement.
*/
- ND_PRINTK1(KERN_WARNING
+ if (skb->pkt_type != PACKET_LOOPBACK)
+ ND_PRINTK1(KERN_WARNING
"ICMPv6 NA: someone advertises our address on %s!\n",
ifp->idev->dev->name);
in6_ifa_put(ifp);
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c
index 07f0b76e742..97c17fdd6f7 100644
--- a/net/ipv6/proc.c
+++ b/net/ipv6/proc.c
@@ -132,7 +132,7 @@ static struct snmp_mib snmp6_udplite6_list[] = {
static void snmp6_seq_show_icmpv6msg(struct seq_file *seq, void **mib)
{
- static char name[32];
+ char name[32];
int i;
/* print by name -- deprecated items */
@@ -144,7 +144,7 @@ static void snmp6_seq_show_icmpv6msg(struct seq_file *seq, void **mib)
p = icmp6type2name[icmptype];
if (!p) /* don't print un-named types here */
continue;
- (void) snprintf(name, sizeof(name)-1, "Icmp6%s%s",
+ snprintf(name, sizeof(name), "Icmp6%s%s",
i & 0x100 ? "Out" : "In", p);
seq_printf(seq, "%-32s\t%lu\n", name,
snmp_fold_field(mib, i));
@@ -157,7 +157,7 @@ static void snmp6_seq_show_icmpv6msg(struct seq_file *seq, void **mib)
val = snmp_fold_field(mib, i);
if (!val)
continue;
- (void) snprintf(name, sizeof(name)-1, "Icmp6%sType%u",
+ snprintf(name, sizeof(name), "Icmp6%sType%u",
i & 0x100 ? "Out" : "In", i & 0xff);
seq_printf(seq, "%-32s\t%lu\n", name, val);
}
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 87665d7bb4f..409bb771623 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -2560,25 +2560,3 @@ void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local)
ieee80211_restart_sta_timer(sdata);
rcu_read_unlock();
}
-
-/* driver notification call */
-void ieee80211_notify_mac(struct ieee80211_hw *hw,
- enum ieee80211_notification_types notif_type)
-{
- struct ieee80211_local *local = hw_to_local(hw);
- struct ieee80211_sub_if_data *sdata;
-
- switch (notif_type) {
- case IEEE80211_NOTIFY_RE_ASSOC:
- rcu_read_lock();
- list_for_each_entry_rcu(sdata, &local->interfaces, list) {
- if (sdata->vif.type != NL80211_IFTYPE_STATION)
- continue;
-
- ieee80211_sta_req_auth(sdata, &sdata->u.sta);
- }
- rcu_read_unlock();
- break;
- }
-}
-EXPORT_SYMBOL(ieee80211_notify_mac);
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 7fef8ea1f5e..d254446b85b 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -99,7 +99,7 @@ struct sta_info *sta_info_get(struct ieee80211_local *local, const u8 *addr)
sta = rcu_dereference(local->sta_hash[STA_HASH(addr)]);
while (sta) {
- if (compare_ether_addr(sta->sta.addr, addr) == 0)
+ if (memcmp(sta->sta.addr, addr, ETH_ALEN) == 0)
break;
sta = rcu_dereference(sta->hnext);
}
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c
index 742f811ca41..ab4ddba874b 100644
--- a/net/mac80211/wext.c
+++ b/net/mac80211/wext.c
@@ -271,6 +271,7 @@ static int ieee80211_ioctl_siwmode(struct net_device *dev,
__u32 *mode, char *extra)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ struct ieee80211_local *local = sdata->local;
int type;
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
@@ -281,6 +282,13 @@ static int ieee80211_ioctl_siwmode(struct net_device *dev,
type = NL80211_IFTYPE_STATION;
break;
case IW_MODE_ADHOC:
+ /* Setting ad-hoc mode on non ibss channel is not
+ * supported.
+ */
+ if (local->oper_channel &&
+ (local->oper_channel->flags & IEEE80211_CHAN_NO_IBSS))
+ return -EOPNOTSUPP;
+
type = NL80211_IFTYPE_ADHOC;
break;
case IW_MODE_REPEAT:
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 622d7c671cb..233fdd2d7d2 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -305,9 +305,7 @@ void nf_conntrack_hash_insert(struct nf_conn *ct)
hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
repl_hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
- spin_lock_bh(&nf_conntrack_lock);
__nf_conntrack_hash_insert(ct, hash, repl_hash);
- spin_unlock_bh(&nf_conntrack_lock);
}
EXPORT_SYMBOL_GPL(nf_conntrack_hash_insert);
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index a040d46f85d..5f4a6516b3b 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -1090,7 +1090,7 @@ ctnetlink_create_conntrack(struct nlattr *cda[],
struct nf_conn_help *help;
struct nf_conntrack_helper *helper;
- ct = nf_conntrack_alloc(&init_net, otuple, rtuple, GFP_KERNEL);
+ ct = nf_conntrack_alloc(&init_net, otuple, rtuple, GFP_ATOMIC);
if (ct == NULL || IS_ERR(ct))
return -ENOMEM;
@@ -1138,7 +1138,7 @@ ctnetlink_create_conntrack(struct nlattr *cda[],
}
}
- nf_ct_acct_ext_add(ct, GFP_KERNEL);
+ nf_ct_acct_ext_add(ct, GFP_ATOMIC);
#if defined(CONFIG_NF_CONNTRACK_MARK)
if (cda[CTA_MARK])
@@ -1212,13 +1212,14 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
atomic_inc(&master_ct->ct_general.use);
}
- spin_unlock_bh(&nf_conntrack_lock);
err = -ENOENT;
if (nlh->nlmsg_flags & NLM_F_CREATE)
err = ctnetlink_create_conntrack(cda,
&otuple,
&rtuple,
master_ct);
+ spin_unlock_bh(&nf_conntrack_lock);
+
if (err < 0 && master_ct)
nf_ct_put(master_ct);
diff --git a/net/netfilter/xt_socket.c b/net/netfilter/xt_socket.c
index 02a8fed2108..1acc089be7e 100644
--- a/net/netfilter/xt_socket.c
+++ b/net/netfilter/xt_socket.c
@@ -141,7 +141,7 @@ socket_mt(const struct sk_buff *skb, const struct xt_match_param *par)
sk = nf_tproxy_get_sock_v4(dev_net(skb->dev), protocol,
saddr, daddr, sport, dport, par->in, false);
if (sk != NULL) {
- bool wildcard = (inet_sk(sk)->rcv_saddr == 0);
+ bool wildcard = (sk->sk_state != TCP_TIME_WAIT && inet_sk(sk)->rcv_saddr == 0);
nf_tproxy_put_sock(sk);
if (wildcard)
diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c
index e8a5c32b0f1..8c030803217 100644
--- a/net/netlabel/netlabel_unlabeled.c
+++ b/net/netlabel/netlabel_unlabeled.c
@@ -562,7 +562,6 @@ static int netlbl_unlhsh_remove_addr4(struct net *net,
const struct in_addr *mask,
struct netlbl_audit *audit_info)
{
- int ret_val = 0;
struct netlbl_af4list *list_entry;
struct netlbl_unlhsh_addr4 *entry;
struct audit_buffer *audit_buf;
@@ -574,9 +573,10 @@ static int netlbl_unlhsh_remove_addr4(struct net *net,
list_entry = netlbl_af4list_remove(addr->s_addr, mask->s_addr,
&iface->addr4_list);
spin_unlock(&netlbl_unlhsh_lock);
- if (list_entry == NULL)
- ret_val = -ENOENT;
- entry = netlbl_unlhsh_addr4_entry(list_entry);
+ if (list_entry != NULL)
+ entry = netlbl_unlhsh_addr4_entry(list_entry);
+ else
+ entry = NULL;
audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_STCDEL,
audit_info);
@@ -587,19 +587,21 @@ static int netlbl_unlhsh_remove_addr4(struct net *net,
addr->s_addr, mask->s_addr);
if (dev != NULL)
dev_put(dev);
- if (entry && security_secid_to_secctx(entry->secid,
- &secctx,
- &secctx_len) == 0) {
+ if (entry != NULL &&
+ security_secid_to_secctx(entry->secid,
+ &secctx, &secctx_len) == 0) {
audit_log_format(audit_buf, " sec_obj=%s", secctx);
security_release_secctx(secctx, secctx_len);
}
- audit_log_format(audit_buf, " res=%u", ret_val == 0 ? 1 : 0);
+ audit_log_format(audit_buf, " res=%u", entry != NULL ? 1 : 0);
audit_log_end(audit_buf);
}
- if (ret_val == 0)
- call_rcu(&entry->rcu, netlbl_unlhsh_free_addr4);
- return ret_val;
+ if (entry == NULL)
+ return -ENOENT;
+
+ call_rcu(&entry->rcu, netlbl_unlhsh_free_addr4);
+ return 0;
}
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
@@ -623,7 +625,6 @@ static int netlbl_unlhsh_remove_addr6(struct net *net,
const struct in6_addr *mask,
struct netlbl_audit *audit_info)
{
- int ret_val = 0;
struct netlbl_af6list *list_entry;
struct netlbl_unlhsh_addr6 *entry;
struct audit_buffer *audit_buf;
@@ -634,9 +635,10 @@ static int netlbl_unlhsh_remove_addr6(struct net *net,
spin_lock(&netlbl_unlhsh_lock);
list_entry = netlbl_af6list_remove(addr, mask, &iface->addr6_list);
spin_unlock(&netlbl_unlhsh_lock);
- if (list_entry == NULL)
- ret_val = -ENOENT;
- entry = netlbl_unlhsh_addr6_entry(list_entry);
+ if (list_entry != NULL)
+ entry = netlbl_unlhsh_addr6_entry(list_entry);
+ else
+ entry = NULL;
audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_STCDEL,
audit_info);
@@ -647,19 +649,21 @@ static int netlbl_unlhsh_remove_addr6(struct net *net,
addr, mask);
if (dev != NULL)
dev_put(dev);
- if (entry && security_secid_to_secctx(entry->secid,
- &secctx,
- &secctx_len) == 0) {
+ if (entry != NULL &&
+ security_secid_to_secctx(entry->secid,
+ &secctx, &secctx_len) == 0) {
audit_log_format(audit_buf, " sec_obj=%s", secctx);
security_release_secctx(secctx, secctx_len);
}
- audit_log_format(audit_buf, " res=%u", ret_val == 0 ? 1 : 0);
+ audit_log_format(audit_buf, " res=%u", entry != NULL ? 1 : 0);
audit_log_end(audit_buf);
}
- if (ret_val == 0)
- call_rcu(&entry->rcu, netlbl_unlhsh_free_addr6);
- return ret_val;
+ if (entry == NULL)
+ return -ENOENT;
+
+ call_rcu(&entry->rcu, netlbl_unlhsh_free_addr6);
+ return 0;
}
#endif /* IPv6 */
diff --git a/net/phonet/af_phonet.c b/net/phonet/af_phonet.c
index defeb7a0d50..9d211f12582 100644
--- a/net/phonet/af_phonet.c
+++ b/net/phonet/af_phonet.c
@@ -33,9 +33,30 @@
#include <net/phonet/phonet.h>
#include <net/phonet/pn_dev.h>
-static struct net_proto_family phonet_proto_family;
-static struct phonet_protocol *phonet_proto_get(int protocol);
-static inline void phonet_proto_put(struct phonet_protocol *pp);
+/* Transport protocol registration */
+static struct phonet_protocol *proto_tab[PHONET_NPROTO] __read_mostly;
+static DEFINE_SPINLOCK(proto_tab_lock);
+
+static struct phonet_protocol *phonet_proto_get(int protocol)
+{
+ struct phonet_protocol *pp;
+
+ if (protocol >= PHONET_NPROTO)
+ return NULL;
+
+ spin_lock(&proto_tab_lock);
+ pp = proto_tab[protocol];
+ if (pp && !try_module_get(pp->prot->owner))
+ pp = NULL;
+ spin_unlock(&proto_tab_lock);
+
+ return pp;
+}
+
+static inline void phonet_proto_put(struct phonet_protocol *pp)
+{
+ module_put(pp->prot->owner);
+}
/* protocol family functions */
@@ -144,8 +165,8 @@ static int pn_send(struct sk_buff *skb, struct net_device *dev,
struct phonethdr *ph;
int err;
- if (skb->len + 2 > 0xffff) {
- /* Phonet length field would overflow */
+ if (skb->len + 2 > 0xffff /* Phonet length field limit */ ||
+ skb->len + sizeof(struct phonethdr) > dev->mtu) {
err = -EMSGSIZE;
goto drop;
}
@@ -375,10 +396,6 @@ static struct packet_type phonet_packet_type = {
.func = phonet_rcv,
};
-/* Transport protocol registration */
-static struct phonet_protocol *proto_tab[PHONET_NPROTO] __read_mostly;
-static DEFINE_SPINLOCK(proto_tab_lock);
-
int __init_or_module phonet_proto_register(int protocol,
struct phonet_protocol *pp)
{
@@ -412,27 +429,6 @@ void phonet_proto_unregister(int protocol, struct phonet_protocol *pp)
}
EXPORT_SYMBOL(phonet_proto_unregister);
-static struct phonet_protocol *phonet_proto_get(int protocol)
-{
- struct phonet_protocol *pp;
-
- if (protocol >= PHONET_NPROTO)
- return NULL;
-
- spin_lock(&proto_tab_lock);
- pp = proto_tab[protocol];
- if (pp && !try_module_get(pp->prot->owner))
- pp = NULL;
- spin_unlock(&proto_tab_lock);
-
- return pp;
-}
-
-static inline void phonet_proto_put(struct phonet_protocol *pp)
-{
- module_put(pp->prot->owner);
-}
-
/* Module registration */
static int __init phonet_init(void)
{
diff --git a/net/phonet/pep-gprs.c b/net/phonet/pep-gprs.c
index 9978afbd9f2..803eeef0aa8 100644
--- a/net/phonet/pep-gprs.c
+++ b/net/phonet/pep-gprs.c
@@ -155,12 +155,13 @@ static void gprs_data_ready(struct sock *sk, int len)
static void gprs_write_space(struct sock *sk)
{
struct gprs_dev *dev = sk->sk_user_data;
+ struct net_device *net = dev->net;
unsigned credits = pep_writeable(sk);
spin_lock_bh(&dev->tx_lock);
dev->tx_max = credits;
- if (credits > skb_queue_len(&dev->tx_queue))
- netif_wake_queue(dev->net);
+ if (credits > skb_queue_len(&dev->tx_queue) && netif_running(net))
+ netif_wake_queue(net);
spin_unlock_bh(&dev->tx_lock);
}
@@ -168,6 +169,23 @@ static void gprs_write_space(struct sock *sk)
* Network device callbacks
*/
+static int gprs_open(struct net_device *dev)
+{
+ struct gprs_dev *gp = netdev_priv(dev);
+
+ gprs_write_space(gp->sk);
+ return 0;
+}
+
+static int gprs_close(struct net_device *dev)
+{
+ struct gprs_dev *gp = netdev_priv(dev);
+
+ netif_stop_queue(dev);
+ flush_work(&gp->tx_work);
+ return 0;
+}
+
static int gprs_xmit(struct sk_buff *skb, struct net_device *net)
{
struct gprs_dev *dev = netdev_priv(net);
@@ -254,6 +272,8 @@ static void gprs_setup(struct net_device *net)
net->tx_queue_len = 10;
net->destructor = free_netdev;
+ net->open = gprs_open;
+ net->stop = gprs_close;
net->hard_start_xmit = gprs_xmit; /* mandatory */
net->change_mtu = gprs_set_mtu;
net->get_stats = gprs_get_stats;
@@ -318,7 +338,6 @@ int gprs_attach(struct sock *sk)
dev->sk = sk;
printk(KERN_DEBUG"%s: attached\n", net->name);
- gprs_write_space(sk); /* kick off TX */
return net->ifindex;
out_rel:
@@ -341,7 +360,5 @@ void gprs_detach(struct sock *sk)
printk(KERN_DEBUG"%s: detached\n", net->name);
unregister_netdev(net);
- flush_scheduled_work();
sock_put(sk);
- skb_queue_purge(&dev->tx_queue);
}
diff --git a/net/phonet/pn_dev.c b/net/phonet/pn_dev.c
index 53be9fc82aa..f93ff8ef47d 100644
--- a/net/phonet/pn_dev.c
+++ b/net/phonet/pn_dev.c
@@ -115,7 +115,7 @@ int phonet_address_del(struct net_device *dev, u8 addr)
pnd = __phonet_get(dev);
if (!pnd || !test_and_clear_bit(addr >> 2, pnd->addrs))
err = -EADDRNOTAVAIL;
- if (bitmap_empty(pnd->addrs, 64))
+ else if (bitmap_empty(pnd->addrs, 64))
__phonet_device_free(pnd);
spin_unlock_bh(&pndevs.lock);
return err;
diff --git a/net/phonet/pn_netlink.c b/net/phonet/pn_netlink.c
index b1770d66bc8..242fe8f8c32 100644
--- a/net/phonet/pn_netlink.c
+++ b/net/phonet/pn_netlink.c
@@ -123,6 +123,7 @@ nla_put_failure:
static int getaddr_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
{
+ struct net *net = sock_net(skb->sk);
struct phonet_device *pnd;
int dev_idx = 0, dev_start_idx = cb->args[0];
int addr_idx = 0, addr_start_idx = cb->args[1];
@@ -131,6 +132,8 @@ static int getaddr_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
list_for_each_entry(pnd, &pndevs.list, list) {
u8 addr;
+ if (!net_eq(dev_net(pnd->netdev), net))
+ continue;
if (dev_idx > dev_start_idx)
addr_start_idx = 0;
if (dev_idx++ < dev_start_idx)
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
index a7f1ce11bc2..0c1cc761280 100644
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -1072,6 +1072,10 @@ static int rose_sendmsg(struct kiocb *iocb, struct socket *sock,
unsigned char *asmptr;
int n, size, qbit = 0;
+ /* ROSE empty frame has no meaning : don't send */
+ if (len == 0)
+ return 0;
+
if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_EOR|MSG_CMSG_COMPAT))
return -EINVAL;
@@ -1265,6 +1269,12 @@ static int rose_recvmsg(struct kiocb *iocb, struct socket *sock,
skb_reset_transport_header(skb);
copied = skb->len;
+ /* ROSE empty frame has no meaning : ignore it */
+ if (copied == 0) {
+ skb_free_datagram(sk, skb);
+ return copied;
+ }
+
if (copied > size) {
copied = size;
msg->msg_flags |= MSG_TRUNC;
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index b16ad2972c6..6ab4a2f92ca 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -417,6 +417,8 @@ static int qdisc_dump_stab(struct sk_buff *skb, struct qdisc_size_table *stab)
struct nlattr *nest;
nest = nla_nest_start(skb, TCA_STAB);
+ if (nest == NULL)
+ goto nla_put_failure;
NLA_PUT(skb, TCA_STAB_BASE, sizeof(stab->szopts), &stab->szopts);
nla_nest_end(skb, nest);
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 93cd30ce650..cdcd16fcfed 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -270,6 +270,8 @@ static void dev_watchdog_down(struct net_device *dev)
void netif_carrier_on(struct net_device *dev)
{
if (test_and_clear_bit(__LINK_STATE_NOCARRIER, &dev->state)) {
+ if (dev->reg_state == NETREG_UNINITIALIZED)
+ return;
linkwatch_fire_event(dev);
if (netif_running(dev))
__netdev_watchdog_up(dev);
@@ -285,8 +287,11 @@ EXPORT_SYMBOL(netif_carrier_on);
*/
void netif_carrier_off(struct net_device *dev)
{
- if (!test_and_set_bit(__LINK_STATE_NOCARRIER, &dev->state))
+ if (!test_and_set_bit(__LINK_STATE_NOCARRIER, &dev->state)) {
+ if (dev->reg_state == NETREG_UNINITIALIZED)
+ return;
linkwatch_fire_event(dev);
+ }
}
EXPORT_SYMBOL(netif_carrier_off);
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index a11959908d9..98402f0efa4 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -46,9 +46,6 @@
layering other disciplines. It does not need to do bandwidth
control either since that can be handled by using token
bucket or other rate control.
-
- The simulator is limited by the Linux timer resolution
- and will create packet bursts on the HZ boundary (1ms).
*/
struct netem_sched_data {
diff --git a/net/socket.c b/net/socket.c
index 57550c3bcab..76ba80aeac1 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -1426,8 +1426,8 @@ asmlinkage long sys_listen(int fd, int backlog)
* clean when we restucture accept also.
*/
-long do_accept(int fd, struct sockaddr __user *upeer_sockaddr,
- int __user *upeer_addrlen, int flags)
+asmlinkage long sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr,
+ int __user *upeer_addrlen, int flags)
{
struct socket *sock, *newsock;
struct file *newfile;
@@ -1510,66 +1510,10 @@ out_fd:
goto out_put;
}
-#if 0
-#ifdef HAVE_SET_RESTORE_SIGMASK
-asmlinkage long sys_paccept(int fd, struct sockaddr __user *upeer_sockaddr,
- int __user *upeer_addrlen,
- const sigset_t __user *sigmask,
- size_t sigsetsize, int flags)
-{
- sigset_t ksigmask, sigsaved;
- int ret;
-
- if (sigmask) {
- /* XXX: Don't preclude handling different sized sigset_t's. */
- if (sigsetsize != sizeof(sigset_t))
- return -EINVAL;
- if (copy_from_user(&ksigmask, sigmask, sizeof(ksigmask)))
- return -EFAULT;
-
- sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
- sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
- }
-
- ret = do_accept(fd, upeer_sockaddr, upeer_addrlen, flags);
-
- if (ret < 0 && signal_pending(current)) {
- /*
- * Don't restore the signal mask yet. Let do_signal() deliver
- * the signal on the way back to userspace, before the signal
- * mask is restored.
- */
- if (sigmask) {
- memcpy(&current->saved_sigmask, &sigsaved,
- sizeof(sigsaved));
- set_restore_sigmask();
- }
- } else if (sigmask)
- sigprocmask(SIG_SETMASK, &sigsaved, NULL);
-
- return ret;
-}
-#else
-asmlinkage long sys_paccept(int fd, struct sockaddr __user *upeer_sockaddr,
- int __user *upeer_addrlen,
- const sigset_t __user *sigmask,
- size_t sigsetsize, int flags)
-{
- /* The platform does not support restoring the signal mask in the
- * return path. So we do not allow using paccept() with a signal
- * mask. */
- if (sigmask)
- return -EINVAL;
-
- return do_accept(fd, upeer_sockaddr, upeer_addrlen, flags);
-}
-#endif
-#endif
-
asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr,
int __user *upeer_addrlen)
{
- return do_accept(fd, upeer_sockaddr, upeer_addrlen, 0);
+ return sys_accept4(fd, upeer_sockaddr, upeer_addrlen, 0);
}
/*
@@ -2096,7 +2040,7 @@ static const unsigned char nargs[19]={
AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
AL(3),AL(3),AL(4),AL(4),AL(4),AL(6),
AL(6),AL(2),AL(5),AL(5),AL(3),AL(3),
- AL(6)
+ AL(4)
};
#undef AL
@@ -2115,7 +2059,7 @@ asmlinkage long sys_socketcall(int call, unsigned long __user *args)
unsigned long a0, a1;
int err;
- if (call < 1 || call > SYS_PACCEPT)
+ if (call < 1 || call > SYS_ACCEPT4)
return -EINVAL;
/* copy_from_user should be SMP safe. */
@@ -2143,9 +2087,8 @@ asmlinkage long sys_socketcall(int call, unsigned long __user *args)
err = sys_listen(a0, a1);
break;
case SYS_ACCEPT:
- err =
- do_accept(a0, (struct sockaddr __user *)a1,
- (int __user *)a[2], 0);
+ err = sys_accept4(a0, (struct sockaddr __user *)a1,
+ (int __user *)a[2], 0);
break;
case SYS_GETSOCKNAME:
err =
@@ -2192,12 +2135,9 @@ asmlinkage long sys_socketcall(int call, unsigned long __user *args)
case SYS_RECVMSG:
err = sys_recvmsg(a0, (struct msghdr __user *)a1, a[2]);
break;
- case SYS_PACCEPT:
- err =
- sys_paccept(a0, (struct sockaddr __user *)a1,
- (int __user *)a[2],
- (const sigset_t __user *) a[3],
- a[4], a[5]);
+ case SYS_ACCEPT4:
+ err = sys_accept4(a0, (struct sockaddr __user *)a1,
+ (int __user *)a[2], a[3]);
break;
default:
err = -EINVAL;
@@ -2367,6 +2307,7 @@ int kernel_accept(struct socket *sock, struct socket **newsock, int flags)
}
(*newsock)->ops = sock->ops;
+ __module_get((*newsock)->ops->owner);
done:
return err;
diff --git a/net/sunrpc/auth_generic.c b/net/sunrpc/auth_generic.c
index 744b79fdcb1..4028502f052 100644
--- a/net/sunrpc/auth_generic.c
+++ b/net/sunrpc/auth_generic.c
@@ -133,13 +133,29 @@ static int
generic_match(struct auth_cred *acred, struct rpc_cred *cred, int flags)
{
struct generic_cred *gcred = container_of(cred, struct generic_cred, gc_base);
+ int i;
if (gcred->acred.uid != acred->uid ||
gcred->acred.gid != acred->gid ||
- gcred->acred.group_info != acred->group_info ||
gcred->acred.machine_cred != acred->machine_cred)
- return 0;
+ goto out_nomatch;
+
+ /* Optimisation in the case where pointers are identical... */
+ if (gcred->acred.group_info == acred->group_info)
+ goto out_match;
+
+ /* Slow path... */
+ if (gcred->acred.group_info->ngroups != acred->group_info->ngroups)
+ goto out_nomatch;
+ for (i = 0; i < gcred->acred.group_info->ngroups; i++) {
+ if (GROUP_AT(gcred->acred.group_info, i) !=
+ GROUP_AT(acred->group_info, i))
+ goto out_nomatch;
+ }
+out_match:
return 1;
+out_nomatch:
+ return 0;
}
void __init rpc_init_generic_auth(void)
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 95293f549e9..a1951dcc577 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -1183,7 +1183,11 @@ int svc_addsock(struct svc_serv *serv,
else if (so->state > SS_UNCONNECTED)
err = -EISCONN;
else {
- svsk = svc_setup_socket(serv, so, &err, SVC_SOCK_DEFAULTS);
+ if (!try_module_get(THIS_MODULE))
+ err = -ENOENT;
+ else
+ svsk = svc_setup_socket(serv, so, &err,
+ SVC_SOCK_DEFAULTS);
if (svsk) {
struct sockaddr_storage addr;
struct sockaddr *sin = (struct sockaddr *)&addr;
@@ -1196,7 +1200,8 @@ int svc_addsock(struct svc_serv *serv,
spin_unlock_bh(&serv->sv_lock);
svc_xprt_received(&svsk->sk_xprt);
err = 0;
- }
+ } else
+ module_put(THIS_MODULE);
}
if (err) {
sockfd_put(so);
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index eb90f77bb0e..66d5ac4773a 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -1343,6 +1343,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
if (NULL == siocb->scm)
siocb->scm = &tmp_scm;
+ wait_for_unix_gc();
err = scm_send(sock, msg, siocb->scm);
if (err < 0)
return err;
@@ -1493,6 +1494,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
if (NULL == siocb->scm)
siocb->scm = &tmp_scm;
+ wait_for_unix_gc();
err = scm_send(sock, msg, siocb->scm);
if (err < 0)
return err;
diff --git a/net/unix/garbage.c b/net/unix/garbage.c
index 6d4a9a8de5e..abb3ab34cb1 100644
--- a/net/unix/garbage.c
+++ b/net/unix/garbage.c
@@ -80,6 +80,7 @@
#include <linux/file.h>
#include <linux/proc_fs.h>
#include <linux/mutex.h>
+#include <linux/wait.h>
#include <net/sock.h>
#include <net/af_unix.h>
@@ -91,6 +92,7 @@
static LIST_HEAD(gc_inflight_list);
static LIST_HEAD(gc_candidates);
static DEFINE_SPINLOCK(unix_gc_lock);
+static DECLARE_WAIT_QUEUE_HEAD(unix_gc_wait);
unsigned int unix_tot_inflight;
@@ -266,12 +268,16 @@ static void inc_inflight_move_tail(struct unix_sock *u)
list_move_tail(&u->link, &gc_candidates);
}
-/* The external entry point: unix_gc() */
+static bool gc_in_progress = false;
-void unix_gc(void)
+void wait_for_unix_gc(void)
{
- static bool gc_in_progress = false;
+ wait_event(unix_gc_wait, gc_in_progress == false);
+}
+/* The external entry point: unix_gc() */
+void unix_gc(void)
+{
struct unix_sock *u;
struct unix_sock *next;
struct sk_buff_head hitlist;
@@ -376,6 +382,7 @@ void unix_gc(void)
/* All candidates should have been detached by now. */
BUG_ON(!list_empty(&gc_candidates));
gc_in_progress = false;
+ wake_up(&unix_gc_wait);
out:
spin_unlock(&unix_gc_lock);
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 626dbb68849..eb3b1a9f9b1 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -343,9 +343,9 @@ static int ignore_request(struct wiphy *wiphy, enum reg_set_by set_by,
return 0;
return -EALREADY;
}
- if (WARN_ON(!is_alpha2_set(alpha2) || !is_an_alpha2(alpha2)),
+ if (WARN(!is_alpha2_set(alpha2) || !is_an_alpha2(alpha2),
"Invalid Country IE regulatory hint passed "
- "to the wireless core\n")
+ "to the wireless core\n"))
return -EINVAL;
/* We ignore Country IE hints for now, as we haven't yet
* added the dot11MultiDomainCapabilityEnabled flag
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 058f04f54b9..fb216c9adf8 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -817,6 +817,7 @@ int xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info)
continue;
hlist_del(&pol->bydst);
hlist_del(&pol->byidx);
+ list_del(&pol->walk.all);
write_unlock_bh(&xfrm_policy_lock);
xfrm_audit_policy_delete(pol, 1, audit_info->loginuid,
diff --git a/scripts/kernel-doc b/scripts/kernel-doc
index a53e2fc8dfb..d27aad78e1d 100755
--- a/scripts/kernel-doc
+++ b/scripts/kernel-doc
@@ -378,6 +378,10 @@ sub dump_section {
# print STDERR "parameter def '$1' = '$contents'\n";
$name = $1;
$parameterdescs{$name} = $contents;
+ } elsif ($name eq "@\.\.\.") {
+# print STDERR "parameter def '...' = '$contents'\n";
+ $name = "...";
+ $parameterdescs{$name} = $contents;
} else {
# print STDERR "other section '$name' = '$contents'\n";
if (defined($sections{$name}) && ($sections{$name} ne "")) {
@@ -1588,12 +1592,12 @@ sub push_parameter($$$) {
if ($type eq "" && $param =~ /\.\.\.$/)
{
- $type="";
- $parameterdescs{$param} = "variable arguments";
+ if (!defined $parameterdescs{$param} || $parameterdescs{$param} eq "") {
+ $parameterdescs{$param} = "variable arguments";
+ }
}
elsif ($type eq "" && ($param eq "" or $param eq "void"))
{
- $type="";
$param="void";
$parameterdescs{void} = "no arguments";
}
diff --git a/sound/ac97_bus.c b/sound/ac97_bus.c
index 7fa37e15f19..a351dd0a09c 100644
--- a/sound/ac97_bus.c
+++ b/sound/ac97_bus.c
@@ -15,6 +15,7 @@
#include <linux/init.h>
#include <linux/device.h>
#include <linux/string.h>
+#include <sound/ac97_codec.h>
/*
* Let drivers decide whether they want to support given codec from their
diff --git a/sound/aoa/codecs/Makefile b/sound/aoa/codecs/Makefile
index 31cbe68fd42..c3ee77fc4b2 100644
--- a/sound/aoa/codecs/Makefile
+++ b/sound/aoa/codecs/Makefile
@@ -1,3 +1,7 @@
+snd-aoa-codec-onyx-objs := onyx.o
+snd-aoa-codec-tas-objs := tas.o
+snd-aoa-codec-toonie-objs := toonie.o
+
obj-$(CONFIG_SND_AOA_ONYX) += snd-aoa-codec-onyx.o
obj-$(CONFIG_SND_AOA_TAS) += snd-aoa-codec-tas.o
obj-$(CONFIG_SND_AOA_TOONIE) += snd-aoa-codec-toonie.o
diff --git a/sound/aoa/codecs/snd-aoa-codec-onyx.c b/sound/aoa/codecs/onyx.c
index 6a3837d480e..15500b9d2da 100644
--- a/sound/aoa/codecs/snd-aoa-codec-onyx.c
+++ b/sound/aoa/codecs/onyx.c
@@ -37,7 +37,7 @@ MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("pcm3052 (onyx) codec driver for snd-aoa");
-#include "snd-aoa-codec-onyx.h"
+#include "onyx.h"
#include "../aoa.h"
#include "../soundbus/soundbus.h"
@@ -292,7 +292,7 @@ static int onyx_snd_capture_source_put(struct snd_kcontrol *kcontrol,
static struct snd_kcontrol_new capture_source_control = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
/* If we name this 'Input Source', it properly shows up in
- * alsamixer as a selection, * but it's shown under the
+ * alsamixer as a selection, * but it's shown under the
* 'Playback' category.
* If I name it 'Capture Source', it shows up in strange
* ways (two bools of which one can be selected at a
@@ -477,7 +477,7 @@ static int onyx_spdif_mask_get(struct snd_kcontrol *kcontrol,
ucontrol->value.iec958.status[3] = 0x3f;
ucontrol->value.iec958.status[4] = 0x0f;
-
+
return 0;
}
@@ -682,7 +682,7 @@ static int onyx_usable(struct codec_info_item *cii,
onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v);
spdif_enabled = !!(v & ONYX_SPDIF_ENABLE);
onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v);
- analog_enabled =
+ analog_enabled =
(v & (ONYX_MUTE_RIGHT|ONYX_MUTE_LEFT))
!= (ONYX_MUTE_RIGHT|ONYX_MUTE_LEFT);
mutex_unlock(&onyx->mutex);
@@ -882,7 +882,7 @@ static int onyx_init_codec(struct aoa_codec *codec)
msleep(1);
onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 0);
msleep(1);
-
+
if (onyx_register_init(onyx)) {
printk(KERN_ERR PFX "failed to initialise onyx registers\n");
return -ENODEV;
@@ -1069,7 +1069,7 @@ static int onyx_i2c_attach(struct i2c_adapter *adapter)
/* if that didn't work, try desperate mode for older
* machines that have stuff missing from the device tree */
-
+
if (!of_device_is_compatible(busnode, "k2-i2c"))
return -ENODEV;
diff --git a/sound/aoa/codecs/snd-aoa-codec-onyx.h b/sound/aoa/codecs/onyx.h
index ffd20254ff7..ffd20254ff7 100644
--- a/sound/aoa/codecs/snd-aoa-codec-onyx.h
+++ b/sound/aoa/codecs/onyx.h
diff --git a/sound/aoa/codecs/snd-aoa-codec-tas-basstreble.h b/sound/aoa/codecs/tas-basstreble.h
index 69b61136fd5..69b61136fd5 100644
--- a/sound/aoa/codecs/snd-aoa-codec-tas-basstreble.h
+++ b/sound/aoa/codecs/tas-basstreble.h
diff --git a/sound/aoa/codecs/snd-aoa-codec-tas-gain-table.h b/sound/aoa/codecs/tas-gain-table.h
index 4cfa6757715..4cfa6757715 100644
--- a/sound/aoa/codecs/snd-aoa-codec-tas-gain-table.h
+++ b/sound/aoa/codecs/tas-gain-table.h
diff --git a/sound/aoa/codecs/snd-aoa-codec-tas.c b/sound/aoa/codecs/tas.c
index 6c515b2b8bb..008e0f85097 100644
--- a/sound/aoa/codecs/snd-aoa-codec-tas.c
+++ b/sound/aoa/codecs/tas.c
@@ -71,9 +71,9 @@ MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("tas codec driver for snd-aoa");
-#include "snd-aoa-codec-tas.h"
-#include "snd-aoa-codec-tas-gain-table.h"
-#include "snd-aoa-codec-tas-basstreble.h"
+#include "tas.h"
+#include "tas-gain-table.h"
+#include "tas-basstreble.h"
#include "../aoa.h"
#include "../soundbus/soundbus.h"
@@ -880,7 +880,7 @@ static void tas_exit_codec(struct aoa_codec *codec)
return;
tas->codec.soundbus_dev->detach_codec(tas->codec.soundbus_dev, tas);
}
-
+
static struct i2c_driver tas_driver;
diff --git a/sound/aoa/codecs/snd-aoa-codec-tas.h b/sound/aoa/codecs/tas.h
index ae177e3466e..ae177e3466e 100644
--- a/sound/aoa/codecs/snd-aoa-codec-tas.h
+++ b/sound/aoa/codecs/tas.h
diff --git a/sound/aoa/codecs/snd-aoa-codec-toonie.c b/sound/aoa/codecs/toonie.c
index 3c7d1d8a9a6..f13827e1756 100644
--- a/sound/aoa/codecs/snd-aoa-codec-toonie.c
+++ b/sound/aoa/codecs/toonie.c
@@ -131,7 +131,7 @@ static int __init toonie_init(void)
toonie->codec.owner = THIS_MODULE;
toonie->codec.init = toonie_init_codec;
toonie->codec.exit = toonie_exit_codec;
-
+
if (aoa_codec_register(&toonie->codec)) {
kfree(toonie);
return -EINVAL;
diff --git a/sound/aoa/core/Makefile b/sound/aoa/core/Makefile
index 62dc7287f66..a1596e88c71 100644
--- a/sound/aoa/core/Makefile
+++ b/sound/aoa/core/Makefile
@@ -1,5 +1,5 @@
obj-$(CONFIG_SND_AOA) += snd-aoa.o
-snd-aoa-objs := snd-aoa-core.o \
- snd-aoa-alsa.o \
- snd-aoa-gpio-pmf.o \
- snd-aoa-gpio-feature.o
+snd-aoa-objs := core.o \
+ alsa.o \
+ gpio-pmf.o \
+ gpio-feature.o
diff --git a/sound/aoa/core/snd-aoa-alsa.c b/sound/aoa/core/alsa.c
index 17fe689ed28..61785046358 100644
--- a/sound/aoa/core/snd-aoa-alsa.c
+++ b/sound/aoa/core/alsa.c
@@ -6,7 +6,7 @@
* GPL v2, can be found in COPYING.
*/
#include <linux/module.h>
-#include "snd-aoa-alsa.h"
+#include "alsa.h"
static int index = -1;
module_param(index, int, 0444);
@@ -64,7 +64,7 @@ int aoa_snd_device_new(snd_device_type_t type,
{
struct snd_card *card = aoa_get_card();
int err;
-
+
if (!card) return -ENOMEM;
err = snd_device_new(card, type, device_data, ops);
diff --git a/sound/aoa/core/snd-aoa-alsa.h b/sound/aoa/core/alsa.h
index 9669e4489ca..9669e4489ca 100644
--- a/sound/aoa/core/snd-aoa-alsa.h
+++ b/sound/aoa/core/alsa.h
diff --git a/sound/aoa/core/snd-aoa-core.c b/sound/aoa/core/core.c
index 19fdae40068..10bec6c6138 100644
--- a/sound/aoa/core/snd-aoa-core.c
+++ b/sound/aoa/core/core.c
@@ -10,7 +10,7 @@
#include <linux/module.h>
#include <linux/list.h>
#include "../aoa.h"
-#include "snd-aoa-alsa.h"
+#include "alsa.h"
MODULE_DESCRIPTION("Apple Onboard Audio Sound Driver");
MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
diff --git a/sound/aoa/core/snd-aoa-gpio-feature.c b/sound/aoa/core/gpio-feature.c
index 805dcbff225..c93ad5dec66 100644
--- a/sound/aoa/core/snd-aoa-gpio-feature.c
+++ b/sound/aoa/core/gpio-feature.c
@@ -5,7 +5,7 @@
*
* GPL v2, can be found in COPYING.
*
- * This file contains the GPIO control routines for
+ * This file contains the GPIO control routines for
* direct (through feature calls) access to the GPIO
* registers.
*/
diff --git a/sound/aoa/core/snd-aoa-gpio-pmf.c b/sound/aoa/core/gpio-pmf.c
index 5ca2220eac7..5ca2220eac7 100644
--- a/sound/aoa/core/snd-aoa-gpio-pmf.c
+++ b/sound/aoa/core/gpio-pmf.c
diff --git a/sound/aoa/fabrics/Makefile b/sound/aoa/fabrics/Makefile
index 55fc5e7e52c..da37c10eca5 100644
--- a/sound/aoa/fabrics/Makefile
+++ b/sound/aoa/fabrics/Makefile
@@ -1 +1,3 @@
+snd-aoa-fabric-layout-objs += layout.o
+
obj-$(CONFIG_SND_AOA_FABRIC_LAYOUT) += snd-aoa-fabric-layout.o
diff --git a/sound/aoa/fabrics/snd-aoa-fabric-layout.c b/sound/aoa/fabrics/layout.c
index dea7abb082c..ad60f5d10e8 100644
--- a/sound/aoa/fabrics/snd-aoa-fabric-layout.c
+++ b/sound/aoa/fabrics/layout.c
@@ -66,7 +66,7 @@ struct layout {
unsigned int layout_id;
struct codec_connect_info codecs[MAX_CODECS_PER_BUS];
int flags;
-
+
/* if busname is not assigned, we use 'Master' below,
* so that our layout table doesn't need to be filled
* too much.
diff --git a/sound/aoa/soundbus/i2sbus/Makefile b/sound/aoa/soundbus/i2sbus/Makefile
index e57a5cf6565..1b949b2a402 100644
--- a/sound/aoa/soundbus/i2sbus/Makefile
+++ b/sound/aoa/soundbus/i2sbus/Makefile
@@ -1,2 +1,2 @@
obj-$(CONFIG_SND_AOA_SOUNDBUS_I2S) += snd-aoa-i2sbus.o
-snd-aoa-i2sbus-objs := i2sbus-core.o i2sbus-pcm.o i2sbus-control.o
+snd-aoa-i2sbus-objs := core.o pcm.o control.o
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-control.c b/sound/aoa/soundbus/i2sbus/control.c
index 87beb4ad4d6..87beb4ad4d6 100644
--- a/sound/aoa/soundbus/i2sbus/i2sbus-control.c
+++ b/sound/aoa/soundbus/i2sbus/control.c
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-core.c b/sound/aoa/soundbus/i2sbus/core.c
index b4590df0746..be468edf3ec 100644
--- a/sound/aoa/soundbus/i2sbus/i2sbus-core.c
+++ b/sound/aoa/soundbus/i2sbus/core.c
@@ -64,7 +64,7 @@ static void free_dbdma_descriptor_ring(struct i2sbus_dev *i2sdev,
struct dbdma_command_mem *r)
{
if (!r->space) return;
-
+
dma_free_coherent(&macio_get_pci_dev(i2sdev->macio)->dev,
r->size, r->space, r->bus_addr);
}
@@ -247,7 +247,7 @@ static int i2sbus_add_dev(struct macio_dev *macio,
* but request_resource doesn't know about parents and
* contained resources...
*/
- dev->allocated_resource[i] =
+ dev->allocated_resource[i] =
request_mem_region(dev->resources[i].start,
dev->resources[i].end -
dev->resources[i].start + 1,
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus.h b/sound/aoa/soundbus/i2sbus/i2sbus.h
index ff29654782c..befefd99e27 100644
--- a/sound/aoa/soundbus/i2sbus/i2sbus.h
+++ b/sound/aoa/soundbus/i2sbus/i2sbus.h
@@ -18,7 +18,7 @@
#include <asm/pmac_feature.h>
#include <asm/dbdma.h>
-#include "i2sbus-interface.h"
+#include "interface.h"
#include "../soundbus.h"
struct i2sbus_control {
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-interface.h b/sound/aoa/soundbus/i2sbus/interface.h
index c6b5f5452d2..c6b5f5452d2 100644
--- a/sound/aoa/soundbus/i2sbus/i2sbus-interface.h
+++ b/sound/aoa/soundbus/i2sbus/interface.h
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-pcm.c b/sound/aoa/soundbus/i2sbus/pcm.c
index 59bacd36573..59bacd36573 100644
--- a/sound/aoa/soundbus/i2sbus/i2sbus-pcm.c
+++ b/sound/aoa/soundbus/i2sbus/pcm.c
diff --git a/sound/core/Kconfig b/sound/core/Kconfig
index 66348c92f88..7bbdda041a9 100644
--- a/sound/core/Kconfig
+++ b/sound/core/Kconfig
@@ -95,6 +95,26 @@ config SND_SEQUENCER_OSS
this will be compiled as a module. The module will be called
snd-seq-oss.
+config SND_HRTIMER
+ tristate "HR-timer backend support"
+ depends on HIGH_RES_TIMERS
+ select SND_TIMER
+ help
+ Say Y here to enable HR-timer backend for ALSA timer. ALSA uses
+ the hrtimer as a precise timing source. The ALSA sequencer code
+ also can use this timing source.
+
+ To compile this driver as a module, choose M here: the module
+ will be called snd-hrtimer.
+
+config SND_SEQ_HRTIMER_DEFAULT
+ bool "Use HR-timer as default sequencer timer"
+ depends on SND_HRTIMER && SND_SEQUENCER
+ default y
+ help
+ Say Y here to use the HR-timer backend as the default sequencer
+ timer.
+
config SND_RTCTIMER
tristate "RTC Timer support"
depends on RTC
@@ -114,6 +134,7 @@ config SND_RTCTIMER
config SND_SEQ_RTCTIMER_DEFAULT
bool "Use RTC as default sequencer timer"
depends on SND_RTCTIMER && SND_SEQUENCER
+ depends on !SND_SEQ_HRTIMER_DEFAULT
default y
help
Say Y here to use the RTC timer as the default sequencer
diff --git a/sound/core/Makefile b/sound/core/Makefile
index d57125a5687..4229052e7b9 100644
--- a/sound/core/Makefile
+++ b/sound/core/Makefile
@@ -17,12 +17,14 @@ snd-page-alloc-$(CONFIG_HAS_DMA) += sgbuf.o
snd-rawmidi-objs := rawmidi.o
snd-timer-objs := timer.o
+snd-hrtimer-objs := hrtimer.o
snd-rtctimer-objs := rtctimer.o
snd-hwdep-objs := hwdep.o
obj-$(CONFIG_SND) += snd.o
obj-$(CONFIG_SND_HWDEP) += snd-hwdep.o
obj-$(CONFIG_SND_TIMER) += snd-timer.o
+obj-$(CONFIG_SND_HRTIMER) += snd-hrtimer.o
obj-$(CONFIG_SND_RTCTIMER) += snd-rtctimer.o
obj-$(CONFIG_SND_PCM) += snd-pcm.o snd-page-alloc.o
obj-$(CONFIG_SND_RAWMIDI) += snd-rawmidi.o
diff --git a/sound/core/device.c b/sound/core/device.c
index c58d8227254..a67dfac08c0 100644
--- a/sound/core/device.c
+++ b/sound/core/device.c
@@ -98,7 +98,7 @@ int snd_device_free(struct snd_card *card, void *device_data)
kfree(dev);
return 0;
}
- snd_printd("device free %p (from %p), not found\n", device_data,
+ snd_printd("device free %p (from %pF), not found\n", device_data,
__builtin_return_address(0));
return -ENXIO;
}
@@ -135,7 +135,7 @@ int snd_device_disconnect(struct snd_card *card, void *device_data)
}
return 0;
}
- snd_printd("device disconnect %p (from %p), not found\n", device_data,
+ snd_printd("device disconnect %p (from %pF), not found\n", device_data,
__builtin_return_address(0));
return -ENXIO;
}
diff --git a/sound/core/hrtimer.c b/sound/core/hrtimer.c
new file mode 100644
index 00000000000..c1d285921f8
--- /dev/null
+++ b/sound/core/hrtimer.c
@@ -0,0 +1,155 @@
+/*
+ * ALSA timer back-end using hrtimer
+ * Copyright (C) 2008 Takashi Iwai
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/hrtimer.h>
+#include <sound/core.h>
+#include <sound/timer.h>
+
+MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
+MODULE_DESCRIPTION("ALSA hrtimer backend");
+MODULE_LICENSE("GPL");
+
+MODULE_ALIAS("snd-timer-" __stringify(SNDRV_TIMER_GLOBAL_HRTIMER));
+
+#define NANO_SEC 1000000000UL /* 10^9 in sec */
+static unsigned int resolution;
+
+struct snd_hrtimer {
+ struct snd_timer *timer;
+ struct hrtimer hrt;
+};
+
+static enum hrtimer_restart snd_hrtimer_callback(struct hrtimer *hrt)
+{
+ struct snd_hrtimer *stime = container_of(hrt, struct snd_hrtimer, hrt);
+ struct snd_timer *t = stime->timer;
+ hrtimer_forward_now(hrt, ns_to_ktime(t->sticks * resolution));
+ snd_timer_interrupt(stime->timer, t->sticks);
+ return HRTIMER_RESTART;
+}
+
+static int snd_hrtimer_open(struct snd_timer *t)
+{
+ struct snd_hrtimer *stime;
+
+ stime = kmalloc(sizeof(*stime), GFP_KERNEL);
+ if (!stime)
+ return -ENOMEM;
+ hrtimer_init(&stime->hrt, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ stime->timer = t;
+ stime->hrt.cb_mode = HRTIMER_CB_IRQSAFE_UNLOCKED;
+ stime->hrt.function = snd_hrtimer_callback;
+ t->private_data = stime;
+ return 0;
+}
+
+static int snd_hrtimer_close(struct snd_timer *t)
+{
+ struct snd_hrtimer *stime = t->private_data;
+
+ if (stime) {
+ hrtimer_cancel(&stime->hrt);
+ kfree(stime);
+ t->private_data = NULL;
+ }
+ return 0;
+}
+
+static int snd_hrtimer_start(struct snd_timer *t)
+{
+ struct snd_hrtimer *stime = t->private_data;
+
+ hrtimer_start(&stime->hrt, ns_to_ktime(t->sticks * resolution),
+ HRTIMER_MODE_REL);
+ return 0;
+}
+
+static int snd_hrtimer_stop(struct snd_timer *t)
+{
+ struct snd_hrtimer *stime = t->private_data;
+
+ hrtimer_cancel(&stime->hrt);
+ return 0;
+}
+
+static struct snd_timer_hardware hrtimer_hw = {
+ .flags = SNDRV_TIMER_HW_AUTO,
+ .open = snd_hrtimer_open,
+ .close = snd_hrtimer_close,
+ .start = snd_hrtimer_start,
+ .stop = snd_hrtimer_stop,
+};
+
+/*
+ * entry functions
+ */
+
+static struct snd_timer *mytimer;
+
+static int __init snd_hrtimer_init(void)
+{
+ struct snd_timer *timer;
+ struct timespec tp;
+ int err;
+
+ hrtimer_get_res(CLOCK_MONOTONIC, &tp);
+ if (tp.tv_sec > 0 || !tp.tv_nsec) {
+ snd_printk(KERN_ERR
+ "snd-hrtimer: Invalid resolution %u.%09u",
+ (unsigned)tp.tv_sec, (unsigned)tp.tv_nsec);
+ return -EINVAL;
+ }
+ resolution = tp.tv_nsec;
+
+ /* Create a new timer and set up the fields */
+ err = snd_timer_global_new("hrtimer", SNDRV_TIMER_GLOBAL_HRTIMER,
+ &timer);
+ if (err < 0)
+ return err;
+
+ timer->module = THIS_MODULE;
+ strcpy(timer->name, "HR timer");
+ timer->hw = hrtimer_hw;
+ timer->hw.resolution = resolution;
+ timer->hw.ticks = NANO_SEC / resolution;
+
+ err = snd_timer_global_register(timer);
+ if (err < 0) {
+ snd_timer_global_free(timer);
+ return err;
+ }
+ mytimer = timer; /* remember this */
+
+ return 0;
+}
+
+static void __exit snd_hrtimer_exit(void)
+{
+ if (mytimer) {
+ snd_timer_global_free(mytimer);
+ mytimer = NULL;
+ }
+}
+
+module_init(snd_hrtimer_init);
+module_exit(snd_hrtimer_exit);
diff --git a/sound/core/jack.c b/sound/core/jack.c
index bd2d9e6b55e..dd4a12dc09a 100644
--- a/sound/core/jack.c
+++ b/sound/core/jack.c
@@ -34,6 +34,7 @@ static int snd_jack_dev_free(struct snd_device *device)
else
input_free_device(jack->input_dev);
+ kfree(jack->id);
kfree(jack);
return 0;
@@ -87,7 +88,7 @@ int snd_jack_new(struct snd_card *card, const char *id, int type,
if (jack == NULL)
return -ENOMEM;
- jack->id = id;
+ jack->id = kstrdup(id, GFP_KERNEL);
jack->input_dev = input_allocate_device();
if (jack->input_dev == NULL) {
@@ -102,9 +103,15 @@ int snd_jack_new(struct snd_card *card, const char *id, int type,
if (type & SND_JACK_HEADPHONE)
input_set_capability(jack->input_dev, EV_SW,
SW_HEADPHONE_INSERT);
+ if (type & SND_JACK_LINEOUT)
+ input_set_capability(jack->input_dev, EV_SW,
+ SW_LINEOUT_INSERT);
if (type & SND_JACK_MICROPHONE)
input_set_capability(jack->input_dev, EV_SW,
SW_MICROPHONE_INSERT);
+ if (type & SND_JACK_MECHANICAL)
+ input_set_capability(jack->input_dev, EV_SW,
+ SW_JACK_PHYSICAL_INSERT);
err = snd_device_new(card, SNDRV_DEV_JACK, jack, &ops);
if (err < 0)
@@ -153,9 +160,15 @@ void snd_jack_report(struct snd_jack *jack, int status)
if (jack->type & SND_JACK_HEADPHONE)
input_report_switch(jack->input_dev, SW_HEADPHONE_INSERT,
status & SND_JACK_HEADPHONE);
+ if (jack->type & SND_JACK_LINEOUT)
+ input_report_switch(jack->input_dev, SW_LINEOUT_INSERT,
+ status & SND_JACK_LINEOUT);
if (jack->type & SND_JACK_MICROPHONE)
input_report_switch(jack->input_dev, SW_MICROPHONE_INSERT,
status & SND_JACK_MICROPHONE);
+ if (jack->type & SND_JACK_MECHANICAL)
+ input_report_switch(jack->input_dev, SW_JACK_PHYSICAL_INSERT,
+ status & SND_JACK_MECHANICAL);
input_sync(jack->input_dev);
}
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index 39672f68ce5..002777ba336 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -151,7 +151,7 @@ static inline void snd_rawmidi_output_trigger(struct snd_rawmidi_substream *subs
if (!substream->opened)
return;
if (up) {
- tasklet_hi_schedule(&substream->runtime->tasklet);
+ tasklet_schedule(&substream->runtime->tasklet);
} else {
tasklet_kill(&substream->runtime->tasklet);
substream->ops->trigger(substream, 0);
@@ -908,7 +908,7 @@ int snd_rawmidi_receive(struct snd_rawmidi_substream *substream,
}
if (result > 0) {
if (runtime->event)
- tasklet_hi_schedule(&runtime->tasklet);
+ tasklet_schedule(&runtime->tasklet);
else if (snd_rawmidi_ready(substream))
wake_up(&runtime->sleep);
}
diff --git a/sound/core/rtctimer.c b/sound/core/rtctimer.c
index 51e64e30dd3..0851cd13e30 100644
--- a/sound/core/rtctimer.c
+++ b/sound/core/rtctimer.c
@@ -118,7 +118,7 @@ static void rtctimer_tasklet(unsigned long data)
*/
static void rtctimer_interrupt(void *private_data)
{
- tasklet_hi_schedule(private_data);
+ tasklet_schedule(private_data);
}
diff --git a/sound/core/seq/seq.c b/sound/core/seq/seq.c
index ee0f8405ab3..bf09a5ad186 100644
--- a/sound/core/seq/seq.c
+++ b/sound/core/seq/seq.c
@@ -43,7 +43,9 @@ int seq_default_timer_class = SNDRV_TIMER_CLASS_GLOBAL;
int seq_default_timer_sclass = SNDRV_TIMER_SCLASS_NONE;
int seq_default_timer_card = -1;
int seq_default_timer_device =
-#ifdef CONFIG_SND_SEQ_RTCTIMER_DEFAULT
+#ifdef CONFIG_SND_SEQ_HRTIMER_DEFAULT
+ SNDRV_TIMER_GLOBAL_HRTIMER
+#elif defined(CONFIG_SND_SEQ_RTCTIMER_DEFAULT)
SNDRV_TIMER_GLOBAL_RTC
#else
SNDRV_TIMER_GLOBAL_SYSTEM
diff --git a/sound/core/timer.c b/sound/core/timer.c
index c584408c9f1..796532081e8 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -743,7 +743,7 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)
spin_unlock_irqrestore(&timer->lock, flags);
if (use_tasklet)
- tasklet_hi_schedule(&timer->task_queue);
+ tasklet_schedule(&timer->task_queue);
}
/*
diff --git a/sound/drivers/Kconfig b/sound/drivers/Kconfig
index 255fd18b9ae..0bcf14640fd 100644
--- a/sound/drivers/Kconfig
+++ b/sound/drivers/Kconfig
@@ -163,7 +163,7 @@ config SND_ML403_AC97CR
config SND_AC97_POWER_SAVE
bool "AC97 Power-Saving Mode"
- depends on SND_AC97_CODEC && EXPERIMENTAL
+ depends on SND_AC97_CODEC
default n
help
Say Y here to enable the aggressive power-saving support of
diff --git a/sound/drivers/pcsp/pcsp.c b/sound/drivers/pcsp/pcsp.c
index 1899cf0685b..2a02f704f36 100644
--- a/sound/drivers/pcsp/pcsp.c
+++ b/sound/drivers/pcsp/pcsp.c
@@ -96,7 +96,7 @@ static int __devinit snd_card_pcsp_probe(int devnum, struct device *dev)
return -EINVAL;
hrtimer_init(&pcsp_chip.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
- pcsp_chip.timer.cb_mode = HRTIMER_CB_SOFTIRQ;
+ pcsp_chip.timer.cb_mode = HRTIMER_CB_IRQSAFE_UNLOCKED;
pcsp_chip.timer.function = pcsp_do_timer;
card = snd_card_new(index, id, THIS_MODULE, 0);
@@ -188,10 +188,8 @@ static int __devexit pcsp_remove(struct platform_device *dev)
static void pcsp_stop_beep(struct snd_pcsp *chip)
{
- spin_lock_irq(&chip->substream_lock);
- if (!chip->playback_substream)
- pcspkr_stop_sound();
- spin_unlock_irq(&chip->substream_lock);
+ pcsp_sync_stop(chip);
+ pcspkr_stop_sound();
}
#ifdef CONFIG_PM
diff --git a/sound/drivers/pcsp/pcsp.h b/sound/drivers/pcsp/pcsp.h
index 1d661f795e8..cdef2664218 100644
--- a/sound/drivers/pcsp/pcsp.h
+++ b/sound/drivers/pcsp/pcsp.h
@@ -62,6 +62,8 @@ struct snd_pcsp {
unsigned short port, irq, dma;
spinlock_t substream_lock;
struct snd_pcm_substream *playback_substream;
+ unsigned int fmt_size;
+ unsigned int is_signed;
size_t playback_ptr;
size_t period_ptr;
atomic_t timer_active;
@@ -77,6 +79,7 @@ struct snd_pcsp {
extern struct snd_pcsp pcsp_chip;
extern enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle);
+extern void pcsp_sync_stop(struct snd_pcsp *chip);
extern int snd_pcsp_new_pcm(struct snd_pcsp *chip);
extern int snd_pcsp_new_mixer(struct snd_pcsp *chip);
diff --git a/sound/drivers/pcsp/pcsp_lib.c b/sound/drivers/pcsp/pcsp_lib.c
index 1f42e406311..84cc2658c05 100644
--- a/sound/drivers/pcsp/pcsp_lib.c
+++ b/sound/drivers/pcsp/pcsp_lib.c
@@ -8,6 +8,7 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
+#include <linux/interrupt.h>
#include <sound/pcm.h>
#include <asm/io.h>
#include "pcsp.h"
@@ -19,61 +20,57 @@ MODULE_PARM_DESC(nforce_wa, "Apply NForce chipset workaround "
#define DMIX_WANTS_S16 1
-enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle)
+/*
+ * Call snd_pcm_period_elapsed in a tasklet
+ * This avoids spinlock messes and long-running irq contexts
+ */
+static void pcsp_call_pcm_elapsed(unsigned long priv)
+{
+ if (atomic_read(&pcsp_chip.timer_active)) {
+ struct snd_pcm_substream *substream;
+ substream = pcsp_chip.playback_substream;
+ if (substream)
+ snd_pcm_period_elapsed(substream);
+ }
+}
+
+static DECLARE_TASKLET(pcsp_pcm_tasklet, pcsp_call_pcm_elapsed, 0);
+
+/* write the port and returns the next expire time in ns;
+ * called at the trigger-start and in hrtimer callback
+ */
+static unsigned long pcsp_timer_update(struct hrtimer *handle)
{
unsigned char timer_cnt, val;
- int fmt_size, periods_elapsed;
u64 ns;
- size_t period_bytes, buffer_bytes;
struct snd_pcm_substream *substream;
struct snd_pcm_runtime *runtime;
struct snd_pcsp *chip = container_of(handle, struct snd_pcsp, timer);
+ unsigned long flags;
if (chip->thalf) {
outb(chip->val61, 0x61);
chip->thalf = 0;
if (!atomic_read(&chip->timer_active))
- return HRTIMER_NORESTART;
- hrtimer_forward(&chip->timer, hrtimer_get_expires(&chip->timer),
- ktime_set(0, chip->ns_rem));
- return HRTIMER_RESTART;
+ return 0;
+ return chip->ns_rem;
}
- spin_lock_irq(&chip->substream_lock);
- /* Takashi Iwai says regarding this extra lock:
-
- If the irq handler handles some data on the DMA buffer, it should
- do snd_pcm_stream_lock().
- That protects basically against all races among PCM callbacks, yes.
- However, there are two remaining issues:
- 1. The substream pointer you try to lock isn't protected _before_
- this lock yet.
- 2. snd_pcm_period_elapsed() itself acquires the lock.
- The requirement of another lock is because of 1. When you get
- chip->playback_substream, it's not protected.
- Keeping this lock while snd_pcm_period_elapsed() assures the substream
- is still protected (at least, not released). And the other status is
- handled properly inside snd_pcm_stream_lock() in
- snd_pcm_period_elapsed().
-
- */
- if (!chip->playback_substream)
- goto exit_nr_unlock1;
- substream = chip->playback_substream;
- snd_pcm_stream_lock(substream);
if (!atomic_read(&chip->timer_active))
- goto exit_nr_unlock2;
+ return 0;
+ substream = chip->playback_substream;
+ if (!substream)
+ return 0;
runtime = substream->runtime;
- fmt_size = snd_pcm_format_physical_width(runtime->format) >> 3;
/* assume it is mono! */
- val = runtime->dma_area[chip->playback_ptr + fmt_size - 1];
- if (snd_pcm_format_signed(runtime->format))
+ val = runtime->dma_area[chip->playback_ptr + chip->fmt_size - 1];
+ if (chip->is_signed)
val ^= 0x80;
timer_cnt = val * CUR_DIV() / 256;
if (timer_cnt && chip->enable) {
- spin_lock(&i8253_lock);
+ spin_lock_irqsave(&i8253_lock, flags);
if (!nforce_wa) {
outb_p(chip->val61, 0x61);
outb_p(timer_cnt, 0x42);
@@ -82,12 +79,39 @@ enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle)
outb(chip->val61 ^ 2, 0x61);
chip->thalf = 1;
}
- spin_unlock(&i8253_lock);
+ spin_unlock_irqrestore(&i8253_lock, flags);
}
+ chip->ns_rem = PCSP_PERIOD_NS();
+ ns = (chip->thalf ? PCSP_CALC_NS(timer_cnt) : chip->ns_rem);
+ chip->ns_rem -= ns;
+ return ns;
+}
+
+enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle)
+{
+ struct snd_pcsp *chip = container_of(handle, struct snd_pcsp, timer);
+ struct snd_pcm_substream *substream;
+ int periods_elapsed, pointer_update;
+ size_t period_bytes, buffer_bytes;
+ unsigned long ns;
+ unsigned long flags;
+
+ pointer_update = !chip->thalf;
+ ns = pcsp_timer_update(handle);
+ if (!ns)
+ return HRTIMER_NORESTART;
+
+ /* update the playback position */
+ substream = chip->playback_substream;
+ if (!substream)
+ return HRTIMER_NORESTART;
+
period_bytes = snd_pcm_lib_period_bytes(substream);
buffer_bytes = snd_pcm_lib_buffer_bytes(substream);
- chip->playback_ptr += PCSP_INDEX_INC() * fmt_size;
+
+ spin_lock_irqsave(&chip->substream_lock, flags);
+ chip->playback_ptr += PCSP_INDEX_INC() * chip->fmt_size;
periods_elapsed = chip->playback_ptr - chip->period_ptr;
if (periods_elapsed < 0) {
#if PCSP_DEBUG
@@ -102,41 +126,30 @@ enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle)
* or ALSA will BUG on us. */
chip->playback_ptr %= buffer_bytes;
- snd_pcm_stream_unlock(substream);
-
if (periods_elapsed) {
- snd_pcm_period_elapsed(substream);
chip->period_ptr += periods_elapsed * period_bytes;
chip->period_ptr %= buffer_bytes;
}
+ spin_unlock_irqrestore(&chip->substream_lock, flags);
- spin_unlock_irq(&chip->substream_lock);
+ if (periods_elapsed)
+ tasklet_schedule(&pcsp_pcm_tasklet);
- if (!atomic_read(&chip->timer_active))
- return HRTIMER_NORESTART;
+ hrtimer_forward(handle, hrtimer_get_expires(handle), ns_to_ktime(ns));
- chip->ns_rem = PCSP_PERIOD_NS();
- ns = (chip->thalf ? PCSP_CALC_NS(timer_cnt) : chip->ns_rem);
- chip->ns_rem -= ns;
- hrtimer_forward(&chip->timer, hrtimer_get_expires(&chip->timer),
- ktime_set(0, ns));
return HRTIMER_RESTART;
-
-exit_nr_unlock2:
- snd_pcm_stream_unlock(substream);
-exit_nr_unlock1:
- spin_unlock_irq(&chip->substream_lock);
- return HRTIMER_NORESTART;
}
-static void pcsp_start_playing(struct snd_pcsp *chip)
+static int pcsp_start_playing(struct snd_pcsp *chip)
{
+ unsigned long ns;
+
#if PCSP_DEBUG
printk(KERN_INFO "PCSP: start_playing called\n");
#endif
if (atomic_read(&chip->timer_active)) {
printk(KERN_ERR "PCSP: Timer already active\n");
- return;
+ return -EIO;
}
spin_lock(&i8253_lock);
@@ -146,7 +159,12 @@ static void pcsp_start_playing(struct snd_pcsp *chip)
atomic_set(&chip->timer_active, 1);
chip->thalf = 0;
- hrtimer_start(&pcsp_chip.timer, ktime_set(0, 0), HRTIMER_MODE_REL);
+ ns = pcsp_timer_update(&pcsp_chip.timer);
+ if (!ns)
+ return -EIO;
+
+ hrtimer_start(&pcsp_chip.timer, ktime_set(0, ns), HRTIMER_MODE_REL);
+ return 0;
}
static void pcsp_stop_playing(struct snd_pcsp *chip)
@@ -165,26 +183,35 @@ static void pcsp_stop_playing(struct snd_pcsp *chip)
spin_unlock(&i8253_lock);
}
+/*
+ * Force to stop and sync the stream
+ */
+void pcsp_sync_stop(struct snd_pcsp *chip)
+{
+ local_irq_disable();
+ pcsp_stop_playing(chip);
+ local_irq_enable();
+ hrtimer_cancel(&chip->timer);
+ tasklet_kill(&pcsp_pcm_tasklet);
+}
+
static int snd_pcsp_playback_close(struct snd_pcm_substream *substream)
{
struct snd_pcsp *chip = snd_pcm_substream_chip(substream);
#if PCSP_DEBUG
printk(KERN_INFO "PCSP: close called\n");
#endif
- if (atomic_read(&chip->timer_active)) {
- printk(KERN_ERR "PCSP: timer still active\n");
- pcsp_stop_playing(chip);
- }
- spin_lock_irq(&chip->substream_lock);
+ pcsp_sync_stop(chip);
chip->playback_substream = NULL;
- spin_unlock_irq(&chip->substream_lock);
return 0;
}
static int snd_pcsp_playback_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *hw_params)
{
+ struct snd_pcsp *chip = snd_pcm_substream_chip(substream);
int err;
+ pcsp_sync_stop(chip);
err = snd_pcm_lib_malloc_pages(substream,
params_buffer_bytes(hw_params));
if (err < 0)
@@ -194,9 +221,11 @@ static int snd_pcsp_playback_hw_params(struct snd_pcm_substream *substream,
static int snd_pcsp_playback_hw_free(struct snd_pcm_substream *substream)
{
+ struct snd_pcsp *chip = snd_pcm_substream_chip(substream);
#if PCSP_DEBUG
printk(KERN_INFO "PCSP: hw_free called\n");
#endif
+ pcsp_sync_stop(chip);
return snd_pcm_lib_free_pages(substream);
}
@@ -212,8 +241,12 @@ static int snd_pcsp_playback_prepare(struct snd_pcm_substream *substream)
snd_pcm_lib_period_bytes(substream),
substream->runtime->periods);
#endif
+ pcsp_sync_stop(chip);
chip->playback_ptr = 0;
chip->period_ptr = 0;
+ chip->fmt_size =
+ snd_pcm_format_physical_width(substream->runtime->format) >> 3;
+ chip->is_signed = snd_pcm_format_signed(substream->runtime->format);
return 0;
}
@@ -226,8 +259,7 @@ static int snd_pcsp_trigger(struct snd_pcm_substream *substream, int cmd)
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
- pcsp_start_playing(chip);
- break;
+ return pcsp_start_playing(chip);
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
pcsp_stop_playing(chip);
@@ -242,7 +274,11 @@ static snd_pcm_uframes_t snd_pcsp_playback_pointer(struct snd_pcm_substream
*substream)
{
struct snd_pcsp *chip = snd_pcm_substream_chip(substream);
- return bytes_to_frames(substream->runtime, chip->playback_ptr);
+ unsigned int pos;
+ spin_lock(&chip->substream_lock);
+ pos = chip->playback_ptr;
+ spin_unlock(&chip->substream_lock);
+ return bytes_to_frames(substream->runtime, pos);
}
static struct snd_pcm_hardware snd_pcsp_playback = {
@@ -279,9 +315,7 @@ static int snd_pcsp_playback_open(struct snd_pcm_substream *substream)
return -EBUSY;
}
runtime->hw = snd_pcsp_playback;
- spin_lock_irq(&chip->substream_lock);
chip->playback_substream = substream;
- spin_unlock_irq(&chip->substream_lock);
return 0;
}
diff --git a/sound/drivers/vx/vx_core.c b/sound/drivers/vx/vx_core.c
index 473b07f6ae8..14e3354be43 100644
--- a/sound/drivers/vx/vx_core.c
+++ b/sound/drivers/vx/vx_core.c
@@ -548,7 +548,7 @@ irqreturn_t snd_vx_irq_handler(int irq, void *dev)
(chip->chip_status & VX_STAT_IS_STALE))
return IRQ_NONE;
if (! vx_test_and_ack(chip))
- tasklet_hi_schedule(&chip->tq);
+ tasklet_schedule(&chip->tq);
return IRQ_HANDLED;
}
diff --git a/sound/drivers/vx/vx_pcm.c b/sound/drivers/vx/vx_pcm.c
index 27de574c08f..6644d0034fb 100644
--- a/sound/drivers/vx/vx_pcm.c
+++ b/sound/drivers/vx/vx_pcm.c
@@ -823,7 +823,7 @@ static int vx_pcm_trigger(struct snd_pcm_substream *subs, int cmd)
* we trigger the pipe using tasklet, so that the interrupts are
* issued surely after the trigger is completed.
*/
- tasklet_hi_schedule(&pipe->start_tq);
+ tasklet_schedule(&pipe->start_tq);
chip->pcm_running++;
pipe->running = 1;
break;
diff --git a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c
index 667eccc676a..ea06877be4b 100644
--- a/sound/isa/sb/sb8.c
+++ b/sound/isa/sb/sb8.c
@@ -140,8 +140,10 @@ static int __devinit snd_sb8_probe(struct device *pdev, unsigned int dev)
break;
}
}
- if (i >= ARRAY_SIZE(possible_ports))
+ if (i >= ARRAY_SIZE(possible_ports)) {
+ err = -EINVAL;
goto _err;
+ }
}
acard->chip = chip;
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index 7003711f4fc..6e3a1848447 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -208,7 +208,8 @@ config SND_OXYGEN
* AuzenTech X-Meridian
* Bgears b-Enspirer
* Club3D Theatron DTS
- * HT-Omega Claro
+ * HT-Omega Claro (plus)
+ * HT-Omega Claro halo (XT)
* Razer Barracuda AC-1
* Sondigo Inferno
@@ -497,129 +498,7 @@ config SND_FM801_TEA575X
depends on SND_FM801_TEA575X_BOOL
default SND_FM801
-config SND_HDA_INTEL
- tristate "Intel HD Audio"
- select SND_PCM
- select SND_VMASTER
- help
- Say Y here to include support for Intel "High Definition
- Audio" (Azalia) motherboard devices.
-
- To compile this driver as a module, choose M here: the module
- will be called snd-hda-intel.
-
-config SND_HDA_HWDEP
- bool "Build hwdep interface for HD-audio driver"
- depends on SND_HDA_INTEL
- select SND_HWDEP
- help
- Say Y here to build a hwdep interface for HD-audio driver.
- This interface can be used for out-of-band communication
- with codecs for debugging purposes.
-
-config SND_HDA_INPUT_BEEP
- bool "Support digital beep via input layer"
- depends on SND_HDA_INTEL
- depends on INPUT=y || INPUT=SND_HDA_INTEL
- help
- Say Y here to build a digital beep interface for HD-audio
- driver. This interface is used to generate digital beeps.
-
-config SND_HDA_CODEC_REALTEK
- bool "Build Realtek HD-audio codec support"
- depends on SND_HDA_INTEL
- default y
- help
- Say Y here to include Realtek HD-audio codec support in
- snd-hda-intel driver, such as ALC880.
-
-config SND_HDA_CODEC_ANALOG
- bool "Build Analog Device HD-audio codec support"
- depends on SND_HDA_INTEL
- default y
- help
- Say Y here to include Analog Device HD-audio codec support in
- snd-hda-intel driver, such as AD1986A.
-
-config SND_HDA_CODEC_SIGMATEL
- bool "Build IDT/Sigmatel HD-audio codec support"
- depends on SND_HDA_INTEL
- default y
- help
- Say Y here to include IDT (Sigmatel) HD-audio codec support in
- snd-hda-intel driver, such as STAC9200.
-
-config SND_HDA_CODEC_VIA
- bool "Build VIA HD-audio codec support"
- depends on SND_HDA_INTEL
- default y
- help
- Say Y here to include VIA HD-audio codec support in
- snd-hda-intel driver, such as VT1708.
-
-config SND_HDA_CODEC_ATIHDMI
- bool "Build ATI HDMI HD-audio codec support"
- depends on SND_HDA_INTEL
- default y
- help
- Say Y here to include ATI HDMI HD-audio codec support in
- snd-hda-intel driver, such as ATI RS600 HDMI.
-
-config SND_HDA_CODEC_NVHDMI
- bool "Build NVIDIA HDMI HD-audio codec support"
- depends on SND_HDA_INTEL
- default y
- help
- Say Y here to include NVIDIA HDMI HD-audio codec support in
- snd-hda-intel driver, such as NVIDIA MCP78 HDMI.
-
-config SND_HDA_CODEC_CONEXANT
- bool "Build Conexant HD-audio codec support"
- depends on SND_HDA_INTEL
- default y
- help
- Say Y here to include Conexant HD-audio codec support in
- snd-hda-intel driver, such as CX20549.
-
-config SND_HDA_CODEC_CMEDIA
- bool "Build C-Media HD-audio codec support"
- depends on SND_HDA_INTEL
- default y
- help
- Say Y here to include C-Media HD-audio codec support in
- snd-hda-intel driver, such as CMI9880.
-
-config SND_HDA_CODEC_SI3054
- bool "Build Silicon Labs 3054 HD-modem codec support"
- depends on SND_HDA_INTEL
- default y
- help
- Say Y here to include Silicon Labs 3054 HD-modem codec
- (and compatibles) support in snd-hda-intel driver.
-
-config SND_HDA_GENERIC
- bool "Enable generic HD-audio codec parser"
- depends on SND_HDA_INTEL
- default y
- help
- Say Y here to enable the generic HD-audio codec parser
- in snd-hda-intel driver.
-
-config SND_HDA_POWER_SAVE
- bool "Aggressive power-saving on HD-audio"
- depends on SND_HDA_INTEL && EXPERIMENTAL
- help
- Say Y here to enable more aggressive power-saving mode on
- HD-audio driver. The power-saving timeout can be configured
- via power_save option or over sysfs on-the-fly.
-
-config SND_HDA_POWER_SAVE_DEFAULT
- int "Default time-out for HD-audio power-save mode"
- depends on SND_HDA_POWER_SAVE
- default 0
- help
- The default time-out value in seconds for HD-audio automatic
- power-save mode. 0 means to disable the power-save mode.
+source "sound/pci/hda/Kconfig"
config SND_HDSP
tristate "RME Hammerfall DSP Audio"
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c
index bd510eceff1..e2b843b4f9d 100644
--- a/sound/pci/ac97/ac97_codec.c
+++ b/sound/pci/ac97/ac97_codec.c
@@ -175,7 +175,7 @@ static const struct ac97_codec_id snd_ac97_codec_ids[] = {
{ 0x574d4C04, 0xffffffff, "WM9704M,WM9704Q", patch_wolfson04, NULL},
{ 0x574d4C05, 0xffffffff, "WM9705,WM9710", patch_wolfson05, NULL},
{ 0x574d4C09, 0xffffffff, "WM9709", NULL, NULL},
-{ 0x574d4C12, 0xffffffff, "WM9711,WM9712", patch_wolfson11, NULL},
+{ 0x574d4C12, 0xffffffff, "WM9711,WM9712,WM9715", patch_wolfson11, NULL},
{ 0x574d4c13, 0xffffffff, "WM9713,WM9714", patch_wolfson13, NULL, AC97_DEFAULT_POWER_OFF},
{ 0x594d4800, 0xffffffff, "YMF743", patch_yamaha_ymf743, NULL },
{ 0x594d4802, 0xffffffff, "YMF752", NULL, NULL },
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c
index 6e831aff1bd..81bc93e5f1e 100644
--- a/sound/pci/ac97/ac97_patch.c
+++ b/sound/pci/ac97/ac97_patch.c
@@ -2054,8 +2054,9 @@ static const struct snd_kcontrol_new snd_ac97_ad1888_controls[] = {
.get = snd_ac97_ad1888_lohpsel_get,
.put = snd_ac97_ad1888_lohpsel_put
},
- AC97_SINGLE("V_REFOUT Enable", AC97_AD_MISC, 2, 1, 1),
- AC97_SINGLE("High Pass Filter Enable", AC97_AD_TEST2, 12, 1, 1),
+ AC97_SINGLE("V_REFOUT Enable", AC97_AD_MISC, AC97_AD_VREFD_SHIFT, 1, 1),
+ AC97_SINGLE("High Pass Filter Enable", AC97_AD_TEST2,
+ AC97_AD_HPFD_SHIFT, 1, 1),
AC97_SINGLE("Spread Front to Surround and Center/LFE", AC97_AD_MISC, 7, 1, 0),
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -2832,6 +2833,8 @@ static int patch_alc655(struct snd_ac97 * ac97)
val &= ~(1 << 1); /* Pin 47 is EAPD (for internal speaker) */
else
val |= (1 << 1); /* Pin 47 is spdif input pin */
+ /* this seems missing on some hardwares */
+ ac97->ext_id |= AC97_EI_SPDIF;
}
val &= ~(1 << 12); /* vref enable */
snd_ac97_write_cache(ac97, 0x7a, val);
diff --git a/sound/pci/ca0106/ca0106.h b/sound/pci/ca0106/ca0106.h
index 74175fc80c7..14b8d9a91aa 100644
--- a/sound/pci/ca0106/ca0106.h
+++ b/sound/pci/ca0106/ca0106.h
@@ -664,10 +664,14 @@ struct snd_ca0106_pcm {
struct snd_ca0106_details {
u32 serial;
char * name;
- int ac97;
- int gpio_type;
- int i2c_adc;
- int spi_dac;
+ int ac97; /* ac97 = 0 -> Select MIC, Line in, TAD in, AUX in.
+ ac97 = 1 -> Default to AC97 in. */
+ int gpio_type; /* gpio_type = 1 -> shared mic-in/line-in
+ gpio_type = 2 -> shared side-out/line-in. */
+ int i2c_adc; /* with i2c_adc=1, the driver adds some capture volume
+ controls, phone, mic, line-in and aux. */
+ int spi_dac; /* spi_dac=1 adds the mute switch for each analog
+ output, front, rear, etc. */
};
// definition of the chip-specific record
@@ -686,11 +690,12 @@ struct snd_ca0106 {
spinlock_t emu_lock;
struct snd_ac97 *ac97;
- struct snd_pcm *pcm;
+ struct snd_pcm *pcm[4];
struct snd_ca0106_channel playback_channels[4];
struct snd_ca0106_channel capture_channels[4];
- u32 spdif_bits[4]; /* s/pdif out setup */
+ u32 spdif_bits[4]; /* s/pdif out default setup */
+ u32 spdif_str_bits[4]; /* s/pdif out per-stream setup */
int spdif_enable;
int capture_source;
int i2c_capture_source;
@@ -703,6 +708,11 @@ struct snd_ca0106 {
struct snd_ca_midi midi2;
u16 spi_dac_reg[16];
+
+#ifdef CONFIG_PM
+#define NUM_SAVED_VOLUMES 9
+ unsigned int saved_vol[NUM_SAVED_VOLUMES];
+#endif
};
int snd_ca0106_mixer(struct snd_ca0106 *emu);
@@ -721,3 +731,11 @@ int snd_ca0106_i2c_write(struct snd_ca0106 *emu, u32 reg, u32 value);
int snd_ca0106_spi_write(struct snd_ca0106 * emu,
unsigned int data);
+
+#ifdef CONFIG_PM
+void snd_ca0106_mixer_suspend(struct snd_ca0106 *chip);
+void snd_ca0106_mixer_resume(struct snd_ca0106 *chip);
+#else
+#define snd_ca0106_mixer_suspend(chip) do { } while (0)
+#define snd_ca0106_mixer_resume(chip) do { } while (0)
+#endif
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
index 88fbf285d2b..0e62205d408 100644
--- a/sound/pci/ca0106/ca0106_main.c
+++ b/sound/pci/ca0106/ca0106_main.c
@@ -254,7 +254,7 @@ static struct snd_ca0106_details ca0106_chip_details[] = {
.name = "MSI K8N Diamond MB",
.gpio_type = 2,
.i2c_adc = 1,
- .spi_dac = 2 } ,
+ .spi_dac = 1 } ,
/* Shuttle XPC SD31P which has an onboard Creative Labs
* Sound Blaster Live! 24-bit EAX
* high-definition 7.1 audio processor".
@@ -305,9 +305,15 @@ static struct snd_pcm_hardware snd_ca0106_capture_hw = {
SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP_VALID),
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
+#if 0 /* FIXME: looks like 44.1kHz capture causes noisy output on 48kHz */
.rates = (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000),
.rate_min = 44100,
+#else
+ .rates = (SNDRV_PCM_RATE_48000 |
+ SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000),
+ .rate_min = 48000,
+#endif /* FIXME */
.rate_max = 192000,
.channels_min = 2,
.channels_max = 2,
@@ -479,6 +485,15 @@ static const int spi_dacd_bit[] = {
[PCM_UNKNOWN_CHANNEL] = SPI_DACD1_BIT,
};
+static void restore_spdif_bits(struct snd_ca0106 *chip, int idx)
+{
+ if (chip->spdif_str_bits[idx] != chip->spdif_bits[idx]) {
+ chip->spdif_str_bits[idx] = chip->spdif_bits[idx];
+ snd_ca0106_ptr_write(chip, SPCS0 + idx, 0,
+ chip->spdif_str_bits[idx]);
+ }
+}
+
/* open_playback callback */
static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substream,
int channel_id)
@@ -524,6 +539,9 @@ static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substr
if (err < 0)
return err;
}
+
+ restore_spdif_bits(chip, channel_id);
+
return 0;
}
@@ -535,6 +553,8 @@ static int snd_ca0106_pcm_close_playback(struct snd_pcm_substream *substream)
struct snd_ca0106_pcm *epcm = runtime->private_data;
chip->playback_channels[epcm->channel_id].use = 0;
+ restore_spdif_bits(chip, epcm->channel_id);
+
if (chip->details->spi_dac && epcm->channel_id != PCM_FRONT_CHANNEL) {
const int reg = spi_dacd_reg[epcm->channel_id];
@@ -847,15 +867,18 @@ static int snd_ca0106_pcm_trigger_playback(struct snd_pcm_substream *substream,
struct snd_pcm_substream *s;
u32 basic = 0;
u32 extended = 0;
- int running=0;
+ u32 bits;
+ int running = 0;
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
- running=1;
+ case SNDRV_PCM_TRIGGER_RESUME:
+ running = 1;
break;
case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
default:
- running=0;
+ running = 0;
break;
}
snd_pcm_group_for_each_entry(s, substream) {
@@ -865,22 +888,32 @@ static int snd_ca0106_pcm_trigger_playback(struct snd_pcm_substream *substream,
runtime = s->runtime;
epcm = runtime->private_data;
channel = epcm->channel_id;
- //snd_printk("channel=%d\n",channel);
+ /* snd_printk("channel=%d\n",channel); */
epcm->running = running;
- basic |= (0x1<<channel);
- extended |= (0x10<<channel);
+ basic |= (0x1 << channel);
+ extended |= (0x10 << channel);
snd_pcm_trigger_done(s, substream);
}
- //snd_printk("basic=0x%x, extended=0x%x\n",basic, extended);
+ /* snd_printk("basic=0x%x, extended=0x%x\n",basic, extended); */
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
- snd_ca0106_ptr_write(emu, EXTENDED_INT_MASK, 0, snd_ca0106_ptr_read(emu, EXTENDED_INT_MASK, 0) | (extended));
- snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, snd_ca0106_ptr_read(emu, BASIC_INTERRUPT, 0)|(basic));
+ case SNDRV_PCM_TRIGGER_RESUME:
+ bits = snd_ca0106_ptr_read(emu, EXTENDED_INT_MASK, 0);
+ bits |= extended;
+ snd_ca0106_ptr_write(emu, EXTENDED_INT_MASK, 0, bits);
+ bits = snd_ca0106_ptr_read(emu, BASIC_INTERRUPT, 0);
+ bits |= basic;
+ snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, bits);
break;
case SNDRV_PCM_TRIGGER_STOP:
- snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, snd_ca0106_ptr_read(emu, BASIC_INTERRUPT, 0) & ~(basic));
- snd_ca0106_ptr_write(emu, EXTENDED_INT_MASK, 0, snd_ca0106_ptr_read(emu, EXTENDED_INT_MASK, 0) & ~(extended));
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ bits = snd_ca0106_ptr_read(emu, BASIC_INTERRUPT, 0);
+ bits &= ~basic;
+ snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, bits);
+ bits = snd_ca0106_ptr_read(emu, EXTENDED_INT_MASK, 0);
+ bits &= ~extended;
+ snd_ca0106_ptr_write(emu, EXTENDED_INT_MASK, 0, bits);
break;
default:
result = -EINVAL;
@@ -1103,21 +1136,13 @@ static int snd_ca0106_ac97(struct snd_ca0106 *chip)
return snd_ac97_mixer(pbus, &ac97, &chip->ac97);
}
+static void ca0106_stop_chip(struct snd_ca0106 *chip);
+
static int snd_ca0106_free(struct snd_ca0106 *chip)
{
- if (chip->res_port != NULL) { /* avoid access to already used hardware */
- // disable interrupts
- snd_ca0106_ptr_write(chip, BASIC_INTERRUPT, 0, 0);
- outl(0, chip->port + INTE);
- snd_ca0106_ptr_write(chip, EXTENDED_INT_MASK, 0, 0);
- udelay(1000);
- // disable audio
- //outl(HCFG_LOCKSOUNDCACHE, chip->port + HCFG);
- outl(0, chip->port + HCFG);
- /* FIXME: We need to stop and DMA transfers here.
- * But as I am not sure how yet, we cannot from the dma pages.
- * So we can fix: snd-malloc: Memory leak? pages not freed = 8
- */
+ if (chip->res_port != NULL) {
+ /* avoid access to already used hardware */
+ ca0106_stop_chip(chip);
}
if (chip->irq >= 0)
free_irq(chip->irq, chip);
@@ -1203,15 +1228,14 @@ static irqreturn_t snd_ca0106_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static int __devinit snd_ca0106_pcm(struct snd_ca0106 *emu, int device, struct snd_pcm **rpcm)
+static int __devinit snd_ca0106_pcm(struct snd_ca0106 *emu, int device)
{
struct snd_pcm *pcm;
struct snd_pcm_substream *substream;
int err;
- if (rpcm)
- *rpcm = NULL;
- if ((err = snd_pcm_new(emu->card, "ca0106", device, 1, 1, &pcm)) < 0)
+ err = snd_pcm_new(emu->card, "ca0106", device, 1, 1, &pcm);
+ if (err < 0)
return err;
pcm->private_data = emu;
@@ -1238,7 +1262,6 @@ static int __devinit snd_ca0106_pcm(struct snd_ca0106 *emu, int device, struct s
pcm->info_flags = 0;
pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
strcpy(pcm->name, "CA0106");
- emu->pcm = pcm;
for(substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
substream;
@@ -1260,8 +1283,7 @@ static int __devinit snd_ca0106_pcm(struct snd_ca0106 *emu, int device, struct s
return err;
}
- if (rpcm)
- *rpcm = pcm;
+ emu->pcm[device] = pcm;
return 0;
}
@@ -1301,89 +1323,10 @@ static unsigned int i2c_adc_init[][2] = {
{ 0x15, ADC_MUX_LINEIN }, /* ADC Mixer control */
};
-static int __devinit snd_ca0106_create(int dev, struct snd_card *card,
- struct pci_dev *pci,
- struct snd_ca0106 **rchip)
+static void ca0106_init_chip(struct snd_ca0106 *chip, int resume)
{
- struct snd_ca0106 *chip;
- struct snd_ca0106_details *c;
- int err;
int ch;
- static struct snd_device_ops ops = {
- .dev_free = snd_ca0106_dev_free,
- };
-
- *rchip = NULL;
-
- if ((err = pci_enable_device(pci)) < 0)
- return err;
- if (pci_set_dma_mask(pci, DMA_32BIT_MASK) < 0 ||
- pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK) < 0) {
- printk(KERN_ERR "error to set 32bit mask DMA\n");
- pci_disable_device(pci);
- return -ENXIO;
- }
-
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
- if (chip == NULL) {
- pci_disable_device(pci);
- return -ENOMEM;
- }
-
- chip->card = card;
- chip->pci = pci;
- chip->irq = -1;
-
- spin_lock_init(&chip->emu_lock);
-
- chip->port = pci_resource_start(pci, 0);
- if ((chip->res_port = request_region(chip->port, 0x20,
- "snd_ca0106")) == NULL) {
- snd_ca0106_free(chip);
- printk(KERN_ERR "cannot allocate the port\n");
- return -EBUSY;
- }
-
- if (request_irq(pci->irq, snd_ca0106_interrupt,
- IRQF_SHARED, "snd_ca0106", chip)) {
- snd_ca0106_free(chip);
- printk(KERN_ERR "cannot grab irq\n");
- return -EBUSY;
- }
- chip->irq = pci->irq;
-
- /* This stores the periods table. */
- if(snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), 1024, &chip->buffer) < 0) {
- snd_ca0106_free(chip);
- return -ENOMEM;
- }
-
- pci_set_master(pci);
- /* read serial */
- pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &chip->serial);
- pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &chip->model);
-#if 1
- printk(KERN_INFO "snd-ca0106: Model %04x Rev %08x Serial %08x\n", chip->model,
- pci->revision, chip->serial);
-#endif
- strcpy(card->driver, "CA0106");
- strcpy(card->shortname, "CA0106");
-
- for (c = ca0106_chip_details; c->serial; c++) {
- if (subsystem[dev]) {
- if (c->serial == subsystem[dev])
- break;
- } else if (c->serial == chip->serial)
- break;
- }
- chip->details = c;
- if (subsystem[dev]) {
- printk(KERN_INFO "snd-ca0106: Sound card name=%s, subsystem=0x%x. Forced to subsystem=0x%x\n",
- c->name, chip->serial, subsystem[dev]);
- }
-
- sprintf(card->longname, "%s at 0x%lx irq %i",
- c->name, chip->port, chip->irq);
+ unsigned int def_bits;
outl(0, chip->port + INTE);
@@ -1401,31 +1344,22 @@ static int __devinit snd_ca0106_create(int dev, struct snd_card *card,
* AN = 0 (Audio data)
* P = 0 (Consumer)
*/
- snd_ca0106_ptr_write(chip, SPCS0, 0,
- chip->spdif_bits[0] =
- SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
- SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
- SPCS_GENERATIONSTATUS | 0x00001200 |
- 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
+ def_bits =
+ SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
+ SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
+ SPCS_GENERATIONSTATUS | 0x00001200 |
+ 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT;
+ if (!resume) {
+ chip->spdif_str_bits[0] = chip->spdif_bits[0] = def_bits;
+ chip->spdif_str_bits[1] = chip->spdif_bits[1] = def_bits;
+ chip->spdif_str_bits[2] = chip->spdif_bits[2] = def_bits;
+ chip->spdif_str_bits[3] = chip->spdif_bits[3] = def_bits;
+ }
/* Only SPCS1 has been tested */
- snd_ca0106_ptr_write(chip, SPCS1, 0,
- chip->spdif_bits[1] =
- SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
- SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
- SPCS_GENERATIONSTATUS | 0x00001200 |
- 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
- snd_ca0106_ptr_write(chip, SPCS2, 0,
- chip->spdif_bits[2] =
- SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
- SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
- SPCS_GENERATIONSTATUS | 0x00001200 |
- 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
- snd_ca0106_ptr_write(chip, SPCS3, 0,
- chip->spdif_bits[3] =
- SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
- SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
- SPCS_GENERATIONSTATUS | 0x00001200 |
- 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
+ snd_ca0106_ptr_write(chip, SPCS1, 0, chip->spdif_str_bits[1]);
+ snd_ca0106_ptr_write(chip, SPCS0, 0, chip->spdif_str_bits[0]);
+ snd_ca0106_ptr_write(chip, SPCS2, 0, chip->spdif_str_bits[2]);
+ snd_ca0106_ptr_write(chip, SPCS3, 0, chip->spdif_str_bits[3]);
snd_ca0106_ptr_write(chip, PLAYBACK_MUTE, 0, 0x00fc0000);
snd_ca0106_ptr_write(chip, CAPTURE_MUTE, 0, 0x00fc0000);
@@ -1433,92 +1367,124 @@ static int __devinit snd_ca0106_create(int dev, struct snd_card *card,
/* Write 0x8000 to AC97_REC_GAIN to mute it. */
outb(AC97_REC_GAIN, chip->port + AC97ADDRESS);
outw(0x8000, chip->port + AC97DATA);
-#if 0
+#if 0 /* FIXME: what are these? */
snd_ca0106_ptr_write(chip, SPCS0, 0, 0x2108006);
snd_ca0106_ptr_write(chip, 0x42, 0, 0x2108006);
snd_ca0106_ptr_write(chip, 0x43, 0, 0x2108006);
snd_ca0106_ptr_write(chip, 0x44, 0, 0x2108006);
#endif
- //snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0xf0f003f); /* OSS drivers set this. */
+ /* OSS drivers set this. */
+ /* snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0xf0f003f); */
+
/* Analog or Digital output */
snd_ca0106_ptr_write(chip, SPDIF_SELECT1, 0, 0xf);
- snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0x000f0000); /* 0x0b000000 for digital, 0x000b0000 for analog, from win2000 drivers. Use 0x000f0000 for surround71 */
+ /* 0x0b000000 for digital, 0x000b0000 for analog, from win2000 drivers.
+ * Use 0x000f0000 for surround71
+ */
+ snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0x000f0000);
+
chip->spdif_enable = 0; /* Set digital SPDIF output off */
- //snd_ca0106_ptr_write(chip, 0x45, 0, 0); /* Analogue out */
- //snd_ca0106_ptr_write(chip, 0x45, 0, 0xf00); /* Digital out */
+ /*snd_ca0106_ptr_write(chip, 0x45, 0, 0);*/ /* Analogue out */
+ /*snd_ca0106_ptr_write(chip, 0x45, 0, 0xf00);*/ /* Digital out */
+
+ /* goes to 0x40c80000 when doing SPDIF IN/OUT */
+ snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 0, 0x40c81000);
+ /* (Mute) CAPTURE feedback into PLAYBACK volume.
+ * Only lower 16 bits matter.
+ */
+ snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 1, 0xffffffff);
+ /* SPDIF IN Volume */
+ snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 2, 0x30300000);
+ /* SPDIF IN Volume, 0x70 = (vol & 0x3f) | 0x40 */
+ snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 3, 0x00700000);
- snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 0, 0x40c81000); /* goes to 0x40c80000 when doing SPDIF IN/OUT */
- snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 1, 0xffffffff); /* (Mute) CAPTURE feedback into PLAYBACK volume. Only lower 16 bits matter. */
- snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 2, 0x30300000); /* SPDIF IN Volume */
- snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 3, 0x00700000); /* SPDIF IN Volume, 0x70 = (vol & 0x3f) | 0x40 */
snd_ca0106_ptr_write(chip, PLAYBACK_ROUTING1, 0, 0x32765410);
snd_ca0106_ptr_write(chip, PLAYBACK_ROUTING2, 0, 0x76767676);
snd_ca0106_ptr_write(chip, CAPTURE_ROUTING1, 0, 0x32765410);
snd_ca0106_ptr_write(chip, CAPTURE_ROUTING2, 0, 0x76767676);
- for(ch = 0; ch < 4; ch++) {
- snd_ca0106_ptr_write(chip, CAPTURE_VOLUME1, ch, 0x30303030); /* Only high 16 bits matter */
+
+ for (ch = 0; ch < 4; ch++) {
+ /* Only high 16 bits matter */
+ snd_ca0106_ptr_write(chip, CAPTURE_VOLUME1, ch, 0x30303030);
snd_ca0106_ptr_write(chip, CAPTURE_VOLUME2, ch, 0x30303030);
- //snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME1, ch, 0x40404040); /* Mute */
- //snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME2, ch, 0x40404040); /* Mute */
- snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME1, ch, 0xffffffff); /* Mute */
- snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME2, ch, 0xffffffff); /* Mute */
+#if 0 /* Mute */
+ snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME1, ch, 0x40404040);
+ snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME2, ch, 0x40404040);
+ snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME1, ch, 0xffffffff);
+ snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME2, ch, 0xffffffff);
+#endif
}
if (chip->details->i2c_adc == 1) {
/* Select MIC, Line in, TAD in, AUX in */
snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x333300e4);
/* Default to CAPTURE_SOURCE to i2s in */
- chip->capture_source = 3;
+ if (!resume)
+ chip->capture_source = 3;
} else if (chip->details->ac97 == 1) {
/* Default to AC97 in */
snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x444400e4);
/* Default to CAPTURE_SOURCE to AC97 in */
- chip->capture_source = 4;
+ if (!resume)
+ chip->capture_source = 4;
} else {
/* Select MIC, Line in, TAD in, AUX in */
snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x333300e4);
/* Default to Set CAPTURE_SOURCE to i2s in */
- chip->capture_source = 3;
+ if (!resume)
+ chip->capture_source = 3;
}
- if (chip->details->gpio_type == 2) { /* The SB0438 use GPIO differently. */
- /* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */
+ if (chip->details->gpio_type == 2) {
+ /* The SB0438 use GPIO differently. */
+ /* FIXME: Still need to find out what the other GPIO bits do.
+ * E.g. For digital spdif out.
+ */
outl(0x0, chip->port+GPIO);
- //outl(0x00f0e000, chip->port+GPIO); /* Analog */
+ /* outl(0x00f0e000, chip->port+GPIO); */ /* Analog */
outl(0x005f5301, chip->port+GPIO); /* Analog */
- } else if (chip->details->gpio_type == 1) { /* The SB0410 and SB0413 use GPIO differently. */
- /* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */
+ } else if (chip->details->gpio_type == 1) {
+ /* The SB0410 and SB0413 use GPIO differently. */
+ /* FIXME: Still need to find out what the other GPIO bits do.
+ * E.g. For digital spdif out.
+ */
outl(0x0, chip->port+GPIO);
- //outl(0x00f0e000, chip->port+GPIO); /* Analog */
+ /* outl(0x00f0e000, chip->port+GPIO); */ /* Analog */
outl(0x005f5301, chip->port+GPIO); /* Analog */
} else {
outl(0x0, chip->port+GPIO);
outl(0x005f03a3, chip->port+GPIO); /* Analog */
- //outl(0x005f02a2, chip->port+GPIO); /* SPDIF */
+ /* outl(0x005f02a2, chip->port+GPIO); */ /* SPDIF */
}
snd_ca0106_intr_enable(chip, 0x105); /* Win2000 uses 0x1e0 */
- //outl(HCFG_LOCKSOUNDCACHE|HCFG_AUDIOENABLE, chip->port+HCFG);
- //outl(0x00001409, chip->port+HCFG); /* 0x1000 causes AC3 to fails. Maybe it effects 24 bit output. */
- //outl(0x00000009, chip->port+HCFG);
- outl(HCFG_AC97 | HCFG_AUDIOENABLE, chip->port+HCFG); /* AC97 2.0, Enable outputs. */
+ /* outl(HCFG_LOCKSOUNDCACHE|HCFG_AUDIOENABLE, chip->port+HCFG); */
+ /* 0x1000 causes AC3 to fails. Maybe it effects 24 bit output. */
+ /* outl(0x00001409, chip->port+HCFG); */
+ /* outl(0x00000009, chip->port+HCFG); */
+ /* AC97 2.0, Enable outputs. */
+ outl(HCFG_AC97 | HCFG_AUDIOENABLE, chip->port+HCFG);
- if (chip->details->i2c_adc == 1) { /* The SB0410 and SB0413 use I2C to control ADC. */
+ if (chip->details->i2c_adc == 1) {
+ /* The SB0410 and SB0413 use I2C to control ADC. */
int size, n;
size = ARRAY_SIZE(i2c_adc_init);
- //snd_printk("I2C:array size=0x%x\n", size);
- for (n=0; n < size; n++) {
- snd_ca0106_i2c_write(chip, i2c_adc_init[n][0], i2c_adc_init[n][1]);
- }
- for (n=0; n < 4; n++) {
- chip->i2c_capture_volume[n][0]= 0xcf;
- chip->i2c_capture_volume[n][1]= 0xcf;
+ /* snd_printk("I2C:array size=0x%x\n", size); */
+ for (n = 0; n < size; n++)
+ snd_ca0106_i2c_write(chip, i2c_adc_init[n][0],
+ i2c_adc_init[n][1]);
+ for (n = 0; n < 4; n++) {
+ chip->i2c_capture_volume[n][0] = 0xcf;
+ chip->i2c_capture_volume[n][1] = 0xcf;
}
- chip->i2c_capture_source=2; /* Line in */
- //snd_ca0106_i2c_write(chip, ADC_MUX, ADC_MUX_LINEIN); /* Enable Line-in capture. MIC in currently untested. */
+ chip->i2c_capture_source = 2; /* Line in */
+ /* Enable Line-in capture. MIC in currently untested. */
+ /* snd_ca0106_i2c_write(chip, ADC_MUX, ADC_MUX_LINEIN); */
}
- if (chip->details->spi_dac == 1) { /* The SB0570 use SPI to control DAC. */
+
+ if (chip->details->spi_dac == 1) {
+ /* The SB0570 use SPI to control DAC. */
int size, n;
size = ARRAY_SIZE(spi_dac_init);
@@ -1530,9 +1496,112 @@ static int __devinit snd_ca0106_create(int dev, struct snd_card *card,
chip->spi_dac_reg[reg] = spi_dac_init[n];
}
}
+}
- if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL,
- chip, &ops)) < 0) {
+static void ca0106_stop_chip(struct snd_ca0106 *chip)
+{
+ /* disable interrupts */
+ snd_ca0106_ptr_write(chip, BASIC_INTERRUPT, 0, 0);
+ outl(0, chip->port + INTE);
+ snd_ca0106_ptr_write(chip, EXTENDED_INT_MASK, 0, 0);
+ udelay(1000);
+ /* disable audio */
+ /* outl(HCFG_LOCKSOUNDCACHE, chip->port + HCFG); */
+ outl(0, chip->port + HCFG);
+ /* FIXME: We need to stop and DMA transfers here.
+ * But as I am not sure how yet, we cannot from the dma pages.
+ * So we can fix: snd-malloc: Memory leak? pages not freed = 8
+ */
+}
+
+static int __devinit snd_ca0106_create(int dev, struct snd_card *card,
+ struct pci_dev *pci,
+ struct snd_ca0106 **rchip)
+{
+ struct snd_ca0106 *chip;
+ struct snd_ca0106_details *c;
+ int err;
+ static struct snd_device_ops ops = {
+ .dev_free = snd_ca0106_dev_free,
+ };
+
+ *rchip = NULL;
+
+ err = pci_enable_device(pci);
+ if (err < 0)
+ return err;
+ if (pci_set_dma_mask(pci, DMA_32BIT_MASK) < 0 ||
+ pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK) < 0) {
+ printk(KERN_ERR "error to set 32bit mask DMA\n");
+ pci_disable_device(pci);
+ return -ENXIO;
+ }
+
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+ if (chip == NULL) {
+ pci_disable_device(pci);
+ return -ENOMEM;
+ }
+
+ chip->card = card;
+ chip->pci = pci;
+ chip->irq = -1;
+
+ spin_lock_init(&chip->emu_lock);
+
+ chip->port = pci_resource_start(pci, 0);
+ chip->res_port = request_region(chip->port, 0x20, "snd_ca0106");
+ if (!chip->res_port) {
+ snd_ca0106_free(chip);
+ printk(KERN_ERR "cannot allocate the port\n");
+ return -EBUSY;
+ }
+
+ if (request_irq(pci->irq, snd_ca0106_interrupt,
+ IRQF_SHARED, "snd_ca0106", chip)) {
+ snd_ca0106_free(chip);
+ printk(KERN_ERR "cannot grab irq\n");
+ return -EBUSY;
+ }
+ chip->irq = pci->irq;
+
+ /* This stores the periods table. */
+ if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
+ 1024, &chip->buffer) < 0) {
+ snd_ca0106_free(chip);
+ return -ENOMEM;
+ }
+
+ pci_set_master(pci);
+ /* read serial */
+ pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &chip->serial);
+ pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &chip->model);
+ printk(KERN_INFO "snd-ca0106: Model %04x Rev %08x Serial %08x\n",
+ chip->model, pci->revision, chip->serial);
+ strcpy(card->driver, "CA0106");
+ strcpy(card->shortname, "CA0106");
+
+ for (c = ca0106_chip_details; c->serial; c++) {
+ if (subsystem[dev]) {
+ if (c->serial == subsystem[dev])
+ break;
+ } else if (c->serial == chip->serial)
+ break;
+ }
+ chip->details = c;
+ if (subsystem[dev]) {
+ printk(KERN_INFO "snd-ca0106: Sound card name=%s, "
+ "subsystem=0x%x. Forced to subsystem=0x%x\n",
+ c->name, chip->serial, subsystem[dev]);
+ }
+
+ sprintf(card->longname, "%s at 0x%lx irq %i",
+ c->name, chip->port, chip->irq);
+
+ ca0106_init_chip(chip, 0);
+
+ err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
+ if (err < 0) {
snd_ca0106_free(chip);
return err;
}
@@ -1629,7 +1698,7 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci,
static int dev;
struct snd_card *card;
struct snd_ca0106 *chip;
- int err;
+ int i, err;
if (dev >= SNDRV_CARDS)
return -ENODEV;
@@ -1642,44 +1711,31 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci,
if (card == NULL)
return -ENOMEM;
- if ((err = snd_ca0106_create(dev, card, pci, &chip)) < 0) {
- snd_card_free(card);
- return err;
- }
+ err = snd_ca0106_create(dev, card, pci, &chip);
+ if (err < 0)
+ goto error;
+ card->private_data = chip;
- if ((err = snd_ca0106_pcm(chip, 0, NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
- if ((err = snd_ca0106_pcm(chip, 1, NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
- if ((err = snd_ca0106_pcm(chip, 2, NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
- if ((err = snd_ca0106_pcm(chip, 3, NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
- if (chip->details->ac97 == 1) { /* The SB0410 and SB0413 do not have an AC97 chip. */
- if ((err = snd_ca0106_ac97(chip)) < 0) {
- snd_card_free(card);
- return err;
- }
+ for (i = 0; i < 4; i++) {
+ err = snd_ca0106_pcm(chip, i);
+ if (err < 0)
+ goto error;
}
- if ((err = snd_ca0106_mixer(chip)) < 0) {
- snd_card_free(card);
- return err;
+
+ if (chip->details->ac97 == 1) {
+ /* The SB0410 and SB0413 do not have an AC97 chip. */
+ err = snd_ca0106_ac97(chip);
+ if (err < 0)
+ goto error;
}
+ err = snd_ca0106_mixer(chip);
+ if (err < 0)
+ goto error;
snd_printdd("ca0106: probe for MIDI channel A ...");
- if ((err = snd_ca0106_midi(chip,CA0106_MIDI_CHAN_A)) < 0) {
- snd_card_free(card);
- snd_printdd(" failed, err=0x%x\n",err);
- return err;
- }
+ err = snd_ca0106_midi(chip, CA0106_MIDI_CHAN_A);
+ if (err < 0)
+ goto error;
snd_printdd(" done.\n");
#ifdef CONFIG_PROC_FS
@@ -1688,14 +1744,17 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci,
snd_card_set_dev(card, &pci->dev);
- if ((err = snd_card_register(card)) < 0) {
- snd_card_free(card);
- return err;
- }
+ err = snd_card_register(card);
+ if (err < 0)
+ goto error;
pci_set_drvdata(pci, card);
dev++;
return 0;
+
+ error:
+ snd_card_free(card);
+ return err;
}
static void __devexit snd_ca0106_remove(struct pci_dev *pci)
@@ -1704,6 +1763,59 @@ static void __devexit snd_ca0106_remove(struct pci_dev *pci)
pci_set_drvdata(pci, NULL);
}
+#ifdef CONFIG_PM
+static int snd_ca0106_suspend(struct pci_dev *pci, pm_message_t state)
+{
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct snd_ca0106 *chip = card->private_data;
+ int i;
+
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+ for (i = 0; i < 4; i++)
+ snd_pcm_suspend_all(chip->pcm[i]);
+ if (chip->details->ac97)
+ snd_ac97_suspend(chip->ac97);
+ snd_ca0106_mixer_suspend(chip);
+
+ ca0106_stop_chip(chip);
+
+ pci_disable_device(pci);
+ pci_save_state(pci);
+ pci_set_power_state(pci, pci_choose_state(pci, state));
+ return 0;
+}
+
+static int snd_ca0106_resume(struct pci_dev *pci)
+{
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct snd_ca0106 *chip = card->private_data;
+ int i;
+
+ pci_set_power_state(pci, PCI_D0);
+ pci_restore_state(pci);
+
+ if (pci_enable_device(pci) < 0) {
+ snd_card_disconnect(card);
+ return -EIO;
+ }
+
+ pci_set_master(pci);
+
+ ca0106_init_chip(chip, 1);
+
+ if (chip->details->ac97)
+ snd_ac97_resume(chip->ac97);
+ snd_ca0106_mixer_resume(chip);
+ if (chip->details->spi_dac) {
+ for (i = 0; i < ARRAY_SIZE(chip->spi_dac_reg); i++)
+ snd_ca0106_spi_write(chip, chip->spi_dac_reg[i]);
+ }
+
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+ return 0;
+}
+#endif
+
// PCI IDs
static struct pci_device_id snd_ca0106_ids[] = {
{ 0x1102, 0x0007, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Audigy LS or Live 24bit */
@@ -1717,6 +1829,10 @@ static struct pci_driver driver = {
.id_table = snd_ca0106_ids,
.probe = snd_ca0106_probe,
.remove = __devexit_p(snd_ca0106_remove),
+#ifdef CONFIG_PM
+ .suspend = snd_ca0106_suspend,
+ .resume = snd_ca0106_resume,
+#endif
};
// initialization of the module
diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c
index 3025ed1b6e1..ad2888705d2 100644
--- a/sound/pci/ca0106/ca0106_mixer.c
+++ b/sound/pci/ca0106/ca0106_mixer.c
@@ -75,6 +75,84 @@
#include "ca0106.h"
+static void ca0106_spdif_enable(struct snd_ca0106 *emu)
+{
+ unsigned int val;
+
+ if (emu->spdif_enable) {
+ /* Digital */
+ snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf);
+ snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x0b000000);
+ val = snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) & ~0x1000;
+ snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0, val);
+ val = inl(emu->port + GPIO) & ~0x101;
+ outl(val, emu->port + GPIO);
+
+ } else {
+ /* Analog */
+ snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf);
+ snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x000f0000);
+ val = snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) | 0x1000;
+ snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0, val);
+ val = inl(emu->port + GPIO) | 0x101;
+ outl(val, emu->port + GPIO);
+ }
+}
+
+static void ca0106_set_capture_source(struct snd_ca0106 *emu)
+{
+ unsigned int val = emu->capture_source;
+ unsigned int source, mask;
+ source = (val << 28) | (val << 24) | (val << 20) | (val << 16);
+ mask = snd_ca0106_ptr_read(emu, CAPTURE_SOURCE, 0) & 0xffff;
+ snd_ca0106_ptr_write(emu, CAPTURE_SOURCE, 0, source | mask);
+}
+
+static void ca0106_set_i2c_capture_source(struct snd_ca0106 *emu,
+ unsigned int val, int force)
+{
+ unsigned int ngain, ogain;
+ u32 source;
+
+ snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */
+ ngain = emu->i2c_capture_volume[val][0]; /* Left */
+ ogain = emu->i2c_capture_volume[emu->i2c_capture_source][0]; /* Left */
+ if (force || ngain != ogain)
+ snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCL, ngain & 0xff);
+ ngain = emu->i2c_capture_volume[val][1]; /* Right */
+ ogain = emu->i2c_capture_volume[emu->i2c_capture_source][1]; /* Right */
+ if (force || ngain != ogain)
+ snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCR, ngain & 0xff);
+ source = 1 << val;
+ snd_ca0106_i2c_write(emu, ADC_MUX, source); /* Set source */
+ emu->i2c_capture_source = val;
+}
+
+static void ca0106_set_capture_mic_line_in(struct snd_ca0106 *emu)
+{
+ u32 tmp;
+
+ if (emu->capture_mic_line_in) {
+ /* snd_ca0106_i2c_write(emu, ADC_MUX, 0); */ /* Mute input */
+ tmp = inl(emu->port+GPIO) & ~0x400;
+ tmp = tmp | 0x400;
+ outl(tmp, emu->port+GPIO);
+ /* snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_MIC); */
+ } else {
+ /* snd_ca0106_i2c_write(emu, ADC_MUX, 0); */ /* Mute input */
+ tmp = inl(emu->port+GPIO) & ~0x400;
+ outl(tmp, emu->port+GPIO);
+ /* snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_LINEIN); */
+ }
+}
+
+static void ca0106_set_spdif_bits(struct snd_ca0106 *emu, int idx)
+{
+ snd_ca0106_ptr_write(emu, SPCS0 + idx, 0, emu->spdif_str_bits[idx]);
+}
+
+/*
+ */
static const DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale1, -5175, 25, 1);
static const DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale2, -10350, 50, 1);
@@ -95,30 +173,12 @@ static int snd_ca0106_shared_spdif_put(struct snd_kcontrol *kcontrol,
struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
unsigned int val;
int change = 0;
- u32 mask;
val = !!ucontrol->value.integer.value[0];
change = (emu->spdif_enable != val);
if (change) {
emu->spdif_enable = val;
- if (val) {
- /* Digital */
- snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf);
- snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x0b000000);
- snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0,
- snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) & ~0x1000);
- mask = inl(emu->port + GPIO) & ~0x101;
- outl(mask, emu->port + GPIO);
-
- } else {
- /* Analog */
- snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf);
- snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x000f0000);
- snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0,
- snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) | 0x1000);
- mask = inl(emu->port + GPIO) | 0x101;
- outl(mask, emu->port + GPIO);
- }
+ ca0106_spdif_enable(emu);
}
return change;
}
@@ -154,8 +214,6 @@ static int snd_ca0106_capture_source_put(struct snd_kcontrol *kcontrol,
struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
unsigned int val;
int change = 0;
- u32 mask;
- u32 source;
val = ucontrol->value.enumerated.item[0] ;
if (val >= 6)
@@ -163,9 +221,7 @@ static int snd_ca0106_capture_source_put(struct snd_kcontrol *kcontrol,
change = (emu->capture_source != val);
if (change) {
emu->capture_source = val;
- source = (val << 28) | (val << 24) | (val << 20) | (val << 16);
- mask = snd_ca0106_ptr_read(emu, CAPTURE_SOURCE, 0) & 0xffff;
- snd_ca0106_ptr_write(emu, CAPTURE_SOURCE, 0, source | mask);
+ ca0106_set_capture_source(emu);
}
return change;
}
@@ -200,9 +256,7 @@ static int snd_ca0106_i2c_capture_source_put(struct snd_kcontrol *kcontrol,
{
struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
unsigned int source_id;
- unsigned int ngain, ogain;
int change = 0;
- u32 source;
/* If the capture source has changed,
* update the capture volume from the cached value
* for the particular source.
@@ -212,18 +266,7 @@ static int snd_ca0106_i2c_capture_source_put(struct snd_kcontrol *kcontrol,
return -EINVAL;
change = (emu->i2c_capture_source != source_id);
if (change) {
- snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */
- ngain = emu->i2c_capture_volume[source_id][0]; /* Left */
- ogain = emu->i2c_capture_volume[emu->i2c_capture_source][0]; /* Left */
- if (ngain != ogain)
- snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff));
- ngain = emu->i2c_capture_volume[source_id][1]; /* Left */
- ogain = emu->i2c_capture_volume[emu->i2c_capture_source][1]; /* Left */
- if (ngain != ogain)
- snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
- source = 1 << source_id;
- snd_ca0106_i2c_write(emu, ADC_MUX, source); /* Set source */
- emu->i2c_capture_source = source_id;
+ ca0106_set_i2c_capture_source(emu, source_id, 0);
}
return change;
}
@@ -271,7 +314,6 @@ static int snd_ca0106_capture_mic_line_in_put(struct snd_kcontrol *kcontrol,
struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
unsigned int val;
int change = 0;
- u32 tmp;
val = ucontrol->value.enumerated.item[0] ;
if (val > 1)
@@ -279,18 +321,7 @@ static int snd_ca0106_capture_mic_line_in_put(struct snd_kcontrol *kcontrol,
change = (emu->capture_mic_line_in != val);
if (change) {
emu->capture_mic_line_in = val;
- if (val) {
- //snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */
- tmp = inl(emu->port+GPIO) & ~0x400;
- tmp = tmp | 0x400;
- outl(tmp, emu->port+GPIO);
- //snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_MIC);
- } else {
- //snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */
- tmp = inl(emu->port+GPIO) & ~0x400;
- outl(tmp, emu->port+GPIO);
- //snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_LINEIN);
- }
+ ca0106_set_capture_mic_line_in(emu);
}
return change;
}
@@ -322,16 +353,33 @@ static int snd_ca0106_spdif_info(struct snd_kcontrol *kcontrol,
return 0;
}
-static int snd_ca0106_spdif_get(struct snd_kcontrol *kcontrol,
+static void decode_spdif_bits(unsigned char *status, unsigned int bits)
+{
+ status[0] = (bits >> 0) & 0xff;
+ status[1] = (bits >> 8) & 0xff;
+ status[2] = (bits >> 16) & 0xff;
+ status[3] = (bits >> 24) & 0xff;
+}
+
+static int snd_ca0106_spdif_get_default(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
- ucontrol->value.iec958.status[0] = (emu->spdif_bits[idx] >> 0) & 0xff;
- ucontrol->value.iec958.status[1] = (emu->spdif_bits[idx] >> 8) & 0xff;
- ucontrol->value.iec958.status[2] = (emu->spdif_bits[idx] >> 16) & 0xff;
- ucontrol->value.iec958.status[3] = (emu->spdif_bits[idx] >> 24) & 0xff;
+ decode_spdif_bits(ucontrol->value.iec958.status,
+ emu->spdif_bits[idx]);
+ return 0;
+}
+
+static int snd_ca0106_spdif_get_stream(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
+ unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+
+ decode_spdif_bits(ucontrol->value.iec958.status,
+ emu->spdif_str_bits[idx]);
return 0;
}
@@ -345,24 +393,48 @@ static int snd_ca0106_spdif_get_mask(struct snd_kcontrol *kcontrol,
return 0;
}
-static int snd_ca0106_spdif_put(struct snd_kcontrol *kcontrol,
+static unsigned int encode_spdif_bits(unsigned char *status)
+{
+ return ((unsigned int)status[0] << 0) |
+ ((unsigned int)status[1] << 8) |
+ ((unsigned int)status[2] << 16) |
+ ((unsigned int)status[3] << 24);
+}
+
+static int snd_ca0106_spdif_put_default(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
- int change;
unsigned int val;
- val = (ucontrol->value.iec958.status[0] << 0) |
- (ucontrol->value.iec958.status[1] << 8) |
- (ucontrol->value.iec958.status[2] << 16) |
- (ucontrol->value.iec958.status[3] << 24);
- change = val != emu->spdif_bits[idx];
- if (change) {
- snd_ca0106_ptr_write(emu, SPCS0 + idx, 0, val);
+ val = encode_spdif_bits(ucontrol->value.iec958.status);
+ if (val != emu->spdif_bits[idx]) {
emu->spdif_bits[idx] = val;
+ /* FIXME: this isn't safe, but needed to keep the compatibility
+ * with older alsa-lib config
+ */
+ emu->spdif_str_bits[idx] = val;
+ ca0106_set_spdif_bits(emu, idx);
+ return 1;
}
- return change;
+ return 0;
+}
+
+static int snd_ca0106_spdif_put_stream(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
+ unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+ unsigned int val;
+
+ val = encode_spdif_bits(ucontrol->value.iec958.status);
+ if (val != emu->spdif_str_bits[idx]) {
+ emu->spdif_str_bits[idx] = val;
+ ca0106_set_spdif_bits(emu, idx);
+ return 1;
+ }
+ return 0;
}
static int snd_ca0106_volume_info(struct snd_kcontrol *kcontrol,
@@ -573,8 +645,16 @@ static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = {
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
.count = 4,
.info = snd_ca0106_spdif_info,
- .get = snd_ca0106_spdif_get,
- .put = snd_ca0106_spdif_put
+ .get = snd_ca0106_spdif_get_default,
+ .put = snd_ca0106_spdif_put_default
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM),
+ .count = 4,
+ .info = snd_ca0106_spdif_info,
+ .get = snd_ca0106_spdif_get_stream,
+ .put = snd_ca0106_spdif_put_stream
},
};
@@ -773,3 +853,50 @@ int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu)
return 0;
}
+#ifdef CONFIG_PM
+struct ca0106_vol_tbl {
+ unsigned int channel_id;
+ unsigned int reg;
+};
+
+static struct ca0106_vol_tbl saved_volumes[NUM_SAVED_VOLUMES] = {
+ { CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME2 },
+ { CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME2 },
+ { CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME2 },
+ { CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME2 },
+ { CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME1 },
+ { CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME1 },
+ { CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME1 },
+ { CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME1 },
+ { 1, CAPTURE_CONTROL },
+};
+
+void snd_ca0106_mixer_suspend(struct snd_ca0106 *chip)
+{
+ int i;
+
+ /* save volumes */
+ for (i = 0; i < NUM_SAVED_VOLUMES; i++)
+ chip->saved_vol[i] =
+ snd_ca0106_ptr_read(chip, saved_volumes[i].reg,
+ saved_volumes[i].channel_id);
+}
+
+void snd_ca0106_mixer_resume(struct snd_ca0106 *chip)
+{
+ int i;
+
+ for (i = 0; i < NUM_SAVED_VOLUMES; i++)
+ snd_ca0106_ptr_write(chip, saved_volumes[i].reg,
+ saved_volumes[i].channel_id,
+ chip->saved_vol[i]);
+
+ ca0106_spdif_enable(chip);
+ ca0106_set_capture_source(chip);
+ ca0106_set_i2c_capture_source(chip, chip->i2c_capture_source, 1);
+ for (i = 0; i < 4; i++)
+ ca0106_set_spdif_bits(chip, i);
+ if (chip->details->i2c_adc)
+ ca0106_set_capture_mic_line_in(chip);
+}
+#endif /* CONFIG_PM */
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
index fb6dc398025..8ab07aa6365 100644
--- a/sound/pci/cs46xx/cs46xx_lib.c
+++ b/sound/pci/cs46xx/cs46xx_lib.c
@@ -3640,7 +3640,10 @@ int snd_cs46xx_resume(struct pci_dev *pci)
{
struct snd_card *card = pci_get_drvdata(pci);
struct snd_cs46xx *chip = card->private_data;
- int i, amp_saved;
+ int amp_saved;
+#ifdef CONFIG_SND_CS46XX_NEW_DSP
+ int i;
+#endif
pci_set_power_state(pci, PCI_D0);
pci_restore_state(pci);
diff --git a/sound/pci/cs5535audio/Makefile b/sound/pci/cs5535audio/Makefile
index bb3d57e6a3c..fda7a94c992 100644
--- a/sound/pci/cs5535audio/Makefile
+++ b/sound/pci/cs5535audio/Makefile
@@ -4,6 +4,9 @@
snd-cs5535audio-y := cs5535audio.o cs5535audio_pcm.o
snd-cs5535audio-$(CONFIG_PM) += cs5535audio_pm.o
+ifdef CONFIG_MGEODE_LX
+snd-cs5535audio-$(CONFIG_OLPC) += cs5535audio_olpc.o
+endif
# Toplevel Module Dependency
obj-$(CONFIG_SND_CS5535AUDIO) += snd-cs5535audio.o
diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c
index 1d8b1605253..826e6dec2e9 100644
--- a/sound/pci/cs5535audio/cs5535audio.c
+++ b/sound/pci/cs5535audio/cs5535audio.c
@@ -159,10 +159,14 @@ static int __devinit snd_cs5535audio_mixer(struct cs5535audio *cs5535au)
return err;
memset(&ac97, 0, sizeof(ac97));
- ac97.scaps = AC97_SCAP_AUDIO|AC97_SCAP_SKIP_MODEM;
+ ac97.scaps = AC97_SCAP_AUDIO | AC97_SCAP_SKIP_MODEM
+ | AC97_SCAP_POWER_SAVE;
ac97.private_data = cs5535au;
ac97.pci = cs5535au->pci;
+ /* set any OLPC-specific scaps */
+ olpc_prequirks(card, &ac97);
+
if ((err = snd_ac97_mixer(pbus, &ac97, &cs5535au->ac97)) < 0) {
snd_printk(KERN_ERR "mixer failed\n");
return err;
@@ -170,6 +174,12 @@ static int __devinit snd_cs5535audio_mixer(struct cs5535audio *cs5535au)
snd_ac97_tune_hardware(cs5535au->ac97, ac97_quirks, ac97_quirk);
+ err = olpc_quirks(card, cs5535au->ac97);
+ if (err < 0) {
+ snd_printk(KERN_ERR "olpc quirks failed\n");
+ return err;
+ }
+
return 0;
}
diff --git a/sound/pci/cs5535audio/cs5535audio.h b/sound/pci/cs5535audio/cs5535audio.h
index 66bae766419..7a298ac662e 100644
--- a/sound/pci/cs5535audio/cs5535audio.h
+++ b/sound/pci/cs5535audio/cs5535audio.h
@@ -78,6 +78,7 @@ struct cs5535audio_dma {
unsigned int buf_addr, buf_bytes;
unsigned int period_bytes, periods;
u32 saved_prd;
+ int pcm_open_flag;
};
struct cs5535audio {
@@ -93,8 +94,46 @@ struct cs5535audio {
struct cs5535audio_dma dmas[NUM_CS5535AUDIO_DMAS];
};
+#ifdef CONFIG_PM
int snd_cs5535audio_suspend(struct pci_dev *pci, pm_message_t state);
int snd_cs5535audio_resume(struct pci_dev *pci);
+#endif
+
+#if defined(CONFIG_OLPC) && defined(CONFIG_MGEODE_LX)
+void __devinit olpc_prequirks(struct snd_card *card,
+ struct snd_ac97_template *ac97);
+int __devinit olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97);
+void olpc_analog_input(struct snd_ac97 *ac97, int on);
+void olpc_mic_bias(struct snd_ac97 *ac97, int on);
+
+static inline void olpc_capture_open(struct snd_ac97 *ac97)
+{
+ /* default to Analog Input off */
+ olpc_analog_input(ac97, 0);
+ /* enable MIC Bias for recording */
+ olpc_mic_bias(ac97, 1);
+}
+
+static inline void olpc_capture_close(struct snd_ac97 *ac97)
+{
+ /* disable Analog Input */
+ olpc_analog_input(ac97, 0);
+ /* disable the MIC Bias (so the recording LED turns off) */
+ olpc_mic_bias(ac97, 0);
+}
+#else
+static inline void olpc_prequirks(struct snd_card *card,
+ struct snd_ac97_template *ac97) { }
+static inline int olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97)
+{
+ return 0;
+}
+static inline void olpc_analog_input(struct snd_ac97 *ac97, int on) { }
+static inline void olpc_mic_bias(struct snd_ac97 *ac97, int on) { }
+static inline void olpc_capture_open(struct snd_ac97 *ac97) { }
+static inline void olpc_capture_close(struct snd_ac97 *ac97) { }
+#endif
+
int __devinit snd_cs5535audio_pcm(struct cs5535audio *cs5535audio);
#endif /* __SOUND_CS5535AUDIO_H */
diff --git a/sound/pci/cs5535audio/cs5535audio_olpc.c b/sound/pci/cs5535audio/cs5535audio_olpc.c
new file mode 100644
index 00000000000..5c6814335cd
--- /dev/null
+++ b/sound/pci/cs5535audio/cs5535audio_olpc.c
@@ -0,0 +1,179 @@
+/*
+ * OLPC XO-1 additional sound features
+ *
+ * Copyright © 2006 Jaya Kumar <jayakumar.lkml@gmail.com>
+ * Copyright © 2007-2008 Andres Salomon <dilinger@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#include <sound/core.h>
+#include <sound/info.h>
+#include <sound/control.h>
+#include <sound/ac97_codec.h>
+
+#include <asm/olpc.h>
+#include "cs5535audio.h"
+
+/*
+ * OLPC has an additional feature on top of the regular AD1888 codec features.
+ * It has an Analog Input mode that is switched into (after disabling the
+ * High Pass Filter) via GPIO. It is supported on B2 and later models.
+ */
+void olpc_analog_input(struct snd_ac97 *ac97, int on)
+{
+ int err;
+
+ if (!machine_is_olpc())
+ return;
+
+ /* update the High Pass Filter (via AC97_AD_TEST2) */
+ err = snd_ac97_update_bits(ac97, AC97_AD_TEST2,
+ 1 << AC97_AD_HPFD_SHIFT, on << AC97_AD_HPFD_SHIFT);
+ if (err < 0) {
+ snd_printk(KERN_ERR "setting High Pass Filter - %d\n", err);
+ return;
+ }
+
+ /* set Analog Input through GPIO */
+ if (on)
+ geode_gpio_set(OLPC_GPIO_MIC_AC, GPIO_OUTPUT_VAL);
+ else
+ geode_gpio_clear(OLPC_GPIO_MIC_AC, GPIO_OUTPUT_VAL);
+}
+
+/*
+ * OLPC XO-1's V_REFOUT is a mic bias enable.
+ */
+void olpc_mic_bias(struct snd_ac97 *ac97, int on)
+{
+ int err;
+
+ if (!machine_is_olpc())
+ return;
+
+ on = on ? 0 : 1;
+ err = snd_ac97_update_bits(ac97, AC97_AD_MISC,
+ 1 << AC97_AD_VREFD_SHIFT, on << AC97_AD_VREFD_SHIFT);
+ if (err < 0)
+ snd_printk(KERN_ERR "setting MIC Bias - %d\n", err);
+}
+
+static int olpc_dc_info(struct snd_kcontrol *kctl,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 1;
+ return 0;
+}
+
+static int olpc_dc_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *v)
+{
+ v->value.integer.value[0] = geode_gpio_isset(OLPC_GPIO_MIC_AC,
+ GPIO_OUTPUT_VAL);
+ return 0;
+}
+
+static int olpc_dc_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *v)
+{
+ struct cs5535audio *cs5535au = snd_kcontrol_chip(kctl);
+
+ olpc_analog_input(cs5535au->ac97, v->value.integer.value[0]);
+ return 1;
+}
+
+static int olpc_mic_info(struct snd_kcontrol *kctl,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 1;
+ return 0;
+}
+
+static int olpc_mic_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *v)
+{
+ struct cs5535audio *cs5535au = snd_kcontrol_chip(kctl);
+ struct snd_ac97 *ac97 = cs5535au->ac97;
+ int i;
+
+ i = (snd_ac97_read(ac97, AC97_AD_MISC) >> AC97_AD_VREFD_SHIFT) & 0x1;
+ v->value.integer.value[0] = i ? 0 : 1;
+ return 0;
+}
+
+static int olpc_mic_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *v)
+{
+ struct cs5535audio *cs5535au = snd_kcontrol_chip(kctl);
+
+ olpc_mic_bias(cs5535au->ac97, v->value.integer.value[0]);
+ return 1;
+}
+
+static struct snd_kcontrol_new olpc_cs5535audio_ctls[] __devinitdata = {
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "DC Mode Enable",
+ .info = olpc_dc_info,
+ .get = olpc_dc_get,
+ .put = olpc_dc_put,
+ .private_value = 0,
+},
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "MIC Bias Enable",
+ .info = olpc_mic_info,
+ .get = olpc_mic_get,
+ .put = olpc_mic_put,
+ .private_value = 0,
+},
+};
+
+void __devinit olpc_prequirks(struct snd_card *card,
+ struct snd_ac97_template *ac97)
+{
+ if (!machine_is_olpc())
+ return;
+
+ /* invert EAPD if on an OLPC B3 or higher */
+ if (olpc_board_at_least(olpc_board_pre(0xb3)))
+ ac97->scaps |= AC97_SCAP_INV_EAPD;
+}
+
+int __devinit olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97)
+{
+ struct snd_ctl_elem_id elem;
+ int i, err;
+
+ if (!machine_is_olpc())
+ return 0;
+
+ /* drop the original AD1888 HPF control */
+ memset(&elem, 0, sizeof(elem));
+ elem.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+ strncpy(elem.name, "High Pass Filter Enable", sizeof(elem.name));
+ snd_ctl_remove_id(card, &elem);
+
+ /* drop the original V_REFOUT control */
+ memset(&elem, 0, sizeof(elem));
+ elem.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+ strncpy(elem.name, "V_REFOUT Enable", sizeof(elem.name));
+ snd_ctl_remove_id(card, &elem);
+
+ /* add the OLPC-specific controls */
+ for (i = 0; i < ARRAY_SIZE(olpc_cs5535audio_ctls); i++) {
+ err = snd_ctl_add(card, snd_ctl_new1(&olpc_cs5535audio_ctls[i],
+ ac97->private_data));
+ if (err < 0)
+ return err;
+ }
+
+ /* turn off the mic by default */
+ olpc_mic_bias(ac97, 0);
+ return 0;
+}
diff --git a/sound/pci/cs5535audio/cs5535audio_pcm.c b/sound/pci/cs5535audio/cs5535audio_pcm.c
index cdcda87116c..0f48a871f17 100644
--- a/sound/pci/cs5535audio/cs5535audio_pcm.c
+++ b/sound/pci/cs5535audio/cs5535audio_pcm.c
@@ -260,6 +260,9 @@ static int snd_cs5535audio_hw_params(struct snd_pcm_substream *substream,
err = cs5535audio_build_dma_packets(cs5535au, dma, substream,
params_periods(hw_params),
params_period_bytes(hw_params));
+ if (!err)
+ dma->pcm_open_flag = 1;
+
return err;
}
@@ -268,6 +271,15 @@ static int snd_cs5535audio_hw_free(struct snd_pcm_substream *substream)
struct cs5535audio *cs5535au = snd_pcm_substream_chip(substream);
struct cs5535audio_dma *dma = substream->runtime->private_data;
+ if (dma->pcm_open_flag) {
+ if (substream == cs5535au->playback_substream)
+ snd_ac97_update_power(cs5535au->ac97,
+ AC97_PCM_FRONT_DAC_RATE, 0);
+ else
+ snd_ac97_update_power(cs5535au->ac97,
+ AC97_PCM_LR_ADC_RATE, 0);
+ dma->pcm_open_flag = 0;
+ }
cs5535audio_clear_dma_packets(cs5535au, dma, substream);
return snd_pcm_lib_free_pages(substream);
}
@@ -351,11 +363,14 @@ static int snd_cs5535audio_capture_open(struct snd_pcm_substream *substream)
if ((err = snd_pcm_hw_constraint_integer(runtime,
SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
return err;
+ olpc_capture_open(cs5535au->ac97);
return 0;
}
static int snd_cs5535audio_capture_close(struct snd_pcm_substream *substream)
{
+ struct cs5535audio *cs5535au = snd_pcm_substream_chip(substream);
+ olpc_capture_close(cs5535au->ac97);
return 0;
}
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
index de5ee8f097f..7958006a1d6 100644
--- a/sound/pci/emu10k1/emu10k1_main.c
+++ b/sound/pci/emu10k1/emu10k1_main.c
@@ -69,7 +69,7 @@ MODULE_FIRMWARE(EMU1010_NOTEBOOK_FILENAME);
* EMU10K1 init / done
*************************************************************************/
-void snd_emu10k1_voice_init(struct snd_emu10k1 * emu, int ch)
+void snd_emu10k1_voice_init(struct snd_emu10k1 *emu, int ch)
{
snd_emu10k1_ptr_write(emu, DCYSUSV, ch, 0);
snd_emu10k1_ptr_write(emu, IP, ch, 0);
@@ -151,9 +151,9 @@ static unsigned int i2c_adc_init[][2] = {
{ 0x12, 0x32 }, /* ALC Control 3 */
{ 0x13, 0x00 }, /* Noise gate control */
{ 0x14, 0xa6 }, /* Limiter control */
- { 0x15, ADC_MUX_2 }, /* ADC Mixer control. Mic for Audigy 2 ZS Notebook */
+ { 0x15, ADC_MUX_2 }, /* ADC Mixer control. Mic for A2ZS Notebook */
};
-
+
static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
{
unsigned int silent_page;
@@ -161,8 +161,8 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
u32 tmp;
/* disable audio and lock cache */
- outl(HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | HCFG_MUTEBUTTONENABLE,
- emu->port + HCFG);
+ outl(HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK |
+ HCFG_MUTEBUTTONENABLE, emu->port + HCFG);
/* reset recording buffers */
snd_emu10k1_ptr_write(emu, MICBS, 0, ADCBS_BUFSIZE_NONE);
@@ -179,7 +179,7 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
snd_emu10k1_ptr_write(emu, SOLEL, 0, 0);
snd_emu10k1_ptr_write(emu, SOLEH, 0, 0);
- if (emu->audigy){
+ if (emu->audigy) {
/* set SPDIF bypass mode */
snd_emu10k1_ptr_write(emu, SPBYPASS, 0, SPBYPASS_FORMAT);
/* enable rear left + rear right AC97 slots */
@@ -197,12 +197,12 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
if (emu->card_capabilities->ca0151_chip) { /* audigy2 */
/* Hacks for Alice3 to work independent of haP16V driver */
- //Setup SRCMulti_I2S SamplingRate
+ /* Setup SRCMulti_I2S SamplingRate */
tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
tmp &= 0xfffff1ff;
tmp |= (0x2<<9);
snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, 0, tmp);
-
+
/* Setup SRCSel (Enable Spdif,I2S SRCMulti) */
snd_emu10k1_ptr20_write(emu, SRCSel, 0, 0x14);
/* Setup SRCMulti Input Audio Enable */
@@ -217,7 +217,7 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
if (emu->card_capabilities->ca0108_chip) { /* audigy2 Value */
/* Hacks for Alice3 to work independent of haP16V driver */
snd_printk(KERN_INFO "Audigy2 value: Special config.\n");
- //Setup SRCMulti_I2S SamplingRate
+ /* Setup SRCMulti_I2S SamplingRate */
tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
tmp &= 0xfffff1ff;
tmp |= (0x2<<9);
@@ -270,13 +270,13 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
size = ARRAY_SIZE(i2c_adc_init);
for (n = 0; n < size; n++)
snd_emu10k1_i2c_write(emu, i2c_adc_init[n][0], i2c_adc_init[n][1]);
- for (n=0; n < 4; n++) {
- emu->i2c_capture_volume[n][0]= 0xcf;
- emu->i2c_capture_volume[n][1]= 0xcf;
+ for (n = 0; n < 4; n++) {
+ emu->i2c_capture_volume[n][0] = 0xcf;
+ emu->i2c_capture_volume[n][1] = 0xcf;
}
}
-
+
snd_emu10k1_ptr_write(emu, PTB, 0, emu->ptb_pages.addr);
snd_emu10k1_ptr_write(emu, TCB, 0, 0); /* taken from original driver */
snd_emu10k1_ptr_write(emu, TCBS, 0, 4); /* taken from original driver */
@@ -313,7 +313,7 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
(emu->model == 0x21 && emu->revision < 6))
outl(HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE, emu->port + HCFG);
else
- // With on-chip joystick
+ /* With on-chip joystick */
outl(HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE | HCFG_JOYENABLE, emu->port + HCFG);
if (enable_ir) { /* enable IR for SB Live */
@@ -335,9 +335,9 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
outl(reg | HCFG_GPOUT1 | HCFG_GPOUT2, emu->port + HCFG);
udelay(100);
outl(reg, emu->port + HCFG);
- }
+ }
}
-
+
if (emu->card_capabilities->emu_model) {
; /* Disable all access to A_IOCFG for the emu1010 */
} else if (emu->card_capabilities->i2c_adc) {
@@ -364,7 +364,7 @@ static void snd_emu10k1_audio_enable(struct snd_emu10k1 *emu)
; /* Disable A_IOCFG for Audigy 2 ZS Notebook */
} else if (emu->audigy) {
outl(inl(emu->port + A_IOCFG) & ~0x44, emu->port + A_IOCFG);
-
+
if (emu->card_capabilities->ca0151_chip) { /* audigy2 */
/* Unmute Analog now. Set GPO6 to 1 for Apollo.
* This has to be done after init ALice3 I2SOut beyond 48KHz.
@@ -378,12 +378,12 @@ static void snd_emu10k1_audio_enable(struct snd_emu10k1 *emu)
outl(inl(emu->port + A_IOCFG) | 0x0080, emu->port + A_IOCFG);
}
}
-
+
#if 0
{
unsigned int tmp;
/* FIXME: the following routine disables LiveDrive-II !! */
- // TOSLink detection
+ /* TOSLink detection */
emu->tos_link = 0;
tmp = inl(emu->port + HCFG);
if (tmp & (HCFG_GPINPUT0 | HCFG_GPINPUT1)) {
@@ -400,7 +400,7 @@ static void snd_emu10k1_audio_enable(struct snd_emu10k1 *emu)
snd_emu10k1_intr_enable(emu, INTE_PCIERRORENABLE);
}
-int snd_emu10k1_done(struct snd_emu10k1 * emu)
+int snd_emu10k1_done(struct snd_emu10k1 *emu)
{
int ch;
@@ -495,7 +495,7 @@ int snd_emu10k1_done(struct snd_emu10k1 * emu)
#define EC_LAST_PROMFILE_ADDR 0x2f
-#define EC_SERIALNUM_ADDR 0x30 /* First word of serial number. The
+#define EC_SERIALNUM_ADDR 0x30 /* First word of serial number. The
* can be up to 30 characters in length
* and is stored as a NULL-terminated
* ASCII string. Any unused bytes must be
@@ -503,8 +503,8 @@ int snd_emu10k1_done(struct snd_emu10k1 * emu)
#define EC_CHECKSUM_ADDR 0x3f /* Location at which checksum is stored */
-/* Most of this stuff is pretty self-evident. According to the hardware
- * dudes, we need to leave the ADCCAL bit low in order to avoid a DC
+/* Most of this stuff is pretty self-evident. According to the hardware
+ * dudes, we need to leave the ADCCAL bit low in order to avoid a DC
* offset problem. Weird.
*/
#define EC_RAW_RUN_MODE (EC_DACMUTEN | EC_ADCRSTN | EC_TRIM_MUTEN | \
@@ -523,7 +523,7 @@ int snd_emu10k1_done(struct snd_emu10k1 * emu)
* register.
*/
-static void snd_emu10k1_ecard_write(struct snd_emu10k1 * emu, unsigned int value)
+static void snd_emu10k1_ecard_write(struct snd_emu10k1 *emu, unsigned int value)
{
unsigned short count;
unsigned int data;
@@ -561,7 +561,7 @@ static void snd_emu10k1_ecard_write(struct snd_emu10k1 * emu, unsigned int value
* channel.
*/
-static void snd_emu10k1_ecard_setadcgain(struct snd_emu10k1 * emu,
+static void snd_emu10k1_ecard_setadcgain(struct snd_emu10k1 *emu,
unsigned short gain)
{
unsigned int bit;
@@ -574,7 +574,7 @@ static void snd_emu10k1_ecard_setadcgain(struct snd_emu10k1 * emu,
for (bit = (1 << 15); bit; bit >>= 1) {
unsigned int value;
-
+
value = emu->ecard_ctrl & ~(EC_TRIM_CSN | EC_TRIM_SDATA);
if (gain & bit)
@@ -589,7 +589,7 @@ static void snd_emu10k1_ecard_setadcgain(struct snd_emu10k1 * emu,
snd_emu10k1_ecard_write(emu, emu->ecard_ctrl);
}
-static int snd_emu10k1_ecard_init(struct snd_emu10k1 * emu)
+static int snd_emu10k1_ecard_init(struct snd_emu10k1 *emu)
{
unsigned int hc_value;
@@ -598,7 +598,7 @@ static int snd_emu10k1_ecard_init(struct snd_emu10k1 * emu)
EC_SPDIF0_SELECT(EC_DEFAULT_SPDIF0_SEL) |
EC_SPDIF1_SELECT(EC_DEFAULT_SPDIF1_SEL);
- /* Step 0: Set the codec type in the hardware control register
+ /* Step 0: Set the codec type in the hardware control register
* and enable audio output */
hc_value = inl(emu->port + HCFG);
outl(hc_value | HCFG_AUDIOENABLE | HCFG_CODECFORMAT_I2S, emu->port + HCFG);
@@ -629,7 +629,7 @@ static int snd_emu10k1_ecard_init(struct snd_emu10k1 * emu)
return 0;
}
-static int snd_emu10k1_cardbus_init(struct snd_emu10k1 * emu)
+static int snd_emu10k1_cardbus_init(struct snd_emu10k1 *emu)
{
unsigned long special_port;
unsigned int value;
@@ -656,7 +656,7 @@ static int snd_emu10k1_cardbus_init(struct snd_emu10k1 * emu)
return 0;
}
-static int snd_emu1010_load_firmware(struct snd_emu10k1 * emu, const char * filename)
+static int snd_emu1010_load_firmware(struct snd_emu10k1 *emu, const char *filename)
{
int err;
int n, i;
@@ -666,11 +666,12 @@ static int snd_emu1010_load_firmware(struct snd_emu10k1 * emu, const char * file
unsigned long flags;
const struct firmware *fw_entry;
- if ((err = request_firmware(&fw_entry, filename, &emu->pci->dev)) != 0) {
- snd_printk(KERN_ERR "firmware: %s not found. Err=%d\n",filename, err);
+ err = request_firmware(&fw_entry, filename, &emu->pci->dev);
+ if (err != 0) {
+ snd_printk(KERN_ERR "firmware: %s not found. Err = %d\n", filename, err);
return err;
}
- snd_printk(KERN_INFO "firmware size=0x%zx\n", fw_entry->size);
+ snd_printk(KERN_INFO "firmware size = 0x%zx\n", fw_entry->size);
/* The FPGA is a Xilinx Spartan IIE XC2S50E */
/* GPIO7 -> FPGA PGMN
@@ -685,13 +686,13 @@ static int snd_emu1010_load_firmware(struct snd_emu10k1 * emu, const char * file
outl(0x80, emu->port + A_IOCFG); /* Leave bit 7 set during netlist setup. */
write_post = inl(emu->port + A_IOCFG);
udelay(100); /* Allow FPGA memory to clean */
- for(n = 0; n < fw_entry->size; n++) {
- value=fw_entry->data[n];
- for(i = 0; i < 8; i++) {
+ for (n = 0; n < fw_entry->size; n++) {
+ value = fw_entry->data[n];
+ for (i = 0; i < 8; i++) {
reg = 0x80;
if (value & 0x1)
reg = reg | 0x20;
- value = value >> 1;
+ value = value >> 1;
outl(reg, emu->port + A_IOCFG);
write_post = inl(emu->port + A_IOCFG);
outl(reg | 0x40, emu->port + A_IOCFG);
@@ -703,14 +704,14 @@ static int snd_emu1010_load_firmware(struct snd_emu10k1 * emu, const char * file
write_post = inl(emu->port + A_IOCFG);
spin_unlock_irqrestore(&emu->emu_lock, flags);
- release_firmware(fw_entry);
+ release_firmware(fw_entry);
return 0;
}
static int emu1010_firmware_thread(void *data)
{
- struct snd_emu10k1 * emu = data;
- int tmp,tmp2;
+ struct snd_emu10k1 *emu = data;
+ int tmp, tmp2;
int reg;
int err;
@@ -719,50 +720,50 @@ static int emu1010_firmware_thread(void *data)
msleep_interruptible(1000);
if (kthread_should_stop())
break;
- snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &tmp ); /* IRQ Status */
- snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg ); /* OPTIONS: Which cards are attached to the EMU */
+ snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &tmp); /* IRQ Status */
+ snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg); /* OPTIONS: Which cards are attached to the EMU */
if (reg & EMU_HANA_OPTION_DOCK_OFFLINE) {
/* Audio Dock attached */
/* Return to Audio Dock programming mode */
snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware\n");
- snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, EMU_HANA_FPGA_CONFIG_AUDIODOCK );
+ snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, EMU_HANA_FPGA_CONFIG_AUDIODOCK);
if (emu->card_capabilities->emu_model ==
EMU_MODEL_EMU1010) {
- if ((err = snd_emu1010_load_firmware(emu, DOCK_FILENAME)) != 0) {
+ err = snd_emu1010_load_firmware(emu, DOCK_FILENAME);
+ if (err != 0)
continue;
- }
} else if (emu->card_capabilities->emu_model ==
EMU_MODEL_EMU1010B) {
- if ((err = snd_emu1010_load_firmware(emu, MICRO_DOCK_FILENAME)) != 0) {
+ err = snd_emu1010_load_firmware(emu, MICRO_DOCK_FILENAME);
+ if (err != 0)
continue;
- }
} else if (emu->card_capabilities->emu_model ==
EMU_MODEL_EMU1616) {
- if ((err = snd_emu1010_load_firmware(emu, MICRO_DOCK_FILENAME)) != 0) {
+ err = snd_emu1010_load_firmware(emu, MICRO_DOCK_FILENAME);
+ if (err != 0)
continue;
- }
}
- snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0 );
- snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &reg );
- snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_IRQ_STATUS=0x%x\n",reg);
+ snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0);
+ snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &reg);
+ snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_IRQ_STATUS = 0x%x\n", reg);
/* ID, should read & 0x7f = 0x55 when FPGA programmed. */
- snd_emu1010_fpga_read(emu, EMU_HANA_ID, &reg );
- snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_ID=0x%x\n",reg);
+ snd_emu1010_fpga_read(emu, EMU_HANA_ID, &reg);
+ snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_ID = 0x%x\n", reg);
if ((reg & 0x1f) != 0x15) {
/* FPGA failed to be programmed */
- snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware file failed, reg=0x%x\n", reg);
+ snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware file failed, reg = 0x%x\n", reg);
continue;
}
snd_printk(KERN_INFO "emu1010: Audio Dock Firmware loaded\n");
- snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp );
- snd_emu1010_fpga_read(emu, EMU_DOCK_MINOR_REV, &tmp2 );
- snd_printk("Audio Dock ver:%d.%d\n",tmp ,tmp2);
+ snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp);
+ snd_emu1010_fpga_read(emu, EMU_DOCK_MINOR_REV, &tmp2);
+ snd_printk("Audio Dock ver:%d.%d\n", tmp, tmp2);
/* Sync clocking between 1010 and Dock */
/* Allow DLL to settle */
msleep(10);
/* Unmute all. Default is muted after a firmware load */
- snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE );
+ snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE);
}
}
snd_printk(KERN_INFO "emu1010: firmware thread stopping\n");
@@ -800,10 +801,10 @@ static int emu1010_firmware_thread(void *data)
* 16 x 16-bit playback - snd_emu10k1_fx8010_playback_ops
* 16 x 32-bit capture - snd_emu10k1_capture_efx_ops
*/
-static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu)
+static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu)
{
unsigned int i;
- int tmp,tmp2;
+ int tmp, tmp2;
int reg;
int err;
const char *filename = NULL;
@@ -818,7 +819,7 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu)
* Lock Tank Memory Cache,
* Mute all codecs.
*/
- outl(0x0005a004, emu->port + HCFG);
+ outl(0x0005a004, emu->port + HCFG);
/* AC97 2.1, Any 16Meg of 4Gig address, Auto-Mute, EMU32 Slave,
* Mute all codecs.
*/
@@ -829,25 +830,25 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu)
outl(0x0005a000, emu->port + HCFG);
/* Disable 48Volt power to Audio Dock */
- snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0 );
+ snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0);
/* ID, should read & 0x7f = 0x55. (Bit 7 is the IRQ bit) */
- snd_emu1010_fpga_read(emu, EMU_HANA_ID, &reg );
- snd_printdd("reg1=0x%x\n",reg);
+ snd_emu1010_fpga_read(emu, EMU_HANA_ID, &reg);
+ snd_printdd("reg1 = 0x%x\n", reg);
if ((reg & 0x3f) == 0x15) {
/* FPGA netlist already present so clear it */
/* Return to programming mode */
- snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0x02 );
+ snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0x02);
}
- snd_emu1010_fpga_read(emu, EMU_HANA_ID, &reg );
- snd_printdd("reg2=0x%x\n",reg);
+ snd_emu1010_fpga_read(emu, EMU_HANA_ID, &reg);
+ snd_printdd("reg2 = 0x%x\n", reg);
if ((reg & 0x3f) == 0x15) {
/* FPGA failed to return to programming mode */
snd_printk(KERN_INFO "emu1010: FPGA failed to return to programming mode\n");
return -ENODEV;
}
- snd_printk(KERN_INFO "emu1010: EMU_HANA_ID=0x%x\n",reg);
+ snd_printk(KERN_INFO "emu1010: EMU_HANA_ID = 0x%x\n", reg);
switch (emu->card_capabilities->emu_model) {
case EMU_MODEL_EMU1010:
filename = HANA_FILENAME;
@@ -876,25 +877,25 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu)
}
/* ID, should read & 0x7f = 0x55 when FPGA programmed. */
- snd_emu1010_fpga_read(emu, EMU_HANA_ID, &reg );
+ snd_emu1010_fpga_read(emu, EMU_HANA_ID, &reg);
if ((reg & 0x3f) != 0x15) {
/* FPGA failed to be programmed */
- snd_printk(KERN_INFO "emu1010: Loading Hana Firmware file failed, reg=0x%x\n", reg);
+ snd_printk(KERN_INFO "emu1010: Loading Hana Firmware file failed, reg = 0x%x\n", reg);
return -ENODEV;
}
snd_printk(KERN_INFO "emu1010: Hana Firmware loaded\n");
- snd_emu1010_fpga_read(emu, EMU_HANA_MAJOR_REV, &tmp );
- snd_emu1010_fpga_read(emu, EMU_HANA_MINOR_REV, &tmp2 );
- snd_printk("Hana ver:%d.%d\n",tmp ,tmp2);
+ snd_emu1010_fpga_read(emu, EMU_HANA_MAJOR_REV, &tmp);
+ snd_emu1010_fpga_read(emu, EMU_HANA_MINOR_REV, &tmp2);
+ snd_printk("emu1010: Hana version: %d.%d\n", tmp, tmp2);
/* Enable 48Volt power to Audio Dock */
- snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, EMU_HANA_DOCK_PWR_ON );
+ snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, EMU_HANA_DOCK_PWR_ON);
- snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg );
- snd_printk(KERN_INFO "emu1010: Card options=0x%x\n",reg);
- snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg );
- snd_printk(KERN_INFO "emu1010: Card options=0x%x\n",reg);
- snd_emu1010_fpga_read(emu, EMU_HANA_OPTICAL_TYPE, &tmp );
+ snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg);
+ snd_printk(KERN_INFO "emu1010: Card options = 0x%x\n", reg);
+ snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg);
+ snd_printk(KERN_INFO "emu1010: Card options = 0x%x\n", reg);
+ snd_emu1010_fpga_read(emu, EMU_HANA_OPTICAL_TYPE, &tmp);
/* Optical -> ADAT I/O */
/* 0 : SPDIF
* 1 : ADAT
@@ -904,41 +905,42 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu)
tmp = 0;
tmp = (emu->emu1010.optical_in ? EMU_HANA_OPTICAL_IN_ADAT : 0) |
(emu->emu1010.optical_out ? EMU_HANA_OPTICAL_OUT_ADAT : 0);
- snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, tmp );
- snd_emu1010_fpga_read(emu, EMU_HANA_ADC_PADS, &tmp );
+ snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, tmp);
+ snd_emu1010_fpga_read(emu, EMU_HANA_ADC_PADS, &tmp);
/* Set no attenuation on Audio Dock pads. */
- snd_emu1010_fpga_write(emu, EMU_HANA_ADC_PADS, 0x00 );
+ snd_emu1010_fpga_write(emu, EMU_HANA_ADC_PADS, 0x00);
emu->emu1010.adc_pads = 0x00;
- snd_emu1010_fpga_read(emu, EMU_HANA_DOCK_MISC, &tmp );
+ snd_emu1010_fpga_read(emu, EMU_HANA_DOCK_MISC, &tmp);
/* Unmute Audio dock DACs, Headphone source DAC-4. */
- snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_MISC, 0x30 );
- snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, 0x12 );
- snd_emu1010_fpga_read(emu, EMU_HANA_DAC_PADS, &tmp );
+ snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_MISC, 0x30);
+ snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, 0x12);
+ snd_emu1010_fpga_read(emu, EMU_HANA_DAC_PADS, &tmp);
/* DAC PADs. */
- snd_emu1010_fpga_write(emu, EMU_HANA_DAC_PADS, 0x0f );
+ snd_emu1010_fpga_write(emu, EMU_HANA_DAC_PADS, 0x0f);
emu->emu1010.dac_pads = 0x0f;
- snd_emu1010_fpga_read(emu, EMU_HANA_DOCK_MISC, &tmp );
- snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_MISC, 0x30 );
- snd_emu1010_fpga_read(emu, EMU_HANA_SPDIF_MODE, &tmp );
+ snd_emu1010_fpga_read(emu, EMU_HANA_DOCK_MISC, &tmp);
+ snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_MISC, 0x30);
+ snd_emu1010_fpga_read(emu, EMU_HANA_SPDIF_MODE, &tmp);
/* SPDIF Format. Set Consumer mode, 24bit, copy enable */
- snd_emu1010_fpga_write(emu, EMU_HANA_SPDIF_MODE, 0x10 );
+ snd_emu1010_fpga_write(emu, EMU_HANA_SPDIF_MODE, 0x10);
/* MIDI routing */
- snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, 0x19 );
+ snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, 0x19);
/* Unknown. */
- snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, 0x0c );
- /* snd_emu1010_fpga_write(emu, 0x09, 0x0f ); // IRQ Enable: All on */
+ snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, 0x0c);
+ /* IRQ Enable: Alll on */
+ /* snd_emu1010_fpga_write(emu, 0x09, 0x0f ); */
/* IRQ Enable: All off */
- snd_emu1010_fpga_write(emu, EMU_HANA_IRQ_ENABLE, 0x00 );
+ snd_emu1010_fpga_write(emu, EMU_HANA_IRQ_ENABLE, 0x00);
- snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg );
- snd_printk(KERN_INFO "emu1010: Card options3=0x%x\n",reg);
+ snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg);
+ snd_printk(KERN_INFO "emu1010: Card options3 = 0x%x\n", reg);
/* Default WCLK set to 48kHz. */
- snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, 0x00 );
+ snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, 0x00);
/* Word Clock source, Internal 48kHz x1 */
- snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K );
- //snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_4X );
+ snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K);
+ /* snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_4X); */
/* Audio Dock LEDs. */
- snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, 0x12 );
+ snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, 0x12);
#if 0
/* For 96kHz */
@@ -992,7 +994,7 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu)
* Defaults only, users will set their own values anyways, let's
* just copy/paste.
*/
-
+
snd_emu1010_fpga_link_dst_src_write(emu,
EMU_DST_ALICE2_EMU32_8, EMU_SRC_DOCK_MIC_A1);
snd_emu1010_fpga_link_dst_src_write(emu,
@@ -1037,19 +1039,19 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu)
snd_emu1010_fpga_link_dst_src_write(emu,
EMU_DST_ALICE2_EMU32_F, EMU_SRC_HAMOA_ADC_LEFT2);
#endif
- for (i = 0;i < 0x20; i++ ) {
- /* AudioDock Elink <- Silence */
- snd_emu1010_fpga_link_dst_src_write(emu, 0x0100+i, EMU_SRC_SILENCE);
+ for (i = 0; i < 0x20; i++) {
+ /* AudioDock Elink <- Silence */
+ snd_emu1010_fpga_link_dst_src_write(emu, 0x0100 + i, EMU_SRC_SILENCE);
}
- for (i = 0;i < 4; i++) {
+ for (i = 0; i < 4; i++) {
/* Hana SPDIF Out <- Silence */
- snd_emu1010_fpga_link_dst_src_write(emu, 0x0200+i, EMU_SRC_SILENCE);
+ snd_emu1010_fpga_link_dst_src_write(emu, 0x0200 + i, EMU_SRC_SILENCE);
}
- for (i = 0;i < 7; i++) {
+ for (i = 0; i < 7; i++) {
/* Hamoa DAC <- Silence */
- snd_emu1010_fpga_link_dst_src_write(emu, 0x0300+i, EMU_SRC_SILENCE);
+ snd_emu1010_fpga_link_dst_src_write(emu, 0x0300 + i, EMU_SRC_SILENCE);
}
- for (i = 0;i < 7; i++) {
+ for (i = 0; i < 7; i++) {
/* Hana ADAT Out <- Silence */
snd_emu1010_fpga_link_dst_src_write(emu, EMU_DST_HANA_ADAT + i, EMU_SRC_SILENCE);
}
@@ -1065,30 +1067,30 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu)
EMU_DST_ALICE_I2S2_LEFT, EMU_SRC_DOCK_ADC3_LEFT1);
snd_emu1010_fpga_link_dst_src_write(emu,
EMU_DST_ALICE_I2S2_RIGHT, EMU_SRC_DOCK_ADC3_RIGHT1);
- snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, 0x01 ); // Unmute all
+ snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, 0x01); /* Unmute all */
+
+ snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &tmp);
- snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &tmp );
-
/* AC97 1.03, Any 32Meg of 2Gig address, Auto-Mute, EMU32 Slave,
* Lock Sound Memory Cache, Lock Tank Memory Cache,
* Mute all codecs.
*/
- outl(0x0000a000, emu->port + HCFG);
+ outl(0x0000a000, emu->port + HCFG);
/* AC97 1.03, Any 32Meg of 2Gig address, Auto-Mute, EMU32 Slave,
* Lock Sound Memory Cache, Lock Tank Memory Cache,
* Un-Mute all codecs.
*/
outl(0x0000a001, emu->port + HCFG);
-
+
/* Initial boot complete. Now patches */
- snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &tmp );
- snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, 0x19 ); /* MIDI Route */
- snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, 0x0c ); /* Unknown */
- snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, 0x19 ); /* MIDI Route */
- snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, 0x0c ); /* Unknown */
- snd_emu1010_fpga_read(emu, EMU_HANA_SPDIF_MODE, &tmp );
- snd_emu1010_fpga_write(emu, EMU_HANA_SPDIF_MODE, 0x10 ); /* SPDIF Format spdif (or 0x11 for aes/ebu) */
+ snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &tmp);
+ snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, 0x19); /* MIDI Route */
+ snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, 0x0c); /* Unknown */
+ snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, 0x19); /* MIDI Route */
+ snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, 0x0c); /* Unknown */
+ snd_emu1010_fpga_read(emu, EMU_HANA_SPDIF_MODE, &tmp);
+ snd_emu1010_fpga_write(emu, EMU_HANA_SPDIF_MODE, 0x10); /* SPDIF Format spdif (or 0x11 for aes/ebu) */
/* Start Micro/Audio Dock firmware loader thread */
if (!emu->emu1010.firmware_thread) {
@@ -1218,20 +1220,20 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu)
emu->emu1010.output_source[23] = 28;
}
/* TEMP: Select SPDIF in/out */
- //snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, 0x0); /* Output spdif */
+ /* snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, 0x0); */ /* Output spdif */
/* TEMP: Select 48kHz SPDIF out */
snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, 0x0); /* Mute all */
snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, 0x0); /* Default fallback clock 48kHz */
/* Word Clock source, Internal 48kHz x1 */
- snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K );
- //snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_4X );
+ snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K);
+ /* snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_4X); */
emu->emu1010.internal_clock = 1; /* 48000 */
- snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, 0x12);/* Set LEDs on Audio Dock */
+ snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, 0x12); /* Set LEDs on Audio Dock */
snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, 0x1); /* Unmute all */
- //snd_emu1010_fpga_write(emu, 0x7, 0x0); /* Mute all */
- //snd_emu1010_fpga_write(emu, 0x7, 0x1); /* Unmute all */
- //snd_emu1010_fpga_write(emu, 0xe, 0x12); /* Set LEDs on Audio Dock */
+ /* snd_emu1010_fpga_write(emu, 0x7, 0x0); */ /* Mute all */
+ /* snd_emu1010_fpga_write(emu, 0x7, 0x1); */ /* Unmute all */
+ /* snd_emu1010_fpga_write(emu, 0xe, 0x12); */ /* Set LEDs on Audio Dock */
return 0;
}
@@ -1247,13 +1249,13 @@ static void free_pm_buffer(struct snd_emu10k1 *emu);
static int snd_emu10k1_free(struct snd_emu10k1 *emu)
{
if (emu->port) { /* avoid access to already used hardware */
- snd_emu10k1_fx8010_tram_setup(emu, 0);
+ snd_emu10k1_fx8010_tram_setup(emu, 0);
snd_emu10k1_done(emu);
snd_emu10k1_free_efx(emu);
- }
+ }
if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1010) {
/* Disable 48Volt power to Audio Dock */
- snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0 );
+ snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0);
}
if (emu->emu1010.firmware_thread)
kthread_stop(emu->emu1010.firmware_thread);
@@ -1278,7 +1280,7 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu)
#endif
if (emu->port)
pci_release_regions(emu->pci);
- if (emu->card_capabilities->ca0151_chip) /* P16V */
+ if (emu->card_capabilities->ca0151_chip) /* P16V */
snd_p16v_free(emu);
pci_disable_device(emu->pci);
kfree(emu);
@@ -1292,21 +1294,6 @@ static int snd_emu10k1_dev_free(struct snd_device *device)
}
static struct snd_emu_chip_details emu_chip_details[] = {
- /* Audigy 2 Value AC3 out does not work yet. Need to find out how to turn off interpolators.*/
- /* Tested by James@superbug.co.uk 3rd July 2005 */
- /* DSP: CA0108-IAT
- * DAC: CS4382-KQ
- * ADC: Philips 1361T
- * AC97: STAC9750
- * CA0151: None
- */
- {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x10011102,
- .driver = "Audigy2", .name = "Audigy 2 Value [SB0400]",
- .id = "Audigy2",
- .emu10k2_chip = 1,
- .ca0108_chip = 1,
- .spk71 = 1,
- .ac97_chip = 1} ,
/* Audigy4 (Not PRO) SB0610 */
/* Tested by James@superbug.co.uk 4th April 2006 */
/* A_IOCFG bits
@@ -1346,20 +1333,37 @@ static struct snd_emu_chip_details emu_chip_details[] = {
* CA0151: None
*/
{.vendor = 0x1102, .device = 0x0008, .subsystem = 0x10211102,
- .driver = "Audigy2", .name = "Audigy 4 [SB0610]",
+ .driver = "Audigy2", .name = "SB Audigy 4 [SB0610]",
.id = "Audigy2",
.emu10k2_chip = 1,
.ca0108_chip = 1,
.spk71 = 1,
.adc_1361t = 1, /* 24 bit capture instead of 16bit */
.ac97_chip = 1} ,
+ /* Audigy 2 Value AC3 out does not work yet.
+ * Need to find out how to turn off interpolators.
+ */
+ /* Tested by James@superbug.co.uk 3rd July 2005 */
+ /* DSP: CA0108-IAT
+ * DAC: CS4382-KQ
+ * ADC: Philips 1361T
+ * AC97: STAC9750
+ * CA0151: None
+ */
+ {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x10011102,
+ .driver = "Audigy2", .name = "SB Audigy 2 Value [SB0400]",
+ .id = "Audigy2",
+ .emu10k2_chip = 1,
+ .ca0108_chip = 1,
+ .spk71 = 1,
+ .ac97_chip = 1} ,
/* Audigy 2 ZS Notebook Cardbus card.*/
/* Tested by James@superbug.co.uk 6th November 2006 */
/* Audio output 7.1/Headphones working.
* Digital output working. (AC3 not checked, only PCM)
* Audio Mic/Line inputs working.
* Digital input not tested.
- */
+ */
/* DSP: Tina2
* DAC: Wolfson WM8768/WM8568
* ADC: Wolfson WM8775
@@ -1386,7 +1390,7 @@ static struct snd_emu_chip_details emu_chip_details[] = {
*
*/
{.vendor = 0x1102, .device = 0x0008, .subsystem = 0x20011102,
- .driver = "Audigy2", .name = "Audigy 2 ZS Notebook [SB0530]",
+ .driver = "Audigy2", .name = "SB Audigy 2 ZS Notebook [SB0530]",
.id = "Audigy2",
.emu10k2_chip = 1,
.ca0108_chip = 1,
@@ -1396,7 +1400,7 @@ static struct snd_emu_chip_details emu_chip_details[] = {
.spk71 = 1} ,
/* Tested by James@superbug.co.uk 4th Nov 2007. */
{.vendor = 0x1102, .device = 0x0008, .subsystem = 0x42011102,
- .driver = "Audigy2", .name = "E-mu 1010 Notebook [MAEM8950]",
+ .driver = "Audigy2", .name = "E-mu 1010 Notebook [MAEM8950]",
.id = "EMU1010",
.emu10k2_chip = 1,
.ca0108_chip = 1,
@@ -1404,47 +1408,49 @@ static struct snd_emu_chip_details emu_chip_details[] = {
.spk71 = 1 ,
.emu_model = EMU_MODEL_EMU1616},
/* Tested by James@superbug.co.uk 4th Nov 2007. */
+ /* This is MAEM8960, 0202 is MAEM 8980 */
{.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40041102,
- .driver = "Audigy2", .name = "E-mu 1010b PCI [MAEM????]",
+ .driver = "Audigy2", .name = "E-mu 1010b PCI [MAEM8960]",
.id = "EMU1010",
.emu10k2_chip = 1,
.ca0108_chip = 1,
.spk71 = 1,
- .emu_model = EMU_MODEL_EMU1010B},
+ .emu_model = EMU_MODEL_EMU1010B}, /* EMU 1010 new revision */
/* Tested by James@superbug.co.uk 8th July 2005. */
+ /* This is MAEM8810, 0202 is MAEM8820 */
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x40011102,
- .driver = "Audigy2", .name = "E-mu 1010 [4001]",
+ .driver = "Audigy2", .name = "E-mu 1010 [MAEM8810]",
.id = "EMU1010",
.emu10k2_chip = 1,
.ca0102_chip = 1,
.spk71 = 1,
- .emu_model = EMU_MODEL_EMU1010}, /* Emu 1010 */
+ .emu_model = EMU_MODEL_EMU1010}, /* EMU 1010 old revision */
/* EMU0404b */
{.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40021102,
- .driver = "Audigy2", .name = "E-mu 0404b [4002]",
+ .driver = "Audigy2", .name = "E-mu 0404b PCI [MAEM8852]",
.id = "EMU0404",
.emu10k2_chip = 1,
.ca0108_chip = 1,
.spk71 = 1,
- .emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 */
+ .emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 new revision */
/* Tested by James@superbug.co.uk 20-3-2007. */
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x40021102,
- .driver = "Audigy2", .name = "E-mu 0404 [4002]",
+ .driver = "Audigy2", .name = "E-mu 0404 [MAEM8850]",
.id = "EMU0404",
.emu10k2_chip = 1,
.ca0102_chip = 1,
.spk71 = 1,
.emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 */
- /* Audigy4 (Not PRO) SB0610 */
- {.vendor = 0x1102, .device = 0x0008,
- .driver = "Audigy2", .name = "Audigy 2 Value [Unknown]",
+ /* Note that all E-mu cards require kernel 2.6 or newer. */
+ {.vendor = 0x1102, .device = 0x0008,
+ .driver = "Audigy2", .name = "SB Audigy 2 Value [Unknown]",
.id = "Audigy2",
.emu10k2_chip = 1,
.ca0108_chip = 1,
.ac97_chip = 1} ,
/* Tested by James@superbug.co.uk 3rd July 2005 */
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20071102,
- .driver = "Audigy2", .name = "Audigy 4 PRO [SB0380]",
+ .driver = "Audigy2", .name = "SB Audigy 4 PRO [SB0380]",
.id = "Audigy2",
.emu10k2_chip = 1,
.ca0102_chip = 1,
@@ -1457,7 +1463,7 @@ static struct snd_emu_chip_details emu_chip_details[] = {
* Just like 0x20021102
*/
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20061102,
- .driver = "Audigy2", .name = "Audigy 2 [SB0350b]",
+ .driver = "Audigy2", .name = "SB Audigy 2 [SB0350b]",
.id = "Audigy2",
.emu10k2_chip = 1,
.ca0102_chip = 1,
@@ -1467,7 +1473,7 @@ static struct snd_emu_chip_details emu_chip_details[] = {
.invert_shared_spdif = 1, /* digital/analog switch swapped */
.ac97_chip = 1} ,
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20021102,
- .driver = "Audigy2", .name = "Audigy 2 ZS [SB0350]",
+ .driver = "Audigy2", .name = "SB Audigy 2 ZS [SB0350]",
.id = "Audigy2",
.emu10k2_chip = 1,
.ca0102_chip = 1,
@@ -1477,7 +1483,7 @@ static struct snd_emu_chip_details emu_chip_details[] = {
.invert_shared_spdif = 1, /* digital/analog switch swapped */
.ac97_chip = 1} ,
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20011102,
- .driver = "Audigy2", .name = "Audigy 2 ZS [2001]",
+ .driver = "Audigy2", .name = "SB Audigy 2 ZS [SB0360]",
.id = "Audigy2",
.emu10k2_chip = 1,
.ca0102_chip = 1,
@@ -1495,7 +1501,7 @@ static struct snd_emu_chip_details emu_chip_details[] = {
* CA0151: Yes
*/
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10071102,
- .driver = "Audigy2", .name = "Audigy 2 [SB0240]",
+ .driver = "Audigy2", .name = "SB Audigy 2 [SB0240]",
.id = "Audigy2",
.emu10k2_chip = 1,
.ca0102_chip = 1,
@@ -1505,7 +1511,7 @@ static struct snd_emu_chip_details emu_chip_details[] = {
.adc_1361t = 1, /* 24 bit capture instead of 16bit */
.ac97_chip = 1} ,
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10051102,
- .driver = "Audigy2", .name = "Audigy 2 EX [1005]",
+ .driver = "Audigy2", .name = "SB Audigy 2 Platinum EX [SB0280]",
.id = "Audigy2",
.emu10k2_chip = 1,
.ca0102_chip = 1,
@@ -1515,7 +1521,7 @@ static struct snd_emu_chip_details emu_chip_details[] = {
/* Dell OEM/Creative Labs Audigy 2 ZS */
/* See ALSA bug#1365 */
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10031102,
- .driver = "Audigy2", .name = "Audigy 2 ZS [SB0353]",
+ .driver = "Audigy2", .name = "SB Audigy 2 ZS [SB0353]",
.id = "Audigy2",
.emu10k2_chip = 1,
.ca0102_chip = 1,
@@ -1524,7 +1530,7 @@ static struct snd_emu_chip_details emu_chip_details[] = {
.spdif_bug = 1,
.ac97_chip = 1} ,
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10021102,
- .driver = "Audigy2", .name = "Audigy 2 Platinum [SB0240P]",
+ .driver = "Audigy2", .name = "SB Audigy 2 Platinum [SB0240P]",
.id = "Audigy2",
.emu10k2_chip = 1,
.ca0102_chip = 1,
@@ -1535,7 +1541,7 @@ static struct snd_emu_chip_details emu_chip_details[] = {
.adc_1361t = 1, /* 24 bit capture instead of 16bit. Fixes ALSA bug#324 */
.ac97_chip = 1} ,
{.vendor = 0x1102, .device = 0x0004, .revision = 0x04,
- .driver = "Audigy2", .name = "Audigy 2 [Unknown]",
+ .driver = "Audigy2", .name = "SB Audigy 2 [Unknown]",
.id = "Audigy2",
.emu10k2_chip = 1,
.ca0102_chip = 1,
@@ -1543,78 +1549,79 @@ static struct snd_emu_chip_details emu_chip_details[] = {
.spdif_bug = 1,
.ac97_chip = 1} ,
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x00531102,
- .driver = "Audigy", .name = "Audigy 1 [SB0090]",
+ .driver = "Audigy", .name = "SB Audigy 1 [SB0092]",
.id = "Audigy",
.emu10k2_chip = 1,
.ca0102_chip = 1,
.ac97_chip = 1} ,
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x00521102,
- .driver = "Audigy", .name = "Audigy 1 ES [SB0160]",
+ .driver = "Audigy", .name = "SB Audigy 1 ES [SB0160]",
.id = "Audigy",
.emu10k2_chip = 1,
.ca0102_chip = 1,
.spdif_bug = 1,
.ac97_chip = 1} ,
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x00511102,
- .driver = "Audigy", .name = "Audigy 1 [SB0090]",
+ .driver = "Audigy", .name = "SB Audigy 1 [SB0090]",
.id = "Audigy",
.emu10k2_chip = 1,
.ca0102_chip = 1,
.ac97_chip = 1} ,
{.vendor = 0x1102, .device = 0x0004,
- .driver = "Audigy", .name = "Audigy 1 [Unknown]",
+ .driver = "Audigy", .name = "Audigy 1 [Unknown]",
.id = "Audigy",
.emu10k2_chip = 1,
.ca0102_chip = 1,
.ac97_chip = 1} ,
- {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x806B1102,
- .driver = "EMU10K1", .name = "SBLive! [SB0105]",
+ {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x100a1102,
+ .driver = "EMU10K1", .name = "SB Live! 5.1 [SB0220]",
+ .id = "Live",
+ .emu10k1_chip = 1,
+ .ac97_chip = 1,
+ .sblive51 = 1} ,
+ {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x806b1102,
+ .driver = "EMU10K1", .name = "SB Live! [SB0105]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
- {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x806A1102,
- .driver = "EMU10K1", .name = "SBLive! Value [SB0103]",
+ {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x806a1102,
+ .driver = "EMU10K1", .name = "SB Live! Value [SB0103]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80691102,
- .driver = "EMU10K1", .name = "SBLive! Value [SB0101]",
+ .driver = "EMU10K1", .name = "SB Live! Value [SB0101]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
/* Tested by ALSA bug#1680 26th December 2005 */
- /* note: It really has SB0220 written on the card. */
+ /* note: It really has SB0220 written on the card, */
+ /* but it's SB0228 according to kx.inf */
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80661102,
- .driver = "EMU10K1", .name = "SB Live 5.1 Dell OEM [SB0220]",
+ .driver = "EMU10K1", .name = "SB Live! 5.1 Dell OEM [SB0228]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
/* Tested by Thomas Zehetbauer 27th Aug 2005 */
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80651102,
- .driver = "EMU10K1", .name = "SB Live 5.1 [SB0220]",
- .id = "Live",
- .emu10k1_chip = 1,
- .ac97_chip = 1,
- .sblive51 = 1} ,
- {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x100a1102,
- .driver = "EMU10K1", .name = "SB Live 5.1 [SB0220]",
+ .driver = "EMU10K1", .name = "SB Live! 5.1 [SB0220]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80641102,
- .driver = "EMU10K1", .name = "SB Live 5.1",
+ .driver = "EMU10K1", .name = "SB Live! 5.1",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
/* Tested by alsa bugtrack user "hus" bug #1297 12th Aug 2005 */
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80611102,
- .driver = "EMU10K1", .name = "SBLive 5.1 [SB0060]",
+ .driver = "EMU10K1", .name = "SB Live! 5.1 [SB0060]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 2, /* ac97 is optional; both SBLive 5.1 and platinum
@@ -1622,78 +1629,78 @@ static struct snd_emu_chip_details emu_chip_details[] = {
*/
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80511102,
- .driver = "EMU10K1", .name = "SBLive! Value [CT4850]",
+ .driver = "EMU10K1", .name = "SB Live! Value [CT4850]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80401102,
- .driver = "EMU10K1", .name = "SBLive! Platinum [CT4760P]",
+ .driver = "EMU10K1", .name = "SB Live! Platinum [CT4760P]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80321102,
- .driver = "EMU10K1", .name = "SBLive! Value [CT4871]",
+ .driver = "EMU10K1", .name = "SB Live! Value [CT4871]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80311102,
- .driver = "EMU10K1", .name = "SBLive! Value [CT4831]",
+ .driver = "EMU10K1", .name = "SB Live! Value [CT4831]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80281102,
- .driver = "EMU10K1", .name = "SBLive! Value [CT4870]",
+ .driver = "EMU10K1", .name = "SB Live! Value [CT4870]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
/* Tested by James@superbug.co.uk 3rd July 2005 */
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80271102,
- .driver = "EMU10K1", .name = "SBLive! Value [CT4832]",
+ .driver = "EMU10K1", .name = "SB Live! Value [CT4832]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80261102,
- .driver = "EMU10K1", .name = "SBLive! Value [CT4830]",
+ .driver = "EMU10K1", .name = "SB Live! Value [CT4830]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80231102,
- .driver = "EMU10K1", .name = "SB PCI512 [CT4790]",
+ .driver = "EMU10K1", .name = "SB PCI512 [CT4790]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80221102,
- .driver = "EMU10K1", .name = "SBLive! Value [CT4780]",
+ .driver = "EMU10K1", .name = "SB Live! Value [CT4780]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x40011102,
- .driver = "EMU10K1", .name = "E-mu APS [4001]",
+ .driver = "EMU10K1", .name = "E-mu APS [PC545]",
.id = "APS",
.emu10k1_chip = 1,
.ecard = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x00211102,
- .driver = "EMU10K1", .name = "SBLive! [CT4620]",
+ .driver = "EMU10K1", .name = "SB Live! [CT4620]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x00201102,
- .driver = "EMU10K1", .name = "SBLive! Value [CT4670]",
+ .driver = "EMU10K1", .name = "SB Live! Value [CT4670]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002,
- .driver = "EMU10K1", .name = "SB Live [Unknown]",
+ .driver = "EMU10K1", .name = "SB Live! [Unknown]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
@@ -1702,13 +1709,13 @@ static struct snd_emu_chip_details emu_chip_details[] = {
};
int __devinit snd_emu10k1_create(struct snd_card *card,
- struct pci_dev * pci,
+ struct pci_dev *pci,
unsigned short extin_mask,
unsigned short extout_mask,
long max_cache_bytes,
int enable_ir,
uint subsystem,
- struct snd_emu10k1 ** remu)
+ struct snd_emu10k1 **remu)
{
struct snd_emu10k1 *emu;
int idx, err;
@@ -1718,11 +1725,12 @@ int __devinit snd_emu10k1_create(struct snd_card *card,
static struct snd_device_ops ops = {
.dev_free = snd_emu10k1_dev_free,
};
-
+
*remu = NULL;
/* enable PCI device */
- if ((err = pci_enable_device(pci)) < 0)
+ err = pci_enable_device(pci);
+ if (err < 0)
return err;
emu = kzalloc(sizeof(*emu), GFP_KERNEL);
@@ -1749,16 +1757,17 @@ int __devinit snd_emu10k1_create(struct snd_card *card,
emu->revision = pci->revision;
pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &emu->serial);
pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &emu->model);
- snd_printdd("vendor=0x%x, device=0x%x, subsystem_vendor_id=0x%x, subsystem_id=0x%x\n",pci->vendor, pci->device, emu->serial, emu->model);
+ snd_printdd("vendor = 0x%x, device = 0x%x, subsystem_vendor_id = 0x%x, subsystem_id = 0x%x\n", pci->vendor, pci->device, emu->serial, emu->model);
for (c = emu_chip_details; c->vendor; c++) {
if (c->vendor == pci->vendor && c->device == pci->device) {
if (subsystem) {
- if (c->subsystem && (c->subsystem == subsystem) ) {
+ if (c->subsystem && (c->subsystem == subsystem))
break;
- } else continue;
+ else
+ continue;
} else {
- if (c->subsystem && (c->subsystem != emu->serial) )
+ if (c->subsystem && (c->subsystem != emu->serial))
continue;
if (c->revision && c->revision != emu->revision)
continue;
@@ -1774,14 +1783,18 @@ int __devinit snd_emu10k1_create(struct snd_card *card,
}
emu->card_capabilities = c;
if (c->subsystem && !subsystem)
- snd_printdd("Sound card name=%s\n", c->name);
- else if (subsystem)
- snd_printdd("Sound card name=%s, vendor=0x%x, device=0x%x, subsystem=0x%x. Forced to subsytem=0x%x\n",
- c->name, pci->vendor, pci->device, emu->serial, c->subsystem);
- else
- snd_printdd("Sound card name=%s, vendor=0x%x, device=0x%x, subsystem=0x%x.\n",
- c->name, pci->vendor, pci->device, emu->serial);
-
+ snd_printdd("Sound card name = %s\n", c->name);
+ else if (subsystem)
+ snd_printdd("Sound card name = %s, "
+ "vendor = 0x%x, device = 0x%x, subsystem = 0x%x. "
+ "Forced to subsytem = 0x%x\n", c->name,
+ pci->vendor, pci->device, emu->serial, c->subsystem);
+ else
+ snd_printdd("Sound card name = %s, "
+ "vendor = 0x%x, device = 0x%x, subsystem = 0x%x.\n",
+ c->name, pci->vendor, pci->device,
+ emu->serial);
+
if (!*card->id && c->id) {
int i, n = 0;
strlcpy(card->id, c->id, sizeof(card->id));
@@ -1815,7 +1828,8 @@ int __devinit snd_emu10k1_create(struct snd_card *card,
else
emu->gpr_base = FXGPREGBASE;
- if ((err = pci_request_regions(pci, "EMU10K1")) < 0) {
+ err = pci_request_regions(pci, "EMU10K1");
+ if (err < 0) {
kfree(emu);
pci_disable_device(pci);
return err;
@@ -1862,21 +1876,25 @@ int __devinit snd_emu10k1_create(struct snd_card *card,
emu->enable_ir = enable_ir;
if (emu->card_capabilities->ca_cardbus_chip) {
- if ((err = snd_emu10k1_cardbus_init(emu)) < 0)
+ err = snd_emu10k1_cardbus_init(emu);
+ if (err < 0)
goto error;
}
if (emu->card_capabilities->ecard) {
- if ((err = snd_emu10k1_ecard_init(emu)) < 0)
+ err = snd_emu10k1_ecard_init(emu);
+ if (err < 0)
goto error;
} else if (emu->card_capabilities->emu_model) {
- if ((err = snd_emu10k1_emu1010_init(emu)) < 0) {
- snd_emu10k1_free(emu);
- return err;
- }
+ err = snd_emu10k1_emu1010_init(emu);
+ if (err < 0) {
+ snd_emu10k1_free(emu);
+ return err;
+ }
} else {
/* 5.1: Enable the additional AC97 Slots. If the emu10k1 version
does not support this, it shouldn't do any harm */
- snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_CNTR|AC97SLOT_LFE);
+ snd_emu10k1_ptr_write(emu, AC97SLOT, 0,
+ AC97SLOT_CNTR|AC97SLOT_LFE);
}
/* initialize TRAM setup */
@@ -1916,7 +1934,7 @@ int __devinit snd_emu10k1_create(struct snd_card *card,
snd_emu10k1_synth_alloc(emu, 4096);
if (emu->reserved_page)
emu->reserved_page->map_locked = 1;
-
+
/* Clear silent pages and set up pointers */
memset(emu->silent_page.area, 0, PAGE_SIZE);
silent_page = emu->silent_page.addr << 1;
@@ -1929,19 +1947,23 @@ int __devinit snd_emu10k1_create(struct snd_card *card,
emu->voices[idx].number = idx;
}
- if ((err = snd_emu10k1_init(emu, enable_ir, 0)) < 0)
+ err = snd_emu10k1_init(emu, enable_ir, 0);
+ if (err < 0)
goto error;
#ifdef CONFIG_PM
- if ((err = alloc_pm_buffer(emu)) < 0)
+ err = alloc_pm_buffer(emu);
+ if (err < 0)
goto error;
#endif
/* Initialize the effect engine */
- if ((err = snd_emu10k1_init_efx(emu)) < 0)
+ err = snd_emu10k1_init_efx(emu);
+ if (err < 0)
goto error;
snd_emu10k1_audio_enable(emu);
- if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, emu, &ops)) < 0)
+ err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, emu, &ops);
+ if (err < 0)
goto error;
#ifdef CONFIG_PROC_FS
@@ -1981,7 +2003,7 @@ static int __devinit alloc_pm_buffer(struct snd_emu10k1 *emu)
if (emu->audigy)
size += ARRAY_SIZE(saved_regs_audigy);
emu->saved_ptr = vmalloc(4 * NUM_G * size);
- if (! emu->saved_ptr)
+ if (!emu->saved_ptr)
return -ENOMEM;
if (snd_emu10k1_efx_alloc_pm_buffer(emu) < 0)
return -ENOMEM;
@@ -2026,7 +2048,7 @@ void snd_emu10k1_resume_init(struct snd_emu10k1 *emu)
if (emu->card_capabilities->ecard)
snd_emu10k1_ecard_init(emu);
else if (emu->card_capabilities->emu_model)
- snd_emu10k1_emu1010_init(emu);
+ snd_emu10k1_emu1010_init(emu);
else
snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_CNTR|AC97SLOT_LFE);
snd_emu10k1_init(emu, emu->enable_ir, 1);
diff --git a/sound/pci/emu10k1/emumixer.c b/sound/pci/emu10k1/emumixer.c
index f34bbfb705f..b0fb6c917c3 100644
--- a/sound/pci/emu10k1/emumixer.c
+++ b/sound/pci/emu10k1/emumixer.c
@@ -1639,6 +1639,45 @@ static struct snd_kcontrol_new snd_audigy_shared_spdif __devinitdata =
.put = snd_emu10k1_shared_spdif_put
};
+/* workaround for too low volume on Audigy due to 16bit/24bit conversion */
+
+#define snd_audigy_capture_boost_info snd_ctl_boolean_mono_info
+
+static int snd_audigy_capture_boost_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
+ unsigned int val;
+
+ /* FIXME: better to use a cached version */
+ val = snd_ac97_read(emu->ac97, AC97_REC_GAIN);
+ ucontrol->value.integer.value[0] = !!val;
+ return 0;
+}
+
+static int snd_audigy_capture_boost_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
+ unsigned int val;
+
+ if (ucontrol->value.integer.value[0])
+ val = 0x0f0f;
+ else
+ val = 0;
+ return snd_ac97_update(emu->ac97, AC97_REC_GAIN, val);
+}
+
+static struct snd_kcontrol_new snd_audigy_capture_boost __devinitdata =
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Analog Capture Boost",
+ .info = snd_audigy_capture_boost_info,
+ .get = snd_audigy_capture_boost_get,
+ .put = snd_audigy_capture_boost_put
+};
+
+
/*
*/
static void snd_emu10k1_mixer_free_ac97(struct snd_ac97 *ac97)
@@ -2087,5 +2126,12 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
}
}
+ if (emu->card_capabilities->ac97_chip && emu->audigy) {
+ err = snd_ctl_add(card, snd_ctl_new1(&snd_audigy_capture_boost,
+ emu));
+ if (err < 0)
+ return err;
+ }
+
return 0;
}
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
index 20ee7599600..e9c3794bbcb 100644
--- a/sound/pci/es1968.c
+++ b/sound/pci/es1968.c
@@ -1953,7 +1953,7 @@ static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id)
outw(inw(chip->io_port + 4) & 1, chip->io_port + 4);
if (event & ESM_HWVOL_IRQ)
- tasklet_hi_schedule(&chip->hwvol_tq); /* we'll do this later */
+ tasklet_schedule(&chip->hwvol_tq); /* we'll do this later */
/* else ack 'em all, i imagine */
outb(0xFF, chip->io_port + 0x1A);
diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig
new file mode 100644
index 00000000000..eb2a19b894a
--- /dev/null
+++ b/sound/pci/hda/Kconfig
@@ -0,0 +1,188 @@
+menuconfig SND_HDA_INTEL
+ tristate "Intel HD Audio"
+ select SND_PCM
+ select SND_VMASTER
+ select SND_JACK if INPUT=y || INPUT=SND
+ help
+ Say Y here to include support for Intel "High Definition
+ Audio" (Azalia) and its compatible devices.
+
+ This option enables the HD-audio controller. Don't forget
+ to choose the appropriate codec options below.
+
+ To compile this driver as a module, choose M here: the module
+ will be called snd-hda-intel.
+
+if SND_HDA_INTEL
+
+config SND_HDA_HWDEP
+ bool "Build hwdep interface for HD-audio driver"
+ select SND_HWDEP
+ help
+ Say Y here to build a hwdep interface for HD-audio driver.
+ This interface can be used for out-of-band communication
+ with codecs for debugging purposes.
+
+config SND_HDA_RECONFIG
+ bool "Allow dynamic codec reconfiguration (EXPERIMENTAL)"
+ depends on SND_HDA_HWDEP && EXPERIMENTAL
+ help
+ Say Y here to enable the HD-audio codec re-configuration feature.
+ This adds the sysfs interfaces to allow user to clear the whole
+ codec configuration, change the codec setup, add extra verbs,
+ and re-configure the codec dynamically.
+
+config SND_HDA_INPUT_BEEP
+ bool "Support digital beep via input layer"
+ depends on INPUT=y || INPUT=SND_HDA_INTEL
+ help
+ Say Y here to build a digital beep interface for HD-audio
+ driver. This interface is used to generate digital beeps.
+
+config SND_HDA_CODEC_REALTEK
+ bool "Build Realtek HD-audio codec support"
+ default y
+ help
+ Say Y here to include Realtek HD-audio codec support in
+ snd-hda-intel driver, such as ALC880.
+
+ When the HD-audio driver is built as a module, the codec
+ support code is also built as another module,
+ snd-hda-codec-realtek.
+ This module is automatically loaded at probing.
+
+config SND_HDA_CODEC_ANALOG
+ bool "Build Analog Device HD-audio codec support"
+ default y
+ help
+ Say Y here to include Analog Device HD-audio codec support in
+ snd-hda-intel driver, such as AD1986A.
+
+ When the HD-audio driver is built as a module, the codec
+ support code is also built as another module,
+ snd-hda-codec-analog.
+ This module is automatically loaded at probing.
+
+config SND_HDA_CODEC_SIGMATEL
+ bool "Build IDT/Sigmatel HD-audio codec support"
+ default y
+ help
+ Say Y here to include IDT (Sigmatel) HD-audio codec support in
+ snd-hda-intel driver, such as STAC9200.
+
+ When the HD-audio driver is built as a module, the codec
+ support code is also built as another module,
+ snd-hda-codec-idt.
+ This module is automatically loaded at probing.
+
+config SND_HDA_CODEC_VIA
+ bool "Build VIA HD-audio codec support"
+ default y
+ help
+ Say Y here to include VIA HD-audio codec support in
+ snd-hda-intel driver, such as VT1708.
+
+ When the HD-audio driver is built as a module, the codec
+ support code is also built as another module,
+ snd-hda-codec-via.
+ This module is automatically loaded at probing.
+
+config SND_HDA_CODEC_ATIHDMI
+ bool "Build ATI HDMI HD-audio codec support"
+ default y
+ help
+ Say Y here to include ATI HDMI HD-audio codec support in
+ snd-hda-intel driver, such as ATI RS600 HDMI.
+
+ When the HD-audio driver is built as a module, the codec
+ support code is also built as another module,
+ snd-hda-codec-atihdmi.
+ This module is automatically loaded at probing.
+
+config SND_HDA_CODEC_NVHDMI
+ bool "Build NVIDIA HDMI HD-audio codec support"
+ default y
+ help
+ Say Y here to include NVIDIA HDMI HD-audio codec support in
+ snd-hda-intel driver, such as NVIDIA MCP78 HDMI.
+
+ When the HD-audio driver is built as a module, the codec
+ support code is also built as another module,
+ snd-hda-codec-nvhdmi.
+ This module is automatically loaded at probing.
+
+config SND_HDA_CODEC_INTELHDMI
+ bool "Build INTEL HDMI HD-audio codec support"
+ default y
+ help
+ Say Y here to include INTEL HDMI HD-audio codec support in
+ snd-hda-intel driver, such as Eaglelake integrated HDMI.
+
+ When the HD-audio driver is built as a module, the codec
+ support code is also built as another module,
+ snd-hda-codec-intelhdmi.
+ This module is automatically loaded at probing.
+
+config SND_HDA_ELD
+ def_bool y
+ depends on SND_HDA_CODEC_INTELHDMI
+
+config SND_HDA_CODEC_CONEXANT
+ bool "Build Conexant HD-audio codec support"
+ default y
+ help
+ Say Y here to include Conexant HD-audio codec support in
+ snd-hda-intel driver, such as CX20549.
+
+ When the HD-audio driver is built as a module, the codec
+ support code is also built as another module,
+ snd-hda-codec-conexant.
+ This module is automatically loaded at probing.
+
+config SND_HDA_CODEC_CMEDIA
+ bool "Build C-Media HD-audio codec support"
+ default y
+ help
+ Say Y here to include C-Media HD-audio codec support in
+ snd-hda-intel driver, such as CMI9880.
+
+ When the HD-audio driver is built as a module, the codec
+ support code is also built as another module,
+ snd-hda-codec-cmedia.
+ This module is automatically loaded at probing.
+
+config SND_HDA_CODEC_SI3054
+ bool "Build Silicon Labs 3054 HD-modem codec support"
+ default y
+ help
+ Say Y here to include Silicon Labs 3054 HD-modem codec
+ (and compatibles) support in snd-hda-intel driver.
+
+ When the HD-audio driver is built as a module, the codec
+ support code is also built as another module,
+ snd-hda-codec-si3054.
+ This module is automatically loaded at probing.
+
+config SND_HDA_GENERIC
+ bool "Enable generic HD-audio codec parser"
+ default y
+ help
+ Say Y here to enable the generic HD-audio codec parser
+ in snd-hda-intel driver.
+
+config SND_HDA_POWER_SAVE
+ bool "Aggressive power-saving on HD-audio"
+ help
+ Say Y here to enable more aggressive power-saving mode on
+ HD-audio driver. The power-saving timeout can be configured
+ via power_save option or over sysfs on-the-fly.
+
+config SND_HDA_POWER_SAVE_DEFAULT
+ int "Default time-out for HD-audio power-save mode"
+ depends on SND_HDA_POWER_SAVE
+ default 0
+ help
+ The default time-out value in seconds for HD-audio automatic
+ power-save mode. 0 means to disable the power-save mode.
+
+endif
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile
index 1980c6d207e..50f9d096725 100644
--- a/sound/pci/hda/Makefile
+++ b/sound/pci/hda/Makefile
@@ -1,20 +1,59 @@
-snd-hda-intel-y := hda_intel.o
-# since snd-hda-intel is the only driver using hda-codec,
-# merge it into a single module although it was originally
-# designed to be individual modules
-snd-hda-intel-y += hda_codec.o
-snd-hda-intel-$(CONFIG_PROC_FS) += hda_proc.o
-snd-hda-intel-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o
-snd-hda-intel-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o
-snd-hda-intel-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o
-snd-hda-intel-$(CONFIG_SND_HDA_CODEC_REALTEK) += patch_realtek.o
-snd-hda-intel-$(CONFIG_SND_HDA_CODEC_CMEDIA) += patch_cmedia.o
-snd-hda-intel-$(CONFIG_SND_HDA_CODEC_ANALOG) += patch_analog.o
-snd-hda-intel-$(CONFIG_SND_HDA_CODEC_SIGMATEL) += patch_sigmatel.o
-snd-hda-intel-$(CONFIG_SND_HDA_CODEC_SI3054) += patch_si3054.o
-snd-hda-intel-$(CONFIG_SND_HDA_CODEC_ATIHDMI) += patch_atihdmi.o
-snd-hda-intel-$(CONFIG_SND_HDA_CODEC_CONEXANT) += patch_conexant.o
-snd-hda-intel-$(CONFIG_SND_HDA_CODEC_VIA) += patch_via.o
-snd-hda-intel-$(CONFIG_SND_HDA_CODEC_NVHDMI) += patch_nvhdmi.o
+snd-hda-intel-objs := hda_intel.o
+snd-hda-codec-y := hda_codec.o
+snd-hda-codec-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o
+snd-hda-codec-$(CONFIG_PROC_FS) += hda_proc.o
+# snd-hda-codec-$(CONFIG_SND_HDA_ELD) += hda_eld.o
+snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o
+snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o
+
+snd-hda-codec-realtek-objs := patch_realtek.o
+snd-hda-codec-cmedia-objs := patch_cmedia.o
+snd-hda-codec-analog-objs := patch_analog.o
+snd-hda-codec-idt-objs := patch_sigmatel.o
+snd-hda-codec-si3054-objs := patch_si3054.o
+snd-hda-codec-atihdmi-objs := patch_atihdmi.o
+snd-hda-codec-conexant-objs := patch_conexant.o
+snd-hda-codec-via-objs := patch_via.o
+snd-hda-codec-nvhdmi-objs := patch_nvhdmi.o
+snd-hda-codec-intelhdmi-objs := patch_intelhdmi.o hda_eld.o
+
+# common driver
+obj-$(CONFIG_SND_HDA_INTEL) := snd-hda-codec.o
+
+# codec drivers (note: CONFIG_SND_HDA_CODEC_XXX are booleans)
+ifdef CONFIG_SND_HDA_CODEC_REALTEK
+obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-realtek.o
+endif
+ifdef CONFIG_SND_HDA_CODEC_CMEDIA
+obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-cmedia.o
+endif
+ifdef CONFIG_SND_HDA_CODEC_ANALOG
+obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-analog.o
+endif
+ifdef CONFIG_SND_HDA_CODEC_SIGMATEL
+obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-idt.o
+endif
+ifdef CONFIG_SND_HDA_CODEC_SI3054
+obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-si3054.o
+endif
+ifdef CONFIG_SND_HDA_CODEC_ATIHDMI
+obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-atihdmi.o
+endif
+ifdef CONFIG_SND_HDA_CODEC_CONEXANT
+obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-conexant.o
+endif
+ifdef CONFIG_SND_HDA_CODEC_VIA
+obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-via.o
+endif
+ifdef CONFIG_SND_HDA_CODEC_NVHDMI
+obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-nvhdmi.o
+endif
+ifdef CONFIG_SND_HDA_CODEC_INTELHDMI
+obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-intelhdmi.o
+endif
+
+# this must be the last entry after codec drivers;
+# otherwise the codec patches won't be hooked before the PCI probe
+# when built in kernel
obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-intel.o
diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c
index 9b77b3e0fa9..e00421c0d8b 100644
--- a/sound/pci/hda/hda_beep.c
+++ b/sound/pci/hda/hda_beep.c
@@ -37,6 +37,9 @@ static void snd_hda_generate_beep(struct work_struct *work)
container_of(work, struct hda_beep, beep_work);
struct hda_codec *codec = beep->codec;
+ if (!beep->enabled)
+ return;
+
/* generate tone */
snd_hda_codec_write_cache(codec, beep->nid, 0,
AC_VERB_SET_BEEP_CONTROL, beep->tone);
@@ -85,6 +88,10 @@ int snd_hda_attach_beep_device(struct hda_codec *codec, int nid)
snprintf(beep->phys, sizeof(beep->phys),
"card%d/codec#%d/beep0", codec->bus->card->number, codec->addr);
input_dev = input_allocate_device();
+ if (!input_dev) {
+ kfree(beep);
+ return -ENOMEM;
+ }
/* setup digital beep device */
input_dev->name = "HDA Digital PCBeep";
@@ -115,11 +122,13 @@ int snd_hda_attach_beep_device(struct hda_codec *codec, int nid)
beep->nid = nid;
beep->dev = input_dev;
beep->codec = codec;
+ beep->enabled = 1;
codec->beep = beep;
INIT_WORK(&beep->beep_work, &snd_hda_generate_beep);
return 0;
}
+EXPORT_SYMBOL_HDA(snd_hda_attach_beep_device);
void snd_hda_detach_beep_device(struct hda_codec *codec)
{
@@ -132,3 +141,4 @@ void snd_hda_detach_beep_device(struct hda_codec *codec)
kfree(beep);
}
}
+EXPORT_SYMBOL_HDA(snd_hda_detach_beep_device);
diff --git a/sound/pci/hda/hda_beep.h b/sound/pci/hda/hda_beep.h
index de4036e6e71..b9679f081ca 100644
--- a/sound/pci/hda/hda_beep.h
+++ b/sound/pci/hda/hda_beep.h
@@ -31,6 +31,7 @@ struct hda_beep {
char phys[32];
int tone;
int nid;
+ int enabled;
struct work_struct beep_work; /* scheduled task for beep event */
};
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index ba1ab737b55..e16cf63821a 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -31,15 +31,6 @@
#include <sound/initval.h>
#include "hda_local.h"
#include <sound/hda_hwdep.h>
-#include "hda_patch.h" /* codec presets */
-
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-/* define this option here to hide as static */
-static int power_save = CONFIG_SND_HDA_POWER_SAVE_DEFAULT;
-module_param(power_save, int, 0644);
-MODULE_PARM_DESC(power_save, "Automatic power-saving timeout "
- "(in second, 0 = disable).");
-#endif
/*
* vendor / preset table
@@ -55,6 +46,7 @@ static struct hda_vendor_id hda_vendor_ids[] = {
{ 0x1002, "ATI" },
{ 0x1057, "Motorola" },
{ 0x1095, "Silicon Image" },
+ { 0x10de, "Nvidia" },
{ 0x10ec, "Realtek" },
{ 0x1106, "VIA" },
{ 0x111d, "IDT" },
@@ -66,40 +58,31 @@ static struct hda_vendor_id hda_vendor_ids[] = {
{ 0x1854, "LG" },
{ 0x1aec, "Wolfson Microelectronics" },
{ 0x434d, "C-Media" },
+ { 0x8086, "Intel" },
{ 0x8384, "SigmaTel" },
{} /* terminator */
};
-static const struct hda_codec_preset *hda_preset_tables[] = {
-#ifdef CONFIG_SND_HDA_CODEC_REALTEK
- snd_hda_preset_realtek,
-#endif
-#ifdef CONFIG_SND_HDA_CODEC_CMEDIA
- snd_hda_preset_cmedia,
-#endif
-#ifdef CONFIG_SND_HDA_CODEC_ANALOG
- snd_hda_preset_analog,
-#endif
-#ifdef CONFIG_SND_HDA_CODEC_SIGMATEL
- snd_hda_preset_sigmatel,
-#endif
-#ifdef CONFIG_SND_HDA_CODEC_SI3054
- snd_hda_preset_si3054,
-#endif
-#ifdef CONFIG_SND_HDA_CODEC_ATIHDMI
- snd_hda_preset_atihdmi,
-#endif
-#ifdef CONFIG_SND_HDA_CODEC_CONEXANT
- snd_hda_preset_conexant,
-#endif
-#ifdef CONFIG_SND_HDA_CODEC_VIA
- snd_hda_preset_via,
-#endif
-#ifdef CONFIG_SND_HDA_CODEC_NVHDMI
- snd_hda_preset_nvhdmi,
-#endif
- NULL
-};
+static DEFINE_MUTEX(preset_mutex);
+static LIST_HEAD(hda_preset_tables);
+
+int snd_hda_add_codec_preset(struct hda_codec_preset_list *preset)
+{
+ mutex_lock(&preset_mutex);
+ list_add_tail(&preset->list, &hda_preset_tables);
+ mutex_unlock(&preset_mutex);
+ return 0;
+}
+EXPORT_SYMBOL_HDA(snd_hda_add_codec_preset);
+
+int snd_hda_delete_codec_preset(struct hda_codec_preset_list *preset)
+{
+ mutex_lock(&preset_mutex);
+ list_del(&preset->list);
+ mutex_unlock(&preset_mutex);
+ return 0;
+}
+EXPORT_SYMBOL_HDA(snd_hda_delete_codec_preset);
#ifdef CONFIG_SND_HDA_POWER_SAVE
static void hda_power_work(struct work_struct *work);
@@ -108,6 +91,72 @@ static void hda_keep_power_on(struct hda_codec *codec);
static inline void hda_keep_power_on(struct hda_codec *codec) {}
#endif
+const char *snd_hda_get_jack_location(u32 cfg)
+{
+ static char *bases[7] = {
+ "N/A", "Rear", "Front", "Left", "Right", "Top", "Bottom",
+ };
+ static unsigned char specials_idx[] = {
+ 0x07, 0x08,
+ 0x17, 0x18, 0x19,
+ 0x37, 0x38
+ };
+ static char *specials[] = {
+ "Rear Panel", "Drive Bar",
+ "Riser", "HDMI", "ATAPI",
+ "Mobile-In", "Mobile-Out"
+ };
+ int i;
+ cfg = (cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT;
+ if ((cfg & 0x0f) < 7)
+ return bases[cfg & 0x0f];
+ for (i = 0; i < ARRAY_SIZE(specials_idx); i++) {
+ if (cfg == specials_idx[i])
+ return specials[i];
+ }
+ return "UNKNOWN";
+}
+EXPORT_SYMBOL_HDA(snd_hda_get_jack_location);
+
+const char *snd_hda_get_jack_connectivity(u32 cfg)
+{
+ static char *jack_locations[4] = { "Ext", "Int", "Sep", "Oth" };
+
+ return jack_locations[(cfg >> (AC_DEFCFG_LOCATION_SHIFT + 4)) & 3];
+}
+EXPORT_SYMBOL_HDA(snd_hda_get_jack_connectivity);
+
+const char *snd_hda_get_jack_type(u32 cfg)
+{
+ static char *jack_types[16] = {
+ "Line Out", "Speaker", "HP Out", "CD",
+ "SPDIF Out", "Digital Out", "Modem Line", "Modem Hand",
+ "Line In", "Aux", "Mic", "Telephony",
+ "SPDIF In", "Digitial In", "Reserved", "Other"
+ };
+
+ return jack_types[(cfg & AC_DEFCFG_DEVICE)
+ >> AC_DEFCFG_DEVICE_SHIFT];
+}
+EXPORT_SYMBOL_HDA(snd_hda_get_jack_type);
+
+/*
+ * Compose a 32bit command word to be sent to the HD-audio controller
+ */
+static inline unsigned int
+make_codec_cmd(struct hda_codec *codec, hda_nid_t nid, int direct,
+ unsigned int verb, unsigned int parm)
+{
+ u32 val;
+
+ val = (u32)(codec->addr & 0x0f) << 28;
+ val |= (u32)direct << 27;
+ val |= (u32)nid << 20;
+ val |= verb << 8;
+ val |= parm;
+ return val;
+}
+
/**
* snd_hda_codec_read - send a command and get the response
* @codec: the HDA codec
@@ -124,17 +173,21 @@ unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid,
int direct,
unsigned int verb, unsigned int parm)
{
+ struct hda_bus *bus = codec->bus;
unsigned int res;
+
+ res = make_codec_cmd(codec, nid, direct, verb, parm);
snd_hda_power_up(codec);
- mutex_lock(&codec->bus->cmd_mutex);
- if (!codec->bus->ops.command(codec, nid, direct, verb, parm))
- res = codec->bus->ops.get_response(codec);
+ mutex_lock(&bus->cmd_mutex);
+ if (!bus->ops.command(bus, res))
+ res = bus->ops.get_response(bus);
else
res = (unsigned int)-1;
- mutex_unlock(&codec->bus->cmd_mutex);
+ mutex_unlock(&bus->cmd_mutex);
snd_hda_power_down(codec);
return res;
}
+EXPORT_SYMBOL_HDA(snd_hda_codec_read);
/**
* snd_hda_codec_write - send a single command without waiting for response
@@ -151,14 +204,19 @@ unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid,
int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct,
unsigned int verb, unsigned int parm)
{
+ struct hda_bus *bus = codec->bus;
+ unsigned int res;
int err;
+
+ res = make_codec_cmd(codec, nid, direct, verb, parm);
snd_hda_power_up(codec);
- mutex_lock(&codec->bus->cmd_mutex);
- err = codec->bus->ops.command(codec, nid, direct, verb, parm);
- mutex_unlock(&codec->bus->cmd_mutex);
+ mutex_lock(&bus->cmd_mutex);
+ err = bus->ops.command(bus, res);
+ mutex_unlock(&bus->cmd_mutex);
snd_hda_power_down(codec);
return err;
}
+EXPORT_SYMBOL_HDA(snd_hda_codec_write);
/**
* snd_hda_sequence_write - sequence writes
@@ -173,6 +231,7 @@ void snd_hda_sequence_write(struct hda_codec *codec, const struct hda_verb *seq)
for (; seq->nid; seq++)
snd_hda_codec_write(codec, seq->nid, 0, seq->verb, seq->param);
}
+EXPORT_SYMBOL_HDA(snd_hda_sequence_write);
/**
* snd_hda_get_sub_nodes - get the range of sub nodes
@@ -194,6 +253,7 @@ int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid,
*start_id = (parm >> 16) & 0x7fff;
return (int)(parm & 0x7fff);
}
+EXPORT_SYMBOL_HDA(snd_hda_get_sub_nodes);
/**
* snd_hda_get_connections - get connection list
@@ -282,6 +342,7 @@ int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
}
return conns;
}
+EXPORT_SYMBOL_HDA(snd_hda_get_connections);
/**
@@ -316,6 +377,7 @@ int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex)
return 0;
}
+EXPORT_SYMBOL_HDA(snd_hda_queue_unsol_event);
/*
* process queued unsolicited events
@@ -345,7 +407,7 @@ static void process_unsol_events(struct work_struct *work)
/*
* initialize unsolicited queue
*/
-static int __devinit init_unsol_queue(struct hda_bus *bus)
+static int init_unsol_queue(struct hda_bus *bus)
{
struct hda_bus_unsolicited *unsol;
@@ -391,9 +453,24 @@ static int snd_hda_bus_free(struct hda_bus *bus)
static int snd_hda_bus_dev_free(struct snd_device *device)
{
struct hda_bus *bus = device->device_data;
+ bus->shutdown = 1;
return snd_hda_bus_free(bus);
}
+#ifdef CONFIG_SND_HDA_HWDEP
+static int snd_hda_bus_dev_register(struct snd_device *device)
+{
+ struct hda_bus *bus = device->device_data;
+ struct hda_codec *codec;
+ list_for_each_entry(codec, &bus->codec_list, list) {
+ snd_hda_hwdep_add_sysfs(codec);
+ }
+ return 0;
+}
+#else
+#define snd_hda_bus_dev_register NULL
+#endif
+
/**
* snd_hda_bus_new - create a HDA bus
* @card: the card entry
@@ -402,13 +479,14 @@ static int snd_hda_bus_dev_free(struct snd_device *device)
*
* Returns 0 if successful, or a negative error code.
*/
-int __devinit snd_hda_bus_new(struct snd_card *card,
+int /*__devinit*/ snd_hda_bus_new(struct snd_card *card,
const struct hda_bus_template *temp,
struct hda_bus **busp)
{
struct hda_bus *bus;
int err;
static struct snd_device_ops dev_ops = {
+ .dev_register = snd_hda_bus_dev_register,
.dev_free = snd_hda_bus_dev_free,
};
@@ -430,6 +508,7 @@ int __devinit snd_hda_bus_new(struct snd_card *card,
bus->private_data = temp->private_data;
bus->pci = temp->pci;
bus->modelname = temp->modelname;
+ bus->power_save = temp->power_save;
bus->ops = temp->ops;
mutex_init(&bus->cmd_mutex);
@@ -444,27 +523,42 @@ int __devinit snd_hda_bus_new(struct snd_card *card,
*busp = bus;
return 0;
}
+EXPORT_SYMBOL_HDA(snd_hda_bus_new);
#ifdef CONFIG_SND_HDA_GENERIC
#define is_generic_config(codec) \
- (codec->bus->modelname && !strcmp(codec->bus->modelname, "generic"))
+ (codec->modelname && !strcmp(codec->modelname, "generic"))
#else
#define is_generic_config(codec) 0
#endif
+#ifdef MODULE
+#define HDA_MODREQ_MAX_COUNT 2 /* two request_modules()'s */
+#else
+#define HDA_MODREQ_MAX_COUNT 0 /* all presets are statically linked */
+#endif
+
/*
* find a matching codec preset
*/
-static const struct hda_codec_preset __devinit *
+static const struct hda_codec_preset *
find_codec_preset(struct hda_codec *codec)
{
- const struct hda_codec_preset **tbl, *preset;
+ struct hda_codec_preset_list *tbl;
+ const struct hda_codec_preset *preset;
+ int mod_requested = 0;
if (is_generic_config(codec))
return NULL; /* use the generic parser */
- for (tbl = hda_preset_tables; *tbl; tbl++) {
- for (preset = *tbl; preset->id; preset++) {
+ again:
+ mutex_lock(&preset_mutex);
+ list_for_each_entry(tbl, &hda_preset_tables, list) {
+ if (!try_module_get(tbl->owner)) {
+ snd_printk(KERN_ERR "hda_codec: cannot module_get\n");
+ continue;
+ }
+ for (preset = tbl->preset; preset->id; preset++) {
u32 mask = preset->mask;
if (preset->afg && preset->afg != codec->afg)
continue;
@@ -474,23 +568,40 @@ find_codec_preset(struct hda_codec *codec)
mask = ~0;
if (preset->id == (codec->vendor_id & mask) &&
(!preset->rev ||
- preset->rev == codec->revision_id))
+ preset->rev == codec->revision_id)) {
+ mutex_unlock(&preset_mutex);
+ codec->owner = tbl->owner;
return preset;
+ }
}
+ module_put(tbl->owner);
+ }
+ mutex_unlock(&preset_mutex);
+
+ if (mod_requested < HDA_MODREQ_MAX_COUNT) {
+ char name[32];
+ if (!mod_requested)
+ snprintf(name, sizeof(name), "snd-hda-codec-id:%08x",
+ codec->vendor_id);
+ else
+ snprintf(name, sizeof(name), "snd-hda-codec-id:%04x*",
+ (codec->vendor_id >> 16) & 0xffff);
+ request_module(name);
+ mod_requested++;
+ goto again;
}
return NULL;
}
/*
- * snd_hda_get_codec_name - store the codec name
+ * get_codec_name - store the codec name
*/
-void snd_hda_get_codec_name(struct hda_codec *codec,
- char *name, int namelen)
+static int get_codec_name(struct hda_codec *codec)
{
const struct hda_vendor_id *c;
const char *vendor = NULL;
u16 vendor_id = codec->vendor_id >> 16;
- char tmp[16];
+ char tmp[16], name[32];
for (c = hda_vendor_ids; c->id; c++) {
if (c->id == vendor_id) {
@@ -503,16 +614,21 @@ void snd_hda_get_codec_name(struct hda_codec *codec,
vendor = tmp;
}
if (codec->preset && codec->preset->name)
- snprintf(name, namelen, "%s %s", vendor, codec->preset->name);
+ snprintf(name, sizeof(name), "%s %s", vendor,
+ codec->preset->name);
else
- snprintf(name, namelen, "%s ID %x", vendor,
+ snprintf(name, sizeof(name), "%s ID %x", vendor,
codec->vendor_id & 0xffff);
+ codec->name = kstrdup(name, GFP_KERNEL);
+ if (!codec->name)
+ return -ENOMEM;
+ return 0;
}
/*
* look for an AFG and MFG nodes
*/
-static void __devinit setup_fg_nodes(struct hda_codec *codec)
+static void /*__devinit*/ setup_fg_nodes(struct hda_codec *codec)
{
int i, total_nodes;
hda_nid_t nid;
@@ -571,11 +687,15 @@ static void snd_hda_codec_free(struct hda_codec *codec)
flush_scheduled_work();
#endif
list_del(&codec->list);
+ snd_array_free(&codec->mixers);
codec->bus->caddr_tbl[codec->addr] = NULL;
if (codec->patch_ops.free)
codec->patch_ops.free(codec);
+ module_put(codec->owner);
free_hda_cache(&codec->amp_cache);
free_hda_cache(&codec->cmd_cache);
+ kfree(codec->name);
+ kfree(codec->modelname);
kfree(codec->wcaps);
kfree(codec);
}
@@ -588,8 +708,8 @@ static void snd_hda_codec_free(struct hda_codec *codec)
*
* Returns 0 if successful, or a negative error code.
*/
-int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
- struct hda_codec **codecp)
+int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
+ int do_init, struct hda_codec **codecp)
{
struct hda_codec *codec;
char component[31];
@@ -617,6 +737,14 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
mutex_init(&codec->spdif_mutex);
init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
+ snd_array_init(&codec->mixers, sizeof(struct snd_kcontrol *), 32);
+ if (codec->bus->modelname) {
+ codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL);
+ if (!codec->modelname) {
+ snd_hda_codec_free(codec);
+ return -ENODEV;
+ }
+ }
#ifdef CONFIG_SND_HDA_POWER_SAVE
INIT_DELAYED_WORK(&codec->power_work, hda_power_work);
@@ -662,12 +790,44 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
snd_hda_codec_read(codec, nid, 0,
AC_VERB_GET_SUBSYSTEM_ID, 0);
}
+ if (bus->modelname)
+ codec->modelname = kstrdup(bus->modelname, GFP_KERNEL);
+
+ if (do_init) {
+ err = snd_hda_codec_configure(codec);
+ if (err < 0) {
+ snd_hda_codec_free(codec);
+ return err;
+ }
+ }
+ snd_hda_codec_proc_new(codec);
+
+ snd_hda_create_hwdep(codec);
+
+ sprintf(component, "HDA:%08x,%08x,%08x", codec->vendor_id,
+ codec->subsystem_id, codec->revision_id);
+ snd_component_add(codec->bus->card, component);
+
+ if (codecp)
+ *codecp = codec;
+ return 0;
+}
+EXPORT_SYMBOL_HDA(snd_hda_codec_new);
+
+int snd_hda_codec_configure(struct hda_codec *codec)
+{
+ int err;
codec->preset = find_codec_preset(codec);
+ if (!codec->name) {
+ err = get_codec_name(codec);
+ if (err < 0)
+ return err;
+ }
/* audio codec should override the mixer name */
- if (codec->afg || !*bus->card->mixername)
- snd_hda_get_codec_name(codec, bus->card->mixername,
- sizeof(bus->card->mixername));
+ if (codec->afg || !*codec->bus->card->mixername)
+ strlcpy(codec->bus->card->mixername, codec->name,
+ sizeof(codec->bus->card->mixername));
if (is_generic_config(codec)) {
err = snd_hda_parse_generic_codec(codec);
@@ -684,25 +844,9 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
printk(KERN_ERR "hda-codec: No codec parser is available\n");
patched:
- if (err < 0) {
- snd_hda_codec_free(codec);
- return err;
- }
-
- if (codec->patch_ops.unsol_event)
- init_unsol_queue(bus);
-
- snd_hda_codec_proc_new(codec);
-#ifdef CONFIG_SND_HDA_HWDEP
- snd_hda_create_hwdep(codec);
-#endif
-
- sprintf(component, "HDA:%08x,%08x,%08x", codec->vendor_id, codec->subsystem_id, codec->revision_id);
- snd_component_add(codec->bus->card, component);
-
- if (codecp)
- *codecp = codec;
- return 0;
+ if (!err && codec->patch_ops.unsol_event)
+ err = init_unsol_queue(codec->bus);
+ return err;
}
/**
@@ -728,6 +872,7 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
msleep(1);
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, format);
}
+EXPORT_SYMBOL_HDA(snd_hda_codec_setup_stream);
void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid)
{
@@ -741,6 +886,7 @@ void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid)
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0);
#endif
}
+EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup_stream);
/*
* amp access functions
@@ -752,17 +898,17 @@ void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid)
#define INFO_AMP_VOL(ch) (1 << (1 + (ch)))
/* initialize the hash table */
-static void __devinit init_hda_cache(struct hda_cache_rec *cache,
+static void /*__devinit*/ init_hda_cache(struct hda_cache_rec *cache,
unsigned int record_size)
{
memset(cache, 0, sizeof(*cache));
memset(cache->hash, 0xff, sizeof(cache->hash));
- cache->record_size = record_size;
+ snd_array_init(&cache->buf, record_size, 64);
}
static void free_hda_cache(struct hda_cache_rec *cache)
{
- kfree(cache->buffer);
+ snd_array_free(&cache->buf);
}
/* query the hash. allocate an entry if not found. */
@@ -774,35 +920,17 @@ static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache,
struct hda_cache_head *info;
while (cur != 0xffff) {
- info = (struct hda_cache_head *)(cache->buffer +
- cur * cache->record_size);
+ info = snd_array_elem(&cache->buf, cur);
if (info->key == key)
return info;
cur = info->next;
}
/* add a new hash entry */
- if (cache->num_entries >= cache->size) {
- /* reallocate the array */
- unsigned int new_size = cache->size + 64;
- void *new_buffer;
- new_buffer = kcalloc(new_size, cache->record_size, GFP_KERNEL);
- if (!new_buffer) {
- snd_printk(KERN_ERR "hda_codec: "
- "can't malloc amp_info\n");
- return NULL;
- }
- if (cache->buffer) {
- memcpy(new_buffer, cache->buffer,
- cache->size * cache->record_size);
- kfree(cache->buffer);
- }
- cache->size = new_size;
- cache->buffer = new_buffer;
- }
- cur = cache->num_entries++;
- info = (struct hda_cache_head *)(cache->buffer +
- cur * cache->record_size);
+ info = snd_array_new(&cache->buf);
+ if (!info)
+ return NULL;
+ cur = snd_array_index(&cache->buf, info);
info->key = key;
info->val = 0;
info->next = cache->hash[idx];
@@ -840,6 +968,7 @@ u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
}
return info->amp_caps;
}
+EXPORT_SYMBOL_HDA(query_amp_caps);
int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
unsigned int caps)
@@ -853,6 +982,7 @@ int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
info->head.val |= INFO_AMP_CAPS;
return 0;
}
+EXPORT_SYMBOL_HDA(snd_hda_override_amp_caps);
/*
* read the current volume to info
@@ -906,6 +1036,7 @@ int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch,
return 0;
return get_vol_mute(codec, info, nid, ch, direction, index);
}
+EXPORT_SYMBOL_HDA(snd_hda_codec_amp_read);
/*
* update the AMP value, mask = bit mask to set, val = the value
@@ -925,6 +1056,7 @@ int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
put_vol_mute(codec, info, nid, ch, direction, idx, val);
return 1;
}
+EXPORT_SYMBOL_HDA(snd_hda_codec_amp_update);
/*
* update the AMP stereo with the same mask and value
@@ -938,15 +1070,16 @@ int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
idx, mask, val);
return ret;
}
+EXPORT_SYMBOL_HDA(snd_hda_codec_amp_stereo);
#ifdef SND_HDA_NEEDS_RESUME
/* resume the all amp commands from the cache */
void snd_hda_codec_resume_amp(struct hda_codec *codec)
{
- struct hda_amp_info *buffer = codec->amp_cache.buffer;
+ struct hda_amp_info *buffer = codec->amp_cache.buf.list;
int i;
- for (i = 0; i < codec->amp_cache.size; i++, buffer++) {
+ for (i = 0; i < codec->amp_cache.buf.used; i++, buffer++) {
u32 key = buffer->head.key;
hda_nid_t nid;
unsigned int idx, dir, ch;
@@ -963,6 +1096,7 @@ void snd_hda_codec_resume_amp(struct hda_codec *codec)
}
}
}
+EXPORT_SYMBOL_HDA(snd_hda_codec_resume_amp);
#endif /* SND_HDA_NEEDS_RESUME */
/* volume */
@@ -990,6 +1124,7 @@ int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol,
uinfo->value.integer.max = caps;
return 0;
}
+EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info);
int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -1009,6 +1144,7 @@ int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
& HDA_AMP_VOLMASK;
return 0;
}
+EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_get);
int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -1033,6 +1169,7 @@ int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
snd_hda_power_down(codec);
return change;
}
+EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_put);
int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
unsigned int size, unsigned int __user *_tlv)
@@ -1059,6 +1196,7 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
return -EFAULT;
return 0;
}
+EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_tlv);
/*
* set (static) TLV for virtual master volume; recalculated as max 0dB
@@ -1078,6 +1216,7 @@ void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,
tlv[2] = -nums * step;
tlv[3] = step;
}
+EXPORT_SYMBOL_HDA(snd_hda_set_vmaster_tlv);
/* find a mixer control element with the given name */
static struct snd_kcontrol *
@@ -1097,6 +1236,69 @@ struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
{
return _snd_hda_find_mixer_ctl(codec, name, 0);
}
+EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl);
+
+/* Add a control element and assign to the codec */
+int snd_hda_ctl_add(struct hda_codec *codec, struct snd_kcontrol *kctl)
+{
+ int err;
+ struct snd_kcontrol **knewp;
+
+ err = snd_ctl_add(codec->bus->card, kctl);
+ if (err < 0)
+ return err;
+ knewp = snd_array_new(&codec->mixers);
+ if (!knewp)
+ return -ENOMEM;
+ *knewp = kctl;
+ return 0;
+}
+EXPORT_SYMBOL_HDA(snd_hda_ctl_add);
+
+#ifdef CONFIG_SND_HDA_RECONFIG
+/* Clear all controls assigned to the given codec */
+void snd_hda_ctls_clear(struct hda_codec *codec)
+{
+ int i;
+ struct snd_kcontrol **kctls = codec->mixers.list;
+ for (i = 0; i < codec->mixers.used; i++)
+ snd_ctl_remove(codec->bus->card, kctls[i]);
+ snd_array_free(&codec->mixers);
+}
+
+void snd_hda_codec_reset(struct hda_codec *codec)
+{
+ int i;
+
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ cancel_delayed_work(&codec->power_work);
+ flush_scheduled_work();
+#endif
+ snd_hda_ctls_clear(codec);
+ /* relase PCMs */
+ for (i = 0; i < codec->num_pcms; i++) {
+ if (codec->pcm_info[i].pcm) {
+ snd_device_free(codec->bus->card,
+ codec->pcm_info[i].pcm);
+ clear_bit(codec->pcm_info[i].device,
+ codec->bus->pcm_dev_bits);
+ }
+ }
+ if (codec->patch_ops.free)
+ codec->patch_ops.free(codec);
+ codec->proc_widget_hook = NULL;
+ codec->spec = NULL;
+ free_hda_cache(&codec->amp_cache);
+ free_hda_cache(&codec->cmd_cache);
+ init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
+ init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
+ codec->num_pcms = 0;
+ codec->pcm_info = NULL;
+ codec->preset = NULL;
+ module_put(codec->owner);
+ codec->owner = NULL;
+}
+#endif /* CONFIG_SND_HDA_RECONFIG */
/* create a virtual master control and add slaves */
int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
@@ -1115,7 +1317,7 @@ int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
kctl = snd_ctl_make_virtual_master(name, tlv);
if (!kctl)
return -ENOMEM;
- err = snd_ctl_add(codec->bus->card, kctl);
+ err = snd_hda_ctl_add(codec, kctl);
if (err < 0)
return err;
@@ -1133,6 +1335,7 @@ int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
}
return 0;
}
+EXPORT_SYMBOL_HDA(snd_hda_add_vmaster);
/* switch */
int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol,
@@ -1146,6 +1349,7 @@ int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol,
uinfo->value.integer.max = 1;
return 0;
}
+EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_info);
int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -1165,6 +1369,7 @@ int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
HDA_AMP_MUTE) ? 0 : 1;
return 0;
}
+EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_get);
int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -1195,6 +1400,7 @@ int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
snd_hda_power_down(codec);
return change;
}
+EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put);
/*
* bound volume controls
@@ -1220,6 +1426,7 @@ int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol,
mutex_unlock(&codec->spdif_mutex);
return err;
}
+EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_get);
int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -1243,6 +1450,7 @@ int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
mutex_unlock(&codec->spdif_mutex);
return err < 0 ? err : change;
}
+EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_put);
/*
* generic bound volume/swtich controls
@@ -1262,6 +1470,7 @@ int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol,
mutex_unlock(&codec->spdif_mutex);
return err;
}
+EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_info);
int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -1278,6 +1487,7 @@ int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol,
mutex_unlock(&codec->spdif_mutex);
return err;
}
+EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_get);
int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -1300,6 +1510,7 @@ int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
mutex_unlock(&codec->spdif_mutex);
return err < 0 ? err : change;
}
+EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_put);
int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
unsigned int size, unsigned int __user *tlv)
@@ -1316,6 +1527,7 @@ int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
mutex_unlock(&codec->spdif_mutex);
return err;
}
+EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_tlv);
struct hda_ctl_ops snd_hda_bind_vol = {
.info = snd_hda_mixer_amp_volume_info,
@@ -1323,6 +1535,7 @@ struct hda_ctl_ops snd_hda_bind_vol = {
.put = snd_hda_mixer_amp_volume_put,
.tlv = snd_hda_mixer_amp_tlv
};
+EXPORT_SYMBOL_HDA(snd_hda_bind_vol);
struct hda_ctl_ops snd_hda_bind_sw = {
.info = snd_hda_mixer_amp_switch_info,
@@ -1330,6 +1543,7 @@ struct hda_ctl_ops snd_hda_bind_sw = {
.put = snd_hda_mixer_amp_switch_put,
.tlv = snd_hda_mixer_amp_tlv
};
+EXPORT_SYMBOL_HDA(snd_hda_bind_sw);
/*
* SPDIF out controls
@@ -1436,12 +1650,12 @@ static void set_dig_out(struct hda_codec *codec, hda_nid_t nid,
{
hda_nid_t *d;
- snd_hda_codec_write(codec, nid, 0, verb, val);
+ snd_hda_codec_write_cache(codec, nid, 0, verb, val);
d = codec->slave_dig_outs;
if (!d)
return;
for (; *d; d++)
- snd_hda_codec_write(codec, *d, 0, verb, val);
+ snd_hda_codec_write_cache(codec, *d, 0, verb, val);
}
static inline void set_dig_out_convert(struct hda_codec *codec, hda_nid_t nid,
@@ -1577,9 +1791,11 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
}
for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) {
kctl = snd_ctl_new1(dig_mix, codec);
+ if (!kctl)
+ return -ENOMEM;
kctl->id.index = idx;
kctl->private_value = nid;
- err = snd_ctl_add(codec->bus->card, kctl);
+ err = snd_hda_ctl_add(codec, kctl);
if (err < 0)
return err;
}
@@ -1589,6 +1805,7 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
codec->spdif_status = convert_to_spdif_status(codec->spdif_ctls);
return 0;
}
+EXPORT_SYMBOL_HDA(snd_hda_create_spdif_out_ctls);
/*
* SPDIF sharing with analog output
@@ -1623,9 +1840,10 @@ int snd_hda_create_spdif_share_sw(struct hda_codec *codec,
if (!mout->dig_out_nid)
return 0;
/* ATTENTION: here mout is passed as private_data, instead of codec */
- return snd_ctl_add(codec->bus->card,
+ return snd_hda_ctl_add(codec,
snd_ctl_new1(&spdif_share_sw, mout));
}
+EXPORT_SYMBOL_HDA(snd_hda_create_spdif_share_sw);
/*
* SPDIF input
@@ -1725,7 +1943,7 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) {
kctl = snd_ctl_new1(dig_mix, codec);
kctl->private_value = nid;
- err = snd_ctl_add(codec->bus->card, kctl);
+ err = snd_hda_ctl_add(codec, kctl);
if (err < 0)
return err;
}
@@ -1735,6 +1953,7 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
AC_DIG1_ENABLE;
return 0;
}
+EXPORT_SYMBOL_HDA(snd_hda_create_spdif_in_ctls);
#ifdef SND_HDA_NEEDS_RESUME
/*
@@ -1761,10 +1980,14 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
int direct, unsigned int verb, unsigned int parm)
{
+ struct hda_bus *bus = codec->bus;
+ unsigned int res;
int err;
+
+ res = make_codec_cmd(codec, nid, direct, verb, parm);
snd_hda_power_up(codec);
- mutex_lock(&codec->bus->cmd_mutex);
- err = codec->bus->ops.command(codec, nid, direct, verb, parm);
+ mutex_lock(&bus->cmd_mutex);
+ err = bus->ops.command(bus, res);
if (!err) {
struct hda_cache_head *c;
u32 key = build_cmd_cache_key(nid, verb);
@@ -1772,18 +1995,19 @@ int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
if (c)
c->val = parm;
}
- mutex_unlock(&codec->bus->cmd_mutex);
+ mutex_unlock(&bus->cmd_mutex);
snd_hda_power_down(codec);
return err;
}
+EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache);
/* resume the all commands from the cache */
void snd_hda_codec_resume_cache(struct hda_codec *codec)
{
- struct hda_cache_head *buffer = codec->cmd_cache.buffer;
+ struct hda_cache_head *buffer = codec->cmd_cache.buf.list;
int i;
- for (i = 0; i < codec->cmd_cache.size; i++, buffer++) {
+ for (i = 0; i < codec->cmd_cache.buf.used; i++, buffer++) {
u32 key = buffer->key;
if (!key)
continue;
@@ -1791,6 +2015,7 @@ void snd_hda_codec_resume_cache(struct hda_codec *codec)
get_cmd_cache_cmd(key), buffer->val);
}
}
+EXPORT_SYMBOL_HDA(snd_hda_codec_resume_cache);
/**
* snd_hda_sequence_write_cache - sequence writes with caching
@@ -1808,6 +2033,7 @@ void snd_hda_sequence_write_cache(struct hda_codec *codec,
snd_hda_codec_write_cache(codec, seq->nid, 0, seq->verb,
seq->param);
}
+EXPORT_SYMBOL_HDA(snd_hda_sequence_write_cache);
#endif /* SND_HDA_NEEDS_RESUME */
/*
@@ -1868,6 +2094,17 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
}
}
+#ifdef CONFIG_SND_HDA_HWDEP
+/* execute additional init verbs */
+static void hda_exec_init_verbs(struct hda_codec *codec)
+{
+ if (codec->init_verbs.list)
+ snd_hda_sequence_write(codec, codec->init_verbs.list);
+}
+#else
+static inline void hda_exec_init_verbs(struct hda_codec *codec) {}
+#endif
+
#ifdef SND_HDA_NEEDS_RESUME
/*
* call suspend and power-down; used both from PM and power-save
@@ -1894,6 +2131,7 @@ static void hda_call_codec_resume(struct hda_codec *codec)
hda_set_power_state(codec,
codec->afg ? codec->afg : codec->mfg,
AC_PWRST_D0);
+ hda_exec_init_verbs(codec);
if (codec->patch_ops.resume)
codec->patch_ops.resume(codec);
else {
@@ -1914,28 +2152,37 @@ static void hda_call_codec_resume(struct hda_codec *codec)
*
* Returns 0 if successful, otherwise a negative error code.
*/
-int __devinit snd_hda_build_controls(struct hda_bus *bus)
+int /*__devinit*/ snd_hda_build_controls(struct hda_bus *bus)
{
struct hda_codec *codec;
list_for_each_entry(codec, &bus->codec_list, list) {
- int err = 0;
- /* fake as if already powered-on */
- hda_keep_power_on(codec);
- /* then fire up */
- hda_set_power_state(codec,
- codec->afg ? codec->afg : codec->mfg,
- AC_PWRST_D0);
- /* continue to initialize... */
- if (codec->patch_ops.init)
- err = codec->patch_ops.init(codec);
- if (!err && codec->patch_ops.build_controls)
- err = codec->patch_ops.build_controls(codec);
- snd_hda_power_down(codec);
+ int err = snd_hda_codec_build_controls(codec);
if (err < 0)
return err;
}
+ return 0;
+}
+EXPORT_SYMBOL_HDA(snd_hda_build_controls);
+int snd_hda_codec_build_controls(struct hda_codec *codec)
+{
+ int err = 0;
+ /* fake as if already powered-on */
+ hda_keep_power_on(codec);
+ /* then fire up */
+ hda_set_power_state(codec,
+ codec->afg ? codec->afg : codec->mfg,
+ AC_PWRST_D0);
+ hda_exec_init_verbs(codec);
+ /* continue to initialize... */
+ if (codec->patch_ops.init)
+ err = codec->patch_ops.init(codec);
+ if (!err && codec->patch_ops.build_controls)
+ err = codec->patch_ops.build_controls(codec);
+ snd_hda_power_down(codec);
+ if (err < 0)
+ return err;
return 0;
}
@@ -2028,6 +2275,7 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate,
return val;
}
+EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format);
/**
* snd_hda_query_supported_pcm - query the supported PCM rates and formats
@@ -2042,7 +2290,7 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate,
*
* Returns 0 if successful, otherwise a negative error code.
*/
-int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
+static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
u32 *ratesp, u64 *formatsp, unsigned int *bpsp)
{
int i;
@@ -2207,6 +2455,7 @@ int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
return 1;
}
+EXPORT_SYMBOL_HDA(snd_hda_is_supported_format);
/*
* PCM stuff
@@ -2236,8 +2485,8 @@ static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo,
return 0;
}
-static int __devinit set_pcm_default_values(struct hda_codec *codec,
- struct hda_pcm_stream *info)
+static int set_pcm_default_values(struct hda_codec *codec,
+ struct hda_pcm_stream *info)
{
/* query support PCM information from the given NID */
if (info->nid && (!info->rates || !info->formats)) {
@@ -2263,6 +2512,110 @@ static int __devinit set_pcm_default_values(struct hda_codec *codec,
return 0;
}
+/*
+ * get the empty PCM device number to assign
+ */
+static int get_empty_pcm_device(struct hda_bus *bus, int type)
+{
+ static const char *dev_name[HDA_PCM_NTYPES] = {
+ "Audio", "SPDIF", "HDMI", "Modem"
+ };
+ /* starting device index for each PCM type */
+ static int dev_idx[HDA_PCM_NTYPES] = {
+ [HDA_PCM_TYPE_AUDIO] = 0,
+ [HDA_PCM_TYPE_SPDIF] = 1,
+ [HDA_PCM_TYPE_HDMI] = 3,
+ [HDA_PCM_TYPE_MODEM] = 6
+ };
+ /* normal audio device indices; not linear to keep compatibility */
+ static int audio_idx[4] = { 0, 2, 4, 5 };
+ int i, dev;
+
+ switch (type) {
+ case HDA_PCM_TYPE_AUDIO:
+ for (i = 0; i < ARRAY_SIZE(audio_idx); i++) {
+ dev = audio_idx[i];
+ if (!test_bit(dev, bus->pcm_dev_bits))
+ break;
+ }
+ if (i >= ARRAY_SIZE(audio_idx)) {
+ snd_printk(KERN_WARNING "Too many audio devices\n");
+ return -EAGAIN;
+ }
+ break;
+ case HDA_PCM_TYPE_SPDIF:
+ case HDA_PCM_TYPE_HDMI:
+ case HDA_PCM_TYPE_MODEM:
+ dev = dev_idx[type];
+ if (test_bit(dev, bus->pcm_dev_bits)) {
+ snd_printk(KERN_WARNING "%s already defined\n",
+ dev_name[type]);
+ return -EAGAIN;
+ }
+ break;
+ default:
+ snd_printk(KERN_WARNING "Invalid PCM type %d\n", type);
+ return -EINVAL;
+ }
+ set_bit(dev, bus->pcm_dev_bits);
+ return dev;
+}
+
+/*
+ * attach a new PCM stream
+ */
+static int snd_hda_attach_pcm(struct hda_codec *codec, struct hda_pcm *pcm)
+{
+ struct hda_bus *bus = codec->bus;
+ struct hda_pcm_stream *info;
+ int stream, err;
+
+ if (snd_BUG_ON(!pcm->name))
+ return -EINVAL;
+ for (stream = 0; stream < 2; stream++) {
+ info = &pcm->stream[stream];
+ if (info->substreams) {
+ err = set_pcm_default_values(codec, info);
+ if (err < 0)
+ return err;
+ }
+ }
+ return bus->ops.attach_pcm(bus, codec, pcm);
+}
+
+/* assign all PCMs of the given codec */
+int snd_hda_codec_build_pcms(struct hda_codec *codec)
+{
+ unsigned int pcm;
+ int err;
+
+ if (!codec->num_pcms) {
+ if (!codec->patch_ops.build_pcms)
+ return 0;
+ err = codec->patch_ops.build_pcms(codec);
+ if (err < 0)
+ return err;
+ }
+ for (pcm = 0; pcm < codec->num_pcms; pcm++) {
+ struct hda_pcm *cpcm = &codec->pcm_info[pcm];
+ int dev;
+
+ if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams)
+ return 0; /* no substreams assigned */
+
+ if (!cpcm->pcm) {
+ dev = get_empty_pcm_device(codec->bus, cpcm->pcm_type);
+ if (dev < 0)
+ return 0;
+ cpcm->device = dev;
+ err = snd_hda_attach_pcm(codec, cpcm);
+ if (err < 0)
+ return err;
+ }
+ }
+ return 0;
+}
+
/**
* snd_hda_build_pcms - build PCM information
* @bus: the BUS
@@ -2294,27 +2647,13 @@ int __devinit snd_hda_build_pcms(struct hda_bus *bus)
struct hda_codec *codec;
list_for_each_entry(codec, &bus->codec_list, list) {
- unsigned int pcm, s;
- int err;
- if (!codec->patch_ops.build_pcms)
- continue;
- err = codec->patch_ops.build_pcms(codec);
+ int err = snd_hda_codec_build_pcms(codec);
if (err < 0)
return err;
- for (pcm = 0; pcm < codec->num_pcms; pcm++) {
- for (s = 0; s < 2; s++) {
- struct hda_pcm_stream *info;
- info = &codec->pcm_info[pcm].stream[s];
- if (!info->substreams)
- continue;
- err = set_pcm_default_values(codec, info);
- if (err < 0)
- return err;
- }
- }
}
return 0;
}
+EXPORT_SYMBOL_HDA(snd_hda_build_pcms);
/**
* snd_hda_check_board_config - compare the current codec with the config table
@@ -2333,11 +2672,11 @@ int snd_hda_check_board_config(struct hda_codec *codec,
int num_configs, const char **models,
const struct snd_pci_quirk *tbl)
{
- if (codec->bus->modelname && models) {
+ if (codec->modelname && models) {
int i;
for (i = 0; i < num_configs; i++) {
if (models[i] &&
- !strcmp(codec->bus->modelname, models[i])) {
+ !strcmp(codec->modelname, models[i])) {
snd_printd(KERN_INFO "hda_codec: model '%s' is "
"selected\n", models[i]);
return i;
@@ -2370,6 +2709,7 @@ int snd_hda_check_board_config(struct hda_codec *codec,
}
return -1;
}
+EXPORT_SYMBOL_HDA(snd_hda_check_board_config);
/**
* snd_hda_add_new_ctls - create controls from the array
@@ -2390,7 +2730,7 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew)
kctl = snd_ctl_new1(knew, codec);
if (!kctl)
return -ENOMEM;
- err = snd_ctl_add(codec->bus->card, kctl);
+ err = snd_hda_ctl_add(codec, kctl);
if (err < 0) {
if (!codec->addr)
return err;
@@ -2398,13 +2738,14 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew)
if (!kctl)
return -ENOMEM;
kctl->id.device = codec->addr;
- err = snd_ctl_add(codec->bus->card, kctl);
+ err = snd_hda_ctl_add(codec, kctl);
if (err < 0)
return err;
}
}
return 0;
}
+EXPORT_SYMBOL_HDA(snd_hda_add_new_ctls);
#ifdef CONFIG_SND_HDA_POWER_SAVE
static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
@@ -2414,6 +2755,7 @@ static void hda_power_work(struct work_struct *work)
{
struct hda_codec *codec =
container_of(work, struct hda_codec, power_work.work);
+ struct hda_bus *bus = codec->bus;
if (!codec->power_on || codec->power_count) {
codec->power_transition = 0;
@@ -2421,8 +2763,8 @@ static void hda_power_work(struct work_struct *work)
}
hda_call_codec_suspend(codec);
- if (codec->bus->ops.pm_notify)
- codec->bus->ops.pm_notify(codec);
+ if (bus->ops.pm_notify)
+ bus->ops.pm_notify(bus);
}
static void hda_keep_power_on(struct hda_codec *codec)
@@ -2433,29 +2775,39 @@ static void hda_keep_power_on(struct hda_codec *codec)
void snd_hda_power_up(struct hda_codec *codec)
{
+ struct hda_bus *bus = codec->bus;
+
codec->power_count++;
if (codec->power_on || codec->power_transition)
return;
codec->power_on = 1;
- if (codec->bus->ops.pm_notify)
- codec->bus->ops.pm_notify(codec);
+ if (bus->ops.pm_notify)
+ bus->ops.pm_notify(bus);
hda_call_codec_resume(codec);
cancel_delayed_work(&codec->power_work);
codec->power_transition = 0;
}
+EXPORT_SYMBOL_HDA(snd_hda_power_up);
+
+#define power_save(codec) \
+ ((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
+
+#define power_save(codec) \
+ ((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
void snd_hda_power_down(struct hda_codec *codec)
{
--codec->power_count;
if (!codec->power_on || codec->power_count || codec->power_transition)
return;
- if (power_save) {
+ if (power_save(codec)) {
codec->power_transition = 1; /* avoid reentrance */
schedule_delayed_work(&codec->power_work,
- msecs_to_jiffies(power_save * 1000));
+ msecs_to_jiffies(power_save(codec) * 1000));
}
}
+EXPORT_SYMBOL_HDA(snd_hda_power_down);
int snd_hda_check_amp_list_power(struct hda_codec *codec,
struct hda_loopback_check *check,
@@ -2492,6 +2844,7 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec,
}
return 0;
}
+EXPORT_SYMBOL_HDA(snd_hda_check_amp_list_power);
#endif
/*
@@ -2511,6 +2864,7 @@ int snd_hda_ch_mode_info(struct hda_codec *codec,
chmode[uinfo->value.enumerated.item].channels);
return 0;
}
+EXPORT_SYMBOL_HDA(snd_hda_ch_mode_info);
int snd_hda_ch_mode_get(struct hda_codec *codec,
struct snd_ctl_elem_value *ucontrol,
@@ -2528,6 +2882,7 @@ int snd_hda_ch_mode_get(struct hda_codec *codec,
}
return 0;
}
+EXPORT_SYMBOL_HDA(snd_hda_ch_mode_get);
int snd_hda_ch_mode_put(struct hda_codec *codec,
struct snd_ctl_elem_value *ucontrol,
@@ -2548,6 +2903,7 @@ int snd_hda_ch_mode_put(struct hda_codec *codec,
snd_hda_sequence_write_cache(codec, chmode[mode].sequence);
return 1;
}
+EXPORT_SYMBOL_HDA(snd_hda_ch_mode_put);
/*
* input MUX helper
@@ -2568,6 +2924,7 @@ int snd_hda_input_mux_info(const struct hda_input_mux *imux,
strcpy(uinfo->value.enumerated.name, imux->items[index].label);
return 0;
}
+EXPORT_SYMBOL_HDA(snd_hda_input_mux_info);
int snd_hda_input_mux_put(struct hda_codec *codec,
const struct hda_input_mux *imux,
@@ -2589,6 +2946,7 @@ int snd_hda_input_mux_put(struct hda_codec *codec,
*cur_val = idx;
return 1;
}
+EXPORT_SYMBOL_HDA(snd_hda_input_mux_put);
/*
@@ -2641,6 +2999,7 @@ int snd_hda_multi_out_dig_open(struct hda_codec *codec,
mutex_unlock(&codec->spdif_mutex);
return 0;
}
+EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_open);
int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
struct hda_multi_out *mout,
@@ -2653,6 +3012,7 @@ int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
mutex_unlock(&codec->spdif_mutex);
return 0;
}
+EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_prepare);
/*
* release the digital out
@@ -2665,6 +3025,7 @@ int snd_hda_multi_out_dig_close(struct hda_codec *codec,
mutex_unlock(&codec->spdif_mutex);
return 0;
}
+EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_close);
/*
* set up more restrictions for analog out
@@ -2704,6 +3065,7 @@ int snd_hda_multi_out_analog_open(struct hda_codec *codec,
return snd_pcm_hw_constraint_step(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_CHANNELS, 2);
}
+EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_open);
/*
* set up the i/o for analog out
@@ -2762,6 +3124,7 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
}
return 0;
}
+EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_prepare);
/*
* clean up the setting for analog out
@@ -2788,6 +3151,7 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
mutex_unlock(&codec->spdif_mutex);
return 0;
}
+EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_cleanup);
/*
* Helper for automatic pin configuration
@@ -3073,11 +3437,13 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
return 0;
}
+EXPORT_SYMBOL_HDA(snd_hda_parse_pin_def_config);
/* labels for input pins */
const char *auto_pin_cfg_labels[AUTO_PIN_LAST] = {
"Mic", "Front Mic", "Line", "Front Line", "CD", "Aux"
};
+EXPORT_SYMBOL_HDA(auto_pin_cfg_labels);
#ifdef CONFIG_PM
@@ -3105,11 +3471,11 @@ int snd_hda_suspend(struct hda_bus *bus, pm_message_t state)
}
return 0;
}
+EXPORT_SYMBOL_HDA(snd_hda_suspend);
/**
* snd_hda_resume - resume the codecs
* @bus: the HDA bus
- * @state: resume state
*
* Returns 0 if successful.
*
@@ -3126,16 +3492,79 @@ int snd_hda_resume(struct hda_bus *bus)
}
return 0;
}
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-int snd_hda_codecs_inuse(struct hda_bus *bus)
-{
- struct hda_codec *codec;
+EXPORT_SYMBOL_HDA(snd_hda_resume);
+#endif /* CONFIG_PM */
- list_for_each_entry(codec, &bus->codec_list, list) {
- if (snd_hda_codec_needs_resume(codec))
- return 1;
+/*
+ * generic arrays
+ */
+
+/* get a new element from the given array
+ * if it exceeds the pre-allocated array size, re-allocate the array
+ */
+void *snd_array_new(struct snd_array *array)
+{
+ if (array->used >= array->alloced) {
+ int num = array->alloced + array->alloc_align;
+ void *nlist;
+ if (snd_BUG_ON(num >= 4096))
+ return NULL;
+ nlist = kcalloc(num + 1, array->elem_size, GFP_KERNEL);
+ if (!nlist)
+ return NULL;
+ if (array->list) {
+ memcpy(nlist, array->list,
+ array->elem_size * array->alloced);
+ kfree(array->list);
+ }
+ array->list = nlist;
+ array->alloced = num;
}
- return 0;
+ return snd_array_elem(array, array->used++);
}
-#endif
-#endif
+EXPORT_SYMBOL_HDA(snd_array_new);
+
+/* free the given array elements */
+void snd_array_free(struct snd_array *array)
+{
+ kfree(array->list);
+ array->used = 0;
+ array->alloced = 0;
+ array->list = NULL;
+}
+EXPORT_SYMBOL_HDA(snd_array_free);
+
+/*
+ * used by hda_proc.c and hda_eld.c
+ */
+void snd_print_pcm_rates(int pcm, char *buf, int buflen)
+{
+ static unsigned int rates[] = {
+ 8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200,
+ 96000, 176400, 192000, 384000
+ };
+ int i, j;
+
+ for (i = 0, j = 0; i < ARRAY_SIZE(rates); i++)
+ if (pcm & (1 << i))
+ j += snprintf(buf + j, buflen - j, " %d", rates[i]);
+
+ buf[j] = '\0'; /* necessary when j == 0 */
+}
+EXPORT_SYMBOL_HDA(snd_print_pcm_rates);
+
+void snd_print_pcm_bits(int pcm, char *buf, int buflen)
+{
+ static unsigned int bits[] = { 8, 16, 20, 24, 32 };
+ int i, j;
+
+ for (i = 0, j = 0; i < ARRAY_SIZE(bits); i++)
+ if (pcm & (AC_SUPPCM_BITS_8 << i))
+ j += snprintf(buf + j, buflen - j, " %d", bits[i]);
+
+ buf[j] = '\0'; /* necessary when j == 0 */
+}
+EXPORT_SYMBOL_HDA(snd_print_pcm_bits);
+
+MODULE_DESCRIPTION("HDA codec core");
+MODULE_LICENSE("GPL");
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index 60468f56240..729fc7642d7 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -520,6 +520,36 @@ enum {
#define HDA_MAX_CODEC_ADDRESS 0x0f
/*
+ * generic arrays
+ */
+struct snd_array {
+ unsigned int used;
+ unsigned int alloced;
+ unsigned int elem_size;
+ unsigned int alloc_align;
+ void *list;
+};
+
+void *snd_array_new(struct snd_array *array);
+void snd_array_free(struct snd_array *array);
+static inline void snd_array_init(struct snd_array *array, unsigned int size,
+ unsigned int align)
+{
+ array->elem_size = size;
+ array->alloc_align = align;
+}
+
+static inline void *snd_array_elem(struct snd_array *array, unsigned int idx)
+{
+ return array->list + idx * array->elem_size;
+}
+
+static inline unsigned int snd_array_index(struct snd_array *array, void *ptr)
+{
+ return (unsigned long)(ptr - array->list) / array->elem_size;
+}
+
+/*
* Structures
*/
@@ -536,15 +566,17 @@ typedef u16 hda_nid_t;
/* bus operators */
struct hda_bus_ops {
/* send a single command */
- int (*command)(struct hda_codec *codec, hda_nid_t nid, int direct,
- unsigned int verb, unsigned int parm);
+ int (*command)(struct hda_bus *bus, unsigned int cmd);
/* get a response from the last command */
- unsigned int (*get_response)(struct hda_codec *codec);
+ unsigned int (*get_response)(struct hda_bus *bus);
/* free the private data */
void (*private_free)(struct hda_bus *);
+ /* attach a PCM stream */
+ int (*attach_pcm)(struct hda_bus *bus, struct hda_codec *codec,
+ struct hda_pcm *pcm);
#ifdef CONFIG_SND_HDA_POWER_SAVE
/* notify power-up/down from codec to controller */
- void (*pm_notify)(struct hda_codec *codec);
+ void (*pm_notify)(struct hda_bus *bus);
#endif
};
@@ -553,6 +585,7 @@ struct hda_bus_template {
void *private_data;
struct pci_dev *pci;
const char *modelname;
+ int *power_save;
struct hda_bus_ops ops;
};
@@ -569,6 +602,7 @@ struct hda_bus {
void *private_data;
struct pci_dev *pci;
const char *modelname;
+ int *power_save;
struct hda_bus_ops ops;
/* codec linked list */
@@ -581,10 +615,12 @@ struct hda_bus {
/* unsolicited event queue */
struct hda_bus_unsolicited *unsol;
- struct snd_info_entry *proc;
+ /* assigned PCMs */
+ DECLARE_BITMAP(pcm_dev_bits, SNDRV_PCM_DEVICES);
/* misc op flags */
unsigned int needs_damn_long_delay :1;
+ unsigned int shutdown :1; /* being unloaded */
};
/*
@@ -604,6 +640,16 @@ struct hda_codec_preset {
int (*patch)(struct hda_codec *codec);
};
+struct hda_codec_preset_list {
+ const struct hda_codec_preset *preset;
+ struct module *owner;
+ struct list_head list;
+};
+
+/* initial hook */
+int snd_hda_add_codec_preset(struct hda_codec_preset_list *preset);
+int snd_hda_delete_codec_preset(struct hda_codec_preset_list *preset);
+
/* ops set by the preset patch */
struct hda_codec_ops {
int (*build_controls)(struct hda_codec *codec);
@@ -635,10 +681,7 @@ struct hda_amp_info {
struct hda_cache_rec {
u16 hash[64]; /* hash table for index */
- unsigned int num_entries; /* number of assigned entries */
- unsigned int size; /* allocated size */
- unsigned int record_size; /* record size (including header) */
- void *buffer; /* hash table entries */
+ struct snd_array buf; /* record entries */
};
/* PCM callbacks */
@@ -680,7 +723,8 @@ struct hda_pcm {
char *name;
struct hda_pcm_stream stream[2];
unsigned int pcm_type; /* HDA_PCM_TYPE_XXX */
- int device; /* assigned device number */
+ int device; /* device number to assign */
+ struct snd_pcm *pcm; /* assigned PCM instance */
};
/* codec information */
@@ -699,6 +743,9 @@ struct hda_codec {
/* detected preset */
const struct hda_codec_preset *preset;
+ struct module *owner;
+ const char *name; /* codec name */
+ const char *modelname; /* model name for preset */
/* set by patch */
struct hda_codec_ops patch_ops;
@@ -718,6 +765,8 @@ struct hda_codec {
hda_nid_t start_nid;
u32 *wcaps;
+ struct snd_array mixers; /* list of assigned mixer elements */
+
struct hda_cache_rec amp_cache; /* cache for amp access */
struct hda_cache_rec cmd_cache; /* cache for other commands */
@@ -727,7 +776,11 @@ struct hda_codec {
unsigned int spdif_in_enable; /* SPDIF input enable? */
hda_nid_t *slave_dig_outs; /* optional digital out slave widgets */
+#ifdef CONFIG_SND_HDA_HWDEP
struct snd_hwdep *hwdep; /* assigned hwdep device */
+ struct snd_array init_verbs; /* additional init verbs */
+ struct snd_array hints; /* additional hints */
+#endif
/* misc flags */
unsigned int spdif_status_reset :1; /* needs to toggle SPDIF for each
@@ -740,6 +793,10 @@ struct hda_codec {
int power_count; /* current (global) power refcount */
struct delayed_work power_work; /* delayed task for powerdown */
#endif
+
+ /* codec-specific additional proc output */
+ void (*proc_widget_hook)(struct snd_info_buffer *buffer,
+ struct hda_codec *codec, hda_nid_t nid);
};
/* direction */
@@ -754,7 +811,7 @@ enum {
int snd_hda_bus_new(struct snd_card *card, const struct hda_bus_template *temp,
struct hda_bus **busp);
int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
- struct hda_codec **codecp);
+ int do_init, struct hda_codec **codecp);
/*
* low level functions
@@ -799,11 +856,13 @@ void snd_hda_codec_resume_cache(struct hda_codec *codec);
* Mixer
*/
int snd_hda_build_controls(struct hda_bus *bus);
+int snd_hda_codec_build_controls(struct hda_codec *codec);
/*
* PCM
*/
int snd_hda_build_pcms(struct hda_bus *bus);
+int snd_hda_codec_build_pcms(struct hda_codec *codec);
void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
u32 stream_tag,
int channel_id, int format);
@@ -812,8 +871,6 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate,
unsigned int channels,
unsigned int format,
unsigned int maxbps);
-int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
- u32 *ratesp, u64 *formatsp, unsigned int *bpsp);
int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
unsigned int format);
@@ -831,18 +888,38 @@ int snd_hda_resume(struct hda_bus *bus);
#endif
/*
+ * get widget information
+ */
+const char *snd_hda_get_jack_connectivity(u32 cfg);
+const char *snd_hda_get_jack_type(u32 cfg);
+const char *snd_hda_get_jack_location(u32 cfg);
+
+/*
* power saving
*/
#ifdef CONFIG_SND_HDA_POWER_SAVE
void snd_hda_power_up(struct hda_codec *codec);
void snd_hda_power_down(struct hda_codec *codec);
#define snd_hda_codec_needs_resume(codec) codec->power_count
-int snd_hda_codecs_inuse(struct hda_bus *bus);
#else
static inline void snd_hda_power_up(struct hda_codec *codec) {}
static inline void snd_hda_power_down(struct hda_codec *codec) {}
#define snd_hda_codec_needs_resume(codec) 1
-#define snd_hda_codecs_inuse(bus) 1
+#endif
+
+/*
+ * Codec modularization
+ */
+
+/* Export symbols only for communication with codec drivers;
+ * When built in kernel, all HD-audio drivers are supposed to be statically
+ * linked to the kernel. Thus, the symbols don't have to (or shouldn't) be
+ * exported unless it's built as a module.
+ */
+#ifdef MODULE
+#define EXPORT_SYMBOL_HDA(sym) EXPORT_SYMBOL_GPL(sym)
+#else
+#define EXPORT_SYMBOL_HDA(sym)
#endif
#endif /* __SOUND_HDA_CODEC_H */
diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c
new file mode 100644
index 00000000000..fcad5ec3177
--- /dev/null
+++ b/sound/pci/hda/hda_eld.c
@@ -0,0 +1,590 @@
+/*
+ * Generic routines and proc interface for ELD(EDID Like Data) information
+ *
+ * Copyright(c) 2008 Intel Corporation.
+ *
+ * Authors:
+ * Wu Fengguang <wfg@linux.intel.com>
+ *
+ * This driver is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This driver is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/init.h>
+#include <sound/core.h>
+#include <asm/unaligned.h>
+#include "hda_codec.h"
+#include "hda_local.h"
+
+enum eld_versions {
+ ELD_VER_CEA_861D = 2,
+ ELD_VER_PARTIAL = 31,
+};
+
+enum cea_edid_versions {
+ CEA_EDID_VER_NONE = 0,
+ CEA_EDID_VER_CEA861 = 1,
+ CEA_EDID_VER_CEA861A = 2,
+ CEA_EDID_VER_CEA861BCD = 3,
+ CEA_EDID_VER_RESERVED = 4,
+};
+
+static char *cea_speaker_allocation_names[] = {
+ /* 0 */ "FL/FR",
+ /* 1 */ "LFE",
+ /* 2 */ "FC",
+ /* 3 */ "RL/RR",
+ /* 4 */ "RC",
+ /* 5 */ "FLC/FRC",
+ /* 6 */ "RLC/RRC",
+ /* 7 */ "FLW/FRW",
+ /* 8 */ "FLH/FRH",
+ /* 9 */ "TC",
+ /* 10 */ "FCH",
+};
+
+static char *eld_connection_type_names[4] = {
+ "HDMI",
+ "DisplayPort",
+ "2-reserved",
+ "3-reserved"
+};
+
+enum cea_audio_coding_types {
+ AUDIO_CODING_TYPE_REF_STREAM_HEADER = 0,
+ AUDIO_CODING_TYPE_LPCM = 1,
+ AUDIO_CODING_TYPE_AC3 = 2,
+ AUDIO_CODING_TYPE_MPEG1 = 3,
+ AUDIO_CODING_TYPE_MP3 = 4,
+ AUDIO_CODING_TYPE_MPEG2 = 5,
+ AUDIO_CODING_TYPE_AACLC = 6,
+ AUDIO_CODING_TYPE_DTS = 7,
+ AUDIO_CODING_TYPE_ATRAC = 8,
+ AUDIO_CODING_TYPE_SACD = 9,
+ AUDIO_CODING_TYPE_EAC3 = 10,
+ AUDIO_CODING_TYPE_DTS_HD = 11,
+ AUDIO_CODING_TYPE_MLP = 12,
+ AUDIO_CODING_TYPE_DST = 13,
+ AUDIO_CODING_TYPE_WMAPRO = 14,
+ AUDIO_CODING_TYPE_REF_CXT = 15,
+ /* also include valid xtypes below */
+ AUDIO_CODING_TYPE_HE_AAC = 15,
+ AUDIO_CODING_TYPE_HE_AAC2 = 16,
+ AUDIO_CODING_TYPE_MPEG_SURROUND = 17,
+};
+
+enum cea_audio_coding_xtypes {
+ AUDIO_CODING_XTYPE_HE_REF_CT = 0,
+ AUDIO_CODING_XTYPE_HE_AAC = 1,
+ AUDIO_CODING_XTYPE_HE_AAC2 = 2,
+ AUDIO_CODING_XTYPE_MPEG_SURROUND = 3,
+ AUDIO_CODING_XTYPE_FIRST_RESERVED = 4,
+};
+
+static char *cea_audio_coding_type_names[] = {
+ /* 0 */ "undefined",
+ /* 1 */ "LPCM",
+ /* 2 */ "AC-3",
+ /* 3 */ "MPEG1",
+ /* 4 */ "MP3",
+ /* 5 */ "MPEG2",
+ /* 6 */ "AAC-LC",
+ /* 7 */ "DTS",
+ /* 8 */ "ATRAC",
+ /* 9 */ "DSD (One Bit Audio)",
+ /* 10 */ "E-AC-3/DD+ (Dolby Digital Plus)",
+ /* 11 */ "DTS-HD",
+ /* 12 */ "MLP (Dolby TrueHD)",
+ /* 13 */ "DST",
+ /* 14 */ "WMAPro",
+ /* 15 */ "HE-AAC",
+ /* 16 */ "HE-AACv2",
+ /* 17 */ "MPEG Surround",
+};
+
+/*
+ * The following two lists are shared between
+ * - HDMI audio InfoFrame (source to sink)
+ * - CEA E-EDID Extension (sink to source)
+ */
+
+/*
+ * SS1:SS0 index => sample size
+ */
+static int cea_sample_sizes[4] = {
+ 0, /* 0: Refer to Stream Header */
+ AC_SUPPCM_BITS_16, /* 1: 16 bits */
+ AC_SUPPCM_BITS_20, /* 2: 20 bits */
+ AC_SUPPCM_BITS_24, /* 3: 24 bits */
+};
+
+/*
+ * SF2:SF1:SF0 index => sampling frequency
+ */
+static int cea_sampling_frequencies[8] = {
+ 0, /* 0: Refer to Stream Header */
+ SNDRV_PCM_RATE_32000, /* 1: 32000Hz */
+ SNDRV_PCM_RATE_44100, /* 2: 44100Hz */
+ SNDRV_PCM_RATE_48000, /* 3: 48000Hz */
+ SNDRV_PCM_RATE_88200, /* 4: 88200Hz */
+ SNDRV_PCM_RATE_96000, /* 5: 96000Hz */
+ SNDRV_PCM_RATE_176400, /* 6: 176400Hz */
+ SNDRV_PCM_RATE_192000, /* 7: 192000Hz */
+};
+
+static unsigned char hdmi_get_eld_byte(struct hda_codec *codec, hda_nid_t nid,
+ int byte_index)
+{
+ unsigned int val;
+
+ val = snd_hda_codec_read(codec, nid, 0,
+ AC_VERB_GET_HDMI_ELDD, byte_index);
+
+#ifdef BE_PARANOID
+ printk(KERN_INFO "HDMI: ELD data byte %d: 0x%x\n", byte_index, val);
+#endif
+
+ if ((val & AC_ELDD_ELD_VALID) == 0) {
+ snd_printd(KERN_INFO "HDMI: invalid ELD data byte %d\n",
+ byte_index);
+ val = 0;
+ }
+
+ return val & AC_ELDD_ELD_DATA;
+}
+
+#define GRAB_BITS(buf, byte, lowbit, bits) \
+({ \
+ BUILD_BUG_ON(lowbit > 7); \
+ BUILD_BUG_ON(bits > 8); \
+ BUILD_BUG_ON(bits <= 0); \
+ \
+ (buf[byte] >> (lowbit)) & ((1 << (bits)) - 1); \
+})
+
+static void hdmi_update_short_audio_desc(struct cea_sad *a,
+ const unsigned char *buf)
+{
+ int i;
+ int val;
+
+ val = GRAB_BITS(buf, 1, 0, 7);
+ a->rates = 0;
+ for (i = 0; i < 7; i++)
+ if (val & (1 << i))
+ a->rates |= cea_sampling_frequencies[i + 1];
+
+ a->channels = GRAB_BITS(buf, 0, 0, 3);
+ a->channels++;
+
+ a->format = GRAB_BITS(buf, 0, 3, 4);
+ switch (a->format) {
+ case AUDIO_CODING_TYPE_REF_STREAM_HEADER:
+ snd_printd(KERN_INFO
+ "HDMI: audio coding type 0 not expected\n");
+ break;
+
+ case AUDIO_CODING_TYPE_LPCM:
+ val = GRAB_BITS(buf, 2, 0, 3);
+ a->sample_bits = 0;
+ for (i = 0; i < 3; i++)
+ if (val & (1 << i))
+ a->sample_bits |= cea_sample_sizes[i + 1];
+ break;
+
+ case AUDIO_CODING_TYPE_AC3:
+ case AUDIO_CODING_TYPE_MPEG1:
+ case AUDIO_CODING_TYPE_MP3:
+ case AUDIO_CODING_TYPE_MPEG2:
+ case AUDIO_CODING_TYPE_AACLC:
+ case AUDIO_CODING_TYPE_DTS:
+ case AUDIO_CODING_TYPE_ATRAC:
+ a->max_bitrate = GRAB_BITS(buf, 2, 0, 8);
+ a->max_bitrate *= 8000;
+ break;
+
+ case AUDIO_CODING_TYPE_SACD:
+ break;
+
+ case AUDIO_CODING_TYPE_EAC3:
+ break;
+
+ case AUDIO_CODING_TYPE_DTS_HD:
+ break;
+
+ case AUDIO_CODING_TYPE_MLP:
+ break;
+
+ case AUDIO_CODING_TYPE_DST:
+ break;
+
+ case AUDIO_CODING_TYPE_WMAPRO:
+ a->profile = GRAB_BITS(buf, 2, 0, 3);
+ break;
+
+ case AUDIO_CODING_TYPE_REF_CXT:
+ a->format = GRAB_BITS(buf, 2, 3, 5);
+ if (a->format == AUDIO_CODING_XTYPE_HE_REF_CT ||
+ a->format >= AUDIO_CODING_XTYPE_FIRST_RESERVED) {
+ snd_printd(KERN_INFO
+ "HDMI: audio coding xtype %d not expected\n",
+ a->format);
+ a->format = 0;
+ } else
+ a->format += AUDIO_CODING_TYPE_HE_AAC -
+ AUDIO_CODING_XTYPE_HE_AAC;
+ break;
+ }
+}
+
+/*
+ * Be careful, ELD buf could be totally rubbish!
+ */
+static int hdmi_update_eld(struct hdmi_eld *e,
+ const unsigned char *buf, int size)
+{
+ int mnl;
+ int i;
+
+ e->eld_ver = GRAB_BITS(buf, 0, 3, 5);
+ if (e->eld_ver != ELD_VER_CEA_861D &&
+ e->eld_ver != ELD_VER_PARTIAL) {
+ snd_printd(KERN_INFO "HDMI: Unknown ELD version %d\n",
+ e->eld_ver);
+ goto out_fail;
+ }
+
+ e->eld_size = size;
+ e->baseline_len = GRAB_BITS(buf, 2, 0, 8);
+ mnl = GRAB_BITS(buf, 4, 0, 5);
+ e->cea_edid_ver = GRAB_BITS(buf, 4, 5, 3);
+
+ e->support_hdcp = GRAB_BITS(buf, 5, 0, 1);
+ e->support_ai = GRAB_BITS(buf, 5, 1, 1);
+ e->conn_type = GRAB_BITS(buf, 5, 2, 2);
+ e->sad_count = GRAB_BITS(buf, 5, 4, 4);
+
+ e->aud_synch_delay = GRAB_BITS(buf, 6, 0, 8) * 2;
+ e->spk_alloc = GRAB_BITS(buf, 7, 0, 7);
+
+ e->port_id = get_unaligned_le64(buf + 8);
+
+ /* not specified, but the spec's tendency is little endian */
+ e->manufacture_id = get_unaligned_le16(buf + 16);
+ e->product_id = get_unaligned_le16(buf + 18);
+
+ if (mnl > ELD_MAX_MNL) {
+ snd_printd(KERN_INFO "HDMI: MNL is reserved value %d\n", mnl);
+ goto out_fail;
+ } else if (ELD_FIXED_BYTES + mnl > size) {
+ snd_printd(KERN_INFO "HDMI: out of range MNL %d\n", mnl);
+ goto out_fail;
+ } else
+ strlcpy(e->monitor_name, buf + ELD_FIXED_BYTES, mnl);
+
+ for (i = 0; i < e->sad_count; i++) {
+ if (ELD_FIXED_BYTES + mnl + 3 * (i + 1) > size) {
+ snd_printd(KERN_INFO "HDMI: out of range SAD %d\n", i);
+ goto out_fail;
+ }
+ hdmi_update_short_audio_desc(e->sad + i,
+ buf + ELD_FIXED_BYTES + mnl + 3 * i);
+ }
+
+ return 0;
+
+out_fail:
+ e->eld_ver = 0;
+ return -EINVAL;
+}
+
+static int hdmi_present_sense(struct hda_codec *codec, hda_nid_t nid)
+{
+ return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_SENSE, 0);
+}
+
+static int hdmi_eld_valid(struct hda_codec *codec, hda_nid_t nid)
+{
+ int eldv;
+ int present;
+
+ present = hdmi_present_sense(codec, nid);
+ eldv = (present & AC_PINSENSE_ELDV);
+ present = (present & AC_PINSENSE_PRESENCE);
+
+#ifdef CONFIG_SND_DEBUG_VERBOSE
+ printk(KERN_INFO "HDMI: sink_present = %d, eld_valid = %d\n",
+ !!present, !!eldv);
+#endif
+
+ return eldv && present;
+}
+
+int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid)
+{
+ return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_SIZE,
+ AC_DIPSIZE_ELD_BUF);
+}
+
+int snd_hdmi_get_eld(struct hdmi_eld *eld,
+ struct hda_codec *codec, hda_nid_t nid)
+{
+ int i;
+ int ret;
+ int size;
+ unsigned char *buf;
+
+ if (!hdmi_eld_valid(codec, nid))
+ return -ENOENT;
+
+ size = snd_hdmi_get_eld_size(codec, nid);
+ if (size == 0) {
+ /* wfg: workaround for ASUS P5E-VM HDMI board */
+ snd_printd(KERN_INFO "HDMI: ELD buf size is 0, force 128\n");
+ size = 128;
+ }
+ if (size < ELD_FIXED_BYTES || size > PAGE_SIZE) {
+ snd_printd(KERN_INFO "HDMI: invalid ELD buf size %d\n", size);
+ return -ERANGE;
+ }
+
+ buf = kmalloc(size, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ for (i = 0; i < size; i++)
+ buf[i] = hdmi_get_eld_byte(codec, nid, i);
+
+ ret = hdmi_update_eld(eld, buf, size);
+
+ kfree(buf);
+ return ret;
+}
+
+static void hdmi_show_short_audio_desc(struct cea_sad *a)
+{
+ char buf[SND_PRINT_RATES_ADVISED_BUFSIZE];
+ char buf2[8 + SND_PRINT_BITS_ADVISED_BUFSIZE] = ", bits =";
+
+ if (!a->format)
+ return;
+
+ snd_print_pcm_rates(a->rates, buf, sizeof(buf));
+
+ if (a->format == AUDIO_CODING_TYPE_LPCM)
+ snd_print_pcm_bits(a->sample_bits, buf2 + 8, sizeof(buf2 - 8));
+ else if (a->max_bitrate)
+ snprintf(buf2, sizeof(buf2),
+ ", max bitrate = %d", a->max_bitrate);
+ else
+ buf2[0] = '\0';
+
+ printk(KERN_INFO "HDMI: supports coding type %s:"
+ " channels = %d, rates =%s%s\n",
+ cea_audio_coding_type_names[a->format],
+ a->channels,
+ buf,
+ buf2);
+}
+
+void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen)
+{
+ int i, j;
+
+ for (i = 0, j = 0; i < ARRAY_SIZE(cea_speaker_allocation_names); i++) {
+ if (spk_alloc & (1 << i))
+ j += snprintf(buf + j, buflen - j, " %s",
+ cea_speaker_allocation_names[i]);
+ }
+ buf[j] = '\0'; /* necessary when j == 0 */
+}
+
+void snd_hdmi_show_eld(struct hdmi_eld *e)
+{
+ int i;
+
+ printk(KERN_INFO "HDMI: detected monitor %s at connection type %s\n",
+ e->monitor_name,
+ eld_connection_type_names[e->conn_type]);
+
+ if (e->spk_alloc) {
+ char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
+ snd_print_channel_allocation(e->spk_alloc, buf, sizeof(buf));
+ printk(KERN_INFO "HDMI: available speakers:%s\n", buf);
+ }
+
+ for (i = 0; i < e->sad_count; i++)
+ hdmi_show_short_audio_desc(e->sad + i);
+}
+
+#ifdef CONFIG_PROC_FS
+
+static void hdmi_print_sad_info(int i, struct cea_sad *a,
+ struct snd_info_buffer *buffer)
+{
+ char buf[SND_PRINT_RATES_ADVISED_BUFSIZE];
+
+ snd_iprintf(buffer, "sad%d_coding_type\t[0x%x] %s\n",
+ i, a->format, cea_audio_coding_type_names[a->format]);
+ snd_iprintf(buffer, "sad%d_channels\t\t%d\n", i, a->channels);
+
+ snd_print_pcm_rates(a->rates, buf, sizeof(buf));
+ snd_iprintf(buffer, "sad%d_rates\t\t[0x%x]%s\n", i, a->rates, buf);
+
+ if (a->format == AUDIO_CODING_TYPE_LPCM) {
+ snd_print_pcm_bits(a->sample_bits, buf, sizeof(buf));
+ snd_iprintf(buffer, "sad%d_bits\t\t[0x%x]%s\n",
+ i, a->sample_bits, buf);
+ }
+
+ if (a->max_bitrate)
+ snd_iprintf(buffer, "sad%d_max_bitrate\t%d\n",
+ i, a->max_bitrate);
+
+ if (a->profile)
+ snd_iprintf(buffer, "sad%d_profile\t\t%d\n", i, a->profile);
+}
+
+static void hdmi_print_eld_info(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
+{
+ struct hdmi_eld *e = entry->private_data;
+ char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
+ int i;
+ static char *eld_versoin_names[32] = {
+ "reserved",
+ "reserved",
+ "CEA-861D or below",
+ [3 ... 30] = "reserved",
+ [31] = "partial"
+ };
+ static char *cea_edid_version_names[8] = {
+ "no CEA EDID Timing Extension block present",
+ "CEA-861",
+ "CEA-861-A",
+ "CEA-861-B, C or D",
+ [4 ... 7] = "reserved"
+ };
+
+ snd_iprintf(buffer, "monitor_name\t\t%s\n", e->monitor_name);
+ snd_iprintf(buffer, "connection_type\t\t%s\n",
+ eld_connection_type_names[e->conn_type]);
+ snd_iprintf(buffer, "eld_version\t\t[0x%x] %s\n", e->eld_ver,
+ eld_versoin_names[e->eld_ver]);
+ snd_iprintf(buffer, "edid_version\t\t[0x%x] %s\n", e->cea_edid_ver,
+ cea_edid_version_names[e->cea_edid_ver]);
+ snd_iprintf(buffer, "manufacture_id\t\t0x%x\n", e->manufacture_id);
+ snd_iprintf(buffer, "product_id\t\t0x%x\n", e->product_id);
+ snd_iprintf(buffer, "port_id\t\t\t0x%llx\n", (long long)e->port_id);
+ snd_iprintf(buffer, "support_hdcp\t\t%d\n", e->support_hdcp);
+ snd_iprintf(buffer, "support_ai\t\t%d\n", e->support_ai);
+ snd_iprintf(buffer, "audio_sync_delay\t%d\n", e->aud_synch_delay);
+
+ snd_print_channel_allocation(e->spk_alloc, buf, sizeof(buf));
+ snd_iprintf(buffer, "speakers\t\t[0x%x]%s\n", e->spk_alloc, buf);
+
+ snd_iprintf(buffer, "sad_count\t\t%d\n", e->sad_count);
+
+ for (i = 0; i < e->sad_count; i++)
+ hdmi_print_sad_info(i, e->sad + i, buffer);
+}
+
+static void hdmi_write_eld_info(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
+{
+ struct hdmi_eld *e = entry->private_data;
+ char line[64];
+ char name[64];
+ char *sname;
+ long long val;
+ int n;
+
+ while (!snd_info_get_line(buffer, line, sizeof(line))) {
+ if (sscanf(line, "%s %llx", name, &val) != 2)
+ continue;
+ /*
+ * We don't allow modification to these fields:
+ * monitor_name manufacture_id product_id
+ * eld_version edid_version
+ */
+ if (!strcmp(name, "connection_type"))
+ e->conn_type = val;
+ else if (!strcmp(name, "port_id"))
+ e->port_id = val;
+ else if (!strcmp(name, "support_hdcp"))
+ e->support_hdcp = val;
+ else if (!strcmp(name, "support_ai"))
+ e->support_ai = val;
+ else if (!strcmp(name, "audio_sync_delay"))
+ e->aud_synch_delay = val;
+ else if (!strcmp(name, "speakers"))
+ e->spk_alloc = val;
+ else if (!strcmp(name, "sad_count"))
+ e->sad_count = val;
+ else if (!strncmp(name, "sad", 3)) {
+ sname = name + 4;
+ n = name[3] - '0';
+ if (name[4] >= '0' && name[4] <= '9') {
+ sname++;
+ n = 10 * n + name[4] - '0';
+ }
+ if (n < 0 || n > 31) /* double the CEA limit */
+ continue;
+ if (!strcmp(sname, "_coding_type"))
+ e->sad[n].format = val;
+ else if (!strcmp(sname, "_channels"))
+ e->sad[n].channels = val;
+ else if (!strcmp(sname, "_rates"))
+ e->sad[n].rates = val;
+ else if (!strcmp(sname, "_bits"))
+ e->sad[n].sample_bits = val;
+ else if (!strcmp(sname, "_max_bitrate"))
+ e->sad[n].max_bitrate = val;
+ else if (!strcmp(sname, "_profile"))
+ e->sad[n].profile = val;
+ if (n >= e->sad_count)
+ e->sad_count = n + 1;
+ }
+ }
+}
+
+
+int snd_hda_eld_proc_new(struct hda_codec *codec, struct hdmi_eld *eld)
+{
+ char name[32];
+ struct snd_info_entry *entry;
+ int err;
+
+ snprintf(name, sizeof(name), "eld#%d", codec->addr);
+ err = snd_card_proc_new(codec->bus->card, name, &entry);
+ if (err < 0)
+ return err;
+
+ snd_info_set_text_ops(entry, eld, hdmi_print_eld_info);
+ entry->c.text.write = hdmi_write_eld_info;
+ entry->mode |= S_IWUSR;
+ eld->proc_entry = entry;
+
+ return 0;
+}
+
+void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld)
+{
+ if (!codec->bus->shutdown && eld->proc_entry) {
+ snd_device_free(codec->bus->card, eld->proc_entry);
+ eld->proc_entry = NULL;
+ }
+}
+
+#endif /* CONFIG_PROC_FS */
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index 0ca30894f7c..65745e96dc7 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -723,7 +723,8 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node,
if (is_loopback)
add_input_loopback(codec, node->nid, HDA_INPUT, index);
snd_printdd("[%s] NID=0x%x, DIR=IN, IDX=0x%x\n", name, node->nid, index);
- if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0)
+ err = snd_hda_ctl_add(codec, snd_ctl_new1(&knew, codec));
+ if (err < 0)
return err;
created = 1;
} else if ((node->wid_caps & AC_WCAP_OUT_AMP) &&
@@ -732,7 +733,8 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node,
if (is_loopback)
add_input_loopback(codec, node->nid, HDA_OUTPUT, 0);
snd_printdd("[%s] NID=0x%x, DIR=OUT\n", name, node->nid);
- if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0)
+ err = snd_hda_ctl_add(codec, snd_ctl_new1(&knew, codec));
+ if (err < 0)
return err;
created = 1;
}
@@ -745,14 +747,16 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node,
(node->amp_in_caps & AC_AMPCAP_NUM_STEPS)) {
knew = (struct snd_kcontrol_new)HDA_CODEC_VOLUME(name, node->nid, index, HDA_INPUT);
snd_printdd("[%s] NID=0x%x, DIR=IN, IDX=0x%x\n", name, node->nid, index);
- if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0)
+ err = snd_hda_ctl_add(codec, snd_ctl_new1(&knew, codec));
+ if (err < 0)
return err;
created = 1;
} else if ((node->wid_caps & AC_WCAP_OUT_AMP) &&
(node->amp_out_caps & AC_AMPCAP_NUM_STEPS)) {
knew = (struct snd_kcontrol_new)HDA_CODEC_VOLUME(name, node->nid, 0, HDA_OUTPUT);
snd_printdd("[%s] NID=0x%x, DIR=OUT\n", name, node->nid);
- if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0)
+ err = snd_hda_ctl_add(codec, snd_ctl_new1(&knew, codec));
+ if (err < 0)
return err;
created = 1;
}
@@ -849,8 +853,8 @@ static int build_input_controls(struct hda_codec *codec)
}
/* create input MUX if multiple sources are available */
- if ((err = snd_ctl_add(codec->bus->card,
- snd_ctl_new1(&cap_sel, codec))) < 0)
+ err = snd_hda_ctl_add(codec, snd_ctl_new1(&cap_sel, codec));
+ if (err < 0)
return err;
/* no volume control? */
@@ -867,8 +871,8 @@ static int build_input_controls(struct hda_codec *codec)
HDA_CODEC_VOLUME(name, adc_node->nid,
spec->input_mux.items[i].index,
HDA_INPUT);
- if ((err = snd_ctl_add(codec->bus->card,
- snd_ctl_new1(&knew, codec))) < 0)
+ err = snd_hda_ctl_add(codec, snd_ctl_new1(&knew, codec));
+ if (err < 0)
return err;
}
@@ -1097,3 +1101,4 @@ int snd_hda_parse_generic_codec(struct hda_codec *codec)
snd_hda_generic_free(codec);
return err;
}
+EXPORT_SYMBOL(snd_hda_parse_generic_codec);
diff --git a/sound/pci/hda/hda_hwdep.c b/sound/pci/hda/hda_hwdep.c
index 6e18a422d99..300ab407cf4 100644
--- a/sound/pci/hda/hda_hwdep.c
+++ b/sound/pci/hda/hda_hwdep.c
@@ -23,10 +23,12 @@
#include <linux/pci.h>
#include <linux/compat.h>
#include <linux/mutex.h>
+#include <linux/ctype.h>
#include <sound/core.h>
#include "hda_codec.h"
#include "hda_local.h"
#include <sound/hda_hwdep.h>
+#include <sound/minors.h>
/*
* write/read an out-of-bound verb
@@ -95,7 +97,26 @@ static int hda_hwdep_open(struct snd_hwdep *hw, struct file *file)
return 0;
}
-int __devinit snd_hda_create_hwdep(struct hda_codec *codec)
+static void clear_hwdep_elements(struct hda_codec *codec)
+{
+ char **head;
+ int i;
+
+ /* clear init verbs */
+ snd_array_free(&codec->init_verbs);
+ /* clear hints */
+ head = codec->hints.list;
+ for (i = 0; i < codec->hints.used; i++, head++)
+ kfree(*head);
+ snd_array_free(&codec->hints);
+}
+
+static void hwdep_free(struct snd_hwdep *hwdep)
+{
+ clear_hwdep_elements(hwdep->private_data);
+}
+
+int /*__devinit*/ snd_hda_create_hwdep(struct hda_codec *codec)
{
char hwname[16];
struct snd_hwdep *hwdep;
@@ -109,6 +130,7 @@ int __devinit snd_hda_create_hwdep(struct hda_codec *codec)
sprintf(hwdep->name, "HDA Codec %d", codec->addr);
hwdep->iface = SNDRV_HWDEP_IFACE_HDA;
hwdep->private_data = codec;
+ hwdep->private_free = hwdep_free;
hwdep->exclusive = 1;
hwdep->ops.open = hda_hwdep_open;
@@ -117,5 +139,215 @@ int __devinit snd_hda_create_hwdep(struct hda_codec *codec)
hwdep->ops.ioctl_compat = hda_hwdep_ioctl_compat;
#endif
+ snd_array_init(&codec->init_verbs, sizeof(struct hda_verb), 32);
+ snd_array_init(&codec->hints, sizeof(char *), 32);
+
return 0;
}
+
+#ifdef CONFIG_SND_HDA_RECONFIG
+
+/*
+ * sysfs interface
+ */
+
+static int clear_codec(struct hda_codec *codec)
+{
+ snd_hda_codec_reset(codec);
+ clear_hwdep_elements(codec);
+ return 0;
+}
+
+static int reconfig_codec(struct hda_codec *codec)
+{
+ int err;
+
+ snd_printk(KERN_INFO "hda-codec: reconfiguring\n");
+ snd_hda_codec_reset(codec);
+ err = snd_hda_codec_configure(codec);
+ if (err < 0)
+ return err;
+ /* rebuild PCMs */
+ err = snd_hda_codec_build_pcms(codec);
+ if (err < 0)
+ return err;
+ /* rebuild mixers */
+ err = snd_hda_codec_build_controls(codec);
+ if (err < 0)
+ return err;
+ return 0;
+}
+
+/*
+ * allocate a string at most len chars, and remove the trailing EOL
+ */
+static char *kstrndup_noeol(const char *src, size_t len)
+{
+ char *s = kstrndup(src, len, GFP_KERNEL);
+ char *p;
+ if (!s)
+ return NULL;
+ p = strchr(s, '\n');
+ if (p)
+ *p = 0;
+ return s;
+}
+
+#define CODEC_INFO_SHOW(type) \
+static ssize_t type##_show(struct device *dev, \
+ struct device_attribute *attr, \
+ char *buf) \
+{ \
+ struct snd_hwdep *hwdep = dev_get_drvdata(dev); \
+ struct hda_codec *codec = hwdep->private_data; \
+ return sprintf(buf, "0x%x\n", codec->type); \
+}
+
+#define CODEC_INFO_STR_SHOW(type) \
+static ssize_t type##_show(struct device *dev, \
+ struct device_attribute *attr, \
+ char *buf) \
+{ \
+ struct snd_hwdep *hwdep = dev_get_drvdata(dev); \
+ struct hda_codec *codec = hwdep->private_data; \
+ return sprintf(buf, "%s\n", \
+ codec->type ? codec->type : ""); \
+}
+
+CODEC_INFO_SHOW(vendor_id);
+CODEC_INFO_SHOW(subsystem_id);
+CODEC_INFO_SHOW(revision_id);
+CODEC_INFO_SHOW(afg);
+CODEC_INFO_SHOW(mfg);
+CODEC_INFO_STR_SHOW(name);
+CODEC_INFO_STR_SHOW(modelname);
+
+#define CODEC_INFO_STORE(type) \
+static ssize_t type##_store(struct device *dev, \
+ struct device_attribute *attr, \
+ const char *buf, size_t count) \
+{ \
+ struct snd_hwdep *hwdep = dev_get_drvdata(dev); \
+ struct hda_codec *codec = hwdep->private_data; \
+ char *after; \
+ codec->type = simple_strtoul(buf, &after, 0); \
+ return count; \
+}
+
+#define CODEC_INFO_STR_STORE(type) \
+static ssize_t type##_store(struct device *dev, \
+ struct device_attribute *attr, \
+ const char *buf, size_t count) \
+{ \
+ struct snd_hwdep *hwdep = dev_get_drvdata(dev); \
+ struct hda_codec *codec = hwdep->private_data; \
+ char *s = kstrndup_noeol(buf, 64); \
+ if (!s) \
+ return -ENOMEM; \
+ kfree(codec->type); \
+ codec->type = s; \
+ return count; \
+}
+
+CODEC_INFO_STORE(vendor_id);
+CODEC_INFO_STORE(subsystem_id);
+CODEC_INFO_STORE(revision_id);
+CODEC_INFO_STR_STORE(name);
+CODEC_INFO_STR_STORE(modelname);
+
+#define CODEC_ACTION_STORE(type) \
+static ssize_t type##_store(struct device *dev, \
+ struct device_attribute *attr, \
+ const char *buf, size_t count) \
+{ \
+ struct snd_hwdep *hwdep = dev_get_drvdata(dev); \
+ struct hda_codec *codec = hwdep->private_data; \
+ int err = 0; \
+ if (*buf) \
+ err = type##_codec(codec); \
+ return err < 0 ? err : count; \
+}
+
+CODEC_ACTION_STORE(reconfig);
+CODEC_ACTION_STORE(clear);
+
+static ssize_t init_verbs_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct snd_hwdep *hwdep = dev_get_drvdata(dev);
+ struct hda_codec *codec = hwdep->private_data;
+ char *p;
+ struct hda_verb verb, *v;
+
+ verb.nid = simple_strtoul(buf, &p, 0);
+ verb.verb = simple_strtoul(p, &p, 0);
+ verb.param = simple_strtoul(p, &p, 0);
+ if (!verb.nid || !verb.verb || !verb.param)
+ return -EINVAL;
+ v = snd_array_new(&codec->init_verbs);
+ if (!v)
+ return -ENOMEM;
+ *v = verb;
+ return count;
+}
+
+static ssize_t hints_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct snd_hwdep *hwdep = dev_get_drvdata(dev);
+ struct hda_codec *codec = hwdep->private_data;
+ char *p;
+ char **hint;
+
+ if (!*buf || isspace(*buf) || *buf == '#' || *buf == '\n')
+ return count;
+ p = kstrndup_noeol(buf, 1024);
+ if (!p)
+ return -ENOMEM;
+ hint = snd_array_new(&codec->hints);
+ if (!hint) {
+ kfree(p);
+ return -ENOMEM;
+ }
+ *hint = p;
+ return count;
+}
+
+#define CODEC_ATTR_RW(type) \
+ __ATTR(type, 0644, type##_show, type##_store)
+#define CODEC_ATTR_RO(type) \
+ __ATTR_RO(type)
+#define CODEC_ATTR_WO(type) \
+ __ATTR(type, 0200, NULL, type##_store)
+
+static struct device_attribute codec_attrs[] = {
+ CODEC_ATTR_RW(vendor_id),
+ CODEC_ATTR_RW(subsystem_id),
+ CODEC_ATTR_RW(revision_id),
+ CODEC_ATTR_RO(afg),
+ CODEC_ATTR_RO(mfg),
+ CODEC_ATTR_RW(name),
+ CODEC_ATTR_RW(modelname),
+ CODEC_ATTR_WO(init_verbs),
+ CODEC_ATTR_WO(hints),
+ CODEC_ATTR_WO(reconfig),
+ CODEC_ATTR_WO(clear),
+};
+
+/*
+ * create sysfs files on hwdep directory
+ */
+int snd_hda_hwdep_add_sysfs(struct hda_codec *codec)
+{
+ struct snd_hwdep *hwdep = codec->hwdep;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(codec_attrs); i++)
+ snd_add_device_sysfs_file(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card,
+ hwdep->device, &codec_attrs[i]);
+ return 0;
+}
+
+#endif /* CONFIG_SND_HDA_RECONFIG */
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 35722ec920c..f04de115ee1 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -58,6 +58,7 @@ static char *model[SNDRV_CARDS];
static int position_fix[SNDRV_CARDS];
static int bdl_pos_adj[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1};
static int probe_mask[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1};
+static int probe_only[SNDRV_CARDS];
static int single_cmd;
static int enable_msi;
@@ -76,6 +77,8 @@ module_param_array(bdl_pos_adj, int, NULL, 0644);
MODULE_PARM_DESC(bdl_pos_adj, "BDL position adjustment offset.");
module_param_array(probe_mask, int, NULL, 0444);
MODULE_PARM_DESC(probe_mask, "Bitmask to probe codecs (default = -1).");
+module_param_array(probe_only, bool, NULL, 0444);
+MODULE_PARM_DESC(probe_only, "Only probing and no codec initialization.");
module_param(single_cmd, bool, 0444);
MODULE_PARM_DESC(single_cmd, "Use single command to communicate with codecs "
"(for debugging only).");
@@ -83,7 +86,10 @@ module_param(enable_msi, int, 0444);
MODULE_PARM_DESC(enable_msi, "Enable Message Signaled Interrupt (MSI)");
#ifdef CONFIG_SND_HDA_POWER_SAVE
-/* power_save option is defined in hda_codec.c */
+static int power_save = CONFIG_SND_HDA_POWER_SAVE_DEFAULT;
+module_param(power_save, int, 0644);
+MODULE_PARM_DESC(power_save, "Automatic power-saving timeout "
+ "(in second, 0 = disable).");
/* reset the HD-audio controller in power save mode.
* this may give more power-saving, but will take longer time to
@@ -292,6 +298,8 @@ enum {
/* Define VIA HD Audio Device ID*/
#define VIA_HDAC_DEVICE_ID 0x3288
+/* HD Audio class code */
+#define PCI_CLASS_MULTIMEDIA_HD_AUDIO 0x0403
/*
*/
@@ -392,6 +400,7 @@ struct azx {
unsigned int msi :1;
unsigned int irq_pending_warned :1;
unsigned int via_dmapos_patch :1; /* enable DMA-position fix for VIA */
+ unsigned int probing :1; /* codec probing phase */
/* for debugging */
unsigned int last_cmd; /* last issued command (to sync) */
@@ -414,6 +423,7 @@ enum {
AZX_DRIVER_ULI,
AZX_DRIVER_NVIDIA,
AZX_DRIVER_TERA,
+ AZX_DRIVER_GENERIC,
AZX_NUM_DRIVERS, /* keep this as last entry */
};
@@ -427,6 +437,7 @@ static char *driver_short_names[] __devinitdata = {
[AZX_DRIVER_ULI] = "HDA ULI M5461",
[AZX_DRIVER_NVIDIA] = "HDA NVidia",
[AZX_DRIVER_TERA] = "HDA Teradici",
+ [AZX_DRIVER_GENERIC] = "HD-Audio Generic",
};
/*
@@ -527,9 +538,9 @@ static void azx_free_cmd_io(struct azx *chip)
}
/* send a command */
-static int azx_corb_send_cmd(struct hda_codec *codec, u32 val)
+static int azx_corb_send_cmd(struct hda_bus *bus, u32 val)
{
- struct azx *chip = codec->bus->private_data;
+ struct azx *chip = bus->private_data;
unsigned int wp;
/* add command to corb */
@@ -577,9 +588,9 @@ static void azx_update_rirb(struct azx *chip)
}
/* receive a response */
-static unsigned int azx_rirb_get_response(struct hda_codec *codec)
+static unsigned int azx_rirb_get_response(struct hda_bus *bus)
{
- struct azx *chip = codec->bus->private_data;
+ struct azx *chip = bus->private_data;
unsigned long timeout;
again:
@@ -596,7 +607,7 @@ static unsigned int azx_rirb_get_response(struct hda_codec *codec)
}
if (time_after(jiffies, timeout))
break;
- if (codec->bus->needs_damn_long_delay)
+ if (bus->needs_damn_long_delay)
msleep(2); /* temporary workaround */
else {
udelay(10);
@@ -624,6 +635,14 @@ static unsigned int azx_rirb_get_response(struct hda_codec *codec)
goto again;
}
+ if (chip->probing) {
+ /* If this critical timeout happens during the codec probing
+ * phase, this is likely an access to a non-existing codec
+ * slot. Better to return an error and reset the system.
+ */
+ return -1;
+ }
+
snd_printk(KERN_ERR "hda_intel: azx_get_response timeout, "
"switching to single_cmd mode: last cmd=0x%08x\n",
chip->last_cmd);
@@ -646,9 +665,9 @@ static unsigned int azx_rirb_get_response(struct hda_codec *codec)
*/
/* send a command */
-static int azx_single_send_cmd(struct hda_codec *codec, u32 val)
+static int azx_single_send_cmd(struct hda_bus *bus, u32 val)
{
- struct azx *chip = codec->bus->private_data;
+ struct azx *chip = bus->private_data;
int timeout = 50;
while (timeout--) {
@@ -671,9 +690,9 @@ static int azx_single_send_cmd(struct hda_codec *codec, u32 val)
}
/* receive a response */
-static unsigned int azx_single_get_response(struct hda_codec *codec)
+static unsigned int azx_single_get_response(struct hda_bus *bus)
{
- struct azx *chip = codec->bus->private_data;
+ struct azx *chip = bus->private_data;
int timeout = 50;
while (timeout--) {
@@ -696,38 +715,29 @@ static unsigned int azx_single_get_response(struct hda_codec *codec)
*/
/* send a command */
-static int azx_send_cmd(struct hda_codec *codec, hda_nid_t nid,
- int direct, unsigned int verb,
- unsigned int para)
+static int azx_send_cmd(struct hda_bus *bus, unsigned int val)
{
- struct azx *chip = codec->bus->private_data;
- u32 val;
-
- val = (u32)(codec->addr & 0x0f) << 28;
- val |= (u32)direct << 27;
- val |= (u32)nid << 20;
- val |= verb << 8;
- val |= para;
- chip->last_cmd = val;
+ struct azx *chip = bus->private_data;
+ chip->last_cmd = val;
if (chip->single_cmd)
- return azx_single_send_cmd(codec, val);
+ return azx_single_send_cmd(bus, val);
else
- return azx_corb_send_cmd(codec, val);
+ return azx_corb_send_cmd(bus, val);
}
/* get a response */
-static unsigned int azx_get_response(struct hda_codec *codec)
+static unsigned int azx_get_response(struct hda_bus *bus)
{
- struct azx *chip = codec->bus->private_data;
+ struct azx *chip = bus->private_data;
if (chip->single_cmd)
- return azx_single_get_response(codec);
+ return azx_single_get_response(bus);
else
- return azx_rirb_get_response(codec);
+ return azx_rirb_get_response(bus);
}
#ifdef CONFIG_SND_HDA_POWER_SAVE
-static void azx_power_notify(struct hda_codec *codec);
+static void azx_power_notify(struct hda_bus *bus);
#endif
/* reset codec link */
@@ -1184,6 +1194,28 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
return 0;
}
+/*
+ * Probe the given codec address
+ */
+static int probe_codec(struct azx *chip, int addr)
+{
+ unsigned int cmd = (addr << 28) | (AC_NODE_ROOT << 20) |
+ (AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID;
+ unsigned int res;
+
+ chip->probing = 1;
+ azx_send_cmd(chip->bus, cmd);
+ res = azx_get_response(chip->bus);
+ chip->probing = 0;
+ if (res == -1)
+ return -EIO;
+ snd_printdd("hda_intel: codec #%d probed OK\n", addr);
+ return 0;
+}
+
+static int azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec,
+ struct hda_pcm *cpcm);
+static void azx_stop_chip(struct azx *chip);
/*
* Codec initialization
@@ -1194,21 +1226,13 @@ static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] __devinitdata = {
[AZX_DRIVER_TERA] = 1,
};
-/* number of slots to probe as default
- * this can be different from azx_max_codecs[] -- e.g. some boards
- * report wrongly the non-existing 4th slot availability
- */
-static unsigned int azx_default_codecs[AZX_NUM_DRIVERS] __devinitdata = {
- [AZX_DRIVER_ICH] = 3,
- [AZX_DRIVER_ATI] = 3,
-};
-
static int __devinit azx_codec_create(struct azx *chip, const char *model,
- unsigned int codec_probe_mask)
+ unsigned int codec_probe_mask,
+ int no_init)
{
struct hda_bus_template bus_temp;
- int c, codecs, audio_codecs, err;
- int def_slots, max_slots;
+ int c, codecs, err;
+ int max_slots;
memset(&bus_temp, 0, sizeof(bus_temp));
bus_temp.private_data = chip;
@@ -1216,7 +1240,9 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model,
bus_temp.pci = chip->pci;
bus_temp.ops.command = azx_send_cmd;
bus_temp.ops.get_response = azx_get_response;
+ bus_temp.ops.attach_pcm = azx_attach_pcm_stream;
#ifdef CONFIG_SND_HDA_POWER_SAVE
+ bus_temp.power_save = &power_save;
bus_temp.ops.pm_notify = azx_power_notify;
#endif
@@ -1227,33 +1253,43 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model,
if (chip->driver_type == AZX_DRIVER_NVIDIA)
chip->bus->needs_damn_long_delay = 1;
- codecs = audio_codecs = 0;
+ codecs = 0;
max_slots = azx_max_codecs[chip->driver_type];
if (!max_slots)
max_slots = AZX_MAX_CODECS;
- def_slots = azx_default_codecs[chip->driver_type];
- if (!def_slots)
- def_slots = max_slots;
- for (c = 0; c < def_slots; c++) {
+
+ /* First try to probe all given codec slots */
+ for (c = 0; c < max_slots; c++) {
+ if ((chip->codec_mask & (1 << c)) & codec_probe_mask) {
+ if (probe_codec(chip, c) < 0) {
+ /* Some BIOSen give you wrong codec addresses
+ * that don't exist
+ */
+ snd_printk(KERN_WARNING
+ "hda_intel: Codec #%d probe error; "
+ "disabling it...\n", c);
+ chip->codec_mask &= ~(1 << c);
+ /* More badly, accessing to a non-existing
+ * codec often screws up the controller chip,
+ * and distrubs the further communications.
+ * Thus if an error occurs during probing,
+ * better to reset the controller chip to
+ * get back to the sanity state.
+ */
+ azx_stop_chip(chip);
+ azx_init_chip(chip);
+ }
+ }
+ }
+
+ /* Then create codec instances */
+ for (c = 0; c < max_slots; c++) {
if ((chip->codec_mask & (1 << c)) & codec_probe_mask) {
struct hda_codec *codec;
- err = snd_hda_codec_new(chip->bus, c, &codec);
+ err = snd_hda_codec_new(chip->bus, c, !no_init, &codec);
if (err < 0)
continue;
codecs++;
- if (codec->afg)
- audio_codecs++;
- }
- }
- if (!audio_codecs) {
- /* probe additional slots if no codec is found */
- for (; c < max_slots; c++) {
- if ((chip->codec_mask & (1 << c)) & codec_probe_mask) {
- err = snd_hda_codec_new(chip->bus, c, NULL);
- if (err < 0)
- continue;
- codecs++;
- }
}
}
if (!codecs) {
@@ -1722,111 +1758,59 @@ static struct snd_pcm_ops azx_pcm_ops = {
static void azx_pcm_free(struct snd_pcm *pcm)
{
- kfree(pcm->private_data);
+ struct azx_pcm *apcm = pcm->private_data;
+ if (apcm) {
+ apcm->chip->pcm[pcm->device] = NULL;
+ kfree(apcm);
+ }
}
-static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec,
- struct hda_pcm *cpcm)
+static int
+azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec,
+ struct hda_pcm *cpcm)
{
- int err;
+ struct azx *chip = bus->private_data;
struct snd_pcm *pcm;
struct azx_pcm *apcm;
+ int pcm_dev = cpcm->device;
+ int s, err;
- /* if no substreams are defined for both playback and capture,
- * it's just a placeholder. ignore it.
- */
- if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams)
- return 0;
-
- if (snd_BUG_ON(!cpcm->name))
+ if (pcm_dev >= AZX_MAX_PCMS) {
+ snd_printk(KERN_ERR SFX "Invalid PCM device number %d\n",
+ pcm_dev);
return -EINVAL;
-
- err = snd_pcm_new(chip->card, cpcm->name, cpcm->device,
- cpcm->stream[0].substreams,
- cpcm->stream[1].substreams,
+ }
+ if (chip->pcm[pcm_dev]) {
+ snd_printk(KERN_ERR SFX "PCM %d already exists\n", pcm_dev);
+ return -EBUSY;
+ }
+ err = snd_pcm_new(chip->card, cpcm->name, pcm_dev,
+ cpcm->stream[SNDRV_PCM_STREAM_PLAYBACK].substreams,
+ cpcm->stream[SNDRV_PCM_STREAM_CAPTURE].substreams,
&pcm);
if (err < 0)
return err;
strcpy(pcm->name, cpcm->name);
- apcm = kmalloc(sizeof(*apcm), GFP_KERNEL);
+ apcm = kzalloc(sizeof(*apcm), GFP_KERNEL);
if (apcm == NULL)
return -ENOMEM;
apcm->chip = chip;
apcm->codec = codec;
- apcm->hinfo[0] = &cpcm->stream[0];
- apcm->hinfo[1] = &cpcm->stream[1];
pcm->private_data = apcm;
pcm->private_free = azx_pcm_free;
- if (cpcm->stream[0].substreams)
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &azx_pcm_ops);
- if (cpcm->stream[1].substreams)
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &azx_pcm_ops);
+ if (cpcm->pcm_type == HDA_PCM_TYPE_MODEM)
+ pcm->dev_class = SNDRV_PCM_CLASS_MODEM;
+ chip->pcm[pcm_dev] = pcm;
+ cpcm->pcm = pcm;
+ for (s = 0; s < 2; s++) {
+ apcm->hinfo[s] = &cpcm->stream[s];
+ if (cpcm->stream[s].substreams)
+ snd_pcm_set_ops(pcm, s, &azx_pcm_ops);
+ }
+ /* buffer pre-allocation */
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
snd_dma_pci_data(chip->pci),
1024 * 64, 32 * 1024 * 1024);
- chip->pcm[cpcm->device] = pcm;
- return 0;
-}
-
-static int __devinit azx_pcm_create(struct azx *chip)
-{
- static const char *dev_name[HDA_PCM_NTYPES] = {
- "Audio", "SPDIF", "HDMI", "Modem"
- };
- /* starting device index for each PCM type */
- static int dev_idx[HDA_PCM_NTYPES] = {
- [HDA_PCM_TYPE_AUDIO] = 0,
- [HDA_PCM_TYPE_SPDIF] = 1,
- [HDA_PCM_TYPE_HDMI] = 3,
- [HDA_PCM_TYPE_MODEM] = 6
- };
- /* normal audio device indices; not linear to keep compatibility */
- static int audio_idx[4] = { 0, 2, 4, 5 };
- struct hda_codec *codec;
- int c, err;
- int num_devs[HDA_PCM_NTYPES];
-
- err = snd_hda_build_pcms(chip->bus);
- if (err < 0)
- return err;
-
- /* create audio PCMs */
- memset(num_devs, 0, sizeof(num_devs));
- list_for_each_entry(codec, &chip->bus->codec_list, list) {
- for (c = 0; c < codec->num_pcms; c++) {
- struct hda_pcm *cpcm = &codec->pcm_info[c];
- int type = cpcm->pcm_type;
- switch (type) {
- case HDA_PCM_TYPE_AUDIO:
- if (num_devs[type] >= ARRAY_SIZE(audio_idx)) {
- snd_printk(KERN_WARNING
- "Too many audio devices\n");
- continue;
- }
- cpcm->device = audio_idx[num_devs[type]];
- break;
- case HDA_PCM_TYPE_SPDIF:
- case HDA_PCM_TYPE_HDMI:
- case HDA_PCM_TYPE_MODEM:
- if (num_devs[type]) {
- snd_printk(KERN_WARNING
- "%s already defined\n",
- dev_name[type]);
- continue;
- }
- cpcm->device = dev_idx[type];
- break;
- default:
- snd_printk(KERN_WARNING
- "Invalid PCM type %d\n", type);
- continue;
- }
- num_devs[type]++;
- err = create_codec_pcm(chip, codec, cpcm);
- if (err < 0)
- return err;
- }
- }
return 0;
}
@@ -1903,13 +1887,13 @@ static void azx_stop_chip(struct azx *chip)
#ifdef CONFIG_SND_HDA_POWER_SAVE
/* power-up/down the controller */
-static void azx_power_notify(struct hda_codec *codec)
+static void azx_power_notify(struct hda_bus *bus)
{
- struct azx *chip = codec->bus->private_data;
+ struct azx *chip = bus->private_data;
struct hda_codec *c;
int power_on = 0;
- list_for_each_entry(c, &codec->bus->codec_list, list) {
+ list_for_each_entry(c, &bus->codec_list, list) {
if (c->power_on) {
power_on = 1;
break;
@@ -1926,6 +1910,18 @@ static void azx_power_notify(struct hda_codec *codec)
/*
* power management
*/
+
+static int snd_hda_codecs_inuse(struct hda_bus *bus)
+{
+ struct hda_codec *codec;
+
+ list_for_each_entry(codec, &bus->codec_list, list) {
+ if (snd_hda_codec_needs_resume(codec))
+ return 1;
+ }
+ return 0;
+}
+
static int azx_suspend(struct pci_dev *pci, pm_message_t state)
{
struct snd_card *card = pci_get_drvdata(pci);
@@ -1951,13 +1947,16 @@ static int azx_suspend(struct pci_dev *pci, pm_message_t state)
return 0;
}
+static int azx_resume_early(struct pci_dev *pci)
+{
+ return pci_restore_state(pci);
+}
+
static int azx_resume(struct pci_dev *pci)
{
struct snd_card *card = pci_get_drvdata(pci);
struct azx *chip = card->private_data;
- pci_set_power_state(pci, PCI_D0);
- pci_restore_state(pci);
if (pci_enable_device(pci) < 0) {
printk(KERN_ERR "hda-intel: pci_enable_device failed, "
"disabling device\n");
@@ -2095,6 +2094,10 @@ static struct snd_pci_quirk probe_mask_list[] __devinitdata = {
SND_PCI_QUIRK(0x1014, 0x05b7, "Thinkpad Z60", 0x01),
SND_PCI_QUIRK(0x17aa, 0x2010, "Thinkpad X/T/R60", 0x01),
SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X/T/R61", 0x01),
+ /* broken BIOS */
+ SND_PCI_QUIRK(0x1028, 0x20ac, "Dell Studio Desktop", 0x01),
+ /* including bogus ALC268 in slot#2 that conflicts with ALC888 */
+ SND_PCI_QUIRK(0x17c0, 0x4085, "Medion MD96630", 0x01),
{}
};
@@ -2229,6 +2232,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
chip->playback_streams = ATIHDMI_NUM_PLAYBACK;
chip->capture_streams = ATIHDMI_NUM_CAPTURE;
break;
+ case AZX_DRIVER_GENERIC:
default:
chip->playback_streams = ICH6_NUM_PLAYBACK;
chip->capture_streams = ICH6_NUM_CAPTURE;
@@ -2338,40 +2342,31 @@ static int __devinit azx_probe(struct pci_dev *pci,
}
err = azx_create(card, pci, dev, pci_id->driver_data, &chip);
- if (err < 0) {
- snd_card_free(card);
- return err;
- }
+ if (err < 0)
+ goto out_free;
card->private_data = chip;
/* create codec instances */
- err = azx_codec_create(chip, model[dev], probe_mask[dev]);
- if (err < 0) {
- snd_card_free(card);
- return err;
- }
+ err = azx_codec_create(chip, model[dev], probe_mask[dev],
+ probe_only[dev]);
+ if (err < 0)
+ goto out_free;
/* create PCM streams */
- err = azx_pcm_create(chip);
- if (err < 0) {
- snd_card_free(card);
- return err;
- }
+ err = snd_hda_build_pcms(chip->bus);
+ if (err < 0)
+ goto out_free;
/* create mixer controls */
err = azx_mixer_create(chip);
- if (err < 0) {
- snd_card_free(card);
- return err;
- }
+ if (err < 0)
+ goto out_free;
snd_card_set_dev(card, &pci->dev);
err = snd_card_register(card);
- if (err < 0) {
- snd_card_free(card);
- return err;
- }
+ if (err < 0)
+ goto out_free;
pci_set_drvdata(pci, card);
chip->running = 1;
@@ -2380,6 +2375,9 @@ static int __devinit azx_probe(struct pci_dev *pci,
dev++;
return err;
+out_free:
+ snd_card_free(card);
+ return err;
}
static void __devexit azx_remove(struct pci_dev *pci)
@@ -2453,6 +2451,11 @@ static struct pci_device_id azx_ids[] = {
{ PCI_DEVICE(0x10de, 0x0bd7), .driver_data = AZX_DRIVER_NVIDIA },
/* Teradici */
{ PCI_DEVICE(0x6549, 0x1200), .driver_data = AZX_DRIVER_TERA },
+ /* AMD Generic, PCI class code and Vendor ID for HD Audio */
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_ANY_ID),
+ .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
+ .class_mask = 0xffffff,
+ .driver_data = AZX_DRIVER_GENERIC },
{ 0, }
};
MODULE_DEVICE_TABLE(pci, azx_ids);
@@ -2465,6 +2468,7 @@ static struct pci_driver driver = {
.remove = __devexit_p(azx_remove),
#ifdef CONFIG_PM
.suspend = azx_suspend,
+ .resume_early = azx_resume_early,
.resume = azx_resume,
#endif
};
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index 7957fefda73..6f2fe0f9fdd 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -96,6 +96,8 @@ struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
const char *name);
int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
unsigned int *tlv, const char **slaves);
+void snd_hda_codec_reset(struct hda_codec *codec);
+int snd_hda_codec_configure(struct hda_codec *codec);
/* amp value bits */
#define HDA_AMP_MUTE 0x80
@@ -282,6 +284,12 @@ int snd_hda_codec_proc_new(struct hda_codec *codec);
static inline int snd_hda_codec_proc_new(struct hda_codec *codec) { return 0; }
#endif
+#define SND_PRINT_RATES_ADVISED_BUFSIZE 80
+void snd_print_pcm_rates(int pcm, char *buf, int buflen);
+
+#define SND_PRINT_BITS_ADVISED_BUFSIZE 16
+void snd_print_pcm_bits(int pcm, char *buf, int buflen);
+
/*
* Misc
*/
@@ -364,17 +372,17 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
/* amp values */
#define AMP_IN_MUTE(idx) (0x7080 | ((idx)<<8))
#define AMP_IN_UNMUTE(idx) (0x7000 | ((idx)<<8))
-#define AMP_OUT_MUTE 0xb080
-#define AMP_OUT_UNMUTE 0xb000
-#define AMP_OUT_ZERO 0xb000
+#define AMP_OUT_MUTE 0xb080
+#define AMP_OUT_UNMUTE 0xb000
+#define AMP_OUT_ZERO 0xb000
/* pinctl values */
#define PIN_IN (AC_PINCTL_IN_EN)
-#define PIN_VREFHIZ (AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ)
+#define PIN_VREFHIZ (AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ)
#define PIN_VREF50 (AC_PINCTL_IN_EN | AC_PINCTL_VREF_50)
-#define PIN_VREFGRD (AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD)
+#define PIN_VREFGRD (AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD)
#define PIN_VREF80 (AC_PINCTL_IN_EN | AC_PINCTL_VREF_80)
-#define PIN_VREF100 (AC_PINCTL_IN_EN | AC_PINCTL_VREF_100)
-#define PIN_OUT (AC_PINCTL_OUT_EN)
+#define PIN_VREF100 (AC_PINCTL_IN_EN | AC_PINCTL_VREF_100)
+#define PIN_OUT (AC_PINCTL_OUT_EN)
#define PIN_HP (AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN)
#define PIN_HP_AMP (AC_PINCTL_HP_EN)
@@ -393,10 +401,26 @@ u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction);
int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
unsigned int caps);
+int snd_hda_ctl_add(struct hda_codec *codec, struct snd_kcontrol *kctl);
+void snd_hda_ctls_clear(struct hda_codec *codec);
+
/*
* hwdep interface
*/
+#ifdef CONFIG_SND_HDA_HWDEP
int snd_hda_create_hwdep(struct hda_codec *codec);
+#else
+static inline int snd_hda_create_hwdep(struct hda_codec *codec) { return 0; }
+#endif
+
+#ifdef CONFIG_SND_HDA_RECONFIG
+int snd_hda_hwdep_add_sysfs(struct hda_codec *codec);
+#else
+static inline int snd_hda_hwdep_add_sysfs(struct hda_codec *codec)
+{
+ return 0;
+}
+#endif
/*
* power-management
@@ -430,4 +454,66 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec,
#define get_amp_direction(kc) (((kc)->private_value >> 18) & 0x1)
#define get_amp_index(kc) (((kc)->private_value >> 19) & 0xf)
+/*
+ * CEA Short Audio Descriptor data
+ */
+struct cea_sad {
+ int channels;
+ int format; /* (format == 0) indicates invalid SAD */
+ int rates;
+ int sample_bits; /* for LPCM */
+ int max_bitrate; /* for AC3...ATRAC */
+ int profile; /* for WMAPRO */
+};
+
+#define ELD_FIXED_BYTES 20
+#define ELD_MAX_MNL 16
+#define ELD_MAX_SAD 16
+
+/*
+ * ELD: EDID Like Data
+ */
+struct hdmi_eld {
+ int eld_size;
+ int baseline_len;
+ int eld_ver; /* (eld_ver == 0) indicates invalid ELD */
+ int cea_edid_ver;
+ char monitor_name[ELD_MAX_MNL + 1];
+ int manufacture_id;
+ int product_id;
+ u64 port_id;
+ int support_hdcp;
+ int support_ai;
+ int conn_type;
+ int aud_synch_delay;
+ int spk_alloc;
+ int sad_count;
+ struct cea_sad sad[ELD_MAX_SAD];
+#ifdef CONFIG_PROC_FS
+ struct snd_info_entry *proc_entry;
+#endif
+};
+
+int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid);
+int snd_hdmi_get_eld(struct hdmi_eld *, struct hda_codec *, hda_nid_t);
+void snd_hdmi_show_eld(struct hdmi_eld *eld);
+
+#ifdef CONFIG_PROC_FS
+int snd_hda_eld_proc_new(struct hda_codec *codec, struct hdmi_eld *eld);
+void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld);
+#else
+static inline int snd_hda_eld_proc_new(struct hda_codec *codec,
+ struct hdmi_eld *eld)
+{
+ return 0;
+}
+static inline void snd_hda_eld_proc_free(struct hda_codec *codec,
+ struct hdmi_eld *eld)
+{
+}
+#endif
+
+#define SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE 80
+void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen);
+
#endif /* __SOUND_HDA_LOCAL_H */
diff --git a/sound/pci/hda/hda_patch.h b/sound/pci/hda/hda_patch.h
deleted file mode 100644
index dfbcfa88da4..00000000000
--- a/sound/pci/hda/hda_patch.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * HDA Patches - included by hda_codec.c
- */
-
-/* Realtek codecs */
-extern struct hda_codec_preset snd_hda_preset_realtek[];
-/* C-Media codecs */
-extern struct hda_codec_preset snd_hda_preset_cmedia[];
-/* Analog Devices codecs */
-extern struct hda_codec_preset snd_hda_preset_analog[];
-/* SigmaTel codecs */
-extern struct hda_codec_preset snd_hda_preset_sigmatel[];
-/* SiLabs 3054/3055 modem codecs */
-extern struct hda_codec_preset snd_hda_preset_si3054[];
-/* ATI HDMI codecs */
-extern struct hda_codec_preset snd_hda_preset_atihdmi[];
-/* Conexant audio codec */
-extern struct hda_codec_preset snd_hda_preset_conexant[];
-/* VIA codecs */
-extern struct hda_codec_preset snd_hda_preset_via[];
-/* NVIDIA HDMI codecs */
-extern struct hda_codec_preset snd_hda_preset_nvhdmi[];
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c
index c39af986bff..7ca66d65414 100644
--- a/sound/pci/hda/hda_proc.c
+++ b/sound/pci/hda/hda_proc.c
@@ -91,31 +91,21 @@ static void print_amp_vals(struct snd_info_buffer *buffer,
static void print_pcm_rates(struct snd_info_buffer *buffer, unsigned int pcm)
{
- static unsigned int rates[] = {
- 8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200,
- 96000, 176400, 192000, 384000
- };
- int i;
+ char buf[SND_PRINT_RATES_ADVISED_BUFSIZE];
pcm &= AC_SUPPCM_RATES;
snd_iprintf(buffer, " rates [0x%x]:", pcm);
- for (i = 0; i < ARRAY_SIZE(rates); i++)
- if (pcm & (1 << i))
- snd_iprintf(buffer, " %d", rates[i]);
- snd_iprintf(buffer, "\n");
+ snd_print_pcm_rates(pcm, buf, sizeof(buf));
+ snd_iprintf(buffer, "%s\n", buf);
}
static void print_pcm_bits(struct snd_info_buffer *buffer, unsigned int pcm)
{
- static unsigned int bits[] = { 8, 16, 20, 24, 32 };
- int i;
+ char buf[SND_PRINT_BITS_ADVISED_BUFSIZE];
- pcm = (pcm >> 16) & 0xff;
- snd_iprintf(buffer, " bits [0x%x]:", pcm);
- for (i = 0; i < ARRAY_SIZE(bits); i++)
- if (pcm & (1 << i))
- snd_iprintf(buffer, " %d", bits[i]);
- snd_iprintf(buffer, "\n");
+ snd_iprintf(buffer, " bits [0x%x]:", (pcm >> 16) & 0xff);
+ snd_print_pcm_bits(pcm, buf, sizeof(buf));
+ snd_iprintf(buffer, "%s\n", buf);
}
static void print_pcm_formats(struct snd_info_buffer *buffer,
@@ -145,32 +135,6 @@ static void print_pcm_caps(struct snd_info_buffer *buffer,
print_pcm_formats(buffer, stream);
}
-static const char *get_jack_location(u32 cfg)
-{
- static char *bases[7] = {
- "N/A", "Rear", "Front", "Left", "Right", "Top", "Bottom",
- };
- static unsigned char specials_idx[] = {
- 0x07, 0x08,
- 0x17, 0x18, 0x19,
- 0x37, 0x38
- };
- static char *specials[] = {
- "Rear Panel", "Drive Bar",
- "Riser", "HDMI", "ATAPI",
- "Mobile-In", "Mobile-Out"
- };
- int i;
- cfg = (cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT;
- if ((cfg & 0x0f) < 7)
- return bases[cfg & 0x0f];
- for (i = 0; i < ARRAY_SIZE(specials_idx); i++) {
- if (cfg == specials_idx[i])
- return specials[i];
- }
- return "UNKNOWN";
-}
-
static const char *get_jack_connection(u32 cfg)
{
static char *names[16] = {
@@ -206,13 +170,6 @@ static void print_pin_caps(struct snd_info_buffer *buffer,
int *supports_vref)
{
static char *jack_conns[4] = { "Jack", "N/A", "Fixed", "Both" };
- static char *jack_types[16] = {
- "Line Out", "Speaker", "HP Out", "CD",
- "SPDIF Out", "Digital Out", "Modem Line", "Modem Hand",
- "Line In", "Aux", "Mic", "Telephony",
- "SPDIF In", "Digitial In", "Reserved", "Other"
- };
- static char *jack_locations[4] = { "Ext", "Int", "Sep", "Oth" };
unsigned int caps, val;
caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
@@ -274,9 +231,9 @@ static void print_pin_caps(struct snd_info_buffer *buffer,
caps = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
snd_iprintf(buffer, " Pin Default 0x%08x: [%s] %s at %s %s\n", caps,
jack_conns[(caps & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT],
- jack_types[(caps & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT],
- jack_locations[(caps >> (AC_DEFCFG_LOCATION_SHIFT + 4)) & 3],
- get_jack_location(caps));
+ snd_hda_get_jack_type(caps),
+ snd_hda_get_jack_connectivity(caps),
+ snd_hda_get_jack_location(caps));
snd_iprintf(buffer, " Conn = %s, Color = %s\n",
get_jack_connection(caps),
get_jack_color(caps));
@@ -457,17 +414,6 @@ static void print_conn_list(struct snd_info_buffer *buffer,
}
}
-static void print_realtek_coef(struct snd_info_buffer *buffer,
- struct hda_codec *codec, hda_nid_t nid)
-{
- int coeff = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_PROC_COEF, 0);
- snd_iprintf(buffer, " Processing Coefficient: 0x%02x\n", coeff);
- coeff = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_COEF_INDEX, 0);
- snd_iprintf(buffer, " Coefficient Index: 0x%02x\n", coeff);
-}
-
static void print_gpio(struct snd_info_buffer *buffer,
struct hda_codec *codec, hda_nid_t nid)
{
@@ -500,12 +446,13 @@ static void print_gpio(struct snd_info_buffer *buffer,
for (i = 0; i < max; ++i)
snd_iprintf(buffer,
" IO[%d]: enable=%d, dir=%d, wake=%d, "
- "sticky=%d, data=%d\n", i,
+ "sticky=%d, data=%d, unsol=%d\n", i,
(enable & (1<<i)) ? 1 : 0,
(direction & (1<<i)) ? 1 : 0,
(wake & (1<<i)) ? 1 : 0,
(sticky & (1<<i)) ? 1 : 0,
- (data & (1<<i)) ? 1 : 0);
+ (data & (1<<i)) ? 1 : 0,
+ (unsol & (1<<i)) ? 1 : 0);
/* FIXME: add GPO and GPI pin information */
}
@@ -513,12 +460,11 @@ static void print_codec_info(struct snd_info_entry *entry,
struct snd_info_buffer *buffer)
{
struct hda_codec *codec = entry->private_data;
- char buf[32];
hda_nid_t nid;
int i, nodes;
- snd_hda_get_codec_name(codec, buf, sizeof(buf));
- snd_iprintf(buffer, "Codec: %s\n", buf);
+ snd_iprintf(buffer, "Codec: %s\n",
+ codec->name ? codec->name : "Not Set");
snd_iprintf(buffer, "Address: %d\n", codec->addr);
snd_iprintf(buffer, "Vendor Id: 0x%x\n", codec->vendor_id);
snd_iprintf(buffer, "Subsystem Id: 0x%x\n", codec->subsystem_id);
@@ -547,6 +493,8 @@ static void print_codec_info(struct snd_info_entry *entry,
}
print_gpio(buffer, codec, codec->afg);
+ if (codec->proc_widget_hook)
+ codec->proc_widget_hook(buffer, codec, codec->afg);
for (i = 0; i < nodes; i++, nid++) {
unsigned int wid_caps =
@@ -649,9 +597,8 @@ static void print_codec_info(struct snd_info_entry *entry,
if (wid_caps & AC_WCAP_PROC_WID)
print_proc_caps(buffer, codec, nid);
- /* NID 0x20 == Realtek Define Registers */
- if (codec->vendor_id == 0x10ec && nid == 0x20)
- print_realtek_coef(buffer, codec, nid);
+ if (codec->proc_widget_hook)
+ codec->proc_widget_hook(buffer, codec, nid);
}
snd_hda_power_down(codec);
}
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 686c77491de..26247cfe749 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -27,7 +27,6 @@
#include <sound/core.h>
#include "hda_codec.h"
#include "hda_local.h"
-#include "hda_patch.h"
struct ad198x_spec {
struct snd_kcontrol_new *mixers[5];
@@ -67,8 +66,7 @@ struct ad198x_spec {
/* dynamic controls, init_verbs and input_mux */
struct auto_pin_cfg autocfg;
- unsigned int num_kctl_alloc, num_kctl_used;
- struct snd_kcontrol_new *kctl_alloc;
+ struct snd_array kctls;
struct hda_input_mux private_imux;
hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
@@ -154,6 +152,8 @@ static const char *ad_slave_sws[] = {
NULL
};
+static void ad198x_free_kctls(struct hda_codec *codec);
+
static int ad198x_build_controls(struct hda_codec *codec)
{
struct ad198x_spec *spec = codec->spec;
@@ -202,6 +202,7 @@ static int ad198x_build_controls(struct hda_codec *codec)
return err;
}
+ ad198x_free_kctls(codec); /* no longer needed */
return 0;
}
@@ -375,16 +376,27 @@ static int ad198x_build_pcms(struct hda_codec *codec)
return 0;
}
-static void ad198x_free(struct hda_codec *codec)
+static void ad198x_free_kctls(struct hda_codec *codec)
{
struct ad198x_spec *spec = codec->spec;
- unsigned int i;
- if (spec->kctl_alloc) {
- for (i = 0; i < spec->num_kctl_used; i++)
- kfree(spec->kctl_alloc[i].name);
- kfree(spec->kctl_alloc);
+ if (spec->kctls.list) {
+ struct snd_kcontrol_new *kctl = spec->kctls.list;
+ int i;
+ for (i = 0; i < spec->kctls.used; i++)
+ kfree(kctl[i].name);
}
+ snd_array_free(&spec->kctls);
+}
+
+static void ad198x_free(struct hda_codec *codec)
+{
+ struct ad198x_spec *spec = codec->spec;
+
+ if (!spec)
+ return;
+
+ ad198x_free_kctls(codec);
kfree(codec->spec);
}
@@ -629,6 +641,36 @@ static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = {
HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Capture Source",
+ .info = ad198x_mux_enum_info,
+ .get = ad198x_mux_enum_get,
+ .put = ad198x_mux_enum_put,
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "External Amplifier",
+ .info = ad198x_eapd_info,
+ .get = ad198x_eapd_get,
+ .put = ad198x_eapd_put,
+ .private_value = 0x1b | (1 << 8), /* port-D, inversed */
+ },
+ { } /* end */
+};
+
+static struct snd_kcontrol_new ad1986a_samsung_mixers[] = {
+ HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
+ HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
+ HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
@@ -917,6 +959,7 @@ enum {
AD1986A_LAPTOP_EAPD,
AD1986A_LAPTOP_AUTOMUTE,
AD1986A_ULTRA,
+ AD1986A_SAMSUNG,
AD1986A_MODELS
};
@@ -927,6 +970,7 @@ static const char *ad1986a_models[AD1986A_MODELS] = {
[AD1986A_LAPTOP_EAPD] = "laptop-eapd",
[AD1986A_LAPTOP_AUTOMUTE] = "laptop-automute",
[AD1986A_ULTRA] = "ultra",
+ [AD1986A_SAMSUNG] = "samsung",
};
static struct snd_pci_quirk ad1986a_cfg_tbl[] = {
@@ -949,9 +993,9 @@ static struct snd_pci_quirk ad1986a_cfg_tbl[] = {
SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba", AD1986A_LAPTOP_EAPD),
SND_PCI_QUIRK(0x144d, 0xb03c, "Samsung R55", AD1986A_3STACK),
SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_LAPTOP),
- SND_PCI_QUIRK(0x144d, 0xc023, "Samsung X60", AD1986A_LAPTOP_EAPD),
- SND_PCI_QUIRK(0x144d, 0xc024, "Samsung R65", AD1986A_LAPTOP_EAPD),
- SND_PCI_QUIRK(0x144d, 0xc026, "Samsung X11", AD1986A_LAPTOP_EAPD),
+ SND_PCI_QUIRK(0x144d, 0xc023, "Samsung X60", AD1986A_SAMSUNG),
+ SND_PCI_QUIRK(0x144d, 0xc024, "Samsung R65", AD1986A_SAMSUNG),
+ SND_PCI_QUIRK(0x144d, 0xc026, "Samsung X11", AD1986A_SAMSUNG),
SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_ULTRA),
SND_PCI_QUIRK(0x144d, 0xc504, "Samsung Q35", AD1986A_3STACK),
SND_PCI_QUIRK(0x17aa, 0x1011, "Lenovo M55", AD1986A_LAPTOP),
@@ -1033,6 +1077,17 @@ static int patch_ad1986a(struct hda_codec *codec)
break;
case AD1986A_LAPTOP_EAPD:
spec->mixers[0] = ad1986a_laptop_eapd_mixers;
+ spec->num_init_verbs = 2;
+ spec->init_verbs[1] = ad1986a_eapd_init_verbs;
+ spec->multiout.max_channels = 2;
+ spec->multiout.num_dacs = 1;
+ spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
+ if (!is_jack_available(codec, 0x25))
+ spec->multiout.dig_out_nid = 0;
+ spec->input_mux = &ad1986a_laptop_eapd_capture_source;
+ break;
+ case AD1986A_SAMSUNG:
+ spec->mixers[0] = ad1986a_samsung_mixers;
spec->num_init_verbs = 3;
spec->init_verbs[1] = ad1986a_eapd_init_verbs;
spec->init_verbs[2] = ad1986a_automic_verbs;
@@ -2452,9 +2507,6 @@ static struct hda_amp_list ad1988_loopbacks[] = {
* Automatic parse of I/O pins from the BIOS configuration
*/
-#define NUM_CONTROL_ALLOC 32
-#define NUM_VERB_ALLOC 32
-
enum {
AD_CTL_WIDGET_VOL,
AD_CTL_WIDGET_MUTE,
@@ -2472,27 +2524,15 @@ static int add_control(struct ad198x_spec *spec, int type, const char *name,
{
struct snd_kcontrol_new *knew;
- if (spec->num_kctl_used >= spec->num_kctl_alloc) {
- int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC;
-
- knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); /* array + terminator */
- if (! knew)
- return -ENOMEM;
- if (spec->kctl_alloc) {
- memcpy(knew, spec->kctl_alloc, sizeof(*knew) * spec->num_kctl_alloc);
- kfree(spec->kctl_alloc);
- }
- spec->kctl_alloc = knew;
- spec->num_kctl_alloc = num;
- }
-
- knew = &spec->kctl_alloc[spec->num_kctl_used];
+ snd_array_init(&spec->kctls, sizeof(*knew), 32);
+ knew = snd_array_new(&spec->kctls);
+ if (!knew)
+ return -ENOMEM;
*knew = ad1988_control_templates[type];
knew->name = kstrdup(name, GFP_KERNEL);
if (! knew->name)
return -ENOMEM;
knew->private_value = val;
- spec->num_kctl_used++;
return 0;
}
@@ -2846,8 +2886,8 @@ static int ad1988_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_in_pin)
spec->dig_in_nid = AD1988_SPDIF_IN;
- if (spec->kctl_alloc)
- spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
+ if (spec->kctls.list)
+ spec->mixers[spec->num_mixers++] = spec->kctls.list;
spec->init_verbs[spec->num_init_verbs++] = ad1988_6stack_init_verbs;
@@ -3861,6 +3901,7 @@ static const char *ad1884a_models[AD1884A_MODELS] = {
static struct snd_pci_quirk ad1884a_cfg_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE),
SND_PCI_QUIRK(0x103c, 0x3056, "HP", AD1884A_MOBILE),
+ SND_PCI_QUIRK(0x103c, 0x30e6, "HP 6730b", AD1884A_LAPTOP),
SND_PCI_QUIRK(0x103c, 0x30e7, "HP EliteBook 8530p", AD1884A_LAPTOP),
SND_PCI_QUIRK(0x103c, 0x3614, "HP 6730s", AD1884A_LAPTOP),
SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD),
@@ -4267,7 +4308,7 @@ static int patch_ad1882(struct hda_codec *codec)
/*
* patch entries
*/
-struct hda_codec_preset snd_hda_preset_analog[] = {
+static struct hda_codec_preset snd_hda_preset_analog[] = {
{ .id = 0x11d4184a, .name = "AD1884A", .patch = patch_ad1884a },
{ .id = 0x11d41882, .name = "AD1882", .patch = patch_ad1882 },
{ .id = 0x11d41883, .name = "AD1883", .patch = patch_ad1884a },
@@ -4285,3 +4326,26 @@ struct hda_codec_preset snd_hda_preset_analog[] = {
{ .id = 0x11d4989b, .name = "AD1989B", .patch = patch_ad1988 },
{} /* terminator */
};
+
+MODULE_ALIAS("snd-hda-codec-id:11d4*");
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Analog Devices HD-audio codec");
+
+static struct hda_codec_preset_list analog_list = {
+ .preset = snd_hda_preset_analog,
+ .owner = THIS_MODULE,
+};
+
+static int __init patch_analog_init(void)
+{
+ return snd_hda_add_codec_preset(&analog_list);
+}
+
+static void __exit patch_analog_exit(void)
+{
+ snd_hda_delete_codec_preset(&analog_list);
+}
+
+module_init(patch_analog_init)
+module_exit(patch_analog_exit)
diff --git a/sound/pci/hda/patch_atihdmi.c b/sound/pci/hda/patch_atihdmi.c
index ba61575983f..233e4778bba 100644
--- a/sound/pci/hda/patch_atihdmi.c
+++ b/sound/pci/hda/patch_atihdmi.c
@@ -27,7 +27,6 @@
#include <sound/core.h>
#include "hda_codec.h"
#include "hda_local.h"
-#include "hda_patch.h"
struct atihdmi_spec {
struct hda_multi_out multiout;
@@ -187,13 +186,40 @@ static int patch_atihdmi(struct hda_codec *codec)
/*
* patch entries
*/
-struct hda_codec_preset snd_hda_preset_atihdmi[] = {
- { .id = 0x1002793c, .name = "ATI RS600 HDMI", .patch = patch_atihdmi },
- { .id = 0x10027919, .name = "ATI RS600 HDMI", .patch = patch_atihdmi },
- { .id = 0x1002791a, .name = "ATI RS690/780 HDMI", .patch = patch_atihdmi },
- { .id = 0x1002aa01, .name = "ATI R6xx HDMI", .patch = patch_atihdmi },
+static struct hda_codec_preset snd_hda_preset_atihdmi[] = {
+ { .id = 0x1002793c, .name = "RS600 HDMI", .patch = patch_atihdmi },
+ { .id = 0x10027919, .name = "RS600 HDMI", .patch = patch_atihdmi },
+ { .id = 0x1002791a, .name = "RS690/780 HDMI", .patch = patch_atihdmi },
+ { .id = 0x1002aa01, .name = "R6xx HDMI", .patch = patch_atihdmi },
{ .id = 0x10951390, .name = "SiI1390 HDMI", .patch = patch_atihdmi },
- { .id = 0x10951392, .name = "SiI1392 HDMI", .patch = patch_atihdmi },
{ .id = 0x17e80047, .name = "Chrontel HDMI", .patch = patch_atihdmi },
{} /* terminator */
};
+
+MODULE_ALIAS("snd-hda-codec-id:1002793c");
+MODULE_ALIAS("snd-hda-codec-id:10027919");
+MODULE_ALIAS("snd-hda-codec-id:1002791a");
+MODULE_ALIAS("snd-hda-codec-id:1002aa01");
+MODULE_ALIAS("snd-hda-codec-id:10951390");
+MODULE_ALIAS("snd-hda-codec-id:17e80047");
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("ATI HDMI HD-audio codec");
+
+static struct hda_codec_preset_list atihdmi_list = {
+ .preset = snd_hda_preset_atihdmi,
+ .owner = THIS_MODULE,
+};
+
+static int __init patch_atihdmi_init(void)
+{
+ return snd_hda_add_codec_preset(&atihdmi_list);
+}
+
+static void __exit patch_atihdmi_exit(void)
+{
+ snd_hda_delete_codec_preset(&atihdmi_list);
+}
+
+module_init(patch_atihdmi_init)
+module_exit(patch_atihdmi_exit)
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c
index 6ef57fbfb6e..f3ebe837f2d 100644
--- a/sound/pci/hda/patch_cmedia.c
+++ b/sound/pci/hda/patch_cmedia.c
@@ -28,7 +28,6 @@
#include <sound/core.h>
#include "hda_codec.h"
#include "hda_local.h"
-#include "hda_patch.h"
#define NUM_PINS 11
@@ -736,8 +735,32 @@ static int patch_cmi9880(struct hda_codec *codec)
/*
* patch entries
*/
-struct hda_codec_preset snd_hda_preset_cmedia[] = {
+static struct hda_codec_preset snd_hda_preset_cmedia[] = {
{ .id = 0x13f69880, .name = "CMI9880", .patch = patch_cmi9880 },
{ .id = 0x434d4980, .name = "CMI9880", .patch = patch_cmi9880 },
{} /* terminator */
};
+
+MODULE_ALIAS("snd-hda-codec-id:13f69880");
+MODULE_ALIAS("snd-hda-codec-id:434d4980");
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("C-Media HD-audio codec");
+
+static struct hda_codec_preset_list cmedia_list = {
+ .preset = snd_hda_preset_cmedia,
+ .owner = THIS_MODULE,
+};
+
+static int __init patch_cmedia_init(void)
+{
+ return snd_hda_add_codec_preset(&cmedia_list);
+}
+
+static void __exit patch_cmedia_exit(void)
+{
+ snd_hda_delete_codec_preset(&cmedia_list);
+}
+
+module_init(patch_cmedia_init)
+module_exit(patch_cmedia_exit)
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index 7c1eb23f0ce..b20e1cede00 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -27,7 +27,6 @@
#include <sound/core.h>
#include "hda_codec.h"
#include "hda_local.h"
-#include "hda_patch.h"
#define CXT_PIN_DIR_IN 0x00
#define CXT_PIN_DIR_OUT 0x01
@@ -86,8 +85,6 @@ struct conexant_spec {
/* dynamic controls, init_verbs and input_mux */
struct auto_pin_cfg autocfg;
- unsigned int num_kctl_alloc, num_kctl_used;
- struct snd_kcontrol_new *kctl_alloc;
struct hda_input_mux private_imux;
hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
@@ -344,15 +341,6 @@ static int conexant_init(struct hda_codec *codec)
static void conexant_free(struct hda_codec *codec)
{
- struct conexant_spec *spec = codec->spec;
- unsigned int i;
-
- if (spec->kctl_alloc) {
- for (i = 0; i < spec->num_kctl_used; i++)
- kfree(spec->kctl_alloc[i].name);
- kfree(spec->kctl_alloc);
- }
-
kfree(codec->spec);
}
@@ -1782,7 +1770,7 @@ static int patch_cxt5051(struct hda_codec *codec)
/*
*/
-struct hda_codec_preset snd_hda_preset_conexant[] = {
+static struct hda_codec_preset snd_hda_preset_conexant[] = {
{ .id = 0x14f15045, .name = "CX20549 (Venice)",
.patch = patch_cxt5045 },
{ .id = 0x14f15047, .name = "CX20551 (Waikiki)",
@@ -1791,3 +1779,28 @@ struct hda_codec_preset snd_hda_preset_conexant[] = {
.patch = patch_cxt5051 },
{} /* terminator */
};
+
+MODULE_ALIAS("snd-hda-codec-id:14f15045");
+MODULE_ALIAS("snd-hda-codec-id:14f15047");
+MODULE_ALIAS("snd-hda-codec-id:14f15051");
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Conexant HD-audio codec");
+
+static struct hda_codec_preset_list conexant_list = {
+ .preset = snd_hda_preset_conexant,
+ .owner = THIS_MODULE,
+};
+
+static int __init patch_conexant_init(void)
+{
+ return snd_hda_add_codec_preset(&conexant_list);
+}
+
+static void __exit patch_conexant_exit(void)
+{
+ snd_hda_delete_codec_preset(&conexant_list);
+}
+
+module_init(patch_conexant_init)
+module_exit(patch_conexant_exit)
diff --git a/sound/pci/hda/patch_intelhdmi.c b/sound/pci/hda/patch_intelhdmi.c
new file mode 100644
index 00000000000..3564f4e4b74
--- /dev/null
+++ b/sound/pci/hda/patch_intelhdmi.c
@@ -0,0 +1,711 @@
+/*
+ *
+ * patch_intelhdmi.c - Patch for Intel HDMI codecs
+ *
+ * Copyright(c) 2008 Intel Corporation. All rights reserved.
+ *
+ * Authors:
+ * Jiang Zhe <zhe.jiang@intel.com>
+ * Wu Fengguang <wfg@linux.intel.com>
+ *
+ * Maintained by:
+ * Wu Fengguang <wfg@linux.intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include "hda_codec.h"
+#include "hda_local.h"
+
+#define CVT_NID 0x02 /* audio converter */
+#define PIN_NID 0x03 /* HDMI output pin */
+
+#define INTEL_HDMI_EVENT_TAG 0x08
+
+struct intel_hdmi_spec {
+ struct hda_multi_out multiout;
+ struct hda_pcm pcm_rec;
+ struct hdmi_eld sink_eld;
+};
+
+static struct hda_verb pinout_enable_verb[] = {
+ {PIN_NID, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {} /* terminator */
+};
+
+static struct hda_verb pinout_disable_verb[] = {
+ {PIN_NID, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00},
+ {}
+};
+
+static struct hda_verb unsolicited_response_verb[] = {
+ {PIN_NID, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN |
+ INTEL_HDMI_EVENT_TAG},
+ {}
+};
+
+static struct hda_verb def_chan_map[] = {
+ {CVT_NID, AC_VERB_SET_HDMI_CHAN_SLOT, 0x00},
+ {CVT_NID, AC_VERB_SET_HDMI_CHAN_SLOT, 0x11},
+ {CVT_NID, AC_VERB_SET_HDMI_CHAN_SLOT, 0x22},
+ {CVT_NID, AC_VERB_SET_HDMI_CHAN_SLOT, 0x33},
+ {CVT_NID, AC_VERB_SET_HDMI_CHAN_SLOT, 0x44},
+ {CVT_NID, AC_VERB_SET_HDMI_CHAN_SLOT, 0x55},
+ {CVT_NID, AC_VERB_SET_HDMI_CHAN_SLOT, 0x66},
+ {CVT_NID, AC_VERB_SET_HDMI_CHAN_SLOT, 0x77},
+ {}
+};
+
+
+struct hdmi_audio_infoframe {
+ u8 type; /* 0x84 */
+ u8 ver; /* 0x01 */
+ u8 len; /* 0x0a */
+
+ u8 checksum; /* PB0 */
+ u8 CC02_CT47; /* CC in bits 0:2, CT in 4:7 */
+ u8 SS01_SF24;
+ u8 CXT04;
+ u8 CA;
+ u8 LFEPBL01_LSV36_DM_INH7;
+ u8 reserved[5]; /* PB6 - PB10 */
+};
+
+/*
+ * CEA speaker placement:
+ *
+ * FLH FCH FRH
+ * FLW FL FLC FC FRC FR FRW
+ *
+ * LFE
+ * TC
+ *
+ * RL RLC RC RRC RR
+ *
+ * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to
+ * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC.
+ */
+enum cea_speaker_placement {
+ FL = (1 << 0), /* Front Left */
+ FC = (1 << 1), /* Front Center */
+ FR = (1 << 2), /* Front Right */
+ FLC = (1 << 3), /* Front Left Center */
+ FRC = (1 << 4), /* Front Right Center */
+ RL = (1 << 5), /* Rear Left */
+ RC = (1 << 6), /* Rear Center */
+ RR = (1 << 7), /* Rear Right */
+ RLC = (1 << 8), /* Rear Left Center */
+ RRC = (1 << 9), /* Rear Right Center */
+ LFE = (1 << 10), /* Low Frequency Effect */
+ FLW = (1 << 11), /* Front Left Wide */
+ FRW = (1 << 12), /* Front Right Wide */
+ FLH = (1 << 13), /* Front Left High */
+ FCH = (1 << 14), /* Front Center High */
+ FRH = (1 << 15), /* Front Right High */
+ TC = (1 << 16), /* Top Center */
+};
+
+/*
+ * ELD SA bits in the CEA Speaker Allocation data block
+ */
+static int eld_speaker_allocation_bits[] = {
+ [0] = FL | FR,
+ [1] = LFE,
+ [2] = FC,
+ [3] = RL | RR,
+ [4] = RC,
+ [5] = FLC | FRC,
+ [6] = RLC | RRC,
+ /* the following are not defined in ELD yet */
+ [7] = FLW | FRW,
+ [8] = FLH | FRH,
+ [9] = TC,
+ [10] = FCH,
+};
+
+struct cea_channel_speaker_allocation {
+ int ca_index;
+ int speakers[8];
+
+ /* derived values, just for convenience */
+ int channels;
+ int spk_mask;
+};
+
+/*
+ * This is an ordered list!
+ *
+ * The preceding ones have better chances to be selected by
+ * hdmi_setup_channel_allocation().
+ */
+static struct cea_channel_speaker_allocation channel_allocations[] = {
+/* channel: 8 7 6 5 4 3 2 1 */
+{ .ca_index = 0x00, .speakers = { 0, 0, 0, 0, 0, 0, FR, FL } },
+ /* 2.1 */
+{ .ca_index = 0x01, .speakers = { 0, 0, 0, 0, 0, LFE, FR, FL } },
+ /* Dolby Surround */
+{ .ca_index = 0x02, .speakers = { 0, 0, 0, 0, FC, 0, FR, FL } },
+{ .ca_index = 0x03, .speakers = { 0, 0, 0, 0, FC, LFE, FR, FL } },
+{ .ca_index = 0x04, .speakers = { 0, 0, 0, RC, 0, 0, FR, FL } },
+{ .ca_index = 0x05, .speakers = { 0, 0, 0, RC, 0, LFE, FR, FL } },
+{ .ca_index = 0x06, .speakers = { 0, 0, 0, RC, FC, 0, FR, FL } },
+{ .ca_index = 0x07, .speakers = { 0, 0, 0, RC, FC, LFE, FR, FL } },
+{ .ca_index = 0x08, .speakers = { 0, 0, RR, RL, 0, 0, FR, FL } },
+{ .ca_index = 0x09, .speakers = { 0, 0, RR, RL, 0, LFE, FR, FL } },
+{ .ca_index = 0x0a, .speakers = { 0, 0, RR, RL, FC, 0, FR, FL } },
+ /* 5.1 */
+{ .ca_index = 0x0b, .speakers = { 0, 0, RR, RL, FC, LFE, FR, FL } },
+{ .ca_index = 0x0c, .speakers = { 0, RC, RR, RL, 0, 0, FR, FL } },
+{ .ca_index = 0x0d, .speakers = { 0, RC, RR, RL, 0, LFE, FR, FL } },
+{ .ca_index = 0x0e, .speakers = { 0, RC, RR, RL, FC, 0, FR, FL } },
+ /* 6.1 */
+{ .ca_index = 0x0f, .speakers = { 0, RC, RR, RL, FC, LFE, FR, FL } },
+{ .ca_index = 0x10, .speakers = { RRC, RLC, RR, RL, 0, 0, FR, FL } },
+{ .ca_index = 0x11, .speakers = { RRC, RLC, RR, RL, 0, LFE, FR, FL } },
+{ .ca_index = 0x12, .speakers = { RRC, RLC, RR, RL, FC, 0, FR, FL } },
+ /* 7.1 */
+{ .ca_index = 0x13, .speakers = { RRC, RLC, RR, RL, FC, LFE, FR, FL } },
+{ .ca_index = 0x14, .speakers = { FRC, FLC, 0, 0, 0, 0, FR, FL } },
+{ .ca_index = 0x15, .speakers = { FRC, FLC, 0, 0, 0, LFE, FR, FL } },
+{ .ca_index = 0x16, .speakers = { FRC, FLC, 0, 0, FC, 0, FR, FL } },
+{ .ca_index = 0x17, .speakers = { FRC, FLC, 0, 0, FC, LFE, FR, FL } },
+{ .ca_index = 0x18, .speakers = { FRC, FLC, 0, RC, 0, 0, FR, FL } },
+{ .ca_index = 0x19, .speakers = { FRC, FLC, 0, RC, 0, LFE, FR, FL } },
+{ .ca_index = 0x1a, .speakers = { FRC, FLC, 0, RC, FC, 0, FR, FL } },
+{ .ca_index = 0x1b, .speakers = { FRC, FLC, 0, RC, FC, LFE, FR, FL } },
+{ .ca_index = 0x1c, .speakers = { FRC, FLC, RR, RL, 0, 0, FR, FL } },
+{ .ca_index = 0x1d, .speakers = { FRC, FLC, RR, RL, 0, LFE, FR, FL } },
+{ .ca_index = 0x1e, .speakers = { FRC, FLC, RR, RL, FC, 0, FR, FL } },
+{ .ca_index = 0x1f, .speakers = { FRC, FLC, RR, RL, FC, LFE, FR, FL } },
+{ .ca_index = 0x20, .speakers = { 0, FCH, RR, RL, FC, 0, FR, FL } },
+{ .ca_index = 0x21, .speakers = { 0, FCH, RR, RL, FC, LFE, FR, FL } },
+{ .ca_index = 0x22, .speakers = { TC, 0, RR, RL, FC, 0, FR, FL } },
+{ .ca_index = 0x23, .speakers = { TC, 0, RR, RL, FC, LFE, FR, FL } },
+{ .ca_index = 0x24, .speakers = { FRH, FLH, RR, RL, 0, 0, FR, FL } },
+{ .ca_index = 0x25, .speakers = { FRH, FLH, RR, RL, 0, LFE, FR, FL } },
+{ .ca_index = 0x26, .speakers = { FRW, FLW, RR, RL, 0, 0, FR, FL } },
+{ .ca_index = 0x27, .speakers = { FRW, FLW, RR, RL, 0, LFE, FR, FL } },
+{ .ca_index = 0x28, .speakers = { TC, RC, RR, RL, FC, 0, FR, FL } },
+{ .ca_index = 0x29, .speakers = { TC, RC, RR, RL, FC, LFE, FR, FL } },
+{ .ca_index = 0x2a, .speakers = { FCH, RC, RR, RL, FC, 0, FR, FL } },
+{ .ca_index = 0x2b, .speakers = { FCH, RC, RR, RL, FC, LFE, FR, FL } },
+{ .ca_index = 0x2c, .speakers = { TC, FCH, RR, RL, FC, 0, FR, FL } },
+{ .ca_index = 0x2d, .speakers = { TC, FCH, RR, RL, FC, LFE, FR, FL } },
+{ .ca_index = 0x2e, .speakers = { FRH, FLH, RR, RL, FC, 0, FR, FL } },
+{ .ca_index = 0x2f, .speakers = { FRH, FLH, RR, RL, FC, LFE, FR, FL } },
+{ .ca_index = 0x30, .speakers = { FRW, FLW, RR, RL, FC, 0, FR, FL } },
+{ .ca_index = 0x31, .speakers = { FRW, FLW, RR, RL, FC, LFE, FR, FL } },
+};
+
+/*
+ * HDMI routines
+ */
+
+#ifdef BE_PARANOID
+static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t nid,
+ int *packet_index, int *byte_index)
+{
+ int val;
+
+ val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_INDEX, 0);
+
+ *packet_index = val >> 5;
+ *byte_index = val & 0x1f;
+}
+#endif
+
+static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t nid,
+ int packet_index, int byte_index)
+{
+ int val;
+
+ val = (packet_index << 5) | (byte_index & 0x1f);
+
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val);
+}
+
+static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t nid,
+ unsigned char val)
+{
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val);
+}
+
+static void hdmi_enable_output(struct hda_codec *codec)
+{
+ /* Enable Audio InfoFrame Transmission */
+ hdmi_set_dip_index(codec, PIN_NID, 0x0, 0x0);
+ snd_hda_codec_write(codec, PIN_NID, 0, AC_VERB_SET_HDMI_DIP_XMIT,
+ AC_DIPXMIT_BEST);
+ /* Unmute */
+ if (get_wcaps(codec, PIN_NID) & AC_WCAP_OUT_AMP)
+ snd_hda_codec_write(codec, PIN_NID, 0,
+ AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
+ /* Enable pin out */
+ snd_hda_sequence_write(codec, pinout_enable_verb);
+}
+
+static void hdmi_disable_output(struct hda_codec *codec)
+{
+ snd_hda_sequence_write(codec, pinout_disable_verb);
+ if (get_wcaps(codec, PIN_NID) & AC_WCAP_OUT_AMP)
+ snd_hda_codec_write(codec, PIN_NID, 0,
+ AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
+
+ /*
+ * FIXME: noises may arise when playing music after reloading the
+ * kernel module, until the next X restart or monitor repower.
+ */
+}
+
+static int hdmi_get_channel_count(struct hda_codec *codec)
+{
+ return 1 + snd_hda_codec_read(codec, CVT_NID, 0,
+ AC_VERB_GET_CVT_CHAN_COUNT, 0);
+}
+
+static void hdmi_set_channel_count(struct hda_codec *codec, int chs)
+{
+ snd_hda_codec_write(codec, CVT_NID, 0,
+ AC_VERB_SET_CVT_CHAN_COUNT, chs - 1);
+
+ if (chs != hdmi_get_channel_count(codec))
+ snd_printd(KERN_INFO "HDMI channel count: expect %d, get %d\n",
+ chs, hdmi_get_channel_count(codec));
+}
+
+static void hdmi_debug_channel_mapping(struct hda_codec *codec)
+{
+#ifdef CONFIG_SND_DEBUG_VERBOSE
+ int i;
+ int slot;
+
+ for (i = 0; i < 8; i++) {
+ slot = snd_hda_codec_read(codec, CVT_NID, 0,
+ AC_VERB_GET_HDMI_CHAN_SLOT, i);
+ printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n",
+ slot >> 4, slot & 0x7);
+ }
+#endif
+}
+
+static void hdmi_parse_eld(struct hda_codec *codec)
+{
+ struct intel_hdmi_spec *spec = codec->spec;
+ struct hdmi_eld *eld = &spec->sink_eld;
+
+ if (!snd_hdmi_get_eld(eld, codec, PIN_NID))
+ snd_hdmi_show_eld(eld);
+}
+
+
+/*
+ * Audio InfoFrame routines
+ */
+
+static void hdmi_debug_dip_size(struct hda_codec *codec)
+{
+#ifdef CONFIG_SND_DEBUG_VERBOSE
+ int i;
+ int size;
+
+ size = snd_hdmi_get_eld_size(codec, PIN_NID);
+ printk(KERN_DEBUG "HDMI: ELD buf size is %d\n", size);
+
+ for (i = 0; i < 8; i++) {
+ size = snd_hda_codec_read(codec, PIN_NID, 0,
+ AC_VERB_GET_HDMI_DIP_SIZE, i);
+ printk(KERN_DEBUG "HDMI: DIP GP[%d] buf size is %d\n", i, size);
+ }
+#endif
+}
+
+static void hdmi_clear_dip_buffers(struct hda_codec *codec)
+{
+#ifdef BE_PARANOID
+ int i, j;
+ int size;
+ int pi, bi;
+ for (i = 0; i < 8; i++) {
+ size = snd_hda_codec_read(codec, PIN_NID, 0,
+ AC_VERB_GET_HDMI_DIP_SIZE, i);
+ if (size == 0)
+ continue;
+
+ hdmi_set_dip_index(codec, PIN_NID, i, 0x0);
+ for (j = 1; j < 1000; j++) {
+ hdmi_write_dip_byte(codec, PIN_NID, 0x0);
+ hdmi_get_dip_index(codec, PIN_NID, &pi, &bi);
+ if (pi != i)
+ snd_printd(KERN_INFO "dip index %d: %d != %d\n",
+ bi, pi, i);
+ if (bi == 0) /* byte index wrapped around */
+ break;
+ }
+ snd_printd(KERN_INFO
+ "HDMI: DIP GP[%d] buf reported size=%d, written=%d\n",
+ i, size, j);
+ }
+#endif
+}
+
+static void hdmi_fill_audio_infoframe(struct hda_codec *codec,
+ struct hdmi_audio_infoframe *ai)
+{
+ u8 *params = (u8 *)ai;
+ int i;
+
+ hdmi_debug_dip_size(codec);
+ hdmi_clear_dip_buffers(codec); /* be paranoid */
+
+ hdmi_set_dip_index(codec, PIN_NID, 0x0, 0x0);
+ for (i = 0; i < sizeof(ai); i++)
+ hdmi_write_dip_byte(codec, PIN_NID, params[i]);
+}
+
+/*
+ * Compute derived values in channel_allocations[].
+ */
+static void init_channel_allocations(void)
+{
+ int i, j;
+ struct cea_channel_speaker_allocation *p;
+
+ for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
+ p = channel_allocations + i;
+ p->channels = 0;
+ p->spk_mask = 0;
+ for (j = 0; j < ARRAY_SIZE(p->speakers); j++)
+ if (p->speakers[j]) {
+ p->channels++;
+ p->spk_mask |= p->speakers[j];
+ }
+ }
+}
+
+/*
+ * The transformation takes two steps:
+ *
+ * eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask
+ * spk_mask => (channel_allocations[]) => ai->CA
+ *
+ * TODO: it could select the wrong CA from multiple candidates.
+*/
+static int hdmi_setup_channel_allocation(struct hda_codec *codec,
+ struct hdmi_audio_infoframe *ai)
+{
+ struct intel_hdmi_spec *spec = codec->spec;
+ struct hdmi_eld *eld = &spec->sink_eld;
+ int i;
+ int spk_mask = 0;
+ int channels = 1 + (ai->CC02_CT47 & 0x7);
+ char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
+
+ /*
+ * CA defaults to 0 for basic stereo audio
+ */
+ if (!eld->eld_ver)
+ return 0;
+ if (!eld->spk_alloc)
+ return 0;
+ if (channels <= 2)
+ return 0;
+
+ /*
+ * expand ELD's speaker allocation mask
+ *
+ * ELD tells the speaker mask in a compact(paired) form,
+ * expand ELD's notions to match the ones used by Audio InfoFrame.
+ */
+ for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) {
+ if (eld->spk_alloc & (1 << i))
+ spk_mask |= eld_speaker_allocation_bits[i];
+ }
+
+ /* search for the first working match in the CA table */
+ for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
+ if (channels == channel_allocations[i].channels &&
+ (spk_mask & channel_allocations[i].spk_mask) ==
+ channel_allocations[i].spk_mask) {
+ ai->CA = channel_allocations[i].ca_index;
+ break;
+ }
+ }
+
+ snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf));
+ snd_printdd(KERN_INFO
+ "HDMI: select CA 0x%x for %d-channel allocation: %s\n",
+ ai->CA, channels, buf);
+
+ return ai->CA;
+}
+
+static void hdmi_setup_channel_mapping(struct hda_codec *codec,
+ struct hdmi_audio_infoframe *ai)
+{
+ if (!ai->CA)
+ return;
+
+ /*
+ * TODO: adjust channel mapping if necessary
+ * ALSA sequence is front/surr/clfe/side?
+ */
+
+ snd_hda_sequence_write(codec, def_chan_map);
+ hdmi_debug_channel_mapping(codec);
+}
+
+
+static void hdmi_setup_audio_infoframe(struct hda_codec *codec,
+ struct snd_pcm_substream *substream)
+{
+ struct hdmi_audio_infoframe ai = {
+ .type = 0x84,
+ .ver = 0x01,
+ .len = 0x0a,
+ .CC02_CT47 = substream->runtime->channels - 1,
+ };
+
+ hdmi_setup_channel_allocation(codec, &ai);
+ hdmi_setup_channel_mapping(codec, &ai);
+
+ hdmi_fill_audio_infoframe(codec, &ai);
+}
+
+
+/*
+ * Unsolicited events
+ */
+
+static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
+{
+ int pind = !!(res & AC_UNSOL_RES_PD);
+ int eldv = !!(res & AC_UNSOL_RES_ELDV);
+
+ printk(KERN_INFO
+ "HDMI hot plug event: Presence_Detect=%d ELD_Valid=%d\n",
+ pind, eldv);
+
+ if (pind && eldv) {
+ hdmi_parse_eld(codec);
+ /* TODO: do real things about ELD */
+ }
+}
+
+static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res)
+{
+ int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
+ int cp_state = !!(res & AC_UNSOL_RES_CP_STATE);
+ int cp_ready = !!(res & AC_UNSOL_RES_CP_READY);
+
+ printk(KERN_INFO
+ "HDMI content protection event: SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n",
+ subtag,
+ cp_state,
+ cp_ready);
+
+ /* TODO */
+ if (cp_state)
+ ;
+ if (cp_ready)
+ ;
+}
+
+
+static void intel_hdmi_unsol_event(struct hda_codec *codec, unsigned int res)
+{
+ int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
+ int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
+
+ if (tag != INTEL_HDMI_EVENT_TAG) {
+ snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag);
+ return;
+ }
+
+ if (subtag == 0)
+ hdmi_intrinsic_event(codec, res);
+ else
+ hdmi_non_intrinsic_event(codec, res);
+}
+
+/*
+ * Callbacks
+ */
+
+static int intel_hdmi_playback_pcm_open(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ struct snd_pcm_substream *substream)
+{
+ struct intel_hdmi_spec *spec = codec->spec;
+
+ return snd_hda_multi_out_dig_open(codec, &spec->multiout);
+}
+
+static int intel_hdmi_playback_pcm_close(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ struct snd_pcm_substream *substream)
+{
+ struct intel_hdmi_spec *spec = codec->spec;
+
+ hdmi_disable_output(codec);
+
+ return snd_hda_multi_out_dig_close(codec, &spec->multiout);
+}
+
+static int intel_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ unsigned int stream_tag,
+ unsigned int format,
+ struct snd_pcm_substream *substream)
+{
+ struct intel_hdmi_spec *spec = codec->spec;
+
+ snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag,
+ format, substream);
+
+ hdmi_set_channel_count(codec, substream->runtime->channels);
+
+ hdmi_setup_audio_infoframe(codec, substream);
+
+ hdmi_enable_output(codec);
+
+ return 0;
+}
+
+static struct hda_pcm_stream intel_hdmi_pcm_playback = {
+ .substreams = 1,
+ .channels_min = 2,
+ .channels_max = 8,
+ .nid = CVT_NID, /* NID to query formats and rates and setup streams */
+ .ops = {
+ .open = intel_hdmi_playback_pcm_open,
+ .close = intel_hdmi_playback_pcm_close,
+ .prepare = intel_hdmi_playback_pcm_prepare
+ },
+};
+
+static int intel_hdmi_build_pcms(struct hda_codec *codec)
+{
+ struct intel_hdmi_spec *spec = codec->spec;
+ struct hda_pcm *info = &spec->pcm_rec;
+
+ codec->num_pcms = 1;
+ codec->pcm_info = info;
+
+ info->name = "INTEL HDMI";
+ info->pcm_type = HDA_PCM_TYPE_HDMI;
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK] = intel_hdmi_pcm_playback;
+
+ return 0;
+}
+
+static int intel_hdmi_build_controls(struct hda_codec *codec)
+{
+ struct intel_hdmi_spec *spec = codec->spec;
+ int err;
+
+ err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+static int intel_hdmi_init(struct hda_codec *codec)
+{
+ /* disable audio output as early as possible */
+ hdmi_disable_output(codec);
+
+ snd_hda_sequence_write(codec, unsolicited_response_verb);
+
+ return 0;
+}
+
+static void intel_hdmi_free(struct hda_codec *codec)
+{
+ struct intel_hdmi_spec *spec = codec->spec;
+
+ snd_hda_eld_proc_free(codec, &spec->sink_eld);
+ kfree(spec);
+}
+
+static struct hda_codec_ops intel_hdmi_patch_ops = {
+ .init = intel_hdmi_init,
+ .free = intel_hdmi_free,
+ .build_pcms = intel_hdmi_build_pcms,
+ .build_controls = intel_hdmi_build_controls,
+ .unsol_event = intel_hdmi_unsol_event,
+};
+
+static int patch_intel_hdmi(struct hda_codec *codec)
+{
+ struct intel_hdmi_spec *spec;
+
+ spec = kzalloc(sizeof(*spec), GFP_KERNEL);
+ if (spec == NULL)
+ return -ENOMEM;
+
+ spec->multiout.num_dacs = 0; /* no analog */
+ spec->multiout.max_channels = 8;
+ spec->multiout.dig_out_nid = CVT_NID;
+
+ codec->spec = spec;
+ codec->patch_ops = intel_hdmi_patch_ops;
+
+ snd_hda_eld_proc_new(codec, &spec->sink_eld);
+
+ init_channel_allocations();
+
+ return 0;
+}
+
+static struct hda_codec_preset snd_hda_preset_intelhdmi[] = {
+ { .id = 0x808629fb, .name = "G45 DEVCL", .patch = patch_intel_hdmi },
+ { .id = 0x80862801, .name = "G45 DEVBLC", .patch = patch_intel_hdmi },
+ { .id = 0x80862802, .name = "G45 DEVCTG", .patch = patch_intel_hdmi },
+ { .id = 0x80862803, .name = "G45 DEVELK", .patch = patch_intel_hdmi },
+ { .id = 0x10951392, .name = "SiI1392 HDMI", .patch = patch_intel_hdmi },
+ {} /* terminator */
+};
+
+MODULE_ALIAS("snd-hda-codec-id:808629fb");
+MODULE_ALIAS("snd-hda-codec-id:80862801");
+MODULE_ALIAS("snd-hda-codec-id:80862802");
+MODULE_ALIAS("snd-hda-codec-id:80862803");
+MODULE_ALIAS("snd-hda-codec-id:10951392");
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Intel HDMI HD-audio codec");
+
+static struct hda_codec_preset_list intel_list = {
+ .preset = snd_hda_preset_intelhdmi,
+ .owner = THIS_MODULE,
+};
+
+static int __init patch_intelhdmi_init(void)
+{
+ return snd_hda_add_codec_preset(&intel_list);
+}
+
+static void __exit patch_intelhdmi_exit(void)
+{
+ snd_hda_delete_codec_preset(&intel_list);
+}
+
+module_init(patch_intelhdmi_init)
+module_exit(patch_intelhdmi_exit)
diff --git a/sound/pci/hda/patch_nvhdmi.c b/sound/pci/hda/patch_nvhdmi.c
index 2eed2c8b98d..0270fda0bda 100644
--- a/sound/pci/hda/patch_nvhdmi.c
+++ b/sound/pci/hda/patch_nvhdmi.c
@@ -158,8 +158,34 @@ static int patch_nvhdmi(struct hda_codec *codec)
/*
* patch entries
*/
-struct hda_codec_preset snd_hda_preset_nvhdmi[] = {
- { .id = 0x10de0002, .name = "NVIDIA MCP78 HDMI", .patch = patch_nvhdmi },
- { .id = 0x10de0007, .name = "NVIDIA MCP7A HDMI", .patch = patch_nvhdmi },
+static struct hda_codec_preset snd_hda_preset_nvhdmi[] = {
+ { .id = 0x10de0002, .name = "MCP78 HDMI", .patch = patch_nvhdmi },
+ { .id = 0x10de0007, .name = "MCP7A HDMI", .patch = patch_nvhdmi },
+ { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi },
{} /* terminator */
};
+
+MODULE_ALIAS("snd-hda-codec-id:10de0002");
+MODULE_ALIAS("snd-hda-codec-id:10de0007");
+MODULE_ALIAS("snd-hda-codec-id:10de0067");
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Nvidia HDMI HD-audio codec");
+
+static struct hda_codec_preset_list nvhdmi_list = {
+ .preset = snd_hda_preset_nvhdmi,
+ .owner = THIS_MODULE,
+};
+
+static int __init patch_nvhdmi_init(void)
+{
+ return snd_hda_add_codec_preset(&nvhdmi_list);
+}
+
+static void __exit patch_nvhdmi_exit(void)
+{
+ snd_hda_delete_codec_preset(&nvhdmi_list);
+}
+
+module_init(patch_nvhdmi_init)
+module_exit(patch_nvhdmi_exit)
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index a378c014512..0bd4e6bf354 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -30,7 +30,6 @@
#include <sound/core.h>
#include "hda_codec.h"
#include "hda_local.h"
-#include "hda_patch.h"
#define ALC880_FRONT_EVENT 0x01
#define ALC880_DCVOL_EVENT 0x02
@@ -114,6 +113,7 @@ enum {
ALC268_3ST,
ALC268_TOSHIBA,
ALC268_ACER,
+ ALC268_ACER_DMIC,
ALC268_ACER_ASPIRE_ONE,
ALC268_DELL,
ALC268_ZEPTO,
@@ -130,6 +130,8 @@ enum {
ALC269_QUANTA_FL1,
ALC269_ASUS_EEEPC_P703,
ALC269_ASUS_EEEPC_P901,
+ ALC269_FUJITSU,
+ ALC269_LIFEBOOK,
ALC269_AUTO,
ALC269_MODEL_LAST /* last tag */
};
@@ -152,6 +154,7 @@ enum {
enum {
ALC660VD_3ST,
ALC660VD_3ST_DIG,
+ ALC660VD_ASUS_V1S,
ALC861VD_3ST,
ALC861VD_3ST_DIG,
ALC861VD_6ST_DIG,
@@ -212,6 +215,7 @@ enum {
ALC883_TARGA_2ch_DIG,
ALC883_ACER,
ALC883_ACER_ASPIRE,
+ ALC888_ACER_ASPIRE_4930G,
ALC883_MEDION,
ALC883_MEDION_MD2,
ALC883_LAPTOP_EAPD,
@@ -225,9 +229,11 @@ enum {
ALC883_MITAC,
ALC883_CLEVO_M720,
ALC883_FUJITSU_PI2515,
+ ALC888_FUJITSU_XA3530,
ALC883_3ST_6ch_INTEL,
ALC888_ASUS_M90V,
ALC888_ASUS_EEE1601,
+ ALC1200_ASUS_P5Q,
ALC883_AUTO,
ALC883_MODEL_LAST,
};
@@ -239,6 +245,7 @@ struct alc_spec {
/* codec parameterization */
struct snd_kcontrol_new *mixers[5]; /* mixer arrays */
unsigned int num_mixers;
+ struct snd_kcontrol_new *cap_mixer; /* capture mixer */
const struct hda_verb *init_verbs[5]; /* initialization verbs
* don't forget NULL
@@ -268,6 +275,7 @@ struct alc_spec {
hda_nid_t *adc_nids;
hda_nid_t *capsrc_nids;
hda_nid_t dig_in_nid; /* digital-in NID; optional */
+ unsigned char is_mix_capture; /* matrix-style capture (non-mux) */
/* capture source */
unsigned int num_mux_defs;
@@ -284,8 +292,7 @@ struct alc_spec {
/* dynamic controls, init_verbs and input_mux */
struct auto_pin_cfg autocfg;
- unsigned int num_kctl_alloc, num_kctl_used;
- struct snd_kcontrol_new *kctl_alloc;
+ struct snd_array kctls;
struct hda_input_mux private_imux;
hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
@@ -323,6 +330,7 @@ struct alc_config_preset {
struct snd_kcontrol_new *mixers[5]; /* should be identical size
* with spec
*/
+ struct snd_kcontrol_new *cap_mixer; /* capture mixer */
const struct hda_verb *init_verbs[5];
unsigned int num_dacs;
hda_nid_t *dac_nids;
@@ -375,14 +383,39 @@ static int alc_mux_enum_put(struct snd_kcontrol *kcontrol,
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct alc_spec *spec = codec->spec;
+ const struct hda_input_mux *imux;
unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
- unsigned int mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx;
+ unsigned int mux_idx;
hda_nid_t nid = spec->capsrc_nids ?
spec->capsrc_nids[adc_idx] : spec->adc_nids[adc_idx];
- return snd_hda_input_mux_put(codec, &spec->input_mux[mux_idx], ucontrol,
- nid, &spec->cur_mux[adc_idx]);
-}
+ mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx;
+ imux = &spec->input_mux[mux_idx];
+
+ if (spec->is_mix_capture) {
+ /* Matrix-mixer style (e.g. ALC882) */
+ unsigned int *cur_val = &spec->cur_mux[adc_idx];
+ unsigned int i, idx;
+
+ idx = ucontrol->value.enumerated.item[0];
+ if (idx >= imux->num_items)
+ idx = imux->num_items - 1;
+ if (*cur_val == idx)
+ return 0;
+ for (i = 0; i < imux->num_items; i++) {
+ unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE;
+ snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT,
+ imux->items[i].index,
+ HDA_AMP_MUTE, v);
+ }
+ *cur_val = idx;
+ return 1;
+ } else {
+ /* MUX style (e.g. ALC880) */
+ return snd_hda_input_mux_put(codec, imux, ucontrol, nid,
+ &spec->cur_mux[adc_idx]);
+ }
+}
/*
* channel mode setting
@@ -717,6 +750,43 @@ static int alc_eapd_ctrl_put(struct snd_kcontrol *kcontrol,
#endif /* CONFIG_SND_DEBUG */
/*
+ */
+static void add_mixer(struct alc_spec *spec, struct snd_kcontrol_new *mix)
+{
+ if (snd_BUG_ON(spec->num_mixers >= ARRAY_SIZE(spec->mixers)))
+ return;
+ spec->mixers[spec->num_mixers++] = mix;
+}
+
+static void add_verb(struct alc_spec *spec, const struct hda_verb *verb)
+{
+ if (snd_BUG_ON(spec->num_init_verbs >= ARRAY_SIZE(spec->init_verbs)))
+ return;
+ spec->init_verbs[spec->num_init_verbs++] = verb;
+}
+
+#ifdef CONFIG_PROC_FS
+/*
+ * hook for proc
+ */
+static void print_realtek_coef(struct snd_info_buffer *buffer,
+ struct hda_codec *codec, hda_nid_t nid)
+{
+ int coeff;
+
+ if (nid != 0x20)
+ return;
+ coeff = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PROC_COEF, 0);
+ snd_iprintf(buffer, " Processing Coefficient: 0x%02x\n", coeff);
+ coeff = snd_hda_codec_read(codec, nid, 0,
+ AC_VERB_GET_COEF_INDEX, 0);
+ snd_iprintf(buffer, " Coefficient Index: 0x%02x\n", coeff);
+}
+#else
+#define print_realtek_coef NULL
+#endif
+
+/*
* set up from the preset table
*/
static void setup_preset(struct alc_spec *spec,
@@ -725,11 +795,11 @@ static void setup_preset(struct alc_spec *spec,
int i;
for (i = 0; i < ARRAY_SIZE(preset->mixers) && preset->mixers[i]; i++)
- spec->mixers[spec->num_mixers++] = preset->mixers[i];
+ add_mixer(spec, preset->mixers[i]);
+ spec->cap_mixer = preset->cap_mixer;
for (i = 0; i < ARRAY_SIZE(preset->init_verbs) && preset->init_verbs[i];
i++)
- spec->init_verbs[spec->num_init_verbs++] =
- preset->init_verbs[i];
+ add_verb(spec, preset->init_verbs[i]);
spec->channel_mode = preset->channel_mode;
spec->num_channel_mode = preset->num_channel_mode;
@@ -1107,6 +1177,226 @@ static void alc_fix_pincfg(struct hda_codec *codec,
}
/*
+ * ALC888
+ */
+
+/*
+ * 2ch mode
+ */
+static struct hda_verb alc888_4ST_ch2_intel_init[] = {
+/* Mic-in jack as mic in */
+ { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
+ { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+/* Line-in jack as Line in */
+ { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
+ { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+/* Line-Out as Front */
+ { 0x17, AC_VERB_SET_CONNECT_SEL, 0x00},
+ { } /* end */
+};
+
+/*
+ * 4ch mode
+ */
+static struct hda_verb alc888_4ST_ch4_intel_init[] = {
+/* Mic-in jack as mic in */
+ { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
+ { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+/* Line-in jack as Surround */
+ { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+ { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+/* Line-Out as Front */
+ { 0x17, AC_VERB_SET_CONNECT_SEL, 0x00},
+ { } /* end */
+};
+
+/*
+ * 6ch mode
+ */
+static struct hda_verb alc888_4ST_ch6_intel_init[] = {
+/* Mic-in jack as CLFE */
+ { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+ { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+/* Line-in jack as Surround */
+ { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+ { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+/* Line-Out as CLFE (workaround because Mic-in is not loud enough) */
+ { 0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
+ { } /* end */
+};
+
+/*
+ * 8ch mode
+ */
+static struct hda_verb alc888_4ST_ch8_intel_init[] = {
+/* Mic-in jack as CLFE */
+ { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+ { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+/* Line-in jack as Surround */
+ { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+ { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+/* Line-Out as Side */
+ { 0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
+ { } /* end */
+};
+
+static struct hda_channel_mode alc888_4ST_8ch_intel_modes[4] = {
+ { 2, alc888_4ST_ch2_intel_init },
+ { 4, alc888_4ST_ch4_intel_init },
+ { 6, alc888_4ST_ch6_intel_init },
+ { 8, alc888_4ST_ch8_intel_init },
+};
+
+/*
+ * ALC888 Fujitsu Siemens Amillo xa3530
+ */
+
+static struct hda_verb alc888_fujitsu_xa3530_verbs[] = {
+/* Front Mic: set to PIN_IN (empty by default) */
+ {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+/* Connect Internal HP to Front */
+ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
+/* Connect Bass HP to Front */
+ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
+/* Connect Line-Out side jack (SPDIF) to Side */
+ {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
+/* Connect Mic jack to CLFE */
+ {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},
+/* Connect Line-in jack to Surround */
+ {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},
+/* Connect HP out jack to Front */
+ {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
+/* Enable unsolicited event for HP jack and Line-out jack */
+ {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
+ {0x17, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
+ {}
+};
+
+static void alc888_fujitsu_xa3530_automute(struct hda_codec *codec)
+{
+ unsigned int present;
+ unsigned int bits;
+ /* Line out presence */
+ present = snd_hda_codec_read(codec, 0x17, 0,
+ AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+ /* HP out presence */
+ present = present || snd_hda_codec_read(codec, 0x1b, 0,
+ AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+ bits = present ? HDA_AMP_MUTE : 0;
+ /* Toggle internal speakers muting */
+ snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, bits);
+ /* Toggle internal bass muting */
+ snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, bits);
+}
+
+static void alc888_fujitsu_xa3530_unsol_event(struct hda_codec *codec,
+ unsigned int res)
+{
+ if (res >> 26 == ALC880_HP_EVENT)
+ alc888_fujitsu_xa3530_automute(codec);
+}
+
+
+/*
+ * ALC888 Acer Aspire 4930G model
+ */
+
+static struct hda_verb alc888_acer_aspire_4930g_verbs[] = {
+/* Front Mic: set to PIN_IN (empty by default) */
+ {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+/* Unselect Front Mic by default in input mixer 3 */
+ {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0xb)},
+/* Enable unsolicited event for HP jack */
+ {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
+/* Connect Internal HP to front */
+ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
+/* Connect HP out to front */
+ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
+ { }
+};
+
+static struct hda_input_mux alc888_2_capture_sources[2] = {
+ /* Front mic only available on one ADC */
+ {
+ .num_items = 4,
+ .items = {
+ { "Mic", 0x0 },
+ { "Line", 0x2 },
+ { "CD", 0x4 },
+ { "Front Mic", 0xb },
+ },
+ },
+ {
+ .num_items = 3,
+ .items = {
+ { "Mic", 0x0 },
+ { "Line", 0x2 },
+ { "CD", 0x4 },
+ },
+ }
+};
+
+static struct snd_kcontrol_new alc888_base_mixer[] = {
+ HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+ HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+ HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+ HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
+ HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0,
+ HDA_OUTPUT),
+ HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+ HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+ HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
+ HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
+ HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
+ 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_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
+ HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
+ HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
+ { } /* end */
+};
+
+static void alc888_acer_aspire_4930g_automute(struct hda_codec *codec)
+{
+ unsigned int present;
+ unsigned int bits;
+ present = snd_hda_codec_read(codec, 0x15, 0,
+ AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+ bits = present ? HDA_AMP_MUTE : 0;
+ snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, bits);
+}
+
+static void alc888_acer_aspire_4930g_unsol_event(struct hda_codec *codec,
+ unsigned int res)
+{
+ if (res >> 26 == ALC880_HP_EVENT)
+ alc888_acer_aspire_4930g_automute(codec);
+}
+
+/*
* ALC880 3-stack model
*
* DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0e)
@@ -1205,49 +1495,126 @@ static struct snd_kcontrol_new alc880_three_stack_mixer[] = {
};
/* capture mixer elements */
-static struct snd_kcontrol_new alc880_capture_mixer[] = {
- HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- /* The multiple "Capture Source" controls confuse alsamixer
- * So call somewhat different..
- */
- /* .name = "Capture Source", */
- .name = "Input Source",
- .count = 3,
- .info = alc_mux_enum_info,
- .get = alc_mux_enum_get,
- .put = alc_mux_enum_put,
- },
- { } /* end */
-};
+static int alc_cap_vol_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct alc_spec *spec = codec->spec;
+ int err;
-/* capture mixer elements (in case NID 0x07 not available) */
-static struct snd_kcontrol_new alc880_capture_alt_mixer[] = {
- 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,
- /* The multiple "Capture Source" controls confuse alsamixer
- * So call somewhat different..
- */
- /* .name = "Capture Source", */
- .name = "Input Source",
- .count = 2,
- .info = alc_mux_enum_info,
- .get = alc_mux_enum_get,
- .put = alc_mux_enum_put,
- },
- { } /* end */
-};
+ mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */
+ kcontrol->private_value = HDA_COMPOSE_AMP_VAL(spec->adc_nids[0], 3, 0,
+ HDA_INPUT);
+ err = snd_hda_mixer_amp_volume_info(kcontrol, uinfo);
+ mutex_unlock(&codec->spdif_mutex); /* reuse spdif_mutex */
+ return err;
+}
+
+static int alc_cap_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
+ unsigned int size, unsigned int __user *tlv)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct alc_spec *spec = codec->spec;
+ int err;
+ mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */
+ kcontrol->private_value = HDA_COMPOSE_AMP_VAL(spec->adc_nids[0], 3, 0,
+ HDA_INPUT);
+ err = snd_hda_mixer_amp_tlv(kcontrol, op_flag, size, tlv);
+ mutex_unlock(&codec->spdif_mutex); /* reuse spdif_mutex */
+ return err;
+}
+
+typedef int (*getput_call_t)(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
+
+static int alc_cap_getput_caller(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol,
+ getput_call_t func)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct alc_spec *spec = codec->spec;
+ unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+ int err;
+
+ mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */
+ kcontrol->private_value = HDA_COMPOSE_AMP_VAL(spec->adc_nids[adc_idx],
+ 3, 0, HDA_INPUT);
+ err = func(kcontrol, ucontrol);
+ mutex_unlock(&codec->spdif_mutex); /* reuse spdif_mutex */
+ return err;
+}
+
+static int alc_cap_vol_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ return alc_cap_getput_caller(kcontrol, ucontrol,
+ snd_hda_mixer_amp_volume_get);
+}
+
+static int alc_cap_vol_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ return alc_cap_getput_caller(kcontrol, ucontrol,
+ snd_hda_mixer_amp_volume_put);
+}
+
+/* capture mixer elements */
+#define alc_cap_sw_info snd_ctl_boolean_stereo_info
+
+static int alc_cap_sw_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ return alc_cap_getput_caller(kcontrol, ucontrol,
+ snd_hda_mixer_amp_switch_get);
+}
+
+static int alc_cap_sw_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ return alc_cap_getput_caller(kcontrol, ucontrol,
+ snd_hda_mixer_amp_switch_put);
+}
+
+#define DEFINE_CAPMIX(num) \
+static struct snd_kcontrol_new alc_capture_mixer ## num[] = { \
+ { \
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+ .name = "Capture Switch", \
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
+ .count = num, \
+ .info = alc_cap_sw_info, \
+ .get = alc_cap_sw_get, \
+ .put = alc_cap_sw_put, \
+ }, \
+ { \
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+ .name = "Capture Volume", \
+ .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | \
+ SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
+ SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK), \
+ .count = num, \
+ .info = alc_cap_vol_info, \
+ .get = alc_cap_vol_get, \
+ .put = alc_cap_vol_put, \
+ .tlv = { .c = alc_cap_vol_tlv }, \
+ }, \
+ { \
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+ /* .name = "Capture Source", */ \
+ .name = "Input Source", \
+ .count = num, \
+ .info = alc_mux_enum_info, \
+ .get = alc_mux_enum_get, \
+ .put = alc_mux_enum_put, \
+ }, \
+ { } /* end */ \
+}
+
+/* up to three ADCs */
+DEFINE_CAPMIX(1);
+DEFINE_CAPMIX(2);
+DEFINE_CAPMIX(3);
/*
@@ -1533,18 +1900,6 @@ static struct snd_kcontrol_new alc880_tcl_s700_mixer[] = {
HDA_CODEC_MUTE("Mic Playback Switch", 0x0B, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- /* The multiple "Capture Source" controls confuse alsamixer
- * So call somewhat different..
- */
- /* .name = "Capture Source", */
- .name = "Input Source",
- .count = 1,
- .info = alc_mux_enum_info,
- .get = alc_mux_enum_get,
- .put = alc_mux_enum_put,
- },
{ } /* end */
};
@@ -1619,6 +1974,7 @@ static const char *alc_slave_vols[] = {
"Speaker Playback Volume",
"Mono Playback Volume",
"Line-Out Playback Volume",
+ "PCM Playback Volume",
NULL,
};
@@ -1638,6 +1994,9 @@ static const char *alc_slave_sws[] = {
/*
* build control elements
*/
+
+static void alc_free_kctls(struct hda_codec *codec);
+
static int alc_build_controls(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
@@ -1649,7 +2008,11 @@ static int alc_build_controls(struct hda_codec *codec)
if (err < 0)
return err;
}
-
+ if (spec->cap_mixer) {
+ err = snd_hda_add_new_ctls(codec, spec->cap_mixer);
+ if (err < 0)
+ return err;
+ }
if (spec->multiout.dig_out_nid) {
err = snd_hda_create_spdif_out_ctls(codec,
spec->multiout.dig_out_nid);
@@ -1684,6 +2047,7 @@ static int alc_build_controls(struct hda_codec *codec)
return err;
}
+ alc_free_kctls(codec); /* no longer needed */
return 0;
}
@@ -2774,19 +3138,27 @@ static int alc_build_pcms(struct hda_codec *codec)
return 0;
}
+static void alc_free_kctls(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+
+ if (spec->kctls.list) {
+ struct snd_kcontrol_new *kctl = spec->kctls.list;
+ int i;
+ for (i = 0; i < spec->kctls.used; i++)
+ kfree(kctl[i].name);
+ }
+ snd_array_free(&spec->kctls);
+}
+
static void alc_free(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- unsigned int i;
if (!spec)
return;
- if (spec->kctl_alloc) {
- for (i = 0; i < spec->num_kctl_used; i++)
- kfree(spec->kctl_alloc[i].name);
- kfree(spec->kctl_alloc);
- }
+ alc_free_kctls(codec);
kfree(spec);
codec->spec = NULL; /* to be sure */
}
@@ -3268,6 +3640,8 @@ static struct alc_config_preset alc880_presets[] = {
alc880_gpio2_init_verbs },
.num_dacs = ARRAY_SIZE(alc880_dac_nids),
.dac_nids = alc880_dac_nids,
+ .adc_nids = alc880_adc_nids_alt, /* FIXME: correct? */
+ .num_adc_nids = 1, /* single ADC */
.hp_nid = 0x03,
.num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
.channel_mode = alc880_2_jack_modes,
@@ -3532,9 +3906,6 @@ static struct alc_config_preset alc880_presets[] = {
* Automatic parse of I/O pins from the BIOS configuration
*/
-#define NUM_CONTROL_ALLOC 32
-#define NUM_VERB_ALLOC 32
-
enum {
ALC_CTL_WIDGET_VOL,
ALC_CTL_WIDGET_MUTE,
@@ -3552,29 +3923,15 @@ static int add_control(struct alc_spec *spec, int type, const char *name,
{
struct snd_kcontrol_new *knew;
- if (spec->num_kctl_used >= spec->num_kctl_alloc) {
- int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC;
-
- /* array + terminator */
- knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL);
- if (!knew)
- return -ENOMEM;
- if (spec->kctl_alloc) {
- memcpy(knew, spec->kctl_alloc,
- sizeof(*knew) * spec->num_kctl_alloc);
- kfree(spec->kctl_alloc);
- }
- spec->kctl_alloc = knew;
- spec->num_kctl_alloc = num;
- }
-
- knew = &spec->kctl_alloc[spec->num_kctl_used];
+ snd_array_init(&spec->kctls, sizeof(*knew), 32);
+ knew = snd_array_new(&spec->kctls);
+ if (!knew)
+ return -ENOMEM;
*knew = alc880_control_templates[type];
knew->name = kstrdup(name, GFP_KERNEL);
if (!knew->name)
return -ENOMEM;
knew->private_value = val;
- spec->num_kctl_used++;
return 0;
}
@@ -3898,10 +4255,10 @@ static int alc880_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_in_pin)
spec->dig_in_nid = ALC880_DIGIN_NID;
- if (spec->kctl_alloc)
- spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
+ if (spec->kctls.list)
+ add_mixer(spec, spec->kctls.list);
- spec->init_verbs[spec->num_init_verbs++] = alc880_volume_init_verbs;
+ add_verb(spec, alc880_volume_init_verbs);
spec->num_mux_defs = 1;
spec->input_mux = &spec->private_imux;
@@ -3925,6 +4282,17 @@ static void alc880_auto_init(struct hda_codec *codec)
* OK, here we have finally the patch for ALC880
*/
+static void set_capture_mixer(struct alc_spec *spec)
+{
+ static struct snd_kcontrol_new *caps[3] = {
+ alc_capture_mixer1,
+ alc_capture_mixer2,
+ alc_capture_mixer3,
+ };
+ if (spec->num_adc_nids > 0 && spec->num_adc_nids <= 3)
+ spec->cap_mixer = caps[spec->num_adc_nids - 1];
+}
+
static int patch_alc880(struct hda_codec *codec)
{
struct alc_spec *spec;
@@ -3980,16 +4348,12 @@ static int patch_alc880(struct hda_codec *codec)
if (wcap != AC_WID_AUD_IN) {
spec->adc_nids = alc880_adc_nids_alt;
spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids_alt);
- spec->mixers[spec->num_mixers] =
- alc880_capture_alt_mixer;
- spec->num_mixers++;
} else {
spec->adc_nids = alc880_adc_nids;
spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids);
- spec->mixers[spec->num_mixers] = alc880_capture_mixer;
- spec->num_mixers++;
}
}
+ set_capture_mixer(spec);
spec->vmaster_nid = 0x0c;
@@ -4000,6 +4364,7 @@ static int patch_alc880(struct hda_codec *codec)
if (!spec->loopback.amplist)
spec->loopback.amplist = alc880_loopbacks;
#endif
+ codec->proc_widget_hook = print_realtek_coef;
return 0;
}
@@ -4024,11 +4389,6 @@ static hda_nid_t alc260_adc_nids_alt[1] = {
0x05,
};
-static hda_nid_t alc260_hp_adc_nids[2] = {
- /* ADC1, 0 */
- 0x05, 0x04
-};
-
/* NIDs used when simultaneous access to both ADCs makes sense. Note that
* alc260_capture_mixer assumes ADC0 (nid 0x04) is the first ADC.
*/
@@ -4157,13 +4517,13 @@ static void alc260_hp_master_update(struct hda_codec *codec,
struct alc_spec *spec = codec->spec;
unsigned int val = spec->master_sw ? PIN_HP : 0;
/* change HP and line-out pins */
- snd_hda_codec_write(codec, 0x0f, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
+ snd_hda_codec_write(codec, hp, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
val);
- snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
+ snd_hda_codec_write(codec, line, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
val);
/* mono (speaker) depending on the HP jack sense */
val = (val && !spec->jack_present) ? PIN_OUT : 0;
- snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
+ snd_hda_codec_write(codec, mono, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
val);
}
@@ -4242,7 +4602,7 @@ static struct snd_kcontrol_new alc260_hp_3013_mixer[] = {
.info = snd_ctl_boolean_mono_info,
.get = alc260_hp_master_sw_get,
.put = alc260_hp_master_sw_put,
- .private_value = (0x10 << 16) | (0x15 << 8) | 0x11
+ .private_value = (0x15 << 16) | (0x10 << 8) | 0x11
},
HDA_CODEC_VOLUME("Front Playback Volume", 0x09, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Front Playback Switch", 0x10, 0x0, HDA_OUTPUT),
@@ -4295,7 +4655,7 @@ static void alc260_hp_3013_automute(struct hda_codec *codec)
present = snd_hda_codec_read(codec, 0x15, 0,
AC_VERB_GET_PIN_SENSE, 0);
spec->jack_present = (present & AC_PINSENSE_PRESENCE) != 0;
- alc260_hp_master_update(codec, 0x10, 0x15, 0x11);
+ alc260_hp_master_update(codec, 0x15, 0x10, 0x11);
}
static void alc260_hp_3013_unsol_event(struct hda_codec *codec,
@@ -4427,45 +4787,6 @@ static struct snd_kcontrol_new alc260_replacer_672v_mixer[] = {
{ } /* end */
};
-/* capture mixer elements */
-static struct snd_kcontrol_new alc260_capture_mixer[] = {
- HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Capture Switch", 0x04, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x05, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x05, 0x0, HDA_INPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- /* The multiple "Capture Source" controls confuse alsamixer
- * So call somewhat different..
- */
- /* .name = "Capture Source", */
- .name = "Input Source",
- .count = 2,
- .info = alc_mux_enum_info,
- .get = alc_mux_enum_get,
- .put = alc_mux_enum_put,
- },
- { } /* end */
-};
-
-static struct snd_kcontrol_new alc260_capture_alt_mixer[] = {
- HDA_CODEC_VOLUME("Capture Volume", 0x05, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Capture Switch", 0x05, 0x0, HDA_INPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- /* The multiple "Capture Source" controls confuse alsamixer
- * So call somewhat different..
- */
- /* .name = "Capture Source", */
- .name = "Input Source",
- .count = 1,
- .info = alc_mux_enum_info,
- .get = alc_mux_enum_get,
- .put = alc_mux_enum_put,
- },
- { } /* end */
-};
-
/*
* initialization verbs
*/
@@ -5282,7 +5603,6 @@ static struct hda_verb alc260_volume_init_verbs[] = {
static int alc260_parse_auto_config(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- unsigned int wcap;
int err;
static hda_nid_t alc260_ignore[] = { 0x17, 0 };
@@ -5293,7 +5613,7 @@ static int alc260_parse_auto_config(struct hda_codec *codec)
err = alc260_auto_create_multi_out_ctls(spec, &spec->autocfg);
if (err < 0)
return err;
- if (!spec->kctl_alloc)
+ if (!spec->kctls.list)
return 0; /* can't find valid BIOS pin config */
err = alc260_auto_create_analog_input_ctls(spec, &spec->autocfg);
if (err < 0)
@@ -5303,28 +5623,14 @@ static int alc260_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_out_pin)
spec->multiout.dig_out_nid = ALC260_DIGOUT_NID;
- if (spec->kctl_alloc)
- spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
+ if (spec->kctls.list)
+ add_mixer(spec, spec->kctls.list);
- spec->init_verbs[spec->num_init_verbs++] = alc260_volume_init_verbs;
+ add_verb(spec, alc260_volume_init_verbs);
spec->num_mux_defs = 1;
spec->input_mux = &spec->private_imux;
- /* check whether NID 0x04 is valid */
- wcap = get_wcaps(codec, 0x04);
- wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */
- if (wcap != AC_WID_AUD_IN || spec->input_mux->num_items == 1) {
- spec->adc_nids = alc260_adc_nids_alt;
- spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt);
- spec->mixers[spec->num_mixers] = alc260_capture_alt_mixer;
- } else {
- spec->adc_nids = alc260_adc_nids;
- spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids);
- spec->mixers[spec->num_mixers] = alc260_capture_mixer;
- }
- spec->num_mixers++;
-
store_pin_configs(codec);
return 1;
}
@@ -5394,12 +5700,11 @@ static struct alc_config_preset alc260_presets[] = {
[ALC260_BASIC] = {
.mixers = { alc260_base_output_mixer,
alc260_input_mixer,
- alc260_pc_beep_mixer,
- alc260_capture_mixer },
+ alc260_pc_beep_mixer },
.init_verbs = { alc260_init_verbs },
.num_dacs = ARRAY_SIZE(alc260_dac_nids),
.dac_nids = alc260_dac_nids,
- .num_adc_nids = ARRAY_SIZE(alc260_adc_nids),
+ .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
.adc_nids = alc260_adc_nids,
.num_channel_mode = ARRAY_SIZE(alc260_modes),
.channel_mode = alc260_modes,
@@ -5407,14 +5712,13 @@ static struct alc_config_preset alc260_presets[] = {
},
[ALC260_HP] = {
.mixers = { alc260_hp_output_mixer,
- alc260_input_mixer,
- alc260_capture_alt_mixer },
+ alc260_input_mixer },
.init_verbs = { alc260_init_verbs,
alc260_hp_unsol_verbs },
.num_dacs = ARRAY_SIZE(alc260_dac_nids),
.dac_nids = alc260_dac_nids,
- .num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids),
- .adc_nids = alc260_hp_adc_nids,
+ .num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt),
+ .adc_nids = alc260_adc_nids_alt,
.num_channel_mode = ARRAY_SIZE(alc260_modes),
.channel_mode = alc260_modes,
.input_mux = &alc260_capture_source,
@@ -5423,14 +5727,13 @@ static struct alc_config_preset alc260_presets[] = {
},
[ALC260_HP_DC7600] = {
.mixers = { alc260_hp_dc7600_mixer,
- alc260_input_mixer,
- alc260_capture_alt_mixer },
+ alc260_input_mixer },
.init_verbs = { alc260_init_verbs,
alc260_hp_dc7600_verbs },
.num_dacs = ARRAY_SIZE(alc260_dac_nids),
.dac_nids = alc260_dac_nids,
- .num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids),
- .adc_nids = alc260_hp_adc_nids,
+ .num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt),
+ .adc_nids = alc260_adc_nids_alt,
.num_channel_mode = ARRAY_SIZE(alc260_modes),
.channel_mode = alc260_modes,
.input_mux = &alc260_capture_source,
@@ -5439,14 +5742,13 @@ static struct alc_config_preset alc260_presets[] = {
},
[ALC260_HP_3013] = {
.mixers = { alc260_hp_3013_mixer,
- alc260_input_mixer,
- alc260_capture_alt_mixer },
+ alc260_input_mixer },
.init_verbs = { alc260_hp_3013_init_verbs,
alc260_hp_3013_unsol_verbs },
.num_dacs = ARRAY_SIZE(alc260_dac_nids),
.dac_nids = alc260_dac_nids,
- .num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids),
- .adc_nids = alc260_hp_adc_nids,
+ .num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt),
+ .adc_nids = alc260_adc_nids_alt,
.num_channel_mode = ARRAY_SIZE(alc260_modes),
.channel_mode = alc260_modes,
.input_mux = &alc260_capture_source,
@@ -5454,8 +5756,7 @@ static struct alc_config_preset alc260_presets[] = {
.init_hook = alc260_hp_3013_automute,
},
[ALC260_FUJITSU_S702X] = {
- .mixers = { alc260_fujitsu_mixer,
- alc260_capture_mixer },
+ .mixers = { alc260_fujitsu_mixer },
.init_verbs = { alc260_fujitsu_init_verbs },
.num_dacs = ARRAY_SIZE(alc260_dac_nids),
.dac_nids = alc260_dac_nids,
@@ -5467,8 +5768,7 @@ static struct alc_config_preset alc260_presets[] = {
.input_mux = alc260_fujitsu_capture_sources,
},
[ALC260_ACER] = {
- .mixers = { alc260_acer_mixer,
- alc260_capture_mixer },
+ .mixers = { alc260_acer_mixer },
.init_verbs = { alc260_acer_init_verbs },
.num_dacs = ARRAY_SIZE(alc260_dac_nids),
.dac_nids = alc260_dac_nids,
@@ -5480,8 +5780,7 @@ static struct alc_config_preset alc260_presets[] = {
.input_mux = alc260_acer_capture_sources,
},
[ALC260_WILL] = {
- .mixers = { alc260_will_mixer,
- alc260_capture_mixer },
+ .mixers = { alc260_will_mixer },
.init_verbs = { alc260_init_verbs, alc260_will_verbs },
.num_dacs = ARRAY_SIZE(alc260_dac_nids),
.dac_nids = alc260_dac_nids,
@@ -5493,8 +5792,7 @@ static struct alc_config_preset alc260_presets[] = {
.input_mux = &alc260_capture_source,
},
[ALC260_REPLACER_672V] = {
- .mixers = { alc260_replacer_672v_mixer,
- alc260_capture_mixer },
+ .mixers = { alc260_replacer_672v_mixer },
.init_verbs = { alc260_init_verbs, alc260_replacer_672v_verbs },
.num_dacs = ARRAY_SIZE(alc260_dac_nids),
.dac_nids = alc260_dac_nids,
@@ -5509,8 +5807,7 @@ static struct alc_config_preset alc260_presets[] = {
},
#ifdef CONFIG_SND_DEBUG
[ALC260_TEST] = {
- .mixers = { alc260_test_mixer,
- alc260_capture_mixer },
+ .mixers = { alc260_test_mixer },
.init_verbs = { alc260_test_init_verbs },
.num_dacs = ARRAY_SIZE(alc260_test_dac_nids),
.dac_nids = alc260_test_dac_nids,
@@ -5569,6 +5866,21 @@ static int patch_alc260(struct hda_codec *codec)
spec->stream_digital_playback = &alc260_pcm_digital_playback;
spec->stream_digital_capture = &alc260_pcm_digital_capture;
+ if (!spec->adc_nids && spec->input_mux) {
+ /* check whether NID 0x04 is valid */
+ unsigned int wcap = get_wcaps(codec, 0x04);
+ wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
+ /* get type */
+ if (wcap != AC_WID_AUD_IN || spec->input_mux->num_items == 1) {
+ spec->adc_nids = alc260_adc_nids_alt;
+ spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt);
+ } else {
+ spec->adc_nids = alc260_adc_nids;
+ spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids);
+ }
+ }
+ set_capture_mixer(spec);
+
spec->vmaster_nid = 0x08;
codec->patch_ops = alc_patch_ops;
@@ -5578,6 +5890,7 @@ static int patch_alc260(struct hda_codec *codec)
if (!spec->loopback.amplist)
spec->loopback.amplist = alc260_loopbacks;
#endif
+ codec->proc_widget_hook = print_realtek_coef;
return 0;
}
@@ -5625,36 +5938,6 @@ static struct hda_input_mux alc882_capture_source = {
{ "CD", 0x4 },
},
};
-#define alc882_mux_enum_info alc_mux_enum_info
-#define alc882_mux_enum_get alc_mux_enum_get
-
-static int alc882_mux_enum_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct alc_spec *spec = codec->spec;
- const struct hda_input_mux *imux = spec->input_mux;
- unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
- hda_nid_t nid = spec->capsrc_nids ?
- spec->capsrc_nids[adc_idx] : spec->adc_nids[adc_idx];
- unsigned int *cur_val = &spec->cur_mux[adc_idx];
- unsigned int i, idx;
-
- idx = ucontrol->value.enumerated.item[0];
- if (idx >= imux->num_items)
- idx = imux->num_items - 1;
- if (*cur_val == idx)
- return 0;
- for (i = 0; i < imux->num_items; i++) {
- unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE;
- snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT,
- imux->items[i].index,
- HDA_AMP_MUTE, v);
- }
- *cur_val = idx;
- return 1;
-}
-
/*
* 2ch mode
*/
@@ -6337,49 +6620,6 @@ static struct hda_verb alc882_auto_init_verbs[] = {
{ }
};
-/* capture mixer elements */
-static struct snd_kcontrol_new alc882_capture_alt_mixer[] = {
- 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,
- /* The multiple "Capture Source" controls confuse alsamixer
- * So call somewhat different..
- */
- /* .name = "Capture Source", */
- .name = "Input Source",
- .count = 2,
- .info = alc882_mux_enum_info,
- .get = alc882_mux_enum_get,
- .put = alc882_mux_enum_put,
- },
- { } /* end */
-};
-
-static struct snd_kcontrol_new alc882_capture_mixer[] = {
- HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- /* The multiple "Capture Source" controls confuse alsamixer
- * So call somewhat different..
- */
- /* .name = "Capture Source", */
- .name = "Input Source",
- .count = 3,
- .info = alc882_mux_enum_info,
- .get = alc882_mux_enum_get,
- .put = alc882_mux_enum_put,
- },
- { } /* end */
-};
-
#ifdef CONFIG_SND_HDA_POWER_SAVE
#define alc882_loopbacks alc880_loopbacks
#endif
@@ -6508,8 +6748,7 @@ static struct alc_config_preset alc882_presets[] = {
.init_hook = alc885_imac24_init_hook,
},
[ALC882_TARGA] = {
- .mixers = { alc882_targa_mixer, alc882_chmode_mixer,
- alc882_capture_mixer },
+ .mixers = { alc882_targa_mixer, alc882_chmode_mixer },
.init_verbs = { alc882_init_verbs, alc882_targa_verbs},
.num_dacs = ARRAY_SIZE(alc882_dac_nids),
.dac_nids = alc882_dac_nids,
@@ -6525,8 +6764,7 @@ static struct alc_config_preset alc882_presets[] = {
.init_hook = alc882_targa_automute,
},
[ALC882_ASUS_A7J] = {
- .mixers = { alc882_asus_a7j_mixer, alc882_chmode_mixer,
- alc882_capture_mixer },
+ .mixers = { alc882_asus_a7j_mixer, alc882_chmode_mixer },
.init_verbs = { alc882_init_verbs, alc882_asus_a7j_verbs},
.num_dacs = ARRAY_SIZE(alc882_dac_nids),
.dac_nids = alc882_dac_nids,
@@ -6831,6 +7069,7 @@ static int patch_alc882(struct hda_codec *codec)
spec->stream_digital_playback = &alc882_pcm_digital_playback;
spec->stream_digital_capture = &alc882_pcm_digital_capture;
+ spec->is_mix_capture = 1; /* matrix-style capture */
if (!spec->adc_nids && spec->input_mux) {
/* check whether NID 0x07 is valid */
unsigned int wcap = get_wcaps(codec, 0x07);
@@ -6840,17 +7079,13 @@ static int patch_alc882(struct hda_codec *codec)
spec->adc_nids = alc882_adc_nids_alt;
spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids_alt);
spec->capsrc_nids = alc882_capsrc_nids_alt;
- spec->mixers[spec->num_mixers] =
- alc882_capture_alt_mixer;
- spec->num_mixers++;
} else {
spec->adc_nids = alc882_adc_nids;
spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids);
spec->capsrc_nids = alc882_capsrc_nids;
- spec->mixers[spec->num_mixers] = alc882_capture_mixer;
- spec->num_mixers++;
}
}
+ set_capture_mixer(spec);
spec->vmaster_nid = 0x0c;
@@ -6861,6 +7096,7 @@ static int patch_alc882(struct hda_codec *codec)
if (!spec->loopback.amplist)
spec->loopback.amplist = alc882_loopbacks;
#endif
+ codec->proc_widget_hook = print_realtek_coef;
return 0;
}
@@ -6879,6 +7115,8 @@ static int patch_alc882(struct hda_codec *codec)
#define ALC883_DIGOUT_NID 0x06
#define ALC883_DIGIN_NID 0x0a
+#define ALC1200_DIGOUT_NID 0x10
+
static hda_nid_t alc883_dac_nids[4] = {
/* front, rear, clfe, rear_surr */
0x02, 0x03, 0x04, 0x05
@@ -6889,8 +7127,20 @@ static hda_nid_t alc883_adc_nids[2] = {
0x08, 0x09,
};
+static hda_nid_t alc883_adc_nids_alt[1] = {
+ /* ADC1 */
+ 0x08,
+};
+
+static hda_nid_t alc883_adc_nids_rev[2] = {
+ /* ADC2-1 */
+ 0x09, 0x08
+};
+
static hda_nid_t alc883_capsrc_nids[2] = { 0x23, 0x22 };
+static hda_nid_t alc883_capsrc_nids_rev[2] = { 0x22, 0x23 };
+
/* input MUX */
/* FIXME: should be a matrix-type input source selection */
@@ -6957,11 +7207,6 @@ static struct hda_input_mux alc883_asus_eee1601_capture_source = {
},
};
-#define alc883_mux_enum_info alc_mux_enum_info
-#define alc883_mux_enum_get alc_mux_enum_get
-/* ALC883 has the ALC882-type input selection */
-#define alc883_mux_enum_put alc882_mux_enum_put
-
/*
* 2ch mode
*/
@@ -7115,19 +7360,6 @@ static struct snd_kcontrol_new alc883_base_mixer[] = {
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, 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 */
};
@@ -7145,19 +7377,6 @@ static struct snd_kcontrol_new alc883_mitac_mixer[] = {
HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
HDA_CODEC_MUTE("Front Mic 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 */
};
@@ -7172,19 +7391,6 @@ static struct snd_kcontrol_new alc883_clevo_m720_mixer[] = {
HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
HDA_CODEC_MUTE("Int Mic 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 */
};
@@ -7199,19 +7405,6 @@ static struct snd_kcontrol_new alc883_2ch_fujitsu_pi2515_mixer[] = {
HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
HDA_CODEC_MUTE("Int Mic 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 */
};
@@ -7231,19 +7424,6 @@ static struct snd_kcontrol_new alc883_3ST_2ch_mixer[] = {
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, 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 */
};
@@ -7269,17 +7449,6 @@ static struct snd_kcontrol_new alc883_3ST_6ch_mixer[] = {
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
- HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- /* .name = "Capture Source", */
- .name = "Input Source",
- .count = 1,
- .info = alc883_mux_enum_info,
- .get = alc883_mux_enum_get,
- .put = alc883_mux_enum_put,
- },
{ } /* end */
};
@@ -7306,19 +7475,6 @@ static struct snd_kcontrol_new alc883_3ST_6ch_intel_mixer[] = {
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, 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 */
};
@@ -7344,18 +7500,6 @@ static struct snd_kcontrol_new alc883_fivestack_mixer[] = {
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
- HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
-
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- /* .name = "Capture Source", */
- .name = "Input Source",
- .count = 1,
- .info = alc883_mux_enum_info,
- .get = alc883_mux_enum_get,
- .put = alc883_mux_enum_put,
- },
{ } /* end */
};
@@ -7376,19 +7520,6 @@ static struct snd_kcontrol_new alc883_tagra_mixer[] = {
HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, 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 */
};
@@ -7404,19 +7535,6 @@ static struct snd_kcontrol_new alc883_tagra_2ch_mixer[] = {
HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
HDA_CODEC_MUTE("Int Mic 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 */
};
@@ -7429,17 +7547,6 @@ static struct snd_kcontrol_new alc883_lenovo_101e_2ch_mixer[] = {
HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- /* .name = "Capture Source", */
- .name = "Input Source",
- .count = 1,
- .info = alc883_mux_enum_info,
- .get = alc883_mux_enum_get,
- .put = alc883_mux_enum_put,
- },
{ } /* end */
};
@@ -7453,19 +7560,6 @@ static struct snd_kcontrol_new alc883_lenovo_nb0763_mixer[] = {
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 */
};
@@ -7479,19 +7573,6 @@ static struct snd_kcontrol_new alc883_medion_md2_mixer[] = {
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 */
};
@@ -7504,19 +7585,6 @@ static struct snd_kcontrol_new alc883_acer_aspire_mixer[] = {
HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, 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 */
};
@@ -7544,19 +7612,6 @@ static struct snd_kcontrol_new alc888_lenovo_sky_mixer[] = {
HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
HDA_CODEC_MUTE("Front Mic 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 */
};
@@ -7587,6 +7642,10 @@ static struct snd_kcontrol_new alc883_asus_eee1601_mixer[] = {
HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+ { } /* end */
+};
+
+static struct snd_kcontrol_new alc883_asus_eee1601_cap_mixer[] = {
HDA_BIND_VOL("Capture Volume", &alc883_bind_cap_vol),
HDA_BIND_SW("Capture Switch", &alc883_bind_cap_switch),
{
@@ -7594,9 +7653,9 @@ static struct snd_kcontrol_new alc883_asus_eee1601_mixer[] = {
/* .name = "Capture Source", */
.name = "Input Source",
.count = 1,
- .info = alc883_mux_enum_info,
- .get = alc883_mux_enum_get,
- .put = alc883_mux_enum_put,
+ .info = alc_mux_enum_info,
+ .get = alc_mux_enum_get,
+ .put = alc_mux_enum_put,
},
{ } /* end */
};
@@ -8251,27 +8310,6 @@ static struct hda_verb alc883_auto_init_verbs[] = {
{ }
};
-/* capture mixer elements */
-static struct snd_kcontrol_new alc883_capture_mixer[] = {
- 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,
- /* The multiple "Capture Source" controls confuse alsamixer
- * So call somewhat different..
- */
- /* .name = "Capture Source", */
- .name = "Input Source",
- .count = 2,
- .info = alc882_mux_enum_info,
- .get = alc882_mux_enum_get,
- .put = alc882_mux_enum_put,
- },
- { } /* end */
-};
-
static struct hda_verb alc888_asus_m90v_verbs[] = {
{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
@@ -8394,6 +8432,7 @@ static const char *alc883_models[ALC883_MODEL_LAST] = {
[ALC883_TARGA_2ch_DIG] = "targa-2ch-dig",
[ALC883_ACER] = "acer",
[ALC883_ACER_ASPIRE] = "acer-aspire",
+ [ALC888_ACER_ASPIRE_4930G] = "acer-aspire-4930g",
[ALC883_MEDION] = "medion",
[ALC883_MEDION_MD2] = "medion-md2",
[ALC883_LAPTOP_EAPD] = "laptop-eapd",
@@ -8407,7 +8446,9 @@ static const char *alc883_models[ALC883_MODEL_LAST] = {
[ALC883_MITAC] = "mitac",
[ALC883_CLEVO_M720] = "clevo-m720",
[ALC883_FUJITSU_PI2515] = "fujitsu-pi2515",
+ [ALC888_FUJITSU_XA3530] = "fujitsu-xa3530",
[ALC883_3ST_6ch_INTEL] = "3stack-6ch-intel",
+ [ALC1200_ASUS_P5Q] = "asus-p5q",
[ALC883_AUTO] = "auto",
};
@@ -8418,6 +8459,8 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
SND_PCI_QUIRK(0x1025, 0x0110, "Acer Aspire", ALC883_ACER_ASPIRE),
SND_PCI_QUIRK(0x1025, 0x0112, "Acer Aspire 9303", ALC883_ACER_ASPIRE),
SND_PCI_QUIRK(0x1025, 0x0121, "Acer Aspire 5920G", ALC883_ACER_ASPIRE),
+ SND_PCI_QUIRK(0x1025, 0x013e, "Acer Aspire 4930G",
+ ALC888_ACER_ASPIRE_4930G),
SND_PCI_QUIRK(0x1025, 0, "Acer laptop", ALC883_ACER), /* default Acer */
SND_PCI_QUIRK(0x1028, 0x020d, "Dell Inspiron 530", ALC888_6ST_DELL),
SND_PCI_QUIRK(0x103c, 0x2a3d, "HP Pavillion", ALC883_6ST_DIG),
@@ -8426,6 +8469,7 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x2a61, "HP Nettle", ALC883_6ST_DIG),
SND_PCI_QUIRK(0x1043, 0x1873, "Asus M90V", ALC888_ASUS_M90V),
SND_PCI_QUIRK(0x1043, 0x8249, "Asus M2A-VM HDMI", ALC883_3ST_6ch_DIG),
+ SND_PCI_QUIRK(0x1043, 0x82fe, "Asus P5Q-EM HDMI", ALC1200_ASUS_P5Q),
SND_PCI_QUIRK(0x1043, 0x835f, "Asus Eee 1601", ALC888_ASUS_EEE1601),
SND_PCI_QUIRK(0x105b, 0x0ce8, "Foxconn P35AX-S", ALC883_6ST_DIG),
SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC883_6ST_DIG),
@@ -8452,6 +8496,7 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC883_6ST_DIG),
SND_PCI_QUIRK(0x1462, 0x7187, "MSI", ALC883_6ST_DIG),
SND_PCI_QUIRK(0x1462, 0x7250, "MSI", ALC883_6ST_DIG),
+ SND_PCI_QUIRK(0x1462, 0x7260, "MSI 7260", ALC883_TARGA_DIG),
SND_PCI_QUIRK(0x1462, 0x7267, "MSI", ALC883_3ST_6ch_DIG),
SND_PCI_QUIRK(0x1462, 0x7280, "MSI", ALC883_6ST_DIG),
SND_PCI_QUIRK(0x1462, 0x7327, "MSI", ALC883_6ST_DIG),
@@ -8463,6 +8508,8 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
SND_PCI_QUIRK(0x15d9, 0x8780, "Supermicro PDSBA", ALC883_3ST_6ch),
SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION),
SND_PCI_QUIRK(0x1734, 0x1108, "Fujitsu AMILO Pi2515", ALC883_FUJITSU_PI2515),
+ SND_PCI_QUIRK(0x1734, 0x113d, "Fujitsu AMILO Xa3530",
+ ALC888_FUJITSU_XA3530),
SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo 101e", ALC883_LENOVO_101E_2ch),
SND_PCI_QUIRK(0x17aa, 0x2085, "Lenovo NB0763", ALC883_LENOVO_NB0763),
SND_PCI_QUIRK(0x17aa, 0x3bfc, "Lenovo NB0763", ALC883_LENOVO_NB0763),
@@ -8553,6 +8600,8 @@ static struct alc_config_preset alc883_presets[] = {
.init_verbs = { alc883_init_verbs, alc883_tagra_verbs},
.num_dacs = ARRAY_SIZE(alc883_dac_nids),
.dac_nids = alc883_dac_nids,
+ .adc_nids = alc883_adc_nids_alt,
+ .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt),
.dig_out_nid = ALC883_DIGOUT_NID,
.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
.channel_mode = alc883_3ST_2ch_modes,
@@ -8586,6 +8635,26 @@ static struct alc_config_preset alc883_presets[] = {
.unsol_event = alc883_acer_aspire_unsol_event,
.init_hook = alc883_acer_aspire_automute,
},
+ [ALC888_ACER_ASPIRE_4930G] = {
+ .mixers = { alc888_base_mixer,
+ alc883_chmode_mixer },
+ .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs,
+ alc888_acer_aspire_4930g_verbs },
+ .num_dacs = ARRAY_SIZE(alc883_dac_nids),
+ .dac_nids = alc883_dac_nids,
+ .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev),
+ .adc_nids = alc883_adc_nids_rev,
+ .capsrc_nids = alc883_capsrc_nids_rev,
+ .dig_out_nid = ALC883_DIGOUT_NID,
+ .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
+ .channel_mode = alc883_3ST_6ch_modes,
+ .need_dac_fix = 1,
+ .num_mux_defs =
+ ARRAY_SIZE(alc888_2_capture_sources),
+ .input_mux = alc888_2_capture_sources,
+ .unsol_event = alc888_acer_aspire_4930g_unsol_event,
+ .init_hook = alc888_acer_aspire_4930g_automute,
+ },
[ALC883_MEDION] = {
.mixers = { alc883_fivestack_mixer,
alc883_chmode_mixer },
@@ -8593,6 +8662,8 @@ static struct alc_config_preset alc883_presets[] = {
alc883_medion_eapd_verbs },
.num_dacs = ARRAY_SIZE(alc883_dac_nids),
.dac_nids = alc883_dac_nids,
+ .adc_nids = alc883_adc_nids_alt,
+ .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt),
.num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
.channel_mode = alc883_sixstack_modes,
.input_mux = &alc883_capture_source,
@@ -8635,6 +8706,8 @@ static struct alc_config_preset alc883_presets[] = {
.init_verbs = { alc883_init_verbs, alc883_lenovo_101e_verbs},
.num_dacs = ARRAY_SIZE(alc883_dac_nids),
.dac_nids = alc883_dac_nids,
+ .adc_nids = alc883_adc_nids_alt,
+ .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt),
.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
.channel_mode = alc883_3ST_2ch_modes,
.input_mux = &alc883_lenovo_101e_capture_source,
@@ -8725,14 +8798,30 @@ static struct alc_config_preset alc883_presets[] = {
.unsol_event = alc883_2ch_fujitsu_pi2515_unsol_event,
.init_hook = alc883_2ch_fujitsu_pi2515_automute,
},
+ [ALC888_FUJITSU_XA3530] = {
+ .mixers = { alc888_base_mixer, alc883_chmode_mixer },
+ .init_verbs = { alc883_init_verbs,
+ alc888_fujitsu_xa3530_verbs },
+ .num_dacs = ARRAY_SIZE(alc883_dac_nids),
+ .dac_nids = alc883_dac_nids,
+ .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev),
+ .adc_nids = alc883_adc_nids_rev,
+ .capsrc_nids = alc883_capsrc_nids_rev,
+ .dig_out_nid = ALC883_DIGOUT_NID,
+ .num_channel_mode = ARRAY_SIZE(alc888_4ST_8ch_intel_modes),
+ .channel_mode = alc888_4ST_8ch_intel_modes,
+ .num_mux_defs =
+ ARRAY_SIZE(alc888_2_capture_sources),
+ .input_mux = alc888_2_capture_sources,
+ .unsol_event = alc888_fujitsu_xa3530_unsol_event,
+ .init_hook = alc888_fujitsu_xa3530_automute,
+ },
[ALC888_LENOVO_SKY] = {
.mixers = { alc888_lenovo_sky_mixer, alc883_chmode_mixer },
.init_verbs = { alc883_init_verbs, alc888_lenovo_sky_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_sixstack_modes),
.channel_mode = alc883_sixstack_modes,
.need_dac_fix = 1,
@@ -8756,6 +8845,7 @@ static struct alc_config_preset alc883_presets[] = {
},
[ALC888_ASUS_EEE1601] = {
.mixers = { alc883_asus_eee1601_mixer },
+ .cap_mixer = alc883_asus_eee1601_cap_mixer,
.init_verbs = { alc883_init_verbs, alc888_asus_eee1601_verbs },
.num_dacs = ARRAY_SIZE(alc883_dac_nids),
.dac_nids = alc883_dac_nids,
@@ -8768,6 +8858,17 @@ static struct alc_config_preset alc883_presets[] = {
.unsol_event = alc883_eee1601_unsol_event,
.init_hook = alc883_eee1601_inithook,
},
+ [ALC1200_ASUS_P5Q] = {
+ .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 = ALC1200_DIGOUT_NID,
+ .dig_in_nid = ALC883_DIGIN_NID,
+ .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
+ .channel_mode = alc883_sixstack_modes,
+ .input_mux = &alc883_capture_source,
+ },
};
@@ -8862,8 +8963,6 @@ static int alc883_parse_auto_config(struct hda_codec *codec)
/* hack - override the init verbs */
spec->init_verbs[0] = alc883_auto_init_verbs;
- spec->mixers[spec->num_mixers] = alc883_capture_mixer;
- spec->num_mixers++;
return 1; /* config found */
}
@@ -8946,9 +9045,15 @@ static int patch_alc883(struct hda_codec *codec)
spec->stream_digital_playback = &alc883_pcm_digital_playback;
spec->stream_digital_capture = &alc883_pcm_digital_capture;
- spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids);
- spec->adc_nids = alc883_adc_nids;
- spec->capsrc_nids = alc883_capsrc_nids;
+ if (!spec->num_adc_nids) {
+ spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids);
+ spec->adc_nids = alc883_adc_nids;
+ }
+ if (!spec->capsrc_nids)
+ spec->capsrc_nids = alc883_capsrc_nids;
+ spec->is_mix_capture = 1; /* matrix-style capture */
+ if (!spec->cap_mixer)
+ set_capture_mixer(spec);
spec->vmaster_nid = 0x0c;
@@ -8960,6 +9065,7 @@ static int patch_alc883(struct hda_codec *codec)
if (!spec->loopback.amplist)
spec->loopback.amplist = alc883_loopbacks;
#endif
+ codec->proc_widget_hook = print_realtek_coef;
return 0;
}
@@ -9439,20 +9545,6 @@ static struct snd_kcontrol_new alc262_toshiba_s06_mixer[] = {
HDA_CODEC_MUTE("Headphone 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("Capture Volume", 0x09, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- /* The multiple "Capture Source" controls confuse alsamixer
- * So call somewhat different..
- */
- /* .name = "Capture Source", */
- .name = "Input Source",
- .count = 1,
- .info = alc_mux_enum_info,
- .get = alc_mux_enum_get,
- .put = alc_mux_enum_put,
- },
{ } /* end */
};
@@ -9969,7 +10061,7 @@ static int alc262_ultra_mux_enum_put(struct snd_kcontrol *kcontrol,
struct alc_spec *spec = codec->spec;
int ret;
- ret = alc882_mux_enum_put(kcontrol, ucontrol);
+ ret = alc_mux_enum_put(kcontrol, ucontrol);
if (!ret)
return 0;
/* reprogram the HP pin as mic or HP according to the input source */
@@ -9986,8 +10078,8 @@ static struct snd_kcontrol_new alc262_ultra_capture_mixer[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Capture Source",
- .info = alc882_mux_enum_info,
- .get = alc882_mux_enum_get,
+ .info = alc_mux_enum_info,
+ .get = alc_mux_enum_get,
.put = alc262_ultra_mux_enum_put,
},
{ } /* end */
@@ -10380,10 +10472,10 @@ static int alc262_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_in_pin)
spec->dig_in_nid = ALC262_DIGIN_NID;
- if (spec->kctl_alloc)
- spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
+ if (spec->kctls.list)
+ add_mixer(spec, spec->kctls.list);
- spec->init_verbs[spec->num_init_verbs++] = alc262_volume_init_verbs;
+ add_verb(spec, alc262_volume_init_verbs);
spec->num_mux_defs = 1;
spec->input_mux = &spec->private_imux;
@@ -10466,6 +10558,8 @@ static struct snd_pci_quirk alc262_cfg_tbl[] = {
SND_PCI_QUIRK(0x104d, 0x820f, "Sony ASSAMD", ALC262_SONY_ASSAMD),
SND_PCI_QUIRK(0x104d, 0x900e, "Sony ASSAMD", ALC262_SONY_ASSAMD),
SND_PCI_QUIRK(0x104d, 0x9015, "Sony 0x9015", ALC262_SONY_ASSAMD),
+ SND_PCI_QUIRK(0x104d, 0x9033, "Sony VAIO VGN-SR19XN",
+ ALC262_SONY_ASSAMD),
SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba dynabook SS RX1",
ALC262_TOSHIBA_RX1),
SND_PCI_QUIRK(0x1179, 0xff7b, "Toshiba S06", ALC262_TOSHIBA_S06),
@@ -10624,7 +10718,8 @@ static struct alc_config_preset alc262_presets[] = {
.init_hook = alc262_hippo_automute,
},
[ALC262_ULTRA] = {
- .mixers = { alc262_ultra_mixer, alc262_ultra_capture_mixer },
+ .mixers = { alc262_ultra_mixer },
+ .cap_mixer = alc262_ultra_capture_mixer,
.init_verbs = { alc262_ultra_verbs },
.num_dacs = ARRAY_SIZE(alc262_dac_nids),
.dac_nids = alc262_dac_nids,
@@ -10750,6 +10845,7 @@ static int patch_alc262(struct hda_codec *codec)
spec->stream_digital_playback = &alc262_pcm_digital_playback;
spec->stream_digital_capture = &alc262_pcm_digital_capture;
+ spec->is_mix_capture = 1;
if (!spec->adc_nids && spec->input_mux) {
/* check whether NID 0x07 is valid */
unsigned int wcap = get_wcaps(codec, 0x07);
@@ -10760,17 +10856,14 @@ static int patch_alc262(struct hda_codec *codec)
spec->adc_nids = alc262_adc_nids_alt;
spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids_alt);
spec->capsrc_nids = alc262_capsrc_nids_alt;
- spec->mixers[spec->num_mixers] =
- alc262_capture_alt_mixer;
- spec->num_mixers++;
} else {
spec->adc_nids = alc262_adc_nids;
spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids);
spec->capsrc_nids = alc262_capsrc_nids;
- spec->mixers[spec->num_mixers] = alc262_capture_mixer;
- spec->num_mixers++;
}
}
+ if (!spec->cap_mixer)
+ set_capture_mixer(spec);
spec->vmaster_nid = 0x0c;
@@ -10781,6 +10874,7 @@ static int patch_alc262(struct hda_codec *codec)
if (!spec->loopback.amplist)
spec->loopback.amplist = alc262_loopbacks;
#endif
+ codec->proc_widget_hook = print_realtek_coef;
return 0;
}
@@ -10942,6 +11036,22 @@ static struct snd_kcontrol_new alc268_acer_mixer[] = {
{ }
};
+static struct snd_kcontrol_new alc268_acer_dmic_mixer[] = {
+ /* output mixer control */
+ HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Master Playback Switch",
+ .info = snd_hda_mixer_amp_switch_info,
+ .get = snd_hda_mixer_amp_switch_get,
+ .put = alc268_acer_master_sw_put,
+ .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
+ },
+ HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
+ HDA_CODEC_VOLUME("Line In Boost", 0x1a, 0, HDA_INPUT),
+ { }
+};
+
static struct hda_verb alc268_acer_aspire_one_verbs[] = {
{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
@@ -11218,10 +11328,6 @@ static struct hda_verb alc268_volume_init_verbs[] = {
{ }
};
-#define alc268_mux_enum_info alc_mux_enum_info
-#define alc268_mux_enum_get alc_mux_enum_get
-#define alc268_mux_enum_put alc_mux_enum_put
-
static struct snd_kcontrol_new alc268_capture_alt_mixer[] = {
HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT),
@@ -11233,9 +11339,9 @@ static struct snd_kcontrol_new alc268_capture_alt_mixer[] = {
/* .name = "Capture Source", */
.name = "Input Source",
.count = 1,
- .info = alc268_mux_enum_info,
- .get = alc268_mux_enum_get,
- .put = alc268_mux_enum_put,
+ .info = alc_mux_enum_info,
+ .get = alc_mux_enum_get,
+ .put = alc_mux_enum_put,
},
{ } /* end */
};
@@ -11253,9 +11359,9 @@ static struct snd_kcontrol_new alc268_capture_mixer[] = {
/* .name = "Capture Source", */
.name = "Input Source",
.count = 2,
- .info = alc268_mux_enum_info,
- .get = alc268_mux_enum_get,
- .put = alc268_mux_enum_put,
+ .info = alc_mux_enum_info,
+ .get = alc_mux_enum_get,
+ .put = alc_mux_enum_put,
},
{ } /* end */
};
@@ -11274,6 +11380,15 @@ static struct hda_input_mux alc268_acer_capture_source = {
.num_items = 3,
.items = {
{ "Mic", 0x0 },
+ { "Internal Mic", 0x1 },
+ { "Line", 0x2 },
+ },
+};
+
+static struct hda_input_mux alc268_acer_dmic_capture_source = {
+ .num_items = 3,
+ .items = {
+ { "Mic", 0x0 },
{ "Internal Mic", 0x6 },
{ "Line", 0x2 },
},
@@ -11512,13 +11627,13 @@ static int alc268_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_out_pin)
spec->multiout.dig_out_nid = ALC268_DIGOUT_NID;
- if (spec->kctl_alloc)
- spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
+ if (spec->kctls.list)
+ add_mixer(spec, spec->kctls.list);
if (spec->autocfg.speaker_pins[0] != 0x1d)
- spec->mixers[spec->num_mixers++] = alc268_beep_mixer;
+ add_mixer(spec, alc268_beep_mixer);
- spec->init_verbs[spec->num_init_verbs++] = alc268_volume_init_verbs;
+ add_verb(spec, alc268_volume_init_verbs);
spec->num_mux_defs = 1;
spec->input_mux = &spec->private_imux;
@@ -11554,6 +11669,7 @@ static const char *alc268_models[ALC268_MODEL_LAST] = {
[ALC268_3ST] = "3stack",
[ALC268_TOSHIBA] = "toshiba",
[ALC268_ACER] = "acer",
+ [ALC268_ACER_DMIC] = "acer-dmic",
[ALC268_ACER_ASPIRE_ONE] = "acer-aspire",
[ALC268_DELL] = "dell",
[ALC268_ZEPTO] = "zepto",
@@ -11649,6 +11765,23 @@ static struct alc_config_preset alc268_presets[] = {
.unsol_event = alc268_acer_unsol_event,
.init_hook = alc268_acer_init_hook,
},
+ [ALC268_ACER_DMIC] = {
+ .mixers = { alc268_acer_dmic_mixer, alc268_capture_alt_mixer,
+ alc268_beep_mixer },
+ .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
+ alc268_acer_verbs },
+ .num_dacs = ARRAY_SIZE(alc268_dac_nids),
+ .dac_nids = alc268_dac_nids,
+ .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
+ .adc_nids = alc268_adc_nids_alt,
+ .capsrc_nids = alc268_capsrc_nids,
+ .hp_nid = 0x02,
+ .num_channel_mode = ARRAY_SIZE(alc268_modes),
+ .channel_mode = alc268_modes,
+ .input_mux = &alc268_acer_dmic_capture_source,
+ .unsol_event = alc268_acer_unsol_event,
+ .init_hook = alc268_acer_init_hook,
+ },
[ALC268_ACER_ASPIRE_ONE] = {
.mixers = { alc268_acer_aspire_one_mixer,
alc268_capture_alt_mixer },
@@ -11787,15 +11920,11 @@ static int patch_alc268(struct hda_codec *codec)
if (wcap != AC_WID_AUD_IN || spec->input_mux->num_items == 1) {
spec->adc_nids = alc268_adc_nids_alt;
spec->num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt);
- spec->mixers[spec->num_mixers] =
- alc268_capture_alt_mixer;
- spec->num_mixers++;
+ add_mixer(spec, alc268_capture_alt_mixer);
} else {
spec->adc_nids = alc268_adc_nids;
spec->num_adc_nids = ARRAY_SIZE(alc268_adc_nids);
- spec->mixers[spec->num_mixers] =
- alc268_capture_mixer;
- spec->num_mixers++;
+ add_mixer(spec, alc268_capture_mixer);
}
spec->capsrc_nids = alc268_capsrc_nids;
/* set default input source */
@@ -11811,6 +11940,8 @@ static int patch_alc268(struct hda_codec *codec)
if (board_config == ALC268_AUTO)
spec->init_hook = alc268_auto_init;
+ codec->proc_widget_hook = print_realtek_coef;
+
return 0;
}
@@ -11893,6 +12024,31 @@ static struct snd_kcontrol_new alc269_quanta_fl1_mixer[] = {
{ }
};
+static struct snd_kcontrol_new alc269_lifebook_mixer[] = {
+ /* output mixer control */
+ HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Master Playback Switch",
+ .info = snd_hda_mixer_amp_switch_info,
+ .get = snd_hda_mixer_amp_switch_get,
+ .put = alc268_acer_master_sw_put,
+ .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, 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("Mic Boost", 0x18, 0, HDA_INPUT),
+ HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
+ HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
+ HDA_CODEC_VOLUME("Internal Mic Boost", 0x19, 0, HDA_INPUT),
+ HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x0b, 0x03, HDA_INPUT),
+ HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x0b, 0x03, HDA_INPUT),
+ HDA_CODEC_VOLUME("Dock Mic Boost", 0x1b, 0, HDA_INPUT),
+ HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x04, HDA_INPUT),
+ HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x04, HDA_INPUT),
+ { }
+};
+
/* bind volumes of both NID 0x0c and 0x0d */
static struct hda_bind_ctls alc269_epc_bind_vol = {
.ops = &snd_hda_bind_vol,
@@ -11911,28 +12067,18 @@ static struct snd_kcontrol_new alc269_eeepc_mixer[] = {
};
/* capture mixer elements */
-static struct snd_kcontrol_new alc269_capture_mixer[] = {
+static struct snd_kcontrol_new alc269_epc_capture_mixer[] = {
HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- /* The multiple "Capture Source" controls confuse alsamixer
- * So call somewhat different..
- */
- /* .name = "Capture Source", */
- .name = "Input Source",
- .count = 1,
- .info = alc_mux_enum_info,
- .get = alc_mux_enum_get,
- .put = alc_mux_enum_put,
- },
+ HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
{ } /* end */
};
-/* capture mixer elements */
-static struct snd_kcontrol_new alc269_epc_capture_mixer[] = {
- HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+/* FSC amilo */
+static struct snd_kcontrol_new alc269_fujitsu_mixer[] = {
+ HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+ HDA_BIND_VOL("PCM Playback Volume", &alc269_epc_bind_vol),
{ } /* end */
};
@@ -11953,6 +12099,20 @@ static struct hda_verb alc269_quanta_fl1_verbs[] = {
{ }
};
+static struct hda_verb alc269_lifebook_verbs[] = {
+ {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
+ {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01},
+ {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
+ {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
+ {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
+ {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+ { }
+};
+
/* toggle speaker-output according to the hp-jack state */
static void alc269_quanta_fl1_speaker_automute(struct hda_codec *codec)
{
@@ -11978,6 +12138,37 @@ static void alc269_quanta_fl1_speaker_automute(struct hda_codec *codec)
AC_VERB_SET_PROC_COEF, 0x480);
}
+/* toggle speaker-output according to the hp-jacks state */
+static void alc269_lifebook_speaker_automute(struct hda_codec *codec)
+{
+ unsigned int present;
+ unsigned char bits;
+
+ /* Check laptop headphone socket */
+ present = snd_hda_codec_read(codec, 0x15, 0,
+ AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+
+ /* Check port replicator headphone socket */
+ present |= snd_hda_codec_read(codec, 0x1a, 0,
+ AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+
+ bits = present ? AMP_IN_MUTE(0) : 0;
+ snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
+ AMP_IN_MUTE(0), bits);
+ snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
+ AMP_IN_MUTE(0), bits);
+
+ snd_hda_codec_write(codec, 0x20, 0,
+ AC_VERB_SET_COEF_INDEX, 0x0c);
+ snd_hda_codec_write(codec, 0x20, 0,
+ AC_VERB_SET_PROC_COEF, 0x680);
+
+ snd_hda_codec_write(codec, 0x20, 0,
+ AC_VERB_SET_COEF_INDEX, 0x0c);
+ snd_hda_codec_write(codec, 0x20, 0,
+ AC_VERB_SET_PROC_COEF, 0x480);
+}
+
static void alc269_quanta_fl1_mic_automute(struct hda_codec *codec)
{
unsigned int present;
@@ -11988,6 +12179,29 @@ static void alc269_quanta_fl1_mic_automute(struct hda_codec *codec)
AC_VERB_SET_CONNECT_SEL, present ? 0x0 : 0x1);
}
+static void alc269_lifebook_mic_autoswitch(struct hda_codec *codec)
+{
+ unsigned int present_laptop;
+ unsigned int present_dock;
+
+ present_laptop = snd_hda_codec_read(codec, 0x18, 0,
+ AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+
+ present_dock = snd_hda_codec_read(codec, 0x1b, 0,
+ AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+
+ /* Laptop mic port overrides dock mic port, design decision */
+ if (present_dock)
+ snd_hda_codec_write(codec, 0x23, 0,
+ AC_VERB_SET_CONNECT_SEL, 0x3);
+ if (present_laptop)
+ snd_hda_codec_write(codec, 0x23, 0,
+ AC_VERB_SET_CONNECT_SEL, 0x0);
+ if (!present_dock && !present_laptop)
+ snd_hda_codec_write(codec, 0x23, 0,
+ AC_VERB_SET_CONNECT_SEL, 0x1);
+}
+
static void alc269_quanta_fl1_unsol_event(struct hda_codec *codec,
unsigned int res)
{
@@ -11997,12 +12211,27 @@ static void alc269_quanta_fl1_unsol_event(struct hda_codec *codec,
alc269_quanta_fl1_mic_automute(codec);
}
+static void alc269_lifebook_unsol_event(struct hda_codec *codec,
+ unsigned int res)
+{
+ if ((res >> 26) == ALC880_HP_EVENT)
+ alc269_lifebook_speaker_automute(codec);
+ if ((res >> 26) == ALC880_MIC_EVENT)
+ alc269_lifebook_mic_autoswitch(codec);
+}
+
static void alc269_quanta_fl1_init_hook(struct hda_codec *codec)
{
alc269_quanta_fl1_speaker_automute(codec);
alc269_quanta_fl1_mic_automute(codec);
}
+static void alc269_lifebook_init_hook(struct hda_codec *codec)
+{
+ alc269_lifebook_speaker_automute(codec);
+ alc269_lifebook_mic_autoswitch(codec);
+}
+
static struct hda_verb alc269_eeepc_dmic_init_verbs[] = {
{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
{0x23, AC_VERB_SET_CONNECT_SEL, 0x05},
@@ -12303,17 +12532,17 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_out_pin)
spec->multiout.dig_out_nid = ALC269_DIGOUT_NID;
- if (spec->kctl_alloc)
- spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
+ if (spec->kctls.list)
+ add_mixer(spec, spec->kctls.list);
/* create a beep mixer control if the pin 0x1d isn't assigned */
for (i = 0; i < ARRAY_SIZE(spec->autocfg.input_pins); i++)
if (spec->autocfg.input_pins[i] == 0x1d)
break;
if (i >= ARRAY_SIZE(spec->autocfg.input_pins))
- spec->mixers[spec->num_mixers++] = alc269_beep_mixer;
+ add_mixer(spec, alc269_beep_mixer);
- spec->init_verbs[spec->num_init_verbs++] = alc269_init_verbs;
+ add_verb(spec, alc269_init_verbs);
spec->num_mux_defs = 1;
spec->input_mux = &spec->private_imux;
/* set default input source */
@@ -12325,8 +12554,8 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
if (err < 0)
return err;
- spec->mixers[spec->num_mixers] = alc269_capture_mixer;
- spec->num_mixers++;
+ if (!spec->cap_mixer)
+ set_capture_mixer(spec);
store_pin_configs(codec);
return 1;
@@ -12355,7 +12584,9 @@ static const char *alc269_models[ALC269_MODEL_LAST] = {
[ALC269_BASIC] = "basic",
[ALC269_QUANTA_FL1] = "quanta",
[ALC269_ASUS_EEEPC_P703] = "eeepc-p703",
- [ALC269_ASUS_EEEPC_P901] = "eeepc-p901"
+ [ALC269_ASUS_EEEPC_P901] = "eeepc-p901",
+ [ALC269_FUJITSU] = "fujitsu",
+ [ALC269_LIFEBOOK] = "lifebook"
};
static struct snd_pci_quirk alc269_cfg_tbl[] = {
@@ -12366,12 +12597,14 @@ static struct snd_pci_quirk alc269_cfg_tbl[] = {
ALC269_ASUS_EEEPC_P901),
SND_PCI_QUIRK(0x1043, 0x834a, "ASUS Eeepc S101",
ALC269_ASUS_EEEPC_P901),
+ SND_PCI_QUIRK(0x1734, 0x115d, "FSC Amilo", ALC269_FUJITSU),
+ SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook ICH9M-based", ALC269_LIFEBOOK),
{}
};
static struct alc_config_preset alc269_presets[] = {
[ALC269_BASIC] = {
- .mixers = { alc269_base_mixer, alc269_capture_mixer },
+ .mixers = { alc269_base_mixer },
.init_verbs = { alc269_init_verbs },
.num_dacs = ARRAY_SIZE(alc269_dac_nids),
.dac_nids = alc269_dac_nids,
@@ -12393,7 +12626,8 @@ static struct alc_config_preset alc269_presets[] = {
.init_hook = alc269_quanta_fl1_init_hook,
},
[ALC269_ASUS_EEEPC_P703] = {
- .mixers = { alc269_eeepc_mixer, alc269_epc_capture_mixer },
+ .mixers = { alc269_eeepc_mixer },
+ .cap_mixer = alc269_epc_capture_mixer,
.init_verbs = { alc269_init_verbs,
alc269_eeepc_amic_init_verbs },
.num_dacs = ARRAY_SIZE(alc269_dac_nids),
@@ -12406,7 +12640,8 @@ static struct alc_config_preset alc269_presets[] = {
.init_hook = alc269_eeepc_amic_inithook,
},
[ALC269_ASUS_EEEPC_P901] = {
- .mixers = { alc269_eeepc_mixer, alc269_epc_capture_mixer},
+ .mixers = { alc269_eeepc_mixer },
+ .cap_mixer = alc269_epc_capture_mixer,
.init_verbs = { alc269_init_verbs,
alc269_eeepc_dmic_init_verbs },
.num_dacs = ARRAY_SIZE(alc269_dac_nids),
@@ -12418,6 +12653,32 @@ static struct alc_config_preset alc269_presets[] = {
.unsol_event = alc269_eeepc_dmic_unsol_event,
.init_hook = alc269_eeepc_dmic_inithook,
},
+ [ALC269_FUJITSU] = {
+ .mixers = { alc269_fujitsu_mixer, alc269_beep_mixer },
+ .cap_mixer = alc269_epc_capture_mixer,
+ .init_verbs = { alc269_init_verbs,
+ alc269_eeepc_dmic_init_verbs },
+ .num_dacs = ARRAY_SIZE(alc269_dac_nids),
+ .dac_nids = alc269_dac_nids,
+ .hp_nid = 0x03,
+ .num_channel_mode = ARRAY_SIZE(alc269_modes),
+ .channel_mode = alc269_modes,
+ .input_mux = &alc269_eeepc_dmic_capture_source,
+ .unsol_event = alc269_eeepc_dmic_unsol_event,
+ .init_hook = alc269_eeepc_dmic_inithook,
+ },
+ [ALC269_LIFEBOOK] = {
+ .mixers = { alc269_lifebook_mixer },
+ .init_verbs = { alc269_init_verbs, alc269_lifebook_verbs },
+ .num_dacs = ARRAY_SIZE(alc269_dac_nids),
+ .dac_nids = alc269_dac_nids,
+ .hp_nid = 0x03,
+ .num_channel_mode = ARRAY_SIZE(alc269_modes),
+ .channel_mode = alc269_modes,
+ .input_mux = &alc269_capture_source,
+ .unsol_event = alc269_lifebook_unsol_event,
+ .init_hook = alc269_lifebook_init_hook,
+ },
};
static int patch_alc269(struct hda_codec *codec)
@@ -12472,6 +12733,8 @@ static int patch_alc269(struct hda_codec *codec)
spec->adc_nids = alc269_adc_nids;
spec->num_adc_nids = ARRAY_SIZE(alc269_adc_nids);
spec->capsrc_nids = alc269_capsrc_nids;
+ if (!spec->cap_mixer)
+ set_capture_mixer(spec);
codec->patch_ops = alc_patch_ops;
if (board_config == ALC269_AUTO)
@@ -12480,6 +12743,7 @@ static int patch_alc269(struct hda_codec *codec)
if (!spec->loopback.amplist)
spec->loopback.amplist = alc269_loopbacks;
#endif
+ codec->proc_widget_hook = print_realtek_coef;
return 0;
}
@@ -12612,17 +12876,6 @@ static struct snd_kcontrol_new alc861_base_mixer[] = {
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
- /* Capture mixer control */
- HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Capture Source",
- .count = 1,
- .info = alc_mux_enum_info,
- .get = alc_mux_enum_get,
- .put = alc_mux_enum_put,
- },
{ } /* end */
};
@@ -12646,17 +12899,6 @@ static struct snd_kcontrol_new alc861_3ST_mixer[] = {
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
- /* Capture mixer control */
- HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Capture Source",
- .count = 1,
- .info = alc_mux_enum_info,
- .get = alc_mux_enum_get,
- .put = alc_mux_enum_put,
- },
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Channel Mode",
@@ -12674,18 +12916,6 @@ static struct snd_kcontrol_new alc861_toshiba_mixer[] = {
HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
- /*Capture mixer control */
- HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Capture Source",
- .count = 1,
- .info = alc_mux_enum_info,
- .get = alc_mux_enum_get,
- .put = alc_mux_enum_put,
- },
-
{ } /* end */
};
@@ -12709,17 +12939,6 @@ static struct snd_kcontrol_new alc861_uniwill_m31_mixer[] = {
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
- /* Capture mixer control */
- HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Capture Source",
- .count = 1,
- .info = alc_mux_enum_info,
- .get = alc_mux_enum_get,
- .put = alc_mux_enum_put,
- },
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Channel Mode",
@@ -12751,17 +12970,6 @@ static struct snd_kcontrol_new alc861_asus_mixer[] = {
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_OUTPUT),
- /* Capture mixer control */
- HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Capture Source",
- .count = 1,
- .info = alc_mux_enum_info,
- .get = alc_mux_enum_get,
- .put = alc_mux_enum_put,
- },
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Channel Mode",
@@ -13293,25 +13501,6 @@ static int alc861_auto_create_analog_input_ctls(struct alc_spec *spec,
return 0;
}
-static struct snd_kcontrol_new alc861_capture_mixer[] = {
- HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
-
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- /* The multiple "Capture Source" controls confuse alsamixer
- * So call somewhat different..
- */
- /* .name = "Capture Source", */
- .name = "Input Source",
- .count = 1,
- .info = alc_mux_enum_info,
- .get = alc_mux_enum_get,
- .put = alc_mux_enum_put,
- },
- { } /* end */
-};
-
static void alc861_auto_set_output_and_unmute(struct hda_codec *codec,
hda_nid_t nid,
int pin_type, int dac_idx)
@@ -13402,18 +13591,17 @@ static int alc861_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_out_pin)
spec->multiout.dig_out_nid = ALC861_DIGOUT_NID;
- if (spec->kctl_alloc)
- spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
+ if (spec->kctls.list)
+ add_mixer(spec, spec->kctls.list);
- spec->init_verbs[spec->num_init_verbs++] = alc861_auto_init_verbs;
+ add_verb(spec, alc861_auto_init_verbs);
spec->num_mux_defs = 1;
spec->input_mux = &spec->private_imux;
spec->adc_nids = alc861_adc_nids;
spec->num_adc_nids = ARRAY_SIZE(alc861_adc_nids);
- spec->mixers[spec->num_mixers] = alc861_capture_mixer;
- spec->num_mixers++;
+ set_capture_mixer(spec);
store_pin_configs(codec);
return 1;
@@ -13644,6 +13832,7 @@ static int patch_alc861(struct hda_codec *codec)
if (!spec->loopback.amplist)
spec->loopback.amplist = alc861_loopbacks;
#endif
+ codec->proc_widget_hook = print_realtek_coef;
return 0;
}
@@ -13709,11 +13898,6 @@ static struct hda_input_mux alc861vd_hp_capture_source = {
},
};
-#define alc861vd_mux_enum_info alc_mux_enum_info
-#define alc861vd_mux_enum_get alc_mux_enum_get
-/* ALC861VD has the ALC882-type input selection (but has only one ADC) */
-#define alc861vd_mux_enum_put alc882_mux_enum_put
-
/*
* 2ch mode
*/
@@ -13759,25 +13943,6 @@ static struct snd_kcontrol_new alc861vd_chmode_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc861vd_capture_mixer[] = {
- HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
-
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- /* The multiple "Capture Source" controls confuse alsamixer
- * So call somewhat different..
- */
- /* .name = "Capture Source", */
- .name = "Input Source",
- .count = 1,
- .info = alc861vd_mux_enum_info,
- .get = alc861vd_mux_enum_get,
- .put = alc861vd_mux_enum_put,
- },
- { } /* end */
-};
-
/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
* Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
*/
@@ -14169,6 +14334,7 @@ static void alc861vd_dallas_unsol_event(struct hda_codec *codec, unsigned int re
static const char *alc861vd_models[ALC861VD_MODEL_LAST] = {
[ALC660VD_3ST] = "3stack-660",
[ALC660VD_3ST_DIG] = "3stack-660-digout",
+ [ALC660VD_ASUS_V1S] = "asus-v1s",
[ALC861VD_3ST] = "3stack",
[ALC861VD_3ST_DIG] = "3stack-digout",
[ALC861VD_6ST_DIG] = "6stack-digout",
@@ -14183,7 +14349,7 @@ static struct snd_pci_quirk alc861vd_cfg_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x30bf, "HP TX1000", ALC861VD_HP),
SND_PCI_QUIRK(0x1043, 0x12e2, "Asus z35m", ALC660VD_3ST),
SND_PCI_QUIRK(0x1043, 0x1339, "Asus G1", ALC660VD_3ST),
- SND_PCI_QUIRK(0x1043, 0x1633, "Asus V1Sn", ALC861VD_LENOVO),
+ SND_PCI_QUIRK(0x1043, 0x1633, "Asus V1Sn", ALC660VD_ASUS_V1S),
SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS", ALC660VD_3ST_DIG),
SND_PCI_QUIRK(0x10de, 0x03f0, "Realtek ALC660 demo", ALC660VD_3ST),
SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba A135", ALC861VD_LENOVO),
@@ -14290,6 +14456,21 @@ static struct alc_config_preset alc861vd_presets[] = {
.unsol_event = alc861vd_dallas_unsol_event,
.init_hook = alc861vd_dallas_automute,
},
+ [ALC660VD_ASUS_V1S] = {
+ .mixers = { alc861vd_lenovo_mixer },
+ .init_verbs = { alc861vd_volume_init_verbs,
+ alc861vd_3stack_init_verbs,
+ alc861vd_eapd_verbs,
+ alc861vd_lenovo_unsol_verbs },
+ .num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
+ .dac_nids = alc660vd_dac_nids,
+ .dig_out_nid = ALC861VD_DIGOUT_NID,
+ .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
+ .channel_mode = alc861vd_3stack_2ch_modes,
+ .input_mux = &alc861vd_capture_source,
+ .unsol_event = alc861vd_lenovo_unsol_event,
+ .init_hook = alc861vd_lenovo_automute,
+ },
};
/*
@@ -14514,11 +14695,10 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_out_pin)
spec->multiout.dig_out_nid = ALC861VD_DIGOUT_NID;
- if (spec->kctl_alloc)
- spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
+ if (spec->kctls.list)
+ add_mixer(spec, spec->kctls.list);
- spec->init_verbs[spec->num_init_verbs++]
- = alc861vd_volume_init_verbs;
+ add_verb(spec, alc861vd_volume_init_verbs);
spec->num_mux_defs = 1;
spec->input_mux = &spec->private_imux;
@@ -14585,7 +14765,7 @@ static int patch_alc861vd(struct hda_codec *codec)
spec->stream_name_analog = "ALC660-VD Analog";
spec->stream_name_digital = "ALC660-VD Digital";
/* always turn on EAPD */
- spec->init_verbs[spec->num_init_verbs++] = alc660vd_eapd_verbs;
+ add_verb(spec, alc660vd_eapd_verbs);
} else {
spec->stream_name_analog = "ALC861VD Analog";
spec->stream_name_digital = "ALC861VD Digital";
@@ -14600,9 +14780,9 @@ static int patch_alc861vd(struct hda_codec *codec)
spec->adc_nids = alc861vd_adc_nids;
spec->num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids);
spec->capsrc_nids = alc861vd_capsrc_nids;
+ spec->is_mix_capture = 1;
- spec->mixers[spec->num_mixers] = alc861vd_capture_mixer;
- spec->num_mixers++;
+ set_capture_mixer(spec);
spec->vmaster_nid = 0x02;
@@ -14614,6 +14794,7 @@ static int patch_alc861vd(struct hda_codec *codec)
if (!spec->loopback.amplist)
spec->loopback.amplist = alc861vd_loopbacks;
#endif
+ codec->proc_widget_hook = print_realtek_coef;
return 0;
}
@@ -14689,10 +14870,6 @@ static struct hda_input_mux alc663_m51va_capture_source = {
},
};
-#define alc662_mux_enum_info alc_mux_enum_info
-#define alc662_mux_enum_get alc_mux_enum_get
-#define alc662_mux_enum_put alc882_mux_enum_put
-
/*
* 2ch mode
*/
@@ -15278,25 +15455,6 @@ static struct hda_verb alc662_ecs_init_verbs[] = {
{}
};
-/* capture mixer elements */
-static struct snd_kcontrol_new alc662_capture_mixer[] = {
- HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- /* The multiple "Capture Source" controls confuse alsamixer
- * So call somewhat different..
- */
- /* .name = "Capture Source", */
- .name = "Input Source",
- .count = 1,
- .info = alc662_mux_enum_info,
- .get = alc662_mux_enum_get,
- .put = alc662_mux_enum_put,
- },
- { } /* end */
-};
-
static struct snd_kcontrol_new alc662_auto_capture_mixer[] = {
HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
@@ -15868,7 +16026,7 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = {
static struct alc_config_preset alc662_presets[] = {
[ALC662_3ST_2ch_DIG] = {
- .mixers = { alc662_3ST_2ch_mixer, alc662_capture_mixer },
+ .mixers = { alc662_3ST_2ch_mixer },
.init_verbs = { alc662_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
@@ -15879,8 +16037,7 @@ static struct alc_config_preset alc662_presets[] = {
.input_mux = &alc662_capture_source,
},
[ALC662_3ST_6ch_DIG] = {
- .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer,
- alc662_capture_mixer },
+ .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer },
.init_verbs = { alc662_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
@@ -15892,8 +16049,7 @@ static struct alc_config_preset alc662_presets[] = {
.input_mux = &alc662_capture_source,
},
[ALC662_3ST_6ch] = {
- .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer,
- alc662_capture_mixer },
+ .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer },
.init_verbs = { alc662_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
@@ -15903,8 +16059,7 @@ static struct alc_config_preset alc662_presets[] = {
.input_mux = &alc662_capture_source,
},
[ALC662_5ST_DIG] = {
- .mixers = { alc662_base_mixer, alc662_chmode_mixer,
- alc662_capture_mixer },
+ .mixers = { alc662_base_mixer, alc662_chmode_mixer },
.init_verbs = { alc662_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
@@ -15915,7 +16070,7 @@ static struct alc_config_preset alc662_presets[] = {
.input_mux = &alc662_capture_source,
},
[ALC662_LENOVO_101E] = {
- .mixers = { alc662_lenovo_101e_mixer, alc662_capture_mixer },
+ .mixers = { alc662_lenovo_101e_mixer },
.init_verbs = { alc662_init_verbs, alc662_sue_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
@@ -15926,7 +16081,7 @@ static struct alc_config_preset alc662_presets[] = {
.init_hook = alc662_lenovo_101e_all_automute,
},
[ALC662_ASUS_EEEPC_P701] = {
- .mixers = { alc662_eeepc_p701_mixer, alc662_capture_mixer },
+ .mixers = { alc662_eeepc_p701_mixer },
.init_verbs = { alc662_init_verbs,
alc662_eeepc_sue_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
@@ -15938,7 +16093,7 @@ static struct alc_config_preset alc662_presets[] = {
.init_hook = alc662_eeepc_inithook,
},
[ALC662_ASUS_EEEPC_EP20] = {
- .mixers = { alc662_eeepc_ep20_mixer, alc662_capture_mixer,
+ .mixers = { alc662_eeepc_ep20_mixer,
alc662_chmode_mixer },
.init_verbs = { alc662_init_verbs,
alc662_eeepc_ep20_sue_init_verbs },
@@ -15951,7 +16106,7 @@ static struct alc_config_preset alc662_presets[] = {
.init_hook = alc662_eeepc_ep20_inithook,
},
[ALC662_ECS] = {
- .mixers = { alc662_ecs_mixer, alc662_capture_mixer },
+ .mixers = { alc662_ecs_mixer },
.init_verbs = { alc662_init_verbs,
alc662_ecs_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
@@ -15963,7 +16118,7 @@ static struct alc_config_preset alc662_presets[] = {
.init_hook = alc662_eeepc_inithook,
},
[ALC663_ASUS_M51VA] = {
- .mixers = { alc663_m51va_mixer, alc662_capture_mixer},
+ .mixers = { alc663_m51va_mixer },
.init_verbs = { alc662_init_verbs, alc663_m51va_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
@@ -15975,7 +16130,7 @@ static struct alc_config_preset alc662_presets[] = {
.init_hook = alc663_m51va_inithook,
},
[ALC663_ASUS_G71V] = {
- .mixers = { alc663_g71v_mixer, alc662_capture_mixer},
+ .mixers = { alc663_g71v_mixer },
.init_verbs = { alc662_init_verbs, alc663_g71v_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
@@ -15987,7 +16142,7 @@ static struct alc_config_preset alc662_presets[] = {
.init_hook = alc663_g71v_inithook,
},
[ALC663_ASUS_H13] = {
- .mixers = { alc663_m51va_mixer, alc662_capture_mixer},
+ .mixers = { alc663_m51va_mixer },
.init_verbs = { alc662_init_verbs, alc663_m51va_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
@@ -15998,7 +16153,7 @@ static struct alc_config_preset alc662_presets[] = {
.init_hook = alc663_m51va_inithook,
},
[ALC663_ASUS_G50V] = {
- .mixers = { alc663_g50v_mixer, alc662_capture_mixer},
+ .mixers = { alc663_g50v_mixer },
.init_verbs = { alc662_init_verbs, alc663_g50v_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
@@ -16010,7 +16165,8 @@ static struct alc_config_preset alc662_presets[] = {
.init_hook = alc663_g50v_inithook,
},
[ALC663_ASUS_MODE1] = {
- .mixers = { alc663_m51va_mixer, alc662_auto_capture_mixer },
+ .mixers = { alc663_m51va_mixer },
+ .cap_mixer = alc662_auto_capture_mixer,
.init_verbs = { alc662_init_verbs,
alc663_21jd_amic_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
@@ -16024,7 +16180,8 @@ static struct alc_config_preset alc662_presets[] = {
.init_hook = alc663_mode1_inithook,
},
[ALC662_ASUS_MODE2] = {
- .mixers = { alc662_1bjd_mixer, alc662_auto_capture_mixer },
+ .mixers = { alc662_1bjd_mixer },
+ .cap_mixer = alc662_auto_capture_mixer,
.init_verbs = { alc662_init_verbs,
alc662_1bjd_amic_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
@@ -16037,7 +16194,8 @@ static struct alc_config_preset alc662_presets[] = {
.init_hook = alc662_mode2_inithook,
},
[ALC663_ASUS_MODE3] = {
- .mixers = { alc663_two_hp_m1_mixer, alc662_auto_capture_mixer },
+ .mixers = { alc663_two_hp_m1_mixer },
+ .cap_mixer = alc662_auto_capture_mixer,
.init_verbs = { alc662_init_verbs,
alc663_two_hp_amic_m1_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
@@ -16051,8 +16209,8 @@ static struct alc_config_preset alc662_presets[] = {
.init_hook = alc663_mode3_inithook,
},
[ALC663_ASUS_MODE4] = {
- .mixers = { alc663_asus_21jd_clfe_mixer,
- alc662_auto_capture_mixer},
+ .mixers = { alc663_asus_21jd_clfe_mixer },
+ .cap_mixer = alc662_auto_capture_mixer,
.init_verbs = { alc662_init_verbs,
alc663_21jd_amic_init_verbs},
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
@@ -16066,8 +16224,8 @@ static struct alc_config_preset alc662_presets[] = {
.init_hook = alc663_mode4_inithook,
},
[ALC663_ASUS_MODE5] = {
- .mixers = { alc663_asus_15jd_clfe_mixer,
- alc662_auto_capture_mixer },
+ .mixers = { alc663_asus_15jd_clfe_mixer },
+ .cap_mixer = alc662_auto_capture_mixer,
.init_verbs = { alc662_init_verbs,
alc663_15jd_amic_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
@@ -16081,7 +16239,8 @@ static struct alc_config_preset alc662_presets[] = {
.init_hook = alc663_mode5_inithook,
},
[ALC663_ASUS_MODE6] = {
- .mixers = { alc663_two_hp_m2_mixer, alc662_auto_capture_mixer },
+ .mixers = { alc663_two_hp_m2_mixer },
+ .cap_mixer = alc662_auto_capture_mixer,
.init_verbs = { alc662_init_verbs,
alc663_two_hp_amic_m2_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
@@ -16342,24 +16501,20 @@ static int alc662_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_out_pin)
spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
- if (spec->kctl_alloc)
- spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
+ if (spec->kctls.list)
+ add_mixer(spec, spec->kctls.list);
spec->num_mux_defs = 1;
spec->input_mux = &spec->private_imux;
- spec->init_verbs[spec->num_init_verbs++] = alc662_auto_init_verbs;
+ add_verb(spec, alc662_auto_init_verbs);
if (codec->vendor_id == 0x10ec0663)
- spec->init_verbs[spec->num_init_verbs++] =
- alc663_auto_init_verbs;
+ add_verb(spec, alc663_auto_init_verbs);
err = alc_auto_add_mic_boost(codec);
if (err < 0)
return err;
- spec->mixers[spec->num_mixers] = alc662_capture_mixer;
- spec->num_mixers++;
-
store_pin_configs(codec);
return 1;
}
@@ -16435,6 +16590,10 @@ static int patch_alc662(struct hda_codec *codec)
spec->adc_nids = alc662_adc_nids;
spec->num_adc_nids = ARRAY_SIZE(alc662_adc_nids);
spec->capsrc_nids = alc662_capsrc_nids;
+ spec->is_mix_capture = 1;
+
+ if (!spec->cap_mixer)
+ set_capture_mixer(spec);
spec->vmaster_nid = 0x02;
@@ -16445,6 +16604,7 @@ static int patch_alc662(struct hda_codec *codec)
if (!spec->loopback.amplist)
spec->loopback.amplist = alc662_loopbacks;
#endif
+ codec->proc_widget_hook = print_realtek_coef;
return 0;
}
@@ -16452,7 +16612,7 @@ static int patch_alc662(struct hda_codec *codec)
/*
* patch entries
*/
-struct hda_codec_preset snd_hda_preset_realtek[] = {
+static struct hda_codec_preset snd_hda_preset_realtek[] = {
{ .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
{ .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 },
{ .id = 0x10ec0267, .name = "ALC267", .patch = patch_alc268 },
@@ -16484,3 +16644,26 @@ struct hda_codec_preset snd_hda_preset_realtek[] = {
{ .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc883 },
{} /* terminator */
};
+
+MODULE_ALIAS("snd-hda-codec-id:10ec*");
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Realtek HD-audio codec");
+
+static struct hda_codec_preset_list realtek_list = {
+ .preset = snd_hda_preset_realtek,
+ .owner = THIS_MODULE,
+};
+
+static int __init patch_realtek_init(void)
+{
+ return snd_hda_add_codec_preset(&realtek_list);
+}
+
+static void __exit patch_realtek_exit(void)
+{
+ snd_hda_delete_codec_preset(&realtek_list);
+}
+
+module_init(patch_realtek_init)
+module_exit(patch_realtek_exit)
diff --git a/sound/pci/hda/patch_si3054.c b/sound/pci/hda/patch_si3054.c
index 9332b63e406..43b436c5d01 100644
--- a/sound/pci/hda/patch_si3054.c
+++ b/sound/pci/hda/patch_si3054.c
@@ -28,7 +28,6 @@
#include <sound/core.h>
#include "hda_codec.h"
#include "hda_local.h"
-#include "hda_patch.h"
/* si3054 verbs */
#define SI3054_VERB_READ_NODE 0x900
@@ -283,7 +282,7 @@ static int patch_si3054(struct hda_codec *codec)
/*
* patch entries
*/
-struct hda_codec_preset snd_hda_preset_si3054[] = {
+static struct hda_codec_preset snd_hda_preset_si3054[] = {
{ .id = 0x163c3055, .name = "Si3054", .patch = patch_si3054 },
{ .id = 0x163c3155, .name = "Si3054", .patch = patch_si3054 },
{ .id = 0x11c13026, .name = "Si3054", .patch = patch_si3054 },
@@ -301,3 +300,35 @@ struct hda_codec_preset snd_hda_preset_si3054[] = {
{}
};
+MODULE_ALIAS("snd-hda-codec-id:163c3055");
+MODULE_ALIAS("snd-hda-codec-id:163c3155");
+MODULE_ALIAS("snd-hda-codec-id:11c13026");
+MODULE_ALIAS("snd-hda-codec-id:11c13055");
+MODULE_ALIAS("snd-hda-codec-id:11c13155");
+MODULE_ALIAS("snd-hda-codec-id:10573055");
+MODULE_ALIAS("snd-hda-codec-id:10573057");
+MODULE_ALIAS("snd-hda-codec-id:10573155");
+MODULE_ALIAS("snd-hda-codec-id:11063288");
+MODULE_ALIAS("snd-hda-codec-id:15433155");
+MODULE_ALIAS("snd-hda-codec-id:18540018");
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Si3054 HD-audio modem codec");
+
+static struct hda_codec_preset_list si3054_list = {
+ .preset = snd_hda_preset_si3054,
+ .owner = THIS_MODULE,
+};
+
+static int __init patch_si3054_init(void)
+{
+ return snd_hda_add_codec_preset(&si3054_list);
+}
+
+static void __exit patch_si3054_exit(void)
+{
+ snd_hda_delete_codec_preset(&si3054_list);
+}
+
+module_init(patch_si3054_init)
+module_exit(patch_si3054_exit)
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index e6085915d86..35b83dc6e19 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -30,15 +30,17 @@
#include <linux/pci.h>
#include <sound/core.h>
#include <sound/asoundef.h>
+#include <sound/jack.h>
#include "hda_codec.h"
#include "hda_local.h"
-#include "hda_patch.h"
#include "hda_beep.h"
-#define NUM_CONTROL_ALLOC 32
-#define STAC_PWR_EVENT 0x20
-#define STAC_HP_EVENT 0x30
-#define STAC_VREF_EVENT 0x40
+enum {
+ STAC_VREF_EVENT = 1,
+ STAC_INSERT_EVENT,
+ STAC_PWR_EVENT,
+ STAC_HP_EVENT,
+};
enum {
STAC_REF,
@@ -67,8 +69,11 @@ enum {
};
enum {
+ STAC_92HD73XX_NO_JD, /* no jack-detection */
STAC_92HD73XX_REF,
- STAC_DELL_M6,
+ STAC_DELL_M6_AMIC,
+ STAC_DELL_M6_DMIC,
+ STAC_DELL_M6_BOTH,
STAC_DELL_EQ,
STAC_92HD73XX_MODELS
};
@@ -82,6 +87,7 @@ enum {
STAC_92HD71BXX_REF,
STAC_DELL_M4_1,
STAC_DELL_M4_2,
+ STAC_DELL_M4_3,
STAC_HP_M4,
STAC_92HD71BXX_MODELS
};
@@ -122,6 +128,7 @@ enum {
};
enum {
+ STAC_D965_REF_NO_JD, /* no jack-detection */
STAC_D965_REF,
STAC_D965_3ST,
STAC_D965_5ST,
@@ -130,14 +137,26 @@ enum {
STAC_927X_MODELS
};
+struct sigmatel_event {
+ hda_nid_t nid;
+ unsigned char type;
+ unsigned char tag;
+ int data;
+};
+
+struct sigmatel_jack {
+ hda_nid_t nid;
+ int type;
+ struct snd_jack *jack;
+};
+
struct sigmatel_spec {
struct snd_kcontrol_new *mixers[4];
unsigned int num_mixers;
int board_config;
+ unsigned int eapd_switch: 1;
unsigned int surr_switch: 1;
- unsigned int line_switch: 1;
- unsigned int mic_switch: 1;
unsigned int alt_switch: 1;
unsigned int hp_detect: 1;
unsigned int spdif_mute: 1;
@@ -162,12 +181,20 @@ struct sigmatel_spec {
hda_nid_t *pwr_nids;
hda_nid_t *dac_list;
+ /* jack detection */
+ struct snd_array jacks;
+
+ /* events */
+ struct snd_array events;
+
/* playback */
struct hda_input_mux *mono_mux;
struct hda_input_mux *amp_mux;
unsigned int cur_mmux;
struct hda_multi_out multiout;
hda_nid_t dac_nids[5];
+ hda_nid_t hp_dacs[5];
+ hda_nid_t speaker_dacs[5];
/* capture */
hda_nid_t *adc_nids;
@@ -191,7 +218,6 @@ struct sigmatel_spec {
hda_nid_t *pin_nids;
unsigned int num_pins;
unsigned int *pin_configs;
- unsigned int *bios_pin_configs;
/* codec specific stuff */
struct hda_verb *init;
@@ -212,15 +238,16 @@ struct sigmatel_spec {
/* i/o switches */
unsigned int io_switch[2];
unsigned int clfe_swap;
- unsigned int hp_switch;
+ hda_nid_t line_switch; /* shared line-in for input and output */
+ hda_nid_t mic_switch; /* shared mic-in for input and output */
+ hda_nid_t hp_switch; /* NID of HP as line-out */
unsigned int aloopback;
struct hda_pcm pcm_rec[2]; /* PCM information */
/* dynamic controls and input_mux */
struct auto_pin_cfg autocfg;
- unsigned int num_kctl_alloc, num_kctl_used;
- struct snd_kcontrol_new *kctl_alloc;
+ struct snd_array kctls;
struct hda_input_mux private_dimux;
struct hda_input_mux private_imux;
struct hda_input_mux private_smux;
@@ -264,9 +291,6 @@ static hda_nid_t stac92hd73xx_dmic_nids[STAC92HD73XX_NUM_DMICS + 1] = {
};
#define STAC92HD73_DAC_COUNT 5
-static hda_nid_t stac92hd73xx_dac_nids[STAC92HD73_DAC_COUNT] = {
- 0x15, 0x16, 0x17, 0x18, 0x19,
-};
static hda_nid_t stac92hd73xx_mux_nids[4] = {
0x28, 0x29, 0x2a, 0x2b,
@@ -285,11 +309,7 @@ static hda_nid_t stac92hd83xxx_dmic_nids[STAC92HD83XXX_NUM_DMICS + 1] = {
0x11, 0x12, 0
};
-#define STAC92HD81_DAC_COUNT 2
#define STAC92HD83_DAC_COUNT 3
-static hda_nid_t stac92hd83xxx_dac_nids[STAC92HD73_DAC_COUNT] = {
- 0x13, 0x14, 0x22,
-};
static hda_nid_t stac92hd83xxx_dmux_nids[2] = {
0x17, 0x18,
@@ -331,10 +351,6 @@ static hda_nid_t stac92hd71bxx_smux_nids[2] = {
0x24, 0x25,
};
-static hda_nid_t stac92hd71bxx_dac_nids[1] = {
- 0x10, /*0x11, */
-};
-
#define STAC92HD71BXX_NUM_DMICS 2
static hda_nid_t stac92hd71bxx_dmic_nids[STAC92HD71BXX_NUM_DMICS + 1] = {
0x18, 0x19, 0
@@ -566,12 +582,12 @@ static int stac92xx_smux_enum_put(struct snd_kcontrol *kcontrol,
else
nid = codec->slave_dig_outs[smux_idx - 1];
if (spec->cur_smux[smux_idx] == smux->num_items - 1)
- val = AMP_OUT_MUTE;
+ val = HDA_AMP_MUTE;
else
- val = AMP_OUT_UNMUTE;
+ val = 0;
/* un/mute SPDIF out */
- snd_hda_codec_write_cache(codec, nid, 0,
- AC_VERB_SET_AMP_GAIN_MUTE, val);
+ snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, val);
}
return 0;
}
@@ -736,10 +752,6 @@ static struct hda_verb stac9200_eapd_init[] = {
static struct hda_verb stac92hd73xx_6ch_core_init[] = {
/* set master volume and direct control */
{ 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
- /* setup audio connections */
- { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00},
- { 0x10, AC_VERB_SET_CONNECT_SEL, 0x01},
- { 0x11, AC_VERB_SET_CONNECT_SEL, 0x02},
/* setup adcs to point to mixer */
{ 0x20, AC_VERB_SET_CONNECT_SEL, 0x0b},
{ 0x21, AC_VERB_SET_CONNECT_SEL, 0x0b},
@@ -758,10 +770,6 @@ static struct hda_verb dell_eq_core_init[] = {
/* set master volume to max value without distortion
* and direct control */
{ 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xec},
- /* setup audio connections */
- { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
- { 0x0a, AC_VERB_SET_CONNECT_SEL, 0x02},
- { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x01},
/* setup adcs to point to mixer */
{ 0x20, AC_VERB_SET_CONNECT_SEL, 0x0b},
{ 0x21, AC_VERB_SET_CONNECT_SEL, 0x0b},
@@ -775,10 +783,6 @@ static struct hda_verb dell_eq_core_init[] = {
static struct hda_verb dell_m6_core_init[] = {
{ 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
- /* setup audio connections */
- { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
- { 0x0a, AC_VERB_SET_CONNECT_SEL, 0x01},
- { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x02},
/* setup adcs to point to mixer */
{ 0x20, AC_VERB_SET_CONNECT_SEL, 0x0b},
{ 0x21, AC_VERB_SET_CONNECT_SEL, 0x0b},
@@ -793,13 +797,6 @@ static struct hda_verb dell_m6_core_init[] = {
static struct hda_verb stac92hd73xx_8ch_core_init[] = {
/* set master volume and direct control */
{ 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
- /* setup audio connections */
- { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00},
- { 0x10, AC_VERB_SET_CONNECT_SEL, 0x01},
- { 0x11, AC_VERB_SET_CONNECT_SEL, 0x02},
- /* connect hp ports to dac3 */
- { 0x0a, AC_VERB_SET_CONNECT_SEL, 0x03},
- { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x03},
/* setup adcs to point to mixer */
{ 0x20, AC_VERB_SET_CONNECT_SEL, 0x0b},
{ 0x21, AC_VERB_SET_CONNECT_SEL, 0x0b},
@@ -817,15 +814,8 @@ static struct hda_verb stac92hd73xx_8ch_core_init[] = {
static struct hda_verb stac92hd73xx_10ch_core_init[] = {
/* set master volume and direct control */
{ 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
- /* setup audio connections */
- { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
- { 0x10, AC_VERB_SET_CONNECT_SEL, 0x01 },
- { 0x11, AC_VERB_SET_CONNECT_SEL, 0x02 },
/* dac3 is connected to import3 mux */
{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb07f},
- /* connect hp ports to dac4 */
- { 0x0a, AC_VERB_SET_CONNECT_SEL, 0x04},
- { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x04},
/* setup adcs to point to mixer */
{ 0x20, AC_VERB_SET_CONNECT_SEL, 0x0b},
{ 0x21, AC_VERB_SET_CONNECT_SEL, 0x0b},
@@ -851,17 +841,17 @@ static struct hda_verb stac92hd83xxx_core_init[] = {
/* power state controls amps */
{ 0x01, AC_VERB_SET_EAPD, 1 << 2},
+ {}
};
static struct hda_verb stac92hd71bxx_core_init[] = {
/* set master volume and direct control */
{ 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
- /* connect headphone jack to dac1 */
- { 0x0a, AC_VERB_SET_CONNECT_SEL, 0x01},
/* unmute right and left channels for nodes 0x0a, 0xd, 0x0f */
{ 0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{ 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{ 0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {}
};
#define HD_DISABLE_PORTF 2
@@ -876,8 +866,6 @@ static struct hda_verb stac92hd71bxx_analog_core_init[] = {
/* set master volume and direct control */
{ 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
- /* connect headphone jack to dac1 */
- { 0x0a, AC_VERB_SET_CONNECT_SEL, 0x01},
/* unmute right and left channels for nodes 0x0a, 0xd */
{ 0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{ 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
@@ -1077,21 +1065,21 @@ static struct snd_kcontrol_new stac92hd83xxx_mixer[] = {
HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x18, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x18, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("DAC0 Capture Volume", 0x1b, 0, HDA_INPUT),
- HDA_CODEC_MUTE("DAC0 Capture Switch", 0x1b, 0, HDA_INPUT),
+ HDA_CODEC_VOLUME("DAC0 Capture Volume", 0x1b, 0x3, HDA_INPUT),
+ HDA_CODEC_MUTE("DAC0 Capture Switch", 0x1b, 0x3, HDA_INPUT),
- HDA_CODEC_VOLUME("DAC1 Capture Volume", 0x1b, 0x1, HDA_INPUT),
- HDA_CODEC_MUTE("DAC1 Capture Switch", 0x1b, 0x1, HDA_INPUT),
+ HDA_CODEC_VOLUME("DAC1 Capture Volume", 0x1b, 0x4, HDA_INPUT),
+ HDA_CODEC_MUTE("DAC1 Capture Switch", 0x1b, 0x4, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Capture Volume", 0x1b, 0x2, HDA_INPUT),
- HDA_CODEC_MUTE("Front Mic Capture Switch", 0x1b, 0x2, HDA_INPUT),
+ HDA_CODEC_VOLUME("Front Mic Capture Volume", 0x1b, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Front Mic Capture Switch", 0x1b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Line In Capture Volume", 0x1b, 0x3, HDA_INPUT),
- HDA_CODEC_MUTE("Line In Capture Switch", 0x1b, 0x3, HDA_INPUT),
+ HDA_CODEC_VOLUME("Line In Capture Volume", 0x1b, 0x2, HDA_INPUT),
+ HDA_CODEC_MUTE("Line In Capture Switch", 0x1b, 0x2, HDA_INPUT),
/*
- HDA_CODEC_VOLUME("Mic Capture Volume", 0x1b, 0x4, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Capture Switch", 0x1b 0x4, HDA_INPUT),
+ HDA_CODEC_VOLUME("Mic Capture Volume", 0x1b, 0x1, HDA_INPUT),
+ HDA_CODEC_MUTE("Mic Capture Switch", 0x1b 0x1, HDA_INPUT),
*/
{ } /* end */
};
@@ -1230,9 +1218,14 @@ static const char *slave_sws[] = {
NULL
};
+static void stac92xx_free_kctls(struct hda_codec *codec);
+static int stac92xx_add_jack(struct hda_codec *codec, hda_nid_t nid, int type);
+
static int stac92xx_build_controls(struct hda_codec *codec)
{
struct sigmatel_spec *spec = codec->spec;
+ struct auto_pin_cfg *cfg = &spec->autocfg;
+ hda_nid_t nid;
int err;
int i;
@@ -1247,7 +1240,7 @@ static int stac92xx_build_controls(struct hda_codec *codec)
}
if (spec->num_dmuxes > 0) {
stac_dmux_mixer.count = spec->num_dmuxes;
- err = snd_ctl_add(codec->bus->card,
+ err = snd_hda_ctl_add(codec,
snd_ctl_new1(&stac_dmux_mixer, codec));
if (err < 0)
return err;
@@ -1263,7 +1256,7 @@ static int stac92xx_build_controls(struct hda_codec *codec)
spec->spdif_mute = 1;
}
stac_smux_mixer.count = spec->num_smuxes;
- err = snd_ctl_add(codec->bus->card,
+ err = snd_hda_ctl_add(codec,
snd_ctl_new1(&stac_smux_mixer, codec));
if (err < 0)
return err;
@@ -1302,6 +1295,37 @@ static int stac92xx_build_controls(struct hda_codec *codec)
return err;
}
+ stac92xx_free_kctls(codec); /* no longer needed */
+
+ /* create jack input elements */
+ if (spec->hp_detect) {
+ for (i = 0; i < cfg->hp_outs; i++) {
+ int type = SND_JACK_HEADPHONE;
+ nid = cfg->hp_pins[i];
+ /* jack detection */
+ if (cfg->hp_outs == i)
+ type |= SND_JACK_LINEOUT;
+ err = stac92xx_add_jack(codec, nid, type);
+ if (err < 0)
+ return err;
+ }
+ }
+ for (i = 0; i < cfg->line_outs; i++) {
+ err = stac92xx_add_jack(codec, cfg->line_out_pins[i],
+ SND_JACK_LINEOUT);
+ if (err < 0)
+ return err;
+ }
+ for (i = 0; i < AUTO_PIN_LAST; i++) {
+ nid = cfg->input_pins[i];
+ if (nid) {
+ err = stac92xx_add_jack(codec, nid,
+ SND_JACK_MICROPHONE);
+ if (err < 0)
+ return err;
+ }
+ }
+
return 0;
}
@@ -1598,13 +1622,18 @@ static unsigned int dell_m6_pin_configs[13] = {
static unsigned int *stac92hd73xx_brd_tbl[STAC_92HD73XX_MODELS] = {
[STAC_92HD73XX_REF] = ref92hd73xx_pin_configs,
- [STAC_DELL_M6] = dell_m6_pin_configs,
+ [STAC_DELL_M6_AMIC] = dell_m6_pin_configs,
+ [STAC_DELL_M6_DMIC] = dell_m6_pin_configs,
+ [STAC_DELL_M6_BOTH] = dell_m6_pin_configs,
[STAC_DELL_EQ] = dell_m6_pin_configs,
};
static const char *stac92hd73xx_models[STAC_92HD73XX_MODELS] = {
+ [STAC_92HD73XX_NO_JD] = "no-jd",
[STAC_92HD73XX_REF] = "ref",
- [STAC_DELL_M6] = "dell-m6",
+ [STAC_DELL_M6_AMIC] = "dell-m6-amic",
+ [STAC_DELL_M6_DMIC] = "dell-m6-dmic",
+ [STAC_DELL_M6_BOTH] = "dell-m6",
[STAC_DELL_EQ] = "dell-eq",
};
@@ -1613,19 +1642,25 @@ static struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = {
SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
"DFI LanParty", STAC_92HD73XX_REF),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0254,
- "unknown Dell", STAC_DELL_M6),
+ "Dell Studio 1535", STAC_DELL_M6_DMIC),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0255,
- "unknown Dell", STAC_DELL_M6),
+ "unknown Dell", STAC_DELL_M6_DMIC),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0256,
- "unknown Dell", STAC_DELL_M6),
+ "unknown Dell", STAC_DELL_M6_BOTH),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0257,
- "unknown Dell", STAC_DELL_M6),
+ "unknown Dell", STAC_DELL_M6_BOTH),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x025e,
- "unknown Dell", STAC_DELL_M6),
+ "unknown Dell", STAC_DELL_M6_AMIC),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x025f,
- "unknown Dell", STAC_DELL_M6),
+ "unknown Dell", STAC_DELL_M6_AMIC),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0271,
- "unknown Dell", STAC_DELL_M6),
+ "unknown Dell", STAC_DELL_M6_DMIC),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0272,
+ "unknown Dell", STAC_DELL_M6_DMIC),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x029f,
+ "Dell Studio 1537", STAC_DELL_M6_DMIC),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02a0,
+ "Dell Studio 17", STAC_DELL_M6_DMIC),
{} /* terminator */
};
@@ -1648,6 +1683,7 @@ static struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = {
/* SigmaTel reference board */
SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
"DFI LanParty", STAC_92HD71BXX_REF),
+ {} /* terminator */
};
static unsigned int ref92hd71bxx_pin_configs[11] = {
@@ -1668,10 +1704,17 @@ static unsigned int dell_m4_2_pin_configs[11] = {
0x40f000f0, 0x044413b0, 0x044413b0,
};
+static unsigned int dell_m4_3_pin_configs[11] = {
+ 0x0421101f, 0x04a11221, 0x90a70330, 0x90170110,
+ 0x40f000f0, 0x40f000f0, 0x40f000f0, 0x90a000f0,
+ 0x40f000f0, 0x044413b0, 0x044413b0,
+};
+
static unsigned int *stac92hd71bxx_brd_tbl[STAC_92HD71BXX_MODELS] = {
[STAC_92HD71BXX_REF] = ref92hd71bxx_pin_configs,
[STAC_DELL_M4_1] = dell_m4_1_pin_configs,
[STAC_DELL_M4_2] = dell_m4_2_pin_configs,
+ [STAC_DELL_M4_3] = dell_m4_3_pin_configs,
[STAC_HP_M4] = NULL,
};
@@ -1679,6 +1722,7 @@ static const char *stac92hd71bxx_models[STAC_92HD71BXX_MODELS] = {
[STAC_92HD71BXX_REF] = "ref",
[STAC_DELL_M4_1] = "dell-m4-1",
[STAC_DELL_M4_2] = "dell-m4-2",
+ [STAC_DELL_M4_3] = "dell-m4-3",
[STAC_HP_M4] = "hp-m4",
};
@@ -1686,6 +1730,12 @@ static struct snd_pci_quirk stac92hd71bxx_cfg_tbl[] = {
/* SigmaTel reference board */
SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
"DFI LanParty", STAC_92HD71BXX_REF),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x30f2,
+ "HP dv5", STAC_HP_M4),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x30f4,
+ "HP dv7", STAC_HP_M4),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x30fc,
+ "HP dv7", STAC_HP_M4),
SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x361a,
"unknown HP", STAC_HP_M4),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0233,
@@ -1710,6 +1760,8 @@ static struct snd_pci_quirk stac92hd71bxx_cfg_tbl[] = {
"unknown Dell", STAC_DELL_M4_2),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0264,
"unknown Dell", STAC_DELL_M4_2),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02aa,
+ "unknown Dell", STAC_DELL_M4_3),
{} /* terminator */
};
@@ -1999,6 +2051,7 @@ static unsigned int dell_3st_pin_configs[14] = {
};
static unsigned int *stac927x_brd_tbl[STAC_927X_MODELS] = {
+ [STAC_D965_REF_NO_JD] = ref927x_pin_configs,
[STAC_D965_REF] = ref927x_pin_configs,
[STAC_D965_3ST] = d965_3st_pin_configs,
[STAC_D965_5ST] = d965_5st_pin_configs,
@@ -2007,6 +2060,7 @@ static unsigned int *stac927x_brd_tbl[STAC_927X_MODELS] = {
};
static const char *stac927x_models[STAC_927X_MODELS] = {
+ [STAC_D965_REF_NO_JD] = "ref-no-jd",
[STAC_D965_REF] = "ref",
[STAC_D965_3ST] = "3stack",
[STAC_D965_5ST] = "5stack",
@@ -2165,12 +2219,11 @@ static int stac92xx_save_bios_config_regs(struct hda_codec *codec)
int i;
struct sigmatel_spec *spec = codec->spec;
- if (! spec->bios_pin_configs) {
- spec->bios_pin_configs = kcalloc(spec->num_pins,
- sizeof(*spec->bios_pin_configs), GFP_KERNEL);
- if (! spec->bios_pin_configs)
- return -ENOMEM;
- }
+ kfree(spec->pin_configs);
+ spec->pin_configs = kcalloc(spec->num_pins, sizeof(*spec->pin_configs),
+ GFP_KERNEL);
+ if (!spec->pin_configs)
+ return -ENOMEM;
for (i = 0; i < spec->num_pins; i++) {
hda_nid_t nid = spec->pin_nids[i];
@@ -2180,7 +2233,7 @@ static int stac92xx_save_bios_config_regs(struct hda_codec *codec)
AC_VERB_GET_CONFIG_DEFAULT, 0x00);
snd_printdd(KERN_INFO "hda_codec: pin nid %2.2x bios pin config %8.8x\n",
nid, pin_cfg);
- spec->bios_pin_configs[i] = pin_cfg;
+ spec->pin_configs[i] = pin_cfg;
}
return 0;
@@ -2222,6 +2275,39 @@ static void stac92xx_set_config_regs(struct hda_codec *codec)
spec->pin_configs[i]);
}
+static int stac_save_pin_cfgs(struct hda_codec *codec, unsigned int *pins)
+{
+ struct sigmatel_spec *spec = codec->spec;
+
+ if (!pins)
+ return stac92xx_save_bios_config_regs(codec);
+
+ kfree(spec->pin_configs);
+ spec->pin_configs = kmemdup(pins,
+ spec->num_pins * sizeof(*pins),
+ GFP_KERNEL);
+ if (!spec->pin_configs)
+ return -ENOMEM;
+
+ stac92xx_set_config_regs(codec);
+ return 0;
+}
+
+static void stac_change_pin_config(struct hda_codec *codec, hda_nid_t nid,
+ unsigned int cfg)
+{
+ struct sigmatel_spec *spec = codec->spec;
+ int i;
+
+ for (i = 0; i < spec->num_pins; i++) {
+ if (spec->pin_nids[i] == nid) {
+ spec->pin_configs[i] = cfg;
+ stac92xx_set_config_reg(codec, nid, cfg);
+ break;
+ }
+ }
+}
+
/*
* Analog playback callbacks
*/
@@ -2299,7 +2385,7 @@ static int stac92xx_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
if (spec->powerdown_adcs) {
msleep(40);
- snd_hda_codec_write_cache(codec, nid, 0,
+ snd_hda_codec_write(codec, nid, 0,
AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
}
snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
@@ -2315,7 +2401,7 @@ static int stac92xx_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
snd_hda_codec_cleanup_stream(codec, nid);
if (spec->powerdown_adcs)
- snd_hda_codec_write_cache(codec, nid, 0,
+ snd_hda_codec_write(codec, nid, 0,
AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
return 0;
}
@@ -2443,22 +2529,26 @@ static int stac92xx_hp_switch_get(struct snd_kcontrol *kcontrol,
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct sigmatel_spec *spec = codec->spec;
- ucontrol->value.integer.value[0] = spec->hp_switch;
+ ucontrol->value.integer.value[0] = !!spec->hp_switch;
return 0;
}
+static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid,
+ unsigned char type);
+
static int stac92xx_hp_switch_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct sigmatel_spec *spec = codec->spec;
-
- spec->hp_switch = ucontrol->value.integer.value[0];
+ int nid = kcontrol->private_value;
+
+ spec->hp_switch = ucontrol->value.integer.value[0] ? nid : 0;
/* check to be sure that the ports are upto date with
* switch changes
*/
- codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26);
+ stac_issue_unsol_event(codec, nid, STAC_HP_EVENT);
return 1;
}
@@ -2498,7 +2588,7 @@ static int stac92xx_io_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_
* appropriately according to the pin direction
*/
if (spec->hp_detect)
- codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26);
+ stac_issue_unsol_event(codec, nid, STAC_HP_EVENT);
return 1;
}
@@ -2586,108 +2676,90 @@ static struct snd_kcontrol_new stac92xx_control_templates[] = {
};
/* add dynamic controls */
-static int stac92xx_add_control_idx(struct sigmatel_spec *spec, int type,
- int idx, const char *name, unsigned long val)
+static int stac92xx_add_control_temp(struct sigmatel_spec *spec,
+ struct snd_kcontrol_new *ktemp,
+ int idx, const char *name,
+ unsigned long val)
{
struct snd_kcontrol_new *knew;
- if (spec->num_kctl_used >= spec->num_kctl_alloc) {
- int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC;
-
- knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); /* array + terminator */
- if (! knew)
- return -ENOMEM;
- if (spec->kctl_alloc) {
- memcpy(knew, spec->kctl_alloc, sizeof(*knew) * spec->num_kctl_alloc);
- kfree(spec->kctl_alloc);
- }
- spec->kctl_alloc = knew;
- spec->num_kctl_alloc = num;
- }
-
- knew = &spec->kctl_alloc[spec->num_kctl_used];
- *knew = stac92xx_control_templates[type];
+ snd_array_init(&spec->kctls, sizeof(*knew), 32);
+ knew = snd_array_new(&spec->kctls);
+ if (!knew)
+ return -ENOMEM;
+ *knew = *ktemp;
knew->index = idx;
knew->name = kstrdup(name, GFP_KERNEL);
- if (! knew->name)
+ if (!knew->name)
return -ENOMEM;
knew->private_value = val;
- spec->num_kctl_used++;
return 0;
}
+static inline int stac92xx_add_control_idx(struct sigmatel_spec *spec,
+ int type, int idx, const char *name,
+ unsigned long val)
+{
+ return stac92xx_add_control_temp(spec,
+ &stac92xx_control_templates[type],
+ idx, name, val);
+}
+
/* add dynamic controls */
-static int stac92xx_add_control(struct sigmatel_spec *spec, int type,
- const char *name, unsigned long val)
+static inline int stac92xx_add_control(struct sigmatel_spec *spec, int type,
+ const char *name, unsigned long val)
{
return stac92xx_add_control_idx(spec, type, 0, name, val);
}
-/* flag inputs as additional dynamic lineouts */
-static int stac92xx_add_dyn_out_pins(struct hda_codec *codec, struct auto_pin_cfg *cfg)
+/* check whether the line-input can be used as line-out */
+static hda_nid_t check_line_out_switch(struct hda_codec *codec)
{
struct sigmatel_spec *spec = codec->spec;
- unsigned int wcaps, wtype;
- int i, num_dacs = 0;
-
- /* use the wcaps cache to count all DACs available for line-outs */
- for (i = 0; i < codec->num_nodes; i++) {
- wcaps = codec->wcaps[i];
- wtype = (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
+ struct auto_pin_cfg *cfg = &spec->autocfg;
+ hda_nid_t nid;
+ unsigned int pincap;
- if (wtype == AC_WID_AUD_OUT && !(wcaps & AC_WCAP_DIGITAL))
- num_dacs++;
- }
+ if (cfg->line_out_type != AUTO_PIN_LINE_OUT)
+ return 0;
+ nid = cfg->input_pins[AUTO_PIN_LINE];
+ pincap = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
+ if (pincap & AC_PINCAP_OUT)
+ return nid;
+ return 0;
+}
- snd_printdd("%s: total dac count=%d\n", __func__, num_dacs);
-
- switch (cfg->line_outs) {
- case 3:
- /* add line-in as side */
- if (cfg->input_pins[AUTO_PIN_LINE] && num_dacs > 3) {
- cfg->line_out_pins[cfg->line_outs] =
- cfg->input_pins[AUTO_PIN_LINE];
- spec->line_switch = 1;
- cfg->line_outs++;
- }
- break;
- case 2:
- /* add line-in as clfe and mic as side */
- if (cfg->input_pins[AUTO_PIN_LINE] && num_dacs > 2) {
- cfg->line_out_pins[cfg->line_outs] =
- cfg->input_pins[AUTO_PIN_LINE];
- spec->line_switch = 1;
- cfg->line_outs++;
- }
- if (cfg->input_pins[AUTO_PIN_MIC] && num_dacs > 3) {
- cfg->line_out_pins[cfg->line_outs] =
- cfg->input_pins[AUTO_PIN_MIC];
- spec->mic_switch = 1;
- cfg->line_outs++;
- }
- break;
- case 1:
- /* add line-in as surr and mic as clfe */
- if (cfg->input_pins[AUTO_PIN_LINE] && num_dacs > 1) {
- cfg->line_out_pins[cfg->line_outs] =
- cfg->input_pins[AUTO_PIN_LINE];
- spec->line_switch = 1;
- cfg->line_outs++;
- }
- if (cfg->input_pins[AUTO_PIN_MIC] && num_dacs > 2) {
- cfg->line_out_pins[cfg->line_outs] =
- cfg->input_pins[AUTO_PIN_MIC];
- spec->mic_switch = 1;
- cfg->line_outs++;
+/* check whether the mic-input can be used as line-out */
+static hda_nid_t check_mic_out_switch(struct hda_codec *codec)
+{
+ struct sigmatel_spec *spec = codec->spec;
+ struct auto_pin_cfg *cfg = &spec->autocfg;
+ unsigned int def_conf, pincap;
+ unsigned int mic_pin;
+
+ if (cfg->line_out_type != AUTO_PIN_LINE_OUT)
+ return 0;
+ mic_pin = AUTO_PIN_MIC;
+ for (;;) {
+ hda_nid_t nid = cfg->input_pins[mic_pin];
+ def_conf = snd_hda_codec_read(codec, nid, 0,
+ AC_VERB_GET_CONFIG_DEFAULT, 0);
+ /* some laptops have an internal analog microphone
+ * which can't be used as a output */
+ if (get_defcfg_connect(def_conf) != AC_JACK_PORT_FIXED) {
+ pincap = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
+ if (pincap & AC_PINCAP_OUT)
+ return nid;
}
- break;
+ if (mic_pin == AUTO_PIN_MIC)
+ mic_pin = AUTO_PIN_FRONT_MIC;
+ else
+ break;
}
-
return 0;
}
-
static int is_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid)
{
int i;
@@ -2700,6 +2772,52 @@ static int is_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid)
return 0;
}
+static int check_all_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid)
+{
+ int i;
+ if (is_in_dac_nids(spec, nid))
+ return 1;
+ for (i = 0; i < spec->autocfg.hp_outs; i++)
+ if (spec->hp_dacs[i] == nid)
+ return 1;
+ for (i = 0; i < spec->autocfg.speaker_outs; i++)
+ if (spec->speaker_dacs[i] == nid)
+ return 1;
+ return 0;
+}
+
+static hda_nid_t get_unassigned_dac(struct hda_codec *codec, hda_nid_t nid)
+{
+ struct sigmatel_spec *spec = codec->spec;
+ int j, conn_len;
+ hda_nid_t conn[HDA_MAX_CONNECTIONS];
+ unsigned int wcaps, wtype;
+
+ conn_len = snd_hda_get_connections(codec, nid, conn,
+ HDA_MAX_CONNECTIONS);
+ for (j = 0; j < conn_len; j++) {
+ wcaps = snd_hda_param_read(codec, conn[j],
+ AC_PAR_AUDIO_WIDGET_CAP);
+ wtype = (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
+ /* we check only analog outputs */
+ if (wtype != AC_WID_AUD_OUT || (wcaps & AC_WCAP_DIGITAL))
+ continue;
+ /* if this route has a free DAC, assign it */
+ if (!check_all_dac_nids(spec, conn[j])) {
+ if (conn_len > 1) {
+ /* select this DAC in the pin's input mux */
+ snd_hda_codec_write_cache(codec, nid, 0,
+ AC_VERB_SET_CONNECT_SEL, j);
+ }
+ return conn[j];
+ }
+ }
+ return 0;
+}
+
+static int add_spec_dacs(struct sigmatel_spec *spec, hda_nid_t nid);
+static int add_spec_extra_dacs(struct sigmatel_spec *spec, hda_nid_t nid);
+
/*
* Fill in the dac_nids table from the parsed pin configuration
* This function only works when every pin in line_out_pins[]
@@ -2707,31 +2825,17 @@ static int is_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid)
* codecs are not connected directly to a DAC, such as the 9200
* and 9202/925x. For those, dac_nids[] must be hard-coded.
*/
-static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec,
- struct auto_pin_cfg *cfg)
+static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec)
{
struct sigmatel_spec *spec = codec->spec;
- int i, j, conn_len = 0;
- hda_nid_t nid, conn[HDA_MAX_CONNECTIONS];
- unsigned int wcaps, wtype;
+ struct auto_pin_cfg *cfg = &spec->autocfg;
+ int i;
+ hda_nid_t nid, dac;
for (i = 0; i < cfg->line_outs; i++) {
nid = cfg->line_out_pins[i];
- conn_len = snd_hda_get_connections(codec, nid, conn,
- HDA_MAX_CONNECTIONS);
- for (j = 0; j < conn_len; j++) {
- wcaps = snd_hda_param_read(codec, conn[j],
- AC_PAR_AUDIO_WIDGET_CAP);
- wtype = (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
- if (wtype != AC_WID_AUD_OUT ||
- (wcaps & AC_WCAP_DIGITAL))
- continue;
- /* conn[j] is a DAC routed to this line-out */
- if (!is_in_dac_nids(spec, conn[j]))
- break;
- }
-
- if (j == conn_len) {
+ dac = get_unassigned_dac(codec, nid);
+ if (!dac) {
if (spec->multiout.num_dacs > 0) {
/* we have already working output pins,
* so let's drop the broken ones again
@@ -2745,24 +2849,64 @@ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec,
__func__, nid);
return -ENODEV;
}
+ add_spec_dacs(spec, dac);
+ }
- spec->multiout.dac_nids[i] = conn[j];
- spec->multiout.num_dacs++;
- if (conn_len > 1) {
- /* select this DAC in the pin's input mux */
- snd_hda_codec_write_cache(codec, nid, 0,
- AC_VERB_SET_CONNECT_SEL, j);
+ /* add line-in as output */
+ nid = check_line_out_switch(codec);
+ if (nid) {
+ dac = get_unassigned_dac(codec, nid);
+ if (dac) {
+ snd_printdd("STAC: Add line-in 0x%x as output %d\n",
+ nid, cfg->line_outs);
+ cfg->line_out_pins[cfg->line_outs] = nid;
+ cfg->line_outs++;
+ spec->line_switch = nid;
+ add_spec_dacs(spec, dac);
+ }
+ }
+ /* add mic as output */
+ nid = check_mic_out_switch(codec);
+ if (nid) {
+ dac = get_unassigned_dac(codec, nid);
+ if (dac) {
+ snd_printdd("STAC: Add mic-in 0x%x as output %d\n",
+ nid, cfg->line_outs);
+ cfg->line_out_pins[cfg->line_outs] = nid;
+ cfg->line_outs++;
+ spec->mic_switch = nid;
+ add_spec_dacs(spec, dac);
+ }
+ }
+ for (i = 0; i < cfg->hp_outs; i++) {
+ nid = cfg->hp_pins[i];
+ dac = get_unassigned_dac(codec, nid);
+ if (dac) {
+ if (!spec->multiout.hp_nid)
+ spec->multiout.hp_nid = dac;
+ else
+ add_spec_extra_dacs(spec, dac);
}
+ spec->hp_dacs[i] = dac;
+ }
+
+ for (i = 0; i < cfg->speaker_outs; i++) {
+ nid = cfg->speaker_pins[i];
+ dac = get_unassigned_dac(codec, nid);
+ if (dac)
+ add_spec_extra_dacs(spec, dac);
+ spec->speaker_dacs[i] = dac;
}
- snd_printd("dac_nids=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
+ snd_printd("stac92xx: dac_nids=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
spec->multiout.num_dacs,
spec->multiout.dac_nids[0],
spec->multiout.dac_nids[1],
spec->multiout.dac_nids[2],
spec->multiout.dac_nids[3],
spec->multiout.dac_nids[4]);
+
return 0;
}
@@ -2787,9 +2931,7 @@ static int create_controls(struct sigmatel_spec *spec, const char *pfx, hda_nid_
static int add_spec_dacs(struct sigmatel_spec *spec, hda_nid_t nid)
{
- if (!spec->multiout.hp_nid)
- spec->multiout.hp_nid = nid;
- else if (spec->multiout.num_dacs > 4) {
+ if (spec->multiout.num_dacs > 4) {
printk(KERN_WARNING "stac92xx: No space for DAC 0x%x\n", nid);
return 1;
} else {
@@ -2799,35 +2941,47 @@ static int add_spec_dacs(struct sigmatel_spec *spec, hda_nid_t nid)
return 0;
}
-static int check_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid)
+static int add_spec_extra_dacs(struct sigmatel_spec *spec, hda_nid_t nid)
{
- if (is_in_dac_nids(spec, nid))
- return 1;
+ int i;
+ for (i = 0; i < ARRAY_SIZE(spec->multiout.extra_out_nid); i++) {
+ if (!spec->multiout.extra_out_nid[i]) {
+ spec->multiout.extra_out_nid[i] = nid;
+ return 0;
+ }
+ }
+ printk(KERN_WARNING "stac92xx: No space for extra DAC 0x%x\n", nid);
+ return 1;
+}
+
+static int is_unique_dac(struct sigmatel_spec *spec, hda_nid_t nid)
+{
+ int i;
+
+ if (spec->autocfg.line_outs != 1)
+ return 0;
if (spec->multiout.hp_nid == nid)
- return 1;
- return 0;
+ return 0;
+ for (i = 0; i < ARRAY_SIZE(spec->multiout.extra_out_nid); i++)
+ if (spec->multiout.extra_out_nid[i] == nid)
+ return 0;
+ return 1;
}
/* add playback controls from the parsed DAC table */
static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
const struct auto_pin_cfg *cfg)
{
+ struct sigmatel_spec *spec = codec->spec;
static const char *chname[4] = {
"Front", "Surround", NULL /*CLFE*/, "Side"
};
hda_nid_t nid = 0;
int i, err;
+ unsigned int wid_caps;
- struct sigmatel_spec *spec = codec->spec;
- unsigned int wid_caps, pincap;
-
-
- for (i = 0; i < cfg->line_outs && i < spec->multiout.num_dacs; i++) {
- if (!spec->multiout.dac_nids[i])
- continue;
-
+ for (i = 0; i < cfg->line_outs && spec->multiout.dac_nids[i]; i++) {
nid = spec->multiout.dac_nids[i];
-
if (i == 2) {
/* Center/LFE */
err = create_controls(spec, "Center", nid, 1);
@@ -2849,64 +3003,47 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
}
} else {
- err = create_controls(spec, chname[i], nid, 3);
+ const char *name = chname[i];
+ /* if it's a single DAC, assign a better name */
+ if (!i && is_unique_dac(spec, nid)) {
+ switch (cfg->line_out_type) {
+ case AUTO_PIN_HP_OUT:
+ name = "Headphone";
+ break;
+ case AUTO_PIN_SPEAKER_OUT:
+ name = "Speaker";
+ break;
+ }
+ }
+ err = create_controls(spec, name, nid, 3);
if (err < 0)
return err;
}
}
- if ((spec->multiout.num_dacs - cfg->line_outs) > 0 &&
- cfg->hp_outs && !spec->multiout.hp_nid)
- spec->multiout.hp_nid = nid;
-
- if (cfg->hp_outs > 1) {
+ if (cfg->hp_outs > 1 && cfg->line_out_type == AUTO_PIN_LINE_OUT) {
err = stac92xx_add_control(spec,
STAC_CTL_WIDGET_HP_SWITCH,
- "Headphone as Line Out Switch", 0);
+ "Headphone as Line Out Switch",
+ cfg->hp_pins[cfg->hp_outs - 1]);
if (err < 0)
return err;
}
if (spec->line_switch) {
- nid = cfg->input_pins[AUTO_PIN_LINE];
- pincap = snd_hda_param_read(codec, nid,
- AC_PAR_PIN_CAP);
- if (pincap & AC_PINCAP_OUT) {
- err = stac92xx_add_control(spec,
- STAC_CTL_WIDGET_IO_SWITCH,
- "Line In as Output Switch", nid << 8);
- if (err < 0)
- return err;
- }
+ err = stac92xx_add_control(spec, STAC_CTL_WIDGET_IO_SWITCH,
+ "Line In as Output Switch",
+ spec->line_switch << 8);
+ if (err < 0)
+ return err;
}
if (spec->mic_switch) {
- unsigned int def_conf;
- unsigned int mic_pin = AUTO_PIN_MIC;
-again:
- nid = cfg->input_pins[mic_pin];
- def_conf = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_CONFIG_DEFAULT, 0);
- /* some laptops have an internal analog microphone
- * which can't be used as a output */
- if (get_defcfg_connect(def_conf) != AC_JACK_PORT_FIXED) {
- pincap = snd_hda_param_read(codec, nid,
- AC_PAR_PIN_CAP);
- if (pincap & AC_PINCAP_OUT) {
- err = stac92xx_add_control(spec,
- STAC_CTL_WIDGET_IO_SWITCH,
- "Mic as Output Switch", (nid << 8) | 1);
- nid = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_CONNECT_LIST, 0) & 0xff;
- if (!check_in_dac_nids(spec, nid))
- add_spec_dacs(spec, nid);
- if (err < 0)
- return err;
- }
- } else if (mic_pin == AUTO_PIN_MIC) {
- mic_pin = AUTO_PIN_FRONT_MIC;
- goto again;
- }
+ err = stac92xx_add_control(spec, STAC_CTL_WIDGET_IO_SWITCH,
+ "Mic as Output Switch",
+ (spec->mic_switch << 8) | 1);
+ if (err < 0)
+ return err;
}
return 0;
@@ -2918,55 +3055,39 @@ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec,
{
struct sigmatel_spec *spec = codec->spec;
hda_nid_t nid;
- int i, old_num_dacs, err;
+ int i, err, nums;
- old_num_dacs = spec->multiout.num_dacs;
+ nums = 0;
for (i = 0; i < cfg->hp_outs; i++) {
+ static const char *pfxs[] = {
+ "Headphone", "Headphone2", "Headphone3",
+ };
unsigned int wid_caps = get_wcaps(codec, cfg->hp_pins[i]);
if (wid_caps & AC_WCAP_UNSOL_CAP)
spec->hp_detect = 1;
- nid = snd_hda_codec_read(codec, cfg->hp_pins[i], 0,
- AC_VERB_GET_CONNECT_LIST, 0) & 0xff;
- if (check_in_dac_nids(spec, nid))
- nid = 0;
- if (! nid)
+ if (nums >= ARRAY_SIZE(pfxs))
continue;
- add_spec_dacs(spec, nid);
- }
- for (i = 0; i < cfg->speaker_outs; i++) {
- nid = snd_hda_codec_read(codec, cfg->speaker_pins[i], 0,
- AC_VERB_GET_CONNECT_LIST, 0) & 0xff;
- if (check_in_dac_nids(spec, nid))
- nid = 0;
- if (! nid)
+ nid = spec->hp_dacs[i];
+ if (!nid)
continue;
- add_spec_dacs(spec, nid);
- }
- for (i = 0; i < cfg->line_outs; i++) {
- nid = snd_hda_codec_read(codec, cfg->line_out_pins[i], 0,
- AC_VERB_GET_CONNECT_LIST, 0) & 0xff;
- if (check_in_dac_nids(spec, nid))
- nid = 0;
- if (! nid)
- continue;
- add_spec_dacs(spec, nid);
+ err = create_controls(spec, pfxs[nums++], nid, 3);
+ if (err < 0)
+ return err;
}
- for (i = old_num_dacs; i < spec->multiout.num_dacs; i++) {
+ nums = 0;
+ for (i = 0; i < cfg->speaker_outs; i++) {
static const char *pfxs[] = {
"Speaker", "External Speaker", "Speaker2",
};
- err = create_controls(spec, pfxs[i - old_num_dacs],
- spec->multiout.dac_nids[i], 3);
- if (err < 0)
- return err;
- }
- if (spec->multiout.hp_nid) {
- err = create_controls(spec, "Headphone",
- spec->multiout.hp_nid, 3);
+ if (nums >= ARRAY_SIZE(pfxs))
+ continue;
+ nid = spec->speaker_dacs[i];
+ if (!nid)
+ continue;
+ err = create_controls(spec, pfxs[nums++], nid, 3);
if (err < 0)
return err;
}
-
return 0;
}
@@ -3060,6 +3181,43 @@ static int stac92xx_auto_create_beep_ctls(struct hda_codec *codec,
return 0;
}
+#ifdef CONFIG_SND_HDA_INPUT_BEEP
+#define stac92xx_dig_beep_switch_info snd_ctl_boolean_mono_info
+
+static int stac92xx_dig_beep_switch_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ ucontrol->value.integer.value[0] = codec->beep->enabled;
+ return 0;
+}
+
+static int stac92xx_dig_beep_switch_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ int enabled = !!ucontrol->value.integer.value[0];
+ if (codec->beep->enabled != enabled) {
+ codec->beep->enabled = enabled;
+ return 1;
+ }
+ return 0;
+}
+
+static struct snd_kcontrol_new stac92xx_dig_beep_ctrl = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .info = stac92xx_dig_beep_switch_info,
+ .get = stac92xx_dig_beep_switch_get,
+ .put = stac92xx_dig_beep_switch_put,
+};
+
+static int stac92xx_beep_switch_ctl(struct hda_codec *codec)
+{
+ return stac92xx_add_control_temp(codec->spec, &stac92xx_dig_beep_ctrl,
+ 0, "PC Beep Playback Switch", 0);
+}
+#endif
+
static int stac92xx_auto_create_mux_input_ctls(struct hda_codec *codec)
{
struct sigmatel_spec *spec = codec->spec;
@@ -3267,7 +3425,6 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out
{
struct sigmatel_spec *spec = codec->spec;
int err;
- int hp_speaker_swap = 0;
if ((err = snd_hda_parse_pin_def_config(codec,
&spec->autocfg,
@@ -3285,13 +3442,15 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out
* speaker_outs so that the following routines can handle
* HP pins as primary outputs.
*/
+ snd_printdd("stac92xx: Enabling multi-HPs workaround\n");
memcpy(spec->autocfg.speaker_pins, spec->autocfg.line_out_pins,
sizeof(spec->autocfg.line_out_pins));
spec->autocfg.speaker_outs = spec->autocfg.line_outs;
memcpy(spec->autocfg.line_out_pins, spec->autocfg.hp_pins,
sizeof(spec->autocfg.hp_pins));
spec->autocfg.line_outs = spec->autocfg.hp_outs;
- hp_speaker_swap = 1;
+ spec->autocfg.line_out_type = AUTO_PIN_HP_OUT;
+ spec->autocfg.hp_outs = 0;
}
if (spec->autocfg.mono_out_pin) {
int dir = get_wcaps(codec, spec->autocfg.mono_out_pin) &
@@ -3343,11 +3502,11 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out
AC_PINCTL_OUT_EN);
}
- if ((err = stac92xx_add_dyn_out_pins(codec, &spec->autocfg)) < 0)
- return err;
- if (spec->multiout.num_dacs == 0)
- if ((err = stac92xx_auto_fill_dac_nids(codec, &spec->autocfg)) < 0)
+ if (!spec->multiout.num_dacs) {
+ err = stac92xx_auto_fill_dac_nids(codec);
+ if (err < 0)
return err;
+ }
err = stac92xx_auto_create_multi_out_ctls(codec, &spec->autocfg);
@@ -3366,6 +3525,7 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out
#ifdef CONFIG_SND_HDA_INPUT_BEEP
if (spec->digbeep_nid > 0) {
hda_nid_t nid = spec->digbeep_nid;
+ unsigned int caps;
err = stac92xx_auto_create_beep_ctls(codec, nid);
if (err < 0)
@@ -3373,22 +3533,17 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out
err = snd_hda_attach_beep_device(codec, nid);
if (err < 0)
return err;
+ /* if no beep switch is available, make its own one */
+ caps = query_amp_caps(codec, nid, HDA_OUTPUT);
+ if (codec->beep &&
+ !((caps & AC_AMPCAP_MUTE) >> AC_AMPCAP_MUTE_SHIFT)) {
+ err = stac92xx_beep_switch_ctl(codec);
+ if (err < 0)
+ return err;
+ }
}
#endif
- if (hp_speaker_swap == 1) {
- /* Restore the hp_outs and line_outs */
- memcpy(spec->autocfg.hp_pins, spec->autocfg.line_out_pins,
- sizeof(spec->autocfg.line_out_pins));
- spec->autocfg.hp_outs = spec->autocfg.line_outs;
- memcpy(spec->autocfg.line_out_pins, spec->autocfg.speaker_pins,
- sizeof(spec->autocfg.speaker_pins));
- spec->autocfg.line_outs = spec->autocfg.speaker_outs;
- memset(spec->autocfg.speaker_pins, 0,
- sizeof(spec->autocfg.speaker_pins));
- spec->autocfg.speaker_outs = 0;
- }
-
err = stac92xx_auto_create_hp_ctls(codec, &spec->autocfg);
if (err < 0)
@@ -3433,11 +3588,12 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out
if (dig_in && spec->autocfg.dig_in_pin)
spec->dig_in_nid = dig_in;
- if (spec->kctl_alloc)
- spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
+ if (spec->kctls.list)
+ spec->mixers[spec->num_mixers++] = spec->kctls.list;
spec->input_mux = &spec->private_imux;
- spec->dinput_mux = &spec->private_dimux;
+ if (!spec->dinput_mux)
+ spec->dinput_mux = &spec->private_dimux;
spec->sinput_mux = &spec->private_smux;
spec->mono_mux = &spec->private_mono_mux;
spec->amp_mux = &spec->private_amp_mux;
@@ -3530,13 +3686,19 @@ static int stac9200_parse_auto_config(struct hda_codec *codec)
if ((err = stac9200_auto_create_lfe_ctls(codec, &spec->autocfg)) < 0)
return err;
+ if (spec->num_muxes > 0) {
+ err = stac92xx_auto_create_mux_input_ctls(codec);
+ if (err < 0)
+ return err;
+ }
+
if (spec->autocfg.dig_out_pin)
spec->multiout.dig_out_nid = 0x05;
if (spec->autocfg.dig_in_pin)
spec->dig_in_nid = 0x04;
- if (spec->kctl_alloc)
- spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
+ if (spec->kctls.list)
+ spec->mixers[spec->num_mixers++] = spec->kctls.list;
spec->input_mux = &spec->private_imux;
spec->dinput_mux = &spec->private_dimux;
@@ -3580,13 +3742,101 @@ static void stac_gpio_set(struct hda_codec *codec, unsigned int mask,
AC_VERB_SET_GPIO_DATA, gpiostate); /* sync */
}
+static int stac92xx_add_jack(struct hda_codec *codec,
+ hda_nid_t nid, int type)
+{
+#ifdef CONFIG_SND_JACK
+ struct sigmatel_spec *spec = codec->spec;
+ struct sigmatel_jack *jack;
+ int def_conf = snd_hda_codec_read(codec, nid,
+ 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
+ int connectivity = get_defcfg_connect(def_conf);
+ char name[32];
+
+ if (connectivity && connectivity != AC_JACK_PORT_FIXED)
+ return 0;
+
+ snd_array_init(&spec->jacks, sizeof(*jack), 32);
+ jack = snd_array_new(&spec->jacks);
+ if (!jack)
+ return -ENOMEM;
+ jack->nid = nid;
+ jack->type = type;
+
+ sprintf(name, "%s at %s %s Jack",
+ snd_hda_get_jack_type(def_conf),
+ snd_hda_get_jack_connectivity(def_conf),
+ snd_hda_get_jack_location(def_conf));
+
+ return snd_jack_new(codec->bus->card, name, type, &jack->jack);
+#else
+ return 0;
+#endif
+}
+
+static int stac_add_event(struct sigmatel_spec *spec, hda_nid_t nid,
+ unsigned char type, int data)
+{
+ struct sigmatel_event *event;
+
+ snd_array_init(&spec->events, sizeof(*event), 32);
+ event = snd_array_new(&spec->events);
+ if (!event)
+ return -ENOMEM;
+ event->nid = nid;
+ event->type = type;
+ event->tag = spec->events.used;
+ event->data = data;
+
+ return event->tag;
+}
+
+static struct sigmatel_event *stac_get_event(struct hda_codec *codec,
+ hda_nid_t nid, unsigned char type)
+{
+ struct sigmatel_spec *spec = codec->spec;
+ struct sigmatel_event *event = spec->events.list;
+ int i;
+
+ for (i = 0; i < spec->events.used; i++, event++) {
+ if (event->nid == nid && event->type == type)
+ return event;
+ }
+ return NULL;
+}
+
+static struct sigmatel_event *stac_get_event_from_tag(struct hda_codec *codec,
+ unsigned char tag)
+{
+ struct sigmatel_spec *spec = codec->spec;
+ struct sigmatel_event *event = spec->events.list;
+ int i;
+
+ for (i = 0; i < spec->events.used; i++, event++) {
+ if (event->tag == tag)
+ return event;
+ }
+ return NULL;
+}
+
static void enable_pin_detect(struct hda_codec *codec, hda_nid_t nid,
- unsigned int event)
+ unsigned int type)
{
- if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP)
- snd_hda_codec_write_cache(codec, nid, 0,
- AC_VERB_SET_UNSOLICITED_ENABLE,
- (AC_USRSP_EN | event));
+ struct sigmatel_event *event;
+ int tag;
+
+ if (!(get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP))
+ return;
+ event = stac_get_event(codec, nid, type);
+ if (event)
+ tag = event->tag;
+ else
+ tag = stac_add_event(codec->spec, nid, type, 0);
+ if (tag < 0)
+ return;
+ snd_hda_codec_write_cache(codec, nid, 0,
+ AC_VERB_SET_UNSOLICITED_ENABLE,
+ AC_USRSP_EN | tag);
}
static int is_nid_hp_pin(struct auto_pin_cfg *cfg, hda_nid_t nid)
@@ -3606,16 +3856,19 @@ static void stac92xx_power_down(struct hda_codec *codec)
/* power down inactive DACs */
hda_nid_t *dac;
for (dac = spec->dac_list; *dac; dac++)
- if (!is_in_dac_nids(spec, *dac) &&
- spec->multiout.hp_nid != *dac)
- snd_hda_codec_write_cache(codec, *dac, 0,
+ if (!check_all_dac_nids(spec, *dac))
+ snd_hda_codec_write(codec, *dac, 0,
AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
}
+static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid,
+ int enable);
+
static int stac92xx_init(struct hda_codec *codec)
{
struct sigmatel_spec *spec = codec->spec;
struct auto_pin_cfg *cfg = &spec->autocfg;
+ unsigned int gpio;
int i;
snd_hda_sequence_write(codec, spec->init);
@@ -3623,96 +3876,159 @@ static int stac92xx_init(struct hda_codec *codec)
/* power down adcs initially */
if (spec->powerdown_adcs)
for (i = 0; i < spec->num_adcs; i++)
- snd_hda_codec_write_cache(codec,
+ snd_hda_codec_write(codec,
spec->adc_nids[i], 0,
AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+
+ /* set up GPIO */
+ gpio = spec->gpio_data;
+ /* turn on EAPD statically when spec->eapd_switch isn't set.
+ * otherwise, unsol event will turn it on/off dynamically
+ */
+ if (!spec->eapd_switch)
+ gpio |= spec->eapd_mask;
+ stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, gpio);
+
/* set up pins */
if (spec->hp_detect) {
/* Enable unsolicited responses on the HP widget */
- for (i = 0; i < cfg->hp_outs; i++)
- enable_pin_detect(codec, cfg->hp_pins[i],
- STAC_HP_EVENT);
+ for (i = 0; i < cfg->hp_outs; i++) {
+ hda_nid_t nid = cfg->hp_pins[i];
+ enable_pin_detect(codec, nid, STAC_HP_EVENT);
+ }
/* force to enable the first line-out; the others are set up
* in unsol_event
*/
stac92xx_auto_set_pinctl(codec, spec->autocfg.line_out_pins[0],
- AC_PINCTL_OUT_EN);
- stac92xx_auto_init_hp_out(codec);
+ AC_PINCTL_OUT_EN);
/* fake event to set up pins */
- codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26);
+ stac_issue_unsol_event(codec, spec->autocfg.hp_pins[0],
+ STAC_HP_EVENT);
} else {
stac92xx_auto_init_multi_out(codec);
stac92xx_auto_init_hp_out(codec);
+ for (i = 0; i < cfg->hp_outs; i++)
+ stac_toggle_power_map(codec, cfg->hp_pins[i], 1);
}
for (i = 0; i < AUTO_PIN_LAST; i++) {
hda_nid_t nid = cfg->input_pins[i];
if (nid) {
- unsigned int pinctl = snd_hda_codec_read(codec, nid,
- 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
- /* if PINCTL already set then skip */
- if (pinctl & AC_PINCAP_IN)
- continue;
- pinctl = AC_PINCTL_IN_EN;
- if (i == AUTO_PIN_MIC || i == AUTO_PIN_FRONT_MIC)
- pinctl |= stac92xx_get_vref(codec, nid);
- stac92xx_auto_set_pinctl(codec, nid, pinctl);
+ unsigned int pinctl, conf;
+ if (i == AUTO_PIN_MIC || i == AUTO_PIN_FRONT_MIC) {
+ /* for mic pins, force to initialize */
+ pinctl = stac92xx_get_vref(codec, nid);
+ pinctl |= AC_PINCTL_IN_EN;
+ stac92xx_auto_set_pinctl(codec, nid, pinctl);
+ } else {
+ pinctl = snd_hda_codec_read(codec, nid, 0,
+ AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+ /* if PINCTL already set then skip */
+ if (!(pinctl & AC_PINCTL_IN_EN)) {
+ pinctl |= AC_PINCTL_IN_EN;
+ stac92xx_auto_set_pinctl(codec, nid,
+ pinctl);
+ }
+ }
+ conf = snd_hda_codec_read(codec, nid, 0,
+ AC_VERB_GET_CONFIG_DEFAULT, 0);
+ if (get_defcfg_connect(conf) != AC_JACK_PORT_FIXED) {
+ enable_pin_detect(codec, nid,
+ STAC_INSERT_EVENT);
+ stac_issue_unsol_event(codec, nid,
+ STAC_INSERT_EVENT);
+ }
}
}
for (i = 0; i < spec->num_dmics; i++)
stac92xx_auto_set_pinctl(codec, spec->dmic_nids[i],
AC_PINCTL_IN_EN);
+ if (cfg->dig_out_pin)
+ stac92xx_auto_set_pinctl(codec, cfg->dig_out_pin,
+ AC_PINCTL_OUT_EN);
+ if (cfg->dig_in_pin)
+ stac92xx_auto_set_pinctl(codec, cfg->dig_in_pin,
+ AC_PINCTL_IN_EN);
for (i = 0; i < spec->num_pwrs; i++) {
- int event = is_nid_hp_pin(cfg, spec->pwr_nids[i])
- ? STAC_HP_EVENT : STAC_PWR_EVENT;
- int pinctl = snd_hda_codec_read(codec, spec->pwr_nids[i],
- 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
- int def_conf = snd_hda_codec_read(codec, spec->pwr_nids[i],
- 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
- def_conf = get_defcfg_connect(def_conf);
+ hda_nid_t nid = spec->pwr_nids[i];
+ int pinctl, def_conf;
+
+ /* power on when no jack detection is available */
+ if (!spec->hp_detect) {
+ stac_toggle_power_map(codec, nid, 1);
+ continue;
+ }
+
+ if (is_nid_hp_pin(cfg, nid))
+ continue; /* already has an unsol event */
+
+ pinctl = snd_hda_codec_read(codec, nid, 0,
+ AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
/* outputs are only ports capable of power management
* any attempts on powering down a input port cause the
* referenced VREF to act quirky.
*/
- if (pinctl & AC_PINCTL_IN_EN)
+ if (pinctl & AC_PINCTL_IN_EN) {
+ stac_toggle_power_map(codec, nid, 1);
continue;
+ }
+ def_conf = snd_hda_codec_read(codec, nid, 0,
+ AC_VERB_GET_CONFIG_DEFAULT, 0);
+ def_conf = get_defcfg_connect(def_conf);
/* skip any ports that don't have jacks since presence
* detection is useless */
- if (def_conf && def_conf != AC_JACK_PORT_FIXED)
+ if (def_conf != AC_JACK_PORT_COMPLEX) {
+ if (def_conf != AC_JACK_PORT_NONE)
+ stac_toggle_power_map(codec, nid, 1);
continue;
- enable_pin_detect(codec, spec->pwr_nids[i], event | i);
- codec->patch_ops.unsol_event(codec, (event | i) << 26);
+ }
+ if (!stac_get_event(codec, nid, STAC_INSERT_EVENT)) {
+ enable_pin_detect(codec, nid, STAC_PWR_EVENT);
+ stac_issue_unsol_event(codec, nid, STAC_PWR_EVENT);
+ }
}
if (spec->dac_list)
stac92xx_power_down(codec);
- if (cfg->dig_out_pin)
- stac92xx_auto_set_pinctl(codec, cfg->dig_out_pin,
- AC_PINCTL_OUT_EN);
- if (cfg->dig_in_pin)
- stac92xx_auto_set_pinctl(codec, cfg->dig_in_pin,
- AC_PINCTL_IN_EN);
+ return 0;
+}
- stac_gpio_set(codec, spec->gpio_mask,
- spec->gpio_dir, spec->gpio_data);
+static void stac92xx_free_jacks(struct hda_codec *codec)
+{
+#ifdef CONFIG_SND_JACK
+ /* free jack instances manually when clearing/reconfiguring */
+ struct sigmatel_spec *spec = codec->spec;
+ if (!codec->bus->shutdown && spec->jacks.list) {
+ struct sigmatel_jack *jacks = spec->jacks.list;
+ int i;
+ for (i = 0; i < spec->jacks.used; i++)
+ snd_device_free(codec->bus->card, &jacks[i].jack);
+ }
+ snd_array_free(&spec->jacks);
+#endif
+}
- return 0;
+static void stac92xx_free_kctls(struct hda_codec *codec)
+{
+ struct sigmatel_spec *spec = codec->spec;
+
+ if (spec->kctls.list) {
+ struct snd_kcontrol_new *kctl = spec->kctls.list;
+ int i;
+ for (i = 0; i < spec->kctls.used; i++)
+ kfree(kctl[i].name);
+ }
+ snd_array_free(&spec->kctls);
}
static void stac92xx_free(struct hda_codec *codec)
{
struct sigmatel_spec *spec = codec->spec;
- int i;
if (! spec)
return;
- if (spec->kctl_alloc) {
- for (i = 0; i < spec->num_kctl_used; i++)
- kfree(spec->kctl_alloc[i].name);
- kfree(spec->kctl_alloc);
- }
-
- if (spec->bios_pin_configs)
- kfree(spec->bios_pin_configs);
+ kfree(spec->pin_configs);
+ stac92xx_free_jacks(codec);
+ snd_array_free(&spec->events);
kfree(spec);
snd_hda_detach_beep_device(codec);
@@ -3731,11 +4047,7 @@ static void stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid,
* "xxx as Output" mixer switch
*/
struct sigmatel_spec *spec = codec->spec;
- struct auto_pin_cfg *cfg = &spec->autocfg;
- if ((nid == cfg->input_pins[AUTO_PIN_LINE] &&
- spec->line_switch) ||
- (nid == cfg->input_pins[AUTO_PIN_MIC] &&
- spec->mic_switch))
+ if (nid == spec->line_switch || nid == spec->mic_switch)
return;
}
@@ -3759,28 +4071,38 @@ static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid,
pin_ctl & ~flag);
}
-static int get_hp_pin_presence(struct hda_codec *codec, hda_nid_t nid)
+static int get_pin_presence(struct hda_codec *codec, hda_nid_t nid)
{
if (!nid)
return 0;
if (snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_SENSE, 0x00)
- & (1 << 31)) {
- unsigned int pinctl;
- pinctl = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
- if (pinctl & AC_PINCTL_IN_EN)
- return 0; /* mic- or line-input */
- else
- return 1; /* HP-output */
- }
+ & (1 << 31))
+ return 1;
+ return 0;
+}
+
+/* return non-zero if the hp-pin of the given array index isn't
+ * a jack-detection target
+ */
+static int no_hp_sensing(struct sigmatel_spec *spec, int i)
+{
+ struct auto_pin_cfg *cfg = &spec->autocfg;
+
+ /* ignore sensing of shared line and mic jacks */
+ if (cfg->hp_pins[i] == spec->line_switch)
+ return 1;
+ if (cfg->hp_pins[i] == spec->mic_switch)
+ return 1;
+ /* ignore if the pin is set as line-out */
+ if (cfg->hp_pins[i] == spec->hp_switch)
+ return 1;
return 0;
}
-static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res)
+static void stac92xx_hp_detect(struct hda_codec *codec)
{
struct sigmatel_spec *spec = codec->spec;
struct auto_pin_cfg *cfg = &spec->autocfg;
- int nid = cfg->hp_pins[cfg->hp_outs - 1];
int i, presence;
presence = 0;
@@ -3791,52 +4113,73 @@ static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res)
for (i = 0; i < cfg->hp_outs; i++) {
if (presence)
break;
- if (spec->hp_switch && cfg->hp_pins[i] == nid)
- break;
- presence = get_hp_pin_presence(codec, cfg->hp_pins[i]);
+ if (no_hp_sensing(spec, i))
+ continue;
+ presence = get_pin_presence(codec, cfg->hp_pins[i]);
+ if (presence) {
+ unsigned int pinctl;
+ pinctl = snd_hda_codec_read(codec, cfg->hp_pins[i], 0,
+ AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+ if (pinctl & AC_PINCTL_IN_EN)
+ presence = 0; /* mic- or line-input */
+ }
}
if (presence) {
- /* disable lineouts, enable hp */
+ /* disable lineouts */
if (spec->hp_switch)
- stac92xx_reset_pinctl(codec, nid, AC_PINCTL_OUT_EN);
+ stac92xx_reset_pinctl(codec, spec->hp_switch,
+ AC_PINCTL_OUT_EN);
for (i = 0; i < cfg->line_outs; i++)
stac92xx_reset_pinctl(codec, cfg->line_out_pins[i],
AC_PINCTL_OUT_EN);
for (i = 0; i < cfg->speaker_outs; i++)
stac92xx_reset_pinctl(codec, cfg->speaker_pins[i],
AC_PINCTL_OUT_EN);
- if (spec->eapd_mask)
+ if (spec->eapd_mask && spec->eapd_switch)
stac_gpio_set(codec, spec->gpio_mask,
spec->gpio_dir, spec->gpio_data &
~spec->eapd_mask);
} else {
- /* enable lineouts, disable hp */
+ /* enable lineouts */
if (spec->hp_switch)
- stac92xx_set_pinctl(codec, nid, AC_PINCTL_OUT_EN);
+ stac92xx_set_pinctl(codec, spec->hp_switch,
+ AC_PINCTL_OUT_EN);
for (i = 0; i < cfg->line_outs; i++)
stac92xx_set_pinctl(codec, cfg->line_out_pins[i],
AC_PINCTL_OUT_EN);
for (i = 0; i < cfg->speaker_outs; i++)
stac92xx_set_pinctl(codec, cfg->speaker_pins[i],
AC_PINCTL_OUT_EN);
- if (spec->eapd_mask)
+ if (spec->eapd_mask && spec->eapd_switch)
stac_gpio_set(codec, spec->gpio_mask,
spec->gpio_dir, spec->gpio_data |
spec->eapd_mask);
}
- if (!spec->hp_switch && cfg->hp_outs > 1 && presence)
- stac92xx_set_pinctl(codec, nid, AC_PINCTL_OUT_EN);
+ /* toggle hp outs */
+ for (i = 0; i < cfg->hp_outs; i++) {
+ unsigned int val = AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN;
+ if (no_hp_sensing(spec, i))
+ continue;
+ if (presence)
+ stac92xx_set_pinctl(codec, cfg->hp_pins[i], val);
+ else
+ stac92xx_reset_pinctl(codec, cfg->hp_pins[i], val);
+ }
}
-static void stac92xx_pin_sense(struct hda_codec *codec, int idx)
+static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid,
+ int enable)
{
struct sigmatel_spec *spec = codec->spec;
- hda_nid_t nid = spec->pwr_nids[idx];
- int presence, val;
- val = snd_hda_codec_read(codec, codec->afg, 0, 0x0fec, 0x0)
- & 0x000000ff;
- presence = get_hp_pin_presence(codec, nid);
+ unsigned int idx, val;
+
+ for (idx = 0; idx < spec->num_pwrs; idx++) {
+ if (spec->pwr_nids[idx] == nid)
+ break;
+ }
+ if (idx >= spec->num_pwrs)
+ return;
/* several codecs have two power down bits */
if (spec->pwr_mapping)
@@ -3844,56 +4187,157 @@ static void stac92xx_pin_sense(struct hda_codec *codec, int idx)
else
idx = 1 << idx;
- if (presence)
+ val = snd_hda_codec_read(codec, codec->afg, 0, 0x0fec, 0x0) & 0xff;
+ if (enable)
val &= ~idx;
else
val |= idx;
/* power down unused output ports */
snd_hda_codec_write(codec, codec->afg, 0, 0x7ec, val);
-};
+}
+
+static void stac92xx_pin_sense(struct hda_codec *codec, hda_nid_t nid)
+{
+ stac_toggle_power_map(codec, nid, get_pin_presence(codec, nid));
+}
+
+static void stac92xx_report_jack(struct hda_codec *codec, hda_nid_t nid)
+{
+ struct sigmatel_spec *spec = codec->spec;
+ struct sigmatel_jack *jacks = spec->jacks.list;
+
+ if (jacks) {
+ int i;
+ for (i = 0; i < spec->jacks.used; i++) {
+ if (jacks->nid == nid) {
+ unsigned int pin_ctl =
+ snd_hda_codec_read(codec, nid,
+ 0, AC_VERB_GET_PIN_WIDGET_CONTROL,
+ 0x00);
+ int type = jacks->type;
+ if (type == (SND_JACK_LINEOUT
+ | SND_JACK_HEADPHONE))
+ type = (pin_ctl & AC_PINCTL_HP_EN)
+ ? SND_JACK_HEADPHONE : SND_JACK_LINEOUT;
+ snd_jack_report(jacks->jack,
+ get_pin_presence(codec, nid)
+ ? type : 0);
+ }
+ jacks++;
+ }
+ }
+}
+
+static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid,
+ unsigned char type)
+{
+ struct sigmatel_event *event = stac_get_event(codec, nid, type);
+ if (!event)
+ return;
+ codec->patch_ops.unsol_event(codec, (unsigned)event->tag << 26);
+}
static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res)
{
struct sigmatel_spec *spec = codec->spec;
- int idx = res >> 26 & 0x0f;
+ struct sigmatel_event *event;
+ int tag, data;
+
+ tag = (res >> 26) & 0x7f;
+ event = stac_get_event_from_tag(codec, tag);
+ if (!event)
+ return;
- switch ((res >> 26) & 0x70) {
+ switch (event->type) {
case STAC_HP_EVENT:
- stac92xx_hp_detect(codec, res);
+ stac92xx_hp_detect(codec);
/* fallthru */
+ case STAC_INSERT_EVENT:
case STAC_PWR_EVENT:
if (spec->num_pwrs > 0)
- stac92xx_pin_sense(codec, idx);
+ stac92xx_pin_sense(codec, event->nid);
+ stac92xx_report_jack(codec, event->nid);
break;
- case STAC_VREF_EVENT: {
- int data = snd_hda_codec_read(codec, codec->afg, 0,
- AC_VERB_GET_GPIO_DATA, 0);
+ case STAC_VREF_EVENT:
+ data = snd_hda_codec_read(codec, codec->afg, 0,
+ AC_VERB_GET_GPIO_DATA, 0);
/* toggle VREF state based on GPIOx status */
snd_hda_codec_write(codec, codec->afg, 0, 0x7e0,
- !!(data & (1 << idx)));
+ !!(data & (1 << event->data)));
break;
- }
}
}
+#ifdef CONFIG_PROC_FS
+static void stac92hd_proc_hook(struct snd_info_buffer *buffer,
+ struct hda_codec *codec, hda_nid_t nid)
+{
+ if (nid == codec->afg)
+ snd_iprintf(buffer, "Power-Map: 0x%02x\n",
+ snd_hda_codec_read(codec, nid, 0, 0x0fec, 0x0));
+}
+
+static void analog_loop_proc_hook(struct snd_info_buffer *buffer,
+ struct hda_codec *codec,
+ unsigned int verb)
+{
+ snd_iprintf(buffer, "Analog Loopback: 0x%02x\n",
+ snd_hda_codec_read(codec, codec->afg, 0, verb, 0));
+}
+
+/* stac92hd71bxx, stac92hd73xx */
+static void stac92hd7x_proc_hook(struct snd_info_buffer *buffer,
+ struct hda_codec *codec, hda_nid_t nid)
+{
+ stac92hd_proc_hook(buffer, codec, nid);
+ if (nid == codec->afg)
+ analog_loop_proc_hook(buffer, codec, 0xfa0);
+}
+
+static void stac9205_proc_hook(struct snd_info_buffer *buffer,
+ struct hda_codec *codec, hda_nid_t nid)
+{
+ if (nid == codec->afg)
+ analog_loop_proc_hook(buffer, codec, 0xfe0);
+}
+
+static void stac927x_proc_hook(struct snd_info_buffer *buffer,
+ struct hda_codec *codec, hda_nid_t nid)
+{
+ if (nid == codec->afg)
+ analog_loop_proc_hook(buffer, codec, 0xfeb);
+}
+#else
+#define stac92hd_proc_hook NULL
+#define stac92hd7x_proc_hook NULL
+#define stac9205_proc_hook NULL
+#define stac927x_proc_hook NULL
+#endif
+
#ifdef SND_HDA_NEEDS_RESUME
static int stac92xx_resume(struct hda_codec *codec)
{
struct sigmatel_spec *spec = codec->spec;
stac92xx_set_config_regs(codec);
- snd_hda_sequence_write(codec, spec->init);
- stac_gpio_set(codec, spec->gpio_mask,
- spec->gpio_dir, spec->gpio_data);
+ stac92xx_init(codec);
snd_hda_codec_resume_amp(codec);
snd_hda_codec_resume_cache(codec);
- /* power down inactive DACs */
- if (spec->dac_list)
- stac92xx_power_down(codec);
- /* invoke unsolicited event to reset the HP state */
+ /* fake event to set up pins again to override cached values */
if (spec->hp_detect)
- codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26);
+ stac_issue_unsol_event(codec, spec->autocfg.hp_pins[0],
+ STAC_HP_EVENT);
+ return 0;
+}
+
+static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state)
+{
+ struct sigmatel_spec *spec = codec->spec;
+ if (spec->eapd_mask)
+ stac_gpio_set(codec, spec->gpio_mask,
+ spec->gpio_dir, spec->gpio_data &
+ ~spec->eapd_mask);
return 0;
}
#endif
@@ -3905,6 +4349,7 @@ static struct hda_codec_ops stac92xx_patch_ops = {
.free = stac92xx_free,
.unsol_event = stac92xx_unsol_event,
#ifdef SND_HDA_NEEDS_RESUME
+ .suspend = stac92xx_suspend,
.resume = stac92xx_resume,
#endif
};
@@ -3927,14 +4372,12 @@ static int patch_stac9200(struct hda_codec *codec)
if (spec->board_config < 0) {
snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9200, using BIOS defaults\n");
err = stac92xx_save_bios_config_regs(codec);
- if (err < 0) {
- stac92xx_free(codec);
- return err;
- }
- spec->pin_configs = spec->bios_pin_configs;
- } else {
- spec->pin_configs = stac9200_brd_tbl[spec->board_config];
- stac92xx_set_config_regs(codec);
+ } else
+ err = stac_save_pin_cfgs(codec,
+ stac9200_brd_tbl[spec->board_config]);
+ if (err < 0) {
+ stac92xx_free(codec);
+ return err;
}
spec->multiout.max_channels = 2;
@@ -3990,14 +4433,12 @@ static int patch_stac925x(struct hda_codec *codec)
snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC925x,"
"using BIOS defaults\n");
err = stac92xx_save_bios_config_regs(codec);
- if (err < 0) {
- stac92xx_free(codec);
- return err;
- }
- spec->pin_configs = spec->bios_pin_configs;
- } else if (stac925x_brd_tbl[spec->board_config] != NULL){
- spec->pin_configs = stac925x_brd_tbl[spec->board_config];
- stac92xx_set_config_regs(codec);
+ } else
+ err = stac_save_pin_cfgs(codec,
+ stac925x_brd_tbl[spec->board_config]);
+ if (err < 0) {
+ stac92xx_free(codec);
+ return err;
}
spec->multiout.max_channels = 2;
@@ -4061,6 +4502,7 @@ static int patch_stac92hd73xx(struct hda_codec *codec)
struct sigmatel_spec *spec;
hda_nid_t conn[STAC92HD73_DAC_COUNT + 2];
int err = 0;
+ int num_dacs;
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (spec == NULL)
@@ -4079,26 +4521,23 @@ again:
snd_printdd(KERN_INFO "hda_codec: Unknown model for"
" STAC92HD73XX, using BIOS defaults\n");
err = stac92xx_save_bios_config_regs(codec);
- if (err < 0) {
- stac92xx_free(codec);
- return err;
- }
- spec->pin_configs = spec->bios_pin_configs;
- } else {
- spec->pin_configs = stac92hd73xx_brd_tbl[spec->board_config];
- stac92xx_set_config_regs(codec);
+ } else
+ err = stac_save_pin_cfgs(codec,
+ stac92hd73xx_brd_tbl[spec->board_config]);
+ if (err < 0) {
+ stac92xx_free(codec);
+ return err;
}
- spec->multiout.num_dacs = snd_hda_get_connections(codec, 0x0a,
+ num_dacs = snd_hda_get_connections(codec, 0x0a,
conn, STAC92HD73_DAC_COUNT + 2) - 1;
- if (spec->multiout.num_dacs < 0) {
+ if (num_dacs < 3 || num_dacs > 5) {
printk(KERN_WARNING "hda_codec: Could not determine "
"number of channels defaulting to DAC count\n");
- spec->multiout.num_dacs = STAC92HD73_DAC_COUNT;
+ num_dacs = STAC92HD73_DAC_COUNT;
}
-
- switch (spec->multiout.num_dacs) {
+ switch (num_dacs) {
case 0x3: /* 6 Channel */
spec->mixer = stac92hd73xx_6ch_mixer;
spec->init = stac92hd73xx_6ch_core_init;
@@ -4110,9 +4549,9 @@ again:
case 0x5: /* 10 Channel */
spec->mixer = stac92hd73xx_10ch_mixer;
spec->init = stac92hd73xx_10ch_core_init;
- };
+ }
+ spec->multiout.dac_nids = spec->dac_nids;
- spec->multiout.dac_nids = stac92hd73xx_dac_nids;
spec->aloopback_mask = 0x01;
spec->aloopback_shift = 8;
@@ -4135,31 +4574,29 @@ again:
case STAC_DELL_EQ:
spec->init = dell_eq_core_init;
/* fallthru */
- case STAC_DELL_M6:
+ case STAC_DELL_M6_AMIC:
+ case STAC_DELL_M6_DMIC:
+ case STAC_DELL_M6_BOTH:
spec->num_smuxes = 0;
spec->mixer = &stac92hd73xx_6ch_mixer[DELL_M6_MIXER];
spec->amp_nids = &stac92hd73xx_amp_nids[DELL_M6_AMP];
+ spec->eapd_switch = 0;
spec->num_amps = 1;
- if (!spec->init)
+ if (spec->board_config != STAC_DELL_EQ)
spec->init = dell_m6_core_init;
- switch (codec->subsystem_id) {
- case 0x1028025e: /* Analog Mics */
- case 0x1028025f:
+ switch (spec->board_config) {
+ case STAC_DELL_M6_AMIC: /* Analog Mics */
stac92xx_set_config_reg(codec, 0x0b, 0x90A70170);
spec->num_dmics = 0;
spec->private_dimux.num_items = 1;
break;
- case 0x10280271: /* Digital Mics */
- case 0x10280272:
- case 0x10280254:
- case 0x10280255:
+ case STAC_DELL_M6_DMIC: /* Digital Mics */
stac92xx_set_config_reg(codec, 0x13, 0x90A60160);
spec->num_dmics = 1;
spec->private_dimux.num_items = 2;
break;
- case 0x10280256: /* Both */
- case 0x10280057:
+ case STAC_DELL_M6_BOTH: /* Both */
stac92xx_set_config_reg(codec, 0x0b, 0x90A70170);
stac92xx_set_config_reg(codec, 0x13, 0x90A60160);
spec->num_dmics = 1;
@@ -4170,6 +4607,7 @@ again:
default:
spec->num_dmics = STAC92HD73XX_NUM_DMICS;
spec->num_smuxes = ARRAY_SIZE(stac92hd73xx_smux_nids);
+ spec->eapd_switch = 1;
}
if (spec->board_config > STAC_92HD73XX_REF) {
/* GPIO0 High = Enable EAPD */
@@ -4198,8 +4636,13 @@ again:
return err;
}
+ if (spec->board_config == STAC_92HD73XX_NO_JD)
+ spec->hp_detect = 0;
+
codec->patch_ops = stac92xx_patch_ops;
+ codec->proc_widget_hook = stac92hd7x_proc_hook;
+
return 0;
}
@@ -4231,17 +4674,15 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
spec->pwr_nids = stac92hd83xxx_pwr_nids;
spec->pwr_mapping = stac92hd83xxx_pwr_mapping;
spec->num_pwrs = ARRAY_SIZE(stac92hd83xxx_pwr_nids);
- spec->multiout.dac_nids = stac92hd83xxx_dac_nids;
+ spec->multiout.dac_nids = spec->dac_nids;
spec->init = stac92hd83xxx_core_init;
switch (codec->vendor_id) {
case 0x111d7605:
- spec->multiout.num_dacs = STAC92HD81_DAC_COUNT;
break;
default:
spec->num_pwrs--;
spec->init++; /* switch to config #2 */
- spec->multiout.num_dacs = STAC92HD83_DAC_COUNT;
}
spec->mixer = stac92hd83xxx_mixer;
@@ -4260,14 +4701,12 @@ again:
snd_printdd(KERN_INFO "hda_codec: Unknown model for"
" STAC92HD83XXX, using BIOS defaults\n");
err = stac92xx_save_bios_config_regs(codec);
- if (err < 0) {
- stac92xx_free(codec);
- return err;
- }
- spec->pin_configs = spec->bios_pin_configs;
- } else {
- spec->pin_configs = stac92hd83xxx_brd_tbl[spec->board_config];
- stac92xx_set_config_regs(codec);
+ } else
+ err = stac_save_pin_cfgs(codec,
+ stac92hd83xxx_brd_tbl[spec->board_config]);
+ if (err < 0) {
+ stac92xx_free(codec);
+ return err;
}
err = stac92xx_parse_auto_config(codec, 0x1d, 0);
@@ -4288,50 +4727,10 @@ again:
codec->patch_ops = stac92xx_patch_ops;
- return 0;
-}
-
-#ifdef SND_HDA_NEEDS_RESUME
-static void stac92hd71xx_set_power_state(struct hda_codec *codec, int pwr)
-{
- struct sigmatel_spec *spec = codec->spec;
- int i;
- snd_hda_codec_write_cache(codec, codec->afg, 0,
- AC_VERB_SET_POWER_STATE, pwr);
+ codec->proc_widget_hook = stac92hd_proc_hook;
- msleep(1);
- for (i = 0; i < spec->num_adcs; i++) {
- snd_hda_codec_write_cache(codec,
- spec->adc_nids[i], 0,
- AC_VERB_SET_POWER_STATE, pwr);
- }
-};
-
-static int stac92hd71xx_resume(struct hda_codec *codec)
-{
- stac92hd71xx_set_power_state(codec, AC_PWRST_D0);
- return stac92xx_resume(codec);
-}
-
-static int stac92hd71xx_suspend(struct hda_codec *codec, pm_message_t state)
-{
- stac92hd71xx_set_power_state(codec, AC_PWRST_D3);
return 0;
-};
-
-#endif
-
-static struct hda_codec_ops stac92hd71bxx_patch_ops = {
- .build_controls = stac92xx_build_controls,
- .build_pcms = stac92xx_build_pcms,
- .init = stac92xx_init,
- .free = stac92xx_free,
- .unsol_event = stac92xx_unsol_event,
-#ifdef SND_HDA_NEEDS_RESUME
- .resume = stac92hd71xx_resume,
- .suspend = stac92hd71xx_suspend,
-#endif
-};
+}
static struct hda_input_mux stac92hd71bxx_dmux = {
.num_items = 4,
@@ -4368,14 +4767,19 @@ again:
snd_printdd(KERN_INFO "hda_codec: Unknown model for"
" STAC92HD71BXX, using BIOS defaults\n");
err = stac92xx_save_bios_config_regs(codec);
- if (err < 0) {
- stac92xx_free(codec);
- return err;
- }
- spec->pin_configs = spec->bios_pin_configs;
- } else {
- spec->pin_configs = stac92hd71bxx_brd_tbl[spec->board_config];
- stac92xx_set_config_regs(codec);
+ } else
+ err = stac_save_pin_cfgs(codec,
+ stac92hd71bxx_brd_tbl[spec->board_config]);
+ if (err < 0) {
+ stac92xx_free(codec);
+ return err;
+ }
+
+ if (spec->board_config > STAC_92HD71BXX_REF) {
+ /* GPIO0 = EAPD */
+ spec->gpio_mask = 0x01;
+ spec->gpio_dir = 0x01;
+ spec->gpio_data = 0x01;
}
switch (codec->vendor_id) {
@@ -4388,24 +4792,24 @@ again:
codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs;
break;
case 0x111d7608: /* 5 Port with Analog Mixer */
- switch (codec->subsystem_id) {
- case 0x103c361a:
+ switch (spec->board_config) {
+ case STAC_HP_M4:
/* Enable VREF power saving on GPIO1 detect */
- snd_hda_codec_write(codec, codec->afg, 0,
+ err = stac_add_event(spec, codec->afg,
+ STAC_VREF_EVENT, 0x02);
+ if (err < 0)
+ return err;
+ snd_hda_codec_write_cache(codec, codec->afg, 0,
AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x02);
snd_hda_codec_write_cache(codec, codec->afg, 0,
- AC_VERB_SET_UNSOLICITED_ENABLE,
- (AC_USRSP_EN | STAC_VREF_EVENT | 0x01));
+ AC_VERB_SET_UNSOLICITED_ENABLE,
+ AC_USRSP_EN | err);
spec->gpio_mask |= 0x02;
break;
}
if ((codec->revision_id & 0xf) == 0 ||
- (codec->revision_id & 0xf) == 1) {
-#ifdef SND_HDA_NEEDS_RESUME
- codec->patch_ops = stac92hd71bxx_patch_ops;
-#endif
+ (codec->revision_id & 0xf) == 1)
spec->stream_delay = 40; /* 40 milliseconds */
- }
/* no output amps */
spec->num_pwrs = 0;
@@ -4414,15 +4818,11 @@ again:
/* disable VSW */
spec->init = &stac92hd71bxx_analog_core_init[HD_DISABLE_PORTF];
- stac92xx_set_config_reg(codec, 0xf, 0x40f000f0);
+ stac_change_pin_config(codec, 0xf, 0x40f000f0);
break;
case 0x111d7603: /* 6 Port with Analog Mixer */
- if ((codec->revision_id & 0xf) == 1) {
-#ifdef SND_HDA_NEEDS_RESUME
- codec->patch_ops = stac92hd71bxx_patch_ops;
-#endif
+ if ((codec->revision_id & 0xf) == 1)
spec->stream_delay = 40; /* 40 milliseconds */
- }
/* no output amps */
spec->num_pwrs = 0;
@@ -4437,13 +4837,6 @@ again:
spec->aloopback_mask = 0x50;
spec->aloopback_shift = 0;
- if (spec->board_config > STAC_92HD71BXX_REF) {
- /* GPIO0 = EAPD */
- spec->gpio_mask = 0x01;
- spec->gpio_dir = 0x01;
- spec->gpio_data = 0x01;
- }
-
spec->powerdown_adcs = 1;
spec->digbeep_nid = 0x26;
spec->mux_nids = stac92hd71bxx_mux_nids;
@@ -4458,14 +4851,21 @@ again:
switch (spec->board_config) {
case STAC_HP_M4:
- spec->num_dmics = 0;
- spec->num_smuxes = 0;
- spec->num_dmuxes = 0;
-
/* enable internal microphone */
- stac92xx_set_config_reg(codec, 0x0e, 0x01813040);
+ stac_change_pin_config(codec, 0x0e, 0x01813040);
stac92xx_auto_set_pinctl(codec, 0x0e,
AC_PINCTL_IN_EN | AC_PINCTL_VREF_80);
+ /* fallthru */
+ case STAC_DELL_M4_2:
+ spec->num_dmics = 0;
+ spec->num_smuxes = 0;
+ spec->num_dmuxes = 0;
+ break;
+ case STAC_DELL_M4_1:
+ case STAC_DELL_M4_3:
+ spec->num_dmics = 1;
+ spec->num_smuxes = 0;
+ spec->num_dmuxes = 0;
break;
default:
spec->num_dmics = STAC92HD71BXX_NUM_DMICS;
@@ -4473,9 +4873,7 @@ again:
spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids);
};
- spec->multiout.num_dacs = 1;
- spec->multiout.hp_nid = 0x11;
- spec->multiout.dac_nids = stac92hd71bxx_dac_nids;
+ spec->multiout.dac_nids = spec->dac_nids;
if (spec->dinput_mux)
spec->private_dimux.num_items +=
spec->num_dmics -
@@ -4497,6 +4895,8 @@ again:
return err;
}
+ codec->proc_widget_hook = stac92hd7x_proc_hook;
+
return 0;
};
@@ -4558,14 +4958,12 @@ static int patch_stac922x(struct hda_codec *codec)
snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC922x, "
"using BIOS defaults\n");
err = stac92xx_save_bios_config_regs(codec);
- if (err < 0) {
- stac92xx_free(codec);
- return err;
- }
- spec->pin_configs = spec->bios_pin_configs;
- } else if (stac922x_brd_tbl[spec->board_config] != NULL) {
- spec->pin_configs = stac922x_brd_tbl[spec->board_config];
- stac92xx_set_config_regs(codec);
+ } else
+ err = stac_save_pin_cfgs(codec,
+ stac922x_brd_tbl[spec->board_config]);
+ if (err < 0) {
+ stac92xx_free(codec);
+ return err;
}
spec->adc_nids = stac922x_adc_nids;
@@ -4628,14 +5026,12 @@ static int patch_stac927x(struct hda_codec *codec)
snd_printdd(KERN_INFO "hda_codec: Unknown model for"
"STAC927x, using BIOS defaults\n");
err = stac92xx_save_bios_config_regs(codec);
- if (err < 0) {
- stac92xx_free(codec);
- return err;
- }
- spec->pin_configs = spec->bios_pin_configs;
- } else {
- spec->pin_configs = stac927x_brd_tbl[spec->board_config];
- stac92xx_set_config_regs(codec);
+ } else
+ err = stac_save_pin_cfgs(codec,
+ stac927x_brd_tbl[spec->board_config]);
+ if (err < 0) {
+ stac92xx_free(codec);
+ return err;
}
spec->digbeep_nid = 0x23;
@@ -4665,15 +5061,15 @@ static int patch_stac927x(struct hda_codec *codec)
case 0x10280209:
case 0x1028022e:
/* correct the device field to SPDIF out */
- stac92xx_set_config_reg(codec, 0x21, 0x01442070);
+ stac_change_pin_config(codec, 0x21, 0x01442070);
break;
};
/* configure the analog microphone on some laptops */
- stac92xx_set_config_reg(codec, 0x0c, 0x90a79130);
+ stac_change_pin_config(codec, 0x0c, 0x90a79130);
/* correct the front output jack as a hp out */
- stac92xx_set_config_reg(codec, 0x0f, 0x0227011f);
+ stac_change_pin_config(codec, 0x0f, 0x0227011f);
/* correct the front input jack as a mic */
- stac92xx_set_config_reg(codec, 0x0e, 0x02a79130);
+ stac_change_pin_config(codec, 0x0e, 0x02a79130);
/* fallthru */
case STAC_DELL_3ST:
/* GPIO2 High = Enable EAPD */
@@ -4702,6 +5098,7 @@ static int patch_stac927x(struct hda_codec *codec)
spec->num_pwrs = 0;
spec->aloopback_mask = 0x40;
spec->aloopback_shift = 0;
+ spec->eapd_switch = 1;
err = stac92xx_parse_auto_config(codec, 0x1e, 0x20);
if (!err) {
@@ -4720,6 +5117,8 @@ static int patch_stac927x(struct hda_codec *codec)
codec->patch_ops = stac92xx_patch_ops;
+ codec->proc_widget_hook = stac927x_proc_hook;
+
/*
* !!FIXME!!
* The STAC927x seem to require fairly long delays for certain
@@ -4732,6 +5131,10 @@ static int patch_stac927x(struct hda_codec *codec)
*/
codec->bus->needs_damn_long_delay = 1;
+ /* no jack detecion for ref-no-jd model */
+ if (spec->board_config == STAC_D965_REF_NO_JD)
+ spec->hp_detect = 0;
+
return 0;
}
@@ -4754,14 +5157,12 @@ static int patch_stac9205(struct hda_codec *codec)
if (spec->board_config < 0) {
snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9205, using BIOS defaults\n");
err = stac92xx_save_bios_config_regs(codec);
- if (err < 0) {
- stac92xx_free(codec);
- return err;
- }
- spec->pin_configs = spec->bios_pin_configs;
- } else {
- spec->pin_configs = stac9205_brd_tbl[spec->board_config];
- stac92xx_set_config_regs(codec);
+ } else
+ err = stac_save_pin_cfgs(codec,
+ stac9205_brd_tbl[spec->board_config]);
+ if (err < 0) {
+ stac92xx_free(codec);
+ return err;
}
spec->digbeep_nid = 0x23;
@@ -4782,20 +5183,24 @@ static int patch_stac9205(struct hda_codec *codec)
spec->aloopback_mask = 0x40;
spec->aloopback_shift = 0;
+ spec->eapd_switch = 1;
spec->multiout.dac_nids = spec->dac_nids;
switch (spec->board_config){
case STAC_9205_DELL_M43:
/* Enable SPDIF in/out */
- stac92xx_set_config_reg(codec, 0x1f, 0x01441030);
- stac92xx_set_config_reg(codec, 0x20, 0x1c410030);
+ stac_change_pin_config(codec, 0x1f, 0x01441030);
+ stac_change_pin_config(codec, 0x20, 0x1c410030);
/* Enable unsol response for GPIO4/Dock HP connection */
- snd_hda_codec_write(codec, codec->afg, 0,
+ err = stac_add_event(spec, codec->afg, STAC_VREF_EVENT, 0x01);
+ if (err < 0)
+ return err;
+ snd_hda_codec_write_cache(codec, codec->afg, 0,
AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x10);
snd_hda_codec_write_cache(codec, codec->afg, 0,
AC_VERB_SET_UNSOLICITED_ENABLE,
- (AC_USRSP_EN | STAC_HP_EVENT));
+ AC_USRSP_EN | err);
spec->gpio_dir = 0x0b;
spec->eapd_mask = 0x01;
@@ -4833,6 +5238,8 @@ static int patch_stac9205(struct hda_codec *codec)
codec->patch_ops = stac92xx_patch_ops;
+ codec->proc_widget_hook = stac9205_proc_hook;
+
return 0;
}
@@ -4889,29 +5296,11 @@ static struct hda_verb vaio_ar_init[] = {
{}
};
-/* bind volumes of both NID 0x02 and 0x05 */
-static struct hda_bind_ctls vaio_bind_master_vol = {
- .ops = &snd_hda_bind_vol,
- .values = {
- HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
- HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT),
- 0
- },
-};
-
-/* bind volumes of both NID 0x02 and 0x05 */
-static struct hda_bind_ctls vaio_bind_master_sw = {
- .ops = &snd_hda_bind_sw,
- .values = {
- HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
- HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT),
- 0,
- },
-};
-
static struct snd_kcontrol_new vaio_mixer[] = {
- HDA_BIND_VOL("Master Playback Volume", &vaio_bind_master_vol),
- HDA_BIND_SW("Master Playback Switch", &vaio_bind_master_sw),
+ HDA_CODEC_VOLUME("Headphone Playback Volume", 0x02, 0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Headphone Playback Switch", 0x02, 0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Speaker Playback Volume", 0x05, 0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Speaker Playback Switch", 0x05, 0, HDA_OUTPUT),
/* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */
HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT),
HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT),
@@ -4927,8 +5316,10 @@ static struct snd_kcontrol_new vaio_mixer[] = {
};
static struct snd_kcontrol_new vaio_ar_mixer[] = {
- HDA_BIND_VOL("Master Playback Volume", &vaio_bind_master_vol),
- HDA_BIND_SW("Master Playback Switch", &vaio_bind_master_sw),
+ HDA_CODEC_VOLUME("Headphone Playback Volume", 0x02, 0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Headphone Playback Switch", 0x02, 0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Speaker Playback Volume", 0x05, 0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Speaker Playback Switch", 0x05, 0, HDA_OUTPUT),
/* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */
HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT),
HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT),
@@ -4969,7 +5360,7 @@ static int stac9872_vaio_init(struct hda_codec *codec)
static void stac9872_vaio_hp_detect(struct hda_codec *codec, unsigned int res)
{
- if (get_hp_pin_presence(codec, 0x0a)) {
+ if (get_pin_presence(codec, 0x0a)) {
stac92xx_reset_pinctl(codec, 0x0f, AC_PINCTL_OUT_EN);
stac92xx_set_pinctl(codec, 0x0a, AC_PINCTL_OUT_EN);
} else {
@@ -5080,7 +5471,7 @@ static int patch_stac9872(struct hda_codec *codec)
/*
* patch entries
*/
-struct hda_codec_preset snd_hda_preset_sigmatel[] = {
+static struct hda_codec_preset snd_hda_preset_sigmatel[] = {
{ .id = 0x83847690, .name = "STAC9200", .patch = patch_stac9200 },
{ .id = 0x83847882, .name = "STAC9220 A1", .patch = patch_stac922x },
{ .id = 0x83847680, .name = "STAC9221 A1", .patch = patch_stac922x },
@@ -5144,3 +5535,27 @@ struct hda_codec_preset snd_hda_preset_sigmatel[] = {
{ .id = 0x111d76b7, .name = "92HD71B5X", .patch = patch_stac92hd71bxx },
{} /* terminator */
};
+
+MODULE_ALIAS("snd-hda-codec-id:8384*");
+MODULE_ALIAS("snd-hda-codec-id:111d*");
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("IDT/Sigmatel HD-audio codec");
+
+static struct hda_codec_preset_list sigmatel_list = {
+ .preset = snd_hda_preset_sigmatel,
+ .owner = THIS_MODULE,
+};
+
+static int __init patch_sigmatel_init(void)
+{
+ return snd_hda_add_codec_preset(&sigmatel_list);
+}
+
+static void __exit patch_sigmatel_exit(void)
+{
+ snd_hda_delete_codec_preset(&sigmatel_list);
+}
+
+module_init(patch_sigmatel_init)
+module_exit(patch_sigmatel_exit)
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index 63e4871e5d8..c761394cbe8 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -47,15 +47,11 @@
#include <sound/asoundef.h>
#include "hda_codec.h"
#include "hda_local.h"
-#include "hda_patch.h"
/* amp values */
#define AMP_VAL_IDX_SHIFT 19
#define AMP_VAL_IDX_MASK (0x0f<<19)
-#define NUM_CONTROL_ALLOC 32
-#define NUM_VERB_ALLOC 32
-
/* Pin Widget NID */
#define VT1708_HP_NID 0x13
#define VT1708_DIGOUT_NID 0x14
@@ -145,8 +141,6 @@ enum {
AUTO_SEQ_SIDE
};
-#define get_amp_nid(kc) ((kc)->private_value & 0xffff)
-
/* Some VT1708S based boards gets the micboost setting wrong, so we have
* to apply some brute-force and re-write the TLV's by software. */
static int mic_boost_tlv(struct snd_kcontrol *kcontrol, int op_flag,
@@ -227,8 +221,7 @@ struct via_spec {
/* dynamic controls, init_verbs and input_mux */
struct auto_pin_cfg autocfg;
- unsigned int num_kctl_alloc, num_kctl_used;
- struct snd_kcontrol_new *kctl_alloc;
+ struct snd_array kctls;
struct hda_input_mux private_imux[2];
hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
@@ -272,33 +265,31 @@ static int via_add_control(struct via_spec *spec, int type, const char *name,
{
struct snd_kcontrol_new *knew;
- if (spec->num_kctl_used >= spec->num_kctl_alloc) {
- int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC;
-
- /* array + terminator */
- knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL);
- if (!knew)
- return -ENOMEM;
- if (spec->kctl_alloc) {
- memcpy(knew, spec->kctl_alloc,
- sizeof(*knew) * spec->num_kctl_alloc);
- kfree(spec->kctl_alloc);
- }
- spec->kctl_alloc = knew;
- spec->num_kctl_alloc = num;
- }
-
- knew = &spec->kctl_alloc[spec->num_kctl_used];
+ snd_array_init(&spec->kctls, sizeof(*knew), 32);
+ knew = snd_array_new(&spec->kctls);
+ if (!knew)
+ return -ENOMEM;
*knew = vt1708_control_templates[type];
knew->name = kstrdup(name, GFP_KERNEL);
-
if (!knew->name)
return -ENOMEM;
knew->private_value = val;
- spec->num_kctl_used++;
return 0;
}
+static void via_free_kctls(struct hda_codec *codec)
+{
+ struct via_spec *spec = codec->spec;
+
+ if (spec->kctls.list) {
+ struct snd_kcontrol_new *kctl = spec->kctls.list;
+ int i;
+ for (i = 0; i < spec->kctls.used; i++)
+ kfree(kctl[i].name);
+ }
+ snd_array_free(&spec->kctls);
+}
+
/* create input playback/capture controls for the given pin */
static int via_new_analog_input(struct via_spec *spec, hda_nid_t pin,
const char *ctlname, int idx, int mix_nid)
@@ -896,6 +887,7 @@ static int via_build_controls(struct hda_codec *codec)
if (err < 0)
return err;
}
+ via_free_kctls(codec); /* no longer needed */
return 0;
}
@@ -941,17 +933,11 @@ static int via_build_pcms(struct hda_codec *codec)
static void via_free(struct hda_codec *codec)
{
struct via_spec *spec = codec->spec;
- unsigned int i;
if (!spec)
return;
- if (spec->kctl_alloc) {
- for (i = 0; i < spec->num_kctl_used; i++)
- kfree(spec->kctl_alloc[i].name);
- kfree(spec->kctl_alloc);
- }
-
+ via_free_kctls(codec);
kfree(codec->spec);
}
@@ -1373,8 +1359,8 @@ static int vt1708_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_in_pin)
spec->dig_in_nid = VT1708_DIGIN_NID;
- if (spec->kctl_alloc)
- spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
+ if (spec->kctls.list)
+ spec->mixers[spec->num_mixers++] = spec->kctls.list;
spec->init_verbs[spec->num_iverbs++] = vt1708_volume_init_verbs;
@@ -1846,8 +1832,8 @@ static int vt1709_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_in_pin)
spec->dig_in_nid = VT1709_DIGIN_NID;
- if (spec->kctl_alloc)
- spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
+ if (spec->kctls.list)
+ spec->mixers[spec->num_mixers++] = spec->kctls.list;
spec->input_mux = &spec->private_imux[0];
@@ -2390,8 +2376,8 @@ static int vt1708B_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_in_pin)
spec->dig_in_nid = VT1708B_DIGIN_NID;
- if (spec->kctl_alloc)
- spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
+ if (spec->kctls.list)
+ spec->mixers[spec->num_mixers++] = spec->kctls.list;
spec->input_mux = &spec->private_imux[0];
@@ -2855,8 +2841,8 @@ static int vt1708S_parse_auto_config(struct hda_codec *codec)
spec->extra_dig_out_nid = 0x15;
- if (spec->kctl_alloc)
- spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
+ if (spec->kctls.list)
+ spec->mixers[spec->num_mixers++] = spec->kctls.list;
spec->input_mux = &spec->private_imux[0];
@@ -3174,8 +3160,8 @@ static int vt1702_parse_auto_config(struct hda_codec *codec)
spec->extra_dig_out_nid = 0x1B;
- if (spec->kctl_alloc)
- spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
+ if (spec->kctls.list)
+ spec->mixers[spec->num_mixers++] = spec->kctls.list;
spec->input_mux = &spec->private_imux[0];
@@ -3262,74 +3248,97 @@ static int patch_vt1702(struct hda_codec *codec)
/*
* patch entries
*/
-struct hda_codec_preset snd_hda_preset_via[] = {
- { .id = 0x11061708, .name = "VIA VT1708", .patch = patch_vt1708},
- { .id = 0x11061709, .name = "VIA VT1708", .patch = patch_vt1708},
- { .id = 0x1106170A, .name = "VIA VT1708", .patch = patch_vt1708},
- { .id = 0x1106170B, .name = "VIA VT1708", .patch = patch_vt1708},
- { .id = 0x1106E710, .name = "VIA VT1709 10-Ch",
+static struct hda_codec_preset snd_hda_preset_via[] = {
+ { .id = 0x11061708, .name = "VT1708", .patch = patch_vt1708},
+ { .id = 0x11061709, .name = "VT1708", .patch = patch_vt1708},
+ { .id = 0x1106170a, .name = "VT1708", .patch = patch_vt1708},
+ { .id = 0x1106170b, .name = "VT1708", .patch = patch_vt1708},
+ { .id = 0x1106e710, .name = "VT1709 10-Ch",
.patch = patch_vt1709_10ch},
- { .id = 0x1106E711, .name = "VIA VT1709 10-Ch",
+ { .id = 0x1106e711, .name = "VT1709 10-Ch",
.patch = patch_vt1709_10ch},
- { .id = 0x1106E712, .name = "VIA VT1709 10-Ch",
+ { .id = 0x1106e712, .name = "VT1709 10-Ch",
.patch = patch_vt1709_10ch},
- { .id = 0x1106E713, .name = "VIA VT1709 10-Ch",
+ { .id = 0x1106e713, .name = "VT1709 10-Ch",
.patch = patch_vt1709_10ch},
- { .id = 0x1106E714, .name = "VIA VT1709 6-Ch",
+ { .id = 0x1106e714, .name = "VT1709 6-Ch",
.patch = patch_vt1709_6ch},
- { .id = 0x1106E715, .name = "VIA VT1709 6-Ch",
+ { .id = 0x1106e715, .name = "VT1709 6-Ch",
.patch = patch_vt1709_6ch},
- { .id = 0x1106E716, .name = "VIA VT1709 6-Ch",
+ { .id = 0x1106e716, .name = "VT1709 6-Ch",
.patch = patch_vt1709_6ch},
- { .id = 0x1106E717, .name = "VIA VT1709 6-Ch",
+ { .id = 0x1106e717, .name = "VT1709 6-Ch",
.patch = patch_vt1709_6ch},
- { .id = 0x1106E720, .name = "VIA VT1708B 8-Ch",
+ { .id = 0x1106e720, .name = "VT1708B 8-Ch",
.patch = patch_vt1708B_8ch},
- { .id = 0x1106E721, .name = "VIA VT1708B 8-Ch",
+ { .id = 0x1106e721, .name = "VT1708B 8-Ch",
.patch = patch_vt1708B_8ch},
- { .id = 0x1106E722, .name = "VIA VT1708B 8-Ch",
+ { .id = 0x1106e722, .name = "VT1708B 8-Ch",
.patch = patch_vt1708B_8ch},
- { .id = 0x1106E723, .name = "VIA VT1708B 8-Ch",
+ { .id = 0x1106e723, .name = "VT1708B 8-Ch",
.patch = patch_vt1708B_8ch},
- { .id = 0x1106E724, .name = "VIA VT1708B 4-Ch",
+ { .id = 0x1106e724, .name = "VT1708B 4-Ch",
.patch = patch_vt1708B_4ch},
- { .id = 0x1106E725, .name = "VIA VT1708B 4-Ch",
+ { .id = 0x1106e725, .name = "VT1708B 4-Ch",
.patch = patch_vt1708B_4ch},
- { .id = 0x1106E726, .name = "VIA VT1708B 4-Ch",
+ { .id = 0x1106e726, .name = "VT1708B 4-Ch",
.patch = patch_vt1708B_4ch},
- { .id = 0x1106E727, .name = "VIA VT1708B 4-Ch",
+ { .id = 0x1106e727, .name = "VT1708B 4-Ch",
.patch = patch_vt1708B_4ch},
- { .id = 0x11060397, .name = "VIA VT1708S",
+ { .id = 0x11060397, .name = "VT1708S",
.patch = patch_vt1708S},
- { .id = 0x11061397, .name = "VIA VT1708S",
+ { .id = 0x11061397, .name = "VT1708S",
.patch = patch_vt1708S},
- { .id = 0x11062397, .name = "VIA VT1708S",
+ { .id = 0x11062397, .name = "VT1708S",
.patch = patch_vt1708S},
- { .id = 0x11063397, .name = "VIA VT1708S",
+ { .id = 0x11063397, .name = "VT1708S",
.patch = patch_vt1708S},
- { .id = 0x11064397, .name = "VIA VT1708S",
+ { .id = 0x11064397, .name = "VT1708S",
.patch = patch_vt1708S},
- { .id = 0x11065397, .name = "VIA VT1708S",
+ { .id = 0x11065397, .name = "VT1708S",
.patch = patch_vt1708S},
- { .id = 0x11066397, .name = "VIA VT1708S",
+ { .id = 0x11066397, .name = "VT1708S",
.patch = patch_vt1708S},
- { .id = 0x11067397, .name = "VIA VT1708S",
+ { .id = 0x11067397, .name = "VT1708S",
.patch = patch_vt1708S},
- { .id = 0x11060398, .name = "VIA VT1702",
+ { .id = 0x11060398, .name = "VT1702",
.patch = patch_vt1702},
- { .id = 0x11061398, .name = "VIA VT1702",
+ { .id = 0x11061398, .name = "VT1702",
.patch = patch_vt1702},
- { .id = 0x11062398, .name = "VIA VT1702",
+ { .id = 0x11062398, .name = "VT1702",
.patch = patch_vt1702},
- { .id = 0x11063398, .name = "VIA VT1702",
+ { .id = 0x11063398, .name = "VT1702",
.patch = patch_vt1702},
- { .id = 0x11064398, .name = "VIA VT1702",
+ { .id = 0x11064398, .name = "VT1702",
.patch = patch_vt1702},
- { .id = 0x11065398, .name = "VIA VT1702",
+ { .id = 0x11065398, .name = "VT1702",
.patch = patch_vt1702},
- { .id = 0x11066398, .name = "VIA VT1702",
+ { .id = 0x11066398, .name = "VT1702",
.patch = patch_vt1702},
- { .id = 0x11067398, .name = "VIA VT1702",
+ { .id = 0x11067398, .name = "VT1702",
.patch = patch_vt1702},
{} /* terminator */
};
+
+MODULE_ALIAS("snd-hda-codec-id:1106*");
+
+static struct hda_codec_preset_list via_list = {
+ .preset = snd_hda_preset_via,
+ .owner = THIS_MODULE,
+};
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("VIA HD-audio codec");
+
+static int __init patch_via_init(void)
+{
+ return snd_hda_add_codec_preset(&via_list);
+}
+
+static void __exit patch_via_exit(void)
+{
+ snd_hda_delete_codec_preset(&via_list);
+}
+
+module_init(patch_via_init)
+module_exit(patch_via_exit)
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
index 1b3f1170271..0dfa0540ce2 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -382,23 +382,25 @@ static irqreturn_t snd_vt1724_interrupt(int irq, void *dev_id)
unsigned char status_mask =
VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX | VT1724_IRQ_MTPCM;
int handled = 0;
-#ifdef CONFIG_SND_DEBUG
int timeout = 0;
-#endif
while (1) {
status = inb(ICEREG1724(ice, IRQSTAT));
status &= status_mask;
if (status == 0)
break;
-#ifdef CONFIG_SND_DEBUG
if (++timeout > 10) {
- printk(KERN_ERR
- "ice1724: Too long irq loop, status = 0x%x\n",
- status);
+ status = inb(ICEREG1724(ice, IRQSTAT));
+ printk(KERN_ERR "ice1724: Too long irq loop, "
+ "status = 0x%x\n", status);
+ if (status & VT1724_IRQ_MPU_TX) {
+ printk(KERN_ERR "ice1724: Disabling MPU_TX\n");
+ outb(inb(ICEREG1724(ice, IRQMASK)) |
+ VT1724_IRQ_MPU_TX,
+ ICEREG1724(ice, IRQMASK));
+ }
break;
}
-#endif
handled = 1;
if (status & VT1724_IRQ_MPU_TX) {
spin_lock(&ice->reg_lock);
@@ -2351,7 +2353,6 @@ static int __devinit snd_vt1724_create(struct snd_card *card,
{
struct snd_ice1712 *ice;
int err;
- unsigned char mask;
static struct snd_device_ops ops = {
.dev_free = snd_vt1724_dev_free,
};
@@ -2412,9 +2413,9 @@ static int __devinit snd_vt1724_create(struct snd_card *card,
return -EIO;
}
- /* unmask used interrupts */
- mask = VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX;
- outb(mask, ICEREG1724(ice, IRQMASK));
+ /* MPU_RX and TX irq masks are cleared later dynamically */
+ outb(VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX , ICEREG1724(ice, IRQMASK));
+
/* don't handle FIFO overrun/underruns (just yet),
* since they cause machine lockups
*/
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c
index 9ff3f9e3440..59bbaf8f3e5 100644
--- a/sound/pci/maestro3.c
+++ b/sound/pci/maestro3.c
@@ -1670,7 +1670,7 @@ static irqreturn_t snd_m3_interrupt(int irq, void *dev_id)
return IRQ_NONE;
if (status & HV_INT_PENDING)
- tasklet_hi_schedule(&chip->hwvol_tq);
+ tasklet_schedule(&chip->hwvol_tq);
/*
* ack an assp int if its running
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c
index ae7601f353a..f23a73577c2 100644
--- a/sound/pci/mixart/mixart.c
+++ b/sound/pci/mixart/mixart.c
@@ -1010,7 +1010,7 @@ static int __devinit snd_mixart_create(struct mixart_mgr *mgr, struct snd_card *
.dev_free = snd_mixart_chip_dev_free,
};
- mgr->chip[idx] = chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (! chip) {
snd_printk(KERN_ERR "cannot allocate chip\n");
return -ENOMEM;
@@ -1025,6 +1025,7 @@ static int __devinit snd_mixart_create(struct mixart_mgr *mgr, struct snd_card *
return err;
}
+ mgr->chip[idx] = chip;
snd_card_set_dev(card, &mgr->pci->dev);
return 0;
@@ -1377,6 +1378,7 @@ static int __devinit snd_mixart_probe(struct pci_dev *pci,
sprintf(card->longname, "%s [PCM #%d]", mgr->longname, i);
if ((err = snd_mixart_create(mgr, card, i)) < 0) {
+ snd_card_free(card);
snd_mixart_free(mgr);
return err;
}
diff --git a/sound/pci/mixart/mixart_core.c b/sound/pci/mixart/mixart_core.c
index b9a06c27939..d3350f38396 100644
--- a/sound/pci/mixart/mixart_core.c
+++ b/sound/pci/mixart/mixart_core.c
@@ -550,7 +550,7 @@ irqreturn_t snd_mixart_interrupt(int irq, void *dev_id)
mgr->msg_fifo[mgr->msg_fifo_writeptr] = msg;
mgr->msg_fifo_writeptr++;
mgr->msg_fifo_writeptr %= MSG_FIFO_SIZE;
- tasklet_hi_schedule(&mgr->msg_taskq);
+ tasklet_schedule(&mgr->msg_taskq);
}
spin_unlock(&mgr->msg_lock);
break;
diff --git a/sound/pci/oxygen/oxygen.c b/sound/pci/oxygen/oxygen.c
index b60f6212745..de999c6d6dd 100644
--- a/sound/pci/oxygen/oxygen.c
+++ b/sound/pci/oxygen/oxygen.c
@@ -61,6 +61,7 @@ MODULE_PARM_DESC(enable, "enable card");
enum {
MODEL_CMEDIA_REF, /* C-Media's reference design */
MODEL_MERIDIAN, /* AuzenTech X-Meridian */
+ MODEL_HALO, /* HT-Omega Claro halo */
};
static struct pci_device_id oxygen_ids[] __devinitdata = {
@@ -74,6 +75,7 @@ static struct pci_device_id oxygen_ids[] __devinitdata = {
{ OXYGEN_PCI_SUBID(0x1a58, 0x0910), .driver_data = MODEL_CMEDIA_REF },
{ OXYGEN_PCI_SUBID(0x415a, 0x5431), .driver_data = MODEL_MERIDIAN },
{ OXYGEN_PCI_SUBID(0x7284, 0x9761), .driver_data = MODEL_CMEDIA_REF },
+ { OXYGEN_PCI_SUBID(0x7284, 0x9781), .driver_data = MODEL_HALO },
{ }
};
MODULE_DEVICE_TABLE(pci, oxygen_ids);
@@ -301,6 +303,8 @@ static int generic_probe(struct oxygen *chip, unsigned long driver_data)
PLAYBACK_1_TO_SPDIF |
CAPTURE_0_FROM_I2S_2 |
CAPTURE_1_FROM_SPDIF;
+ }
+ if (driver_data == MODEL_MERIDIAN || driver_data == MODEL_HALO) {
chip->model.misc_flags = OXYGEN_MISC_MIDI;
chip->model.device_config |= MIDI_OUTPUT | MIDI_INPUT;
}
diff --git a/sound/pci/pcxhr/Makefile b/sound/pci/pcxhr/Makefile
index 10473c05918..b06128e918c 100644
--- a/sound/pci/pcxhr/Makefile
+++ b/sound/pci/pcxhr/Makefile
@@ -1,2 +1,2 @@
-snd-pcxhr-objs := pcxhr.o pcxhr_hwdep.o pcxhr_mixer.o pcxhr_core.o
+snd-pcxhr-objs := pcxhr.o pcxhr_hwdep.o pcxhr_mixer.o pcxhr_core.o pcxhr_mix22.o
obj-$(CONFIG_SND_PCXHR) += snd-pcxhr.o
diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c
index 0e06c6c9fcc..27cf2c28d11 100644
--- a/sound/pci/pcxhr/pcxhr.c
+++ b/sound/pci/pcxhr/pcxhr.c
@@ -40,18 +40,20 @@
#include "pcxhr_mixer.h"
#include "pcxhr_hwdep.h"
#include "pcxhr_core.h"
+#include "pcxhr_mix22.h"
#define DRIVER_NAME "pcxhr"
-MODULE_AUTHOR("Markus Bollinger <bollinger@digigram.com>");
+MODULE_AUTHOR("Markus Bollinger <bollinger@digigram.com>, "
+ "Marc Titinger <titinger@digigram.com>");
MODULE_DESCRIPTION("Digigram " DRIVER_NAME " " PCXHR_DRIVER_VERSION_STRING);
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{Digigram," DRIVER_NAME "}}");
-static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
-static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
-static int mono[SNDRV_CARDS]; /* capture in mono only */
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */
+static int mono[SNDRV_CARDS]; /* capture mono only */
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for Digigram " DRIVER_NAME " soundcard");
@@ -67,18 +69,58 @@ enum {
PCI_ID_PCX882HR,
PCI_ID_VX881HR,
PCI_ID_PCX881HR,
+ PCI_ID_VX882E,
+ PCI_ID_PCX882E,
+ PCI_ID_VX881E,
+ PCI_ID_PCX881E,
+ PCI_ID_VX1222HR,
PCI_ID_PCX1222HR,
+ PCI_ID_VX1221HR,
PCI_ID_PCX1221HR,
+ PCI_ID_VX1222E,
+ PCI_ID_PCX1222E,
+ PCI_ID_VX1221E,
+ PCI_ID_PCX1221E,
+ PCI_ID_VX222HR,
+ PCI_ID_VX222E,
+ PCI_ID_PCX22HR,
+ PCI_ID_PCX22E,
+ PCI_ID_VX222HRMIC,
+ PCI_ID_VX222E_MIC,
+ PCI_ID_PCX924HR,
+ PCI_ID_PCX924E,
+ PCI_ID_PCX924HRMIC,
+ PCI_ID_PCX924E_MIC,
PCI_ID_LAST
};
static struct pci_device_id pcxhr_ids[] = {
- { 0x10b5, 0x9656, 0x1369, 0xb001, 0, 0, PCI_ID_VX882HR, }, /* VX882HR */
- { 0x10b5, 0x9656, 0x1369, 0xb101, 0, 0, PCI_ID_PCX882HR, }, /* PCX882HR */
- { 0x10b5, 0x9656, 0x1369, 0xb201, 0, 0, PCI_ID_VX881HR, }, /* VX881HR */
- { 0x10b5, 0x9656, 0x1369, 0xb301, 0, 0, PCI_ID_PCX881HR, }, /* PCX881HR */
- { 0x10b5, 0x9656, 0x1369, 0xb501, 0, 0, PCI_ID_PCX1222HR, }, /* PCX1222HR */
- { 0x10b5, 0x9656, 0x1369, 0xb701, 0, 0, PCI_ID_PCX1221HR, }, /* PCX1221HR */
+ { 0x10b5, 0x9656, 0x1369, 0xb001, 0, 0, PCI_ID_VX882HR, },
+ { 0x10b5, 0x9656, 0x1369, 0xb101, 0, 0, PCI_ID_PCX882HR, },
+ { 0x10b5, 0x9656, 0x1369, 0xb201, 0, 0, PCI_ID_VX881HR, },
+ { 0x10b5, 0x9656, 0x1369, 0xb301, 0, 0, PCI_ID_PCX881HR, },
+ { 0x10b5, 0x9056, 0x1369, 0xb021, 0, 0, PCI_ID_VX882E, },
+ { 0x10b5, 0x9056, 0x1369, 0xb121, 0, 0, PCI_ID_PCX882E, },
+ { 0x10b5, 0x9056, 0x1369, 0xb221, 0, 0, PCI_ID_VX881E, },
+ { 0x10b5, 0x9056, 0x1369, 0xb321, 0, 0, PCI_ID_PCX881E, },
+ { 0x10b5, 0x9656, 0x1369, 0xb401, 0, 0, PCI_ID_VX1222HR, },
+ { 0x10b5, 0x9656, 0x1369, 0xb501, 0, 0, PCI_ID_PCX1222HR, },
+ { 0x10b5, 0x9656, 0x1369, 0xb601, 0, 0, PCI_ID_VX1221HR, },
+ { 0x10b5, 0x9656, 0x1369, 0xb701, 0, 0, PCI_ID_PCX1221HR, },
+ { 0x10b5, 0x9056, 0x1369, 0xb421, 0, 0, PCI_ID_VX1222E, },
+ { 0x10b5, 0x9056, 0x1369, 0xb521, 0, 0, PCI_ID_PCX1222E, },
+ { 0x10b5, 0x9056, 0x1369, 0xb621, 0, 0, PCI_ID_VX1221E, },
+ { 0x10b5, 0x9056, 0x1369, 0xb721, 0, 0, PCI_ID_PCX1221E, },
+ { 0x10b5, 0x9056, 0x1369, 0xba01, 0, 0, PCI_ID_VX222HR, },
+ { 0x10b5, 0x9056, 0x1369, 0xba21, 0, 0, PCI_ID_VX222E, },
+ { 0x10b5, 0x9056, 0x1369, 0xbd01, 0, 0, PCI_ID_PCX22HR, },
+ { 0x10b5, 0x9056, 0x1369, 0xbd21, 0, 0, PCI_ID_PCX22E, },
+ { 0x10b5, 0x9056, 0x1369, 0xbc01, 0, 0, PCI_ID_VX222HRMIC, },
+ { 0x10b5, 0x9056, 0x1369, 0xbc21, 0, 0, PCI_ID_VX222E_MIC, },
+ { 0x10b5, 0x9056, 0x1369, 0xbb01, 0, 0, PCI_ID_PCX924HR, },
+ { 0x10b5, 0x9056, 0x1369, 0xbb21, 0, 0, PCI_ID_PCX924E, },
+ { 0x10b5, 0x9056, 0x1369, 0xbf01, 0, 0, PCI_ID_PCX924HRMIC, },
+ { 0x10b5, 0x9056, 0x1369, 0xbf21, 0, 0, PCI_ID_PCX924E_MIC, },
{ 0, }
};
@@ -88,27 +130,55 @@ struct board_parameters {
char* board_name;
short playback_chips;
short capture_chips;
+ short fw_file_set;
short firmware_num;
};
static struct board_parameters pcxhr_board_params[] = {
-[PCI_ID_VX882HR] = { "VX882HR", 4, 4, 41, },
-[PCI_ID_PCX882HR] = { "PCX882HR", 4, 4, 41, },
-[PCI_ID_VX881HR] = { "VX881HR", 4, 4, 41, },
-[PCI_ID_PCX881HR] = { "PCX881HR", 4, 4, 41, },
-[PCI_ID_PCX1222HR] = { "PCX1222HR", 6, 1, 42, },
-[PCI_ID_PCX1221HR] = { "PCX1221HR", 6, 1, 42, },
+[PCI_ID_VX882HR] = { "VX882HR", 4, 4, 0, 41 },
+[PCI_ID_PCX882HR] = { "PCX882HR", 4, 4, 0, 41 },
+[PCI_ID_VX881HR] = { "VX881HR", 4, 4, 0, 41 },
+[PCI_ID_PCX881HR] = { "PCX881HR", 4, 4, 0, 41 },
+[PCI_ID_VX882E] = { "VX882e", 4, 4, 1, 41 },
+[PCI_ID_PCX882E] = { "PCX882e", 4, 4, 1, 41 },
+[PCI_ID_VX881E] = { "VX881e", 4, 4, 1, 41 },
+[PCI_ID_PCX881E] = { "PCX881e", 4, 4, 1, 41 },
+[PCI_ID_VX1222HR] = { "VX1222HR", 6, 1, 2, 42 },
+[PCI_ID_PCX1222HR] = { "PCX1222HR", 6, 1, 2, 42 },
+[PCI_ID_VX1221HR] = { "VX1221HR", 6, 1, 2, 42 },
+[PCI_ID_PCX1221HR] = { "PCX1221HR", 6, 1, 2, 42 },
+[PCI_ID_VX1222E] = { "VX1222e", 6, 1, 3, 42 },
+[PCI_ID_PCX1222E] = { "PCX1222e", 6, 1, 3, 42 },
+[PCI_ID_VX1221E] = { "VX1221e", 6, 1, 3, 42 },
+[PCI_ID_PCX1221E] = { "PCX1221e", 6, 1, 3, 42 },
+[PCI_ID_VX222HR] = { "VX222HR", 1, 1, 4, 44 },
+[PCI_ID_VX222E] = { "VX222e", 1, 1, 4, 44 },
+[PCI_ID_PCX22HR] = { "PCX22HR", 1, 0, 4, 44 },
+[PCI_ID_PCX22E] = { "PCX22e", 1, 0, 4, 44 },
+[PCI_ID_VX222HRMIC] = { "VX222HR-Mic", 1, 1, 5, 44 },
+[PCI_ID_VX222E_MIC] = { "VX222e-Mic", 1, 1, 5, 44 },
+[PCI_ID_PCX924HR] = { "PCX924HR", 1, 1, 5, 44 },
+[PCI_ID_PCX924E] = { "PCX924e", 1, 1, 5, 44 },
+[PCI_ID_PCX924HRMIC] = { "PCX924HR-Mic", 1, 1, 5, 44 },
+[PCI_ID_PCX924E_MIC] = { "PCX924e-Mic", 1, 1, 5, 44 },
};
+/* boards without hw AES1 and SRC onboard are all using fw_file_set==4 */
+/* VX222HR, VX222e, PCX22HR and PCX22e */
+#define PCXHR_BOARD_HAS_AES1(x) (x->fw_file_set != 4)
+/* some boards do not support 192kHz on digital AES input plugs */
+#define PCXHR_BOARD_AESIN_NO_192K(x) ((x->capture_chips == 0) || \
+ (x->fw_file_set == 0) || \
+ (x->fw_file_set == 2))
static int pcxhr_pll_freq_register(unsigned int freq, unsigned int* pllreg,
unsigned int* realfreq)
{
unsigned int reg;
- if (freq < 6900 || freq > 110250)
+ if (freq < 6900 || freq > 110000)
return -EINVAL;
- reg = (28224000 * 10) / freq;
- reg = (reg + 5) / 10;
+ reg = (28224000 * 2) / freq;
+ reg = (reg - 1) / 2;
if (reg < 0x200)
*pllreg = reg + 0x800;
else if (reg < 0x400)
@@ -121,7 +191,7 @@ static int pcxhr_pll_freq_register(unsigned int freq, unsigned int* pllreg,
reg &= ~3;
}
if (realfreq)
- *realfreq = ((28224000 * 10) / reg + 5) / 10;
+ *realfreq = (28224000 / (reg + 1));
return 0;
}
@@ -151,11 +221,6 @@ static int pcxhr_pll_freq_register(unsigned int freq, unsigned int* pllreg,
#define PCXHR_FREQ_AES_3 0x03
#define PCXHR_FREQ_AES_4 0x0d
-#define PCXHR_MODIFY_CLOCK_S_BIT 0x04
-
-#define PCXHR_IRQ_TIMER_FREQ 92000
-#define PCXHR_IRQ_TIMER_PERIOD 48
-
static int pcxhr_get_clock_reg(struct pcxhr_mgr *mgr, unsigned int rate,
unsigned int *reg, unsigned int *freq)
{
@@ -196,19 +261,32 @@ static int pcxhr_get_clock_reg(struct pcxhr_mgr *mgr, unsigned int rate,
err = pcxhr_send_msg(mgr, &rmh);
if (err < 0) {
snd_printk(KERN_ERR
- "error CMD_ACCESS_IO_WRITE for PLL register : %x!\n",
- err );
+ "error CMD_ACCESS_IO_WRITE "
+ "for PLL register : %x!\n", err);
return err;
}
}
break;
- case PCXHR_CLOCK_TYPE_WORD_CLOCK : val = PCXHR_FREQ_WORD_CLOCK; break;
- case PCXHR_CLOCK_TYPE_AES_SYNC : val = PCXHR_FREQ_SYNC_AES; break;
- case PCXHR_CLOCK_TYPE_AES_1 : val = PCXHR_FREQ_AES_1; break;
- case PCXHR_CLOCK_TYPE_AES_2 : val = PCXHR_FREQ_AES_2; break;
- case PCXHR_CLOCK_TYPE_AES_3 : val = PCXHR_FREQ_AES_3; break;
- case PCXHR_CLOCK_TYPE_AES_4 : val = PCXHR_FREQ_AES_4; break;
- default : return -EINVAL;
+ case PCXHR_CLOCK_TYPE_WORD_CLOCK:
+ val = PCXHR_FREQ_WORD_CLOCK;
+ break;
+ case PCXHR_CLOCK_TYPE_AES_SYNC:
+ val = PCXHR_FREQ_SYNC_AES;
+ break;
+ case PCXHR_CLOCK_TYPE_AES_1:
+ val = PCXHR_FREQ_AES_1;
+ break;
+ case PCXHR_CLOCK_TYPE_AES_2:
+ val = PCXHR_FREQ_AES_2;
+ break;
+ case PCXHR_CLOCK_TYPE_AES_3:
+ val = PCXHR_FREQ_AES_3;
+ break;
+ case PCXHR_CLOCK_TYPE_AES_4:
+ val = PCXHR_FREQ_AES_4;
+ break;
+ default:
+ return -EINVAL;
}
*reg = val;
*freq = realfreq;
@@ -216,14 +294,13 @@ static int pcxhr_get_clock_reg(struct pcxhr_mgr *mgr, unsigned int rate,
}
-int pcxhr_set_clock(struct pcxhr_mgr *mgr, unsigned int rate)
+static int pcxhr_sub_set_clock(struct pcxhr_mgr *mgr,
+ unsigned int rate,
+ int *changed)
{
unsigned int val, realfreq, speed;
struct pcxhr_rmh rmh;
- int err, changed;
-
- if (rate == 0)
- return 0; /* nothing to do */
+ int err;
err = pcxhr_get_clock_reg(mgr, rate, &val, &realfreq);
if (err)
@@ -237,13 +314,17 @@ int pcxhr_set_clock(struct pcxhr_mgr *mgr, unsigned int rate)
else
speed = 2; /* quad speed */
if (mgr->codec_speed != speed) {
- pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE); /* mute outputs */
+ pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE); /* mute outputs */
rmh.cmd[0] |= IO_NUM_REG_MUTE_OUT;
+ if (DSP_EXT_CMD_SET(mgr)) {
+ rmh.cmd[1] = 1;
+ rmh.cmd_len = 2;
+ }
err = pcxhr_send_msg(mgr, &rmh);
if (err)
return err;
- pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE); /* set speed ratio */
+ pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE); /* set speed ratio */
rmh.cmd[0] |= IO_NUM_SPEED_RATIO;
rmh.cmd[1] = speed;
rmh.cmd_len = 2;
@@ -253,25 +334,57 @@ int pcxhr_set_clock(struct pcxhr_mgr *mgr, unsigned int rate)
}
/* set the new frequency */
snd_printdd("clock register : set %x\n", val);
- err = pcxhr_write_io_num_reg_cont(mgr, PCXHR_FREQ_REG_MASK, val, &changed);
+ err = pcxhr_write_io_num_reg_cont(mgr, PCXHR_FREQ_REG_MASK,
+ val, changed);
if (err)
return err;
+
mgr->sample_rate_real = realfreq;
mgr->cur_clock_type = mgr->use_clock_type;
/* unmute after codec speed modes */
if (mgr->codec_speed != speed) {
- pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_READ); /* unmute outputs */
+ pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_READ); /* unmute outputs */
rmh.cmd[0] |= IO_NUM_REG_MUTE_OUT;
+ if (DSP_EXT_CMD_SET(mgr)) {
+ rmh.cmd[1] = 1;
+ rmh.cmd_len = 2;
+ }
err = pcxhr_send_msg(mgr, &rmh);
if (err)
return err;
- mgr->codec_speed = speed; /* save new codec speed */
+ mgr->codec_speed = speed; /* save new codec speed */
}
+ snd_printdd("pcxhr_sub_set_clock to %dHz (realfreq=%d)\n",
+ rate, realfreq);
+ return 0;
+}
+
+#define PCXHR_MODIFY_CLOCK_S_BIT 0x04
+
+#define PCXHR_IRQ_TIMER_FREQ 92000
+#define PCXHR_IRQ_TIMER_PERIOD 48
+
+int pcxhr_set_clock(struct pcxhr_mgr *mgr, unsigned int rate)
+{
+ struct pcxhr_rmh rmh;
+ int err, changed;
+
+ if (rate == 0)
+ return 0; /* nothing to do */
+
+ if (mgr->is_hr_stereo)
+ err = hr222_sub_set_clock(mgr, rate, &changed);
+ else
+ err = pcxhr_sub_set_clock(mgr, rate, &changed);
+
+ if (err)
+ return err;
+
if (changed) {
pcxhr_init_rmh(&rmh, CMD_MODIFY_CLOCK);
- rmh.cmd[0] |= PCXHR_MODIFY_CLOCK_S_BIT; /* resync fifos */
+ rmh.cmd[0] |= PCXHR_MODIFY_CLOCK_S_BIT; /* resync fifos */
if (rate < PCXHR_IRQ_TIMER_FREQ)
rmh.cmd[1] = PCXHR_IRQ_TIMER_PERIOD;
else
@@ -282,26 +395,39 @@ int pcxhr_set_clock(struct pcxhr_mgr *mgr, unsigned int rate)
if (err)
return err;
}
- snd_printdd("pcxhr_set_clock to %dHz (realfreq=%d)\n", rate, realfreq);
return 0;
}
-int pcxhr_get_external_clock(struct pcxhr_mgr *mgr, enum pcxhr_clock_type clock_type,
- int *sample_rate)
+static int pcxhr_sub_get_external_clock(struct pcxhr_mgr *mgr,
+ enum pcxhr_clock_type clock_type,
+ int *sample_rate)
{
struct pcxhr_rmh rmh;
unsigned char reg;
int err, rate;
switch (clock_type) {
- case PCXHR_CLOCK_TYPE_WORD_CLOCK : reg = REG_STATUS_WORD_CLOCK; break;
- case PCXHR_CLOCK_TYPE_AES_SYNC : reg = REG_STATUS_AES_SYNC; break;
- case PCXHR_CLOCK_TYPE_AES_1 : reg = REG_STATUS_AES_1; break;
- case PCXHR_CLOCK_TYPE_AES_2 : reg = REG_STATUS_AES_2; break;
- case PCXHR_CLOCK_TYPE_AES_3 : reg = REG_STATUS_AES_3; break;
- case PCXHR_CLOCK_TYPE_AES_4 : reg = REG_STATUS_AES_4; break;
- default : return -EINVAL;
+ case PCXHR_CLOCK_TYPE_WORD_CLOCK:
+ reg = REG_STATUS_WORD_CLOCK;
+ break;
+ case PCXHR_CLOCK_TYPE_AES_SYNC:
+ reg = REG_STATUS_AES_SYNC;
+ break;
+ case PCXHR_CLOCK_TYPE_AES_1:
+ reg = REG_STATUS_AES_1;
+ break;
+ case PCXHR_CLOCK_TYPE_AES_2:
+ reg = REG_STATUS_AES_2;
+ break;
+ case PCXHR_CLOCK_TYPE_AES_3:
+ reg = REG_STATUS_AES_3;
+ break;
+ case PCXHR_CLOCK_TYPE_AES_4:
+ reg = REG_STATUS_AES_4;
+ break;
+ default:
+ return -EINVAL;
}
pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_READ);
rmh.cmd_len = 2;
@@ -311,7 +437,7 @@ int pcxhr_get_external_clock(struct pcxhr_mgr *mgr, enum pcxhr_clock_type clock_
err = pcxhr_send_msg(mgr, &rmh);
if (err)
return err;
- udelay(100); /* wait minimum 2 sample_frames at 32kHz ! */
+ udelay(100); /* wait minimum 2 sample_frames at 32kHz ! */
mgr->last_reg_stat = reg;
}
rmh.cmd[1] = REG_STATUS_CURRENT;
@@ -336,6 +462,18 @@ int pcxhr_get_external_clock(struct pcxhr_mgr *mgr, enum pcxhr_clock_type clock_
}
+int pcxhr_get_external_clock(struct pcxhr_mgr *mgr,
+ enum pcxhr_clock_type clock_type,
+ int *sample_rate)
+{
+ if (mgr->is_hr_stereo)
+ return hr222_get_external_clock(mgr, clock_type,
+ sample_rate);
+ else
+ return pcxhr_sub_get_external_clock(mgr, clock_type,
+ sample_rate);
+}
+
/*
* start or stop playback/capture substream
*/
@@ -350,7 +488,8 @@ static int pcxhr_set_stream_state(struct pcxhr_stream *stream)
start = 1;
else {
if (stream->status != PCXHR_STREAM_STATUS_SCHEDULE_STOP) {
- snd_printk(KERN_ERR "ERROR pcxhr_set_stream_state CANNOT be stopped\n");
+ snd_printk(KERN_ERR "ERROR pcxhr_set_stream_state "
+ "CANNOT be stopped\n");
return -EINVAL;
}
start = 0;
@@ -359,11 +498,12 @@ static int pcxhr_set_stream_state(struct pcxhr_stream *stream)
return -EINVAL;
stream->timer_abs_periods = 0;
- stream->timer_period_frag = 0; /* reset theoretical stream pos */
+ stream->timer_period_frag = 0; /* reset theoretical stream pos */
stream->timer_buf_periods = 0;
stream->timer_is_synced = 0;
- stream_mask = stream->pipe->is_capture ? 1 : 1<<stream->substream->number;
+ stream_mask =
+ stream->pipe->is_capture ? 1 : 1<<stream->substream->number;
pcxhr_init_rmh(&rmh, start ? CMD_START_STREAM : CMD_STOP_STREAM);
pcxhr_set_pipe_cmd_params(&rmh, stream->pipe->is_capture,
@@ -373,8 +513,10 @@ static int pcxhr_set_stream_state(struct pcxhr_stream *stream)
err = pcxhr_send_msg(chip->mgr, &rmh);
if (err)
- snd_printk(KERN_ERR "ERROR pcxhr_set_stream_state err=%x;\n", err);
- stream->status = start ? PCXHR_STREAM_STATUS_STARTED : PCXHR_STREAM_STATUS_STOPPED;
+ snd_printk(KERN_ERR "ERROR pcxhr_set_stream_state err=%x;\n",
+ err);
+ stream->status =
+ start ? PCXHR_STREAM_STATUS_STARTED : PCXHR_STREAM_STATUS_STOPPED;
return err;
}
@@ -399,13 +541,15 @@ static int pcxhr_set_format(struct pcxhr_stream *stream)
header = HEADER_FMT_BASE_LIN;
break;
case SNDRV_PCM_FORMAT_S16_LE:
- header = HEADER_FMT_BASE_LIN | HEADER_FMT_16BITS | HEADER_FMT_INTEL;
+ header = HEADER_FMT_BASE_LIN |
+ HEADER_FMT_16BITS | HEADER_FMT_INTEL;
break;
case SNDRV_PCM_FORMAT_S16_BE:
header = HEADER_FMT_BASE_LIN | HEADER_FMT_16BITS;
break;
case SNDRV_PCM_FORMAT_S24_3LE:
- header = HEADER_FMT_BASE_LIN | HEADER_FMT_24BITS | HEADER_FMT_INTEL;
+ header = HEADER_FMT_BASE_LIN |
+ HEADER_FMT_24BITS | HEADER_FMT_INTEL;
break;
case SNDRV_PCM_FORMAT_S24_3BE:
header = HEADER_FMT_BASE_LIN | HEADER_FMT_24BITS;
@@ -414,7 +558,8 @@ static int pcxhr_set_format(struct pcxhr_stream *stream)
header = HEADER_FMT_BASE_FLOAT | HEADER_FMT_INTEL;
break;
default:
- snd_printk(KERN_ERR "error pcxhr_set_format() : unknown format\n");
+ snd_printk(KERN_ERR
+ "error pcxhr_set_format() : unknown format\n");
return -EINVAL;
}
chip = snd_pcm_substream_chip(stream->substream);
@@ -432,14 +577,31 @@ static int pcxhr_set_format(struct pcxhr_stream *stream)
is_capture = stream->pipe->is_capture;
stream_num = is_capture ? 0 : stream->substream->number;
- pcxhr_init_rmh(&rmh, is_capture ? CMD_FORMAT_STREAM_IN : CMD_FORMAT_STREAM_OUT);
- pcxhr_set_pipe_cmd_params(&rmh, is_capture, stream->pipe->first_audio, stream_num, 0);
- if (is_capture)
- rmh.cmd[0] |= 1<<12;
+ pcxhr_init_rmh(&rmh, is_capture ?
+ CMD_FORMAT_STREAM_IN : CMD_FORMAT_STREAM_OUT);
+ pcxhr_set_pipe_cmd_params(&rmh, is_capture, stream->pipe->first_audio,
+ stream_num, 0);
+ if (is_capture) {
+ /* bug with old dsp versions: */
+ /* bit 12 also sets the format of the playback stream */
+ if (DSP_EXT_CMD_SET(chip->mgr))
+ rmh.cmd[0] |= 1<<10;
+ else
+ rmh.cmd[0] |= 1<<12;
+ }
rmh.cmd[1] = 0;
- rmh.cmd[2] = header >> 8;
- rmh.cmd[3] = (header & 0xff) << 16;
- rmh.cmd_len = 4;
+ rmh.cmd_len = 2;
+ if (DSP_EXT_CMD_SET(chip->mgr)) {
+ /* add channels and set bit 19 if channels>2 */
+ rmh.cmd[1] = stream->channels;
+ if (!is_capture) {
+ /* playback : add channel mask to command */
+ rmh.cmd[2] = (stream->channels == 1) ? 0x01 : 0x03;
+ rmh.cmd_len = 3;
+ }
+ }
+ rmh.cmd[rmh.cmd_len++] = header >> 8;
+ rmh.cmd[rmh.cmd_len++] = (header & 0xff) << 16;
err = pcxhr_send_msg(chip->mgr, &rmh);
if (err)
snd_printk(KERN_ERR "ERROR pcxhr_set_format err=%x;\n", err);
@@ -456,30 +618,38 @@ static int pcxhr_update_r_buffer(struct pcxhr_stream *stream)
is_capture = (subs->stream == SNDRV_PCM_STREAM_CAPTURE);
stream_num = is_capture ? 0 : subs->number;
- snd_printdd("pcxhr_update_r_buffer(pcm%c%d) : addr(%p) bytes(%zx) subs(%d)\n",
+ snd_printdd("pcxhr_update_r_buffer(pcm%c%d) : "
+ "addr(%p) bytes(%zx) subs(%d)\n",
is_capture ? 'c' : 'p',
chip->chip_idx, (void *)(long)subs->runtime->dma_addr,
subs->runtime->dma_bytes, subs->number);
pcxhr_init_rmh(&rmh, CMD_UPDATE_R_BUFFERS);
- pcxhr_set_pipe_cmd_params(&rmh, is_capture, stream->pipe->first_audio, stream_num, 0);
+ pcxhr_set_pipe_cmd_params(&rmh, is_capture, stream->pipe->first_audio,
+ stream_num, 0);
/* max buffer size is 2 MByte */
snd_BUG_ON(subs->runtime->dma_bytes >= 0x200000);
- rmh.cmd[1] = subs->runtime->dma_bytes * 8; /* size in bits */
- rmh.cmd[2] = subs->runtime->dma_addr >> 24; /* most significant byte */
- rmh.cmd[2] |= 1<<19; /* this is a circular buffer */
- rmh.cmd[3] = subs->runtime->dma_addr & MASK_DSP_WORD; /* least 3 significant bytes */
+ /* size in bits */
+ rmh.cmd[1] = subs->runtime->dma_bytes * 8;
+ /* most significant byte */
+ rmh.cmd[2] = subs->runtime->dma_addr >> 24;
+ /* this is a circular buffer */
+ rmh.cmd[2] |= 1<<19;
+ /* least 3 significant bytes */
+ rmh.cmd[3] = subs->runtime->dma_addr & MASK_DSP_WORD;
rmh.cmd_len = 4;
err = pcxhr_send_msg(chip->mgr, &rmh);
if (err)
- snd_printk(KERN_ERR "ERROR CMD_UPDATE_R_BUFFERS err=%x;\n", err);
+ snd_printk(KERN_ERR
+ "ERROR CMD_UPDATE_R_BUFFERS err=%x;\n", err);
return err;
}
#if 0
-static int pcxhr_pipe_sample_count(struct pcxhr_stream *stream, snd_pcm_uframes_t *sample_count)
+static int pcxhr_pipe_sample_count(struct pcxhr_stream *stream,
+ snd_pcm_uframes_t *sample_count)
{
struct pcxhr_rmh rmh;
int err;
@@ -533,8 +703,8 @@ static void pcxhr_trigger_tasklet(unsigned long arg)
for (j = 0; j < chip->nb_streams_play; j++) {
if (pcxhr_stream_scheduled_get_pipe(&chip->playback_stream[j], &pipe)) {
playback_mask |= (1 << pipe->first_audio);
- break; /* add only once, as all playback streams of
- * one chip use the same pipe
+ break; /* add only once, as all playback
+ * streams of one chip use the same pipe
*/
}
}
@@ -545,19 +715,21 @@ static void pcxhr_trigger_tasklet(unsigned long arg)
return;
}
- snd_printdd("pcxhr_trigger_tasklet : playback_mask=%x capture_mask=%x\n",
+ snd_printdd("pcxhr_trigger_tasklet : "
+ "playback_mask=%x capture_mask=%x\n",
playback_mask, capture_mask);
/* synchronous stop of all the pipes concerned */
err = pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 0);
if (err) {
mutex_unlock(&mgr->setup_mutex);
- snd_printk(KERN_ERR "pcxhr_trigger_tasklet : error stop pipes (P%x C%x)\n",
+ snd_printk(KERN_ERR "pcxhr_trigger_tasklet : "
+ "error stop pipes (P%x C%x)\n",
playback_mask, capture_mask);
return;
}
- /* unfortunately the dsp lost format and buffer info with the stop pipe */
+ /* the dsp lost format and buffer info with the stop pipe */
for (i = 0; i < mgr->num_cards; i++) {
struct pcxhr_stream *stream;
chip = mgr->chip[i];
@@ -596,12 +768,15 @@ static void pcxhr_trigger_tasklet(unsigned long arg)
err = pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 1);
if (err) {
mutex_unlock(&mgr->setup_mutex);
- snd_printk(KERN_ERR "pcxhr_trigger_tasklet : error start pipes (P%x C%x)\n",
+ snd_printk(KERN_ERR "pcxhr_trigger_tasklet : "
+ "error start pipes (P%x C%x)\n",
playback_mask, capture_mask);
return;
}
- /* put the streams into the running state now (increment pointer by interrupt) */
+ /* put the streams into the running state now
+ * (increment pointer by interrupt)
+ */
spin_lock_irqsave(&mgr->lock, flags);
for ( i =0; i < mgr->num_cards; i++) {
struct pcxhr_stream *stream;
@@ -615,7 +790,7 @@ static void pcxhr_trigger_tasklet(unsigned long arg)
stream = &chip->playback_stream[j];
if (stream->status == PCXHR_STREAM_STATUS_STARTED) {
/* playback will already have advanced ! */
- stream->timer_period_frag += PCXHR_GRANULARITY;
+ stream->timer_period_frag += mgr->granularity;
stream->status = PCXHR_STREAM_STATUS_RUNNING;
}
}
@@ -653,7 +828,7 @@ static int pcxhr_trigger(struct snd_pcm_substream *subs, int cmd)
PCXHR_STREAM_STATUS_SCHEDULE_RUN;
snd_pcm_trigger_done(s, subs);
}
- tasklet_hi_schedule(&chip->mgr->trigger_taskq);
+ tasklet_schedule(&chip->mgr->trigger_taskq);
} else {
stream = subs->runtime->private_data;
snd_printdd("Only one Substream %c %d\n",
@@ -697,12 +872,14 @@ static int pcxhr_hardware_timer(struct pcxhr_mgr *mgr, int start)
pcxhr_init_rmh(&rmh, CMD_SET_TIMER_INTERRUPT);
if (start) {
- mgr->dsp_time_last = PCXHR_DSP_TIME_INVALID; /* last dsp time invalid */
- rmh.cmd[0] |= PCXHR_GRANULARITY;
+ /* last dsp time invalid */
+ mgr->dsp_time_last = PCXHR_DSP_TIME_INVALID;
+ rmh.cmd[0] |= mgr->granularity;
}
err = pcxhr_send_msg(mgr, &rmh);
if (err < 0)
- snd_printk(KERN_ERR "error pcxhr_hardware_timer err(%x)\n", err);
+ snd_printk(KERN_ERR "error pcxhr_hardware_timer err(%x)\n",
+ err);
return err;
}
@@ -713,38 +890,16 @@ static int pcxhr_prepare(struct snd_pcm_substream *subs)
{
struct snd_pcxhr *chip = snd_pcm_substream_chip(subs);
struct pcxhr_mgr *mgr = chip->mgr;
- /*
- struct pcxhr_stream *stream = (pcxhr_stream_t*)subs->runtime->private_data;
- */
int err = 0;
snd_printdd("pcxhr_prepare : period_size(%lx) periods(%x) buffer_size(%lx)\n",
subs->runtime->period_size, subs->runtime->periods,
subs->runtime->buffer_size);
- /*
- if(subs->runtime->period_size <= PCXHR_GRANULARITY) {
- snd_printk(KERN_ERR "pcxhr_prepare : error period_size too small (%x)\n",
- (unsigned int)subs->runtime->period_size);
- return -EINVAL;
- }
- */
-
mutex_lock(&mgr->setup_mutex);
do {
- /* if the stream was stopped before, format and buffer were reset */
- /*
- if(stream->status == PCXHR_STREAM_STATUS_STOPPED) {
- err = pcxhr_set_format(stream);
- if(err) break;
- err = pcxhr_update_r_buffer(stream);
- if(err) break;
- }
- */
-
/* only the first stream can choose the sample rate */
- /* the further opened streams will be limited to its frequency (see open) */
/* set the clock only once (first stream) */
if (mgr->sample_rate != subs->runtime->rate) {
err = pcxhr_set_clock(mgr, subs->runtime->rate);
@@ -787,22 +942,9 @@ static int pcxhr_hw_params(struct snd_pcm_substream *subs,
stream->channels = channels;
stream->format = format;
- /* set the format to the board */
- /*
- err = pcxhr_set_format(stream);
- if(err) {
- mutex_unlock(&mgr->setup_mutex);
- return err;
- }
- */
/* allocate buffer */
err = snd_pcm_lib_malloc_pages(subs, params_buffer_bytes(hw));
- /*
- if (err > 0) {
- err = pcxhr_update_r_buffer(stream);
- }
- */
mutex_unlock(&mgr->setup_mutex);
return err;
@@ -820,14 +962,18 @@ static int pcxhr_hw_free(struct snd_pcm_substream *subs)
*/
static struct snd_pcm_hardware pcxhr_caps =
{
- .info = ( SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START |
- 0 /*SNDRV_PCM_INFO_PAUSE*/),
- .formats = ( SNDRV_PCM_FMTBIT_U8 |
- SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |
- SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE |
- SNDRV_PCM_FMTBIT_FLOAT_LE ),
- .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_192000,
+ .info = (SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_SYNC_START),
+ .formats = (SNDRV_PCM_FMTBIT_U8 |
+ SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S16_BE |
+ SNDRV_PCM_FMTBIT_S24_3LE |
+ SNDRV_PCM_FMTBIT_S24_3BE |
+ SNDRV_PCM_FMTBIT_FLOAT_LE),
+ .rates = (SNDRV_PCM_RATE_CONTINUOUS |
+ SNDRV_PCM_RATE_8000_192000),
.rate_min = 8000,
.rate_max = 192000,
.channels_min = 1,
@@ -847,6 +993,7 @@ static int pcxhr_open(struct snd_pcm_substream *subs)
struct pcxhr_mgr *mgr = chip->mgr;
struct snd_pcm_runtime *runtime = subs->runtime;
struct pcxhr_stream *stream;
+ int err;
mutex_lock(&mgr->setup_mutex);
@@ -874,6 +1021,18 @@ static int pcxhr_open(struct snd_pcm_substream *subs)
return -EBUSY;
}
+ /* float format support is in some cases buggy on stereo cards */
+ if (mgr->is_hr_stereo)
+ runtime->hw.formats &= ~SNDRV_PCM_FMTBIT_FLOAT_LE;
+
+ /* buffer-size should better be multiple of period-size */
+ err = snd_pcm_hw_constraint_integer(runtime,
+ SNDRV_PCM_HW_PARAM_PERIODS);
+ if (err < 0) {
+ mutex_unlock(&mgr->setup_mutex);
+ return err;
+ }
+
/* if a sample rate is already used or fixed by external clock,
* the stream cannot change
*/
@@ -889,7 +1048,8 @@ static int pcxhr_open(struct snd_pcm_substream *subs)
mutex_unlock(&mgr->setup_mutex);
return -EBUSY;
}
- runtime->hw.rate_min = runtime->hw.rate_max = external_rate;
+ runtime->hw.rate_min = external_rate;
+ runtime->hw.rate_max = external_rate;
}
}
@@ -899,9 +1059,11 @@ static int pcxhr_open(struct snd_pcm_substream *subs)
runtime->private_data = stream;
- snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 4);
- snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 4);
-
+ /* better get a divisor of granularity values (96 or 192) */
+ snd_pcm_hw_constraint_step(runtime, 0,
+ SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 32);
+ snd_pcm_hw_constraint_step(runtime, 0,
+ SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 32);
snd_pcm_set_sync(subs);
mgr->ref_count_rate++;
@@ -919,11 +1081,12 @@ static int pcxhr_close(struct snd_pcm_substream *subs)
mutex_lock(&mgr->setup_mutex);
- snd_printdd("pcxhr_close chip%d subs%d\n", chip->chip_idx, subs->number);
+ snd_printdd("pcxhr_close chip%d subs%d\n",
+ chip->chip_idx, subs->number);
/* sample rate released */
if (--mgr->ref_count_rate == 0) {
- mgr->sample_rate = 0; /* the sample rate is no more locked */
+ mgr->sample_rate = 0; /* the sample rate is no more locked */
pcxhr_hardware_timer(mgr, 0); /* stop the DSP-timer */
}
@@ -1016,7 +1179,8 @@ static int pcxhr_chip_dev_free(struct snd_device *device)
/*
*/
-static int __devinit pcxhr_create(struct pcxhr_mgr *mgr, struct snd_card *card, int idx)
+static int __devinit pcxhr_create(struct pcxhr_mgr *mgr,
+ struct snd_card *card, int idx)
{
int err;
struct snd_pcxhr *chip;
@@ -1024,7 +1188,7 @@ static int __devinit pcxhr_create(struct pcxhr_mgr *mgr, struct snd_card *card,
.dev_free = pcxhr_chip_dev_free,
};
- mgr->chip[idx] = chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (! chip) {
snd_printk(KERN_ERR "cannot allocate chip\n");
return -ENOMEM;
@@ -1040,7 +1204,7 @@ static int __devinit pcxhr_create(struct pcxhr_mgr *mgr, struct snd_card *card,
if (idx < mgr->capture_chips) {
if (mgr->mono_capture)
- chip->nb_streams_capt = 2; /* 2 mono streams (left+right) */
+ chip->nb_streams_capt = 2; /* 2 mono streams */
else
chip->nb_streams_capt = 1; /* or 1 stereo stream */
}
@@ -1050,13 +1214,15 @@ static int __devinit pcxhr_create(struct pcxhr_mgr *mgr, struct snd_card *card,
return err;
}
+ mgr->chip[idx] = chip;
snd_card_set_dev(card, &mgr->pci->dev);
return 0;
}
/* proc interface */
-static void pcxhr_proc_info(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
+static void pcxhr_proc_info(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
struct snd_pcxhr *chip = entry->private_data;
struct pcxhr_mgr *mgr = chip->mgr;
@@ -1069,8 +1235,10 @@ static void pcxhr_proc_info(struct snd_info_entry *entry, struct snd_info_buffer
short ver_maj = (mgr->dsp_version >> 16) & 0xff;
short ver_min = (mgr->dsp_version >> 8) & 0xff;
short ver_build = mgr->dsp_version & 0xff;
- snd_iprintf(buffer, "module version %s\n", PCXHR_DRIVER_VERSION_STRING);
- snd_iprintf(buffer, "dsp version %d.%d.%d\n", ver_maj, ver_min, ver_build);
+ snd_iprintf(buffer, "module version %s\n",
+ PCXHR_DRIVER_VERSION_STRING);
+ snd_iprintf(buffer, "dsp version %d.%d.%d\n",
+ ver_maj, ver_min, ver_build);
if (mgr->board_has_analog)
snd_iprintf(buffer, "analog io available\n");
else
@@ -1084,18 +1252,22 @@ static void pcxhr_proc_info(struct snd_info_entry *entry, struct snd_info_buffer
if (ref > 0) {
if (mgr->sample_rate_real != 0 &&
mgr->sample_rate_real != 48000) {
- ref = (ref * 48000) / mgr->sample_rate_real;
- if (mgr->sample_rate_real >= PCXHR_IRQ_TIMER_FREQ)
+ ref = (ref * 48000) /
+ mgr->sample_rate_real;
+ if (mgr->sample_rate_real >=
+ PCXHR_IRQ_TIMER_FREQ)
ref *= 2;
}
cur = 100 - (100 * cur) / ref;
snd_iprintf(buffer, "cpu load %d%%\n", cur);
- snd_iprintf(buffer, "buffer pool %d/%d kWords\n",
+ snd_iprintf(buffer, "buffer pool %d/%d\n",
rmh.stat[2], rmh.stat[3]);
}
}
- snd_iprintf(buffer, "dma granularity : %d\n", PCXHR_GRANULARITY);
- snd_iprintf(buffer, "dsp time errors : %d\n", mgr->dsp_time_err);
+ snd_iprintf(buffer, "dma granularity : %d\n",
+ mgr->granularity);
+ snd_iprintf(buffer, "dsp time errors : %d\n",
+ mgr->dsp_time_err);
snd_iprintf(buffer, "dsp async pipe xrun errors : %d\n",
mgr->async_err_pipe_xrun);
snd_iprintf(buffer, "dsp async stream xrun errors : %d\n",
@@ -1110,33 +1282,52 @@ static void pcxhr_proc_info(struct snd_info_entry *entry, struct snd_info_buffer
rmh.cmd_idx = CMD_LAST_INDEX;
if( ! pcxhr_send_msg(mgr, &rmh) ) {
int i;
+ if (rmh.stat_len > 8)
+ rmh.stat_len = 8;
for (i = 0; i < rmh.stat_len; i++)
- snd_iprintf(buffer, "debug[%02d] = %06x\n", i, rmh.stat[i]);
+ snd_iprintf(buffer, "debug[%02d] = %06x\n",
+ i, rmh.stat[i]);
}
} else
snd_iprintf(buffer, "no firmware loaded\n");
snd_iprintf(buffer, "\n");
}
-static void pcxhr_proc_sync(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
+static void pcxhr_proc_sync(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
struct snd_pcxhr *chip = entry->private_data;
struct pcxhr_mgr *mgr = chip->mgr;
- static char *texts[7] = {
- "Internal", "Word", "AES Sync", "AES 1", "AES 2", "AES 3", "AES 4"
+ static const char *textsHR22[3] = {
+ "Internal", "AES Sync", "AES 1"
+ };
+ static const char *textsPCXHR[7] = {
+ "Internal", "Word", "AES Sync",
+ "AES 1", "AES 2", "AES 3", "AES 4"
};
+ const char **texts;
+ int max_clock;
+ if (mgr->is_hr_stereo) {
+ texts = textsHR22;
+ max_clock = HR22_CLOCK_TYPE_MAX;
+ } else {
+ texts = textsPCXHR;
+ max_clock = PCXHR_CLOCK_TYPE_MAX;
+ }
snd_iprintf(buffer, "\n%s\n", mgr->longname);
- snd_iprintf(buffer, "Current Sample Clock\t: %s\n", texts[mgr->cur_clock_type]);
- snd_iprintf(buffer, "Current Sample Rate\t= %d\n", mgr->sample_rate_real);
-
+ snd_iprintf(buffer, "Current Sample Clock\t: %s\n",
+ texts[mgr->cur_clock_type]);
+ snd_iprintf(buffer, "Current Sample Rate\t= %d\n",
+ mgr->sample_rate_real);
/* commands available when embedded DSP is running */
if (mgr->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_MAIN_INDEX)) {
int i, err, sample_rate;
- for (i = PCXHR_CLOCK_TYPE_WORD_CLOCK; i< (3 + mgr->capture_chips); i++) {
+ for (i = 1; i <= max_clock; i++) {
err = pcxhr_get_external_clock(mgr, i, &sample_rate);
if (err)
break;
- snd_iprintf(buffer, "%s Clock\t\t= %d\n", texts[i], sample_rate);
+ snd_iprintf(buffer, "%s Clock\t\t= %d\n",
+ texts[i], sample_rate);
}
} else
snd_iprintf(buffer, "no firmware loaded\n");
@@ -1194,7 +1385,8 @@ static int pcxhr_free(struct pcxhr_mgr *mgr)
/*
* probe function - creates the card manager
*/
-static int __devinit pcxhr_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
+static int __devinit pcxhr_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
static int dev;
struct pcxhr_mgr *mgr;
@@ -1217,7 +1409,8 @@ static int __devinit pcxhr_probe(struct pci_dev *pci, const struct pci_device_id
/* check if we can restrict PCI DMA transfers to 32 bits */
if (pci_set_dma_mask(pci, DMA_32BIT_MASK) < 0) {
- snd_printk(KERN_ERR "architecture does not support 32bit PCI busmaster DMA\n");
+ snd_printk(KERN_ERR "architecture does not support "
+ "32bit PCI busmaster DMA\n");
pci_disable_device(pci);
return -ENXIO;
}
@@ -1229,13 +1422,30 @@ static int __devinit pcxhr_probe(struct pci_dev *pci, const struct pci_device_id
return -ENOMEM;
}
- if (snd_BUG_ON(pci_id->driver_data >= PCI_ID_LAST))
+ if (snd_BUG_ON(pci_id->driver_data >= PCI_ID_LAST)) {
+ kfree(mgr);
+ pci_disable_device(pci);
return -ENODEV;
- card_name = pcxhr_board_params[pci_id->driver_data].board_name;
- mgr->playback_chips = pcxhr_board_params[pci_id->driver_data].playback_chips;
- mgr->capture_chips = pcxhr_board_params[pci_id->driver_data].capture_chips;
- mgr->firmware_num = pcxhr_board_params[pci_id->driver_data].firmware_num;
+ }
+ card_name =
+ pcxhr_board_params[pci_id->driver_data].board_name;
+ mgr->playback_chips =
+ pcxhr_board_params[pci_id->driver_data].playback_chips;
+ mgr->capture_chips =
+ pcxhr_board_params[pci_id->driver_data].capture_chips;
+ mgr->fw_file_set =
+ pcxhr_board_params[pci_id->driver_data].fw_file_set;
+ mgr->firmware_num =
+ pcxhr_board_params[pci_id->driver_data].firmware_num;
mgr->mono_capture = mono[dev];
+ mgr->is_hr_stereo = (mgr->playback_chips == 1);
+ mgr->board_has_aes1 = PCXHR_BOARD_HAS_AES1(mgr);
+ mgr->board_aes_in_192k = !PCXHR_BOARD_AESIN_NO_192K(mgr);
+
+ if (mgr->is_hr_stereo)
+ mgr->granularity = PCXHR_GRANULARITY_HR22;
+ else
+ mgr->granularity = PCXHR_GRANULARITY;
/* resource assignment */
if ((err = pci_request_regions(pci, card_name)) < 0) {
@@ -1258,7 +1468,8 @@ static int __devinit pcxhr_probe(struct pci_dev *pci, const struct pci_device_id
mgr->irq = pci->irq;
sprintf(mgr->shortname, "Digigram %s", card_name);
- sprintf(mgr->longname, "%s at 0x%lx & 0x%lx, 0x%lx irq %i", mgr->shortname,
+ sprintf(mgr->longname, "%s at 0x%lx & 0x%lx, 0x%lx irq %i",
+ mgr->shortname,
mgr->port[0], mgr->port[1], mgr->port[2], mgr->irq);
/* ISR spinlock */
@@ -1269,10 +1480,14 @@ static int __devinit pcxhr_probe(struct pci_dev *pci, const struct pci_device_id
mutex_init(&mgr->setup_mutex);
/* init taslket */
- tasklet_init(&mgr->msg_taskq, pcxhr_msg_tasklet, (unsigned long) mgr);
- tasklet_init(&mgr->trigger_taskq, pcxhr_trigger_tasklet, (unsigned long) mgr);
+ tasklet_init(&mgr->msg_taskq, pcxhr_msg_tasklet,
+ (unsigned long) mgr);
+ tasklet_init(&mgr->trigger_taskq, pcxhr_trigger_tasklet,
+ (unsigned long) mgr);
+
mgr->prmh = kmalloc(sizeof(*mgr->prmh) +
- sizeof(u32) * (PCXHR_SIZE_MAX_LONG_STATUS - PCXHR_SIZE_MAX_STATUS),
+ sizeof(u32) * (PCXHR_SIZE_MAX_LONG_STATUS -
+ PCXHR_SIZE_MAX_STATUS),
GFP_KERNEL);
if (! mgr->prmh) {
pcxhr_free(mgr);
@@ -1293,7 +1508,8 @@ static int __devinit pcxhr_probe(struct pci_dev *pci, const struct pci_device_id
else
idx = index[dev] + i;
- snprintf(tmpid, sizeof(tmpid), "%s-%d", id[dev] ? id[dev] : card_name, i);
+ snprintf(tmpid, sizeof(tmpid), "%s-%d",
+ id[dev] ? id[dev] : card_name, i);
card = snd_card_new(idx, tmpid, THIS_MODULE, 0);
if (! card) {
@@ -1307,6 +1523,7 @@ static int __devinit pcxhr_probe(struct pci_dev *pci, const struct pci_device_id
sprintf(card->longname, "%s [PCM #%d]", mgr->longname, i);
if ((err = pcxhr_create(mgr, card, i)) < 0) {
+ snd_card_free(card);
pcxhr_free(mgr);
return err;
}
diff --git a/sound/pci/pcxhr/pcxhr.h b/sound/pci/pcxhr/pcxhr.h
index 652064787a5..84131a916c9 100644
--- a/sound/pci/pcxhr/pcxhr.h
+++ b/sound/pci/pcxhr/pcxhr.h
@@ -27,15 +27,18 @@
#include <linux/mutex.h>
#include <sound/pcm.h>
-#define PCXHR_DRIVER_VERSION 0x000804 /* 0.8.4 */
-#define PCXHR_DRIVER_VERSION_STRING "0.8.4" /* 0.8.4 */
+#define PCXHR_DRIVER_VERSION 0x000905 /* 0.9.5 */
+#define PCXHR_DRIVER_VERSION_STRING "0.9.5" /* 0.9.5 */
-#define PCXHR_MAX_CARDS 6
-#define PCXHR_PLAYBACK_STREAMS 4
+#define PCXHR_MAX_CARDS 6
+#define PCXHR_PLAYBACK_STREAMS 4
-#define PCXHR_GRANULARITY 96 /* transfer granularity (should be min 96 and multiple of 48) */
-#define PCXHR_GRANULARITY_MIN 96 /* transfer granularity of pipes and the dsp time (MBOX4) */
+#define PCXHR_GRANULARITY 96 /* min 96 and multiple of 48 */
+/* transfer granularity of pipes and the dsp time (MBOX4) */
+#define PCXHR_GRANULARITY_MIN 96
+/* TODO : granularity could be 64 or 128 */
+#define PCXHR_GRANULARITY_HR22 192 /* granularity for stereo cards */
struct snd_pcxhr;
struct pcxhr_mgr;
@@ -51,6 +54,11 @@ enum pcxhr_clock_type {
PCXHR_CLOCK_TYPE_AES_2,
PCXHR_CLOCK_TYPE_AES_3,
PCXHR_CLOCK_TYPE_AES_4,
+ PCXHR_CLOCK_TYPE_MAX = PCXHR_CLOCK_TYPE_AES_4,
+ HR22_CLOCK_TYPE_INTERNAL = PCXHR_CLOCK_TYPE_INTERNAL,
+ HR22_CLOCK_TYPE_AES_SYNC,
+ HR22_CLOCK_TYPE_AES_1,
+ HR22_CLOCK_TYPE_MAX = HR22_CLOCK_TYPE_AES_1,
};
struct pcxhr_mgr {
@@ -61,6 +69,8 @@ struct pcxhr_mgr {
int irq;
+ int granularity;
+
/* card access with 1 mem bar and 2 io bar's */
unsigned long port[3];
@@ -83,11 +93,16 @@ struct pcxhr_mgr {
/* hardware interface */
unsigned int dsp_loaded; /* bit flags of loaded dsp indices */
unsigned int dsp_version; /* read from embedded once firmware is loaded */
- int board_has_analog; /* if 0 the board is digital only */
- int mono_capture; /* if 1 the board does mono capture */
- int playback_chips; /* 4 or 6 */
- int capture_chips; /* 4 or 1 */
- int firmware_num; /* 41 or 42 */
+ int playback_chips;
+ int capture_chips;
+ int fw_file_set;
+ int firmware_num;
+ int is_hr_stereo:1;
+ int board_has_aes1:1; /* if 1 board has AES1 plug and SRC */
+ int board_has_analog:1; /* if 0 the board is digital only */
+ int board_has_mic:1; /* if 1 the board has microphone input */
+ int board_aes_in_192k:1;/* if 1 the aes input plugs do support 192kHz */
+ int mono_capture:1; /* if 1 the board does mono capture */
struct snd_dma_buffer hostport;
@@ -106,6 +121,9 @@ struct pcxhr_mgr {
int async_err_stream_xrun;
int async_err_pipe_xrun;
int async_err_other_last;
+
+ unsigned char xlx_cfg; /* copy of PCXHR_XLX_CFG register */
+ unsigned char xlx_selmic; /* copy of PCXHR_XLX_SELMIC register */
};
@@ -155,24 +173,30 @@ struct snd_pcxhr {
struct snd_pcm *pcm; /* PCM */
- struct pcxhr_pipe playback_pipe; /* 1 stereo pipe only */
- struct pcxhr_pipe capture_pipe[2]; /* 1 stereo pipe or 2 mono pipes */
+ struct pcxhr_pipe playback_pipe; /* 1 stereo pipe only */
+ struct pcxhr_pipe capture_pipe[2]; /* 1 stereo or 2 mono pipes */
struct pcxhr_stream playback_stream[PCXHR_PLAYBACK_STREAMS];
- struct pcxhr_stream capture_stream[2]; /* 1 stereo stream or 2 mono streams */
+ struct pcxhr_stream capture_stream[2]; /* 1 stereo or 2 mono streams */
int nb_streams_play;
int nb_streams_capt;
- int analog_playback_active[2]; /* Mixer : Master Playback active (!mute) */
- int analog_playback_volume[2]; /* Mixer : Master Playback Volume */
- int analog_capture_volume[2]; /* Mixer : Master Capture Volume */
- int digital_playback_active[PCXHR_PLAYBACK_STREAMS][2]; /* Mixer : Digital Playback Active [streams][stereo]*/
- int digital_playback_volume[PCXHR_PLAYBACK_STREAMS][2]; /* Mixer : Digital Playback Volume [streams][stereo]*/
- int digital_capture_volume[2]; /* Mixer : Digital Capture Volume [stereo] */
- int monitoring_active[2]; /* Mixer : Monitoring Active */
- int monitoring_volume[2]; /* Mixer : Monitoring Volume */
- int audio_capture_source; /* Mixer : Audio Capture Source */
- unsigned char aes_bits[5]; /* Mixer : IEC958_AES bits */
+ int analog_playback_active[2]; /* Mixer : Master Playback !mute */
+ int analog_playback_volume[2]; /* Mixer : Master Playback Volume */
+ int analog_capture_volume[2]; /* Mixer : Master Capture Volume */
+ int digital_playback_active[PCXHR_PLAYBACK_STREAMS][2];
+ int digital_playback_volume[PCXHR_PLAYBACK_STREAMS][2];
+ int digital_capture_volume[2]; /* Mixer : Digital Capture Volume */
+ int monitoring_active[2]; /* Mixer : Monitoring Active */
+ int monitoring_volume[2]; /* Mixer : Monitoring Volume */
+ int audio_capture_source; /* Mixer : Audio Capture Source */
+ int mic_volume; /* used by cards with MIC only */
+ int mic_boost; /* used by cards with MIC only */
+ int mic_active; /* used by cards with MIC only */
+ int analog_capture_active; /* used by cards with MIC only */
+ int phantom_power; /* used by cards with MIC only */
+
+ unsigned char aes_bits[5]; /* Mixer : IEC958_AES bits */
};
struct pcxhr_hostport
@@ -184,6 +208,8 @@ struct pcxhr_hostport
/* exported */
int pcxhr_create_pcm(struct snd_pcxhr *chip);
int pcxhr_set_clock(struct pcxhr_mgr *mgr, unsigned int rate);
-int pcxhr_get_external_clock(struct pcxhr_mgr *mgr, enum pcxhr_clock_type clock_type, int *sample_rate);
+int pcxhr_get_external_clock(struct pcxhr_mgr *mgr,
+ enum pcxhr_clock_type clock_type,
+ int *sample_rate);
#endif /* __SOUND_PCXHR_H */
diff --git a/sound/pci/pcxhr/pcxhr_core.c b/sound/pci/pcxhr/pcxhr_core.c
index 7143259cfe3..833e7180ad2 100644
--- a/sound/pci/pcxhr/pcxhr_core.c
+++ b/sound/pci/pcxhr/pcxhr_core.c
@@ -132,13 +132,15 @@ static int pcxhr_check_reg_bit(struct pcxhr_mgr *mgr, unsigned int reg,
*read = PCXHR_INPB(mgr, reg);
if ((*read & mask) == bit) {
if (i > 100)
- snd_printdd("ATTENTION! check_reg(%x) loopcount=%d\n",
+ snd_printdd("ATTENTION! check_reg(%x) "
+ "loopcount=%d\n",
reg, i);
return 0;
}
i++;
} while (time_after_eq(end_time, jiffies));
- snd_printk(KERN_ERR "pcxhr_check_reg_bit: timeout, reg=%x, mask=0x%x, val=0x%x\n",
+ snd_printk(KERN_ERR
+ "pcxhr_check_reg_bit: timeout, reg=%x, mask=0x%x, val=%x\n",
reg, mask, *read);
return -EIO;
}
@@ -159,18 +161,22 @@ static int pcxhr_check_reg_bit(struct pcxhr_mgr *mgr, unsigned int reg,
#define PCXHR_IT_TEST_XILINX (0x0000003C | PCXHR_MASK_IT_HF1 | \
PCXHR_MASK_IT_MANAGE_HF5)
#define PCXHR_IT_DOWNLOAD_BOOT (0x0000000C | PCXHR_MASK_IT_HF1 | \
- PCXHR_MASK_IT_MANAGE_HF5 | PCXHR_MASK_IT_WAIT)
+ PCXHR_MASK_IT_MANAGE_HF5 | \
+ PCXHR_MASK_IT_WAIT)
#define PCXHR_IT_RESET_BOARD_FUNC (0x0000000C | PCXHR_MASK_IT_HF0 | \
- PCXHR_MASK_IT_MANAGE_HF5 | PCXHR_MASK_IT_WAIT_EXTRA)
+ PCXHR_MASK_IT_MANAGE_HF5 | \
+ PCXHR_MASK_IT_WAIT_EXTRA)
#define PCXHR_IT_DOWNLOAD_DSP (0x0000000C | \
- PCXHR_MASK_IT_MANAGE_HF5 | PCXHR_MASK_IT_WAIT)
+ PCXHR_MASK_IT_MANAGE_HF5 | \
+ PCXHR_MASK_IT_WAIT)
#define PCXHR_IT_DEBUG (0x0000005A | PCXHR_MASK_IT_NO_HF0_HF1)
#define PCXHR_IT_RESET_SEMAPHORE (0x0000005C | PCXHR_MASK_IT_NO_HF0_HF1)
#define PCXHR_IT_MESSAGE (0x00000074 | PCXHR_MASK_IT_NO_HF0_HF1)
#define PCXHR_IT_RESET_CHK (0x00000076 | PCXHR_MASK_IT_NO_HF0_HF1)
#define PCXHR_IT_UPDATE_RBUFFER (0x00000078 | PCXHR_MASK_IT_NO_HF0_HF1)
-static int pcxhr_send_it_dsp(struct pcxhr_mgr *mgr, unsigned int itdsp, int atomic)
+static int pcxhr_send_it_dsp(struct pcxhr_mgr *mgr,
+ unsigned int itdsp, int atomic)
{
int err;
unsigned char reg;
@@ -178,17 +184,21 @@ static int pcxhr_send_it_dsp(struct pcxhr_mgr *mgr, unsigned int itdsp, int atom
if (itdsp & PCXHR_MASK_IT_MANAGE_HF5) {
/* clear hf5 bit */
PCXHR_OUTPL(mgr, PCXHR_PLX_MBOX0,
- PCXHR_INPL(mgr, PCXHR_PLX_MBOX0) & ~PCXHR_MBOX0_HF5);
+ PCXHR_INPL(mgr, PCXHR_PLX_MBOX0) &
+ ~PCXHR_MBOX0_HF5);
}
if ((itdsp & PCXHR_MASK_IT_NO_HF0_HF1) == 0) {
- reg = PCXHR_ICR_HI08_RREQ | PCXHR_ICR_HI08_TREQ | PCXHR_ICR_HI08_HDRQ;
+ reg = (PCXHR_ICR_HI08_RREQ |
+ PCXHR_ICR_HI08_TREQ |
+ PCXHR_ICR_HI08_HDRQ);
if (itdsp & PCXHR_MASK_IT_HF0)
reg |= PCXHR_ICR_HI08_HF0;
if (itdsp & PCXHR_MASK_IT_HF1)
reg |= PCXHR_ICR_HI08_HF1;
PCXHR_OUTPB(mgr, PCXHR_DSP_ICR, reg);
}
- reg = (unsigned char)(((itdsp & PCXHR_MASK_EXTRA_INFO) >> 1) | PCXHR_CVR_HI08_HC);
+ reg = (unsigned char)(((itdsp & PCXHR_MASK_EXTRA_INFO) >> 1) |
+ PCXHR_CVR_HI08_HC);
PCXHR_OUTPB(mgr, PCXHR_DSP_CVR, reg);
if (itdsp & PCXHR_MASK_IT_WAIT) {
if (atomic)
@@ -211,10 +221,14 @@ static int pcxhr_send_it_dsp(struct pcxhr_mgr *mgr, unsigned int itdsp, int atom
}
if (itdsp & PCXHR_MASK_IT_MANAGE_HF5) {
/* wait for hf5 bit */
- err = pcxhr_check_reg_bit(mgr, PCXHR_PLX_MBOX0, PCXHR_MBOX0_HF5,
- PCXHR_MBOX0_HF5, PCXHR_TIMEOUT_DSP, &reg);
+ err = pcxhr_check_reg_bit(mgr, PCXHR_PLX_MBOX0,
+ PCXHR_MBOX0_HF5,
+ PCXHR_MBOX0_HF5,
+ PCXHR_TIMEOUT_DSP,
+ &reg);
if (err) {
- snd_printk(KERN_ERR "pcxhr_send_it_dsp : TIMEOUT HF5\n");
+ snd_printk(KERN_ERR
+ "pcxhr_send_it_dsp : TIMEOUT HF5\n");
return err;
}
}
@@ -263,7 +277,8 @@ void pcxhr_enable_dsp(struct pcxhr_mgr *mgr)
/*
* load the xilinx image
*/
-int pcxhr_load_xilinx_binary(struct pcxhr_mgr *mgr, const struct firmware *xilinx, int second)
+int pcxhr_load_xilinx_binary(struct pcxhr_mgr *mgr,
+ const struct firmware *xilinx, int second)
{
unsigned int i;
unsigned int chipsc;
@@ -274,7 +289,9 @@ int pcxhr_load_xilinx_binary(struct pcxhr_mgr *mgr, const struct firmware *xilin
/* test first xilinx */
chipsc = PCXHR_INPL(mgr, PCXHR_PLX_CHIPSC);
/* REV01 cards do not support the PCXHR_CHIPSC_GPI_USERI bit anymore */
- /* this bit will always be 1; no possibility to test presence of first xilinx */
+ /* this bit will always be 1;
+ * no possibility to test presence of first xilinx
+ */
if(second) {
if ((chipsc & PCXHR_CHIPSC_GPI_USERI) == 0) {
snd_printk(KERN_ERR "error loading first xilinx\n");
@@ -290,7 +307,8 @@ int pcxhr_load_xilinx_binary(struct pcxhr_mgr *mgr, const struct firmware *xilin
data = *image;
mask = 0x80;
while (mask) {
- chipsc &= ~(PCXHR_CHIPSC_DATA_CLK | PCXHR_CHIPSC_DATA_IN);
+ chipsc &= ~(PCXHR_CHIPSC_DATA_CLK |
+ PCXHR_CHIPSC_DATA_IN);
if (data & mask)
chipsc |= PCXHR_CHIPSC_DATA_IN;
PCXHR_OUTPL(mgr, PCXHR_PLX_CHIPSC, chipsc);
@@ -330,15 +348,20 @@ static int pcxhr_download_dsp(struct pcxhr_mgr *mgr, const struct firmware *dsp)
data = dsp->data + i;
if (i == 0) {
/* test data header consistency */
- len = (unsigned int)((data[0]<<16) + (data[1]<<8) + data[2]);
- if (len && dsp->size != (len + 2) * 3)
+ len = (unsigned int)((data[0]<<16) +
+ (data[1]<<8) +
+ data[2]);
+ if (len && (dsp->size != (len + 2) * 3))
return -EINVAL;
}
/* wait DSP ready for new transfer */
- err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_TRDY,
- PCXHR_ISR_HI08_TRDY, PCXHR_TIMEOUT_DSP, &dummy);
+ err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR,
+ PCXHR_ISR_HI08_TRDY,
+ PCXHR_ISR_HI08_TRDY,
+ PCXHR_TIMEOUT_DSP, &dummy);
if (err) {
- snd_printk(KERN_ERR "dsp loading error at position %d\n", i);
+ snd_printk(KERN_ERR
+ "dsp loading error at position %d\n", i);
return err;
}
/* send host data */
@@ -357,7 +380,8 @@ static int pcxhr_download_dsp(struct pcxhr_mgr *mgr, const struct firmware *dsp)
/*
* load the eeprom image
*/
-int pcxhr_load_eeprom_binary(struct pcxhr_mgr *mgr, const struct firmware *eeprom)
+int pcxhr_load_eeprom_binary(struct pcxhr_mgr *mgr,
+ const struct firmware *eeprom)
{
int err;
unsigned char reg;
@@ -365,7 +389,9 @@ int pcxhr_load_eeprom_binary(struct pcxhr_mgr *mgr, const struct firmware *eepro
/* init value of the ICR register */
reg = PCXHR_ICR_HI08_RREQ | PCXHR_ICR_HI08_TREQ | PCXHR_ICR_HI08_HDRQ;
if (PCXHR_INPL(mgr, PCXHR_PLX_MBOX0) & PCXHR_MBOX0_BOOT_HERE) {
- /* no need to load the eeprom binary, but init the HI08 interface */
+ /* no need to load the eeprom binary,
+ * but init the HI08 interface
+ */
PCXHR_OUTPB(mgr, PCXHR_DSP_ICR, reg | PCXHR_ICR_HI08_INIT);
msleep(PCXHR_WAIT_DEFAULT);
PCXHR_OUTPB(mgr, PCXHR_DSP_ICR, reg);
@@ -429,8 +455,10 @@ int pcxhr_load_dsp_binary(struct pcxhr_mgr *mgr, const struct firmware *dsp)
if (err)
return err;
/* wait for chk bit */
- return pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_CHK,
- PCXHR_ISR_HI08_CHK, PCXHR_TIMEOUT_DSP, &dummy);
+ return pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR,
+ PCXHR_ISR_HI08_CHK,
+ PCXHR_ISR_HI08_CHK,
+ PCXHR_TIMEOUT_DSP, &dummy);
}
@@ -443,8 +471,8 @@ struct pcxhr_cmd_info {
/* RMH status type */
enum {
RMH_SSIZE_FIXED = 0, /* status size fix (st_length = 0..x) */
- RMH_SSIZE_ARG = 1, /* status size given in the LSB byte (used with st_length = 1) */
- RMH_SSIZE_MASK = 2, /* status size given in bitmask (used with st_length = 1) */
+ RMH_SSIZE_ARG = 1, /* status size given in the LSB byte */
+ RMH_SSIZE_MASK = 2, /* status size given in bitmask */
};
/*
@@ -474,7 +502,7 @@ static struct pcxhr_cmd_info pcxhr_dsp_cmds[] = {
[CMD_UPDATE_R_BUFFERS] = { 0x840000, 0, RMH_SSIZE_FIXED },
[CMD_FORMAT_STREAM_OUT] = { 0x860000, 0, RMH_SSIZE_FIXED },
[CMD_FORMAT_STREAM_IN] = { 0x870000, 0, RMH_SSIZE_FIXED },
-[CMD_STREAM_SAMPLE_COUNT] = { 0x902000, 2, RMH_SSIZE_FIXED }, /* stat_len = nb_streams * 2 */
+[CMD_STREAM_SAMPLE_COUNT] = { 0x902000, 2, RMH_SSIZE_FIXED },
[CMD_AUDIO_LEVEL_ADJUST] = { 0xc22000, 0, RMH_SSIZE_FIXED },
};
@@ -524,10 +552,13 @@ static int pcxhr_read_rmh_status(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh)
for (i = 0; i < rmh->stat_len; i++) {
/* wait for receiver full */
- err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_RXDF,
- PCXHR_ISR_HI08_RXDF, PCXHR_TIMEOUT_DSP, &reg);
+ err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR,
+ PCXHR_ISR_HI08_RXDF,
+ PCXHR_ISR_HI08_RXDF,
+ PCXHR_TIMEOUT_DSP, &reg);
if (err) {
- snd_printk(KERN_ERR "ERROR RMH stat: ISR:RXDF=1 (ISR = %x; i=%d )\n",
+ snd_printk(KERN_ERR "ERROR RMH stat: "
+ "ISR:RXDF=1 (ISR = %x; i=%d )\n",
reg, i);
return err;
}
@@ -537,10 +568,10 @@ static int pcxhr_read_rmh_status(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh)
data |= PCXHR_INPB(mgr, PCXHR_DSP_TXL);
/* need to update rmh->stat_len on the fly ?? */
- if (i==0) {
+ if (!i) {
if (rmh->dsp_stat != RMH_SSIZE_FIXED) {
if (rmh->dsp_stat == RMH_SSIZE_ARG) {
- rmh->stat_len = (u16)(data & 0x0000ff) + 1;
+ rmh->stat_len = (data & 0x0000ff) + 1;
data &= 0xffff00;
} else {
/* rmh->dsp_stat == RMH_SSIZE_MASK */
@@ -562,7 +593,8 @@ static int pcxhr_read_rmh_status(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh)
rmh->stat[i] = data;
}
if (rmh->stat_len > max_stat_len) {
- snd_printdd("PCXHR : rmh->stat_len=%x too big\n", rmh->stat_len);
+ snd_printdd("PCXHR : rmh->stat_len=%x too big\n",
+ rmh->stat_len);
rmh->stat_len = max_stat_len;
}
return 0;
@@ -605,7 +637,8 @@ static int pcxhr_send_msg_nolock(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh)
data &= 0xff7fff; /* MASK_1_WORD_COMMAND */
#ifdef CONFIG_SND_DEBUG_VERBOSE
if (rmh->cmd_idx < CMD_LAST_INDEX)
- snd_printdd("MSG cmd[0]=%x (%s)\n", data, cmd_names[rmh->cmd_idx]);
+ snd_printdd("MSG cmd[0]=%x (%s)\n",
+ data, cmd_names[rmh->cmd_idx]);
#endif
err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_TRDY,
@@ -619,8 +652,10 @@ static int pcxhr_send_msg_nolock(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh)
if (rmh->cmd_len > 1) {
/* send length */
data = rmh->cmd_len - 1;
- err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_TRDY,
- PCXHR_ISR_HI08_TRDY, PCXHR_TIMEOUT_DSP, &reg);
+ err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR,
+ PCXHR_ISR_HI08_TRDY,
+ PCXHR_ISR_HI08_TRDY,
+ PCXHR_TIMEOUT_DSP, &reg);
if (err)
return err;
PCXHR_OUTPB(mgr, PCXHR_DSP_TXH, (data>>16)&0xFF);
@@ -653,8 +688,10 @@ static int pcxhr_send_msg_nolock(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh)
/* test status ISR */
if (reg & PCXHR_ISR_HI08_ERR) {
/* ERROR, wait for receiver full */
- err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_RXDF,
- PCXHR_ISR_HI08_RXDF, PCXHR_TIMEOUT_DSP, &reg);
+ err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR,
+ PCXHR_ISR_HI08_RXDF,
+ PCXHR_ISR_HI08_RXDF,
+ PCXHR_TIMEOUT_DSP, &reg);
if (err) {
snd_printk(KERN_ERR "ERROR RMH: ISR:RXDF=1 (ISR = %x)\n", reg);
return err;
@@ -663,7 +700,8 @@ static int pcxhr_send_msg_nolock(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh)
data = PCXHR_INPB(mgr, PCXHR_DSP_TXH) << 16;
data |= PCXHR_INPB(mgr, PCXHR_DSP_TXM) << 8;
data |= PCXHR_INPB(mgr, PCXHR_DSP_TXL);
- snd_printk(KERN_ERR "ERROR RMH(%d): 0x%x\n", rmh->cmd_idx, data);
+ snd_printk(KERN_ERR "ERROR RMH(%d): 0x%x\n",
+ rmh->cmd_idx, data);
err = -EINVAL;
} else {
/* read the response data */
@@ -732,8 +770,9 @@ int pcxhr_send_msg(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh)
static inline int pcxhr_pipes_running(struct pcxhr_mgr *mgr)
{
int start_mask = PCXHR_INPL(mgr, PCXHR_PLX_MBOX2);
- /* least segnificant 12 bits are the pipe states for the playback audios */
- /* next 12 bits are the pipe states for the capture audios
+ /* least segnificant 12 bits are the pipe states
+ * for the playback audios
+ * next 12 bits are the pipe states for the capture audios
* (PCXHR_PIPE_STATE_CAPTURE_OFFSET)
*/
start_mask &= 0xffffff;
@@ -744,7 +783,8 @@ static inline int pcxhr_pipes_running(struct pcxhr_mgr *mgr)
#define PCXHR_PIPE_STATE_CAPTURE_OFFSET 12
#define MAX_WAIT_FOR_DSP 20
-static int pcxhr_prepair_pipe_start(struct pcxhr_mgr *mgr, int audio_mask, int *retry)
+static int pcxhr_prepair_pipe_start(struct pcxhr_mgr *mgr,
+ int audio_mask, int *retry)
{
struct pcxhr_rmh rmh;
int err;
@@ -760,17 +800,20 @@ static int pcxhr_prepair_pipe_start(struct pcxhr_mgr *mgr, int audio_mask, int *
} else {
/* can start capture pipe */
pcxhr_set_pipe_cmd_params(&rmh, 1, audio -
- PCXHR_PIPE_STATE_CAPTURE_OFFSET,
- 0, 0);
+ PCXHR_PIPE_STATE_CAPTURE_OFFSET,
+ 0, 0);
}
err = pcxhr_send_msg(mgr, &rmh);
if (err) {
snd_printk(KERN_ERR
- "error pipe start (CMD_CAN_START_PIPE) err=%x!\n",
+ "error pipe start "
+ "(CMD_CAN_START_PIPE) err=%x!\n",
err);
return err;
}
- /* if the pipe couldn't be prepaired for start, retry it later */
+ /* if the pipe couldn't be prepaired for start,
+ * retry it later
+ */
if (rmh.stat[0] == 0)
*retry |= (1<<audio);
}
@@ -795,14 +838,14 @@ static int pcxhr_stop_pipes(struct pcxhr_mgr *mgr, int audio_mask)
} else {
/* stop capture pipe */
pcxhr_set_pipe_cmd_params(&rmh, 1, audio -
- PCXHR_PIPE_STATE_CAPTURE_OFFSET,
- 0, 0);
+ PCXHR_PIPE_STATE_CAPTURE_OFFSET,
+ 0, 0);
}
err = pcxhr_send_msg(mgr, &rmh);
if (err) {
snd_printk(KERN_ERR
- "error pipe stop (CMD_STOP_PIPE) err=%x!\n",
- err);
+ "error pipe stop "
+ "(CMD_STOP_PIPE) err=%x!\n", err);
return err;
}
}
@@ -822,15 +865,16 @@ static int pcxhr_toggle_pipes(struct pcxhr_mgr *mgr, int audio_mask)
if (audio_mask & 1) {
pcxhr_init_rmh(&rmh, CMD_CONF_PIPE);
if (audio < PCXHR_PIPE_STATE_CAPTURE_OFFSET)
- pcxhr_set_pipe_cmd_params(&rmh, 0, 0, 0, 1 << audio);
+ pcxhr_set_pipe_cmd_params(&rmh, 0, 0, 0,
+ 1 << audio);
else
pcxhr_set_pipe_cmd_params(&rmh, 1, 0, 0,
1 << (audio - PCXHR_PIPE_STATE_CAPTURE_OFFSET));
err = pcxhr_send_msg(mgr, &rmh);
if (err) {
snd_printk(KERN_ERR
- "error pipe start (CMD_CONF_PIPE) err=%x!\n",
- err);
+ "error pipe start "
+ "(CMD_CONF_PIPE) err=%x!\n", err);
return err;
}
}
@@ -841,7 +885,9 @@ static int pcxhr_toggle_pipes(struct pcxhr_mgr *mgr, int audio_mask)
pcxhr_init_rmh(&rmh, CMD_SEND_IRQA);
err = pcxhr_send_msg(mgr, &rmh);
if (err) {
- snd_printk(KERN_ERR "error pipe start (CMD_SEND_IRQA) err=%x!\n", err );
+ snd_printk(KERN_ERR
+ "error pipe start (CMD_SEND_IRQA) err=%x!\n",
+ err);
return err;
}
return 0;
@@ -849,7 +895,8 @@ static int pcxhr_toggle_pipes(struct pcxhr_mgr *mgr, int audio_mask)
-int pcxhr_set_pipe_state(struct pcxhr_mgr *mgr, int playback_mask, int capture_mask, int start)
+int pcxhr_set_pipe_state(struct pcxhr_mgr *mgr, int playback_mask,
+ int capture_mask, int start)
{
int state, i, err;
int audio_mask;
@@ -858,21 +905,23 @@ int pcxhr_set_pipe_state(struct pcxhr_mgr *mgr, int playback_mask, int capture_m
struct timeval my_tv1, my_tv2;
do_gettimeofday(&my_tv1);
#endif
- audio_mask = (playback_mask | (capture_mask << PCXHR_PIPE_STATE_CAPTURE_OFFSET));
+ audio_mask = (playback_mask |
+ (capture_mask << PCXHR_PIPE_STATE_CAPTURE_OFFSET));
/* current pipe state (playback + record) */
state = pcxhr_pipes_running(mgr);
snd_printdd("pcxhr_set_pipe_state %s (mask %x current %x)\n",
start ? "START" : "STOP", audio_mask, state);
if (start) {
- audio_mask &= ~state; /* start only pipes that are not yet started */
+ /* start only pipes that are not yet started */
+ audio_mask &= ~state;
state = audio_mask;
for (i = 0; i < MAX_WAIT_FOR_DSP; i++) {
err = pcxhr_prepair_pipe_start(mgr, state, &state);
if (err)
return err;
if (state == 0)
- break; /* success, all pipes prepaired for start */
- mdelay(1); /* otherwise wait 1 millisecond and retry */
+ break; /* success, all pipes prepaired */
+ mdelay(1); /* wait 1 millisecond and retry */
}
} else {
audio_mask &= state; /* stop only pipes that are started */
@@ -891,7 +940,7 @@ int pcxhr_set_pipe_state(struct pcxhr_mgr *mgr, int playback_mask, int capture_m
if ((state & audio_mask) == (start ? audio_mask : 0))
break;
if (++i >= MAX_WAIT_FOR_DSP * 100) {
- snd_printk(KERN_ERR "error pipe start/stop (ED_NO_RESPONSE_AT_IRQA)\n");
+ snd_printk(KERN_ERR "error pipe start/stop\n");
return -EBUSY;
}
udelay(10); /* wait 10 microseconds */
@@ -918,7 +967,8 @@ int pcxhr_write_io_num_reg_cont(struct pcxhr_mgr *mgr, unsigned int mask,
spin_lock_irqsave(&mgr->msg_lock, flags);
if ((mgr->io_num_reg_cont & mask) == value) {
- snd_printdd("IO_NUM_REG_CONT mask %x already is set to %x\n", mask, value);
+ snd_printdd("IO_NUM_REG_CONT mask %x already is set to %x\n",
+ mask, value);
if (changed)
*changed = 0;
spin_unlock_irqrestore(&mgr->msg_lock, flags);
@@ -971,7 +1021,8 @@ static int pcxhr_handle_async_err(struct pcxhr_mgr *mgr, u32 err,
err = ((err >> 12) & 0xfff);
if (!err)
return 0;
- snd_printdd("CMD_ASYNC : Error %s %s Pipe %d err=%x\n", err_src_name[err_src],
+ snd_printdd("CMD_ASYNC : Error %s %s Pipe %d err=%x\n",
+ err_src_name[err_src],
is_capture ? "Record" : "Play", pipe, err);
if (err == 0xe01)
mgr->async_err_stream_xrun++;
@@ -996,6 +1047,13 @@ void pcxhr_msg_tasklet(unsigned long arg)
snd_printdd("TASKLET : PCXHR_IRQ_TIME_CODE event occured\n");
if (mgr->src_it_dsp & PCXHR_IRQ_NOTIFY)
snd_printdd("TASKLET : PCXHR_IRQ_NOTIFY event occured\n");
+ if (mgr->src_it_dsp & (PCXHR_IRQ_FREQ_CHANGE | PCXHR_IRQ_TIME_CODE)) {
+ /* clear events FREQ_CHANGE and TIME_CODE */
+ pcxhr_init_rmh(prmh, CMD_TEST_IT);
+ err = pcxhr_send_msg(mgr, prmh);
+ snd_printdd("CMD_TEST_IT : err=%x, stat=%x\n",
+ err, prmh->stat[0]);
+ }
if (mgr->src_it_dsp & PCXHR_IRQ_ASYNC) {
snd_printdd("TASKLET : PCXHR_IRQ_ASYNC event occured\n");
@@ -1005,18 +1063,22 @@ void pcxhr_msg_tasklet(unsigned long arg)
prmh->stat_len = PCXHR_SIZE_MAX_LONG_STATUS;
err = pcxhr_send_msg(mgr, prmh);
if (err)
- snd_printk(KERN_ERR "ERROR pcxhr_msg_tasklet=%x;\n", err);
+ snd_printk(KERN_ERR "ERROR pcxhr_msg_tasklet=%x;\n",
+ err);
i = 1;
while (i < prmh->stat_len) {
- int nb_audio = (prmh->stat[i] >> FIELD_SIZE) & MASK_FIRST_FIELD;
- int nb_stream = (prmh->stat[i] >> (2*FIELD_SIZE)) & MASK_FIRST_FIELD;
+ int nb_audio = ((prmh->stat[i] >> FIELD_SIZE) &
+ MASK_FIRST_FIELD);
+ int nb_stream = ((prmh->stat[i] >> (2*FIELD_SIZE)) &
+ MASK_FIRST_FIELD);
int pipe = prmh->stat[i] & MASK_FIRST_FIELD;
int is_capture = prmh->stat[i] & 0x400000;
u32 err2;
if (prmh->stat[i] & 0x800000) { /* if BIT_END */
snd_printdd("TASKLET : End%sPipe %d\n",
- is_capture ? "Record" : "Play", pipe);
+ is_capture ? "Record" : "Play",
+ pipe);
}
i++;
err2 = prmh->stat[i] ? prmh->stat[i] : prmh->stat[i+1];
@@ -1062,7 +1124,7 @@ static u_int64_t pcxhr_stream_read_position(struct pcxhr_mgr *mgr,
pcxhr_init_rmh(&rmh, CMD_STREAM_SAMPLE_COUNT);
pcxhr_set_pipe_cmd_params(&rmh, stream->pipe->is_capture,
stream->pipe->first_audio, 0, stream_mask);
- /* rmh.stat_len = 2; */ /* 2 resp data for each stream of the pipe */
+ /* rmh.stat_len = 2; */ /* 2 resp data for each stream of the pipe */
err = pcxhr_send_msg(mgr, &rmh);
if (err)
@@ -1072,18 +1134,21 @@ static u_int64_t pcxhr_stream_read_position(struct pcxhr_mgr *mgr,
hw_sample_count += (u_int64_t)rmh.stat[1];
snd_printdd("stream %c%d : abs samples real(%ld) timer(%ld)\n",
- stream->pipe->is_capture ? 'C':'P', stream->substream->number,
+ stream->pipe->is_capture ? 'C' : 'P',
+ stream->substream->number,
(long unsigned int)hw_sample_count,
(long unsigned int)(stream->timer_abs_periods +
- stream->timer_period_frag + PCXHR_GRANULARITY));
-
+ stream->timer_period_frag +
+ mgr->granularity));
return hw_sample_count;
}
static void pcxhr_update_timer_pos(struct pcxhr_mgr *mgr,
- struct pcxhr_stream *stream, int samples_to_add)
+ struct pcxhr_stream *stream,
+ int samples_to_add)
{
- if (stream->substream && (stream->status == PCXHR_STREAM_STATUS_RUNNING)) {
+ if (stream->substream &&
+ (stream->status == PCXHR_STREAM_STATUS_RUNNING)) {
u_int64_t new_sample_count;
int elapsed = 0;
int hardware_read = 0;
@@ -1092,20 +1157,22 @@ static void pcxhr_update_timer_pos(struct pcxhr_mgr *mgr,
if (samples_to_add < 0) {
stream->timer_is_synced = 0;
/* add default if no hardware_read possible */
- samples_to_add = PCXHR_GRANULARITY;
+ samples_to_add = mgr->granularity;
}
if (!stream->timer_is_synced) {
- if (stream->timer_abs_periods != 0 ||
- stream->timer_period_frag + PCXHR_GRANULARITY >=
- runtime->period_size) {
- new_sample_count = pcxhr_stream_read_position(mgr, stream);
+ if ((stream->timer_abs_periods != 0) ||
+ ((stream->timer_period_frag + samples_to_add) >=
+ runtime->period_size)) {
+ new_sample_count =
+ pcxhr_stream_read_position(mgr, stream);
hardware_read = 1;
- if (new_sample_count >= PCXHR_GRANULARITY_MIN) {
- /* sub security offset because of jitter and
- * finer granularity of dsp time (MBOX4)
+ if (new_sample_count >= mgr->granularity) {
+ /* sub security offset because of
+ * jitter and finer granularity of
+ * dsp time (MBOX4)
*/
- new_sample_count -= PCXHR_GRANULARITY_MIN;
+ new_sample_count -= mgr->granularity;
stream->timer_is_synced = 1;
}
}
@@ -1128,12 +1195,15 @@ static void pcxhr_update_timer_pos(struct pcxhr_mgr *mgr,
stream->timer_buf_periods = 0;
stream->timer_abs_periods = new_elapse_pos;
}
- if (new_sample_count >= stream->timer_abs_periods)
- stream->timer_period_frag = (u_int32_t)(new_sample_count -
- stream->timer_abs_periods);
- else
- snd_printk(KERN_ERR "ERROR new_sample_count too small ??? %lx\n",
+ if (new_sample_count >= stream->timer_abs_periods) {
+ stream->timer_period_frag =
+ (u_int32_t)(new_sample_count -
+ stream->timer_abs_periods);
+ } else {
+ snd_printk(KERN_ERR
+ "ERROR new_sample_count too small ??? %ld\n",
(long unsigned int)new_sample_count);
+ }
if (elapsed) {
spin_unlock(&mgr->lock);
@@ -1143,7 +1213,6 @@ static void pcxhr_update_timer_pos(struct pcxhr_mgr *mgr,
}
}
-
irqreturn_t pcxhr_interrupt(int irq, void *dev_id)
{
struct pcxhr_mgr *mgr = dev_id;
@@ -1156,7 +1225,8 @@ irqreturn_t pcxhr_interrupt(int irq, void *dev_id)
reg = PCXHR_INPL(mgr, PCXHR_PLX_IRQCS);
if (! (reg & PCXHR_IRQCS_ACTIVE_PCIDB)) {
spin_unlock(&mgr->lock);
- return IRQ_NONE; /* this device did not cause the interrupt */
+ /* this device did not cause the interrupt */
+ return IRQ_NONE;
}
/* clear interrupt */
@@ -1167,10 +1237,12 @@ irqreturn_t pcxhr_interrupt(int irq, void *dev_id)
if (reg & PCXHR_IRQ_TIMER) {
int timer_toggle = reg & PCXHR_IRQ_TIMER;
/* is a 24 bit counter */
- int dsp_time_new = PCXHR_INPL(mgr, PCXHR_PLX_MBOX4) & PCXHR_DSP_TIME_MASK;
+ int dsp_time_new =
+ PCXHR_INPL(mgr, PCXHR_PLX_MBOX4) & PCXHR_DSP_TIME_MASK;
int dsp_time_diff = dsp_time_new - mgr->dsp_time_last;
- if (dsp_time_diff < 0 && mgr->dsp_time_last != PCXHR_DSP_TIME_INVALID) {
+ if ((dsp_time_diff < 0) &&
+ (mgr->dsp_time_last != PCXHR_DSP_TIME_INVALID)) {
snd_printdd("ERROR DSP TIME old(%d) new(%d) -> "
"resynchronize all streams\n",
mgr->dsp_time_last, dsp_time_new);
@@ -1178,42 +1250,51 @@ irqreturn_t pcxhr_interrupt(int irq, void *dev_id)
}
#ifdef CONFIG_SND_DEBUG_VERBOSE
if (dsp_time_diff == 0)
- snd_printdd("ERROR DSP TIME NO DIFF time(%d)\n", dsp_time_new);
- else if (dsp_time_diff >= (2*PCXHR_GRANULARITY))
+ snd_printdd("ERROR DSP TIME NO DIFF time(%d)\n",
+ dsp_time_new);
+ else if (dsp_time_diff >= (2*mgr->granularity))
snd_printdd("ERROR DSP TIME TOO BIG old(%d) add(%d)\n",
- mgr->dsp_time_last, dsp_time_new - mgr->dsp_time_last);
+ mgr->dsp_time_last,
+ dsp_time_new - mgr->dsp_time_last);
+ else if (dsp_time_diff % mgr->granularity)
+ snd_printdd("ERROR DSP TIME increased by %d\n",
+ dsp_time_diff);
#endif
mgr->dsp_time_last = dsp_time_new;
- if (timer_toggle == mgr->timer_toggle)
+ if (timer_toggle == mgr->timer_toggle) {
snd_printdd("ERROR TIMER TOGGLE\n");
+ mgr->dsp_time_err++;
+ }
mgr->timer_toggle = timer_toggle;
reg &= ~PCXHR_IRQ_TIMER;
for (i = 0; i < mgr->num_cards; i++) {
chip = mgr->chip[i];
for (j = 0; j < chip->nb_streams_capt; j++)
- pcxhr_update_timer_pos(mgr, &chip->capture_stream[j],
- dsp_time_diff);
+ pcxhr_update_timer_pos(mgr,
+ &chip->capture_stream[j],
+ dsp_time_diff);
}
for (i = 0; i < mgr->num_cards; i++) {
chip = mgr->chip[i];
for (j = 0; j < chip->nb_streams_play; j++)
- pcxhr_update_timer_pos(mgr, &chip->playback_stream[j],
- dsp_time_diff);
+ pcxhr_update_timer_pos(mgr,
+ &chip->playback_stream[j],
+ dsp_time_diff);
}
}
/* other irq's handled in the tasklet */
if (reg & PCXHR_IRQ_MASK) {
-
- /* as we didn't request any notifications, some kind of xrun error
- * will probably occured
- */
- /* better resynchronize all streams next interrupt : */
- mgr->dsp_time_last = PCXHR_DSP_TIME_INVALID;
-
+ if (reg & PCXHR_IRQ_ASYNC) {
+ /* as we didn't request any async notifications,
+ * some kind of xrun error will probably occured
+ */
+ /* better resynchronize all streams next interrupt : */
+ mgr->dsp_time_last = PCXHR_DSP_TIME_INVALID;
+ }
mgr->src_it_dsp = reg;
- tasklet_hi_schedule(&mgr->msg_taskq);
+ tasklet_schedule(&mgr->msg_taskq);
}
#ifdef CONFIG_SND_DEBUG_VERBOSE
if (reg & PCXHR_FATAL_DSP_ERR)
diff --git a/sound/pci/pcxhr/pcxhr_core.h b/sound/pci/pcxhr/pcxhr_core.h
index d9a4ab60987..bbbd66d13a6 100644
--- a/sound/pci/pcxhr/pcxhr_core.h
+++ b/sound/pci/pcxhr/pcxhr_core.h
@@ -65,7 +65,7 @@ enum {
CMD_RESYNC_AUDIO_INPUTS, /* cmd_len = 1 stat_len = 0 */
CMD_GET_DSP_RESOURCES, /* cmd_len = 1 stat_len = 4 */
CMD_SET_TIMER_INTERRUPT, /* cmd_len = 1 stat_len = 0 */
- CMD_RES_PIPE, /* cmd_len = 2 stat_len = 0 */
+ CMD_RES_PIPE, /* cmd_len >=2 stat_len = 0 */
CMD_FREE_PIPE, /* cmd_len = 1 stat_len = 0 */
CMD_CONF_PIPE, /* cmd_len = 2 stat_len = 0 */
CMD_STOP_PIPE, /* cmd_len = 1 stat_len = 0 */
@@ -96,6 +96,8 @@ void pcxhr_init_rmh(struct pcxhr_rmh *rmh, int cmd);
void pcxhr_set_pipe_cmd_params(struct pcxhr_rmh* rmh, int capture, unsigned int param1,
unsigned int param2, unsigned int param3);
+#define DSP_EXT_CMD_SET(x) (x->dsp_version > 0x012800)
+
/*
send the rmh
*/
@@ -110,6 +112,7 @@ int pcxhr_send_msg(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh);
#define IO_NUM_REG_STATUS 5
#define IO_NUM_REG_CUER 10
#define IO_NUM_UER_CHIP_REG 11
+#define IO_NUM_REG_CONFIG_SRC 12
#define IO_NUM_REG_OUT_ANA_LEVEL 20
#define IO_NUM_REG_IN_ANA_LEVEL 21
diff --git a/sound/pci/pcxhr/pcxhr_hwdep.c b/sound/pci/pcxhr/pcxhr_hwdep.c
index 96640d9c227..592743a298b 100644
--- a/sound/pci/pcxhr/pcxhr_hwdep.c
+++ b/sound/pci/pcxhr/pcxhr_hwdep.c
@@ -31,6 +31,7 @@
#include "pcxhr_mixer.h"
#include "pcxhr_hwdep.h"
#include "pcxhr_core.h"
+#include "pcxhr_mix22.h"
#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE)
@@ -40,10 +41,10 @@
#endif
+static int pcxhr_sub_init(struct pcxhr_mgr *mgr);
/*
* get basic information and init pcxhr card
*/
-
static int pcxhr_init_board(struct pcxhr_mgr *mgr)
{
int err;
@@ -68,7 +69,7 @@ static int pcxhr_init_board(struct pcxhr_mgr *mgr)
if ((rmh.stat[0] & MASK_FIRST_FIELD) != mgr->playback_chips * 2)
return -EINVAL;
/* test 8 or 2 phys in */
- if (((rmh.stat[0] >> (2 * FIELD_SIZE)) & MASK_FIRST_FIELD) !=
+ if (((rmh.stat[0] >> (2 * FIELD_SIZE)) & MASK_FIRST_FIELD) <
mgr->capture_chips * 2)
return -EINVAL;
/* test max nb substream per board */
@@ -77,20 +78,34 @@ static int pcxhr_init_board(struct pcxhr_mgr *mgr)
/* test max nb substream per pipe */
if (((rmh.stat[1] >> 7) & 0x5F) < PCXHR_PLAYBACK_STREAMS)
return -EINVAL;
+ snd_printdd("supported formats : playback=%x capture=%x\n",
+ rmh.stat[2], rmh.stat[3]);
pcxhr_init_rmh(&rmh, CMD_VERSION);
/* firmware num for DSP */
rmh.cmd[0] |= mgr->firmware_num;
/* transfer granularity in samples (should be multiple of 48) */
- rmh.cmd[1] = (1<<23) + PCXHR_GRANULARITY;
+ rmh.cmd[1] = (1<<23) + mgr->granularity;
rmh.cmd_len = 2;
err = pcxhr_send_msg(mgr, &rmh);
if (err)
return err;
- snd_printdd("PCXHR DSP version is %d.%d.%d\n",
- (rmh.stat[0]>>16)&0xff, (rmh.stat[0]>>8)&0xff, rmh.stat[0]&0xff);
+ snd_printdd("PCXHR DSP version is %d.%d.%d\n", (rmh.stat[0]>>16)&0xff,
+ (rmh.stat[0]>>8)&0xff, rmh.stat[0]&0xff);
mgr->dsp_version = rmh.stat[0];
+ if (mgr->is_hr_stereo)
+ err = hr222_sub_init(mgr);
+ else
+ err = pcxhr_sub_init(mgr);
+ return err;
+}
+
+static int pcxhr_sub_init(struct pcxhr_mgr *mgr)
+{
+ int err;
+ struct pcxhr_rmh rmh;
+
/* get options */
pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_READ);
rmh.cmd[0] |= IO_NUM_REG_STATUS;
@@ -100,20 +115,22 @@ static int pcxhr_init_board(struct pcxhr_mgr *mgr)
if (err)
return err;
- if ((rmh.stat[1] & REG_STATUS_OPT_DAUGHTER_MASK) == REG_STATUS_OPT_ANALOG_BOARD)
- mgr->board_has_analog = 1; /* analog addon board available */
- else
- /* analog addon board not available -> no support for instance */
- return -EINVAL;
+ if ((rmh.stat[1] & REG_STATUS_OPT_DAUGHTER_MASK) ==
+ REG_STATUS_OPT_ANALOG_BOARD)
+ mgr->board_has_analog = 1; /* analog addon board found */
/* unmute inputs */
err = pcxhr_write_io_num_reg_cont(mgr, REG_CONT_UNMUTE_INPUTS,
REG_CONT_UNMUTE_INPUTS, NULL);
if (err)
return err;
- /* unmute outputs */
- pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_READ); /* a write to IO_NUM_REG_MUTE_OUT mutes! */
+ /* unmute outputs (a write to IO_NUM_REG_MUTE_OUT mutes!) */
+ pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_READ);
rmh.cmd[0] |= IO_NUM_REG_MUTE_OUT;
+ if (DSP_EXT_CMD_SET(mgr)) {
+ rmh.cmd[1] = 1; /* unmute digital plugs */
+ rmh.cmd_len = 2;
+ }
err = pcxhr_send_msg(mgr, &rmh);
return err;
}
@@ -124,19 +141,25 @@ void pcxhr_reset_board(struct pcxhr_mgr *mgr)
if (mgr->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_MAIN_INDEX)) {
/* mute outputs */
+ if (!mgr->is_hr_stereo) {
/* a read to IO_NUM_REG_MUTE_OUT register unmutes! */
pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE);
rmh.cmd[0] |= IO_NUM_REG_MUTE_OUT;
pcxhr_send_msg(mgr, &rmh);
/* mute inputs */
- pcxhr_write_io_num_reg_cont(mgr, REG_CONT_UNMUTE_INPUTS, 0, NULL);
+ pcxhr_write_io_num_reg_cont(mgr, REG_CONT_UNMUTE_INPUTS,
+ 0, NULL);
+ }
+ /* stereo cards mute with reset of dsp */
}
/* reset pcxhr dsp */
- if (mgr->dsp_loaded & ( 1 << PCXHR_FIRMWARE_DSP_EPRM_INDEX))
+ if (mgr->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_EPRM_INDEX))
pcxhr_reset_dsp(mgr);
/* reset second xilinx */
- if (mgr->dsp_loaded & ( 1 << PCXHR_FIRMWARE_XLX_COM_INDEX))
+ if (mgr->dsp_loaded & (1 << PCXHR_FIRMWARE_XLX_COM_INDEX)) {
pcxhr_reset_xilinx_com(mgr);
+ mgr->dsp_loaded = 1;
+ }
return;
}
@@ -144,8 +167,9 @@ void pcxhr_reset_board(struct pcxhr_mgr *mgr)
/*
* allocate a playback/capture pipe (pcmp0/pcmc0)
*/
-static int pcxhr_dsp_allocate_pipe( struct pcxhr_mgr *mgr, struct pcxhr_pipe *pipe,
- int is_capture, int pin)
+static int pcxhr_dsp_allocate_pipe(struct pcxhr_mgr *mgr,
+ struct pcxhr_pipe *pipe,
+ int is_capture, int pin)
{
int stream_count, audio_count;
int err;
@@ -161,15 +185,23 @@ static int pcxhr_dsp_allocate_pipe( struct pcxhr_mgr *mgr, struct pcxhr_pipe *pi
stream_count = PCXHR_PLAYBACK_STREAMS;
audio_count = 2; /* always stereo */
}
- snd_printdd("snd_add_ref_pipe pin(%d) pcm%c0\n", pin, is_capture ? 'c' : 'p');
+ snd_printdd("snd_add_ref_pipe pin(%d) pcm%c0\n",
+ pin, is_capture ? 'c' : 'p');
pipe->is_capture = is_capture;
pipe->first_audio = pin;
/* define pipe (P_PCM_ONLY_MASK (0x020000) is not necessary) */
pcxhr_init_rmh(&rmh, CMD_RES_PIPE);
- pcxhr_set_pipe_cmd_params(&rmh, is_capture, pin, audio_count, stream_count);
+ pcxhr_set_pipe_cmd_params(&rmh, is_capture, pin,
+ audio_count, stream_count);
+ rmh.cmd[1] |= 0x020000; /* add P_PCM_ONLY_MASK */
+ if (DSP_EXT_CMD_SET(mgr)) {
+ /* add channel mask to command */
+ rmh.cmd[rmh.cmd_len++] = (audio_count == 1) ? 0x01 : 0x03;
+ }
err = pcxhr_send_msg(mgr, &rmh);
if (err < 0) {
- snd_printk(KERN_ERR "error pipe allocation (CMD_RES_PIPE) err=%x!\n", err );
+ snd_printk(KERN_ERR "error pipe allocation "
+ "(CMD_RES_PIPE) err=%x!\n", err);
return err;
}
pipe->status = PCXHR_PIPE_DEFINED;
@@ -199,10 +231,12 @@ static int pcxhr_dsp_free_pipe( struct pcxhr_mgr *mgr, struct pcxhr_pipe *pipe)
snd_printk(KERN_ERR "error stopping pipe!\n");
/* release the pipe */
pcxhr_init_rmh(&rmh, CMD_FREE_PIPE);
- pcxhr_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->first_audio, 0, 0);
+ pcxhr_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->first_audio,
+ 0, 0);
err = pcxhr_send_msg(mgr, &rmh);
if (err < 0)
- snd_printk(KERN_ERR "error pipe release (CMD_FREE_PIPE) err(%x)\n", err);
+ snd_printk(KERN_ERR "error pipe release "
+ "(CMD_FREE_PIPE) err(%x)\n", err);
pipe->status = PCXHR_PIPE_UNDEFINED;
return err;
}
@@ -248,15 +282,16 @@ static int pcxhr_start_pipes(struct pcxhr_mgr *mgr)
for (i = 0; i < mgr->num_cards; i++) {
chip = mgr->chip[i];
if (chip->nb_streams_play)
- playback_mask |= (1 << chip->playback_pipe.first_audio);
+ playback_mask |= 1 << chip->playback_pipe.first_audio;
for (j = 0; j < chip->nb_streams_capt; j++)
- capture_mask |= (1 << chip->capture_pipe[j].first_audio);
+ capture_mask |= 1 << chip->capture_pipe[j].first_audio;
}
return pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 1);
}
-static int pcxhr_dsp_load(struct pcxhr_mgr *mgr, int index, const struct firmware *dsp)
+static int pcxhr_dsp_load(struct pcxhr_mgr *mgr, int index,
+ const struct firmware *dsp)
{
int err, card_index;
@@ -330,22 +365,33 @@ static int pcxhr_dsp_load(struct pcxhr_mgr *mgr, int index, const struct firmwar
int pcxhr_setup_firmware(struct pcxhr_mgr *mgr)
{
- static char *fw_files[5] = {
- "xi_1_882.dat",
- "xc_1_882.dat",
- "e321_512.e56",
- "b321_512.b56",
- "d321_512.d56"
+ static char *fw_files[][5] = {
+ [0] = { "xlxint.dat", "xlxc882hr.dat",
+ "dspe882.e56", "dspb882hr.b56", "dspd882.d56" },
+ [1] = { "xlxint.dat", "xlxc882e.dat",
+ "dspe882.e56", "dspb882e.b56", "dspd882.d56" },
+ [2] = { "xlxint.dat", "xlxc1222hr.dat",
+ "dspe882.e56", "dspb1222hr.b56", "dspd1222.d56" },
+ [3] = { "xlxint.dat", "xlxc1222e.dat",
+ "dspe882.e56", "dspb1222e.b56", "dspd1222.d56" },
+ [4] = { NULL, "xlxc222.dat",
+ "dspe924.e56", "dspb924.b56", "dspd222.d56" },
+ [5] = { NULL, "xlxc924.dat",
+ "dspe924.e56", "dspb924.b56", "dspd222.d56" },
};
char path[32];
const struct firmware *fw_entry;
int i, err;
+ int fw_set = mgr->fw_file_set;
- for (i = 0; i < ARRAY_SIZE(fw_files); i++) {
- sprintf(path, "pcxhr/%s", fw_files[i]);
+ for (i = 0; i < 5; i++) {
+ if (!fw_files[fw_set][i])
+ continue;
+ sprintf(path, "pcxhr/%s", fw_files[fw_set][i]);
if (request_firmware(&fw_entry, path, &mgr->pci->dev)) {
- snd_printk(KERN_ERR "pcxhr: can't load firmware %s\n", path);
+ snd_printk(KERN_ERR "pcxhr: can't load firmware %s\n",
+ path);
return -ENOENT;
}
/* fake hwdep dsp record */
@@ -358,11 +404,26 @@ int pcxhr_setup_firmware(struct pcxhr_mgr *mgr)
return 0;
}
-MODULE_FIRMWARE("pcxhr/xi_1_882.dat");
-MODULE_FIRMWARE("pcxhr/xc_1_882.dat");
-MODULE_FIRMWARE("pcxhr/e321_512.e56");
-MODULE_FIRMWARE("pcxhr/b321_512.b56");
-MODULE_FIRMWARE("pcxhr/d321_512.d56");
+MODULE_FIRMWARE("pcxhr/xlxint.dat");
+MODULE_FIRMWARE("pcxhr/xlxc882hr.dat");
+MODULE_FIRMWARE("pcxhr/xlxc882e.dat");
+MODULE_FIRMWARE("pcxhr/dspe882.e56");
+MODULE_FIRMWARE("pcxhr/dspb882hr.b56");
+MODULE_FIRMWARE("pcxhr/dspb882e.b56");
+MODULE_FIRMWARE("pcxhr/dspd882.d56");
+
+MODULE_FIRMWARE("pcxhr/xlxc1222hr.dat");
+MODULE_FIRMWARE("pcxhr/xlxc1222e.dat");
+MODULE_FIRMWARE("pcxhr/dspb1222hr.b56");
+MODULE_FIRMWARE("pcxhr/dspb1222e.b56");
+MODULE_FIRMWARE("pcxhr/dspd1222.d56");
+
+MODULE_FIRMWARE("pcxhr/xlxc222.dat");
+MODULE_FIRMWARE("pcxhr/xlxc924.dat");
+MODULE_FIRMWARE("pcxhr/dspe924.e56");
+MODULE_FIRMWARE("pcxhr/dspb924.b56");
+MODULE_FIRMWARE("pcxhr/dspd222.d56");
+
#else /* old style firmware loading */
@@ -373,7 +434,8 @@ MODULE_FIRMWARE("pcxhr/d321_512.d56");
static int pcxhr_hwdep_dsp_status(struct snd_hwdep *hw,
struct snd_hwdep_dsp_status *info)
{
- strcpy(info->id, "pcxhr");
+ struct pcxhr_mgr *mgr = hw->private_data;
+ sprintf(info->id, "pcxhr%d", mgr->fw_file_set);
info->num_dsps = PCXHR_FIRMWARE_FILES_MAX_INDEX;
if (hw->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_MAIN_INDEX))
@@ -393,8 +455,8 @@ static int pcxhr_hwdep_dsp_load(struct snd_hwdep *hw,
fw.size = dsp->length;
fw.data = vmalloc(fw.size);
if (! fw.data) {
- snd_printk(KERN_ERR "pcxhr: cannot allocate dsp image (%lu bytes)\n",
- (unsigned long)fw.size);
+ snd_printk(KERN_ERR "pcxhr: cannot allocate dsp image "
+ "(%lu bytes)\n", (unsigned long)fw.size);
return -ENOMEM;
}
if (copy_from_user((void *)fw.data, dsp->image, dsp->length)) {
@@ -424,8 +486,11 @@ int pcxhr_setup_firmware(struct pcxhr_mgr *mgr)
int err;
struct snd_hwdep *hw;
- /* only create hwdep interface for first cardX (see "index" module parameter)*/
- if ((err = snd_hwdep_new(mgr->chip[0]->card, PCXHR_HWDEP_ID, 0, &hw)) < 0)
+ /* only create hwdep interface for first cardX
+ * (see "index" module parameter)
+ */
+ err = snd_hwdep_new(mgr->chip[0]->card, PCXHR_HWDEP_ID, 0, &hw);
+ if (err < 0)
return err;
hw->iface = SNDRV_HWDEP_IFACE_PCXHR;
@@ -435,10 +500,13 @@ int pcxhr_setup_firmware(struct pcxhr_mgr *mgr)
hw->ops.dsp_status = pcxhr_hwdep_dsp_status;
hw->ops.dsp_load = pcxhr_hwdep_dsp_load;
hw->exclusive = 1;
+ /* stereo cards don't need fw_file_0 -> dsp_loaded = 1 */
+ hw->dsp_loaded = mgr->is_hr_stereo ? 1 : 0;
mgr->dsp_loaded = 0;
sprintf(hw->name, PCXHR_HWDEP_ID);
- if ((err = snd_card_register(mgr->chip[0]->card)) < 0)
+ err = snd_card_register(mgr->chip[0]->card);
+ if (err < 0)
return err;
return 0;
}
diff --git a/sound/pci/pcxhr/pcxhr_mix22.c b/sound/pci/pcxhr/pcxhr_mix22.c
new file mode 100644
index 00000000000..ff019126b67
--- /dev/null
+++ b/sound/pci/pcxhr/pcxhr_mix22.c
@@ -0,0 +1,820 @@
+/*
+ * Driver for Digigram pcxhr compatible soundcards
+ *
+ * mixer interface for stereo cards
+ *
+ * Copyright (c) 2004 by Digigram <alsa@digigram.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <sound/core.h>
+#include <sound/control.h>
+#include <sound/tlv.h>
+#include <sound/asoundef.h>
+#include "pcxhr.h"
+#include "pcxhr_core.h"
+#include "pcxhr_mix22.h"
+
+
+/* registers used on the DSP and Xilinx (port 2) : HR stereo cards only */
+#define PCXHR_DSP_RESET 0x20
+#define PCXHR_XLX_CFG 0x24
+#define PCXHR_XLX_RUER 0x28
+#define PCXHR_XLX_DATA 0x2C
+#define PCXHR_XLX_STATUS 0x30
+#define PCXHR_XLX_LOFREQ 0x34
+#define PCXHR_XLX_HIFREQ 0x38
+#define PCXHR_XLX_CSUER 0x3C
+#define PCXHR_XLX_SELMIC 0x40
+
+#define PCXHR_DSP 2
+
+/* byte access only ! */
+#define PCXHR_INPB(mgr, x) inb((mgr)->port[PCXHR_DSP] + (x))
+#define PCXHR_OUTPB(mgr, x, data) outb((data), (mgr)->port[PCXHR_DSP] + (x))
+
+
+/* values for PCHR_DSP_RESET register */
+#define PCXHR_DSP_RESET_DSP 0x01
+#define PCXHR_DSP_RESET_MUTE 0x02
+#define PCXHR_DSP_RESET_CODEC 0x08
+
+/* values for PCHR_XLX_CFG register */
+#define PCXHR_CFG_SYNCDSP_MASK 0x80
+#define PCXHR_CFG_DEPENDENCY_MASK 0x60
+#define PCXHR_CFG_INDEPENDANT_SEL 0x00
+#define PCXHR_CFG_MASTER_SEL 0x40
+#define PCXHR_CFG_SLAVE_SEL 0x20
+#define PCXHR_CFG_DATA_UER1_SEL_MASK 0x10 /* 0 (UER0), 1(UER1) */
+#define PCXHR_CFG_DATAIN_SEL_MASK 0x08 /* 0 (ana), 1 (UER) */
+#define PCXHR_CFG_SRC_MASK 0x04 /* 0 (Bypass), 1 (SRC Actif) */
+#define PCXHR_CFG_CLOCK_UER1_SEL_MASK 0x02 /* 0 (UER0), 1(UER1) */
+#define PCXHR_CFG_CLOCKIN_SEL_MASK 0x01 /* 0 (internal), 1 (AES/EBU) */
+
+/* values for PCHR_XLX_DATA register */
+#define PCXHR_DATA_CODEC 0x80
+#define AKM_POWER_CONTROL_CMD 0xA007
+#define AKM_RESET_ON_CMD 0xA100
+#define AKM_RESET_OFF_CMD 0xA103
+#define AKM_CLOCK_INF_55K_CMD 0xA240
+#define AKM_CLOCK_SUP_55K_CMD 0xA24D
+#define AKM_MUTE_CMD 0xA38D
+#define AKM_UNMUTE_CMD 0xA30D
+#define AKM_LEFT_LEVEL_CMD 0xA600
+#define AKM_RIGHT_LEVEL_CMD 0xA700
+
+/* values for PCHR_XLX_STATUS register - READ */
+#define PCXHR_STAT_SRC_LOCK 0x01
+#define PCXHR_STAT_LEVEL_IN 0x02
+#define PCXHR_STAT_MIC_CAPS 0x10
+/* values for PCHR_XLX_STATUS register - WRITE */
+#define PCXHR_STAT_FREQ_SYNC_MASK 0x01
+#define PCXHR_STAT_FREQ_UER1_MASK 0x02
+#define PCXHR_STAT_FREQ_SAVE_MASK 0x80
+
+/* values for PCHR_XLX_CSUER register */
+#define PCXHR_SUER1_BIT_U_READ_MASK 0x80
+#define PCXHR_SUER1_BIT_C_READ_MASK 0x40
+#define PCXHR_SUER1_DATA_PRESENT_MASK 0x20
+#define PCXHR_SUER1_CLOCK_PRESENT_MASK 0x10
+#define PCXHR_SUER_BIT_U_READ_MASK 0x08
+#define PCXHR_SUER_BIT_C_READ_MASK 0x04
+#define PCXHR_SUER_DATA_PRESENT_MASK 0x02
+#define PCXHR_SUER_CLOCK_PRESENT_MASK 0x01
+
+#define PCXHR_SUER_BIT_U_WRITE_MASK 0x02
+#define PCXHR_SUER_BIT_C_WRITE_MASK 0x01
+
+/* values for PCXHR_XLX_SELMIC register - WRITE */
+#define PCXHR_SELMIC_PREAMPLI_OFFSET 2
+#define PCXHR_SELMIC_PREAMPLI_MASK 0x0C
+#define PCXHR_SELMIC_PHANTOM_ALIM 0x80
+
+
+static const unsigned char g_hr222_p_level[] = {
+ 0x00, /* [000] -49.5 dB: AKM[000] = -1.#INF dB (mute) */
+ 0x01, /* [001] -49.0 dB: AKM[001] = -48.131 dB (diff=0.86920 dB) */
+ 0x01, /* [002] -48.5 dB: AKM[001] = -48.131 dB (diff=0.36920 dB) */
+ 0x01, /* [003] -48.0 dB: AKM[001] = -48.131 dB (diff=0.13080 dB) */
+ 0x01, /* [004] -47.5 dB: AKM[001] = -48.131 dB (diff=0.63080 dB) */
+ 0x01, /* [005] -46.5 dB: AKM[001] = -48.131 dB (diff=1.63080 dB) */
+ 0x01, /* [006] -47.0 dB: AKM[001] = -48.131 dB (diff=1.13080 dB) */
+ 0x01, /* [007] -46.0 dB: AKM[001] = -48.131 dB (diff=2.13080 dB) */
+ 0x01, /* [008] -45.5 dB: AKM[001] = -48.131 dB (diff=2.63080 dB) */
+ 0x02, /* [009] -45.0 dB: AKM[002] = -42.110 dB (diff=2.88980 dB) */
+ 0x02, /* [010] -44.5 dB: AKM[002] = -42.110 dB (diff=2.38980 dB) */
+ 0x02, /* [011] -44.0 dB: AKM[002] = -42.110 dB (diff=1.88980 dB) */
+ 0x02, /* [012] -43.5 dB: AKM[002] = -42.110 dB (diff=1.38980 dB) */
+ 0x02, /* [013] -43.0 dB: AKM[002] = -42.110 dB (diff=0.88980 dB) */
+ 0x02, /* [014] -42.5 dB: AKM[002] = -42.110 dB (diff=0.38980 dB) */
+ 0x02, /* [015] -42.0 dB: AKM[002] = -42.110 dB (diff=0.11020 dB) */
+ 0x02, /* [016] -41.5 dB: AKM[002] = -42.110 dB (diff=0.61020 dB) */
+ 0x02, /* [017] -41.0 dB: AKM[002] = -42.110 dB (diff=1.11020 dB) */
+ 0x02, /* [018] -40.5 dB: AKM[002] = -42.110 dB (diff=1.61020 dB) */
+ 0x03, /* [019] -40.0 dB: AKM[003] = -38.588 dB (diff=1.41162 dB) */
+ 0x03, /* [020] -39.5 dB: AKM[003] = -38.588 dB (diff=0.91162 dB) */
+ 0x03, /* [021] -39.0 dB: AKM[003] = -38.588 dB (diff=0.41162 dB) */
+ 0x03, /* [022] -38.5 dB: AKM[003] = -38.588 dB (diff=0.08838 dB) */
+ 0x03, /* [023] -38.0 dB: AKM[003] = -38.588 dB (diff=0.58838 dB) */
+ 0x03, /* [024] -37.5 dB: AKM[003] = -38.588 dB (diff=1.08838 dB) */
+ 0x04, /* [025] -37.0 dB: AKM[004] = -36.090 dB (diff=0.91040 dB) */
+ 0x04, /* [026] -36.5 dB: AKM[004] = -36.090 dB (diff=0.41040 dB) */
+ 0x04, /* [027] -36.0 dB: AKM[004] = -36.090 dB (diff=0.08960 dB) */
+ 0x04, /* [028] -35.5 dB: AKM[004] = -36.090 dB (diff=0.58960 dB) */
+ 0x05, /* [029] -35.0 dB: AKM[005] = -34.151 dB (diff=0.84860 dB) */
+ 0x05, /* [030] -34.5 dB: AKM[005] = -34.151 dB (diff=0.34860 dB) */
+ 0x05, /* [031] -34.0 dB: AKM[005] = -34.151 dB (diff=0.15140 dB) */
+ 0x05, /* [032] -33.5 dB: AKM[005] = -34.151 dB (diff=0.65140 dB) */
+ 0x06, /* [033] -33.0 dB: AKM[006] = -32.568 dB (diff=0.43222 dB) */
+ 0x06, /* [034] -32.5 dB: AKM[006] = -32.568 dB (diff=0.06778 dB) */
+ 0x06, /* [035] -32.0 dB: AKM[006] = -32.568 dB (diff=0.56778 dB) */
+ 0x07, /* [036] -31.5 dB: AKM[007] = -31.229 dB (diff=0.27116 dB) */
+ 0x07, /* [037] -31.0 dB: AKM[007] = -31.229 dB (diff=0.22884 dB) */
+ 0x08, /* [038] -30.5 dB: AKM[008] = -30.069 dB (diff=0.43100 dB) */
+ 0x08, /* [039] -30.0 dB: AKM[008] = -30.069 dB (diff=0.06900 dB) */
+ 0x09, /* [040] -29.5 dB: AKM[009] = -29.046 dB (diff=0.45405 dB) */
+ 0x09, /* [041] -29.0 dB: AKM[009] = -29.046 dB (diff=0.04595 dB) */
+ 0x0a, /* [042] -28.5 dB: AKM[010] = -28.131 dB (diff=0.36920 dB) */
+ 0x0a, /* [043] -28.0 dB: AKM[010] = -28.131 dB (diff=0.13080 dB) */
+ 0x0b, /* [044] -27.5 dB: AKM[011] = -27.303 dB (diff=0.19705 dB) */
+ 0x0b, /* [045] -27.0 dB: AKM[011] = -27.303 dB (diff=0.30295 dB) */
+ 0x0c, /* [046] -26.5 dB: AKM[012] = -26.547 dB (diff=0.04718 dB) */
+ 0x0d, /* [047] -26.0 dB: AKM[013] = -25.852 dB (diff=0.14806 dB) */
+ 0x0e, /* [048] -25.5 dB: AKM[014] = -25.208 dB (diff=0.29176 dB) */
+ 0x0e, /* [049] -25.0 dB: AKM[014] = -25.208 dB (diff=0.20824 dB) */
+ 0x0f, /* [050] -24.5 dB: AKM[015] = -24.609 dB (diff=0.10898 dB) */
+ 0x10, /* [051] -24.0 dB: AKM[016] = -24.048 dB (diff=0.04840 dB) */
+ 0x11, /* [052] -23.5 dB: AKM[017] = -23.522 dB (diff=0.02183 dB) */
+ 0x12, /* [053] -23.0 dB: AKM[018] = -23.025 dB (diff=0.02535 dB) */
+ 0x13, /* [054] -22.5 dB: AKM[019] = -22.556 dB (diff=0.05573 dB) */
+ 0x14, /* [055] -22.0 dB: AKM[020] = -22.110 dB (diff=0.11020 dB) */
+ 0x15, /* [056] -21.5 dB: AKM[021] = -21.686 dB (diff=0.18642 dB) */
+ 0x17, /* [057] -21.0 dB: AKM[023] = -20.896 dB (diff=0.10375 dB) */
+ 0x18, /* [058] -20.5 dB: AKM[024] = -20.527 dB (diff=0.02658 dB) */
+ 0x1a, /* [059] -20.0 dB: AKM[026] = -19.831 dB (diff=0.16866 dB) */
+ 0x1b, /* [060] -19.5 dB: AKM[027] = -19.504 dB (diff=0.00353 dB) */
+ 0x1d, /* [061] -19.0 dB: AKM[029] = -18.883 dB (diff=0.11716 dB) */
+ 0x1e, /* [062] -18.5 dB: AKM[030] = -18.588 dB (diff=0.08838 dB) */
+ 0x20, /* [063] -18.0 dB: AKM[032] = -18.028 dB (diff=0.02780 dB) */
+ 0x22, /* [064] -17.5 dB: AKM[034] = -17.501 dB (diff=0.00123 dB) */
+ 0x24, /* [065] -17.0 dB: AKM[036] = -17.005 dB (diff=0.00475 dB) */
+ 0x26, /* [066] -16.5 dB: AKM[038] = -16.535 dB (diff=0.03513 dB) */
+ 0x28, /* [067] -16.0 dB: AKM[040] = -16.090 dB (diff=0.08960 dB) */
+ 0x2b, /* [068] -15.5 dB: AKM[043] = -15.461 dB (diff=0.03857 dB) */
+ 0x2d, /* [069] -15.0 dB: AKM[045] = -15.067 dB (diff=0.06655 dB) */
+ 0x30, /* [070] -14.5 dB: AKM[048] = -14.506 dB (diff=0.00598 dB) */
+ 0x33, /* [071] -14.0 dB: AKM[051] = -13.979 dB (diff=0.02060 dB) */
+ 0x36, /* [072] -13.5 dB: AKM[054] = -13.483 dB (diff=0.01707 dB) */
+ 0x39, /* [073] -13.0 dB: AKM[057] = -13.013 dB (diff=0.01331 dB) */
+ 0x3c, /* [074] -12.5 dB: AKM[060] = -12.568 dB (diff=0.06778 dB) */
+ 0x40, /* [075] -12.0 dB: AKM[064] = -12.007 dB (diff=0.00720 dB) */
+ 0x44, /* [076] -11.5 dB: AKM[068] = -11.481 dB (diff=0.01937 dB) */
+ 0x48, /* [077] -11.0 dB: AKM[072] = -10.984 dB (diff=0.01585 dB) */
+ 0x4c, /* [078] -10.5 dB: AKM[076] = -10.515 dB (diff=0.01453 dB) */
+ 0x51, /* [079] -10.0 dB: AKM[081] = -9.961 dB (diff=0.03890 dB) */
+ 0x55, /* [080] -9.5 dB: AKM[085] = -9.542 dB (diff=0.04243 dB) */
+ 0x5a, /* [081] -9.0 dB: AKM[090] = -9.046 dB (diff=0.04595 dB) */
+ 0x60, /* [082] -8.5 dB: AKM[096] = -8.485 dB (diff=0.01462 dB) */
+ 0x66, /* [083] -8.0 dB: AKM[102] = -7.959 dB (diff=0.04120 dB) */
+ 0x6c, /* [084] -7.5 dB: AKM[108] = -7.462 dB (diff=0.03767 dB) */
+ 0x72, /* [085] -7.0 dB: AKM[114] = -6.993 dB (diff=0.00729 dB) */
+ 0x79, /* [086] -6.5 dB: AKM[121] = -6.475 dB (diff=0.02490 dB) */
+ 0x80, /* [087] -6.0 dB: AKM[128] = -5.987 dB (diff=0.01340 dB) */
+ 0x87, /* [088] -5.5 dB: AKM[135] = -5.524 dB (diff=0.02413 dB) */
+ 0x8f, /* [089] -5.0 dB: AKM[143] = -5.024 dB (diff=0.02408 dB) */
+ 0x98, /* [090] -4.5 dB: AKM[152] = -4.494 dB (diff=0.00607 dB) */
+ 0xa1, /* [091] -4.0 dB: AKM[161] = -3.994 dB (diff=0.00571 dB) */
+ 0xaa, /* [092] -3.5 dB: AKM[170] = -3.522 dB (diff=0.02183 dB) */
+ 0xb5, /* [093] -3.0 dB: AKM[181] = -2.977 dB (diff=0.02277 dB) */
+ 0xbf, /* [094] -2.5 dB: AKM[191] = -2.510 dB (diff=0.01014 dB) */
+ 0xcb, /* [095] -2.0 dB: AKM[203] = -1.981 dB (diff=0.01912 dB) */
+ 0xd7, /* [096] -1.5 dB: AKM[215] = -1.482 dB (diff=0.01797 dB) */
+ 0xe3, /* [097] -1.0 dB: AKM[227] = -1.010 dB (diff=0.01029 dB) */
+ 0xf1, /* [098] -0.5 dB: AKM[241] = -0.490 dB (diff=0.00954 dB) */
+ 0xff, /* [099] +0.0 dB: AKM[255] = +0.000 dB (diff=0.00000 dB) */
+};
+
+
+static void hr222_config_akm(struct pcxhr_mgr *mgr, unsigned short data)
+{
+ unsigned short mask = 0x8000;
+ /* activate access to codec registers */
+ PCXHR_INPB(mgr, PCXHR_XLX_HIFREQ);
+
+ while (mask) {
+ PCXHR_OUTPB(mgr, PCXHR_XLX_DATA,
+ data & mask ? PCXHR_DATA_CODEC : 0);
+ mask >>= 1;
+ }
+ /* termiate access to codec registers */
+ PCXHR_INPB(mgr, PCXHR_XLX_RUER);
+}
+
+
+static int hr222_set_hw_playback_level(struct pcxhr_mgr *mgr,
+ int idx, int level)
+{
+ unsigned short cmd;
+ if (idx > 1 ||
+ level < 0 ||
+ level >= ARRAY_SIZE(g_hr222_p_level))
+ return -EINVAL;
+
+ if (idx == 0)
+ cmd = AKM_LEFT_LEVEL_CMD;
+ else
+ cmd = AKM_RIGHT_LEVEL_CMD;
+
+ /* conversion from PmBoardCodedLevel to AKM nonlinear programming */
+ cmd += g_hr222_p_level[level];
+
+ hr222_config_akm(mgr, cmd);
+ return 0;
+}
+
+
+static int hr222_set_hw_capture_level(struct pcxhr_mgr *mgr,
+ int level_l, int level_r, int level_mic)
+{
+ /* program all input levels at the same time */
+ unsigned int data;
+ int i;
+
+ if (!mgr->capture_chips)
+ return -EINVAL; /* no PCX22 */
+
+ data = ((level_mic & 0xff) << 24); /* micro is mono, but apply */
+ data |= ((level_mic & 0xff) << 16); /* level on both channels */
+ data |= ((level_r & 0xff) << 8); /* line input right channel */
+ data |= (level_l & 0xff); /* line input left channel */
+
+ PCXHR_INPB(mgr, PCXHR_XLX_DATA); /* activate input codec */
+ /* send 32 bits (4 x 8 bits) */
+ for (i = 0; i < 32; i++, data <<= 1) {
+ PCXHR_OUTPB(mgr, PCXHR_XLX_DATA,
+ (data & 0x80000000) ? PCXHR_DATA_CODEC : 0);
+ }
+ PCXHR_INPB(mgr, PCXHR_XLX_RUER); /* close input level codec */
+ return 0;
+}
+
+static void hr222_micro_boost(struct pcxhr_mgr *mgr, int level);
+
+int hr222_sub_init(struct pcxhr_mgr *mgr)
+{
+ unsigned char reg;
+
+ mgr->board_has_analog = 1; /* analog always available */
+ mgr->xlx_cfg = PCXHR_CFG_SYNCDSP_MASK;
+
+ reg = PCXHR_INPB(mgr, PCXHR_XLX_STATUS);
+ if (reg & PCXHR_STAT_MIC_CAPS)
+ mgr->board_has_mic = 1; /* microphone available */
+ snd_printdd("MIC input available = %d\n", mgr->board_has_mic);
+
+ /* reset codec */
+ PCXHR_OUTPB(mgr, PCXHR_DSP_RESET,
+ PCXHR_DSP_RESET_DSP);
+ msleep(5);
+ PCXHR_OUTPB(mgr, PCXHR_DSP_RESET,
+ PCXHR_DSP_RESET_DSP |
+ PCXHR_DSP_RESET_MUTE |
+ PCXHR_DSP_RESET_CODEC);
+ msleep(5);
+
+ /* config AKM */
+ hr222_config_akm(mgr, AKM_POWER_CONTROL_CMD);
+ hr222_config_akm(mgr, AKM_CLOCK_INF_55K_CMD);
+ hr222_config_akm(mgr, AKM_UNMUTE_CMD);
+ hr222_config_akm(mgr, AKM_RESET_OFF_CMD);
+
+ /* init micro boost */
+ hr222_micro_boost(mgr, 0);
+
+ return 0;
+}
+
+
+/* calc PLL register */
+/* TODO : there is a very similar fct in pcxhr.c */
+static int hr222_pll_freq_register(unsigned int freq,
+ unsigned int *pllreg,
+ unsigned int *realfreq)
+{
+ unsigned int reg;
+
+ if (freq < 6900 || freq > 219000)
+ return -EINVAL;
+ reg = (28224000 * 2) / freq;
+ reg = (reg - 1) / 2;
+ if (reg < 0x100)
+ *pllreg = reg + 0xC00;
+ else if (reg < 0x200)
+ *pllreg = reg + 0x800;
+ else if (reg < 0x400)
+ *pllreg = reg & 0x1ff;
+ else if (reg < 0x800) {
+ *pllreg = ((reg >> 1) & 0x1ff) + 0x200;
+ reg &= ~1;
+ } else {
+ *pllreg = ((reg >> 2) & 0x1ff) + 0x400;
+ reg &= ~3;
+ }
+ if (realfreq)
+ *realfreq = (28224000 / (reg + 1));
+ return 0;
+}
+
+int hr222_sub_set_clock(struct pcxhr_mgr *mgr,
+ unsigned int rate,
+ int *changed)
+{
+ unsigned int speed, pllreg = 0;
+ int err;
+ unsigned realfreq = rate;
+
+ switch (mgr->use_clock_type) {
+ case HR22_CLOCK_TYPE_INTERNAL:
+ err = hr222_pll_freq_register(rate, &pllreg, &realfreq);
+ if (err)
+ return err;
+
+ mgr->xlx_cfg &= ~(PCXHR_CFG_CLOCKIN_SEL_MASK |
+ PCXHR_CFG_CLOCK_UER1_SEL_MASK);
+ break;
+ case HR22_CLOCK_TYPE_AES_SYNC:
+ mgr->xlx_cfg |= PCXHR_CFG_CLOCKIN_SEL_MASK;
+ mgr->xlx_cfg &= ~PCXHR_CFG_CLOCK_UER1_SEL_MASK;
+ break;
+ case HR22_CLOCK_TYPE_AES_1:
+ if (!mgr->board_has_aes1)
+ return -EINVAL;
+
+ mgr->xlx_cfg |= (PCXHR_CFG_CLOCKIN_SEL_MASK |
+ PCXHR_CFG_CLOCK_UER1_SEL_MASK);
+ break;
+ default:
+ return -EINVAL;
+ }
+ hr222_config_akm(mgr, AKM_MUTE_CMD);
+
+ if (mgr->use_clock_type == HR22_CLOCK_TYPE_INTERNAL) {
+ PCXHR_OUTPB(mgr, PCXHR_XLX_HIFREQ, pllreg >> 8);
+ PCXHR_OUTPB(mgr, PCXHR_XLX_LOFREQ, pllreg & 0xff);
+ }
+
+ /* set clock source */
+ PCXHR_OUTPB(mgr, PCXHR_XLX_CFG, mgr->xlx_cfg);
+
+ /* codec speed modes */
+ speed = rate < 55000 ? 0 : 1;
+ if (mgr->codec_speed != speed) {
+ mgr->codec_speed = speed;
+ if (speed == 0)
+ hr222_config_akm(mgr, AKM_CLOCK_INF_55K_CMD);
+ else
+ hr222_config_akm(mgr, AKM_CLOCK_SUP_55K_CMD);
+ }
+
+ mgr->sample_rate_real = realfreq;
+ mgr->cur_clock_type = mgr->use_clock_type;
+
+ if (changed)
+ *changed = 1;
+
+ hr222_config_akm(mgr, AKM_UNMUTE_CMD);
+
+ snd_printdd("set_clock to %dHz (realfreq=%d pllreg=%x)\n",
+ rate, realfreq, pllreg);
+ return 0;
+}
+
+int hr222_get_external_clock(struct pcxhr_mgr *mgr,
+ enum pcxhr_clock_type clock_type,
+ int *sample_rate)
+{
+ int rate, calc_rate = 0;
+ unsigned int ticks;
+ unsigned char mask, reg;
+
+ if (clock_type == HR22_CLOCK_TYPE_AES_SYNC) {
+
+ mask = (PCXHR_SUER_CLOCK_PRESENT_MASK |
+ PCXHR_SUER_DATA_PRESENT_MASK);
+ reg = PCXHR_STAT_FREQ_SYNC_MASK;
+
+ } else if (clock_type == HR22_CLOCK_TYPE_AES_1 && mgr->board_has_aes1) {
+
+ mask = (PCXHR_SUER1_CLOCK_PRESENT_MASK |
+ PCXHR_SUER1_DATA_PRESENT_MASK);
+ reg = PCXHR_STAT_FREQ_UER1_MASK;
+
+ } else {
+ snd_printdd("get_external_clock : type %d not supported\n",
+ clock_type);
+ return -EINVAL; /* other clocks not supported */
+ }
+
+ if ((PCXHR_INPB(mgr, PCXHR_XLX_CSUER) & mask) != mask) {
+ snd_printdd("get_external_clock(%d) = 0 Hz\n", clock_type);
+ *sample_rate = 0;
+ return 0; /* no external clock locked */
+ }
+
+ PCXHR_OUTPB(mgr, PCXHR_XLX_STATUS, reg); /* calculate freq */
+
+ /* save the measured clock frequency */
+ reg |= PCXHR_STAT_FREQ_SAVE_MASK;
+
+ if (mgr->last_reg_stat != reg) {
+ udelay(500); /* wait min 2 cycles of lowest freq (8000) */
+ mgr->last_reg_stat = reg;
+ }
+
+ PCXHR_OUTPB(mgr, PCXHR_XLX_STATUS, reg); /* save */
+
+ /* get the frequency */
+ ticks = (unsigned int)PCXHR_INPB(mgr, PCXHR_XLX_CFG);
+ ticks = (ticks & 0x03) << 8;
+ ticks |= (unsigned int)PCXHR_INPB(mgr, PCXHR_DSP_RESET);
+
+ if (ticks != 0)
+ calc_rate = 28224000 / ticks;
+ /* rounding */
+ if (calc_rate > 184200)
+ rate = 192000;
+ else if (calc_rate > 152200)
+ rate = 176400;
+ else if (calc_rate > 112000)
+ rate = 128000;
+ else if (calc_rate > 92100)
+ rate = 96000;
+ else if (calc_rate > 76100)
+ rate = 88200;
+ else if (calc_rate > 56000)
+ rate = 64000;
+ else if (calc_rate > 46050)
+ rate = 48000;
+ else if (calc_rate > 38050)
+ rate = 44100;
+ else if (calc_rate > 28000)
+ rate = 32000;
+ else if (calc_rate > 23025)
+ rate = 24000;
+ else if (calc_rate > 19025)
+ rate = 22050;
+ else if (calc_rate > 14000)
+ rate = 16000;
+ else if (calc_rate > 11512)
+ rate = 12000;
+ else if (calc_rate > 9512)
+ rate = 11025;
+ else if (calc_rate > 7000)
+ rate = 8000;
+ else
+ rate = 0;
+
+ snd_printdd("External clock is at %d Hz (measured %d Hz)\n",
+ rate, calc_rate);
+ *sample_rate = rate;
+ return 0;
+}
+
+
+int hr222_update_analog_audio_level(struct snd_pcxhr *chip,
+ int is_capture, int channel)
+{
+ snd_printdd("hr222_update_analog_audio_level(%s chan=%d)\n",
+ is_capture ? "capture" : "playback", channel);
+ if (is_capture) {
+ int level_l, level_r, level_mic;
+ /* we have to update all levels */
+ if (chip->analog_capture_active) {
+ level_l = chip->analog_capture_volume[0];
+ level_r = chip->analog_capture_volume[1];
+ } else {
+ level_l = HR222_LINE_CAPTURE_LEVEL_MIN;
+ level_r = HR222_LINE_CAPTURE_LEVEL_MIN;
+ }
+ if (chip->mic_active)
+ level_mic = chip->mic_volume;
+ else
+ level_mic = HR222_MICRO_CAPTURE_LEVEL_MIN;
+ return hr222_set_hw_capture_level(chip->mgr,
+ level_l, level_r, level_mic);
+ } else {
+ int vol;
+ if (chip->analog_playback_active[channel])
+ vol = chip->analog_playback_volume[channel];
+ else
+ vol = HR222_LINE_PLAYBACK_LEVEL_MIN;
+ return hr222_set_hw_playback_level(chip->mgr, channel, vol);
+ }
+}
+
+
+/*texts[5] = {"Line", "Digital", "Digi+SRC", "Mic", "Line+Mic"}*/
+#define SOURCE_LINE 0
+#define SOURCE_DIGITAL 1
+#define SOURCE_DIGISRC 2
+#define SOURCE_MIC 3
+#define SOURCE_LINEMIC 4
+
+int hr222_set_audio_source(struct snd_pcxhr *chip)
+{
+ int digital = 0;
+ /* default analog source */
+ chip->mgr->xlx_cfg &= ~(PCXHR_CFG_SRC_MASK |
+ PCXHR_CFG_DATAIN_SEL_MASK |
+ PCXHR_CFG_DATA_UER1_SEL_MASK);
+
+ if (chip->audio_capture_source == SOURCE_DIGISRC) {
+ chip->mgr->xlx_cfg |= PCXHR_CFG_SRC_MASK;
+ digital = 1;
+ } else {
+ if (chip->audio_capture_source == SOURCE_DIGITAL)
+ digital = 1;
+ }
+ if (digital) {
+ chip->mgr->xlx_cfg |= PCXHR_CFG_DATAIN_SEL_MASK;
+ if (chip->mgr->board_has_aes1) {
+ /* get data from the AES1 plug */
+ chip->mgr->xlx_cfg |= PCXHR_CFG_DATA_UER1_SEL_MASK;
+ }
+ /* chip->mic_active = 0; */
+ /* chip->analog_capture_active = 0; */
+ } else {
+ int update_lvl = 0;
+ chip->analog_capture_active = 0;
+ chip->mic_active = 0;
+ if (chip->audio_capture_source == SOURCE_LINE ||
+ chip->audio_capture_source == SOURCE_LINEMIC) {
+ if (chip->analog_capture_active == 0)
+ update_lvl = 1;
+ chip->analog_capture_active = 1;
+ }
+ if (chip->audio_capture_source == SOURCE_MIC ||
+ chip->audio_capture_source == SOURCE_LINEMIC) {
+ if (chip->mic_active == 0)
+ update_lvl = 1;
+ chip->mic_active = 1;
+ }
+ if (update_lvl) {
+ /* capture: update all 3 mutes/unmutes with one call */
+ hr222_update_analog_audio_level(chip, 1, 0);
+ }
+ }
+ /* set the source infos (max 3 bits modified) */
+ PCXHR_OUTPB(chip->mgr, PCXHR_XLX_CFG, chip->mgr->xlx_cfg);
+ return 0;
+}
+
+
+int hr222_iec958_capture_byte(struct snd_pcxhr *chip,
+ int aes_idx, unsigned char *aes_bits)
+{
+ unsigned char idx = (unsigned char)(aes_idx * 8);
+ unsigned char temp = 0;
+ unsigned char mask = chip->mgr->board_has_aes1 ?
+ PCXHR_SUER1_BIT_C_READ_MASK : PCXHR_SUER_BIT_C_READ_MASK;
+ int i;
+ for (i = 0; i < 8; i++) {
+ PCXHR_OUTPB(chip->mgr, PCXHR_XLX_RUER, idx++); /* idx < 192 */
+ temp <<= 1;
+ if (PCXHR_INPB(chip->mgr, PCXHR_XLX_CSUER) & mask)
+ temp |= 1;
+ }
+ snd_printdd("read iec958 AES %d byte %d = 0x%x\n",
+ chip->chip_idx, aes_idx, temp);
+ *aes_bits = temp;
+ return 0;
+}
+
+
+int hr222_iec958_update_byte(struct snd_pcxhr *chip,
+ int aes_idx, unsigned char aes_bits)
+{
+ int i;
+ unsigned char new_bits = aes_bits;
+ unsigned char old_bits = chip->aes_bits[aes_idx];
+ unsigned char idx = (unsigned char)(aes_idx * 8);
+ for (i = 0; i < 8; i++) {
+ if ((old_bits & 0x01) != (new_bits & 0x01)) {
+ /* idx < 192 */
+ PCXHR_OUTPB(chip->mgr, PCXHR_XLX_RUER, idx);
+ /* write C and U bit */
+ PCXHR_OUTPB(chip->mgr, PCXHR_XLX_CSUER, new_bits&0x01 ?
+ PCXHR_SUER_BIT_C_WRITE_MASK : 0);
+ }
+ idx++;
+ old_bits >>= 1;
+ new_bits >>= 1;
+ }
+ chip->aes_bits[aes_idx] = aes_bits;
+ return 0;
+}
+
+static void hr222_micro_boost(struct pcxhr_mgr *mgr, int level)
+{
+ unsigned char boost_mask;
+ boost_mask = (unsigned char) (level << PCXHR_SELMIC_PREAMPLI_OFFSET);
+ if (boost_mask & (~PCXHR_SELMIC_PREAMPLI_MASK))
+ return; /* only values form 0 to 3 accepted */
+
+ mgr->xlx_selmic &= ~PCXHR_SELMIC_PREAMPLI_MASK;
+ mgr->xlx_selmic |= boost_mask;
+
+ PCXHR_OUTPB(mgr, PCXHR_XLX_SELMIC, mgr->xlx_selmic);
+
+ snd_printdd("hr222_micro_boost : set %x\n", boost_mask);
+}
+
+static void hr222_phantom_power(struct pcxhr_mgr *mgr, int power)
+{
+ if (power)
+ mgr->xlx_selmic |= PCXHR_SELMIC_PHANTOM_ALIM;
+ else
+ mgr->xlx_selmic &= ~PCXHR_SELMIC_PHANTOM_ALIM;
+
+ PCXHR_OUTPB(mgr, PCXHR_XLX_SELMIC, mgr->xlx_selmic);
+
+ snd_printdd("hr222_phantom_power : set %d\n", power);
+}
+
+
+/* mic level */
+static const DECLARE_TLV_DB_SCALE(db_scale_mic_hr222, -9850, 50, 650);
+
+static int hr222_mic_vol_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 1;
+ uinfo->value.integer.min = HR222_MICRO_CAPTURE_LEVEL_MIN; /* -98 dB */
+ /* gains from 9 dB to 31.5 dB not recommended; use micboost instead */
+ uinfo->value.integer.max = HR222_MICRO_CAPTURE_LEVEL_MAX; /* +7 dB */
+ return 0;
+}
+
+static int hr222_mic_vol_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
+ mutex_lock(&chip->mgr->mixer_mutex);
+ ucontrol->value.integer.value[0] = chip->mic_volume;
+ mutex_unlock(&chip->mgr->mixer_mutex);
+ return 0;
+}
+
+static int hr222_mic_vol_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
+ int changed = 0;
+ mutex_lock(&chip->mgr->mixer_mutex);
+ if (chip->mic_volume != ucontrol->value.integer.value[0]) {
+ changed = 1;
+ chip->mic_volume = ucontrol->value.integer.value[0];
+ hr222_update_analog_audio_level(chip, 1, 0);
+ }
+ mutex_unlock(&chip->mgr->mixer_mutex);
+ return changed;
+}
+
+static struct snd_kcontrol_new hr222_control_mic_level = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
+ SNDRV_CTL_ELEM_ACCESS_TLV_READ),
+ .name = "Mic Capture Volume",
+ .info = hr222_mic_vol_info,
+ .get = hr222_mic_vol_get,
+ .put = hr222_mic_vol_put,
+ .tlv = { .p = db_scale_mic_hr222 },
+};
+
+
+/* mic boost level */
+static const DECLARE_TLV_DB_SCALE(db_scale_micboost_hr222, 0, 1800, 5400);
+
+static int hr222_mic_boost_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0; /* 0 dB */
+ uinfo->value.integer.max = 3; /* 54 dB */
+ return 0;
+}
+
+static int hr222_mic_boost_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
+ mutex_lock(&chip->mgr->mixer_mutex);
+ ucontrol->value.integer.value[0] = chip->mic_boost;
+ mutex_unlock(&chip->mgr->mixer_mutex);
+ return 0;
+}
+
+static int hr222_mic_boost_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
+ int changed = 0;
+ mutex_lock(&chip->mgr->mixer_mutex);
+ if (chip->mic_boost != ucontrol->value.integer.value[0]) {
+ changed = 1;
+ chip->mic_boost = ucontrol->value.integer.value[0];
+ hr222_micro_boost(chip->mgr, chip->mic_boost);
+ }
+ mutex_unlock(&chip->mgr->mixer_mutex);
+ return changed;
+}
+
+static struct snd_kcontrol_new hr222_control_mic_boost = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
+ SNDRV_CTL_ELEM_ACCESS_TLV_READ),
+ .name = "MicBoost Capture Volume",
+ .info = hr222_mic_boost_info,
+ .get = hr222_mic_boost_get,
+ .put = hr222_mic_boost_put,
+ .tlv = { .p = db_scale_micboost_hr222 },
+};
+
+
+/******************* Phantom power switch *******************/
+#define hr222_phantom_power_info snd_ctl_boolean_mono_info
+
+static int hr222_phantom_power_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
+ mutex_lock(&chip->mgr->mixer_mutex);
+ ucontrol->value.integer.value[0] = chip->phantom_power;
+ mutex_unlock(&chip->mgr->mixer_mutex);
+ return 0;
+}
+
+static int hr222_phantom_power_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
+ int power, changed = 0;
+
+ mutex_lock(&chip->mgr->mixer_mutex);
+ power = !!ucontrol->value.integer.value[0];
+ if (chip->phantom_power != power) {
+ hr222_phantom_power(chip->mgr, power);
+ chip->phantom_power = power;
+ changed = 1;
+ }
+ mutex_unlock(&chip->mgr->mixer_mutex);
+ return changed;
+}
+
+static struct snd_kcontrol_new hr222_phantom_power_switch = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Phantom Power Switch",
+ .info = hr222_phantom_power_info,
+ .get = hr222_phantom_power_get,
+ .put = hr222_phantom_power_put,
+};
+
+
+int hr222_add_mic_controls(struct snd_pcxhr *chip)
+{
+ int err;
+ if (!chip->mgr->board_has_mic)
+ return 0;
+
+ /* controls */
+ err = snd_ctl_add(chip->card, snd_ctl_new1(&hr222_control_mic_level,
+ chip));
+ if (err < 0)
+ return err;
+
+ err = snd_ctl_add(chip->card, snd_ctl_new1(&hr222_control_mic_boost,
+ chip));
+ if (err < 0)
+ return err;
+
+ err = snd_ctl_add(chip->card, snd_ctl_new1(&hr222_phantom_power_switch,
+ chip));
+ return err;
+}
diff --git a/sound/pci/pcxhr/pcxhr_mix22.h b/sound/pci/pcxhr/pcxhr_mix22.h
new file mode 100644
index 00000000000..6b318b2f010
--- /dev/null
+++ b/sound/pci/pcxhr/pcxhr_mix22.h
@@ -0,0 +1,56 @@
+/*
+ * Driver for Digigram pcxhr compatible soundcards
+ *
+ * low level interface with interrupt ans message handling
+ *
+ * Copyright (c) 2004 by Digigram <alsa@digigram.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __SOUND_PCXHR_MIX22_H
+#define __SOUND_PCXHR_MIX22_H
+
+struct pcxhr_mgr;
+
+int hr222_sub_init(struct pcxhr_mgr *mgr);
+int hr222_sub_set_clock(struct pcxhr_mgr *mgr, unsigned int rate,
+ int *changed);
+int hr222_get_external_clock(struct pcxhr_mgr *mgr,
+ enum pcxhr_clock_type clock_type,
+ int *sample_rate);
+
+#define HR222_LINE_PLAYBACK_LEVEL_MIN 0 /* -25.5 dB */
+#define HR222_LINE_PLAYBACK_ZERO_LEVEL 51 /* 0.0 dB */
+#define HR222_LINE_PLAYBACK_LEVEL_MAX 99 /* +24.0 dB */
+
+#define HR222_LINE_CAPTURE_LEVEL_MIN 0 /* -111.5 dB */
+#define HR222_LINE_CAPTURE_ZERO_LEVEL 223 /* 0.0 dB */
+#define HR222_LINE_CAPTURE_LEVEL_MAX 255 /* +16 dB */
+#define HR222_MICRO_CAPTURE_LEVEL_MIN 0 /* -98.5 dB */
+#define HR222_MICRO_CAPTURE_LEVEL_MAX 210 /* +6.5 dB */
+
+int hr222_update_analog_audio_level(struct snd_pcxhr *chip,
+ int is_capture,
+ int channel);
+int hr222_set_audio_source(struct snd_pcxhr *chip);
+int hr222_iec958_capture_byte(struct snd_pcxhr *chip, int aes_idx,
+ unsigned char *aes_bits);
+int hr222_iec958_update_byte(struct snd_pcxhr *chip, int aes_idx,
+ unsigned char aes_bits);
+
+int hr222_add_mic_controls(struct snd_pcxhr *chip);
+
+#endif /* __SOUND_PCXHR_MIX22_H */
diff --git a/sound/pci/pcxhr/pcxhr_mixer.c b/sound/pci/pcxhr/pcxhr_mixer.c
index aabc7bc5321..2436e374586 100644
--- a/sound/pci/pcxhr/pcxhr_mixer.c
+++ b/sound/pci/pcxhr/pcxhr_mixer.c
@@ -33,20 +33,24 @@
#include <sound/tlv.h>
#include <sound/asoundef.h>
#include "pcxhr_mixer.h"
+#include "pcxhr_mix22.h"
+#define PCXHR_LINE_CAPTURE_LEVEL_MIN 0 /* -112.0 dB */
+#define PCXHR_LINE_CAPTURE_LEVEL_MAX 255 /* +15.5 dB */
+#define PCXHR_LINE_CAPTURE_ZERO_LEVEL 224 /* 0.0 dB ( 0 dBu -> 0 dBFS ) */
-#define PCXHR_ANALOG_CAPTURE_LEVEL_MIN 0 /* -96.0 dB */
-#define PCXHR_ANALOG_CAPTURE_LEVEL_MAX 255 /* +31.5 dB */
-#define PCXHR_ANALOG_CAPTURE_ZERO_LEVEL 224 /* +16.0 dB ( +31.5 dB - fix level +15.5 dB ) */
+#define PCXHR_LINE_PLAYBACK_LEVEL_MIN 0 /* -104.0 dB */
+#define PCXHR_LINE_PLAYBACK_LEVEL_MAX 128 /* +24.0 dB */
+#define PCXHR_LINE_PLAYBACK_ZERO_LEVEL 104 /* 0.0 dB ( 0 dBFS -> 0 dBu ) */
-#define PCXHR_ANALOG_PLAYBACK_LEVEL_MIN 0 /* -128.0 dB */
-#define PCXHR_ANALOG_PLAYBACK_LEVEL_MAX 128 /* 0.0 dB */
-#define PCXHR_ANALOG_PLAYBACK_ZERO_LEVEL 104 /* -24.0 dB ( 0.0 dB - fix level +24.0 dB ) */
-
-static const DECLARE_TLV_DB_SCALE(db_scale_analog_capture, -9600, 50, 3150);
+static const DECLARE_TLV_DB_SCALE(db_scale_analog_capture, -11200, 50, 1550);
static const DECLARE_TLV_DB_SCALE(db_scale_analog_playback, -10400, 100, 2400);
-static int pcxhr_update_analog_audio_level(struct snd_pcxhr *chip, int is_capture, int channel)
+static const DECLARE_TLV_DB_SCALE(db_scale_a_hr222_capture, -11150, 50, 1600);
+static const DECLARE_TLV_DB_SCALE(db_scale_a_hr222_playback, -2550, 50, 2400);
+
+static int pcxhr_update_analog_audio_level(struct snd_pcxhr *chip,
+ int is_capture, int channel)
{
int err, vol;
struct pcxhr_rmh rmh;
@@ -60,15 +64,17 @@ static int pcxhr_update_analog_audio_level(struct snd_pcxhr *chip, int is_captur
if (chip->analog_playback_active[channel])
vol = chip->analog_playback_volume[channel];
else
- vol = PCXHR_ANALOG_PLAYBACK_LEVEL_MIN;
- rmh.cmd[2] = PCXHR_ANALOG_PLAYBACK_LEVEL_MAX - vol; /* playback analog levels are inversed */
+ vol = PCXHR_LINE_PLAYBACK_LEVEL_MIN;
+ /* playback analog levels are inversed */
+ rmh.cmd[2] = PCXHR_LINE_PLAYBACK_LEVEL_MAX - vol;
}
rmh.cmd[1] = 1 << ((2 * chip->chip_idx) + channel); /* audio mask */
rmh.cmd_len = 3;
err = pcxhr_send_msg(chip->mgr, &rmh);
if (err < 0) {
- snd_printk(KERN_DEBUG "error update_analog_audio_level card(%d) "
- "is_capture(%d) err(%x)\n", chip->chip_idx, is_capture, err);
+ snd_printk(KERN_DEBUG "error update_analog_audio_level card(%d)"
+ " is_capture(%d) err(%x)\n",
+ chip->chip_idx, is_capture, err);
return -EINVAL;
}
return 0;
@@ -80,14 +86,34 @@ static int pcxhr_update_analog_audio_level(struct snd_pcxhr *chip, int is_captur
static int pcxhr_analog_vol_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
+ struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
+
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
if (kcontrol->private_value == 0) { /* playback */
- uinfo->value.integer.min = PCXHR_ANALOG_PLAYBACK_LEVEL_MIN; /* -128 dB */
- uinfo->value.integer.max = PCXHR_ANALOG_PLAYBACK_LEVEL_MAX; /* 0 dB */
+ if (chip->mgr->is_hr_stereo) {
+ uinfo->value.integer.min =
+ HR222_LINE_PLAYBACK_LEVEL_MIN; /* -25 dB */
+ uinfo->value.integer.max =
+ HR222_LINE_PLAYBACK_LEVEL_MAX; /* +24 dB */
+ } else {
+ uinfo->value.integer.min =
+ PCXHR_LINE_PLAYBACK_LEVEL_MIN; /*-104 dB */
+ uinfo->value.integer.max =
+ PCXHR_LINE_PLAYBACK_LEVEL_MAX; /* +24 dB */
+ }
} else { /* capture */
- uinfo->value.integer.min = PCXHR_ANALOG_CAPTURE_LEVEL_MIN; /* -96 dB */
- uinfo->value.integer.max = PCXHR_ANALOG_CAPTURE_LEVEL_MAX; /* 31.5 dB */
+ if (chip->mgr->is_hr_stereo) {
+ uinfo->value.integer.min =
+ HR222_LINE_CAPTURE_LEVEL_MIN; /*-112 dB */
+ uinfo->value.integer.max =
+ HR222_LINE_CAPTURE_LEVEL_MAX; /* +15.5 dB */
+ } else {
+ uinfo->value.integer.min =
+ PCXHR_LINE_CAPTURE_LEVEL_MIN; /*-112 dB */
+ uinfo->value.integer.max =
+ PCXHR_LINE_CAPTURE_LEVEL_MAX; /* +15.5 dB */
+ }
}
return 0;
}
@@ -98,11 +124,11 @@ static int pcxhr_analog_vol_get(struct snd_kcontrol *kcontrol,
struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
mutex_lock(&chip->mgr->mixer_mutex);
if (kcontrol->private_value == 0) { /* playback */
- ucontrol->value.integer.value[0] = chip->analog_playback_volume[0];
- ucontrol->value.integer.value[1] = chip->analog_playback_volume[1];
+ ucontrol->value.integer.value[0] = chip->analog_playback_volume[0];
+ ucontrol->value.integer.value[1] = chip->analog_playback_volume[1];
} else { /* capture */
- ucontrol->value.integer.value[0] = chip->analog_capture_volume[0];
- ucontrol->value.integer.value[1] = chip->analog_capture_volume[1];
+ ucontrol->value.integer.value[0] = chip->analog_capture_volume[0];
+ ucontrol->value.integer.value[1] = chip->analog_capture_volume[1];
}
mutex_unlock(&chip->mgr->mixer_mutex);
return 0;
@@ -123,18 +149,35 @@ static int pcxhr_analog_vol_put(struct snd_kcontrol *kcontrol,
&chip->analog_capture_volume[i] :
&chip->analog_playback_volume[i];
if (is_capture) {
- if (new_volume < PCXHR_ANALOG_CAPTURE_LEVEL_MIN ||
- new_volume > PCXHR_ANALOG_CAPTURE_LEVEL_MAX)
- continue;
+ if (chip->mgr->is_hr_stereo) {
+ if (new_volume < HR222_LINE_CAPTURE_LEVEL_MIN ||
+ new_volume > HR222_LINE_CAPTURE_LEVEL_MAX)
+ continue;
+ } else {
+ if (new_volume < PCXHR_LINE_CAPTURE_LEVEL_MIN ||
+ new_volume > PCXHR_LINE_CAPTURE_LEVEL_MAX)
+ continue;
+ }
} else {
- if (new_volume < PCXHR_ANALOG_PLAYBACK_LEVEL_MIN ||
- new_volume > PCXHR_ANALOG_PLAYBACK_LEVEL_MAX)
- continue;
+ if (chip->mgr->is_hr_stereo) {
+ if (new_volume < HR222_LINE_PLAYBACK_LEVEL_MIN ||
+ new_volume > HR222_LINE_PLAYBACK_LEVEL_MAX)
+ continue;
+ } else {
+ if (new_volume < PCXHR_LINE_PLAYBACK_LEVEL_MIN ||
+ new_volume > PCXHR_LINE_PLAYBACK_LEVEL_MAX)
+ continue;
+ }
}
if (*stored_volume != new_volume) {
*stored_volume = new_volume;
changed = 1;
- pcxhr_update_analog_audio_level(chip, is_capture, i);
+ if (chip->mgr->is_hr_stereo)
+ hr222_update_analog_audio_level(chip,
+ is_capture, i);
+ else
+ pcxhr_update_analog_audio_level(chip,
+ is_capture, i);
}
}
mutex_unlock(&chip->mgr->mixer_mutex);
@@ -153,6 +196,7 @@ static struct snd_kcontrol_new pcxhr_control_analog_level = {
};
/* shared */
+
#define pcxhr_sw_info snd_ctl_boolean_stereo_info
static int pcxhr_audio_sw_get(struct snd_kcontrol *kcontrol,
@@ -180,7 +224,10 @@ static int pcxhr_audio_sw_put(struct snd_kcontrol *kcontrol,
!!ucontrol->value.integer.value[i];
changed = 1;
/* update playback levels */
- pcxhr_update_analog_audio_level(chip, 0, i);
+ if (chip->mgr->is_hr_stereo)
+ hr222_update_analog_audio_level(chip, 0, i);
+ else
+ pcxhr_update_analog_audio_level(chip, 0, i);
}
}
mutex_unlock(&chip->mgr->mixer_mutex);
@@ -251,7 +298,8 @@ static int pcxhr_update_playback_stream_level(struct snd_pcxhr* chip, int idx)
#define VALID_AUDIO_IO_MUTE_LEVEL 0x000004
#define VALID_AUDIO_IO_MUTE_MONITOR_1 0x000008
-static int pcxhr_update_audio_pipe_level(struct snd_pcxhr* chip, int capture, int channel)
+static int pcxhr_update_audio_pipe_level(struct snd_pcxhr *chip,
+ int capture, int channel)
{
int err;
struct pcxhr_rmh rmh;
@@ -264,18 +312,20 @@ static int pcxhr_update_audio_pipe_level(struct snd_pcxhr* chip, int capture, in
pcxhr_init_rmh(&rmh, CMD_AUDIO_LEVEL_ADJUST);
/* add channel mask */
- pcxhr_set_pipe_cmd_params(&rmh, capture, 0, 0, 1 << (channel + pipe->first_audio));
- /* TODO : if mask (3 << pipe->first_audio) is used, left and right channel
- * will be programmed to the same params
- */
+ pcxhr_set_pipe_cmd_params(&rmh, capture, 0, 0,
+ 1 << (channel + pipe->first_audio));
+ /* TODO : if mask (3 << pipe->first_audio) is used, left and right
+ * channel will be programmed to the same params */
if (capture) {
rmh.cmd[0] |= VALID_AUDIO_IO_DIGITAL_LEVEL;
- /* VALID_AUDIO_IO_MUTE_LEVEL not yet handled (capture pipe level) */
+ /* VALID_AUDIO_IO_MUTE_LEVEL not yet handled
+ * (capture pipe level) */
rmh.cmd[2] = chip->digital_capture_volume[channel];
} else {
- rmh.cmd[0] |= VALID_AUDIO_IO_MONITOR_LEVEL | VALID_AUDIO_IO_MUTE_MONITOR_1;
- /* VALID_AUDIO_IO_DIGITAL_LEVEL and VALID_AUDIO_IO_MUTE_LEVEL not yet
- * handled (playback pipe level)
+ rmh.cmd[0] |= VALID_AUDIO_IO_MONITOR_LEVEL |
+ VALID_AUDIO_IO_MUTE_MONITOR_1;
+ /* VALID_AUDIO_IO_DIGITAL_LEVEL and VALID_AUDIO_IO_MUTE_LEVEL
+ * not yet handled (playback pipe level)
*/
rmh.cmd[2] = chip->monitoring_volume[channel] << 10;
if (chip->monitoring_active[channel] == 0)
@@ -284,8 +334,8 @@ static int pcxhr_update_audio_pipe_level(struct snd_pcxhr* chip, int capture, in
rmh.cmd_len = 3;
err = pcxhr_send_msg(chip->mgr, &rmh);
- if(err<0) {
- snd_printk(KERN_DEBUG "error update_audio_level card(%d) err(%x)\n",
+ if (err < 0) {
+ snd_printk(KERN_DEBUG "error update_audio_level(%d) err=%x\n",
chip->chip_idx, err);
return -EINVAL;
}
@@ -309,15 +359,15 @@ static int pcxhr_pcm_vol_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
- int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */
+ int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */
int *stored_volume;
int is_capture = kcontrol->private_value;
mutex_lock(&chip->mgr->mixer_mutex);
- if (is_capture)
- stored_volume = chip->digital_capture_volume; /* digital capture */
- else
- stored_volume = chip->digital_playback_volume[idx]; /* digital playback */
+ if (is_capture) /* digital capture */
+ stored_volume = chip->digital_capture_volume;
+ else /* digital playback */
+ stored_volume = chip->digital_playback_volume[idx];
ucontrol->value.integer.value[0] = stored_volume[0];
ucontrol->value.integer.value[1] = stored_volume[1];
mutex_unlock(&chip->mgr->mixer_mutex);
@@ -328,7 +378,7 @@ static int pcxhr_pcm_vol_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
- int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */
+ int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */
int changed = 0;
int is_capture = kcontrol->private_value;
int *stored_volume;
@@ -384,7 +434,8 @@ static int pcxhr_pcm_sw_get(struct snd_kcontrol *kcontrol,
return 0;
}
-static int pcxhr_pcm_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+static int pcxhr_pcm_sw_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
int changed = 0;
@@ -444,8 +495,8 @@ static int pcxhr_monitor_vol_put(struct snd_kcontrol *kcontrol,
if (chip->monitoring_volume[i] !=
ucontrol->value.integer.value[i]) {
chip->monitoring_volume[i] =
- !!ucontrol->value.integer.value[i];
- if(chip->monitoring_active[i])
+ ucontrol->value.integer.value[i];
+ if (chip->monitoring_active[i])
/* update monitoring volume and mute */
/* do only when monitoring is unmuted */
pcxhr_update_audio_pipe_level(chip, 0, i);
@@ -460,7 +511,7 @@ static struct snd_kcontrol_new pcxhr_control_monitor_vol = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
SNDRV_CTL_ELEM_ACCESS_TLV_READ),
- .name = "Monitoring Volume",
+ .name = "Monitoring Playback Volume",
.info = pcxhr_digital_vol_info, /* shared */
.get = pcxhr_monitor_vol_get,
.put = pcxhr_monitor_vol_put,
@@ -511,7 +562,7 @@ static int pcxhr_monitor_sw_put(struct snd_kcontrol *kcontrol,
static struct snd_kcontrol_new pcxhr_control_monitor_sw = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Monitoring Switch",
+ .name = "Monitoring Playback Switch",
.info = pcxhr_sw_info, /* shared */
.get = pcxhr_monitor_sw_get,
.put = pcxhr_monitor_sw_put
@@ -533,7 +584,7 @@ static int pcxhr_set_audio_source(struct snd_pcxhr* chip)
struct pcxhr_rmh rmh;
unsigned int mask, reg;
unsigned int codec;
- int err, use_src, changed;
+ int err, changed;
switch (chip->chip_idx) {
case 0 : mask = PCXHR_SOURCE_AUDIO01_UER; codec = CS8420_01_CS; break;
@@ -542,13 +593,10 @@ static int pcxhr_set_audio_source(struct snd_pcxhr* chip)
case 3 : mask = PCXHR_SOURCE_AUDIO67_UER; codec = CS8420_67_CS; break;
default: return -EINVAL;
}
- reg = 0; /* audio source from analog plug */
- use_src = 0; /* do not activate codec SRC */
-
if (chip->audio_capture_source != 0) {
reg = mask; /* audio source from digital plug */
- if (chip->audio_capture_source == 2)
- use_src = 1;
+ } else {
+ reg = 0; /* audio source from analog plug */
}
/* set the input source */
pcxhr_write_io_num_reg_cont(chip->mgr, mask, reg, &changed);
@@ -560,29 +608,61 @@ static int pcxhr_set_audio_source(struct snd_pcxhr* chip)
if (err)
return err;
}
- pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE); /* set codec SRC on off */
- rmh.cmd_len = 3;
- rmh.cmd[0] |= IO_NUM_UER_CHIP_REG;
- rmh.cmd[1] = codec;
- rmh.cmd[2] = (CS8420_DATA_FLOW_CTL & CHIP_SIG_AND_MAP_SPI) | (use_src ? 0x41 : 0x54);
- err = pcxhr_send_msg(chip->mgr, &rmh);
- if(err)
- return err;
- rmh.cmd[2] = (CS8420_CLOCK_SRC_CTL & CHIP_SIG_AND_MAP_SPI) | (use_src ? 0x41 : 0x49);
- err = pcxhr_send_msg(chip->mgr, &rmh);
+ if (chip->mgr->board_aes_in_192k) {
+ int i;
+ unsigned int src_config = 0xC0;
+ /* update all src configs with one call */
+ for (i = 0; (i < 4) && (i < chip->mgr->capture_chips); i++) {
+ if (chip->mgr->chip[i]->audio_capture_source == 2)
+ src_config |= (1 << (3 - i));
+ }
+ /* set codec SRC on off */
+ pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE);
+ rmh.cmd_len = 2;
+ rmh.cmd[0] |= IO_NUM_REG_CONFIG_SRC;
+ rmh.cmd[1] = src_config;
+ err = pcxhr_send_msg(chip->mgr, &rmh);
+ } else {
+ int use_src = 0;
+ if (chip->audio_capture_source == 2)
+ use_src = 1;
+ /* set codec SRC on off */
+ pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE);
+ rmh.cmd_len = 3;
+ rmh.cmd[0] |= IO_NUM_UER_CHIP_REG;
+ rmh.cmd[1] = codec;
+ rmh.cmd[2] = ((CS8420_DATA_FLOW_CTL & CHIP_SIG_AND_MAP_SPI) |
+ (use_src ? 0x41 : 0x54));
+ err = pcxhr_send_msg(chip->mgr, &rmh);
+ if (err)
+ return err;
+ rmh.cmd[2] = ((CS8420_CLOCK_SRC_CTL & CHIP_SIG_AND_MAP_SPI) |
+ (use_src ? 0x41 : 0x49));
+ err = pcxhr_send_msg(chip->mgr, &rmh);
+ }
return err;
}
static int pcxhr_audio_src_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
- static char *texts[3] = {"Analog", "Digital", "Digi+SRC"};
+ static const char *texts[5] = {
+ "Line", "Digital", "Digi+SRC", "Mic", "Line+Mic"
+ };
+ int i;
+ struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
+ i = 2; /* no SRC, no Mic available */
+ if (chip->mgr->board_has_aes1) {
+ i = 3; /* SRC available */
+ if (chip->mgr->board_has_mic)
+ i = 5; /* Mic and MicroMix available */
+ }
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
- uinfo->value.enumerated.items = 3;
- if (uinfo->value.enumerated.item > 2)
- uinfo->value.enumerated.item = 2;
+ uinfo->value.enumerated.items = i;
+ if (uinfo->value.enumerated.item > (i-1))
+ uinfo->value.enumerated.item = i-1;
strcpy(uinfo->value.enumerated.name,
texts[uinfo->value.enumerated.item]);
return 0;
@@ -601,13 +681,21 @@ static int pcxhr_audio_src_put(struct snd_kcontrol *kcontrol,
{
struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
int ret = 0;
-
- if (ucontrol->value.enumerated.item[0] >= 3)
+ int i = 2; /* no SRC, no Mic available */
+ if (chip->mgr->board_has_aes1) {
+ i = 3; /* SRC available */
+ if (chip->mgr->board_has_mic)
+ i = 5; /* Mic and MicroMix available */
+ }
+ if (ucontrol->value.enumerated.item[0] >= i)
return -EINVAL;
mutex_lock(&chip->mgr->mixer_mutex);
if (chip->audio_capture_source != ucontrol->value.enumerated.item[0]) {
chip->audio_capture_source = ucontrol->value.enumerated.item[0];
- pcxhr_set_audio_source(chip);
+ if (chip->mgr->is_hr_stereo)
+ hr222_set_audio_source(chip);
+ else
+ pcxhr_set_audio_source(chip);
ret = 1;
}
mutex_unlock(&chip->mgr->mixer_mutex);
@@ -626,25 +714,46 @@ static struct snd_kcontrol_new pcxhr_control_audio_src = {
/*
* clock type selection
* enum pcxhr_clock_type {
- * PCXHR_CLOCK_TYPE_INTERNAL = 0,
- * PCXHR_CLOCK_TYPE_WORD_CLOCK,
- * PCXHR_CLOCK_TYPE_AES_SYNC,
- * PCXHR_CLOCK_TYPE_AES_1,
- * PCXHR_CLOCK_TYPE_AES_2,
- * PCXHR_CLOCK_TYPE_AES_3,
- * PCXHR_CLOCK_TYPE_AES_4,
- * };
+ * PCXHR_CLOCK_TYPE_INTERNAL = 0,
+ * PCXHR_CLOCK_TYPE_WORD_CLOCK,
+ * PCXHR_CLOCK_TYPE_AES_SYNC,
+ * PCXHR_CLOCK_TYPE_AES_1,
+ * PCXHR_CLOCK_TYPE_AES_2,
+ * PCXHR_CLOCK_TYPE_AES_3,
+ * PCXHR_CLOCK_TYPE_AES_4,
+ * PCXHR_CLOCK_TYPE_MAX = PCXHR_CLOCK_TYPE_AES_4,
+ * HR22_CLOCK_TYPE_INTERNAL = PCXHR_CLOCK_TYPE_INTERNAL,
+ * HR22_CLOCK_TYPE_AES_SYNC,
+ * HR22_CLOCK_TYPE_AES_1,
+ * HR22_CLOCK_TYPE_MAX = HR22_CLOCK_TYPE_AES_1,
+ * };
*/
static int pcxhr_clock_type_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
- static char *texts[7] = {
- "Internal", "WordClock", "AES Sync", "AES 1", "AES 2", "AES 3", "AES 4"
+ static const char *textsPCXHR[7] = {
+ "Internal", "WordClock", "AES Sync",
+ "AES 1", "AES 2", "AES 3", "AES 4"
+ };
+ static const char *textsHR22[3] = {
+ "Internal", "AES Sync", "AES 1"
};
+ const char **texts;
struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol);
- int clock_items = 3 + mgr->capture_chips;
-
+ int clock_items = 2; /* at least Internal and AES Sync clock */
+ if (mgr->board_has_aes1) {
+ clock_items += mgr->capture_chips; /* add AES x */
+ if (!mgr->is_hr_stereo)
+ clock_items += 1; /* add word clock */
+ }
+ if (mgr->is_hr_stereo) {
+ texts = textsHR22;
+ snd_BUG_ON(clock_items > (HR22_CLOCK_TYPE_MAX+1));
+ } else {
+ texts = textsPCXHR;
+ snd_BUG_ON(clock_items > (PCXHR_CLOCK_TYPE_MAX+1));
+ }
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
uinfo->value.enumerated.items = clock_items;
@@ -667,9 +776,13 @@ static int pcxhr_clock_type_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol);
- unsigned int clock_items = 3 + mgr->capture_chips;
int rate, ret = 0;
-
+ unsigned int clock_items = 2; /* at least Internal and AES Sync clock */
+ if (mgr->board_has_aes1) {
+ clock_items += mgr->capture_chips; /* add AES x */
+ if (!mgr->is_hr_stereo)
+ clock_items += 1; /* add word clock */
+ }
if (ucontrol->value.enumerated.item[0] >= clock_items)
return -EINVAL;
mutex_lock(&mgr->mixer_mutex);
@@ -677,7 +790,8 @@ static int pcxhr_clock_type_put(struct snd_kcontrol *kcontrol,
mutex_lock(&mgr->setup_mutex);
mgr->use_clock_type = ucontrol->value.enumerated.item[0];
if (mgr->use_clock_type)
- pcxhr_get_external_clock(mgr, mgr->use_clock_type, &rate);
+ pcxhr_get_external_clock(mgr, mgr->use_clock_type,
+ &rate);
else
rate = mgr->sample_rate;
if (rate) {
@@ -686,7 +800,7 @@ static int pcxhr_clock_type_put(struct snd_kcontrol *kcontrol,
mgr->sample_rate = rate;
}
mutex_unlock(&mgr->setup_mutex);
- ret = 1; /* return 1 even if the set was not done. ok ? */
+ ret = 1; /* return 1 even if the set was not done. ok ? */
}
mutex_unlock(&mgr->mixer_mutex);
return ret;
@@ -747,14 +861,16 @@ static struct snd_kcontrol_new pcxhr_control_clock_rate = {
/*
* IEC958 status bits
*/
-static int pcxhr_iec958_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
+static int pcxhr_iec958_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
return 0;
}
-static int pcxhr_iec958_capture_byte(struct snd_pcxhr *chip, int aes_idx, unsigned char* aes_bits)
+static int pcxhr_iec958_capture_byte(struct snd_pcxhr *chip,
+ int aes_idx, unsigned char *aes_bits)
{
int i, err;
unsigned char temp;
@@ -763,39 +879,61 @@ static int pcxhr_iec958_capture_byte(struct snd_pcxhr *chip, int aes_idx, unsign
pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_READ);
rmh.cmd[0] |= IO_NUM_UER_CHIP_REG;
switch (chip->chip_idx) {
- case 0: rmh.cmd[1] = CS8420_01_CS; break; /* use CS8416_01_CS for AES SYNC plug */
+ /* instead of CS8420_01_CS use CS8416_01_CS for AES SYNC plug */
+ case 0: rmh.cmd[1] = CS8420_01_CS; break;
case 1: rmh.cmd[1] = CS8420_23_CS; break;
case 2: rmh.cmd[1] = CS8420_45_CS; break;
case 3: rmh.cmd[1] = CS8420_67_CS; break;
default: return -EINVAL;
}
- switch (aes_idx) {
- case 0: rmh.cmd[2] = CS8420_CSB0; break; /* use CS8416_CSBx for AES SYNC plug */
- case 1: rmh.cmd[2] = CS8420_CSB1; break;
- case 2: rmh.cmd[2] = CS8420_CSB2; break;
- case 3: rmh.cmd[2] = CS8420_CSB3; break;
- case 4: rmh.cmd[2] = CS8420_CSB4; break;
- default: return -EINVAL;
+ if (chip->mgr->board_aes_in_192k) {
+ switch (aes_idx) {
+ case 0: rmh.cmd[2] = CS8416_CSB0; break;
+ case 1: rmh.cmd[2] = CS8416_CSB1; break;
+ case 2: rmh.cmd[2] = CS8416_CSB2; break;
+ case 3: rmh.cmd[2] = CS8416_CSB3; break;
+ case 4: rmh.cmd[2] = CS8416_CSB4; break;
+ default: return -EINVAL;
+ }
+ } else {
+ switch (aes_idx) {
+ /* instead of CS8420_CSB0 use CS8416_CSBx for AES SYNC plug */
+ case 0: rmh.cmd[2] = CS8420_CSB0; break;
+ case 1: rmh.cmd[2] = CS8420_CSB1; break;
+ case 2: rmh.cmd[2] = CS8420_CSB2; break;
+ case 3: rmh.cmd[2] = CS8420_CSB3; break;
+ case 4: rmh.cmd[2] = CS8420_CSB4; break;
+ default: return -EINVAL;
+ }
}
- rmh.cmd[1] &= 0x0fffff; /* size and code the chip id for the fpga */
- rmh.cmd[2] &= CHIP_SIG_AND_MAP_SPI; /* chip signature + map for spi read */
+ /* size and code the chip id for the fpga */
+ rmh.cmd[1] &= 0x0fffff;
+ /* chip signature + map for spi read */
+ rmh.cmd[2] &= CHIP_SIG_AND_MAP_SPI;
rmh.cmd_len = 3;
err = pcxhr_send_msg(chip->mgr, &rmh);
if (err)
return err;
- temp = 0;
- for (i = 0; i < 8; i++) {
- /* attention : reversed bit order (not with CS8416_01_CS) */
- temp <<= 1;
- if (rmh.stat[1] & (1 << i))
- temp |= 1;
+
+ if (chip->mgr->board_aes_in_192k) {
+ temp = (unsigned char)rmh.stat[1];
+ } else {
+ temp = 0;
+ /* reversed bit order (not with CS8416_01_CS) */
+ for (i = 0; i < 8; i++) {
+ temp <<= 1;
+ if (rmh.stat[1] & (1 << i))
+ temp |= 1;
+ }
}
- snd_printdd("read iec958 AES %d byte %d = 0x%x\n", chip->chip_idx, aes_idx, temp);
+ snd_printdd("read iec958 AES %d byte %d = 0x%x\n",
+ chip->chip_idx, aes_idx, temp);
*aes_bits = temp;
return 0;
}
-static int pcxhr_iec958_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+static int pcxhr_iec958_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
unsigned char aes_bits;
@@ -806,7 +944,12 @@ static int pcxhr_iec958_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v
if (kcontrol->private_value == 0) /* playback */
aes_bits = chip->aes_bits[i];
else { /* capture */
- err = pcxhr_iec958_capture_byte(chip, i, &aes_bits);
+ if (chip->mgr->is_hr_stereo)
+ err = hr222_iec958_capture_byte(chip, i,
+ &aes_bits);
+ else
+ err = pcxhr_iec958_capture_byte(chip, i,
+ &aes_bits);
if (err)
break;
}
@@ -825,7 +968,8 @@ static int pcxhr_iec958_mask_get(struct snd_kcontrol *kcontrol,
return 0;
}
-static int pcxhr_iec958_update_byte(struct snd_pcxhr *chip, int aes_idx, unsigned char aes_bits)
+static int pcxhr_iec958_update_byte(struct snd_pcxhr *chip,
+ int aes_idx, unsigned char aes_bits)
{
int i, err, cmd;
unsigned char new_bits = aes_bits;
@@ -834,12 +978,12 @@ static int pcxhr_iec958_update_byte(struct snd_pcxhr *chip, int aes_idx, unsigne
for (i = 0; i < 8; i++) {
if ((old_bits & 0x01) != (new_bits & 0x01)) {
- cmd = chip->chip_idx & 0x03; /* chip index 0..3 */
- if(chip->chip_idx > 3)
+ cmd = chip->chip_idx & 0x03; /* chip index 0..3 */
+ if (chip->chip_idx > 3)
/* new bit used if chip_idx>3 (PCX1222HR) */
cmd |= 1 << 22;
- cmd |= ((aes_idx << 3) + i) << 2; /* add bit offset */
- cmd |= (new_bits & 0x01) << 23; /* add bit value */
+ cmd |= ((aes_idx << 3) + i) << 2; /* add bit offset */
+ cmd |= (new_bits & 0x01) << 23; /* add bit value */
pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE);
rmh.cmd[0] |= IO_NUM_REG_CUER;
rmh.cmd[1] = cmd;
@@ -867,7 +1011,12 @@ static int pcxhr_iec958_put(struct snd_kcontrol *kcontrol,
mutex_lock(&chip->mgr->mixer_mutex);
for (i = 0; i < 5; i++) {
if (ucontrol->value.iec958.status[i] != chip->aes_bits[i]) {
- pcxhr_iec958_update_byte(chip, i, ucontrol->value.iec958.status[i]);
+ if (chip->mgr->is_hr_stereo)
+ hr222_iec958_update_byte(chip, i,
+ ucontrol->value.iec958.status[i]);
+ else
+ pcxhr_iec958_update_byte(chip, i,
+ ucontrol->value.iec958.status[i]);
changed = 1;
}
}
@@ -917,29 +1066,53 @@ static void pcxhr_init_audio_levels(struct snd_pcxhr *chip)
/* at boot time the digital volumes are unmuted 0dB */
for (j = 0; j < PCXHR_PLAYBACK_STREAMS; j++) {
chip->digital_playback_active[j][i] = 1;
- chip->digital_playback_volume[j][i] = PCXHR_DIGITAL_ZERO_LEVEL;
+ chip->digital_playback_volume[j][i] =
+ PCXHR_DIGITAL_ZERO_LEVEL;
}
- /* after boot, only two bits are set on the uer interface */
- chip->aes_bits[0] = IEC958_AES0_PROFESSIONAL | IEC958_AES0_PRO_FS_48000;
-/* only for test purpose, remove later */
+ /* after boot, only two bits are set on the uer
+ * interface
+ */
+ chip->aes_bits[0] = (IEC958_AES0_PROFESSIONAL |
+ IEC958_AES0_PRO_FS_48000);
#ifdef CONFIG_SND_DEBUG
- /* analog volumes for playback (is LEVEL_MIN after boot) */
+ /* analog volumes for playback
+ * (is LEVEL_MIN after boot)
+ */
chip->analog_playback_active[i] = 1;
- chip->analog_playback_volume[i] = PCXHR_ANALOG_PLAYBACK_ZERO_LEVEL;
- pcxhr_update_analog_audio_level(chip, 0, i);
+ if (chip->mgr->is_hr_stereo)
+ chip->analog_playback_volume[i] =
+ HR222_LINE_PLAYBACK_ZERO_LEVEL;
+ else {
+ chip->analog_playback_volume[i] =
+ PCXHR_LINE_PLAYBACK_ZERO_LEVEL;
+ pcxhr_update_analog_audio_level(chip, 0, i);
+ }
#endif
-/* test end */
+ /* stereo cards need to be initialised after boot */
+ if (chip->mgr->is_hr_stereo)
+ hr222_update_analog_audio_level(chip, 0, i);
}
if (chip->nb_streams_capt) {
/* at boot time the digital volumes are unmuted 0dB */
- chip->digital_capture_volume[i] = PCXHR_DIGITAL_ZERO_LEVEL;
-/* only for test purpose, remove later */
+ chip->digital_capture_volume[i] =
+ PCXHR_DIGITAL_ZERO_LEVEL;
+ chip->analog_capture_active = 1;
#ifdef CONFIG_SND_DEBUG
- /* analog volumes for playback (is LEVEL_MIN after boot) */
- chip->analog_capture_volume[i] = PCXHR_ANALOG_CAPTURE_ZERO_LEVEL;
- pcxhr_update_analog_audio_level(chip, 1, i);
+ /* analog volumes for playback
+ * (is LEVEL_MIN after boot)
+ */
+ if (chip->mgr->is_hr_stereo)
+ chip->analog_capture_volume[i] =
+ HR222_LINE_CAPTURE_ZERO_LEVEL;
+ else {
+ chip->analog_capture_volume[i] =
+ PCXHR_LINE_CAPTURE_ZERO_LEVEL;
+ pcxhr_update_analog_audio_level(chip, 1, i);
+ }
#endif
-/* test end */
+ /* stereo cards need to be initialised after boot */
+ if (chip->mgr->is_hr_stereo)
+ hr222_update_analog_audio_level(chip, 1, i);
}
}
@@ -963,90 +1136,125 @@ int pcxhr_create_mixer(struct pcxhr_mgr *mgr)
temp = pcxhr_control_analog_level;
temp.name = "Master Playback Volume";
temp.private_value = 0; /* playback */
- temp.tlv.p = db_scale_analog_playback;
- if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0)
+ if (mgr->is_hr_stereo)
+ temp.tlv.p = db_scale_a_hr222_playback;
+ else
+ temp.tlv.p = db_scale_analog_playback;
+ err = snd_ctl_add(chip->card,
+ snd_ctl_new1(&temp, chip));
+ if (err < 0)
return err;
+
/* output mute controls */
- if ((err = snd_ctl_add(chip->card,
- snd_ctl_new1(&pcxhr_control_output_switch,
- chip))) < 0)
+ err = snd_ctl_add(chip->card,
+ snd_ctl_new1(&pcxhr_control_output_switch,
+ chip));
+ if (err < 0)
return err;
-
+
temp = snd_pcxhr_pcm_vol;
temp.name = "PCM Playback Volume";
temp.count = PCXHR_PLAYBACK_STREAMS;
temp.private_value = 0; /* playback */
- if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0)
+ err = snd_ctl_add(chip->card,
+ snd_ctl_new1(&temp, chip));
+ if (err < 0)
return err;
- if ((err = snd_ctl_add(chip->card,
- snd_ctl_new1(&pcxhr_control_pcm_switch,
- chip))) < 0)
+ err = snd_ctl_add(chip->card,
+ snd_ctl_new1(&pcxhr_control_pcm_switch, chip));
+ if (err < 0)
return err;
/* IEC958 controls */
- if ((err = snd_ctl_add(chip->card,
- snd_ctl_new1(&pcxhr_control_playback_iec958_mask,
- chip))) < 0)
+ err = snd_ctl_add(chip->card,
+ snd_ctl_new1(&pcxhr_control_playback_iec958_mask,
+ chip));
+ if (err < 0)
return err;
- if ((err = snd_ctl_add(chip->card,
- snd_ctl_new1(&pcxhr_control_playback_iec958,
- chip))) < 0)
+
+ err = snd_ctl_add(chip->card,
+ snd_ctl_new1(&pcxhr_control_playback_iec958,
+ chip));
+ if (err < 0)
return err;
}
if (chip->nb_streams_capt) {
- /* analog input level control only on first two chips !*/
+ /* analog input level control */
temp = pcxhr_control_analog_level;
- temp.name = "Master Capture Volume";
+ temp.name = "Line Capture Volume";
temp.private_value = 1; /* capture */
- temp.tlv.p = db_scale_analog_capture;
- if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0)
+ if (mgr->is_hr_stereo)
+ temp.tlv.p = db_scale_a_hr222_capture;
+ else
+ temp.tlv.p = db_scale_analog_capture;
+
+ err = snd_ctl_add(chip->card,
+ snd_ctl_new1(&temp, chip));
+ if (err < 0)
return err;
temp = snd_pcxhr_pcm_vol;
temp.name = "PCM Capture Volume";
temp.count = 1;
temp.private_value = 1; /* capture */
- if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0)
+
+ err = snd_ctl_add(chip->card,
+ snd_ctl_new1(&temp, chip));
+ if (err < 0)
return err;
+
/* Audio source */
- if ((err = snd_ctl_add(chip->card,
- snd_ctl_new1(&pcxhr_control_audio_src,
- chip))) < 0)
+ err = snd_ctl_add(chip->card,
+ snd_ctl_new1(&pcxhr_control_audio_src, chip));
+ if (err < 0)
return err;
+
/* IEC958 controls */
- if ((err = snd_ctl_add(chip->card,
- snd_ctl_new1(&pcxhr_control_capture_iec958_mask,
- chip))) < 0)
+ err = snd_ctl_add(chip->card,
+ snd_ctl_new1(&pcxhr_control_capture_iec958_mask,
+ chip));
+ if (err < 0)
return err;
- if ((err = snd_ctl_add(chip->card,
- snd_ctl_new1(&pcxhr_control_capture_iec958,
- chip))) < 0)
+
+ err = snd_ctl_add(chip->card,
+ snd_ctl_new1(&pcxhr_control_capture_iec958,
+ chip));
+ if (err < 0)
return err;
+
+ if (mgr->is_hr_stereo) {
+ err = hr222_add_mic_controls(chip);
+ if (err < 0)
+ return err;
+ }
}
/* monitoring only if playback and capture device available */
if (chip->nb_streams_capt > 0 && chip->nb_streams_play > 0) {
/* monitoring */
- if ((err = snd_ctl_add(chip->card,
- snd_ctl_new1(&pcxhr_control_monitor_vol,
- chip))) < 0)
+ err = snd_ctl_add(chip->card,
+ snd_ctl_new1(&pcxhr_control_monitor_vol, chip));
+ if (err < 0)
return err;
- if ((err = snd_ctl_add(chip->card,
- snd_ctl_new1(&pcxhr_control_monitor_sw,
- chip))) < 0)
+
+ err = snd_ctl_add(chip->card,
+ snd_ctl_new1(&pcxhr_control_monitor_sw, chip));
+ if (err < 0)
return err;
}
if (i == 0) {
/* clock mode only one control per pcxhr */
- if ((err = snd_ctl_add(chip->card,
- snd_ctl_new1(&pcxhr_control_clock_type,
- mgr))) < 0)
+ err = snd_ctl_add(chip->card,
+ snd_ctl_new1(&pcxhr_control_clock_type, mgr));
+ if (err < 0)
return err;
- /* non standard control used to scan the external clock presence/frequencies */
- if ((err = snd_ctl_add(chip->card,
- snd_ctl_new1(&pcxhr_control_clock_rate,
- mgr))) < 0)
+ /* non standard control used to scan
+ * the external clock presence/frequencies
+ */
+ err = snd_ctl_add(chip->card,
+ snd_ctl_new1(&pcxhr_control_clock_rate, mgr));
+ if (err < 0)
return err;
}
diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c
index e9f0706ed3e..3caacfb9d8e 100644
--- a/sound/pci/riptide/riptide.c
+++ b/sound/pci/riptide/riptide.c
@@ -172,7 +172,7 @@ MODULE_PARM_DESC(opl3_port, "OPL3 port # for Riptide driver.");
#define MAX_WRITE_RETRY 10 /* cmd interface limits */
#define MAX_ERROR_COUNT 10
-#define CMDIF_TIMEOUT 500000
+#define CMDIF_TIMEOUT 50000
#define RESET_TRIES 5
#define READ_PORT_ULONG(p) inl((unsigned long)&(p))
@@ -1754,7 +1754,7 @@ snd_riptide_interrupt(int irq, void *dev_id)
if (IS_EOBIRQ(cif->hwport) || IS_EOSIRQ(cif->hwport) ||
IS_EOCIRQ(cif->hwport)) {
chip->handled_irqs++;
- tasklet_hi_schedule(&chip->riptide_tq);
+ tasklet_schedule(&chip->riptide_tq);
}
if (chip->rmidi && IS_MPUIRQ(cif->hwport)) {
chip->handled_irqs++;
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index fdd3be5b439..44d0c15e2b7 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -3750,7 +3750,7 @@ static irqreturn_t snd_hdsp_interrupt(int irq, void *dev_id)
}
}
if (hdsp->use_midi_tasklet && schedule)
- tasklet_hi_schedule(&hdsp->midi_tasklet);
+ tasklet_schedule(&hdsp->midi_tasklet);
return IRQ_HANDLED;
}
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index dc5c4baa1e6..71231cf1b2b 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -3476,7 +3476,7 @@ static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id)
schedule = 1;
}
if (schedule)
- tasklet_hi_schedule(&hdspm->midi_tasklet);
+ tasklet_schedule(&hdspm->midi_tasklet);
return IRQ_HANDLED;
}
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c b/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c
index fa4b11398b1..ea903c8e90d 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c
@@ -41,7 +41,7 @@ irqreturn_t pdacf_interrupt(int irq, void *dev)
if (stat & PDAUDIOCF_IRQOVR) /* should never happen */
snd_printk(KERN_ERR "PDAUDIOCF SRAM buffer overrun detected!\n");
if (chip->pcm_substream)
- tasklet_hi_schedule(&chip->tq);
+ tasklet_schedule(&chip->tq);
if (!(stat & PDAUDIOCF_IRQAKM))
stat |= PDAUDIOCF_IRQAKM; /* check rate */
}
diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c
index a38c0c790d2..af76ee862d2 100644
--- a/sound/ppc/pmac.c
+++ b/sound/ppc/pmac.c
@@ -1033,7 +1033,7 @@ static int __init snd_pmac_detect(struct snd_pmac *chip)
}
if (of_device_is_compatible(sound, "tumbler")) {
chip->model = PMAC_TUMBLER;
- chip->can_capture = 0; /* no capture */
+ chip->can_capture = machine_is_compatible("PowerMac4,2");
chip->can_duplex = 0;
// chip->can_byte_swap = 0; /* FIXME: check this */
chip->num_freqs = ARRAY_SIZE(tumbler_freqs);
diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c
index f746e15b848..3eb22338541 100644
--- a/sound/ppc/tumbler.c
+++ b/sound/ppc/tumbler.c
@@ -875,7 +875,8 @@ static struct snd_kcontrol_new snapper_mixers[] __initdata = {
.put = tumbler_put_master_switch
},
DEFINE_SNAPPER_MIX("PCM Playback Volume", 0, VOL_IDX_PCM),
- DEFINE_SNAPPER_MIX("PCM Playback Volume", 1, VOL_IDX_PCM2),
+ /* Alternative PCM is assigned to Mic analog loopback on iBook G4 */
+ DEFINE_SNAPPER_MIX("Mic Playback Volume", 0, VOL_IDX_PCM2),
DEFINE_SNAPPER_MIX("Monitor Mix Volume", 0, VOL_IDX_ADC),
DEFINE_SNAPPER_MONO("Tone Control - Bass", bass),
DEFINE_SNAPPER_MONO("Tone Control - Treble", treble),
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index 4dfda6674be..ef025c66cc6 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -22,17 +22,16 @@ if SND_SOC
config SND_SOC_AC97_BUS
bool
-# All the supported Soc's
-source "sound/soc/at32/Kconfig"
-source "sound/soc/at91/Kconfig"
+# All the supported SoCs
+source "sound/soc/atmel/Kconfig"
source "sound/soc/au1x/Kconfig"
+source "sound/soc/blackfin/Kconfig"
+source "sound/soc/davinci/Kconfig"
+source "sound/soc/fsl/Kconfig"
+source "sound/soc/omap/Kconfig"
source "sound/soc/pxa/Kconfig"
source "sound/soc/s3c24xx/Kconfig"
source "sound/soc/sh/Kconfig"
-source "sound/soc/fsl/Kconfig"
-source "sound/soc/davinci/Kconfig"
-source "sound/soc/omap/Kconfig"
-source "sound/soc/blackfin/Kconfig"
# Supported codecs
source "sound/soc/codecs/Kconfig"
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index d849349f2c6..86a9b1f5b0f 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -1,5 +1,13 @@
snd-soc-core-objs := soc-core.o soc-dapm.o
obj-$(CONFIG_SND_SOC) += snd-soc-core.o
-obj-$(CONFIG_SND_SOC) += codecs/ at32/ at91/ pxa/ s3c24xx/ sh/ fsl/ davinci/
-obj-$(CONFIG_SND_SOC) += omap/ au1x/ blackfin/
+obj-$(CONFIG_SND_SOC) += codecs/
+obj-$(CONFIG_SND_SOC) += atmel/
+obj-$(CONFIG_SND_SOC) += au1x/
+obj-$(CONFIG_SND_SOC) += blackfin/
+obj-$(CONFIG_SND_SOC) += davinci/
+obj-$(CONFIG_SND_SOC) += fsl/
+obj-$(CONFIG_SND_SOC) += omap/
+obj-$(CONFIG_SND_SOC) += pxa/
+obj-$(CONFIG_SND_SOC) += s3c24xx/
+obj-$(CONFIG_SND_SOC) += sh/
diff --git a/sound/soc/at32/Kconfig b/sound/soc/at32/Kconfig
deleted file mode 100644
index b0765e86c08..00000000000
--- a/sound/soc/at32/Kconfig
+++ /dev/null
@@ -1,34 +0,0 @@
-config SND_AT32_SOC
- tristate "SoC Audio for the Atmel AT32 System-on-a-Chip"
- depends on AVR32 && SND_SOC
- help
- Say Y or M if you want to add support for codecs attached to
- the AT32 SSC interface. You will also need to
- to select the audio interfaces to support below.
-
-
-config SND_AT32_SOC_SSC
- tristate
-
-
-
-config SND_AT32_SOC_PLAYPAQ
- tristate "SoC Audio support for PlayPaq with WM8510"
- depends on SND_AT32_SOC && BOARD_PLAYPAQ
- select SND_AT32_SOC_SSC
- select SND_SOC_WM8510
- help
- Say Y or M here if you want to add support for SoC audio
- on the LRS PlayPaq.
-
-
-
-config SND_AT32_SOC_PLAYPAQ_SLAVE
- bool "Run CODEC on PlayPaq in slave mode"
- depends on SND_AT32_SOC_PLAYPAQ
- default n
- help
- Say Y if you want to run with the AT32 SSC generating the BCLK
- and FRAME signals on the PlayPaq. Unless you want to play
- with the AT32 as the SSC master, you probably want to say N here,
- as this will give you better sound quality.
diff --git a/sound/soc/at32/Makefile b/sound/soc/at32/Makefile
deleted file mode 100644
index c03e55ecece..00000000000
--- a/sound/soc/at32/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-# AT32 Platform Support
-snd-soc-at32-objs := at32-pcm.o
-snd-soc-at32-ssc-objs := at32-ssc.o
-
-obj-$(CONFIG_SND_AT32_SOC) += snd-soc-at32.o
-obj-$(CONFIG_SND_AT32_SOC_SSC) += snd-soc-at32-ssc.o
-
-# AT32 Machine Support
-snd-soc-playpaq-objs := playpaq_wm8510.o
-
-obj-$(CONFIG_SND_AT32_SOC_PLAYPAQ) += snd-soc-playpaq.o
diff --git a/sound/soc/at32/at32-pcm.c b/sound/soc/at32/at32-pcm.c
deleted file mode 100644
index c83584f989a..00000000000
--- a/sound/soc/at32/at32-pcm.c
+++ /dev/null
@@ -1,492 +0,0 @@
-/* sound/soc/at32/at32-pcm.c
- * ASoC PCM interface for Atmel AT32 SoC
- *
- * Copyright (C) 2008 Long Range Systems
- * Geoffrey Wossum <gwossum@acm.org>
- *
- * 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.
- *
- * Note that this is basically a port of the sound/soc/at91-pcm.c to
- * the AVR32 kernel. Thanks to Frank Mandarino for that code.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/dma-mapping.h>
-#include <linux/atmel_pdc.h>
-
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/soc.h>
-
-#include "at32-pcm.h"
-
-
-
-/*--------------------------------------------------------------------------*\
- * Hardware definition
-\*--------------------------------------------------------------------------*/
-/* TODO: These values were taken from the AT91 platform driver, check
- * them against real values for AT32
- */
-static const struct snd_pcm_hardware at32_pcm_hardware = {
- .info = (SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_BLOCK_TRANSFER |
- SNDRV_PCM_INFO_PAUSE),
-
- .formats = SNDRV_PCM_FMTBIT_S16,
- .period_bytes_min = 32,
- .period_bytes_max = 8192, /* 512 frames * 16 bytes / frame */
- .periods_min = 2,
- .periods_max = 1024,
- .buffer_bytes_max = 32 * 1024,
-};
-
-
-
-/*--------------------------------------------------------------------------*\
- * Data types
-\*--------------------------------------------------------------------------*/
-struct at32_runtime_data {
- struct at32_pcm_dma_params *params;
- dma_addr_t dma_buffer; /* physical address of DMA buffer */
- dma_addr_t dma_buffer_end; /* first address beyond DMA buffer */
- size_t period_size;
-
- dma_addr_t period_ptr; /* physical address of next period */
- int periods; /* period index of period_ptr */
-
- /* Save PDC registers (for power management) */
- u32 pdc_xpr_save;
- u32 pdc_xcr_save;
- u32 pdc_xnpr_save;
- u32 pdc_xncr_save;
-};
-
-
-
-/*--------------------------------------------------------------------------*\
- * Helper functions
-\*--------------------------------------------------------------------------*/
-static int at32_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
-{
- struct snd_pcm_substream *substream = pcm->streams[stream].substream;
- struct snd_dma_buffer *dmabuf = &substream->dma_buffer;
- size_t size = at32_pcm_hardware.buffer_bytes_max;
-
- dmabuf->dev.type = SNDRV_DMA_TYPE_DEV;
- dmabuf->dev.dev = pcm->card->dev;
- dmabuf->private_data = NULL;
- dmabuf->area = dma_alloc_coherent(pcm->card->dev, size,
- &dmabuf->addr, GFP_KERNEL);
- pr_debug("at32_pcm: preallocate_dma_buffer: "
- "area=%p, addr=%p, size=%ld\n",
- (void *)dmabuf->area, (void *)dmabuf->addr, size);
-
- if (!dmabuf->area)
- return -ENOMEM;
-
- dmabuf->bytes = size;
- return 0;
-}
-
-
-
-/*--------------------------------------------------------------------------*\
- * ISR
-\*--------------------------------------------------------------------------*/
-static void at32_pcm_dma_irq(u32 ssc_sr, struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *rtd = substream->runtime;
- struct at32_runtime_data *prtd = rtd->private_data;
- struct at32_pcm_dma_params *params = prtd->params;
- static int count;
-
- count++;
- if (ssc_sr & params->mask->ssc_endbuf) {
- pr_warning("at32-pcm: buffer %s on %s (SSC_SR=%#x, count=%d)\n",
- substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
- "underrun" : "overrun", params->name, ssc_sr, count);
-
- /* re-start the PDC */
- ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
- params->mask->pdc_disable);
- prtd->period_ptr += prtd->period_size;
- if (prtd->period_ptr >= prtd->dma_buffer_end)
- prtd->period_ptr = prtd->dma_buffer;
-
-
- ssc_writex(params->ssc->regs, params->pdc->xpr,
- prtd->period_ptr);
- ssc_writex(params->ssc->regs, params->pdc->xcr,
- prtd->period_size / params->pdc_xfer_size);
- ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
- params->mask->pdc_enable);
- }
-
-
- if (ssc_sr & params->mask->ssc_endx) {
- /* Load the PDC next pointer and counter registers */
- prtd->period_ptr += prtd->period_size;
- if (prtd->period_ptr >= prtd->dma_buffer_end)
- prtd->period_ptr = prtd->dma_buffer;
- ssc_writex(params->ssc->regs, params->pdc->xnpr,
- prtd->period_ptr);
- ssc_writex(params->ssc->regs, params->pdc->xncr,
- prtd->period_size / params->pdc_xfer_size);
- }
-
-
- snd_pcm_period_elapsed(substream);
-}
-
-
-
-/*--------------------------------------------------------------------------*\
- * PCM operations
-\*--------------------------------------------------------------------------*/
-static int at32_pcm_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct at32_runtime_data *prtd = runtime->private_data;
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
-
- /* this may get called several times by oss emulation
- * with different params
- */
- snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
- runtime->dma_bytes = params_buffer_bytes(params);
-
- prtd->params = rtd->dai->cpu_dai->dma_data;
- prtd->params->dma_intr_handler = at32_pcm_dma_irq;
-
- prtd->dma_buffer = runtime->dma_addr;
- prtd->dma_buffer_end = runtime->dma_addr + runtime->dma_bytes;
- prtd->period_size = params_period_bytes(params);
-
- pr_debug("hw_params: DMA for %s initialized "
- "(dma_bytes=%ld, period_size=%ld)\n",
- prtd->params->name, runtime->dma_bytes, prtd->period_size);
-
- return 0;
-}
-
-
-
-static int at32_pcm_hw_free(struct snd_pcm_substream *substream)
-{
- struct at32_runtime_data *prtd = substream->runtime->private_data;
- struct at32_pcm_dma_params *params = prtd->params;
-
- if (params != NULL) {
- ssc_writex(params->ssc->regs, SSC_PDC_PTCR,
- params->mask->pdc_disable);
- prtd->params->dma_intr_handler = NULL;
- }
-
- return 0;
-}
-
-
-
-static int at32_pcm_prepare(struct snd_pcm_substream *substream)
-{
- struct at32_runtime_data *prtd = substream->runtime->private_data;
- struct at32_pcm_dma_params *params = prtd->params;
-
- ssc_writex(params->ssc->regs, SSC_IDR,
- params->mask->ssc_endx | params->mask->ssc_endbuf);
- ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
- params->mask->pdc_disable);
-
- return 0;
-}
-
-
-static int at32_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
-{
- struct snd_pcm_runtime *rtd = substream->runtime;
- struct at32_runtime_data *prtd = rtd->private_data;
- struct at32_pcm_dma_params *params = prtd->params;
- int ret = 0;
-
- pr_debug("at32_pcm_trigger: buffer_size = %ld, "
- "dma_area = %p, dma_bytes = %ld\n",
- rtd->buffer_size, rtd->dma_area, rtd->dma_bytes);
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- prtd->period_ptr = prtd->dma_buffer;
-
- ssc_writex(params->ssc->regs, params->pdc->xpr,
- prtd->period_ptr);
- ssc_writex(params->ssc->regs, params->pdc->xcr,
- prtd->period_size / params->pdc_xfer_size);
-
- prtd->period_ptr += prtd->period_size;
- ssc_writex(params->ssc->regs, params->pdc->xnpr,
- prtd->period_ptr);
- ssc_writex(params->ssc->regs, params->pdc->xncr,
- prtd->period_size / params->pdc_xfer_size);
-
- pr_debug("trigger: period_ptr=%lx, xpr=%x, "
- "xcr=%d, xnpr=%x, xncr=%d\n",
- (unsigned long)prtd->period_ptr,
- ssc_readx(params->ssc->regs, params->pdc->xpr),
- ssc_readx(params->ssc->regs, params->pdc->xcr),
- ssc_readx(params->ssc->regs, params->pdc->xnpr),
- ssc_readx(params->ssc->regs, params->pdc->xncr));
-
- ssc_writex(params->ssc->regs, SSC_IER,
- params->mask->ssc_endx | params->mask->ssc_endbuf);
- ssc_writex(params->ssc->regs, SSC_PDC_PTCR,
- params->mask->pdc_enable);
-
- pr_debug("sr=%x, imr=%x\n",
- ssc_readx(params->ssc->regs, SSC_SR),
- ssc_readx(params->ssc->regs, SSC_IER));
- break; /* SNDRV_PCM_TRIGGER_START */
-
-
-
- case SNDRV_PCM_TRIGGER_STOP:
- case SNDRV_PCM_TRIGGER_SUSPEND:
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
- params->mask->pdc_disable);
- break;
-
-
- case SNDRV_PCM_TRIGGER_RESUME:
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
- params->mask->pdc_enable);
- break;
-
- default:
- ret = -EINVAL;
- }
-
- return ret;
-}
-
-
-
-static snd_pcm_uframes_t at32_pcm_pointer(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct at32_runtime_data *prtd = runtime->private_data;
- struct at32_pcm_dma_params *params = prtd->params;
- dma_addr_t ptr;
- snd_pcm_uframes_t x;
-
- ptr = (dma_addr_t) ssc_readx(params->ssc->regs, params->pdc->xpr);
- x = bytes_to_frames(runtime, ptr - prtd->dma_buffer);
-
- if (x == runtime->buffer_size)
- x = 0;
-
- return x;
-}
-
-
-
-static int at32_pcm_open(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct at32_runtime_data *prtd;
- int ret = 0;
-
- snd_soc_set_runtime_hwparams(substream, &at32_pcm_hardware);
-
- /* ensure that buffer size is a multiple of period size */
- ret = snd_pcm_hw_constraint_integer(runtime,
- SNDRV_PCM_HW_PARAM_PERIODS);
- if (ret < 0)
- goto out;
-
- prtd = kzalloc(sizeof(*prtd), GFP_KERNEL);
- if (prtd == NULL) {
- ret = -ENOMEM;
- goto out;
- }
- runtime->private_data = prtd;
-
-
-out:
- return ret;
-}
-
-
-
-static int at32_pcm_close(struct snd_pcm_substream *substream)
-{
- struct at32_runtime_data *prtd = substream->runtime->private_data;
-
- kfree(prtd);
- return 0;
-}
-
-
-static int at32_pcm_mmap(struct snd_pcm_substream *substream,
- struct vm_area_struct *vma)
-{
- return remap_pfn_range(vma, vma->vm_start,
- substream->dma_buffer.addr >> PAGE_SHIFT,
- vma->vm_end - vma->vm_start, vma->vm_page_prot);
-}
-
-
-
-static struct snd_pcm_ops at32_pcm_ops = {
- .open = at32_pcm_open,
- .close = at32_pcm_close,
- .ioctl = snd_pcm_lib_ioctl,
- .hw_params = at32_pcm_hw_params,
- .hw_free = at32_pcm_hw_free,
- .prepare = at32_pcm_prepare,
- .trigger = at32_pcm_trigger,
- .pointer = at32_pcm_pointer,
- .mmap = at32_pcm_mmap,
-};
-
-
-
-/*--------------------------------------------------------------------------*\
- * ASoC platform driver
-\*--------------------------------------------------------------------------*/
-static u64 at32_pcm_dmamask = 0xffffffff;
-
-static int at32_pcm_new(struct snd_card *card,
- struct snd_soc_dai *dai,
- struct snd_pcm *pcm)
-{
- int ret = 0;
-
- if (!card->dev->dma_mask)
- card->dev->dma_mask = &at32_pcm_dmamask;
- if (!card->dev->coherent_dma_mask)
- card->dev->coherent_dma_mask = 0xffffffff;
-
- if (dai->playback.channels_min) {
- ret = at32_pcm_preallocate_dma_buffer(
- pcm, SNDRV_PCM_STREAM_PLAYBACK);
- if (ret)
- goto out;
- }
-
- if (dai->capture.channels_min) {
- pr_debug("at32-pcm: Allocating PCM capture DMA buffer\n");
- ret = at32_pcm_preallocate_dma_buffer(
- pcm, SNDRV_PCM_STREAM_CAPTURE);
- if (ret)
- goto out;
- }
-
-
-out:
- return ret;
-}
-
-
-
-static void at32_pcm_free_dma_buffers(struct snd_pcm *pcm)
-{
- struct snd_pcm_substream *substream;
- struct snd_dma_buffer *buf;
- int stream;
-
- for (stream = 0; stream < 2; stream++) {
- substream = pcm->streams[stream].substream;
- if (substream == NULL)
- continue;
-
- buf = &substream->dma_buffer;
- if (!buf->area)
- continue;
- dma_free_coherent(pcm->card->dev, buf->bytes,
- buf->area, buf->addr);
- buf->area = NULL;
- }
-}
-
-
-
-#ifdef CONFIG_PM
-static int at32_pcm_suspend(struct platform_device *pdev,
- struct snd_soc_dai *dai)
-{
- struct snd_pcm_runtime *runtime = dai->runtime;
- struct at32_runtime_data *prtd;
- struct at32_pcm_dma_params *params;
-
- if (runtime == NULL)
- return 0;
- prtd = runtime->private_data;
- params = prtd->params;
-
- /* Disable the PDC and save the PDC registers */
- ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
- params->mask->pdc_disable);
-
- prtd->pdc_xpr_save = ssc_readx(params->ssc->regs, params->pdc->xpr);
- prtd->pdc_xcr_save = ssc_readx(params->ssc->regs, params->pdc->xcr);
- prtd->pdc_xnpr_save = ssc_readx(params->ssc->regs, params->pdc->xnpr);
- prtd->pdc_xncr_save = ssc_readx(params->ssc->regs, params->pdc->xncr);
-
- return 0;
-}
-
-
-
-static int at32_pcm_resume(struct platform_device *pdev,
- struct snd_soc_dai *dai)
-{
- struct snd_pcm_runtime *runtime = dai->runtime;
- struct at32_runtime_data *prtd;
- struct at32_pcm_dma_params *params;
-
- if (runtime == NULL)
- return 0;
- prtd = runtime->private_data;
- params = prtd->params;
-
- /* Restore the PDC registers and enable the PDC */
- ssc_writex(params->ssc->regs, params->pdc->xpr, prtd->pdc_xpr_save);
- ssc_writex(params->ssc->regs, params->pdc->xcr, prtd->pdc_xcr_save);
- ssc_writex(params->ssc->regs, params->pdc->xnpr, prtd->pdc_xnpr_save);
- ssc_writex(params->ssc->regs, params->pdc->xncr, prtd->pdc_xncr_save);
-
- ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR, params->mask->pdc_enable);
- return 0;
-}
-#else /* CONFIG_PM */
-# define at32_pcm_suspend NULL
-# define at32_pcm_resume NULL
-#endif /* CONFIG_PM */
-
-
-
-struct snd_soc_platform at32_soc_platform = {
- .name = "at32-audio",
- .pcm_ops = &at32_pcm_ops,
- .pcm_new = at32_pcm_new,
- .pcm_free = at32_pcm_free_dma_buffers,
- .suspend = at32_pcm_suspend,
- .resume = at32_pcm_resume,
-};
-EXPORT_SYMBOL_GPL(at32_soc_platform);
-
-
-
-MODULE_AUTHOR("Geoffrey Wossum <gwossum@acm.org>");
-MODULE_DESCRIPTION("Atmel AT32 PCM module");
-MODULE_LICENSE("GPL");
diff --git a/sound/soc/at32/at32-pcm.h b/sound/soc/at32/at32-pcm.h
deleted file mode 100644
index 2a52430417d..00000000000
--- a/sound/soc/at32/at32-pcm.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/* sound/soc/at32/at32-pcm.h
- * ASoC PCM interface for Atmel AT32 SoC
- *
- * Copyright (C) 2008 Long Range Systems
- * Geoffrey Wossum <gwossum@acm.org>
- *
- * 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 __SOUND_SOC_AT32_AT32_PCM_H
-#define __SOUND_SOC_AT32_AT32_PCM_H __FILE__
-
-#include <linux/atmel-ssc.h>
-
-
-/*
- * Registers and status bits that are required by the PCM driver
- * TODO: Is ptcr really used?
- */
-struct at32_pdc_regs {
- u32 xpr; /* PDC RX/TX pointer */
- u32 xcr; /* PDC RX/TX counter */
- u32 xnpr; /* PDC next RX/TX pointer */
- u32 xncr; /* PDC next RX/TX counter */
- u32 ptcr; /* PDC transfer control */
-};
-
-
-
-/*
- * SSC mask info
- */
-struct at32_ssc_mask {
- u32 ssc_enable; /* SSC RX/TX enable */
- u32 ssc_disable; /* SSC RX/TX disable */
- u32 ssc_endx; /* SSC ENDTX or ENDRX */
- u32 ssc_endbuf; /* SSC TXBUFF or RXBUFF */
- u32 pdc_enable; /* PDC RX/TX enable */
- u32 pdc_disable; /* PDC RX/TX disable */
-};
-
-
-
-/*
- * This structure, shared between the PCM driver and the interface,
- * contains all information required by the PCM driver to perform the
- * PDC DMA operation. All fields except dma_intr_handler() are initialized
- * by the interface. The dms_intr_handler() pointer is set by the PCM
- * driver and called by the interface SSC interrupt handler if it is
- * non-NULL.
- */
-struct at32_pcm_dma_params {
- char *name; /* stream identifier */
- int pdc_xfer_size; /* PDC counter increment in bytes */
- struct ssc_device *ssc; /* SSC device for stream */
- struct at32_pdc_regs *pdc; /* PDC register info */
- struct at32_ssc_mask *mask; /* SSC mask info */
- struct snd_pcm_substream *substream;
- void (*dma_intr_handler) (u32, struct snd_pcm_substream *);
-};
-
-
-
-/*
- * The AT32 ASoC platform driver
- */
-extern struct snd_soc_platform at32_soc_platform;
-
-
-
-/*
- * SSC register access (since ssc_writel() / ssc_readl() require literal name)
- */
-#define ssc_readx(base, reg) (__raw_readl((base) + (reg)))
-#define ssc_writex(base, reg, value) __raw_writel((value), (base) + (reg))
-
-#endif /* __SOUND_SOC_AT32_AT32_PCM_H */
diff --git a/sound/soc/at32/at32-ssc.c b/sound/soc/at32/at32-ssc.c
deleted file mode 100644
index 4ef6492c902..00000000000
--- a/sound/soc/at32/at32-ssc.c
+++ /dev/null
@@ -1,849 +0,0 @@
-/* sound/soc/at32/at32-ssc.c
- * ASoC platform driver for AT32 using SSC as DAI
- *
- * Copyright (C) 2008 Long Range Systems
- * Geoffrey Wossum <gwossum@acm.org>
- *
- * 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.
- *
- * Note that this is basically a port of the sound/soc/at91-ssc.c to
- * the AVR32 kernel. Thanks to Frank Mandarino for that code.
- */
-
-/* #define DEBUG */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/device.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/atmel_pdc.h>
-#include <linux/atmel-ssc.h>
-
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/initval.h>
-#include <sound/soc.h>
-
-#include "at32-pcm.h"
-#include "at32-ssc.h"
-
-
-
-/*-------------------------------------------------------------------------*\
- * Constants
-\*-------------------------------------------------------------------------*/
-#define NUM_SSC_DEVICES 3
-
-/*
- * SSC direction masks
- */
-#define SSC_DIR_MASK_UNUSED 0
-#define SSC_DIR_MASK_PLAYBACK 1
-#define SSC_DIR_MASK_CAPTURE 2
-
-/*
- * SSC register values that Atmel left out of <linux/atmel-ssc.h>. These
- * are expected to be used with SSC_BF
- */
-/* START bit field values */
-#define SSC_START_CONTINUOUS 0
-#define SSC_START_TX_RX 1
-#define SSC_START_LOW_RF 2
-#define SSC_START_HIGH_RF 3
-#define SSC_START_FALLING_RF 4
-#define SSC_START_RISING_RF 5
-#define SSC_START_LEVEL_RF 6
-#define SSC_START_EDGE_RF 7
-#define SSS_START_COMPARE_0 8
-
-/* CKI bit field values */
-#define SSC_CKI_FALLING 0
-#define SSC_CKI_RISING 1
-
-/* CKO bit field values */
-#define SSC_CKO_NONE 0
-#define SSC_CKO_CONTINUOUS 1
-#define SSC_CKO_TRANSFER 2
-
-/* CKS bit field values */
-#define SSC_CKS_DIV 0
-#define SSC_CKS_CLOCK 1
-#define SSC_CKS_PIN 2
-
-/* FSEDGE bit field values */
-#define SSC_FSEDGE_POSITIVE 0
-#define SSC_FSEDGE_NEGATIVE 1
-
-/* FSOS bit field values */
-#define SSC_FSOS_NONE 0
-#define SSC_FSOS_NEGATIVE 1
-#define SSC_FSOS_POSITIVE 2
-#define SSC_FSOS_LOW 3
-#define SSC_FSOS_HIGH 4
-#define SSC_FSOS_TOGGLE 5
-
-#define START_DELAY 1
-
-
-
-/*-------------------------------------------------------------------------*\
- * Module data
-\*-------------------------------------------------------------------------*/
-/*
- * SSC PDC registered required by the PCM DMA engine
- */
-static struct at32_pdc_regs pdc_tx_reg = {
- .xpr = SSC_PDC_TPR,
- .xcr = SSC_PDC_TCR,
- .xnpr = SSC_PDC_TNPR,
- .xncr = SSC_PDC_TNCR,
-};
-
-
-
-static struct at32_pdc_regs pdc_rx_reg = {
- .xpr = SSC_PDC_RPR,
- .xcr = SSC_PDC_RCR,
- .xnpr = SSC_PDC_RNPR,
- .xncr = SSC_PDC_RNCR,
-};
-
-
-
-/*
- * SSC and PDC status bits for transmit and receive
- */
-static struct at32_ssc_mask ssc_tx_mask = {
- .ssc_enable = SSC_BIT(CR_TXEN),
- .ssc_disable = SSC_BIT(CR_TXDIS),
- .ssc_endx = SSC_BIT(SR_ENDTX),
- .ssc_endbuf = SSC_BIT(SR_TXBUFE),
- .pdc_enable = SSC_BIT(PDC_PTCR_TXTEN),
- .pdc_disable = SSC_BIT(PDC_PTCR_TXTDIS),
-};
-
-
-
-static struct at32_ssc_mask ssc_rx_mask = {
- .ssc_enable = SSC_BIT(CR_RXEN),
- .ssc_disable = SSC_BIT(CR_RXDIS),
- .ssc_endx = SSC_BIT(SR_ENDRX),
- .ssc_endbuf = SSC_BIT(SR_RXBUFF),
- .pdc_enable = SSC_BIT(PDC_PTCR_RXTEN),
- .pdc_disable = SSC_BIT(PDC_PTCR_RXTDIS),
-};
-
-
-
-/*
- * DMA parameters for each SSC
- */
-static struct at32_pcm_dma_params ssc_dma_params[NUM_SSC_DEVICES][2] = {
- {
- {
- .name = "SSC0 PCM out",
- .pdc = &pdc_tx_reg,
- .mask = &ssc_tx_mask,
- },
- {
- .name = "SSC0 PCM in",
- .pdc = &pdc_rx_reg,
- .mask = &ssc_rx_mask,
- },
- },
- {
- {
- .name = "SSC1 PCM out",
- .pdc = &pdc_tx_reg,
- .mask = &ssc_tx_mask,
- },
- {
- .name = "SSC1 PCM in",
- .pdc = &pdc_rx_reg,
- .mask = &ssc_rx_mask,
- },
- },
- {
- {
- .name = "SSC2 PCM out",
- .pdc = &pdc_tx_reg,
- .mask = &ssc_tx_mask,
- },
- {
- .name = "SSC2 PCM in",
- .pdc = &pdc_rx_reg,
- .mask = &ssc_rx_mask,
- },
- },
-};
-
-
-
-static struct at32_ssc_info ssc_info[NUM_SSC_DEVICES] = {
- {
- .name = "ssc0",
- .lock = __SPIN_LOCK_UNLOCKED(ssc_info[0].lock),
- .dir_mask = SSC_DIR_MASK_UNUSED,
- .initialized = 0,
- },
- {
- .name = "ssc1",
- .lock = __SPIN_LOCK_UNLOCKED(ssc_info[1].lock),
- .dir_mask = SSC_DIR_MASK_UNUSED,
- .initialized = 0,
- },
- {
- .name = "ssc2",
- .lock = __SPIN_LOCK_UNLOCKED(ssc_info[2].lock),
- .dir_mask = SSC_DIR_MASK_UNUSED,
- .initialized = 0,
- },
-};
-
-
-
-
-/*-------------------------------------------------------------------------*\
- * ISR
-\*-------------------------------------------------------------------------*/
-/*
- * SSC interrupt handler. Passes PDC interrupts to the DMA interrupt
- * handler in the PCM driver.
- */
-static irqreturn_t at32_ssc_interrupt(int irq, void *dev_id)
-{
- struct at32_ssc_info *ssc_p = dev_id;
- struct at32_pcm_dma_params *dma_params;
- u32 ssc_sr;
- u32 ssc_substream_mask;
- int i;
-
- ssc_sr = (ssc_readl(ssc_p->ssc->regs, SR) &
- ssc_readl(ssc_p->ssc->regs, IMR));
-
- /*
- * Loop through substreams attached to this SSC. If a DMA-related
- * interrupt occured on that substream, call the DMA interrupt
- * handler function, if one has been registered in the dma_param
- * structure by the PCM driver.
- */
- for (i = 0; i < ARRAY_SIZE(ssc_p->dma_params); i++) {
- dma_params = ssc_p->dma_params[i];
-
- if ((dma_params != NULL) &&
- (dma_params->dma_intr_handler != NULL)) {
- ssc_substream_mask = (dma_params->mask->ssc_endx |
- dma_params->mask->ssc_endbuf);
- if (ssc_sr & ssc_substream_mask) {
- dma_params->dma_intr_handler(ssc_sr,
- dma_params->
- substream);
- }
- }
- }
-
-
- return IRQ_HANDLED;
-}
-
-/*-------------------------------------------------------------------------*\
- * DAI functions
-\*-------------------------------------------------------------------------*/
-/*
- * Startup. Only that one substream allowed in each direction.
- */
-static int at32_ssc_startup(struct snd_pcm_substream *substream)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct at32_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
- int dir_mask;
-
- dir_mask = ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
- SSC_DIR_MASK_PLAYBACK : SSC_DIR_MASK_CAPTURE);
-
- spin_lock_irq(&ssc_p->lock);
- if (ssc_p->dir_mask & dir_mask) {
- spin_unlock_irq(&ssc_p->lock);
- return -EBUSY;
- }
- ssc_p->dir_mask |= dir_mask;
- spin_unlock_irq(&ssc_p->lock);
-
- return 0;
-}
-
-
-
-/*
- * Shutdown. Clear DMA parameters and shutdown the SSC if there
- * are no other substreams open.
- */
-static void at32_ssc_shutdown(struct snd_pcm_substream *substream)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct at32_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
- struct at32_pcm_dma_params *dma_params;
- int dir_mask;
-
- dma_params = ssc_p->dma_params[substream->stream];
-
- if (dma_params != NULL) {
- ssc_writel(dma_params->ssc->regs, CR,
- dma_params->mask->ssc_disable);
- pr_debug("%s disabled SSC_SR=0x%08x\n",
- (substream->stream ? "receiver" : "transmit"),
- ssc_readl(ssc_p->ssc->regs, SR));
-
- dma_params->ssc = NULL;
- dma_params->substream = NULL;
- ssc_p->dma_params[substream->stream] = NULL;
- }
-
-
- dir_mask = 1 << substream->stream;
- spin_lock_irq(&ssc_p->lock);
- ssc_p->dir_mask &= ~dir_mask;
- if (!ssc_p->dir_mask) {
- /* Shutdown the SSC clock */
- pr_debug("at32-ssc: Stopping user %d clock\n",
- ssc_p->ssc->user);
- clk_disable(ssc_p->ssc->clk);
-
- if (ssc_p->initialized) {
- free_irq(ssc_p->ssc->irq, ssc_p);
- ssc_p->initialized = 0;
- }
-
- /* Reset the SSC */
- ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST));
-
- /* clear the SSC dividers */
- ssc_p->cmr_div = 0;
- ssc_p->tcmr_period = 0;
- ssc_p->rcmr_period = 0;
- }
- spin_unlock_irq(&ssc_p->lock);
-}
-
-
-
-/*
- * Set the SSC system clock rate
- */
-static int at32_ssc_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
- int clk_id, unsigned int freq, int dir)
-{
- /* TODO: What the heck do I do here? */
- return 0;
-}
-
-
-
-/*
- * Record DAI format for use by hw_params()
- */
-static int at32_ssc_set_dai_fmt(struct snd_soc_dai *cpu_dai,
- unsigned int fmt)
-{
- struct at32_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
-
- ssc_p->daifmt = fmt;
- return 0;
-}
-
-
-
-/*
- * Record SSC clock dividers for use in hw_params()
- */
-static int at32_ssc_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
- int div_id, int div)
-{
- struct at32_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
-
- switch (div_id) {
- case AT32_SSC_CMR_DIV:
- /*
- * The same master clock divider is used for both
- * transmit and receive, so if a value has already
- * been set, it must match this value
- */
- if (ssc_p->cmr_div == 0)
- ssc_p->cmr_div = div;
- else if (div != ssc_p->cmr_div)
- return -EBUSY;
- break;
-
- case AT32_SSC_TCMR_PERIOD:
- ssc_p->tcmr_period = div;
- break;
-
- case AT32_SSC_RCMR_PERIOD:
- ssc_p->rcmr_period = div;
- break;
-
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-
-
-/*
- * Configure the SSC
- */
-static int at32_ssc_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- int id = rtd->dai->cpu_dai->id;
- struct at32_ssc_info *ssc_p = &ssc_info[id];
- struct at32_pcm_dma_params *dma_params;
- int channels, bits;
- u32 tfmr, rfmr, tcmr, rcmr;
- int start_event;
- int ret;
-
-
- /*
- * Currently, there is only one set of dma_params for each direction.
- * If more are added, this code will have to be changed to select
- * the proper set
- */
- dma_params = &ssc_dma_params[id][substream->stream];
- dma_params->ssc = ssc_p->ssc;
- dma_params->substream = substream;
-
- ssc_p->dma_params[substream->stream] = dma_params;
-
-
- /*
- * The cpu_dai->dma_data field is only used to communicate the
- * appropriate DMA parameters to the PCM driver's hw_params()
- * function. It should not be used for other purposes as it
- * is common to all substreams.
- */
- rtd->dai->cpu_dai->dma_data = dma_params;
-
- channels = params_channels(params);
-
-
- /*
- * Determine sample size in bits and the PDC increment
- */
- switch (params_format(params)) {
- case SNDRV_PCM_FORMAT_S8:
- bits = 8;
- dma_params->pdc_xfer_size = 1;
- break;
-
- case SNDRV_PCM_FORMAT_S16:
- bits = 16;
- dma_params->pdc_xfer_size = 2;
- break;
-
- case SNDRV_PCM_FORMAT_S24:
- bits = 24;
- dma_params->pdc_xfer_size = 4;
- break;
-
- case SNDRV_PCM_FORMAT_S32:
- bits = 32;
- dma_params->pdc_xfer_size = 4;
- break;
-
- default:
- pr_warning("at32-ssc: Unsupported PCM format %d",
- params_format(params));
- return -EINVAL;
- }
- pr_debug("at32-ssc: bits = %d, pdc_xfer_size = %d, channels = %d\n",
- bits, dma_params->pdc_xfer_size, channels);
-
-
- /*
- * The SSC only supports up to 16-bit samples in I2S format, due
- * to the size of the Frame Mode Register FSLEN field.
- */
- if ((ssc_p->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S)
- if (bits > 16) {
- pr_warning("at32-ssc: "
- "sample size %d is too large for I2S\n",
- bits);
- return -EINVAL;
- }
-
-
- /*
- * Compute the SSC register settings
- */
- switch (ssc_p->daifmt & (SND_SOC_DAIFMT_FORMAT_MASK |
- SND_SOC_DAIFMT_MASTER_MASK)) {
- case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS:
- /*
- * I2S format, SSC provides BCLK and LRS clocks.
- *
- * The SSC transmit and receive clocks are generated from the
- * MCK divider, and the BCLK signal is output on the SSC TK line
- */
- pr_debug("at32-ssc: SSC mode is I2S BCLK / FRAME master\n");
- rcmr = (SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period) |
- SSC_BF(RCMR_STTDLY, START_DELAY) |
- SSC_BF(RCMR_START, SSC_START_FALLING_RF) |
- SSC_BF(RCMR_CKI, SSC_CKI_RISING) |
- SSC_BF(RCMR_CKO, SSC_CKO_NONE) |
- SSC_BF(RCMR_CKS, SSC_CKS_DIV));
-
- rfmr = (SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) |
- SSC_BF(RFMR_FSOS, SSC_FSOS_NEGATIVE) |
- SSC_BF(RFMR_FSLEN, bits - 1) |
- SSC_BF(RFMR_DATNB, channels - 1) |
- SSC_BIT(RFMR_MSBF) | SSC_BF(RFMR_DATLEN, bits - 1));
-
- tcmr = (SSC_BF(TCMR_PERIOD, ssc_p->tcmr_period) |
- SSC_BF(TCMR_STTDLY, START_DELAY) |
- SSC_BF(TCMR_START, SSC_START_FALLING_RF) |
- SSC_BF(TCMR_CKI, SSC_CKI_FALLING) |
- SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS) |
- SSC_BF(TCMR_CKS, SSC_CKS_DIV));
-
- tfmr = (SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) |
- SSC_BF(TFMR_FSOS, SSC_FSOS_NEGATIVE) |
- SSC_BF(TFMR_FSLEN, bits - 1) |
- SSC_BF(TFMR_DATNB, channels - 1) | SSC_BIT(TFMR_MSBF) |
- SSC_BF(TFMR_DATLEN, bits - 1));
- break;
-
-
- case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM:
- /*
- * I2S format, CODEC supplies BCLK and LRC clock.
- *
- * The SSC transmit clock is obtained from the BCLK signal
- * on the TK line, and the SSC receive clock is generated from
- * the transmit clock.
- *
- * For single channel data, one sample is transferred on the
- * falling edge of the LRC clock. For two channel data, one
- * sample is transferred on both edges of the LRC clock.
- */
- pr_debug("at32-ssc: SSC mode is I2S BCLK / FRAME slave\n");
- start_event = ((channels == 1) ?
- SSC_START_FALLING_RF : SSC_START_EDGE_RF);
-
- rcmr = (SSC_BF(RCMR_STTDLY, START_DELAY) |
- SSC_BF(RCMR_START, start_event) |
- SSC_BF(RCMR_CKI, SSC_CKI_RISING) |
- SSC_BF(RCMR_CKO, SSC_CKO_NONE) |
- SSC_BF(RCMR_CKS, SSC_CKS_CLOCK));
-
- rfmr = (SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) |
- SSC_BF(RFMR_FSOS, SSC_FSOS_NONE) |
- SSC_BIT(RFMR_MSBF) | SSC_BF(RFMR_DATLEN, bits - 1));
-
- tcmr = (SSC_BF(TCMR_STTDLY, START_DELAY) |
- SSC_BF(TCMR_START, start_event) |
- SSC_BF(TCMR_CKI, SSC_CKI_FALLING) |
- SSC_BF(TCMR_CKO, SSC_CKO_NONE) |
- SSC_BF(TCMR_CKS, SSC_CKS_PIN));
-
- tfmr = (SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) |
- SSC_BF(TFMR_FSOS, SSC_FSOS_NONE) |
- SSC_BIT(TFMR_MSBF) | SSC_BF(TFMR_DATLEN, bits - 1));
- break;
-
-
- case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS:
- /*
- * DSP/PCM Mode A format, SSC provides BCLK and LRC clocks.
- *
- * The SSC transmit and receive clocks are generated from the
- * MCK divider, and the BCLK signal is output on the SSC TK line
- */
- pr_debug("at32-ssc: SSC mode is DSP A BCLK / FRAME master\n");
- rcmr = (SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period) |
- SSC_BF(RCMR_STTDLY, 1) |
- SSC_BF(RCMR_START, SSC_START_RISING_RF) |
- SSC_BF(RCMR_CKI, SSC_CKI_RISING) |
- SSC_BF(RCMR_CKO, SSC_CKO_NONE) |
- SSC_BF(RCMR_CKS, SSC_CKS_DIV));
-
- rfmr = (SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) |
- SSC_BF(RFMR_FSOS, SSC_FSOS_POSITIVE) |
- SSC_BF(RFMR_DATNB, channels - 1) |
- SSC_BIT(RFMR_MSBF) | SSC_BF(RFMR_DATLEN, bits - 1));
-
- tcmr = (SSC_BF(TCMR_PERIOD, ssc_p->tcmr_period) |
- SSC_BF(TCMR_STTDLY, 1) |
- SSC_BF(TCMR_START, SSC_START_RISING_RF) |
- SSC_BF(TCMR_CKI, SSC_CKI_RISING) |
- SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS) |
- SSC_BF(TCMR_CKS, SSC_CKS_DIV));
-
- tfmr = (SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) |
- SSC_BF(TFMR_FSOS, SSC_FSOS_POSITIVE) |
- SSC_BF(TFMR_DATNB, channels - 1) |
- SSC_BIT(TFMR_MSBF) | SSC_BF(TFMR_DATLEN, bits - 1));
- break;
-
-
- case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM:
- default:
- pr_warning("at32-ssc: unsupported DAI format 0x%x\n",
- ssc_p->daifmt);
- return -EINVAL;
- break;
- }
- pr_debug("at32-ssc: RCMR=%08x RFMR=%08x TCMR=%08x TFMR=%08x\n",
- rcmr, rfmr, tcmr, tfmr);
-
-
- if (!ssc_p->initialized) {
- /* enable peripheral clock */
- pr_debug("at32-ssc: Starting clock\n");
- clk_enable(ssc_p->ssc->clk);
-
- /* Reset the SSC and its PDC registers */
- ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST));
-
- ssc_writel(ssc_p->ssc->regs, PDC_RPR, 0);
- ssc_writel(ssc_p->ssc->regs, PDC_RCR, 0);
- ssc_writel(ssc_p->ssc->regs, PDC_RNPR, 0);
- ssc_writel(ssc_p->ssc->regs, PDC_RNCR, 0);
-
- ssc_writel(ssc_p->ssc->regs, PDC_TPR, 0);
- ssc_writel(ssc_p->ssc->regs, PDC_TCR, 0);
- ssc_writel(ssc_p->ssc->regs, PDC_TNPR, 0);
- ssc_writel(ssc_p->ssc->regs, PDC_TNCR, 0);
-
- ret = request_irq(ssc_p->ssc->irq, at32_ssc_interrupt, 0,
- ssc_p->name, ssc_p);
- if (ret < 0) {
- pr_warning("at32-ssc: request irq failed (%d)\n", ret);
- pr_debug("at32-ssc: Stopping clock\n");
- clk_disable(ssc_p->ssc->clk);
- return ret;
- }
-
- ssc_p->initialized = 1;
- }
-
- /* Set SSC clock mode register */
- ssc_writel(ssc_p->ssc->regs, CMR, ssc_p->cmr_div);
-
- /* set receive clock mode and format */
- ssc_writel(ssc_p->ssc->regs, RCMR, rcmr);
- ssc_writel(ssc_p->ssc->regs, RFMR, rfmr);
-
- /* set transmit clock mode and format */
- ssc_writel(ssc_p->ssc->regs, TCMR, tcmr);
- ssc_writel(ssc_p->ssc->regs, TFMR, tfmr);
-
- pr_debug("at32-ssc: SSC initialized\n");
- return 0;
-}
-
-
-
-static int at32_ssc_prepare(struct snd_pcm_substream *substream)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct at32_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
- struct at32_pcm_dma_params *dma_params;
-
- dma_params = ssc_p->dma_params[substream->stream];
-
- ssc_writel(dma_params->ssc->regs, CR, dma_params->mask->ssc_enable);
-
- return 0;
-}
-
-
-
-#ifdef CONFIG_PM
-static int at32_ssc_suspend(struct platform_device *pdev,
- struct snd_soc_dai *cpu_dai)
-{
- struct at32_ssc_info *ssc_p;
-
- if (!cpu_dai->active)
- return 0;
-
- ssc_p = &ssc_info[cpu_dai->id];
-
- /* Save the status register before disabling transmit and receive */
- ssc_p->ssc_state.ssc_sr = ssc_readl(ssc_p->ssc->regs, SR);
- ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_TXDIS) | SSC_BIT(CR_RXDIS));
-
- /* Save the current interrupt mask, then disable unmasked interrupts */
- ssc_p->ssc_state.ssc_imr = ssc_readl(ssc_p->ssc->regs, IMR);
- ssc_writel(ssc_p->ssc->regs, IDR, ssc_p->ssc_state.ssc_imr);
-
- ssc_p->ssc_state.ssc_cmr = ssc_readl(ssc_p->ssc->regs, CMR);
- ssc_p->ssc_state.ssc_rcmr = ssc_readl(ssc_p->ssc->regs, RCMR);
- ssc_p->ssc_state.ssc_rfmr = ssc_readl(ssc_p->ssc->regs, RFMR);
- ssc_p->ssc_state.ssc_tcmr = ssc_readl(ssc_p->ssc->regs, TCMR);
- ssc_p->ssc_state.ssc_tfmr = ssc_readl(ssc_p->ssc->regs, TFMR);
-
- return 0;
-}
-
-
-
-static int at32_ssc_resume(struct platform_device *pdev,
- struct snd_soc_dai *cpu_dai)
-{
- struct at32_ssc_info *ssc_p;
- u32 cr;
-
- if (!cpu_dai->active)
- return 0;
-
- ssc_p = &ssc_info[cpu_dai->id];
-
- /* restore SSC register settings */
- ssc_writel(ssc_p->ssc->regs, TFMR, ssc_p->ssc_state.ssc_tfmr);
- ssc_writel(ssc_p->ssc->regs, TCMR, ssc_p->ssc_state.ssc_tcmr);
- ssc_writel(ssc_p->ssc->regs, RFMR, ssc_p->ssc_state.ssc_rfmr);
- ssc_writel(ssc_p->ssc->regs, RCMR, ssc_p->ssc_state.ssc_rcmr);
- ssc_writel(ssc_p->ssc->regs, CMR, ssc_p->ssc_state.ssc_cmr);
-
- /* re-enable interrupts */
- ssc_writel(ssc_p->ssc->regs, IER, ssc_p->ssc_state.ssc_imr);
-
- /* Re-enable recieve and transmit as appropriate */
- cr = 0;
- cr |=
- (ssc_p->ssc_state.ssc_sr & SSC_BIT(SR_RXEN)) ? SSC_BIT(CR_RXEN) : 0;
- cr |=
- (ssc_p->ssc_state.ssc_sr & SSC_BIT(SR_TXEN)) ? SSC_BIT(CR_TXEN) : 0;
- ssc_writel(ssc_p->ssc->regs, CR, cr);
-
- return 0;
-}
-#else /* CONFIG_PM */
-# define at32_ssc_suspend NULL
-# define at32_ssc_resume NULL
-#endif /* CONFIG_PM */
-
-
-#define AT32_SSC_RATES \
- (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \
- SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
- SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
-
-
-#define AT32_SSC_FORMATS \
- (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16 | \
- SNDRV_PCM_FMTBIT_S24 | SNDRV_PCM_FMTBIT_S32)
-
-
-struct snd_soc_dai at32_ssc_dai[NUM_SSC_DEVICES] = {
- {
- .name = "at32-ssc0",
- .id = 0,
- .type = SND_SOC_DAI_PCM,
- .suspend = at32_ssc_suspend,
- .resume = at32_ssc_resume,
- .playback = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = AT32_SSC_RATES,
- .formats = AT32_SSC_FORMATS,
- },
- .capture = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = AT32_SSC_RATES,
- .formats = AT32_SSC_FORMATS,
- },
- .ops = {
- .startup = at32_ssc_startup,
- .shutdown = at32_ssc_shutdown,
- .prepare = at32_ssc_prepare,
- .hw_params = at32_ssc_hw_params,
- },
- .dai_ops = {
- .set_sysclk = at32_ssc_set_dai_sysclk,
- .set_fmt = at32_ssc_set_dai_fmt,
- .set_clkdiv = at32_ssc_set_dai_clkdiv,
- },
- .private_data = &ssc_info[0],
- },
- {
- .name = "at32-ssc1",
- .id = 1,
- .type = SND_SOC_DAI_PCM,
- .suspend = at32_ssc_suspend,
- .resume = at32_ssc_resume,
- .playback = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = AT32_SSC_RATES,
- .formats = AT32_SSC_FORMATS,
- },
- .capture = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = AT32_SSC_RATES,
- .formats = AT32_SSC_FORMATS,
- },
- .ops = {
- .startup = at32_ssc_startup,
- .shutdown = at32_ssc_shutdown,
- .prepare = at32_ssc_prepare,
- .hw_params = at32_ssc_hw_params,
- },
- .dai_ops = {
- .set_sysclk = at32_ssc_set_dai_sysclk,
- .set_fmt = at32_ssc_set_dai_fmt,
- .set_clkdiv = at32_ssc_set_dai_clkdiv,
- },
- .private_data = &ssc_info[1],
- },
- {
- .name = "at32-ssc2",
- .id = 2,
- .type = SND_SOC_DAI_PCM,
- .suspend = at32_ssc_suspend,
- .resume = at32_ssc_resume,
- .playback = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = AT32_SSC_RATES,
- .formats = AT32_SSC_FORMATS,
- },
- .capture = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = AT32_SSC_RATES,
- .formats = AT32_SSC_FORMATS,
- },
- .ops = {
- .startup = at32_ssc_startup,
- .shutdown = at32_ssc_shutdown,
- .prepare = at32_ssc_prepare,
- .hw_params = at32_ssc_hw_params,
- },
- .dai_ops = {
- .set_sysclk = at32_ssc_set_dai_sysclk,
- .set_fmt = at32_ssc_set_dai_fmt,
- .set_clkdiv = at32_ssc_set_dai_clkdiv,
- },
- .private_data = &ssc_info[2],
- },
-};
-EXPORT_SYMBOL_GPL(at32_ssc_dai);
-
-
-MODULE_AUTHOR("Geoffrey Wossum <gwossum@acm.org>");
-MODULE_DESCRIPTION("AT32 SSC ASoC Interface");
-MODULE_LICENSE("GPL");
diff --git a/sound/soc/at32/at32-ssc.h b/sound/soc/at32/at32-ssc.h
deleted file mode 100644
index 3c052dbbe46..00000000000
--- a/sound/soc/at32/at32-ssc.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/* sound/soc/at32/at32-ssc.h
- * ASoC SSC interface for Atmel AT32 SoC
- *
- * Copyright (C) 2008 Long Range Systems
- * Geoffrey Wossum <gwossum@acm.org>
- *
- * 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 __SOUND_SOC_AT32_AT32_SSC_H
-#define __SOUND_SOC_AT32_AT32_SSC_H __FILE__
-
-#include <linux/types.h>
-#include <linux/atmel-ssc.h>
-
-#include "at32-pcm.h"
-
-
-
-struct at32_ssc_state {
- u32 ssc_cmr;
- u32 ssc_rcmr;
- u32 ssc_rfmr;
- u32 ssc_tcmr;
- u32 ssc_tfmr;
- u32 ssc_sr;
- u32 ssc_imr;
-};
-
-
-
-struct at32_ssc_info {
- char *name;
- struct ssc_device *ssc;
- spinlock_t lock; /* lock for dir_mask */
- unsigned short dir_mask; /* 0=unused, 1=playback, 2=capture */
- unsigned short initialized; /* true if SSC has been initialized */
- unsigned short daifmt;
- unsigned short cmr_div;
- unsigned short tcmr_period;
- unsigned short rcmr_period;
- struct at32_pcm_dma_params *dma_params[2];
- struct at32_ssc_state ssc_state;
-};
-
-
-/* SSC divider ids */
-#define AT32_SSC_CMR_DIV 0 /* MCK divider for BCLK */
-#define AT32_SSC_TCMR_PERIOD 1 /* BCLK divider for transmit FS */
-#define AT32_SSC_RCMR_PERIOD 2 /* BCLK divider for receive FS */
-
-
-extern struct snd_soc_dai at32_ssc_dai[];
-
-
-
-#endif /* __SOUND_SOC_AT32_AT32_SSC_H */
diff --git a/sound/soc/at91/Kconfig b/sound/soc/at91/Kconfig
deleted file mode 100644
index 85a883299c2..00000000000
--- a/sound/soc/at91/Kconfig
+++ /dev/null
@@ -1,10 +0,0 @@
-config SND_AT91_SOC
- tristate "SoC Audio for the Atmel AT91 System-on-Chip"
- depends on ARCH_AT91
- help
- Say Y or M if you want to add support for codecs attached to
- the AT91 SSC interface. You will also need
- to select the audio interfaces to support below.
-
-config SND_AT91_SOC_SSC
- tristate
diff --git a/sound/soc/at91/Makefile b/sound/soc/at91/Makefile
deleted file mode 100644
index b817f11df28..00000000000
--- a/sound/soc/at91/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-# AT91 Platform Support
-snd-soc-at91-objs := at91-pcm.o
-snd-soc-at91-ssc-objs := at91-ssc.o
-
-obj-$(CONFIG_SND_AT91_SOC) += snd-soc-at91.o
-obj-$(CONFIG_SND_AT91_SOC_SSC) += snd-soc-at91-ssc.o
diff --git a/sound/soc/at91/at91-pcm.c b/sound/soc/at91/at91-pcm.c
deleted file mode 100644
index 7ab48bd25e4..00000000000
--- a/sound/soc/at91/at91-pcm.c
+++ /dev/null
@@ -1,434 +0,0 @@
-/*
- * at91-pcm.c -- ALSA PCM interface for the Atmel AT91 SoC
- *
- * Author: Frank Mandarino <fmandarino@endrelia.com>
- * Endrelia Technologies Inc.
- * Created: Mar 3, 2006
- *
- * Based on pxa2xx-pcm.c by:
- *
- * Author: Nicolas Pitre
- * Created: Nov 30, 2004
- * Copyright: (C) 2004 MontaVista Software, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/dma-mapping.h>
-#include <linux/atmel_pdc.h>
-
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/soc.h>
-
-#include <mach/hardware.h>
-#include <mach/at91_ssc.h>
-
-#include "at91-pcm.h"
-
-#if 0
-#define DBG(x...) printk(KERN_INFO "at91-pcm: " x)
-#else
-#define DBG(x...)
-#endif
-
-static const struct snd_pcm_hardware at91_pcm_hardware = {
- .info = SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_PAUSE,
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
- .period_bytes_min = 32,
- .period_bytes_max = 8192,
- .periods_min = 2,
- .periods_max = 1024,
- .buffer_bytes_max = 32 * 1024,
-};
-
-struct at91_runtime_data {
- struct at91_pcm_dma_params *params;
- dma_addr_t dma_buffer; /* physical address of dma buffer */
- dma_addr_t dma_buffer_end; /* first address beyond DMA buffer */
- size_t period_size;
- dma_addr_t period_ptr; /* physical address of next period */
- u32 pdc_xpr_save; /* PDC register save */
- u32 pdc_xcr_save;
- u32 pdc_xnpr_save;
- u32 pdc_xncr_save;
-};
-
-static void at91_pcm_dma_irq(u32 ssc_sr,
- struct snd_pcm_substream *substream)
-{
- struct at91_runtime_data *prtd = substream->runtime->private_data;
- struct at91_pcm_dma_params *params = prtd->params;
- static int count = 0;
-
- count++;
-
- if (ssc_sr & params->mask->ssc_endbuf) {
-
- printk(KERN_WARNING
- "at91-pcm: buffer %s on %s (SSC_SR=%#x, count=%d)\n",
- substream->stream == SNDRV_PCM_STREAM_PLAYBACK
- ? "underrun" : "overrun",
- params->name, ssc_sr, count);
-
- /* re-start the PDC */
- at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_disable);
-
- prtd->period_ptr += prtd->period_size;
- if (prtd->period_ptr >= prtd->dma_buffer_end) {
- prtd->period_ptr = prtd->dma_buffer;
- }
-
- at91_ssc_write(params->ssc_base + params->pdc->xpr, prtd->period_ptr);
- at91_ssc_write(params->ssc_base + params->pdc->xcr,
- prtd->period_size / params->pdc_xfer_size);
-
- at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_enable);
- }
-
- if (ssc_sr & params->mask->ssc_endx) {
-
- /* Load the PDC next pointer and counter registers */
- prtd->period_ptr += prtd->period_size;
- if (prtd->period_ptr >= prtd->dma_buffer_end) {
- prtd->period_ptr = prtd->dma_buffer;
- }
- at91_ssc_write(params->ssc_base + params->pdc->xnpr,
- prtd->period_ptr);
- at91_ssc_write(params->ssc_base + params->pdc->xncr,
- prtd->period_size / params->pdc_xfer_size);
- }
-
- snd_pcm_period_elapsed(substream);
-}
-
-static int at91_pcm_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct at91_runtime_data *prtd = runtime->private_data;
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
-
- /* this may get called several times by oss emulation
- * with different params */
-
- snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
- runtime->dma_bytes = params_buffer_bytes(params);
-
- prtd->params = rtd->dai->cpu_dai->dma_data;
- prtd->params->dma_intr_handler = at91_pcm_dma_irq;
-
- prtd->dma_buffer = runtime->dma_addr;
- prtd->dma_buffer_end = runtime->dma_addr + runtime->dma_bytes;
- prtd->period_size = params_period_bytes(params);
-
- DBG("hw_params: DMA for %s initialized (dma_bytes=%d, period_size=%d)\n",
- prtd->params->name, runtime->dma_bytes, prtd->period_size);
- return 0;
-}
-
-static int at91_pcm_hw_free(struct snd_pcm_substream *substream)
-{
- struct at91_runtime_data *prtd = substream->runtime->private_data;
- struct at91_pcm_dma_params *params = prtd->params;
-
- if (params != NULL) {
- at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_disable);
- prtd->params->dma_intr_handler = NULL;
- }
-
- return 0;
-}
-
-static int at91_pcm_prepare(struct snd_pcm_substream *substream)
-{
- struct at91_runtime_data *prtd = substream->runtime->private_data;
- struct at91_pcm_dma_params *params = prtd->params;
-
- at91_ssc_write(params->ssc_base + AT91_SSC_IDR,
- params->mask->ssc_endx | params->mask->ssc_endbuf);
-
- at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_disable);
- return 0;
-}
-
-static int at91_pcm_trigger(struct snd_pcm_substream *substream,
- int cmd)
-{
- struct at91_runtime_data *prtd = substream->runtime->private_data;
- struct at91_pcm_dma_params *params = prtd->params;
- int ret = 0;
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- prtd->period_ptr = prtd->dma_buffer;
-
- at91_ssc_write(params->ssc_base + params->pdc->xpr, prtd->period_ptr);
- at91_ssc_write(params->ssc_base + params->pdc->xcr,
- prtd->period_size / params->pdc_xfer_size);
-
- prtd->period_ptr += prtd->period_size;
- at91_ssc_write(params->ssc_base + params->pdc->xnpr, prtd->period_ptr);
- at91_ssc_write(params->ssc_base + params->pdc->xncr,
- prtd->period_size / params->pdc_xfer_size);
-
- DBG("trigger: period_ptr=%lx, xpr=%lx, xcr=%ld, xnpr=%lx, xncr=%ld\n",
- (unsigned long) prtd->period_ptr,
- at91_ssc_read(params->ssc_base + params->pdc->xpr),
- at91_ssc_read(params->ssc_base + params->pdc->xcr),
- at91_ssc_read(params->ssc_base + params->pdc->xnpr),
- at91_ssc_read(params->ssc_base + params->pdc->xncr));
-
- at91_ssc_write(params->ssc_base + AT91_SSC_IER,
- params->mask->ssc_endx | params->mask->ssc_endbuf);
-
- at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR,
- params->mask->pdc_enable);
-
- DBG("sr=%lx imr=%lx\n",
- at91_ssc_read(params->ssc_base + AT91_SSC_SR),
- at91_ssc_read(params->ssc_base + AT91_SSC_IMR));
- break;
-
- case SNDRV_PCM_TRIGGER_STOP:
- case SNDRV_PCM_TRIGGER_SUSPEND:
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_disable);
- break;
-
- case SNDRV_PCM_TRIGGER_RESUME:
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_enable);
- break;
-
- default:
- ret = -EINVAL;
- }
-
- return ret;
-}
-
-static snd_pcm_uframes_t at91_pcm_pointer(
- struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct at91_runtime_data *prtd = runtime->private_data;
- struct at91_pcm_dma_params *params = prtd->params;
- dma_addr_t ptr;
- snd_pcm_uframes_t x;
-
- ptr = (dma_addr_t) at91_ssc_read(params->ssc_base + params->pdc->xpr);
- x = bytes_to_frames(runtime, ptr - prtd->dma_buffer);
-
- if (x == runtime->buffer_size)
- x = 0;
- return x;
-}
-
-static int at91_pcm_open(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct at91_runtime_data *prtd;
- int ret = 0;
-
- snd_soc_set_runtime_hwparams(substream, &at91_pcm_hardware);
-
- /* ensure that buffer size is a multiple of period size */
- ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
- if (ret < 0)
- goto out;
-
- prtd = kzalloc(sizeof(struct at91_runtime_data), GFP_KERNEL);
- if (prtd == NULL) {
- ret = -ENOMEM;
- goto out;
- }
- runtime->private_data = prtd;
-
- out:
- return ret;
-}
-
-static int at91_pcm_close(struct snd_pcm_substream *substream)
-{
- struct at91_runtime_data *prtd = substream->runtime->private_data;
-
- kfree(prtd);
- return 0;
-}
-
-static int at91_pcm_mmap(struct snd_pcm_substream *substream,
- struct vm_area_struct *vma)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
-
- return dma_mmap_writecombine(substream->pcm->card->dev, vma,
- runtime->dma_area,
- runtime->dma_addr,
- runtime->dma_bytes);
-}
-
-struct snd_pcm_ops at91_pcm_ops = {
- .open = at91_pcm_open,
- .close = at91_pcm_close,
- .ioctl = snd_pcm_lib_ioctl,
- .hw_params = at91_pcm_hw_params,
- .hw_free = at91_pcm_hw_free,
- .prepare = at91_pcm_prepare,
- .trigger = at91_pcm_trigger,
- .pointer = at91_pcm_pointer,
- .mmap = at91_pcm_mmap,
-};
-
-static int at91_pcm_preallocate_dma_buffer(struct snd_pcm *pcm,
- int stream)
-{
- struct snd_pcm_substream *substream = pcm->streams[stream].substream;
- struct snd_dma_buffer *buf = &substream->dma_buffer;
- size_t size = at91_pcm_hardware.buffer_bytes_max;
-
- buf->dev.type = SNDRV_DMA_TYPE_DEV;
- buf->dev.dev = pcm->card->dev;
- buf->private_data = NULL;
- buf->area = dma_alloc_writecombine(pcm->card->dev, size,
- &buf->addr, GFP_KERNEL);
-
- DBG("preallocate_dma_buffer: area=%p, addr=%p, size=%d\n",
- (void *) buf->area,
- (void *) buf->addr,
- size);
-
- if (!buf->area)
- return -ENOMEM;
-
- buf->bytes = size;
- return 0;
-}
-
-static u64 at91_pcm_dmamask = 0xffffffff;
-
-static int at91_pcm_new(struct snd_card *card,
- struct snd_soc_dai *dai, struct snd_pcm *pcm)
-{
- int ret = 0;
-
- if (!card->dev->dma_mask)
- card->dev->dma_mask = &at91_pcm_dmamask;
- if (!card->dev->coherent_dma_mask)
- card->dev->coherent_dma_mask = 0xffffffff;
-
- if (dai->playback.channels_min) {
- ret = at91_pcm_preallocate_dma_buffer(pcm,
- SNDRV_PCM_STREAM_PLAYBACK);
- if (ret)
- goto out;
- }
-
- if (dai->capture.channels_min) {
- ret = at91_pcm_preallocate_dma_buffer(pcm,
- SNDRV_PCM_STREAM_CAPTURE);
- if (ret)
- goto out;
- }
- out:
- return ret;
-}
-
-static void at91_pcm_free_dma_buffers(struct snd_pcm *pcm)
-{
- struct snd_pcm_substream *substream;
- struct snd_dma_buffer *buf;
- int stream;
-
- for (stream = 0; stream < 2; stream++) {
- substream = pcm->streams[stream].substream;
- if (!substream)
- continue;
-
- buf = &substream->dma_buffer;
- if (!buf->area)
- continue;
-
- dma_free_writecombine(pcm->card->dev, buf->bytes,
- buf->area, buf->addr);
- buf->area = NULL;
- }
-}
-
-#ifdef CONFIG_PM
-static int at91_pcm_suspend(struct platform_device *pdev,
- struct snd_soc_dai *dai)
-{
- struct snd_pcm_runtime *runtime = dai->runtime;
- struct at91_runtime_data *prtd;
- struct at91_pcm_dma_params *params;
-
- if (!runtime)
- return 0;
-
- prtd = runtime->private_data;
- params = prtd->params;
-
- /* disable the PDC and save the PDC registers */
-
- at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_disable);
-
- prtd->pdc_xpr_save = at91_ssc_read(params->ssc_base + params->pdc->xpr);
- prtd->pdc_xcr_save = at91_ssc_read(params->ssc_base + params->pdc->xcr);
- prtd->pdc_xnpr_save = at91_ssc_read(params->ssc_base + params->pdc->xnpr);
- prtd->pdc_xncr_save = at91_ssc_read(params->ssc_base + params->pdc->xncr);
-
- return 0;
-}
-
-static int at91_pcm_resume(struct platform_device *pdev,
- struct snd_soc_dai *dai)
-{
- struct snd_pcm_runtime *runtime = dai->runtime;
- struct at91_runtime_data *prtd;
- struct at91_pcm_dma_params *params;
-
- if (!runtime)
- return 0;
-
- prtd = runtime->private_data;
- params = prtd->params;
-
- /* restore the PDC registers and enable the PDC */
- at91_ssc_write(params->ssc_base + params->pdc->xpr, prtd->pdc_xpr_save);
- at91_ssc_write(params->ssc_base + params->pdc->xcr, prtd->pdc_xcr_save);
- at91_ssc_write(params->ssc_base + params->pdc->xnpr, prtd->pdc_xnpr_save);
- at91_ssc_write(params->ssc_base + params->pdc->xncr, prtd->pdc_xncr_save);
-
- at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_enable);
- return 0;
-}
-#else
-#define at91_pcm_suspend NULL
-#define at91_pcm_resume NULL
-#endif
-
-struct snd_soc_platform at91_soc_platform = {
- .name = "at91-audio",
- .pcm_ops = &at91_pcm_ops,
- .pcm_new = at91_pcm_new,
- .pcm_free = at91_pcm_free_dma_buffers,
- .suspend = at91_pcm_suspend,
- .resume = at91_pcm_resume,
-};
-
-EXPORT_SYMBOL_GPL(at91_soc_platform);
-
-MODULE_AUTHOR("Frank Mandarino <fmandarino@endrelia.com>");
-MODULE_DESCRIPTION("Atmel AT91 PCM module");
-MODULE_LICENSE("GPL");
diff --git a/sound/soc/at91/at91-pcm.h b/sound/soc/at91/at91-pcm.h
deleted file mode 100644
index e5aada2cb10..00000000000
--- a/sound/soc/at91/at91-pcm.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * at91-pcm.h - ALSA PCM interface for the Atmel AT91 SoC
- *
- * Author: Frank Mandarino <fmandarino@endrelia.com>
- * Endrelia Technologies Inc.
- * Created: Mar 3, 2006
- *
- * Based on pxa2xx-pcm.h by:
- *
- * Author: Nicolas Pitre
- * Created: Nov 30, 2004
- * Copyright: MontaVista Software, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef _AT91_PCM_H
-#define _AT91_PCM_H
-
-#include <mach/hardware.h>
-
-struct at91_ssc_periph {
- void __iomem *base;
- u32 pid;
-};
-
-/*
- * Registers and status bits that are required by the PCM driver.
- */
-struct at91_pdc_regs {
- unsigned int xpr; /* PDC recv/trans pointer */
- unsigned int xcr; /* PDC recv/trans counter */
- unsigned int xnpr; /* PDC next recv/trans pointer */
- unsigned int xncr; /* PDC next recv/trans counter */
- unsigned int ptcr; /* PDC transfer control */
-};
-
-struct at91_ssc_mask {
- u32 ssc_enable; /* SSC recv/trans enable */
- u32 ssc_disable; /* SSC recv/trans disable */
- u32 ssc_endx; /* SSC ENDTX or ENDRX */
- u32 ssc_endbuf; /* SSC TXBUFE or RXBUFF */
- u32 pdc_enable; /* PDC recv/trans enable */
- u32 pdc_disable; /* PDC recv/trans disable */
-};
-
-/*
- * This structure, shared between the PCM driver and the interface,
- * contains all information required by the PCM driver to perform the
- * PDC DMA operation. All fields except dma_intr_handler() are initialized
- * by the interface. The dms_intr_handler() pointer is set by the PCM
- * driver and called by the interface SSC interrupt handler if it is
- * non-NULL.
- */
-struct at91_pcm_dma_params {
- char *name; /* stream identifier */
- int pdc_xfer_size; /* PDC counter increment in bytes */
- void __iomem *ssc_base; /* SSC base address */
- struct at91_pdc_regs *pdc; /* PDC receive or transmit registers */
- struct at91_ssc_mask *mask;/* SSC & PDC status bits */
- struct snd_pcm_substream *substream;
- void (*dma_intr_handler)(u32, struct snd_pcm_substream *);
-};
-
-extern struct snd_soc_platform at91_soc_platform;
-
-#define at91_ssc_read(a) ((unsigned long) __raw_readl(a))
-#define at91_ssc_write(a,v) __raw_writel((v),(a))
-
-#endif /* _AT91_PCM_H */
diff --git a/sound/soc/at91/at91-ssc.c b/sound/soc/at91/at91-ssc.c
deleted file mode 100644
index 1b61cc46126..00000000000
--- a/sound/soc/at91/at91-ssc.c
+++ /dev/null
@@ -1,791 +0,0 @@
-/*
- * at91-ssc.c -- ALSA SoC AT91 SSC Audio Layer Platform driver
- *
- * Author: Frank Mandarino <fmandarino@endrelia.com>
- * Endrelia Technologies Inc.
- *
- * Based on pxa2xx Platform drivers by
- * Liam Girdwood <lrg@slimlogic.co.uk>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/device.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/atmel_pdc.h>
-
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/initval.h>
-#include <sound/soc.h>
-
-#include <mach/hardware.h>
-#include <mach/at91_pmc.h>
-#include <mach/at91_ssc.h>
-
-#include "at91-pcm.h"
-#include "at91-ssc.h"
-
-#if 0
-#define DBG(x...) printk(KERN_DEBUG "at91-ssc:" x)
-#else
-#define DBG(x...)
-#endif
-
-#if defined(CONFIG_ARCH_AT91SAM9260) || defined(CONFIG_ARCH_AT91SAM9G20)
-#define NUM_SSC_DEVICES 1
-#else
-#define NUM_SSC_DEVICES 3
-#endif
-
-
-/*
- * SSC PDC registers required by the PCM DMA engine.
- */
-static struct at91_pdc_regs pdc_tx_reg = {
- .xpr = ATMEL_PDC_TPR,
- .xcr = ATMEL_PDC_TCR,
- .xnpr = ATMEL_PDC_TNPR,
- .xncr = ATMEL_PDC_TNCR,
-};
-
-static struct at91_pdc_regs pdc_rx_reg = {
- .xpr = ATMEL_PDC_RPR,
- .xcr = ATMEL_PDC_RCR,
- .xnpr = ATMEL_PDC_RNPR,
- .xncr = ATMEL_PDC_RNCR,
-};
-
-/*
- * SSC & PDC status bits for transmit and receive.
- */
-static struct at91_ssc_mask ssc_tx_mask = {
- .ssc_enable = AT91_SSC_TXEN,
- .ssc_disable = AT91_SSC_TXDIS,
- .ssc_endx = AT91_SSC_ENDTX,
- .ssc_endbuf = AT91_SSC_TXBUFE,
- .pdc_enable = ATMEL_PDC_TXTEN,
- .pdc_disable = ATMEL_PDC_TXTDIS,
-};
-
-static struct at91_ssc_mask ssc_rx_mask = {
- .ssc_enable = AT91_SSC_RXEN,
- .ssc_disable = AT91_SSC_RXDIS,
- .ssc_endx = AT91_SSC_ENDRX,
- .ssc_endbuf = AT91_SSC_RXBUFF,
- .pdc_enable = ATMEL_PDC_RXTEN,
- .pdc_disable = ATMEL_PDC_RXTDIS,
-};
-
-
-/*
- * DMA parameters.
- */
-static struct at91_pcm_dma_params ssc_dma_params[NUM_SSC_DEVICES][2] = {
- {{
- .name = "SSC0 PCM out",
- .pdc = &pdc_tx_reg,
- .mask = &ssc_tx_mask,
- },
- {
- .name = "SSC0 PCM in",
- .pdc = &pdc_rx_reg,
- .mask = &ssc_rx_mask,
- }},
-#if NUM_SSC_DEVICES == 3
- {{
- .name = "SSC1 PCM out",
- .pdc = &pdc_tx_reg,
- .mask = &ssc_tx_mask,
- },
- {
- .name = "SSC1 PCM in",
- .pdc = &pdc_rx_reg,
- .mask = &ssc_rx_mask,
- }},
- {{
- .name = "SSC2 PCM out",
- .pdc = &pdc_tx_reg,
- .mask = &ssc_tx_mask,
- },
- {
- .name = "SSC2 PCM in",
- .pdc = &pdc_rx_reg,
- .mask = &ssc_rx_mask,
- }},
-#endif
-};
-
-struct at91_ssc_state {
- u32 ssc_cmr;
- u32 ssc_rcmr;
- u32 ssc_rfmr;
- u32 ssc_tcmr;
- u32 ssc_tfmr;
- u32 ssc_sr;
- u32 ssc_imr;
-};
-
-static struct at91_ssc_info {
- char *name;
- struct at91_ssc_periph ssc;
- spinlock_t lock; /* lock for dir_mask */
- unsigned short dir_mask; /* 0=unused, 1=playback, 2=capture */
- unsigned short initialized; /* 1=SSC has been initialized */
- unsigned short daifmt;
- unsigned short cmr_div;
- unsigned short tcmr_period;
- unsigned short rcmr_period;
- struct at91_pcm_dma_params *dma_params[2];
- struct at91_ssc_state ssc_state;
-
-} ssc_info[NUM_SSC_DEVICES] = {
- {
- .name = "ssc0",
- .lock = __SPIN_LOCK_UNLOCKED(ssc_info[0].lock),
- .dir_mask = 0,
- .initialized = 0,
- },
-#if NUM_SSC_DEVICES == 3
- {
- .name = "ssc1",
- .lock = __SPIN_LOCK_UNLOCKED(ssc_info[1].lock),
- .dir_mask = 0,
- .initialized = 0,
- },
- {
- .name = "ssc2",
- .lock = __SPIN_LOCK_UNLOCKED(ssc_info[2].lock),
- .dir_mask = 0,
- .initialized = 0,
- },
-#endif
-};
-
-static unsigned int at91_ssc_sysclk;
-
-/*
- * SSC interrupt handler. Passes PDC interrupts to the DMA
- * interrupt handler in the PCM driver.
- */
-static irqreturn_t at91_ssc_interrupt(int irq, void *dev_id)
-{
- struct at91_ssc_info *ssc_p = dev_id;
- struct at91_pcm_dma_params *dma_params;
- u32 ssc_sr;
- int i;
-
- ssc_sr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR)
- & at91_ssc_read(ssc_p->ssc.base + AT91_SSC_IMR);
-
- /*
- * Loop through the substreams attached to this SSC. If
- * a DMA-related interrupt occurred on that substream, call
- * the DMA interrupt handler function, if one has been
- * registered in the dma_params structure by the PCM driver.
- */
- for (i = 0; i < ARRAY_SIZE(ssc_p->dma_params); i++) {
- dma_params = ssc_p->dma_params[i];
-
- if (dma_params != NULL && dma_params->dma_intr_handler != NULL &&
- (ssc_sr &
- (dma_params->mask->ssc_endx | dma_params->mask->ssc_endbuf)))
-
- dma_params->dma_intr_handler(ssc_sr, dma_params->substream);
- }
-
- return IRQ_HANDLED;
-}
-
-/*
- * Startup. Only that one substream allowed in each direction.
- */
-static int at91_ssc_startup(struct snd_pcm_substream *substream)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct at91_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
- int dir_mask;
-
- DBG("ssc_startup: SSC_SR=0x%08lx\n",
- at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR));
- dir_mask = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0x1 : 0x2;
-
- spin_lock_irq(&ssc_p->lock);
- if (ssc_p->dir_mask & dir_mask) {
- spin_unlock_irq(&ssc_p->lock);
- return -EBUSY;
- }
- ssc_p->dir_mask |= dir_mask;
- spin_unlock_irq(&ssc_p->lock);
-
- return 0;
-}
-
-/*
- * Shutdown. Clear DMA parameters and shutdown the SSC if there
- * are no other substreams open.
- */
-static void at91_ssc_shutdown(struct snd_pcm_substream *substream)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct at91_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
- struct at91_pcm_dma_params *dma_params;
- int dir, dir_mask;
-
- dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1;
- dma_params = ssc_p->dma_params[dir];
-
- if (dma_params != NULL) {
- at91_ssc_write(dma_params->ssc_base + AT91_SSC_CR,
- dma_params->mask->ssc_disable);
- DBG("%s disabled SSC_SR=0x%08lx\n", (dir ? "receive" : "transmit"),
- at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR));
-
- dma_params->ssc_base = NULL;
- dma_params->substream = NULL;
- ssc_p->dma_params[dir] = NULL;
- }
-
- dir_mask = 1 << dir;
-
- spin_lock_irq(&ssc_p->lock);
- ssc_p->dir_mask &= ~dir_mask;
- if (!ssc_p->dir_mask) {
- /* Shutdown the SSC clock. */
- DBG("Stopping pid %d clock\n", ssc_p->ssc.pid);
- at91_sys_write(AT91_PMC_PCDR, 1<<ssc_p->ssc.pid);
-
- if (ssc_p->initialized) {
- free_irq(ssc_p->ssc.pid, ssc_p);
- ssc_p->initialized = 0;
- }
-
- /* Reset the SSC */
- at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR, AT91_SSC_SWRST);
-
- /* Clear the SSC dividers */
- ssc_p->cmr_div = ssc_p->tcmr_period = ssc_p->rcmr_period = 0;
- }
- spin_unlock_irq(&ssc_p->lock);
-}
-
-/*
- * Record the SSC system clock rate.
- */
-static int at91_ssc_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
- int clk_id, unsigned int freq, int dir)
-{
- /*
- * The only clock supplied to the SSC is the AT91 master clock,
- * which is only used if the SSC is generating BCLK and/or
- * LRC clocks.
- */
- switch (clk_id) {
- case AT91_SYSCLK_MCK:
- at91_ssc_sysclk = freq;
- break;
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-/*
- * Record the DAI format for use in hw_params().
- */
-static int at91_ssc_set_dai_fmt(struct snd_soc_dai *cpu_dai,
- unsigned int fmt)
-{
- struct at91_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
-
- ssc_p->daifmt = fmt;
- return 0;
-}
-
-/*
- * Record SSC clock dividers for use in hw_params().
- */
-static int at91_ssc_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
- int div_id, int div)
-{
- struct at91_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
-
- switch (div_id) {
- case AT91SSC_CMR_DIV:
- /*
- * The same master clock divider is used for both
- * transmit and receive, so if a value has already
- * been set, it must match this value.
- */
- if (ssc_p->cmr_div == 0)
- ssc_p->cmr_div = div;
- else
- if (div != ssc_p->cmr_div)
- return -EBUSY;
- break;
-
- case AT91SSC_TCMR_PERIOD:
- ssc_p->tcmr_period = div;
- break;
-
- case AT91SSC_RCMR_PERIOD:
- ssc_p->rcmr_period = div;
- break;
-
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-/*
- * Configure the SSC.
- */
-static int at91_ssc_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- int id = rtd->dai->cpu_dai->id;
- struct at91_ssc_info *ssc_p = &ssc_info[id];
- struct at91_pcm_dma_params *dma_params;
- int dir, channels, bits;
- u32 tfmr, rfmr, tcmr, rcmr;
- int start_event;
- int ret;
-
- /*
- * Currently, there is only one set of dma params for
- * each direction. If more are added, this code will
- * have to be changed to select the proper set.
- */
- dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1;
-
- dma_params = &ssc_dma_params[id][dir];
- dma_params->ssc_base = ssc_p->ssc.base;
- dma_params->substream = substream;
-
- ssc_p->dma_params[dir] = dma_params;
-
- /*
- * The cpu_dai->dma_data field is only used to communicate the
- * appropriate DMA parameters to the pcm driver hw_params()
- * function. It should not be used for other purposes
- * as it is common to all substreams.
- */
- rtd->dai->cpu_dai->dma_data = dma_params;
-
- channels = params_channels(params);
-
- /*
- * Determine sample size in bits and the PDC increment.
- */
- switch(params_format(params)) {
- case SNDRV_PCM_FORMAT_S8:
- bits = 8;
- dma_params->pdc_xfer_size = 1;
- break;
- case SNDRV_PCM_FORMAT_S16_LE:
- bits = 16;
- dma_params->pdc_xfer_size = 2;
- break;
- case SNDRV_PCM_FORMAT_S24_LE:
- bits = 24;
- dma_params->pdc_xfer_size = 4;
- break;
- case SNDRV_PCM_FORMAT_S32_LE:
- bits = 32;
- dma_params->pdc_xfer_size = 4;
- break;
- default:
- printk(KERN_WARNING "at91-ssc: unsupported PCM format\n");
- return -EINVAL;
- }
-
- /*
- * The SSC only supports up to 16-bit samples in I2S format, due
- * to the size of the Frame Mode Register FSLEN field.
- */
- if ((ssc_p->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S
- && bits > 16) {
- printk(KERN_WARNING
- "at91-ssc: sample size %d is too large for I2S\n", bits);
- return -EINVAL;
- }
-
- /*
- * Compute SSC register settings.
- */
- switch (ssc_p->daifmt
- & (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_MASTER_MASK)) {
-
- case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS:
- /*
- * I2S format, SSC provides BCLK and LRC clocks.
- *
- * The SSC transmit and receive clocks are generated from the
- * MCK divider, and the BCLK signal is output on the SSC TK line.
- */
- rcmr = (( ssc_p->rcmr_period << 24) & AT91_SSC_PERIOD)
- | (( 1 << 16) & AT91_SSC_STTDLY)
- | (( AT91_SSC_START_FALLING_RF ) & AT91_SSC_START)
- | (( AT91_SSC_CK_RISING ) & AT91_SSC_CKI)
- | (( AT91_SSC_CKO_NONE ) & AT91_SSC_CKO)
- | (( AT91_SSC_CKS_DIV ) & AT91_SSC_CKS);
-
- rfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE)
- | (( AT91_SSC_FSOS_NEGATIVE ) & AT91_SSC_FSOS)
- | (((bits - 1) << 16) & AT91_SSC_FSLEN)
- | (((channels - 1) << 8) & AT91_SSC_DATNB)
- | (( 1 << 7) & AT91_SSC_MSBF)
- | (( 0 << 5) & AT91_SSC_LOOP)
- | (((bits - 1) << 0) & AT91_SSC_DATALEN);
-
- tcmr = (( ssc_p->tcmr_period << 24) & AT91_SSC_PERIOD)
- | (( 1 << 16) & AT91_SSC_STTDLY)
- | (( AT91_SSC_START_FALLING_RF ) & AT91_SSC_START)
- | (( AT91_SSC_CKI_FALLING ) & AT91_SSC_CKI)
- | (( AT91_SSC_CKO_CONTINUOUS ) & AT91_SSC_CKO)
- | (( AT91_SSC_CKS_DIV ) & AT91_SSC_CKS);
-
- tfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE)
- | (( 0 << 23) & AT91_SSC_FSDEN)
- | (( AT91_SSC_FSOS_NEGATIVE ) & AT91_SSC_FSOS)
- | (((bits - 1) << 16) & AT91_SSC_FSLEN)
- | (((channels - 1) << 8) & AT91_SSC_DATNB)
- | (( 1 << 7) & AT91_SSC_MSBF)
- | (( 0 << 5) & AT91_SSC_DATDEF)
- | (((bits - 1) << 0) & AT91_SSC_DATALEN);
- break;
-
- case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM:
- /*
- * I2S format, CODEC supplies BCLK and LRC clocks.
- *
- * The SSC transmit clock is obtained from the BCLK signal on
- * on the TK line, and the SSC receive clock is generated from the
- * transmit clock.
- *
- * For single channel data, one sample is transferred on the falling
- * edge of the LRC clock. For two channel data, one sample is
- * transferred on both edges of the LRC clock.
- */
- start_event = channels == 1
- ? AT91_SSC_START_FALLING_RF
- : AT91_SSC_START_EDGE_RF;
-
- rcmr = (( 0 << 24) & AT91_SSC_PERIOD)
- | (( 1 << 16) & AT91_SSC_STTDLY)
- | (( start_event ) & AT91_SSC_START)
- | (( AT91_SSC_CK_RISING ) & AT91_SSC_CKI)
- | (( AT91_SSC_CKO_NONE ) & AT91_SSC_CKO)
- | (( AT91_SSC_CKS_CLOCK ) & AT91_SSC_CKS);
-
- rfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE)
- | (( AT91_SSC_FSOS_NONE ) & AT91_SSC_FSOS)
- | (( 0 << 16) & AT91_SSC_FSLEN)
- | (( 0 << 8) & AT91_SSC_DATNB)
- | (( 1 << 7) & AT91_SSC_MSBF)
- | (( 0 << 5) & AT91_SSC_LOOP)
- | (((bits - 1) << 0) & AT91_SSC_DATALEN);
-
- tcmr = (( 0 << 24) & AT91_SSC_PERIOD)
- | (( 1 << 16) & AT91_SSC_STTDLY)
- | (( start_event ) & AT91_SSC_START)
- | (( AT91_SSC_CKI_FALLING ) & AT91_SSC_CKI)
- | (( AT91_SSC_CKO_NONE ) & AT91_SSC_CKO)
- | (( AT91_SSC_CKS_PIN ) & AT91_SSC_CKS);
-
- tfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE)
- | (( 0 << 23) & AT91_SSC_FSDEN)
- | (( AT91_SSC_FSOS_NONE ) & AT91_SSC_FSOS)
- | (( 0 << 16) & AT91_SSC_FSLEN)
- | (( 0 << 8) & AT91_SSC_DATNB)
- | (( 1 << 7) & AT91_SSC_MSBF)
- | (( 0 << 5) & AT91_SSC_DATDEF)
- | (((bits - 1) << 0) & AT91_SSC_DATALEN);
- break;
-
- case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS:
- /*
- * DSP/PCM Mode A format, SSC provides BCLK and LRC clocks.
- *
- * The SSC transmit and receive clocks are generated from the
- * MCK divider, and the BCLK signal is output on the SSC TK line.
- */
- rcmr = (( ssc_p->rcmr_period << 24) & AT91_SSC_PERIOD)
- | (( 1 << 16) & AT91_SSC_STTDLY)
- | (( AT91_SSC_START_RISING_RF ) & AT91_SSC_START)
- | (( AT91_SSC_CK_RISING ) & AT91_SSC_CKI)
- | (( AT91_SSC_CKO_NONE ) & AT91_SSC_CKO)
- | (( AT91_SSC_CKS_DIV ) & AT91_SSC_CKS);
-
- rfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE)
- | (( AT91_SSC_FSOS_POSITIVE ) & AT91_SSC_FSOS)
- | (( 0 << 16) & AT91_SSC_FSLEN)
- | (((channels - 1) << 8) & AT91_SSC_DATNB)
- | (( 1 << 7) & AT91_SSC_MSBF)
- | (( 0 << 5) & AT91_SSC_LOOP)
- | (((bits - 1) << 0) & AT91_SSC_DATALEN);
-
- tcmr = (( ssc_p->tcmr_period << 24) & AT91_SSC_PERIOD)
- | (( 1 << 16) & AT91_SSC_STTDLY)
- | (( AT91_SSC_START_RISING_RF ) & AT91_SSC_START)
- | (( AT91_SSC_CK_RISING ) & AT91_SSC_CKI)
- | (( AT91_SSC_CKO_CONTINUOUS ) & AT91_SSC_CKO)
- | (( AT91_SSC_CKS_DIV ) & AT91_SSC_CKS);
-
- tfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE)
- | (( 0 << 23) & AT91_SSC_FSDEN)
- | (( AT91_SSC_FSOS_POSITIVE ) & AT91_SSC_FSOS)
- | (( 0 << 16) & AT91_SSC_FSLEN)
- | (((channels - 1) << 8) & AT91_SSC_DATNB)
- | (( 1 << 7) & AT91_SSC_MSBF)
- | (( 0 << 5) & AT91_SSC_DATDEF)
- | (((bits - 1) << 0) & AT91_SSC_DATALEN);
-
-
-
- break;
-
- case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM:
- default:
- printk(KERN_WARNING "at91-ssc: unsupported DAI format 0x%x.\n",
- ssc_p->daifmt);
- return -EINVAL;
- break;
- }
- DBG("RCMR=%08x RFMR=%08x TCMR=%08x TFMR=%08x\n", rcmr, rfmr, tcmr, tfmr);
-
- if (!ssc_p->initialized) {
-
- /* Enable PMC peripheral clock for this SSC */
- DBG("Starting pid %d clock\n", ssc_p->ssc.pid);
- at91_sys_write(AT91_PMC_PCER, 1<<ssc_p->ssc.pid);
-
- /* Reset the SSC and its PDC registers */
- at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR, AT91_SSC_SWRST);
-
- at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_RPR, 0);
- at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_RCR, 0);
- at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_RNPR, 0);
- at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_RNCR, 0);
- at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_TPR, 0);
- at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_TCR, 0);
- at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_TNPR, 0);
- at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_TNCR, 0);
-
- if ((ret = request_irq(ssc_p->ssc.pid, at91_ssc_interrupt,
- 0, ssc_p->name, ssc_p)) < 0) {
- printk(KERN_WARNING "at91-ssc: request_irq failure\n");
-
- DBG("Stopping pid %d clock\n", ssc_p->ssc.pid);
- at91_sys_write(AT91_PMC_PCDR, 1<<ssc_p->ssc.pid);
- return ret;
- }
-
- ssc_p->initialized = 1;
- }
-
- /* set SSC clock mode register */
- at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CMR, ssc_p->cmr_div);
-
- /* set receive clock mode and format */
- at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RCMR, rcmr);
- at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RFMR, rfmr);
-
- /* set transmit clock mode and format */
- at91_ssc_write(ssc_p->ssc.base + AT91_SSC_TCMR, tcmr);
- at91_ssc_write(ssc_p->ssc.base + AT91_SSC_TFMR, tfmr);
-
- DBG("hw_params: SSC initialized\n");
- return 0;
-}
-
-
-static int at91_ssc_prepare(struct snd_pcm_substream *substream)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct at91_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
- struct at91_pcm_dma_params *dma_params;
- int dir;
-
- dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1;
- dma_params = ssc_p->dma_params[dir];
-
- at91_ssc_write(dma_params->ssc_base + AT91_SSC_CR,
- dma_params->mask->ssc_enable);
-
- DBG("%s enabled SSC_SR=0x%08lx\n", dir ? "receive" : "transmit",
- at91_ssc_read(dma_params->ssc_base + AT91_SSC_SR));
- return 0;
-}
-
-
-#ifdef CONFIG_PM
-static int at91_ssc_suspend(struct platform_device *pdev,
- struct snd_soc_dai *cpu_dai)
-{
- struct at91_ssc_info *ssc_p;
-
- if(!cpu_dai->active)
- return 0;
-
- ssc_p = &ssc_info[cpu_dai->id];
-
- /* Save the status register before disabling transmit and receive. */
- ssc_p->ssc_state.ssc_sr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR);
- at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR,
- AT91_SSC_TXDIS | AT91_SSC_RXDIS);
-
- /* Save the current interrupt mask, then disable unmasked interrupts. */
- ssc_p->ssc_state.ssc_imr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_IMR);
- at91_ssc_write(ssc_p->ssc.base + AT91_SSC_IDR, ssc_p->ssc_state.ssc_imr);
-
- ssc_p->ssc_state.ssc_cmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_CMR);
- ssc_p->ssc_state.ssc_rcmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_RCMR);
- ssc_p->ssc_state.ssc_rfmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_RFMR);
- ssc_p->ssc_state.ssc_tcmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_TCMR);
- ssc_p->ssc_state.ssc_tfmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_TFMR);
-
- return 0;
-}
-
-static int at91_ssc_resume(struct platform_device *pdev,
- struct snd_soc_dai *cpu_dai)
-{
- struct at91_ssc_info *ssc_p;
-
- if(!cpu_dai->active)
- return 0;
-
- ssc_p = &ssc_info[cpu_dai->id];
-
- at91_ssc_write(ssc_p->ssc.base + AT91_SSC_TFMR, ssc_p->ssc_state.ssc_tfmr);
- at91_ssc_write(ssc_p->ssc.base + AT91_SSC_TCMR, ssc_p->ssc_state.ssc_tcmr);
- at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RFMR, ssc_p->ssc_state.ssc_rfmr);
- at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RCMR, ssc_p->ssc_state.ssc_rcmr);
- at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CMR, ssc_p->ssc_state.ssc_cmr);
-
- at91_ssc_write(ssc_p->ssc.base + AT91_SSC_IER, ssc_p->ssc_state.ssc_imr);
-
- at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR,
- ((ssc_p->ssc_state.ssc_sr & AT91_SSC_RXENA) ? AT91_SSC_RXEN : 0) |
- ((ssc_p->ssc_state.ssc_sr & AT91_SSC_TXENA) ? AT91_SSC_TXEN : 0));
-
- return 0;
-}
-
-#else
-#define at91_ssc_suspend NULL
-#define at91_ssc_resume NULL
-#endif
-
-#define AT91_SSC_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
- SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\
- SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\
- SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\
- SNDRV_PCM_RATE_96000)
-
-#define AT91_SSC_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\
- SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
-
-struct snd_soc_dai at91_ssc_dai[NUM_SSC_DEVICES] = {
- { .name = "at91-ssc0",
- .id = 0,
- .type = SND_SOC_DAI_PCM,
- .suspend = at91_ssc_suspend,
- .resume = at91_ssc_resume,
- .playback = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = AT91_SSC_RATES,
- .formats = AT91_SSC_FORMATS,},
- .capture = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = AT91_SSC_RATES,
- .formats = AT91_SSC_FORMATS,},
- .ops = {
- .startup = at91_ssc_startup,
- .shutdown = at91_ssc_shutdown,
- .prepare = at91_ssc_prepare,
- .hw_params = at91_ssc_hw_params,},
- .dai_ops = {
- .set_sysclk = at91_ssc_set_dai_sysclk,
- .set_fmt = at91_ssc_set_dai_fmt,
- .set_clkdiv = at91_ssc_set_dai_clkdiv,},
- .private_data = &ssc_info[0].ssc,
- },
-#if NUM_SSC_DEVICES == 3
- { .name = "at91-ssc1",
- .id = 1,
- .type = SND_SOC_DAI_PCM,
- .suspend = at91_ssc_suspend,
- .resume = at91_ssc_resume,
- .playback = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = AT91_SSC_RATES,
- .formats = AT91_SSC_FORMATS,},
- .capture = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = AT91_SSC_RATES,
- .formats = AT91_SSC_FORMATS,},
- .ops = {
- .startup = at91_ssc_startup,
- .shutdown = at91_ssc_shutdown,
- .prepare = at91_ssc_prepare,
- .hw_params = at91_ssc_hw_params,},
- .dai_ops = {
- .set_sysclk = at91_ssc_set_dai_sysclk,
- .set_fmt = at91_ssc_set_dai_fmt,
- .set_clkdiv = at91_ssc_set_dai_clkdiv,},
- .private_data = &ssc_info[1].ssc,
- },
- { .name = "at91-ssc2",
- .id = 2,
- .type = SND_SOC_DAI_PCM,
- .suspend = at91_ssc_suspend,
- .resume = at91_ssc_resume,
- .playback = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = AT91_SSC_RATES,
- .formats = AT91_SSC_FORMATS,},
- .capture = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = AT91_SSC_RATES,
- .formats = AT91_SSC_FORMATS,},
- .ops = {
- .startup = at91_ssc_startup,
- .shutdown = at91_ssc_shutdown,
- .prepare = at91_ssc_prepare,
- .hw_params = at91_ssc_hw_params,},
- .dai_ops = {
- .set_sysclk = at91_ssc_set_dai_sysclk,
- .set_fmt = at91_ssc_set_dai_fmt,
- .set_clkdiv = at91_ssc_set_dai_clkdiv,},
- .private_data = &ssc_info[2].ssc,
- },
-#endif
-};
-
-EXPORT_SYMBOL_GPL(at91_ssc_dai);
-
-/* Module information */
-MODULE_AUTHOR("Frank Mandarino, fmandarino@endrelia.com, www.endrelia.com");
-MODULE_DESCRIPTION("AT91 SSC ASoC Interface");
-MODULE_LICENSE("GPL");
diff --git a/sound/soc/at91/at91-ssc.h b/sound/soc/at91/at91-ssc.h
deleted file mode 100644
index 6b7bf382d06..00000000000
--- a/sound/soc/at91/at91-ssc.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * at91-ssc.h - ALSA SSC interface for the Atmel AT91 SoC
- *
- * Author: Frank Mandarino <fmandarino@endrelia.com>
- * Endrelia Technologies Inc.
- * Created: Jan 9, 2007
- *
- * 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 _AT91_SSC_H
-#define _AT91_SSC_H
-
-/* SSC system clock ids */
-#define AT91_SYSCLK_MCK 0 /* SSC uses AT91 MCK as system clock */
-
-/* SSC divider ids */
-#define AT91SSC_CMR_DIV 0 /* MCK divider for BCLK */
-#define AT91SSC_TCMR_PERIOD 1 /* BCLK divider for transmit FS */
-#define AT91SSC_RCMR_PERIOD 2 /* BCLK divider for receive FS */
-
-extern struct snd_soc_dai at91_ssc_dai[];
-
-#endif /* _AT91_SSC_H */
-
diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig
new file mode 100644
index 00000000000..a608d7009db
--- /dev/null
+++ b/sound/soc/atmel/Kconfig
@@ -0,0 +1,43 @@
+config SND_ATMEL_SOC
+ tristate "SoC Audio for the Atmel System-on-Chip"
+ depends on ARCH_AT91 || AVR32
+ help
+ Say Y or M if you want to add support for codecs attached to
+ the ATMEL SSC interface. You will also need
+ to select the audio interfaces to support below.
+
+config SND_ATMEL_SOC_SSC
+ tristate
+ depends on SND_ATMEL_SOC
+ help
+ Say Y or M if you want to add support for codecs the
+ ATMEL SSC interface. You will also needs to select the individual
+ machine drivers to support below.
+
+config SND_AT91_SOC_SAM9G20_WM8731
+ tristate "SoC Audio support for WM8731-based At91sam9g20 evaluation board"
+ depends on ATMEL_SSC && ARCH_AT91SAM9G20 && SND_ATMEL_SOC
+ select SND_ATMEL_SOC_SSC
+ select SND_SOC_WM8731
+ help
+ Say Y if you want to add support for SoC audio on WM8731-based
+ AT91sam9g20 evaluation board.
+
+config SND_AT32_SOC_PLAYPAQ
+ tristate "SoC Audio support for PlayPaq with WM8510"
+ depends on SND_ATMEL_SOC && BOARD_PLAYPAQ
+ select SND_ATMEL_SOC_SSC
+ select SND_SOC_WM8510
+ help
+ Say Y or M here if you want to add support for SoC audio
+ on the LRS PlayPaq.
+
+config SND_AT32_SOC_PLAYPAQ_SLAVE
+ bool "Run CODEC on PlayPaq in slave mode"
+ depends on SND_AT32_SOC_PLAYPAQ
+ default n
+ help
+ Say Y if you want to run with the AT32 SSC generating the BCLK
+ and FRAME signals on the PlayPaq. Unless you want to play
+ with the AT32 as the SSC master, you probably want to say N here,
+ as this will give you better sound quality.
diff --git a/sound/soc/atmel/Makefile b/sound/soc/atmel/Makefile
new file mode 100644
index 00000000000..f54a7cc68e6
--- /dev/null
+++ b/sound/soc/atmel/Makefile
@@ -0,0 +1,15 @@
+# AT91 Platform Support
+snd-soc-atmel-pcm-objs := atmel-pcm.o
+snd-soc-atmel_ssc_dai-objs := atmel_ssc_dai.o
+
+obj-$(CONFIG_SND_ATMEL_SOC) += snd-soc-atmel-pcm.o
+obj-$(CONFIG_SND_ATMEL_SOC_SSC) += snd-soc-atmel_ssc_dai.o
+
+# AT91 Machine Support
+snd-soc-sam9g20-wm8731-objs := sam9g20_wm8731.o
+
+# AT32 Machine Support
+snd-soc-playpaq-objs := playpaq_wm8510.o
+
+obj-$(CONFIG_SND_AT91_SOC_SAM9G20_WM8731) += snd-soc-sam9g20-wm8731.o
+obj-$(CONFIG_SND_AT32_SOC_PLAYPAQ) += snd-soc-playpaq.o
diff --git a/sound/soc/atmel/atmel-pcm.c b/sound/soc/atmel/atmel-pcm.c
new file mode 100644
index 00000000000..1fac5efd285
--- /dev/null
+++ b/sound/soc/atmel/atmel-pcm.c
@@ -0,0 +1,494 @@
+/*
+ * atmel-pcm.c -- ALSA PCM interface for the Atmel atmel SoC.
+ *
+ * Copyright (C) 2005 SAN People
+ * Copyright (C) 2008 Atmel
+ *
+ * Authors: Sedji Gaouaou <sedji.gaouaou@atmel.com>
+ *
+ * Based on at91-pcm. by:
+ * Frank Mandarino <fmandarino@endrelia.com>
+ * Copyright 2006 Endrelia Technologies Inc.
+ *
+ * Based on pxa2xx-pcm.c by:
+ *
+ * Author: Nicolas Pitre
+ * Created: Nov 30, 2004
+ * Copyright: (C) 2004 MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/atmel_pdc.h>
+#include <linux/atmel-ssc.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include <mach/hardware.h>
+
+#include "atmel-pcm.h"
+
+
+/*--------------------------------------------------------------------------*\
+ * Hardware definition
+\*--------------------------------------------------------------------------*/
+/* TODO: These values were taken from the AT91 platform driver, check
+ * them against real values for AT32
+ */
+static const struct snd_pcm_hardware atmel_pcm_hardware = {
+ .info = SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_PAUSE,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .period_bytes_min = 32,
+ .period_bytes_max = 8192,
+ .periods_min = 2,
+ .periods_max = 1024,
+ .buffer_bytes_max = 32 * 1024,
+};
+
+
+/*--------------------------------------------------------------------------*\
+ * Data types
+\*--------------------------------------------------------------------------*/
+struct atmel_runtime_data {
+ struct atmel_pcm_dma_params *params;
+ dma_addr_t dma_buffer; /* physical address of dma buffer */
+ dma_addr_t dma_buffer_end; /* first address beyond DMA buffer */
+ size_t period_size;
+
+ dma_addr_t period_ptr; /* physical address of next period */
+ int periods; /* period index of period_ptr */
+
+ /* PDC register save */
+ u32 pdc_xpr_save;
+ u32 pdc_xcr_save;
+ u32 pdc_xnpr_save;
+ u32 pdc_xncr_save;
+};
+
+
+/*--------------------------------------------------------------------------*\
+ * Helper functions
+\*--------------------------------------------------------------------------*/
+static int atmel_pcm_preallocate_dma_buffer(struct snd_pcm *pcm,
+ int stream)
+{
+ struct snd_pcm_substream *substream = pcm->streams[stream].substream;
+ struct snd_dma_buffer *buf = &substream->dma_buffer;
+ size_t size = atmel_pcm_hardware.buffer_bytes_max;
+
+ buf->dev.type = SNDRV_DMA_TYPE_DEV;
+ buf->dev.dev = pcm->card->dev;
+ buf->private_data = NULL;
+ buf->area = dma_alloc_coherent(pcm->card->dev, size,
+ &buf->addr, GFP_KERNEL);
+ pr_debug("atmel-pcm:"
+ "preallocate_dma_buffer: area=%p, addr=%p, size=%d\n",
+ (void *) buf->area,
+ (void *) buf->addr,
+ size);
+
+ if (!buf->area)
+ return -ENOMEM;
+
+ buf->bytes = size;
+ return 0;
+}
+/*--------------------------------------------------------------------------*\
+ * ISR
+\*--------------------------------------------------------------------------*/
+static void atmel_pcm_dma_irq(u32 ssc_sr,
+ struct snd_pcm_substream *substream)
+{
+ struct atmel_runtime_data *prtd = substream->runtime->private_data;
+ struct atmel_pcm_dma_params *params = prtd->params;
+ static int count;
+
+ count++;
+
+ if (ssc_sr & params->mask->ssc_endbuf) {
+ pr_warning("atmel-pcm: buffer %s on %s"
+ " (SSC_SR=%#x, count=%d)\n",
+ substream->stream == SNDRV_PCM_STREAM_PLAYBACK
+ ? "underrun" : "overrun",
+ params->name, ssc_sr, count);
+
+ /* re-start the PDC */
+ ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
+ params->mask->pdc_disable);
+ prtd->period_ptr += prtd->period_size;
+ if (prtd->period_ptr >= prtd->dma_buffer_end)
+ prtd->period_ptr = prtd->dma_buffer;
+
+ ssc_writex(params->ssc->regs, params->pdc->xpr,
+ prtd->period_ptr);
+ ssc_writex(params->ssc->regs, params->pdc->xcr,
+ prtd->period_size / params->pdc_xfer_size);
+ ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
+ params->mask->pdc_enable);
+ }
+
+ if (ssc_sr & params->mask->ssc_endx) {
+ /* Load the PDC next pointer and counter registers */
+ prtd->period_ptr += prtd->period_size;
+ if (prtd->period_ptr >= prtd->dma_buffer_end)
+ prtd->period_ptr = prtd->dma_buffer;
+
+ ssc_writex(params->ssc->regs, params->pdc->xnpr,
+ prtd->period_ptr);
+ ssc_writex(params->ssc->regs, params->pdc->xncr,
+ prtd->period_size / params->pdc_xfer_size);
+ }
+
+ snd_pcm_period_elapsed(substream);
+}
+
+
+/*--------------------------------------------------------------------------*\
+ * PCM operations
+\*--------------------------------------------------------------------------*/
+static int atmel_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct atmel_runtime_data *prtd = runtime->private_data;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+
+ /* this may get called several times by oss emulation
+ * with different params */
+
+ snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
+ runtime->dma_bytes = params_buffer_bytes(params);
+
+ prtd->params = rtd->dai->cpu_dai->dma_data;
+ prtd->params->dma_intr_handler = atmel_pcm_dma_irq;
+
+ prtd->dma_buffer = runtime->dma_addr;
+ prtd->dma_buffer_end = runtime->dma_addr + runtime->dma_bytes;
+ prtd->period_size = params_period_bytes(params);
+
+ pr_debug("atmel-pcm: "
+ "hw_params: DMA for %s initialized "
+ "(dma_bytes=%u, period_size=%u)\n",
+ prtd->params->name,
+ runtime->dma_bytes,
+ prtd->period_size);
+ return 0;
+}
+
+static int atmel_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+ struct atmel_runtime_data *prtd = substream->runtime->private_data;
+ struct atmel_pcm_dma_params *params = prtd->params;
+
+ if (params != NULL) {
+ ssc_writex(params->ssc->regs, SSC_PDC_PTCR,
+ params->mask->pdc_disable);
+ prtd->params->dma_intr_handler = NULL;
+ }
+
+ return 0;
+}
+
+static int atmel_pcm_prepare(struct snd_pcm_substream *substream)
+{
+ struct atmel_runtime_data *prtd = substream->runtime->private_data;
+ struct atmel_pcm_dma_params *params = prtd->params;
+
+ ssc_writex(params->ssc->regs, SSC_IDR,
+ params->mask->ssc_endx | params->mask->ssc_endbuf);
+ ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
+ params->mask->pdc_disable);
+ return 0;
+}
+
+static int atmel_pcm_trigger(struct snd_pcm_substream *substream,
+ int cmd)
+{
+ struct snd_pcm_runtime *rtd = substream->runtime;
+ struct atmel_runtime_data *prtd = rtd->private_data;
+ struct atmel_pcm_dma_params *params = prtd->params;
+ int ret = 0;
+
+ pr_debug("atmel-pcm:buffer_size = %ld,"
+ "dma_area = %p, dma_bytes = %u\n",
+ rtd->buffer_size, rtd->dma_area, rtd->dma_bytes);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ prtd->period_ptr = prtd->dma_buffer;
+
+ ssc_writex(params->ssc->regs, params->pdc->xpr,
+ prtd->period_ptr);
+ ssc_writex(params->ssc->regs, params->pdc->xcr,
+ prtd->period_size / params->pdc_xfer_size);
+
+ prtd->period_ptr += prtd->period_size;
+ ssc_writex(params->ssc->regs, params->pdc->xnpr,
+ prtd->period_ptr);
+ ssc_writex(params->ssc->regs, params->pdc->xncr,
+ prtd->period_size / params->pdc_xfer_size);
+
+ pr_debug("atmel-pcm: trigger: "
+ "period_ptr=%lx, xpr=%u, "
+ "xcr=%u, xnpr=%u, xncr=%u\n",
+ (unsigned long)prtd->period_ptr,
+ ssc_readx(params->ssc->regs, params->pdc->xpr),
+ ssc_readx(params->ssc->regs, params->pdc->xcr),
+ ssc_readx(params->ssc->regs, params->pdc->xnpr),
+ ssc_readx(params->ssc->regs, params->pdc->xncr));
+
+ ssc_writex(params->ssc->regs, SSC_IER,
+ params->mask->ssc_endx | params->mask->ssc_endbuf);
+ ssc_writex(params->ssc->regs, SSC_PDC_PTCR,
+ params->mask->pdc_enable);
+
+ pr_debug("sr=%u imr=%u\n",
+ ssc_readx(params->ssc->regs, SSC_SR),
+ ssc_readx(params->ssc->regs, SSC_IER));
+ break; /* SNDRV_PCM_TRIGGER_START */
+
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
+ params->mask->pdc_disable);
+ break;
+
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
+ params->mask->pdc_enable);
+ break;
+
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static snd_pcm_uframes_t atmel_pcm_pointer(
+ struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct atmel_runtime_data *prtd = runtime->private_data;
+ struct atmel_pcm_dma_params *params = prtd->params;
+ dma_addr_t ptr;
+ snd_pcm_uframes_t x;
+
+ ptr = (dma_addr_t) ssc_readx(params->ssc->regs, params->pdc->xpr);
+ x = bytes_to_frames(runtime, ptr - prtd->dma_buffer);
+
+ if (x == runtime->buffer_size)
+ x = 0;
+
+ return x;
+}
+
+static int atmel_pcm_open(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct atmel_runtime_data *prtd;
+ int ret = 0;
+
+ snd_soc_set_runtime_hwparams(substream, &atmel_pcm_hardware);
+
+ /* ensure that buffer size is a multiple of period size */
+ ret = snd_pcm_hw_constraint_integer(runtime,
+ SNDRV_PCM_HW_PARAM_PERIODS);
+ if (ret < 0)
+ goto out;
+
+ prtd = kzalloc(sizeof(struct atmel_runtime_data), GFP_KERNEL);
+ if (prtd == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ runtime->private_data = prtd;
+
+ out:
+ return ret;
+}
+
+static int atmel_pcm_close(struct snd_pcm_substream *substream)
+{
+ struct atmel_runtime_data *prtd = substream->runtime->private_data;
+
+ kfree(prtd);
+ return 0;
+}
+
+static int atmel_pcm_mmap(struct snd_pcm_substream *substream,
+ struct vm_area_struct *vma)
+{
+ return remap_pfn_range(vma, vma->vm_start,
+ substream->dma_buffer.addr >> PAGE_SHIFT,
+ vma->vm_end - vma->vm_start, vma->vm_page_prot);
+}
+
+struct snd_pcm_ops atmel_pcm_ops = {
+ .open = atmel_pcm_open,
+ .close = atmel_pcm_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = atmel_pcm_hw_params,
+ .hw_free = atmel_pcm_hw_free,
+ .prepare = atmel_pcm_prepare,
+ .trigger = atmel_pcm_trigger,
+ .pointer = atmel_pcm_pointer,
+ .mmap = atmel_pcm_mmap,
+};
+
+
+/*--------------------------------------------------------------------------*\
+ * ASoC platform driver
+\*--------------------------------------------------------------------------*/
+static u64 atmel_pcm_dmamask = 0xffffffff;
+
+static int atmel_pcm_new(struct snd_card *card,
+ struct snd_soc_dai *dai, struct snd_pcm *pcm)
+{
+ int ret = 0;
+
+ if (!card->dev->dma_mask)
+ card->dev->dma_mask = &atmel_pcm_dmamask;
+ if (!card->dev->coherent_dma_mask)
+ card->dev->coherent_dma_mask = 0xffffffff;
+
+ if (dai->playback.channels_min) {
+ ret = atmel_pcm_preallocate_dma_buffer(pcm,
+ SNDRV_PCM_STREAM_PLAYBACK);
+ if (ret)
+ goto out;
+ }
+
+ if (dai->capture.channels_min) {
+ pr_debug("at32-pcm:"
+ "Allocating PCM capture DMA buffer\n");
+ ret = atmel_pcm_preallocate_dma_buffer(pcm,
+ SNDRV_PCM_STREAM_CAPTURE);
+ if (ret)
+ goto out;
+ }
+ out:
+ return ret;
+}
+
+static void atmel_pcm_free_dma_buffers(struct snd_pcm *pcm)
+{
+ struct snd_pcm_substream *substream;
+ struct snd_dma_buffer *buf;
+ int stream;
+
+ for (stream = 0; stream < 2; stream++) {
+ substream = pcm->streams[stream].substream;
+ if (!substream)
+ continue;
+
+ buf = &substream->dma_buffer;
+ if (!buf->area)
+ continue;
+ dma_free_coherent(pcm->card->dev, buf->bytes,
+ buf->area, buf->addr);
+ buf->area = NULL;
+ }
+}
+
+#ifdef CONFIG_PM
+static int atmel_pcm_suspend(struct snd_soc_dai *dai)
+{
+ struct snd_pcm_runtime *runtime = dai->runtime;
+ struct atmel_runtime_data *prtd;
+ struct atmel_pcm_dma_params *params;
+
+ if (!runtime)
+ return 0;
+
+ prtd = runtime->private_data;
+ params = prtd->params;
+
+ /* disable the PDC and save the PDC registers */
+
+ ssc_writel(params->ssc->regs, PDC_PTCR, params->mask->pdc_disable);
+
+ prtd->pdc_xpr_save = ssc_readx(params->ssc->regs, params->pdc->xpr);
+ prtd->pdc_xcr_save = ssc_readx(params->ssc->regs, params->pdc->xcr);
+ prtd->pdc_xnpr_save = ssc_readx(params->ssc->regs, params->pdc->xnpr);
+ prtd->pdc_xncr_save = ssc_readx(params->ssc->regs, params->pdc->xncr);
+
+ return 0;
+}
+
+static int atmel_pcm_resume(struct snd_soc_dai *dai)
+{
+ struct snd_pcm_runtime *runtime = dai->runtime;
+ struct atmel_runtime_data *prtd;
+ struct atmel_pcm_dma_params *params;
+
+ if (!runtime)
+ return 0;
+
+ prtd = runtime->private_data;
+ params = prtd->params;
+
+ /* restore the PDC registers and enable the PDC */
+ ssc_writex(params->ssc->regs, params->pdc->xpr, prtd->pdc_xpr_save);
+ ssc_writex(params->ssc->regs, params->pdc->xcr, prtd->pdc_xcr_save);
+ ssc_writex(params->ssc->regs, params->pdc->xnpr, prtd->pdc_xnpr_save);
+ ssc_writex(params->ssc->regs, params->pdc->xncr, prtd->pdc_xncr_save);
+
+ ssc_writel(params->ssc->regs, PDC_PTCR, params->mask->pdc_enable);
+ return 0;
+}
+#else
+#define atmel_pcm_suspend NULL
+#define atmel_pcm_resume NULL
+#endif
+
+struct snd_soc_platform atmel_soc_platform = {
+ .name = "atmel-audio",
+ .pcm_ops = &atmel_pcm_ops,
+ .pcm_new = atmel_pcm_new,
+ .pcm_free = atmel_pcm_free_dma_buffers,
+ .suspend = atmel_pcm_suspend,
+ .resume = atmel_pcm_resume,
+};
+EXPORT_SYMBOL_GPL(atmel_soc_platform);
+
+static int __init atmel_pcm_modinit(void)
+{
+ return snd_soc_register_platform(&atmel_soc_platform);
+}
+module_init(atmel_pcm_modinit);
+
+static void __exit atmel_pcm_modexit(void)
+{
+ snd_soc_unregister_platform(&atmel_soc_platform);
+}
+module_exit(atmel_pcm_modexit);
+
+MODULE_AUTHOR("Sedji Gaouaou <sedji.gaouaou@atmel.com>");
+MODULE_DESCRIPTION("Atmel PCM module");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/atmel/atmel-pcm.h b/sound/soc/atmel/atmel-pcm.h
new file mode 100644
index 00000000000..ec9b2824b66
--- /dev/null
+++ b/sound/soc/atmel/atmel-pcm.h
@@ -0,0 +1,86 @@
+/*
+ * at91-pcm.h - ALSA PCM interface for the Atmel AT91 SoC.
+ *
+ * Copyright (C) 2005 SAN People
+ * Copyright (C) 2008 Atmel
+ *
+ * Authors: Sedji Gaouaou <sedji.gaouaou@atmel.com>
+ *
+ * Based on at91-pcm. by:
+ * Frank Mandarino <fmandarino@endrelia.com>
+ * Copyright 2006 Endrelia Technologies Inc.
+ *
+ * Based on pxa2xx-pcm.c by:
+ *
+ * Author: Nicolas Pitre
+ * Created: Nov 30, 2004
+ * Copyright: (C) 2004 MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _ATMEL_PCM_H
+#define _ATMEL_PCM_H
+
+#include <linux/atmel-ssc.h>
+
+/*
+ * Registers and status bits that are required by the PCM driver.
+ */
+struct atmel_pdc_regs {
+ unsigned int xpr; /* PDC recv/trans pointer */
+ unsigned int xcr; /* PDC recv/trans counter */
+ unsigned int xnpr; /* PDC next recv/trans pointer */
+ unsigned int xncr; /* PDC next recv/trans counter */
+ unsigned int ptcr; /* PDC transfer control */
+};
+
+struct atmel_ssc_mask {
+ u32 ssc_enable; /* SSC recv/trans enable */
+ u32 ssc_disable; /* SSC recv/trans disable */
+ u32 ssc_endx; /* SSC ENDTX or ENDRX */
+ u32 ssc_endbuf; /* SSC TXBUFE or RXBUFF */
+ u32 pdc_enable; /* PDC recv/trans enable */
+ u32 pdc_disable; /* PDC recv/trans disable */
+};
+
+/*
+ * This structure, shared between the PCM driver and the interface,
+ * contains all information required by the PCM driver to perform the
+ * PDC DMA operation. All fields except dma_intr_handler() are initialized
+ * by the interface. The dms_intr_handler() pointer is set by the PCM
+ * driver and called by the interface SSC interrupt handler if it is
+ * non-NULL.
+ */
+struct atmel_pcm_dma_params {
+ char *name; /* stream identifier */
+ int pdc_xfer_size; /* PDC counter increment in bytes */
+ struct ssc_device *ssc; /* SSC device for stream */
+ struct atmel_pdc_regs *pdc; /* PDC receive or transmit registers */
+ struct atmel_ssc_mask *mask; /* SSC & PDC status bits */
+ struct snd_pcm_substream *substream;
+ void (*dma_intr_handler)(u32, struct snd_pcm_substream *);
+};
+
+extern struct snd_soc_platform atmel_soc_platform;
+
+
+/*
+ * SSC register access (since ssc_writel() / ssc_readl() require literal name)
+ */
+#define ssc_readx(base, reg) (__raw_readl((base) + (reg)))
+#define ssc_writex(base, reg, value) __raw_writel((value), (base) + (reg))
+
+#endif /* _ATMEL_PCM_H */
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c
new file mode 100644
index 00000000000..c5d67900d66
--- /dev/null
+++ b/sound/soc/atmel/atmel_ssc_dai.c
@@ -0,0 +1,790 @@
+/*
+ * atmel_ssc_dai.c -- ALSA SoC ATMEL SSC Audio Layer Platform driver
+ *
+ * Copyright (C) 2005 SAN People
+ * Copyright (C) 2008 Atmel
+ *
+ * Author: Sedji Gaouaou <sedji.gaouaou@atmel.com>
+ * ATMEL CORP.
+ *
+ * Based on at91-ssc.c by
+ * Frank Mandarino <fmandarino@endrelia.com>
+ * Based on pxa2xx Platform drivers by
+ * Liam Girdwood <liam.girdwood@wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/atmel_pdc.h>
+
+#include <linux/atmel-ssc.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+
+#include <mach/hardware.h>
+
+#include "atmel-pcm.h"
+#include "atmel_ssc_dai.h"
+
+
+#if defined(CONFIG_ARCH_AT91SAM9260) || defined(CONFIG_ARCH_AT91SAM9G20)
+#define NUM_SSC_DEVICES 1
+#else
+#define NUM_SSC_DEVICES 3
+#endif
+
+/*
+ * SSC PDC registers required by the PCM DMA engine.
+ */
+static struct atmel_pdc_regs pdc_tx_reg = {
+ .xpr = ATMEL_PDC_TPR,
+ .xcr = ATMEL_PDC_TCR,
+ .xnpr = ATMEL_PDC_TNPR,
+ .xncr = ATMEL_PDC_TNCR,
+};
+
+static struct atmel_pdc_regs pdc_rx_reg = {
+ .xpr = ATMEL_PDC_RPR,
+ .xcr = ATMEL_PDC_RCR,
+ .xnpr = ATMEL_PDC_RNPR,
+ .xncr = ATMEL_PDC_RNCR,
+};
+
+/*
+ * SSC & PDC status bits for transmit and receive.
+ */
+static struct atmel_ssc_mask ssc_tx_mask = {
+ .ssc_enable = SSC_BIT(CR_TXEN),
+ .ssc_disable = SSC_BIT(CR_TXDIS),
+ .ssc_endx = SSC_BIT(SR_ENDTX),
+ .ssc_endbuf = SSC_BIT(SR_TXBUFE),
+ .pdc_enable = ATMEL_PDC_TXTEN,
+ .pdc_disable = ATMEL_PDC_TXTDIS,
+};
+
+static struct atmel_ssc_mask ssc_rx_mask = {
+ .ssc_enable = SSC_BIT(CR_RXEN),
+ .ssc_disable = SSC_BIT(CR_RXDIS),
+ .ssc_endx = SSC_BIT(SR_ENDRX),
+ .ssc_endbuf = SSC_BIT(SR_RXBUFF),
+ .pdc_enable = ATMEL_PDC_RXTEN,
+ .pdc_disable = ATMEL_PDC_RXTDIS,
+};
+
+
+/*
+ * DMA parameters.
+ */
+static struct atmel_pcm_dma_params ssc_dma_params[NUM_SSC_DEVICES][2] = {
+ {{
+ .name = "SSC0 PCM out",
+ .pdc = &pdc_tx_reg,
+ .mask = &ssc_tx_mask,
+ },
+ {
+ .name = "SSC0 PCM in",
+ .pdc = &pdc_rx_reg,
+ .mask = &ssc_rx_mask,
+ } },
+#if NUM_SSC_DEVICES == 3
+ {{
+ .name = "SSC1 PCM out",
+ .pdc = &pdc_tx_reg,
+ .mask = &ssc_tx_mask,
+ },
+ {
+ .name = "SSC1 PCM in",
+ .pdc = &pdc_rx_reg,
+ .mask = &ssc_rx_mask,
+ } },
+ {{
+ .name = "SSC2 PCM out",
+ .pdc = &pdc_tx_reg,
+ .mask = &ssc_tx_mask,
+ },
+ {
+ .name = "SSC2 PCM in",
+ .pdc = &pdc_rx_reg,
+ .mask = &ssc_rx_mask,
+ } },
+#endif
+};
+
+
+static struct atmel_ssc_info ssc_info[NUM_SSC_DEVICES] = {
+ {
+ .name = "ssc0",
+ .lock = __SPIN_LOCK_UNLOCKED(ssc_info[0].lock),
+ .dir_mask = SSC_DIR_MASK_UNUSED,
+ .initialized = 0,
+ },
+#if NUM_SSC_DEVICES == 3
+ {
+ .name = "ssc1",
+ .lock = __SPIN_LOCK_UNLOCKED(ssc_info[1].lock),
+ .dir_mask = SSC_DIR_MASK_UNUSED,
+ .initialized = 0,
+ },
+ {
+ .name = "ssc2",
+ .lock = __SPIN_LOCK_UNLOCKED(ssc_info[2].lock),
+ .dir_mask = SSC_DIR_MASK_UNUSED,
+ .initialized = 0,
+ },
+#endif
+};
+
+
+/*
+ * SSC interrupt handler. Passes PDC interrupts to the DMA
+ * interrupt handler in the PCM driver.
+ */
+static irqreturn_t atmel_ssc_interrupt(int irq, void *dev_id)
+{
+ struct atmel_ssc_info *ssc_p = dev_id;
+ struct atmel_pcm_dma_params *dma_params;
+ u32 ssc_sr;
+ u32 ssc_substream_mask;
+ int i;
+
+ ssc_sr = (unsigned long)ssc_readl(ssc_p->ssc->regs, SR)
+ & (unsigned long)ssc_readl(ssc_p->ssc->regs, IMR);
+
+ /*
+ * Loop through the substreams attached to this SSC. If
+ * a DMA-related interrupt occurred on that substream, call
+ * the DMA interrupt handler function, if one has been
+ * registered in the dma_params structure by the PCM driver.
+ */
+ for (i = 0; i < ARRAY_SIZE(ssc_p->dma_params); i++) {
+ dma_params = ssc_p->dma_params[i];
+
+ if ((dma_params != NULL) &&
+ (dma_params->dma_intr_handler != NULL)) {
+ ssc_substream_mask = (dma_params->mask->ssc_endx |
+ dma_params->mask->ssc_endbuf);
+ if (ssc_sr & ssc_substream_mask) {
+ dma_params->dma_intr_handler(ssc_sr,
+ dma_params->
+ substream);
+ }
+ }
+ }
+
+ return IRQ_HANDLED;
+}
+
+
+/*-------------------------------------------------------------------------*\
+ * DAI functions
+\*-------------------------------------------------------------------------*/
+/*
+ * Startup. Only that one substream allowed in each direction.
+ */
+static int atmel_ssc_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
+ struct atmel_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
+ int dir_mask;
+
+ pr_debug("atmel_ssc_startup: SSC_SR=0x%u\n",
+ ssc_readl(ssc_p->ssc->regs, SR));
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ dir_mask = SSC_DIR_MASK_PLAYBACK;
+ else
+ dir_mask = SSC_DIR_MASK_CAPTURE;
+
+ spin_lock_irq(&ssc_p->lock);
+ if (ssc_p->dir_mask & dir_mask) {
+ spin_unlock_irq(&ssc_p->lock);
+ return -EBUSY;
+ }
+ ssc_p->dir_mask |= dir_mask;
+ spin_unlock_irq(&ssc_p->lock);
+
+ return 0;
+}
+
+/*
+ * Shutdown. Clear DMA parameters and shutdown the SSC if there
+ * are no other substreams open.
+ */
+static void atmel_ssc_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
+ struct atmel_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
+ struct atmel_pcm_dma_params *dma_params;
+ int dir, dir_mask;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ dir = 0;
+ else
+ dir = 1;
+
+ dma_params = ssc_p->dma_params[dir];
+
+ if (dma_params != NULL) {
+ ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_disable);
+ pr_debug("atmel_ssc_shutdown: %s disabled SSC_SR=0x%08x\n",
+ (dir ? "receive" : "transmit"),
+ ssc_readl(ssc_p->ssc->regs, SR));
+
+ dma_params->ssc = NULL;
+ dma_params->substream = NULL;
+ ssc_p->dma_params[dir] = NULL;
+ }
+
+ dir_mask = 1 << dir;
+
+ spin_lock_irq(&ssc_p->lock);
+ ssc_p->dir_mask &= ~dir_mask;
+ if (!ssc_p->dir_mask) {
+ if (ssc_p->initialized) {
+ /* Shutdown the SSC clock. */
+ pr_debug("atmel_ssc_dau: Stopping clock\n");
+ clk_disable(ssc_p->ssc->clk);
+
+ free_irq(ssc_p->ssc->irq, ssc_p);
+ ssc_p->initialized = 0;
+ }
+
+ /* Reset the SSC */
+ ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST));
+ /* Clear the SSC dividers */
+ ssc_p->cmr_div = ssc_p->tcmr_period = ssc_p->rcmr_period = 0;
+ }
+ spin_unlock_irq(&ssc_p->lock);
+}
+
+
+/*
+ * Record the DAI format for use in hw_params().
+ */
+static int atmel_ssc_set_dai_fmt(struct snd_soc_dai *cpu_dai,
+ unsigned int fmt)
+{
+ struct atmel_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
+
+ ssc_p->daifmt = fmt;
+ return 0;
+}
+
+/*
+ * Record SSC clock dividers for use in hw_params().
+ */
+static int atmel_ssc_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
+ int div_id, int div)
+{
+ struct atmel_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
+
+ switch (div_id) {
+ case ATMEL_SSC_CMR_DIV:
+ /*
+ * The same master clock divider is used for both
+ * transmit and receive, so if a value has already
+ * been set, it must match this value.
+ */
+ if (ssc_p->cmr_div == 0)
+ ssc_p->cmr_div = div;
+ else
+ if (div != ssc_p->cmr_div)
+ return -EBUSY;
+ break;
+
+ case ATMEL_SSC_TCMR_PERIOD:
+ ssc_p->tcmr_period = div;
+ break;
+
+ case ATMEL_SSC_RCMR_PERIOD:
+ ssc_p->rcmr_period = div;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/*
+ * Configure the SSC.
+ */
+static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
+ int id = rtd->dai->cpu_dai->id;
+ struct atmel_ssc_info *ssc_p = &ssc_info[id];
+ struct atmel_pcm_dma_params *dma_params;
+ int dir, channels, bits;
+ u32 tfmr, rfmr, tcmr, rcmr;
+ int start_event;
+ int ret;
+
+ /*
+ * Currently, there is only one set of dma params for
+ * each direction. If more are added, this code will
+ * have to be changed to select the proper set.
+ */
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ dir = 0;
+ else
+ dir = 1;
+
+ dma_params = &ssc_dma_params[id][dir];
+ dma_params->ssc = ssc_p->ssc;
+ dma_params->substream = substream;
+
+ ssc_p->dma_params[dir] = dma_params;
+
+ /*
+ * The cpu_dai->dma_data field is only used to communicate the
+ * appropriate DMA parameters to the pcm driver hw_params()
+ * function. It should not be used for other purposes
+ * as it is common to all substreams.
+ */
+ rtd->dai->cpu_dai->dma_data = dma_params;
+
+ channels = params_channels(params);
+
+ /*
+ * Determine sample size in bits and the PDC increment.
+ */
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S8:
+ bits = 8;
+ dma_params->pdc_xfer_size = 1;
+ break;
+ case SNDRV_PCM_FORMAT_S16_LE:
+ bits = 16;
+ dma_params->pdc_xfer_size = 2;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ bits = 24;
+ dma_params->pdc_xfer_size = 4;
+ break;
+ case SNDRV_PCM_FORMAT_S32_LE:
+ bits = 32;
+ dma_params->pdc_xfer_size = 4;
+ break;
+ default:
+ printk(KERN_WARNING "atmel_ssc_dai: unsupported PCM format");
+ return -EINVAL;
+ }
+
+ /*
+ * The SSC only supports up to 16-bit samples in I2S format, due
+ * to the size of the Frame Mode Register FSLEN field.
+ */
+ if ((ssc_p->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S
+ && bits > 16) {
+ printk(KERN_WARNING
+ "atmel_ssc_dai: sample size %d"
+ "is too large for I2S\n", bits);
+ return -EINVAL;
+ }
+
+ /*
+ * Compute SSC register settings.
+ */
+ switch (ssc_p->daifmt
+ & (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_MASTER_MASK)) {
+
+ case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS:
+ /*
+ * I2S format, SSC provides BCLK and LRC clocks.
+ *
+ * The SSC transmit and receive clocks are generated
+ * from the MCK divider, and the BCLK signal
+ * is output on the SSC TK line.
+ */
+ rcmr = SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period)
+ | SSC_BF(RCMR_STTDLY, START_DELAY)
+ | SSC_BF(RCMR_START, SSC_START_FALLING_RF)
+ | SSC_BF(RCMR_CKI, SSC_CKI_RISING)
+ | SSC_BF(RCMR_CKO, SSC_CKO_NONE)
+ | SSC_BF(RCMR_CKS, SSC_CKS_DIV);
+
+ rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
+ | SSC_BF(RFMR_FSOS, SSC_FSOS_NEGATIVE)
+ | SSC_BF(RFMR_FSLEN, (bits - 1))
+ | SSC_BF(RFMR_DATNB, (channels - 1))
+ | SSC_BIT(RFMR_MSBF)
+ | SSC_BF(RFMR_LOOP, 0)
+ | SSC_BF(RFMR_DATLEN, (bits - 1));
+
+ tcmr = SSC_BF(TCMR_PERIOD, ssc_p->tcmr_period)
+ | SSC_BF(TCMR_STTDLY, START_DELAY)
+ | SSC_BF(TCMR_START, SSC_START_FALLING_RF)
+ | SSC_BF(TCMR_CKI, SSC_CKI_FALLING)
+ | SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS)
+ | SSC_BF(TCMR_CKS, SSC_CKS_DIV);
+
+ tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
+ | SSC_BF(TFMR_FSDEN, 0)
+ | SSC_BF(TFMR_FSOS, SSC_FSOS_NEGATIVE)
+ | SSC_BF(TFMR_FSLEN, (bits - 1))
+ | SSC_BF(TFMR_DATNB, (channels - 1))
+ | SSC_BIT(TFMR_MSBF)
+ | SSC_BF(TFMR_DATDEF, 0)
+ | SSC_BF(TFMR_DATLEN, (bits - 1));
+ break;
+
+ case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM:
+ /*
+ * I2S format, CODEC supplies BCLK and LRC clocks.
+ *
+ * The SSC transmit clock is obtained from the BCLK signal on
+ * on the TK line, and the SSC receive clock is
+ * generated from the transmit clock.
+ *
+ * For single channel data, one sample is transferred
+ * on the falling edge of the LRC clock.
+ * For two channel data, one sample is
+ * transferred on both edges of the LRC clock.
+ */
+ start_event = ((channels == 1)
+ ? SSC_START_FALLING_RF
+ : SSC_START_EDGE_RF);
+
+ rcmr = SSC_BF(RCMR_PERIOD, 0)
+ | SSC_BF(RCMR_STTDLY, START_DELAY)
+ | SSC_BF(RCMR_START, start_event)
+ | SSC_BF(RCMR_CKI, SSC_CKI_RISING)
+ | SSC_BF(RCMR_CKO, SSC_CKO_NONE)
+ | SSC_BF(RCMR_CKS, SSC_CKS_CLOCK);
+
+ rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
+ | SSC_BF(RFMR_FSOS, SSC_FSOS_NONE)
+ | SSC_BF(RFMR_FSLEN, 0)
+ | SSC_BF(RFMR_DATNB, 0)
+ | SSC_BIT(RFMR_MSBF)
+ | SSC_BF(RFMR_LOOP, 0)
+ | SSC_BF(RFMR_DATLEN, (bits - 1));
+
+ tcmr = SSC_BF(TCMR_PERIOD, 0)
+ | SSC_BF(TCMR_STTDLY, START_DELAY)
+ | SSC_BF(TCMR_START, start_event)
+ | SSC_BF(TCMR_CKI, SSC_CKI_FALLING)
+ | SSC_BF(TCMR_CKO, SSC_CKO_NONE)
+ | SSC_BF(TCMR_CKS, SSC_CKS_PIN);
+
+ tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
+ | SSC_BF(TFMR_FSDEN, 0)
+ | SSC_BF(TFMR_FSOS, SSC_FSOS_NONE)
+ | SSC_BF(TFMR_FSLEN, 0)
+ | SSC_BF(TFMR_DATNB, 0)
+ | SSC_BIT(TFMR_MSBF)
+ | SSC_BF(TFMR_DATDEF, 0)
+ | SSC_BF(TFMR_DATLEN, (bits - 1));
+ break;
+
+ case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS:
+ /*
+ * DSP/PCM Mode A format, SSC provides BCLK and LRC clocks.
+ *
+ * The SSC transmit and receive clocks are generated from the
+ * MCK divider, and the BCLK signal is output
+ * on the SSC TK line.
+ */
+ rcmr = SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period)
+ | SSC_BF(RCMR_STTDLY, 1)
+ | SSC_BF(RCMR_START, SSC_START_RISING_RF)
+ | SSC_BF(RCMR_CKI, SSC_CKI_RISING)
+ | SSC_BF(RCMR_CKO, SSC_CKO_NONE)
+ | SSC_BF(RCMR_CKS, SSC_CKS_DIV);
+
+ rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
+ | SSC_BF(RFMR_FSOS, SSC_FSOS_POSITIVE)
+ | SSC_BF(RFMR_FSLEN, 0)
+ | SSC_BF(RFMR_DATNB, (channels - 1))
+ | SSC_BIT(RFMR_MSBF)
+ | SSC_BF(RFMR_LOOP, 0)
+ | SSC_BF(RFMR_DATLEN, (bits - 1));
+
+ tcmr = SSC_BF(TCMR_PERIOD, ssc_p->tcmr_period)
+ | SSC_BF(TCMR_STTDLY, 1)
+ | SSC_BF(TCMR_START, SSC_START_RISING_RF)
+ | SSC_BF(TCMR_CKI, SSC_CKI_RISING)
+ | SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS)
+ | SSC_BF(TCMR_CKS, SSC_CKS_DIV);
+
+ tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
+ | SSC_BF(TFMR_FSDEN, 0)
+ | SSC_BF(TFMR_FSOS, SSC_FSOS_POSITIVE)
+ | SSC_BF(TFMR_FSLEN, 0)
+ | SSC_BF(TFMR_DATNB, (channels - 1))
+ | SSC_BIT(TFMR_MSBF)
+ | SSC_BF(TFMR_DATDEF, 0)
+ | SSC_BF(TFMR_DATLEN, (bits - 1));
+ break;
+
+ case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM:
+ default:
+ printk(KERN_WARNING "atmel_ssc_dai: unsupported DAI format 0x%x\n",
+ ssc_p->daifmt);
+ return -EINVAL;
+ break;
+ }
+ pr_debug("atmel_ssc_hw_params: "
+ "RCMR=%08x RFMR=%08x TCMR=%08x TFMR=%08x\n",
+ rcmr, rfmr, tcmr, tfmr);
+
+ if (!ssc_p->initialized) {
+
+ /* Enable PMC peripheral clock for this SSC */
+ pr_debug("atmel_ssc_dai: Starting clock\n");
+ clk_enable(ssc_p->ssc->clk);
+
+ /* Reset the SSC and its PDC registers */
+ ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST));
+
+ ssc_writel(ssc_p->ssc->regs, PDC_RPR, 0);
+ ssc_writel(ssc_p->ssc->regs, PDC_RCR, 0);
+ ssc_writel(ssc_p->ssc->regs, PDC_RNPR, 0);
+ ssc_writel(ssc_p->ssc->regs, PDC_RNCR, 0);
+
+ ssc_writel(ssc_p->ssc->regs, PDC_TPR, 0);
+ ssc_writel(ssc_p->ssc->regs, PDC_TCR, 0);
+ ssc_writel(ssc_p->ssc->regs, PDC_TNPR, 0);
+ ssc_writel(ssc_p->ssc->regs, PDC_TNCR, 0);
+
+ ret = request_irq(ssc_p->ssc->irq, atmel_ssc_interrupt, 0,
+ ssc_p->name, ssc_p);
+ if (ret < 0) {
+ printk(KERN_WARNING
+ "atmel_ssc_dai: request_irq failure\n");
+ pr_debug("Atmel_ssc_dai: Stoping clock\n");
+ clk_disable(ssc_p->ssc->clk);
+ return ret;
+ }
+
+ ssc_p->initialized = 1;
+ }
+
+ /* set SSC clock mode register */
+ ssc_writel(ssc_p->ssc->regs, CMR, ssc_p->cmr_div);
+
+ /* set receive clock mode and format */
+ ssc_writel(ssc_p->ssc->regs, RCMR, rcmr);
+ ssc_writel(ssc_p->ssc->regs, RFMR, rfmr);
+
+ /* set transmit clock mode and format */
+ ssc_writel(ssc_p->ssc->regs, TCMR, tcmr);
+ ssc_writel(ssc_p->ssc->regs, TFMR, tfmr);
+
+ pr_debug("atmel_ssc_dai,hw_params: SSC initialized\n");
+ return 0;
+}
+
+
+static int atmel_ssc_prepare(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
+ struct atmel_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
+ struct atmel_pcm_dma_params *dma_params;
+ int dir;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ dir = 0;
+ else
+ dir = 1;
+
+ dma_params = ssc_p->dma_params[dir];
+
+ ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_enable);
+
+ pr_debug("%s enabled SSC_SR=0x%08x\n",
+ dir ? "receive" : "transmit",
+ ssc_readl(ssc_p->ssc->regs, SR));
+ return 0;
+}
+
+
+#ifdef CONFIG_PM
+static int atmel_ssc_suspend(struct snd_soc_dai *cpu_dai)
+{
+ struct atmel_ssc_info *ssc_p;
+
+ if (!cpu_dai->active)
+ return 0;
+
+ ssc_p = &ssc_info[cpu_dai->id];
+
+ /* Save the status register before disabling transmit and receive */
+ ssc_p->ssc_state.ssc_sr = ssc_readl(ssc_p->ssc->regs, SR);
+ ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_TXDIS) | SSC_BIT(CR_RXDIS));
+
+ /* Save the current interrupt mask, then disable unmasked interrupts */
+ ssc_p->ssc_state.ssc_imr = ssc_readl(ssc_p->ssc->regs, IMR);
+ ssc_writel(ssc_p->ssc->regs, IDR, ssc_p->ssc_state.ssc_imr);
+
+ ssc_p->ssc_state.ssc_cmr = ssc_readl(ssc_p->ssc->regs, CMR);
+ ssc_p->ssc_state.ssc_rcmr = ssc_readl(ssc_p->ssc->regs, RCMR);
+ ssc_p->ssc_state.ssc_rfmr = ssc_readl(ssc_p->ssc->regs, RFMR);
+ ssc_p->ssc_state.ssc_tcmr = ssc_readl(ssc_p->ssc->regs, TCMR);
+ ssc_p->ssc_state.ssc_tfmr = ssc_readl(ssc_p->ssc->regs, TFMR);
+
+ return 0;
+}
+
+
+
+static int atmel_ssc_resume(struct snd_soc_dai *cpu_dai)
+{
+ struct atmel_ssc_info *ssc_p;
+ u32 cr;
+
+ if (!cpu_dai->active)
+ return 0;
+
+ ssc_p = &ssc_info[cpu_dai->id];
+
+ /* restore SSC register settings */
+ ssc_writel(ssc_p->ssc->regs, TFMR, ssc_p->ssc_state.ssc_tfmr);
+ ssc_writel(ssc_p->ssc->regs, TCMR, ssc_p->ssc_state.ssc_tcmr);
+ ssc_writel(ssc_p->ssc->regs, RFMR, ssc_p->ssc_state.ssc_rfmr);
+ ssc_writel(ssc_p->ssc->regs, RCMR, ssc_p->ssc_state.ssc_rcmr);
+ ssc_writel(ssc_p->ssc->regs, CMR, ssc_p->ssc_state.ssc_cmr);
+
+ /* re-enable interrupts */
+ ssc_writel(ssc_p->ssc->regs, IER, ssc_p->ssc_state.ssc_imr);
+
+ /* Re-enable recieve and transmit as appropriate */
+ cr = 0;
+ cr |=
+ (ssc_p->ssc_state.ssc_sr & SSC_BIT(SR_RXEN)) ? SSC_BIT(CR_RXEN) : 0;
+ cr |=
+ (ssc_p->ssc_state.ssc_sr & SSC_BIT(SR_TXEN)) ? SSC_BIT(CR_TXEN) : 0;
+ ssc_writel(ssc_p->ssc->regs, CR, cr);
+
+ return 0;
+}
+#else /* CONFIG_PM */
+# define atmel_ssc_suspend NULL
+# define atmel_ssc_resume NULL
+#endif /* CONFIG_PM */
+
+
+#define ATMEL_SSC_RATES (SNDRV_PCM_RATE_8000_96000)
+
+#define ATMEL_SSC_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+struct snd_soc_dai atmel_ssc_dai[NUM_SSC_DEVICES] = {
+ { .name = "atmel-ssc0",
+ .id = 0,
+ .suspend = atmel_ssc_suspend,
+ .resume = atmel_ssc_resume,
+ .playback = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = ATMEL_SSC_RATES,
+ .formats = ATMEL_SSC_FORMATS,},
+ .capture = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = ATMEL_SSC_RATES,
+ .formats = ATMEL_SSC_FORMATS,},
+ .ops = {
+ .startup = atmel_ssc_startup,
+ .shutdown = atmel_ssc_shutdown,
+ .prepare = atmel_ssc_prepare,
+ .hw_params = atmel_ssc_hw_params,
+ .set_fmt = atmel_ssc_set_dai_fmt,
+ .set_clkdiv = atmel_ssc_set_dai_clkdiv,},
+ .private_data = &ssc_info[0],
+ },
+#if NUM_SSC_DEVICES == 3
+ { .name = "atmel-ssc1",
+ .id = 1,
+ .suspend = atmel_ssc_suspend,
+ .resume = atmel_ssc_resume,
+ .playback = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = ATMEL_SSC_RATES,
+ .formats = ATMEL_SSC_FORMATS,},
+ .capture = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = ATMEL_SSC_RATES,
+ .formats = ATMEL_SSC_FORMATS,},
+ .ops = {
+ .startup = atmel_ssc_startup,
+ .shutdown = atmel_ssc_shutdown,
+ .prepare = atmel_ssc_prepare,
+ .hw_params = atmel_ssc_hw_params,
+ .set_fmt = atmel_ssc_set_dai_fmt,
+ .set_clkdiv = atmel_ssc_set_dai_clkdiv,},
+ .private_data = &ssc_info[1],
+ },
+ { .name = "atmel-ssc2",
+ .id = 2,
+ .suspend = atmel_ssc_suspend,
+ .resume = atmel_ssc_resume,
+ .playback = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = ATMEL_SSC_RATES,
+ .formats = ATMEL_SSC_FORMATS,},
+ .capture = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = ATMEL_SSC_RATES,
+ .formats = ATMEL_SSC_FORMATS,},
+ .ops = {
+ .startup = atmel_ssc_startup,
+ .shutdown = atmel_ssc_shutdown,
+ .prepare = atmel_ssc_prepare,
+ .hw_params = atmel_ssc_hw_params,
+ .set_fmt = atmel_ssc_set_dai_fmt,
+ .set_clkdiv = atmel_ssc_set_dai_clkdiv,},
+ .private_data = &ssc_info[2],
+ },
+#endif
+};
+EXPORT_SYMBOL_GPL(atmel_ssc_dai);
+
+static int __init atmel_ssc_modinit(void)
+{
+ return snd_soc_register_dais(atmel_ssc_dai, ARRAY_SIZE(atmel_ssc_dai));
+}
+module_init(atmel_ssc_modinit);
+
+static void __exit atmel_ssc_modexit(void)
+{
+ snd_soc_unregister_dais(atmel_ssc_dai, ARRAY_SIZE(atmel_ssc_dai));
+}
+module_exit(atmel_ssc_modexit);
+
+/* Module information */
+MODULE_AUTHOR("Sedji Gaouaou, sedji.gaouaou@atmel.com, www.atmel.com");
+MODULE_DESCRIPTION("ATMEL SSC ASoC Interface");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/atmel/atmel_ssc_dai.h b/sound/soc/atmel/atmel_ssc_dai.h
new file mode 100644
index 00000000000..a828746e8a2
--- /dev/null
+++ b/sound/soc/atmel/atmel_ssc_dai.h
@@ -0,0 +1,121 @@
+/*
+ * atmel_ssc_dai.h - ALSA SSC interface for the Atmel SoC
+ *
+ * Copyright (C) 2005 SAN People
+ * Copyright (C) 2008 Atmel
+ *
+ * Author: Sedji Gaouaou <sedji.gaouaou@atmel.com>
+ * ATMEL CORP.
+ *
+ * Based on at91-ssc.c by
+ * Frank Mandarino <fmandarino@endrelia.com>
+ * Based on pxa2xx Platform drivers by
+ * Liam Girdwood <liam.girdwood@wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _ATMEL_SSC_DAI_H
+#define _ATMEL_SSC_DAI_H
+
+#include <linux/types.h>
+#include <linux/atmel-ssc.h>
+
+#include "atmel-pcm.h"
+
+/* SSC system clock ids */
+#define ATMEL_SYSCLK_MCK 0 /* SSC uses AT91 MCK as system clock */
+
+/* SSC divider ids */
+#define ATMEL_SSC_CMR_DIV 0 /* MCK divider for BCLK */
+#define ATMEL_SSC_TCMR_PERIOD 1 /* BCLK divider for transmit FS */
+#define ATMEL_SSC_RCMR_PERIOD 2 /* BCLK divider for receive FS */
+/*
+ * SSC direction masks
+ */
+#define SSC_DIR_MASK_UNUSED 0
+#define SSC_DIR_MASK_PLAYBACK 1
+#define SSC_DIR_MASK_CAPTURE 2
+
+/*
+ * SSC register values that Atmel left out of <linux/atmel-ssc.h>. These
+ * are expected to be used with SSC_BF
+ */
+/* START bit field values */
+#define SSC_START_CONTINUOUS 0
+#define SSC_START_TX_RX 1
+#define SSC_START_LOW_RF 2
+#define SSC_START_HIGH_RF 3
+#define SSC_START_FALLING_RF 4
+#define SSC_START_RISING_RF 5
+#define SSC_START_LEVEL_RF 6
+#define SSC_START_EDGE_RF 7
+#define SSS_START_COMPARE_0 8
+
+/* CKI bit field values */
+#define SSC_CKI_FALLING 0
+#define SSC_CKI_RISING 1
+
+/* CKO bit field values */
+#define SSC_CKO_NONE 0
+#define SSC_CKO_CONTINUOUS 1
+#define SSC_CKO_TRANSFER 2
+
+/* CKS bit field values */
+#define SSC_CKS_DIV 0
+#define SSC_CKS_CLOCK 1
+#define SSC_CKS_PIN 2
+
+/* FSEDGE bit field values */
+#define SSC_FSEDGE_POSITIVE 0
+#define SSC_FSEDGE_NEGATIVE 1
+
+/* FSOS bit field values */
+#define SSC_FSOS_NONE 0
+#define SSC_FSOS_NEGATIVE 1
+#define SSC_FSOS_POSITIVE 2
+#define SSC_FSOS_LOW 3
+#define SSC_FSOS_HIGH 4
+#define SSC_FSOS_TOGGLE 5
+
+#define START_DELAY 1
+
+struct atmel_ssc_state {
+ u32 ssc_cmr;
+ u32 ssc_rcmr;
+ u32 ssc_rfmr;
+ u32 ssc_tcmr;
+ u32 ssc_tfmr;
+ u32 ssc_sr;
+ u32 ssc_imr;
+};
+
+
+struct atmel_ssc_info {
+ char *name;
+ struct ssc_device *ssc;
+ spinlock_t lock; /* lock for dir_mask */
+ unsigned short dir_mask; /* 0=unused, 1=playback, 2=capture */
+ unsigned short initialized; /* true if SSC has been initialized */
+ unsigned short daifmt;
+ unsigned short cmr_div;
+ unsigned short tcmr_period;
+ unsigned short rcmr_period;
+ struct atmel_pcm_dma_params *dma_params[2];
+ struct atmel_ssc_state ssc_state;
+};
+extern struct snd_soc_dai atmel_ssc_dai[];
+
+#endif /* _AT91_SSC_DAI_H */
diff --git a/sound/soc/at32/playpaq_wm8510.c b/sound/soc/atmel/playpaq_wm8510.c
index b1966e4dfcd..43dd8cee83c 100644
--- a/sound/soc/at32/playpaq_wm8510.c
+++ b/sound/soc/atmel/playpaq_wm8510.c
@@ -22,7 +22,6 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
-#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/clk.h>
@@ -40,8 +39,8 @@
#include <mach/portmux.h>
#include "../codecs/wm8510.h"
-#include "at32-pcm.h"
-#include "at32-ssc.h"
+#include "atmel-pcm.h"
+#include "atmel_ssc_dai.h"
/*-------------------------------------------------------------------------*\
@@ -362,8 +361,9 @@ static struct snd_soc_dai_link playpaq_wm8510_dai = {
-static struct snd_soc_machine snd_soc_machine_playpaq = {
+static struct snd_soc_card snd_soc_playpaq = {
.name = "LRS_PlayPaq_WM8510",
+ .platform = &at32_soc_platform,
.dai_link = &playpaq_wm8510_dai,
.num_links = 1,
};
@@ -378,8 +378,7 @@ static struct wm8510_setup_data playpaq_wm8510_setup = {
static struct snd_soc_device playpaq_wm8510_snd_devdata = {
- .machine = &snd_soc_machine_playpaq,
- .platform = &at32_soc_platform,
+ .card = &snd_soc_playpaq,
.codec_dev = &soc_codec_dev_wm8510,
.codec_data = &playpaq_wm8510_setup,
};
diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c
new file mode 100644
index 00000000000..1fb59a9d371
--- /dev/null
+++ b/sound/soc/atmel/sam9g20_wm8731.c
@@ -0,0 +1,328 @@
+/*
+ * sam9g20_wm8731 -- SoC audio for AT91SAM9G20-based
+ * ATMEL AT91SAM9G20ek board.
+ *
+ * Copyright (C) 2005 SAN People
+ * Copyright (C) 2008 Atmel
+ *
+ * Authors: Sedji Gaouaou <sedji.gaouaou@atmel.com>
+ *
+ * Based on ati_b1_wm8731.c by:
+ * Frank Mandarino <fmandarino@endrelia.com>
+ * Copyright 2006 Endrelia Technologies Inc.
+ * Based on corgi.c by:
+ * Copyright 2005 Wolfson Microelectronics PLC.
+ * Copyright 2005 Openedhand Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+
+#include <linux/atmel-ssc.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <mach/hardware.h>
+#include <mach/gpio.h>
+
+#include "../codecs/wm8731.h"
+#include "atmel-pcm.h"
+#include "atmel_ssc_dai.h"
+
+
+static int at91sam9g20ek_startup(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
+ struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+ int ret;
+
+ /* codec system clock is supplied by PCK0, set to 12MHz */
+ ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK,
+ 12000000, SND_SOC_CLOCK_IN);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static void at91sam9g20ek_shutdown(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
+
+ dev_dbg(rtd->socdev->dev, "shutdown");
+}
+
+static int at91sam9g20ek_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+ struct atmel_ssc_info *ssc_p = cpu_dai->private_data;
+ struct ssc_device *ssc = ssc_p->ssc;
+ int ret;
+
+ unsigned int rate;
+ int cmr_div, period;
+
+ if (ssc == NULL) {
+ printk(KERN_INFO "at91sam9g20ek_hw_params: ssc is NULL!\n");
+ return -EINVAL;
+ }
+
+ /* set codec DAI configuration */
+ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
+ if (ret < 0)
+ return ret;
+
+ /* set cpu DAI configuration */
+ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * The SSC clock dividers depend on the sample rate. The CMR.DIV
+ * field divides the system master clock MCK to drive the SSC TK
+ * signal which provides the codec BCLK. The TCMR.PERIOD and
+ * RCMR.PERIOD fields further divide the BCLK signal to drive
+ * the SSC TF and RF signals which provide the codec DACLRC and
+ * ADCLRC clocks.
+ *
+ * The dividers were determined through trial and error, where a
+ * CMR.DIV value is chosen such that the resulting BCLK value is
+ * divisible, or almost divisible, by (2 * sample rate), and then
+ * the TCMR.PERIOD or RCMR.PERIOD is BCLK / (2 * sample rate) - 1.
+ */
+ rate = params_rate(params);
+
+ switch (rate) {
+ case 8000:
+ cmr_div = 55; /* BCLK = 133MHz/(2*55) = 1.209MHz */
+ period = 74; /* LRC = BCLK/(2*(74+1)) ~= 8060,6Hz */
+ break;
+ case 11025:
+ cmr_div = 67; /* BCLK = 133MHz/(2*60) = 1.108MHz */
+ period = 45; /* LRC = BCLK/(2*(49+1)) = 11083,3Hz */
+ break;
+ case 16000:
+ cmr_div = 63; /* BCLK = 133MHz/(2*63) = 1.055MHz */
+ period = 32; /* LRC = BCLK/(2*(32+1)) = 15993,2Hz */
+ break;
+ case 22050:
+ cmr_div = 52; /* BCLK = 133MHz/(2*52) = 1.278MHz */
+ period = 28; /* LRC = BCLK/(2*(28+1)) = 22049Hz */
+ break;
+ case 32000:
+ cmr_div = 66; /* BCLK = 133MHz/(2*66) = 1.007MHz */
+ period = 15; /* LRC = BCLK/(2*(15+1)) = 31486,742Hz */
+ break;
+ case 44100:
+ cmr_div = 29; /* BCLK = 133MHz/(2*29) = 2.293MHz */
+ period = 25; /* LRC = BCLK/(2*(25+1)) = 44098Hz */
+ break;
+ case 48000:
+ cmr_div = 33; /* BCLK = 133MHz/(2*33) = 2.015MHz */
+ period = 20; /* LRC = BCLK/(2*(20+1)) = 47979,79Hz */
+ break;
+ case 88200:
+ cmr_div = 29; /* BCLK = 133MHz/(2*29) = 2.293MHz */
+ period = 12; /* LRC = BCLK/(2*(12+1)) = 88196Hz */
+ break;
+ case 96000:
+ cmr_div = 23; /* BCLK = 133MHz/(2*23) = 2.891MHz */
+ period = 14; /* LRC = BCLK/(2*(14+1)) = 96376Hz */
+ break;
+ default:
+ printk(KERN_WARNING "unsupported rate %d"
+ " on at91sam9g20ek board\n", rate);
+ return -EINVAL;
+ }
+
+ /* set the MCK divider for BCLK */
+ ret = snd_soc_dai_set_clkdiv(cpu_dai, ATMEL_SSC_CMR_DIV, cmr_div);
+ if (ret < 0)
+ return ret;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ /* set the BCLK divider for DACLRC */
+ ret = snd_soc_dai_set_clkdiv(cpu_dai,
+ ATMEL_SSC_TCMR_PERIOD, period);
+ } else {
+ /* set the BCLK divider for ADCLRC */
+ ret = snd_soc_dai_set_clkdiv(cpu_dai,
+ ATMEL_SSC_RCMR_PERIOD, period);
+ }
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static struct snd_soc_ops at91sam9g20ek_ops = {
+ .startup = at91sam9g20ek_startup,
+ .hw_params = at91sam9g20ek_hw_params,
+ .shutdown = at91sam9g20ek_shutdown,
+};
+
+
+static const struct snd_soc_dapm_widget at91sam9g20ek_dapm_widgets[] = {
+ SND_SOC_DAPM_MIC("Int Mic", NULL),
+ SND_SOC_DAPM_SPK("Ext Spk", NULL),
+};
+
+static const struct snd_soc_dapm_route intercon[] = {
+
+ /* speaker connected to LHPOUT */
+ {"Ext Spk", NULL, "LHPOUT"},
+
+ /* mic is connected to Mic Jack, with WM8731 Mic Bias */
+ {"MICIN", NULL, "Mic Bias"},
+ {"Mic Bias", NULL, "Int Mic"},
+};
+
+/*
+ * Logic for a wm8731 as connected on a at91sam9g20ek board.
+ */
+static int at91sam9g20ek_wm8731_init(struct snd_soc_codec *codec)
+{
+ printk(KERN_DEBUG
+ "at91sam9g20ek_wm8731 "
+ ": at91sam9g20ek_wm8731_init() called\n");
+
+ /* Add specific widgets */
+ snd_soc_dapm_new_controls(codec, at91sam9g20ek_dapm_widgets,
+ ARRAY_SIZE(at91sam9g20ek_dapm_widgets));
+ /* Set up specific audio path interconnects */
+ snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
+
+ /* not connected */
+ snd_soc_dapm_disable_pin(codec, "RLINEIN");
+ snd_soc_dapm_disable_pin(codec, "LLINEIN");
+
+ /* always connected */
+ snd_soc_dapm_enable_pin(codec, "Int Mic");
+ snd_soc_dapm_enable_pin(codec, "Ext Spk");
+
+ snd_soc_dapm_sync(codec);
+
+ return 0;
+}
+
+static struct snd_soc_dai_link at91sam9g20ek_dai = {
+ .name = "WM8731",
+ .stream_name = "WM8731 PCM",
+ .cpu_dai = &atmel_ssc_dai[0],
+ .codec_dai = &wm8731_dai,
+ .init = at91sam9g20ek_wm8731_init,
+ .ops = &at91sam9g20ek_ops,
+};
+
+static struct snd_soc_card snd_soc_at91sam9g20ek = {
+ .name = "WM8731",
+ .platform = &atmel_soc_platform,
+ .dai_link = &at91sam9g20ek_dai,
+ .num_links = 1,
+};
+
+static struct wm8731_setup_data at91sam9g20ek_wm8731_setup = {
+ .i2c_bus = 0,
+ .i2c_address = 0x1b,
+};
+
+static struct snd_soc_device at91sam9g20ek_snd_devdata = {
+ .card = &snd_soc_at91sam9g20ek,
+ .codec_dev = &soc_codec_dev_wm8731,
+ .codec_data = &at91sam9g20ek_wm8731_setup,
+};
+
+static struct platform_device *at91sam9g20ek_snd_device;
+
+static int __init at91sam9g20ek_init(void)
+{
+ struct atmel_ssc_info *ssc_p = at91sam9g20ek_dai.cpu_dai->private_data;
+ struct ssc_device *ssc = NULL;
+ int ret;
+
+ /*
+ * Request SSC device
+ */
+ ssc = ssc_request(0);
+ if (IS_ERR(ssc)) {
+ ret = PTR_ERR(ssc);
+ ssc = NULL;
+ goto err_ssc;
+ }
+ ssc_p->ssc = ssc;
+
+ at91sam9g20ek_snd_device = platform_device_alloc("soc-audio", -1);
+ if (!at91sam9g20ek_snd_device) {
+ printk(KERN_DEBUG
+ "platform device allocation failed\n");
+ ret = -ENOMEM;
+ }
+
+ platform_set_drvdata(at91sam9g20ek_snd_device,
+ &at91sam9g20ek_snd_devdata);
+ at91sam9g20ek_snd_devdata.dev = &at91sam9g20ek_snd_device->dev;
+
+ ret = platform_device_add(at91sam9g20ek_snd_device);
+ if (ret) {
+ printk(KERN_DEBUG
+ "platform device allocation failed\n");
+ platform_device_put(at91sam9g20ek_snd_device);
+ }
+
+ return ret;
+
+err_ssc:
+ return ret;
+}
+
+static void __exit at91sam9g20ek_exit(void)
+{
+ struct atmel_ssc_info *ssc_p = at91sam9g20ek_dai.cpu_dai->private_data;
+ struct ssc_device *ssc;
+
+ if (ssc_p != NULL) {
+ ssc = ssc_p->ssc;
+ if (ssc != NULL)
+ ssc_free(ssc);
+ ssc_p->ssc = NULL;
+ }
+
+ platform_device_unregister(at91sam9g20ek_snd_device);
+ at91sam9g20ek_snd_device = NULL;
+}
+
+module_init(at91sam9g20ek_init);
+module_exit(at91sam9g20ek_exit);
+
+/* Module information */
+MODULE_AUTHOR("Sedji Gaouaou <sedji.gaouaou@atmel.com>");
+MODULE_DESCRIPTION("ALSA SoC AT91SAM9G20EK_WM8731");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/au1x/dbdma2.c b/sound/soc/au1x/dbdma2.c
index 1466d932880..74c823d60f9 100644
--- a/sound/soc/au1x/dbdma2.c
+++ b/sound/soc/au1x/dbdma2.c
@@ -406,11 +406,12 @@ static int __init au1xpsc_audio_dbdma_init(void)
{
au1xpsc_audio_pcmdma[PCM_TX] = NULL;
au1xpsc_audio_pcmdma[PCM_RX] = NULL;
- return 0;
+ return snd_soc_register_platform(&au1xpsc_soc_platform);
}
static void __exit au1xpsc_audio_dbdma_exit(void)
{
+ snd_soc_unregister_platform(&au1xpsc_soc_platform);
}
module_init(au1xpsc_audio_dbdma_init);
diff --git a/sound/soc/au1x/psc-ac97.c b/sound/soc/au1x/psc-ac97.c
index 57facbad682..f0e30aec7f2 100644
--- a/sound/soc/au1x/psc-ac97.c
+++ b/sound/soc/au1x/psc-ac97.c
@@ -160,7 +160,8 @@ struct snd_ac97_bus_ops soc_ac97_ops = {
EXPORT_SYMBOL_GPL(soc_ac97_ops);
static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
/* FIXME */
struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
@@ -210,7 +211,7 @@ static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream,
}
static int au1xpsc_ac97_trigger(struct snd_pcm_substream *substream,
- int cmd)
+ int cmd, struct snd_soc_dai *dai)
{
/* FIXME */
struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
@@ -313,8 +314,7 @@ static void au1xpsc_ac97_remove(struct platform_device *pdev,
au1xpsc_ac97_workdata = NULL;
}
-static int au1xpsc_ac97_suspend(struct platform_device *pdev,
- struct snd_soc_dai *dai)
+static int au1xpsc_ac97_suspend(struct snd_soc_dai *dai)
{
/* save interesting registers and disable PSC */
au1xpsc_ac97_workdata->pm[0] =
@@ -328,8 +328,7 @@ static int au1xpsc_ac97_suspend(struct platform_device *pdev,
return 0;
}
-static int au1xpsc_ac97_resume(struct platform_device *pdev,
- struct snd_soc_dai *dai)
+static int au1xpsc_ac97_resume(struct snd_soc_dai *dai)
{
/* restore PSC clock config */
au_writel(au1xpsc_ac97_workdata->pm[0] | PSC_SEL_PS_AC97MODE,
@@ -345,7 +344,7 @@ static int au1xpsc_ac97_resume(struct platform_device *pdev,
struct snd_soc_dai au1xpsc_ac97_dai = {
.name = "au1xpsc_ac97",
- .type = SND_SOC_DAI_AC97,
+ .ac97_control = 1,
.probe = au1xpsc_ac97_probe,
.remove = au1xpsc_ac97_remove,
.suspend = au1xpsc_ac97_suspend,
@@ -372,11 +371,12 @@ EXPORT_SYMBOL_GPL(au1xpsc_ac97_dai);
static int __init au1xpsc_ac97_init(void)
{
au1xpsc_ac97_workdata = NULL;
- return 0;
+ return snd_soc_register_dai(&au1xpsc_ac97_dai);
}
static void __exit au1xpsc_ac97_exit(void)
{
+ snd_soc_unregister_dai(&au1xpsc_ac97_dai);
}
module_init(au1xpsc_ac97_init);
diff --git a/sound/soc/au1x/psc-i2s.c b/sound/soc/au1x/psc-i2s.c
index 9384702c7eb..f916de4400e 100644
--- a/sound/soc/au1x/psc-i2s.c
+++ b/sound/soc/au1x/psc-i2s.c
@@ -116,7 +116,8 @@ out:
}
static int au1xpsc_i2s_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct au1xpsc_audio_data *pscdata = au1xpsc_i2s_workdata;
@@ -240,7 +241,8 @@ static int au1xpsc_i2s_stop(struct au1xpsc_audio_data *pscdata, int stype)
return 0;
}
-static int au1xpsc_i2s_trigger(struct snd_pcm_substream *substream, int cmd)
+static int au1xpsc_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
{
struct au1xpsc_audio_data *pscdata = au1xpsc_i2s_workdata;
int ret, stype = SUBSTREAM_TYPE(substream);
@@ -337,8 +339,7 @@ static void au1xpsc_i2s_remove(struct platform_device *pdev,
au1xpsc_i2s_workdata = NULL;
}
-static int au1xpsc_i2s_suspend(struct platform_device *pdev,
- struct snd_soc_dai *cpu_dai)
+static int au1xpsc_i2s_suspend(struct snd_soc_dai *cpu_dai)
{
/* save interesting register and disable PSC */
au1xpsc_i2s_workdata->pm[0] =
@@ -352,8 +353,7 @@ static int au1xpsc_i2s_suspend(struct platform_device *pdev,
return 0;
}
-static int au1xpsc_i2s_resume(struct platform_device *pdev,
- struct snd_soc_dai *cpu_dai)
+static int au1xpsc_i2s_resume(struct snd_soc_dai *cpu_dai)
{
/* select I2S mode and PSC clock */
au_writel(PSC_CTRL_DISABLE, PSC_CTRL(au1xpsc_i2s_workdata));
@@ -369,7 +369,6 @@ static int au1xpsc_i2s_resume(struct platform_device *pdev,
struct snd_soc_dai au1xpsc_i2s_dai = {
.name = "au1xpsc_i2s",
- .type = SND_SOC_DAI_I2S,
.probe = au1xpsc_i2s_probe,
.remove = au1xpsc_i2s_remove,
.suspend = au1xpsc_i2s_suspend,
@@ -389,8 +388,6 @@ struct snd_soc_dai au1xpsc_i2s_dai = {
.ops = {
.trigger = au1xpsc_i2s_trigger,
.hw_params = au1xpsc_i2s_hw_params,
- },
- .dai_ops = {
.set_fmt = au1xpsc_i2s_set_fmt,
},
};
@@ -399,11 +396,12 @@ EXPORT_SYMBOL(au1xpsc_i2s_dai);
static int __init au1xpsc_i2s_init(void)
{
au1xpsc_i2s_workdata = NULL;
- return 0;
+ return snd_soc_register_dai(&au1xpsc_i2s_dai);
}
static void __exit au1xpsc_i2s_exit(void)
{
+ snd_soc_unregister_dai(&au1xpsc_i2s_dai);
}
module_init(au1xpsc_i2s_init);
diff --git a/sound/soc/au1x/sample-ac97.c b/sound/soc/au1x/sample-ac97.c
index f75ae7f62c3..27683eb7905 100644
--- a/sound/soc/au1x/sample-ac97.c
+++ b/sound/soc/au1x/sample-ac97.c
@@ -42,14 +42,14 @@ static struct snd_soc_dai_link au1xpsc_sample_ac97_dai = {
.ops = NULL,
};
-static struct snd_soc_machine au1xpsc_sample_ac97_machine = {
+static struct snd_soc_card au1xpsc_sample_ac97_machine = {
.name = "Au1xxx PSC AC97 Audio",
.dai_link = &au1xpsc_sample_ac97_dai,
.num_links = 1,
};
static struct snd_soc_device au1xpsc_sample_ac97_devdata = {
- .machine = &au1xpsc_sample_ac97_machine,
+ .card = &au1xpsc_sample_ac97_machine,
.platform = &au1xpsc_soc_platform, /* see dbdma2.c */
.codec_dev = &soc_codec_dev_ac97,
};
diff --git a/sound/soc/blackfin/Kconfig b/sound/soc/blackfin/Kconfig
index dc006206f62..0a2f8f9eff5 100644
--- a/sound/soc/blackfin/Kconfig
+++ b/sound/soc/blackfin/Kconfig
@@ -1,6 +1,6 @@
config SND_BF5XX_I2S
tristate "SoC I2S Audio for the ADI BF5xx chip"
- depends on BLACKFIN && SND_SOC
+ depends on BLACKFIN
help
Say Y or M if you want to add support for codecs attached to
the Blackfin SPORT (synchronous serial ports) interface in I2S
@@ -13,7 +13,6 @@ config SND_BF5XX_SOC_SSM2602
select SND_BF5XX_SOC_I2S
select SND_SOC_SSM2602
select I2C
- select I2C_BLACKFIN_TWI
help
Say Y if you want to add support for SoC audio on BF527-EZKIT.
@@ -35,7 +34,7 @@ config SND_BFIN_AD73311_SE
config SND_BF5XX_AC97
tristate "SoC AC97 Audio for the ADI BF5xx chip"
- depends on BLACKFIN && SND_SOC
+ depends on BLACKFIN
help
Say Y or M if you want to add support for codecs attached to
the Blackfin SPORT (synchronous serial ports) interface in slot 16
@@ -47,7 +46,7 @@ config SND_BF5XX_AC97
properly with this driver. This driver is known to work with the
Analog Devices line of AC97 codecs.
-config SND_MMAP_SUPPORT
+config SND_BF5XX_MMAP_SUPPORT
bool "Enable MMAP Support"
depends on SND_BF5XX_AC97
default y
@@ -55,9 +54,17 @@ config SND_MMAP_SUPPORT
Say y if you want AC97 driver to support mmap mode.
We introduce an intermediate buffer to simulate mmap.
+config SND_BF5XX_MULTICHAN_SUPPORT
+ bool "Enable Multichannel Support"
+ depends on SND_BF5XX_AC97
+ default n
+ help
+ Say y if you want AC97 driver to support up to 5.1 channel audio.
+ this mode will consume much more memory for DMA.
+
config SND_BF5XX_SOC_SPORT
tristate
-
+
config SND_BF5XX_SOC_I2S
tristate
select SND_BF5XX_SOC_SPORT
@@ -80,7 +87,7 @@ config SND_BF5XX_SPORT_NUM
int "Set a SPORT for Sound chip"
depends on (SND_BF5XX_I2S || SND_BF5XX_AC97)
range 0 3 if BF54x
- range 0 1 if (BF53x || BF561)
+ range 0 1 if !BF54x
default 0
help
Set the correct SPORT for sound chip.
@@ -90,12 +97,13 @@ config SND_BF5XX_HAVE_COLD_RESET
depends on SND_BF5XX_AC97
default y if BFIN548_EZKIT
default n if !BFIN548_EZKIT
-
+
config SND_BF5XX_RESET_GPIO_NUM
int "Set a GPIO for cold reset"
depends on SND_BF5XX_HAVE_COLD_RESET
range 0 159
default 19 if BFIN548_EZKIT
default 5 if BFIN537_STAMP
+ default 0
help
Set the correct GPIO for RESET the sound chip.
diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.c b/sound/soc/blackfin/bf5xx-ac97-pcm.c
index 25e50d2ea1e..8067cfafa3a 100644
--- a/sound/soc/blackfin/bf5xx-ac97-pcm.c
+++ b/sound/soc/blackfin/bf5xx-ac97-pcm.c
@@ -43,24 +43,34 @@
#include "bf5xx-ac97.h"
#include "bf5xx-sport.h"
-#if defined(CONFIG_SND_MMAP_SUPPORT)
+static unsigned int ac97_chan_mask[] = {
+ SP_FL, /* Mono */
+ SP_STEREO, /* Stereo */
+ SP_2DOT1, /* 2.1*/
+ SP_QUAD,/*Quadraquic*/
+ SP_FL | SP_FR | SP_FC | SP_SL | SP_SR,/*5 channels */
+ SP_5DOT1, /* 5.1 */
+};
+
+#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
static void bf5xx_mmap_copy(struct snd_pcm_substream *substream,
snd_pcm_uframes_t count)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct sport_device *sport = runtime->private_data;
+ unsigned int chan_mask = ac97_chan_mask[runtime->channels - 1];
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- bf5xx_pcm_to_ac97(
- (struct ac97_frame *)sport->tx_dma_buf + sport->tx_pos,
- (__u32 *)runtime->dma_area + sport->tx_pos, count);
+ bf5xx_pcm_to_ac97((struct ac97_frame *)sport->tx_dma_buf +
+ sport->tx_pos, (__u16 *)runtime->dma_area + sport->tx_pos *
+ runtime->channels, count, chan_mask);
sport->tx_pos += runtime->period_size;
if (sport->tx_pos >= runtime->buffer_size)
sport->tx_pos %= runtime->buffer_size;
sport->tx_delay_pos = sport->tx_pos;
} else {
- bf5xx_ac97_to_pcm(
- (struct ac97_frame *)sport->rx_dma_buf + sport->rx_pos,
- (__u32 *)runtime->dma_area + sport->rx_pos, count);
+ bf5xx_ac97_to_pcm((struct ac97_frame *)sport->rx_dma_buf +
+ sport->rx_pos, (__u16 *)runtime->dma_area + sport->rx_pos *
+ runtime->channels, count);
sport->rx_pos += runtime->period_size;
if (sport->rx_pos >= runtime->buffer_size)
sport->rx_pos %= runtime->buffer_size;
@@ -71,7 +81,7 @@ static void bf5xx_mmap_copy(struct snd_pcm_substream *substream,
static void bf5xx_dma_irq(void *data)
{
struct snd_pcm_substream *pcm = data;
-#if defined(CONFIG_SND_MMAP_SUPPORT)
+#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
struct snd_pcm_runtime *runtime = pcm->runtime;
struct sport_device *sport = runtime->private_data;
bf5xx_mmap_copy(pcm, runtime->period_size);
@@ -90,17 +100,14 @@ static void bf5xx_dma_irq(void *data)
* The total rx/tx buffer is for ac97 frame to hold all pcm data
* is 0x20000 * sizeof(struct ac97_frame) / 4.
*/
-#ifdef CONFIG_SND_MMAP_SUPPORT
static const struct snd_pcm_hardware bf5xx_pcm_hardware = {
.info = SNDRV_PCM_INFO_INTERLEAVED |
+#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_BLOCK_TRANSFER,
-#else
-static const struct snd_pcm_hardware bf5xx_pcm_hardware = {
- .info = SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_BLOCK_TRANSFER,
#endif
+ SNDRV_PCM_INFO_BLOCK_TRANSFER,
+
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.period_bytes_min = 32,
.period_bytes_max = 0x10000,
@@ -123,10 +130,20 @@ static int bf5xx_pcm_hw_params(struct snd_pcm_substream *substream,
static int bf5xx_pcm_hw_free(struct snd_pcm_substream *substream)
{
+#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
struct snd_pcm_runtime *runtime = substream->runtime;
+ struct sport_device *sport = runtime->private_data;
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- memset(runtime->dma_area, 0, runtime->buffer_size);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ sport->once = 0;
+ if (runtime->dma_area)
+ memset(runtime->dma_area, 0, runtime->buffer_size);
+ memset(sport->tx_dma_buf, 0, runtime->buffer_size *
+ sizeof(struct ac97_frame));
+ } else
+ memset(sport->rx_dma_buf, 0, runtime->buffer_size *
+ sizeof(struct ac97_frame));
+#endif
snd_pcm_lib_free_pages(substream);
return 0;
}
@@ -139,7 +156,7 @@ static int bf5xx_pcm_prepare(struct snd_pcm_substream *substream)
/* An intermediate buffer is introduced for implementing mmap for
* SPORT working in TMD mode(include AC97).
*/
-#if defined(CONFIG_SND_MMAP_SUPPORT)
+#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
sport_set_tx_callback(sport, bf5xx_dma_irq, substream);
sport_config_tx_dma(sport, sport->tx_dma_buf, runtime->periods,
@@ -173,24 +190,24 @@ static int bf5xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
bf5xx_mmap_copy(substream, runtime->period_size);
- snd_pcm_period_elapsed(substream);
sport->tx_delay_pos = 0;
+#endif
sport_tx_start(sport);
- }
- else
+ } else
sport_rx_start(sport);
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-#if defined(CONFIG_SND_MMAP_SUPPORT)
+#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
sport->tx_pos = 0;
#endif
sport_tx_stop(sport);
} else {
-#if defined(CONFIG_SND_MMAP_SUPPORT)
+#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
sport->rx_pos = 0;
#endif
sport_rx_stop(sport);
@@ -208,7 +225,7 @@ static snd_pcm_uframes_t bf5xx_pcm_pointer(struct snd_pcm_substream *substream)
struct sport_device *sport = runtime->private_data;
unsigned int curr;
-#if defined(CONFIG_SND_MMAP_SUPPORT)
+#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
curr = sport->tx_delay_pos;
else
@@ -249,22 +266,7 @@ static int bf5xx_pcm_open(struct snd_pcm_substream *substream)
return ret;
}
-static int bf5xx_pcm_close(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct sport_device *sport = runtime->private_data;
-
- pr_debug("%s enter\n", __func__);
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- sport->once = 0;
- memset(sport->tx_dma_buf, 0, runtime->buffer_size * sizeof(struct ac97_frame));
- } else
- memset(sport->rx_dma_buf, 0, runtime->buffer_size * sizeof(struct ac97_frame));
-
- return 0;
-}
-
-#ifdef CONFIG_SND_MMAP_SUPPORT
+#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
static int bf5xx_pcm_mmap(struct snd_pcm_substream *substream,
struct vm_area_struct *vma)
{
@@ -281,32 +283,29 @@ static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel,
void __user *buf, snd_pcm_uframes_t count)
{
struct snd_pcm_runtime *runtime = substream->runtime;
-
+ unsigned int chan_mask = ac97_chan_mask[runtime->channels - 1];
pr_debug("%s copy pos:0x%lx count:0x%lx\n",
substream->stream ? "Capture" : "Playback", pos, count);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- bf5xx_pcm_to_ac97(
- (struct ac97_frame *)runtime->dma_area + pos,
- buf, count);
+ bf5xx_pcm_to_ac97((struct ac97_frame *)runtime->dma_area + pos,
+ (__u16 *)buf, count, chan_mask);
else
- bf5xx_ac97_to_pcm(
- (struct ac97_frame *)runtime->dma_area + pos,
- buf, count);
+ bf5xx_ac97_to_pcm((struct ac97_frame *)runtime->dma_area + pos,
+ (__u16 *)buf, count);
return 0;
}
#endif
struct snd_pcm_ops bf5xx_pcm_ac97_ops = {
.open = bf5xx_pcm_open,
- .close = bf5xx_pcm_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = bf5xx_pcm_hw_params,
.hw_free = bf5xx_pcm_hw_free,
.prepare = bf5xx_pcm_prepare,
.trigger = bf5xx_pcm_trigger,
.pointer = bf5xx_pcm_pointer,
-#ifdef CONFIG_SND_MMAP_SUPPORT
+#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
.mmap = bf5xx_pcm_mmap,
#else
.copy = bf5xx_pcm_copy,
@@ -344,7 +343,7 @@ static int bf5xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
* Need to allocate local buffer when enable
* MMAP for SPORT working in TMD mode (include AC97).
*/
-#if defined(CONFIG_SND_MMAP_SUPPORT)
+#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
if (!sport_handle->tx_dma_buf) {
sport_handle->tx_dma_buf = dma_alloc_coherent(NULL, \
@@ -381,7 +380,7 @@ static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
struct snd_pcm_substream *substream;
struct snd_dma_buffer *buf;
int stream;
-#if defined(CONFIG_SND_MMAP_SUPPORT)
+#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
size_t size = bf5xx_pcm_hardware.buffer_bytes_max *
sizeof(struct ac97_frame) / 4;
#endif
@@ -395,7 +394,7 @@ static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
continue;
dma_free_coherent(NULL, buf->bytes, buf->area, 0);
buf->area = NULL;
-#if defined(CONFIG_SND_MMAP_SUPPORT)
+#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
if (sport_handle->tx_dma_buf)
dma_free_coherent(NULL, size, \
@@ -452,6 +451,18 @@ struct snd_soc_platform bf5xx_ac97_soc_platform = {
};
EXPORT_SYMBOL_GPL(bf5xx_ac97_soc_platform);
+static int __init bfin_ac97_init(void)
+{
+ return snd_soc_register_platform(&bf5xx_ac97_soc_platform);
+}
+module_init(bfin_ac97_init);
+
+static void __exit bfin_ac97_exit(void)
+{
+ snd_soc_unregister_platform(&bf5xx_ac97_soc_platform);
+}
+module_exit(bfin_ac97_exit);
+
MODULE_AUTHOR("Cliff Cai");
MODULE_DESCRIPTION("ADI Blackfin AC97 PCM DMA module");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/blackfin/bf5xx-ac97.c b/sound/soc/blackfin/bf5xx-ac97.c
index 5e5aafb6485..3be2be60576 100644
--- a/sound/soc/blackfin/bf5xx-ac97.c
+++ b/sound/soc/blackfin/bf5xx-ac97.c
@@ -54,71 +54,103 @@
static int *cmd_count;
static int sport_num = CONFIG_SND_BF5XX_SPORT_NUM;
-#if defined(CONFIG_BF54x)
+static u16 sport_req[][7] = {
+ PIN_REQ_SPORT_0,
+#ifdef PIN_REQ_SPORT_1
+ PIN_REQ_SPORT_1,
+#endif
+#ifdef PIN_REQ_SPORT_2
+ PIN_REQ_SPORT_2,
+#endif
+#ifdef PIN_REQ_SPORT_3
+ PIN_REQ_SPORT_3,
+#endif
+ };
+
static struct sport_param sport_params[4] = {
{
.dma_rx_chan = CH_SPORT0_RX,
.dma_tx_chan = CH_SPORT0_TX,
- .err_irq = IRQ_SPORT0_ERR,
+ .err_irq = IRQ_SPORT0_ERROR,
.regs = (struct sport_register *)SPORT0_TCR1,
},
+#ifdef PIN_REQ_SPORT_1
{
.dma_rx_chan = CH_SPORT1_RX,
.dma_tx_chan = CH_SPORT1_TX,
- .err_irq = IRQ_SPORT1_ERR,
+ .err_irq = IRQ_SPORT1_ERROR,
.regs = (struct sport_register *)SPORT1_TCR1,
},
+#endif
+#ifdef PIN_REQ_SPORT_2
{
.dma_rx_chan = CH_SPORT2_RX,
.dma_tx_chan = CH_SPORT2_TX,
- .err_irq = IRQ_SPORT2_ERR,
+ .err_irq = IRQ_SPORT2_ERROR,
.regs = (struct sport_register *)SPORT2_TCR1,
},
+#endif
+#ifdef PIN_REQ_SPORT_3
{
.dma_rx_chan = CH_SPORT3_RX,
.dma_tx_chan = CH_SPORT3_TX,
- .err_irq = IRQ_SPORT3_ERR,
+ .err_irq = IRQ_SPORT3_ERROR,
.regs = (struct sport_register *)SPORT3_TCR1,
}
-};
-#else
-static struct sport_param sport_params[2] = {
- {
- .dma_rx_chan = CH_SPORT0_RX,
- .dma_tx_chan = CH_SPORT0_TX,
- .err_irq = IRQ_SPORT0_ERROR,
- .regs = (struct sport_register *)SPORT0_TCR1,
- },
- {
- .dma_rx_chan = CH_SPORT1_RX,
- .dma_tx_chan = CH_SPORT1_TX,
- .err_irq = IRQ_SPORT1_ERROR,
- .regs = (struct sport_register *)SPORT1_TCR1,
- }
-};
#endif
+};
-void bf5xx_pcm_to_ac97(struct ac97_frame *dst, const __u32 *src, \
- size_t count)
+void bf5xx_pcm_to_ac97(struct ac97_frame *dst, const __u16 *src,
+ size_t count, unsigned int chan_mask)
{
while (count--) {
- dst->ac97_tag = TAG_VALID | TAG_PCM;
- (dst++)->ac97_pcm = *src++;
+ dst->ac97_tag = TAG_VALID;
+ if (chan_mask & SP_FL) {
+ dst->ac97_pcm_r = *src++;
+ dst->ac97_tag |= TAG_PCM_RIGHT;
+ }
+ if (chan_mask & SP_FR) {
+ dst->ac97_pcm_l = *src++;
+ dst->ac97_tag |= TAG_PCM_LEFT;
+
+ }
+#if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT)
+ if (chan_mask & SP_SR) {
+ dst->ac97_sl = *src++;
+ dst->ac97_tag |= TAG_PCM_SL;
+ }
+ if (chan_mask & SP_SL) {
+ dst->ac97_sr = *src++;
+ dst->ac97_tag |= TAG_PCM_SR;
+ }
+ if (chan_mask & SP_LFE) {
+ dst->ac97_lfe = *src++;
+ dst->ac97_tag |= TAG_PCM_LFE;
+ }
+ if (chan_mask & SP_FC) {
+ dst->ac97_center = *src++;
+ dst->ac97_tag |= TAG_PCM_CENTER;
+ }
+#endif
+ dst++;
}
}
EXPORT_SYMBOL(bf5xx_pcm_to_ac97);
-void bf5xx_ac97_to_pcm(const struct ac97_frame *src, __u32 *dst, \
+void bf5xx_ac97_to_pcm(const struct ac97_frame *src, __u16 *dst,
size_t count)
{
- while (count--)
- *(dst++) = (src++)->ac97_pcm;
+ while (count--) {
+ *(dst++) = src->ac97_pcm_l;
+ *(dst++) = src->ac97_pcm_r;
+ src++;
+ }
}
EXPORT_SYMBOL(bf5xx_ac97_to_pcm);
static unsigned int sport_tx_curr_frag(struct sport_device *sport)
{
- return sport->tx_curr_frag = sport_curr_offset_tx(sport) / \
+ return sport->tx_curr_frag = sport_curr_offset_tx(sport) /
sport->tx_fragsize;
}
@@ -130,7 +162,7 @@ static void enqueue_cmd(struct snd_ac97 *ac97, __u16 addr, __u16 data)
sport_incfrag(sport, &nextfrag, 1);
- nextwrite = (struct ac97_frame *)(sport->tx_buf + \
+ nextwrite = (struct ac97_frame *)(sport->tx_buf +
nextfrag * sport->tx_fragsize);
pr_debug("sport->tx_buf:%p, nextfrag:0x%x nextwrite:%p, cmd_count:%d\n",
sport->tx_buf, nextfrag, nextwrite, cmd_count[nextfrag]);
@@ -237,8 +269,7 @@ struct snd_ac97_bus_ops soc_ac97_ops = {
EXPORT_SYMBOL_GPL(soc_ac97_ops);
#ifdef CONFIG_PM
-static int bf5xx_ac97_suspend(struct platform_device *pdev,
- struct snd_soc_dai *dai)
+static int bf5xx_ac97_suspend(struct snd_soc_dai *dai)
{
struct sport_device *sport =
(struct sport_device *)dai->private_data;
@@ -253,8 +284,7 @@ static int bf5xx_ac97_suspend(struct platform_device *pdev,
return 0;
}
-static int bf5xx_ac97_resume(struct platform_device *pdev,
- struct snd_soc_dai *dai)
+static int bf5xx_ac97_resume(struct snd_soc_dai *dai)
{
int ret;
struct sport_device *sport =
@@ -297,20 +327,15 @@ static int bf5xx_ac97_resume(struct platform_device *pdev,
static int bf5xx_ac97_probe(struct platform_device *pdev,
struct snd_soc_dai *dai)
{
- int ret;
-#if defined(CONFIG_BF54x)
- u16 sport_req[][7] = {PIN_REQ_SPORT_0, PIN_REQ_SPORT_1,
- PIN_REQ_SPORT_2, PIN_REQ_SPORT_3};
-#else
- u16 sport_req[][7] = {PIN_REQ_SPORT_0, PIN_REQ_SPORT_1};
-#endif
+ int ret = 0;
cmd_count = (int *)get_zeroed_page(GFP_KERNEL);
if (cmd_count == NULL)
return -ENOMEM;
if (peripheral_request_list(&sport_req[sport_num][0], "soc-audio")) {
pr_err("Requesting Peripherals failed\n");
- return -EFAULT;
+ ret = -EFAULT;
+ goto peripheral_err;
}
#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
@@ -318,54 +343,54 @@ static int bf5xx_ac97_probe(struct platform_device *pdev,
if (gpio_request(CONFIG_SND_BF5XX_RESET_GPIO_NUM, "SND_AD198x RESET")) {
pr_err("Failed to request GPIO_%d for reset\n",
CONFIG_SND_BF5XX_RESET_GPIO_NUM);
- peripheral_free_list(&sport_req[sport_num][0]);
- return -1;
+ ret = -1;
+ goto gpio_err;
}
gpio_direction_output(CONFIG_SND_BF5XX_RESET_GPIO_NUM, 1);
#endif
sport_handle = sport_init(&sport_params[sport_num], 2, \
sizeof(struct ac97_frame), NULL);
if (!sport_handle) {
- peripheral_free_list(&sport_req[sport_num][0]);
-#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
- gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM);
-#endif
- return -ENODEV;
+ ret = -ENODEV;
+ goto sport_err;
}
/*SPORT works in TDM mode to simulate AC97 transfers*/
ret = sport_set_multichannel(sport_handle, 16, 0x1F, 1);
if (ret) {
pr_err("SPORT is busy!\n");
- kfree(sport_handle);
- peripheral_free_list(&sport_req[sport_num][0]);
-#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
- gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM);
-#endif
- return -EBUSY;
+ ret = -EBUSY;
+ goto sport_config_err;
}
ret = sport_config_rx(sport_handle, IRFS, 0xF, 0, (16*16-1));
if (ret) {
pr_err("SPORT is busy!\n");
- kfree(sport_handle);
- peripheral_free_list(&sport_req[sport_num][0]);
-#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
- gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM);
-#endif
- return -EBUSY;
+ ret = -EBUSY;
+ goto sport_config_err;
}
ret = sport_config_tx(sport_handle, ITFS, 0xF, 0, (16*16-1));
if (ret) {
pr_err("SPORT is busy!\n");
- kfree(sport_handle);
- peripheral_free_list(&sport_req[sport_num][0]);
-#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
- gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM);
-#endif
- return -EBUSY;
+ ret = -EBUSY;
+ goto sport_config_err;
}
+
return 0;
+
+sport_config_err:
+ kfree(sport_handle);
+sport_err:
+#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
+ gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM);
+#endif
+gpio_err:
+ peripheral_free_list(&sport_req[sport_num][0]);
+peripheral_err:
+ free_page((unsigned long)cmd_count);
+ cmd_count = NULL;
+
+ return ret;
}
static void bf5xx_ac97_remove(struct platform_device *pdev,
@@ -373,6 +398,7 @@ static void bf5xx_ac97_remove(struct platform_device *pdev,
{
free_page((unsigned long)cmd_count);
cmd_count = NULL;
+ peripheral_free_list(&sport_req[sport_num][0]);
#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM);
#endif
@@ -381,7 +407,7 @@ static void bf5xx_ac97_remove(struct platform_device *pdev,
struct snd_soc_dai bfin_ac97_dai = {
.name = "bf5xx-ac97",
.id = 0,
- .type = SND_SOC_DAI_AC97,
+ .ac97_control = 1,
.probe = bf5xx_ac97_probe,
.remove = bf5xx_ac97_remove,
.suspend = bf5xx_ac97_suspend,
@@ -389,7 +415,11 @@ struct snd_soc_dai bfin_ac97_dai = {
.playback = {
.stream_name = "AC97 Playback",
.channels_min = 2,
+#if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT)
+ .channels_max = 6,
+#else
.channels_max = 2,
+#endif
.rates = SNDRV_PCM_RATE_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE, },
.capture = {
@@ -401,6 +431,18 @@ struct snd_soc_dai bfin_ac97_dai = {
};
EXPORT_SYMBOL_GPL(bfin_ac97_dai);
+static int __init bfin_ac97_init(void)
+{
+ return snd_soc_register_dai(&bfin_ac97_dai);
+}
+module_init(bfin_ac97_init);
+
+static void __exit bfin_ac97_exit(void)
+{
+ snd_soc_unregister_dai(&bfin_ac97_dai);
+}
+module_exit(bfin_ac97_exit);
+
MODULE_AUTHOR("Roy Huang");
MODULE_DESCRIPTION("AC97 driver for ADI Blackfin");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/blackfin/bf5xx-ac97.h b/sound/soc/blackfin/bf5xx-ac97.h
index 3f77cc558dc..3f2a911fe0c 100644
--- a/sound/soc/blackfin/bf5xx-ac97.h
+++ b/sound/soc/blackfin/bf5xx-ac97.h
@@ -16,21 +16,46 @@ struct ac97_frame {
u16 ac97_tag; /* slot 0 */
u16 ac97_addr; /* slot 1 */
u16 ac97_data; /* slot 2 */
- u32 ac97_pcm; /* slot 3 and 4: left and right pcm data */
+ u16 ac97_pcm_l; /*slot 3:front left*/
+ u16 ac97_pcm_r; /*slot 4:front left*/
+#if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT)
+ u16 ac97_mdm_l1;
+ u16 ac97_center; /*slot 6:center*/
+ u16 ac97_sl; /*slot 7:surround left*/
+ u16 ac97_sr; /*slot 8:surround right*/
+ u16 ac97_lfe; /*slot 9:lfe*/
+#endif
} __attribute__ ((packed));
+/* Speaker location */
+#define SP_FL 0x0001
+#define SP_FR 0x0010
+#define SP_FC 0x0002
+#define SP_LFE 0x0020
+#define SP_SL 0x0004
+#define SP_SR 0x0040
+
+#define SP_STEREO (SP_FL | SP_FR)
+#define SP_2DOT1 (SP_FL | SP_FR | SP_LFE)
+#define SP_QUAD (SP_FL | SP_FR | SP_SL | SP_SR)
+#define SP_5DOT1 (SP_FL | SP_FR | SP_FC | SP_LFE | SP_SL | SP_SR)
+
#define TAG_VALID 0x8000
#define TAG_CMD 0x6000
#define TAG_PCM_LEFT 0x1000
#define TAG_PCM_RIGHT 0x0800
-#define TAG_PCM (TAG_PCM_LEFT | TAG_PCM_RIGHT)
+#define TAG_PCM_MDM_L1 0x0400
+#define TAG_PCM_CENTER 0x0200
+#define TAG_PCM_SL 0x0100
+#define TAG_PCM_SR 0x0080
+#define TAG_PCM_LFE 0x0040
extern struct snd_soc_dai bfin_ac97_dai;
-void bf5xx_pcm_to_ac97(struct ac97_frame *dst, const __u32 *src, \
- size_t count);
+void bf5xx_pcm_to_ac97(struct ac97_frame *dst, const __u16 *src, \
+ size_t count, unsigned int chan_mask);
-void bf5xx_ac97_to_pcm(const struct ac97_frame *src, __u32 *dst, \
+void bf5xx_ac97_to_pcm(const struct ac97_frame *src, __u16 *dst, \
size_t count);
#endif
diff --git a/sound/soc/blackfin/bf5xx-ad1980.c b/sound/soc/blackfin/bf5xx-ad1980.c
index 124425d2232..d8f59127377 100644
--- a/sound/soc/blackfin/bf5xx-ad1980.c
+++ b/sound/soc/blackfin/bf5xx-ad1980.c
@@ -43,7 +43,7 @@
#include "bf5xx-ac97-pcm.h"
#include "bf5xx-ac97.h"
-static struct snd_soc_machine bf5xx_board;
+static struct snd_soc_card bf5xx_board;
static int bf5xx_board_startup(struct snd_pcm_substream *substream)
{
@@ -67,15 +67,15 @@ static struct snd_soc_dai_link bf5xx_board_dai = {
.ops = &bf5xx_board_ops,
};
-static struct snd_soc_machine bf5xx_board = {
+static struct snd_soc_card bf5xx_board = {
.name = "bf5xx-board",
+ .platform = &bf5xx_ac97_soc_platform,
.dai_link = &bf5xx_board_dai,
.num_links = 1,
};
static struct snd_soc_device bf5xx_board_snd_devdata = {
- .machine = &bf5xx_board,
- .platform = &bf5xx_ac97_soc_platform,
+ .card = &bf5xx_board,
.codec_dev = &soc_codec_dev_ad1980,
};
diff --git a/sound/soc/blackfin/bf5xx-ad73311.c b/sound/soc/blackfin/bf5xx-ad73311.c
index 622c9b90953..7f2a5e19907 100644
--- a/sound/soc/blackfin/bf5xx-ad73311.c
+++ b/sound/soc/blackfin/bf5xx-ad73311.c
@@ -65,7 +65,7 @@
#define GPIO_SE CONFIG_SND_BFIN_AD73311_SE
-static struct snd_soc_machine bf5xx_ad73311;
+static struct snd_soc_card bf5xx_ad73311;
static int snd_ad73311_startup(void)
{
@@ -168,7 +168,7 @@ static int bf5xx_ad73311_hw_params(struct snd_pcm_substream *substream,
params_format(params));
/* set cpu DAI configuration */
- ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A |
+ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A |
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
if (ret < 0)
return ret;
@@ -190,16 +190,16 @@ static struct snd_soc_dai_link bf5xx_ad73311_dai = {
.ops = &bf5xx_ad73311_ops,
};
-static struct snd_soc_machine bf5xx_ad73311 = {
+static struct snd_soc_card bf5xx_ad73311 = {
.name = "bf5xx_ad73311",
+ .platform = &bf5xx_i2s_soc_platform,
.probe = bf5xx_probe,
.dai_link = &bf5xx_ad73311_dai,
.num_links = 1,
};
static struct snd_soc_device bf5xx_ad73311_snd_devdata = {
- .machine = &bf5xx_ad73311,
- .platform = &bf5xx_i2s_soc_platform,
+ .card = &bf5xx_ad73311,
.codec_dev = &soc_codec_dev_ad73311,
};
diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c b/sound/soc/blackfin/bf5xx-i2s-pcm.c
index 61fccf92519..53d290b3ea4 100644
--- a/sound/soc/blackfin/bf5xx-i2s-pcm.c
+++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c
@@ -283,6 +283,18 @@ struct snd_soc_platform bf5xx_i2s_soc_platform = {
};
EXPORT_SYMBOL_GPL(bf5xx_i2s_soc_platform);
+static int __init bfin_i2s_init(void)
+{
+ return snd_soc_register_platform(&bf5xx_i2s_soc_platform);
+}
+module_init(bfin_i2s_init);
+
+static void __exit bfin_i2s_exit(void)
+{
+ snd_soc_unregister_platform(&bf5xx_i2s_soc_platform);
+}
+module_exit(bfin_i2s_exit);
+
MODULE_AUTHOR("Cliff Cai");
MODULE_DESCRIPTION("ADI Blackfin I2S PCM DMA module");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/blackfin/bf5xx-i2s.c b/sound/soc/blackfin/bf5xx-i2s.c
index e020c160ee4..d1d95d2393f 100644
--- a/sound/soc/blackfin/bf5xx-i2s.c
+++ b/sound/soc/blackfin/bf5xx-i2s.c
@@ -132,7 +132,8 @@ static int bf5xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
return ret;
}
-static int bf5xx_i2s_startup(struct snd_pcm_substream *substream)
+static int bf5xx_i2s_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
pr_debug("%s enter\n", __func__);
@@ -142,7 +143,8 @@ static int bf5xx_i2s_startup(struct snd_pcm_substream *substream)
}
static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
int ret = 0;
@@ -193,7 +195,8 @@ static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream,
return 0;
}
-static void bf5xx_i2s_shutdown(struct snd_pcm_substream *substream)
+static void bf5xx_i2s_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
pr_debug("%s enter\n", __func__);
bf5xx_i2s.counter--;
@@ -219,16 +222,14 @@ static int bf5xx_i2s_probe(struct platform_device *pdev,
return 0;
}
-static void bf5xx_i2s_remove(struct platform_device *pdev,
- struct snd_soc_dai *dai)
+static void bf5xx_i2s_remove(struct snd_soc_dai *dai)
{
pr_debug("%s enter\n", __func__);
peripheral_free_list(&sport_req[sport_num][0]);
}
#ifdef CONFIG_PM
-static int bf5xx_i2s_suspend(struct platform_device *dev,
- struct snd_soc_dai *dai)
+static int bf5xx_i2s_suspend(struct snd_soc_dai *dai)
{
struct sport_device *sport =
(struct sport_device *)dai->private_data;
@@ -289,7 +290,6 @@ static int bf5xx_i2s_resume(struct platform_device *pdev,
struct snd_soc_dai bf5xx_i2s_dai = {
.name = "bf5xx-i2s",
.id = 0,
- .type = SND_SOC_DAI_I2S,
.probe = bf5xx_i2s_probe,
.remove = bf5xx_i2s_remove,
.suspend = bf5xx_i2s_suspend,
@@ -307,13 +307,24 @@ struct snd_soc_dai bf5xx_i2s_dai = {
.ops = {
.startup = bf5xx_i2s_startup,
.shutdown = bf5xx_i2s_shutdown,
- .hw_params = bf5xx_i2s_hw_params,},
- .dai_ops = {
+ .hw_params = bf5xx_i2s_hw_params,
.set_fmt = bf5xx_i2s_set_dai_fmt,
},
};
EXPORT_SYMBOL_GPL(bf5xx_i2s_dai);
+static int __init bfin_i2s_init(void)
+{
+ return snd_soc_register_dai(&bf5xx_i2s_dai);
+}
+module_init(bfin_i2s_init);
+
+static void __exit bfin_i2s_exit(void)
+{
+ snd_soc_unregister_dai(&bf5xx_i2s_dai);
+}
+module_exit(bfin_i2s_exit);
+
/* Module information */
MODULE_AUTHOR("Cliff Cai");
MODULE_DESCRIPTION("I2S driver for ADI Blackfin");
diff --git a/sound/soc/blackfin/bf5xx-sport.h b/sound/soc/blackfin/bf5xx-sport.h
index fcadcc081f7..2e63dea73e9 100644
--- a/sound/soc/blackfin/bf5xx-sport.h
+++ b/sound/soc/blackfin/bf5xx-sport.h
@@ -116,7 +116,7 @@ struct sport_device {
void *err_data;
unsigned char *tx_dma_buf;
unsigned char *rx_dma_buf;
-#ifdef CONFIG_SND_MMAP_SUPPORT
+#ifdef CONFIG_SND_BF5XX_MMAP_SUPPORT
dma_addr_t tx_dma_phy;
dma_addr_t rx_dma_phy;
int tx_pos;/*pcm sample count*/
diff --git a/sound/soc/blackfin/bf5xx-ssm2602.c b/sound/soc/blackfin/bf5xx-ssm2602.c
index e15f67fd776..bc0cdded711 100644
--- a/sound/soc/blackfin/bf5xx-ssm2602.c
+++ b/sound/soc/blackfin/bf5xx-ssm2602.c
@@ -44,7 +44,7 @@
#include "bf5xx-i2s-pcm.h"
#include "bf5xx-i2s.h"
-static struct snd_soc_machine bf5xx_ssm2602;
+static struct snd_soc_card bf5xx_ssm2602;
static int bf5xx_ssm2602_startup(struct snd_pcm_substream *substream)
{
@@ -92,17 +92,17 @@ static int bf5xx_ssm2602_hw_params(struct snd_pcm_substream *substream,
*/
/* set codec DAI configuration */
- ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
+ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
if (ret < 0)
return ret;
/* set cpu DAI configuration */
- ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
+ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
if (ret < 0)
return ret;
- ret = codec_dai->dai_ops.set_sysclk(codec_dai, SSM2602_SYSCLK, clk,
+ ret = snd_soc_dai_set_sysclk(codec_dai, SSM2602_SYSCLK, clk,
SND_SOC_CLOCK_IN);
if (ret < 0)
return ret;
@@ -135,15 +135,15 @@ static struct ssm2602_setup_data bf5xx_ssm2602_setup = {
.i2c_address = 0x1b,
};
-static struct snd_soc_machine bf5xx_ssm2602 = {
+static struct snd_soc_card bf5xx_ssm2602 = {
.name = "bf5xx_ssm2602",
+ .platform = &bf5xx_i2s_soc_platform,
.dai_link = &bf5xx_ssm2602_dai,
.num_links = 1,
};
static struct snd_soc_device bf5xx_ssm2602_snd_devdata = {
- .machine = &bf5xx_ssm2602,
- .platform = &bf5xx_i2s_soc_platform,
+ .card = &bf5xx_ssm2602,
.codec_dev = &soc_codec_dev_ssm2602,
.codec_data = &bf5xx_ssm2602_setup,
};
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 38a0e3b620a..c41289b5f58 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -1,31 +1,40 @@
config SND_SOC_ALL_CODECS
tristate "Build all ASoC CODEC drivers"
- depends on I2C
- select SPI
- select SPI_MASTER
- select SND_SOC_AD73311
- select SND_SOC_AK4535
- select SND_SOC_CS4270
- select SND_SOC_SSM2602
- select SND_SOC_TLV320AIC23
- select SND_SOC_TLV320AIC26
- select SND_SOC_TLV320AIC3X
- select SND_SOC_UDA1380
- select SND_SOC_WM8510
- select SND_SOC_WM8580
- select SND_SOC_WM8731
- select SND_SOC_WM8750
- select SND_SOC_WM8753
- select SND_SOC_WM8900
- select SND_SOC_WM8903
- select SND_SOC_WM8971
- select SND_SOC_WM8990
+ select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS
+ select SND_SOC_AD1980 if SND_SOC_AC97_BUS
+ select SND_SOC_AD73311 if I2C
+ select SND_SOC_AK4535 if I2C
+ select SND_SOC_CS4270 if I2C
+ select SND_SOC_PCM3008
+ select SND_SOC_SSM2602 if I2C
+ select SND_SOC_TLV320AIC23 if I2C
+ select SND_SOC_TLV320AIC26 if SPI_MASTER
+ select SND_SOC_TLV320AIC3X if I2C
+ select SND_SOC_TWL4030 if TWL4030_CORE
+ select SND_SOC_UDA134X
+ select SND_SOC_UDA1380 if I2C
+ select SND_SOC_WM8350 if MFD_WM8350
+ select SND_SOC_WM8510 if (I2C || SPI_MASTER)
+ select SND_SOC_WM8580 if I2C
+ select SND_SOC_WM8728 if (I2C || SPI_MASTER)
+ select SND_SOC_WM8731 if (I2C || SPI_MASTER)
+ select SND_SOC_WM8750 if (I2C || SPI_MASTER)
+ select SND_SOC_WM8753 if (I2C || SPI_MASTER)
+ select SND_SOC_WM8900 if I2C
+ select SND_SOC_WM8903 if I2C
+ select SND_SOC_WM8971 if I2C
+ select SND_SOC_WM8990 if I2C
+ select SND_SOC_WM9712 if SND_SOC_AC97_BUS
+ select SND_SOC_WM9713 if SND_SOC_AC97_BUS
help
Normally ASoC codec drivers are only built if a machine driver which
uses them is also built since they are only usable with a machine
driver. Selecting this option will allow these drivers to be built
without an explicit machine driver for test and development purposes.
+ Support for the bus types used to access the codecs to be built must
+ be selected separately.
+
If unsure select "N".
@@ -60,6 +69,12 @@ config SND_SOC_CS4270_VD33_ERRATA
bool
depends on SND_SOC_CS4270
+config SND_SOC_L3
+ tristate
+
+config SND_SOC_PCM3008
+ tristate
+
config SND_SOC_SSM2602
tristate
@@ -75,15 +90,29 @@ config SND_SOC_TLV320AIC3X
tristate
depends on I2C
+config SND_SOC_TWL4030
+ tristate
+ depends on TWL4030_CORE
+
+config SND_SOC_UDA134X
+ tristate
+ select SND_SOC_L3
+
config SND_SOC_UDA1380
tristate
+config SND_SOC_WM8350
+ tristate
+
config SND_SOC_WM8510
tristate
config SND_SOC_WM8580
tristate
+config SND_SOC_WM8728
+ tristate
+
config SND_SOC_WM8731
tristate
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 90f0a585fc7..c4ddc9aa2bb 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -3,13 +3,19 @@ snd-soc-ad1980-objs := ad1980.o
snd-soc-ad73311-objs := ad73311.o
snd-soc-ak4535-objs := ak4535.o
snd-soc-cs4270-objs := cs4270.o
+snd-soc-l3-objs := l3.o
+snd-soc-pcm3008-objs := pcm3008.o
snd-soc-ssm2602-objs := ssm2602.o
snd-soc-tlv320aic23-objs := tlv320aic23.o
snd-soc-tlv320aic26-objs := tlv320aic26.o
snd-soc-tlv320aic3x-objs := tlv320aic3x.o
+snd-soc-twl4030-objs := twl4030.o
+snd-soc-uda134x-objs := uda134x.o
snd-soc-uda1380-objs := uda1380.o
+snd-soc-wm8350-objs := wm8350.o
snd-soc-wm8510-objs := wm8510.o
snd-soc-wm8580-objs := wm8580.o
+snd-soc-wm8728-objs := wm8728.o
snd-soc-wm8731-objs := wm8731.o
snd-soc-wm8750-objs := wm8750.o
snd-soc-wm8753-objs := wm8753.o
@@ -25,13 +31,19 @@ obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o
obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o
obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o
obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o
+obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o
+obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o
obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o
obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o
obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o
obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o
+obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o
+obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o
obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o
+obj-$(CONFIG_SND_SOC_WM8350) += snd-soc-wm8350.o
obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o
obj-$(CONFIG_SND_SOC_WM8580) += snd-soc-wm8580.o
+obj-$(CONFIG_SND_SOC_WM8728) += snd-soc-wm8728.o
obj-$(CONFIG_SND_SOC_WM8731) += snd-soc-wm8731.o
obj-$(CONFIG_SND_SOC_WM8750) += snd-soc-wm8750.o
obj-$(CONFIG_SND_SOC_WM8753) += snd-soc-wm8753.o
diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c
index bd1ebdc6c86..fb53e6511af 100644
--- a/sound/soc/codecs/ac97.c
+++ b/sound/soc/codecs/ac97.c
@@ -24,7 +24,8 @@
#define AC97_VERSION "0.6"
-static int ac97_prepare(struct snd_pcm_substream *substream)
+static int ac97_prepare(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
@@ -42,7 +43,7 @@ static int ac97_prepare(struct snd_pcm_substream *substream)
struct snd_soc_dai ac97_dai = {
.name = "AC97 HiFi",
- .type = SND_SOC_DAI_AC97,
+ .ac97_control = 1,
.playback = {
.stream_name = "AC97 Playback",
.channels_min = 1,
@@ -113,7 +114,7 @@ static int ac97_soc_probe(struct platform_device *pdev)
if (ret < 0)
goto bus_err;
- ret = snd_soc_register_card(socdev);
+ ret = snd_soc_init_card(socdev);
if (ret < 0)
goto bus_err;
return 0;
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c
index 1397b8e06c0..73fdbb4d4a3 100644
--- a/sound/soc/codecs/ad1980.c
+++ b/sound/soc/codecs/ad1980.c
@@ -85,6 +85,9 @@ SOC_DOUBLE("Line HP Swap Switch", AC97_AD_MISC, 10, 5, 1, 0),
SOC_DOUBLE("Surround Playback Volume", AC97_SURROUND_MASTER, 8, 0, 31, 1),
SOC_DOUBLE("Surround Playback Switch", AC97_SURROUND_MASTER, 15, 7, 1, 1),
+SOC_DOUBLE("Center/LFE Playback Volume", AC97_CENTER_LFE_MASTER, 8, 0, 31, 1),
+SOC_DOUBLE("Center/LFE Playback Switch", AC97_CENTER_LFE_MASTER, 15, 7, 1, 1),
+
SOC_ENUM("Capture Source", ad1980_cap_src),
SOC_SINGLE("Mic Boost Switch", AC97_MIC, 6, 1, 0),
@@ -142,10 +145,11 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
struct snd_soc_dai ad1980_dai = {
.name = "AC97",
+ .ac97_control = 1,
.playback = {
.stream_name = "Playback",
.channels_min = 2,
- .channels_max = 2,
+ .channels_max = 6,
.rates = SNDRV_PCM_RATE_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE, },
.capture = {
@@ -192,6 +196,7 @@ static int ad1980_soc_probe(struct platform_device *pdev)
struct snd_soc_codec *codec;
int ret = 0;
u16 vendor_id2;
+ u16 ext_status;
printk(KERN_INFO "AD1980 SoC Audio Codec\n");
@@ -234,7 +239,7 @@ static int ad1980_soc_probe(struct platform_device *pdev)
ret = ad1980_reset(codec, 0);
if (ret < 0) {
- printk(KERN_ERR "AC97 link error\n");
+ printk(KERN_ERR "Failed to reset AD1980: AC97 link error\n");
goto reset_err;
}
@@ -253,12 +258,19 @@ static int ad1980_soc_probe(struct platform_device *pdev)
"supported\n");
}
- ac97_write(codec, AC97_MASTER, 0x0000); /* unmute line out volume */
- ac97_write(codec, AC97_PCM, 0x0000); /* unmute PCM out volume */
- ac97_write(codec, AC97_REC_GAIN, 0x0000);/* unmute record volume */
+ /* unmute captures and playbacks volume */
+ ac97_write(codec, AC97_MASTER, 0x0000);
+ ac97_write(codec, AC97_PCM, 0x0000);
+ ac97_write(codec, AC97_REC_GAIN, 0x0000);
+ ac97_write(codec, AC97_CENTER_LFE_MASTER, 0x0000);
+ ac97_write(codec, AC97_SURROUND_MASTER, 0x0000);
+
+ /*power on LFE/CENTER/Surround DACs*/
+ ext_status = ac97_read(codec, AC97_EXTENDED_STATUS);
+ ac97_write(codec, AC97_EXTENDED_STATUS, ext_status&~0x3800);
ad1980_add_controls(codec);
- ret = snd_soc_register_card(socdev);
+ ret = snd_soc_init_card(socdev);
if (ret < 0) {
printk(KERN_ERR "ad1980: failed to register card\n");
goto reset_err;
diff --git a/sound/soc/codecs/ad73311.c b/sound/soc/codecs/ad73311.c
index 37af8607b00..b09289a1e55 100644
--- a/sound/soc/codecs/ad73311.c
+++ b/sound/soc/codecs/ad73311.c
@@ -8,14 +8,10 @@
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
- *
- * Revision history
- * 25th Sep 2008 Initial version.
*/
#include <linux/init.h>
#include <linux/module.h>
-#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <sound/core.h>
@@ -68,7 +64,7 @@ static int ad73311_soc_probe(struct platform_device *pdev)
goto pcm_err;
}
- ret = snd_soc_register_card(socdev);
+ ret = snd_soc_init_card(socdev);
if (ret < 0) {
printk(KERN_ERR "ad73311: failed to register card\n");
goto register_err;
@@ -102,6 +98,18 @@ struct snd_soc_codec_device soc_codec_dev_ad73311 = {
};
EXPORT_SYMBOL_GPL(soc_codec_dev_ad73311);
+static int __init ad73311_init(void)
+{
+ return snd_soc_register_dai(&ad73311_dai);
+}
+module_init(ad73311_init);
+
+static void __exit ad73311_exit(void)
+{
+ snd_soc_unregister_dai(&ad73311_dai);
+}
+module_exit(ad73311_exit);
+
MODULE_DESCRIPTION("ASoC ad73311 driver");
MODULE_AUTHOR("Cliff Cai ");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c
index 2a89b5888e1..81300d8d42c 100644
--- a/sound/soc/codecs/ak4535.c
+++ b/sound/soc/codecs/ak4535.c
@@ -339,7 +339,8 @@ static int ak4535_set_dai_sysclk(struct snd_soc_dai *codec_dai,
}
static int ak4535_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
@@ -451,8 +452,6 @@ struct snd_soc_dai ak4535_dai = {
.formats = SNDRV_PCM_FMTBIT_S16_LE,},
.ops = {
.hw_params = ak4535_hw_params,
- },
- .dai_ops = {
.set_fmt = ak4535_set_dai_fmt,
.digital_mute = ak4535_mute,
.set_sysclk = ak4535_set_dai_sysclk,
@@ -513,7 +512,7 @@ static int ak4535_init(struct snd_soc_device *socdev)
ak4535_add_controls(codec);
ak4535_add_widgets(codec);
- ret = snd_soc_register_card(socdev);
+ ret = snd_soc_init_card(socdev);
if (ret < 0) {
printk(KERN_ERR "ak4535: failed to register card\n");
goto card_err;
@@ -689,6 +688,18 @@ struct snd_soc_codec_device soc_codec_dev_ak4535 = {
};
EXPORT_SYMBOL_GPL(soc_codec_dev_ak4535);
+static int __init ak4535_modinit(void)
+{
+ return snd_soc_register_dai(&ak4535_dai);
+}
+module_init(ak4535_modinit);
+
+static void __exit ak4535_exit(void)
+{
+ snd_soc_unregister_dai(&ak4535_dai);
+}
+module_exit(ak4535_exit);
+
MODULE_DESCRIPTION("Soc AK4535 driver");
MODULE_AUTHOR("Richard Purdie");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c
index 0bbd94501d7..f1aa0c34421 100644
--- a/sound/soc/codecs/cs4270.c
+++ b/sound/soc/codecs/cs4270.c
@@ -360,13 +360,14 @@ static int cs4270_i2c_write(struct snd_soc_codec *codec, unsigned int reg,
/*
* Program the CS4270 with the given hardware parameters.
*
- * The .dai_ops functions are used to provide board-specific data, like
+ * The .ops functions are used to provide board-specific data, like
* input frequencies, to this driver. This function takes that information,
* combines it with the hardware parameters provided, and programs the
* hardware accordingly.
*/
static int cs4270_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
@@ -450,6 +451,19 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream,
return ret;
}
+ /* Disable automatic volume control. It's enabled by default, and
+ * it causes volume change commands to be delayed, sometimes until
+ * after playback has started.
+ */
+
+ reg = cs4270_read_reg_cache(codec, CS4270_TRANS);
+ reg &= ~(CS4270_TRANS_SOFT | CS4270_TRANS_ZERO);
+ ret = cs4270_i2c_write(codec, CS4270_TRANS, reg);
+ if (ret < 0) {
+ printk(KERN_ERR "I2C write failed\n");
+ return ret;
+ }
+
/* Thaw and power-up the codec */
ret = snd_soc_write(codec, CS4270_PWRCTL, 0);
@@ -697,10 +711,10 @@ static int cs4270_probe(struct platform_device *pdev)
if (codec->control_data) {
/* Initialize codec ops */
cs4270_dai.ops.hw_params = cs4270_hw_params;
- cs4270_dai.dai_ops.set_sysclk = cs4270_set_dai_sysclk;
- cs4270_dai.dai_ops.set_fmt = cs4270_set_dai_fmt;
+ cs4270_dai.ops.set_sysclk = cs4270_set_dai_sysclk;
+ cs4270_dai.ops.set_fmt = cs4270_set_dai_fmt;
#ifdef CONFIG_SND_SOC_CS4270_HWMUTE
- cs4270_dai.dai_ops.digital_mute = cs4270_mute;
+ cs4270_dai.ops.digital_mute = cs4270_mute;
#endif
} else
printk(KERN_INFO "cs4270: no I2C device found, "
@@ -709,7 +723,7 @@ static int cs4270_probe(struct platform_device *pdev)
printk(KERN_INFO "cs4270: I2C disabled, using stand-alone mode\n");
#endif
- ret = snd_soc_register_card(socdev);
+ ret = snd_soc_init_card(socdev);
if (ret < 0) {
printk(KERN_ERR "cs4270: failed to register card\n");
goto error_del_driver;
@@ -760,6 +774,18 @@ struct snd_soc_codec_device soc_codec_device_cs4270 = {
};
EXPORT_SYMBOL_GPL(soc_codec_device_cs4270);
+static int __init cs4270_init(void)
+{
+ return snd_soc_register_dai(&cs4270_dai);
+}
+module_init(cs4270_init);
+
+static void __exit cs4270_exit(void)
+{
+ snd_soc_unregister_dai(&cs4270_dai);
+}
+module_exit(cs4270_exit);
+
MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
MODULE_DESCRIPTION("Cirrus Logic CS4270 ALSA SoC Codec Driver");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/l3.c b/sound/soc/codecs/l3.c
new file mode 100644
index 00000000000..5353af58862
--- /dev/null
+++ b/sound/soc/codecs/l3.c
@@ -0,0 +1,91 @@
+/*
+ * L3 code
+ *
+ * Copyright (C) 2008, Christian Pellegrin <chripell@evolware.org>
+ *
+ * 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.
+ *
+ *
+ * based on:
+ *
+ * L3 bus algorithm module.
+ *
+ * Copyright (C) 2001 Russell King, All Rights Reserved.
+ *
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+
+#include <sound/l3.h>
+
+/*
+ * Send one byte of data to the chip. Data is latched into the chip on
+ * the rising edge of the clock.
+ */
+static void sendbyte(struct l3_pins *adap, unsigned int byte)
+{
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ adap->setclk(0);
+ udelay(adap->data_hold);
+ adap->setdat(byte & 1);
+ udelay(adap->data_setup);
+ adap->setclk(1);
+ udelay(adap->clock_high);
+ byte >>= 1;
+ }
+}
+
+/*
+ * Send a set of bytes to the chip. We need to pulse the MODE line
+ * between each byte, but never at the start nor at the end of the
+ * transfer.
+ */
+static void sendbytes(struct l3_pins *adap, const u8 *buf,
+ int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++) {
+ if (i) {
+ udelay(adap->mode_hold);
+ adap->setmode(0);
+ udelay(adap->mode);
+ }
+ adap->setmode(1);
+ udelay(adap->mode_setup);
+ sendbyte(adap, buf[i]);
+ }
+}
+
+int l3_write(struct l3_pins *adap, u8 addr, u8 *data, int len)
+{
+ adap->setclk(1);
+ adap->setdat(1);
+ adap->setmode(1);
+ udelay(adap->mode);
+
+ adap->setmode(0);
+ udelay(adap->mode_setup);
+ sendbyte(adap, addr);
+ udelay(adap->mode_hold);
+
+ sendbytes(adap, data, len);
+
+ adap->setclk(1);
+ adap->setdat(1);
+ adap->setmode(0);
+
+ return len;
+}
+EXPORT_SYMBOL_GPL(l3_write);
+
+MODULE_DESCRIPTION("L3 bit-banging driver");
+MODULE_AUTHOR("Christian Pellegrin <chripell@evolware.org>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/pcm3008.c b/sound/soc/codecs/pcm3008.c
new file mode 100644
index 00000000000..9a3e67e5319
--- /dev/null
+++ b/sound/soc/codecs/pcm3008.c
@@ -0,0 +1,212 @@
+/*
+ * ALSA Soc PCM3008 codec support
+ *
+ * Author: Hugo Villeneuve
+ * Copyright (C) 2008 Lyrtech inc
+ *
+ * Based on AC97 Soc codec, original copyright follow:
+ * Copyright 2005 Wolfson Microelectronics PLC.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * Generic PCM3008 support.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/gpio.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+
+#include "pcm3008.h"
+
+#define PCM3008_VERSION "0.2"
+
+#define PCM3008_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
+ SNDRV_PCM_RATE_48000)
+
+struct snd_soc_dai pcm3008_dai = {
+ .name = "PCM3008 HiFi",
+ .playback = {
+ .stream_name = "PCM3008 Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = PCM3008_RATES,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ },
+ .capture = {
+ .stream_name = "PCM3008 Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = PCM3008_RATES,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ },
+};
+EXPORT_SYMBOL_GPL(pcm3008_dai);
+
+static void pcm3008_gpio_free(struct pcm3008_setup_data *setup)
+{
+ gpio_free(setup->dem0_pin);
+ gpio_free(setup->dem1_pin);
+ gpio_free(setup->pdad_pin);
+ gpio_free(setup->pdda_pin);
+}
+
+static int pcm3008_soc_probe(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec;
+ struct pcm3008_setup_data *setup = socdev->codec_data;
+ int ret = 0;
+
+ printk(KERN_INFO "PCM3008 SoC Audio Codec %s\n", PCM3008_VERSION);
+
+ socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
+ if (!socdev->codec)
+ return -ENOMEM;
+
+ codec = socdev->codec;
+ mutex_init(&codec->mutex);
+
+ codec->name = "PCM3008";
+ codec->owner = THIS_MODULE;
+ codec->dai = &pcm3008_dai;
+ codec->num_dai = 1;
+ codec->write = NULL;
+ codec->read = NULL;
+ INIT_LIST_HEAD(&codec->dapm_widgets);
+ INIT_LIST_HEAD(&codec->dapm_paths);
+
+ /* Register PCMs. */
+ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+ if (ret < 0) {
+ printk(KERN_ERR "pcm3008: failed to create pcms\n");
+ goto pcm_err;
+ }
+
+ /* Register Card. */
+ ret = snd_soc_init_card(socdev);
+ if (ret < 0) {
+ printk(KERN_ERR "pcm3008: failed to register card\n");
+ goto card_err;
+ }
+
+ /* DEM1 DEM0 DE-EMPHASIS_MODE
+ * Low Low De-emphasis 44.1 kHz ON
+ * Low High De-emphasis OFF
+ * High Low De-emphasis 48 kHz ON
+ * High High De-emphasis 32 kHz ON
+ */
+
+ /* Configure DEM0 GPIO (turning OFF DAC De-emphasis). */
+ ret = gpio_request(setup->dem0_pin, "codec_dem0");
+ if (ret == 0)
+ ret = gpio_direction_output(setup->dem0_pin, 1);
+ if (ret != 0)
+ goto gpio_err;
+
+ /* Configure DEM1 GPIO (turning OFF DAC De-emphasis). */
+ ret = gpio_request(setup->dem1_pin, "codec_dem1");
+ if (ret == 0)
+ ret = gpio_direction_output(setup->dem1_pin, 0);
+ if (ret != 0)
+ goto gpio_err;
+
+ /* Configure PDAD GPIO. */
+ ret = gpio_request(setup->pdad_pin, "codec_pdad");
+ if (ret == 0)
+ ret = gpio_direction_output(setup->pdad_pin, 1);
+ if (ret != 0)
+ goto gpio_err;
+
+ /* Configure PDDA GPIO. */
+ ret = gpio_request(setup->pdda_pin, "codec_pdda");
+ if (ret == 0)
+ ret = gpio_direction_output(setup->pdda_pin, 1);
+ if (ret != 0)
+ goto gpio_err;
+
+ return ret;
+
+gpio_err:
+ pcm3008_gpio_free(setup);
+card_err:
+ snd_soc_free_pcms(socdev);
+pcm_err:
+ kfree(socdev->codec);
+
+ return ret;
+}
+
+static int pcm3008_soc_remove(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec = socdev->codec;
+ struct pcm3008_setup_data *setup = socdev->codec_data;
+
+ if (!codec)
+ return 0;
+
+ pcm3008_gpio_free(setup);
+ snd_soc_free_pcms(socdev);
+ kfree(socdev->codec);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int pcm3008_soc_suspend(struct platform_device *pdev, pm_message_t msg)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct pcm3008_setup_data *setup = socdev->codec_data;
+
+ gpio_set_value(setup->pdad_pin, 0);
+ gpio_set_value(setup->pdda_pin, 0);
+
+ return 0;
+}
+
+static int pcm3008_soc_resume(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct pcm3008_setup_data *setup = socdev->codec_data;
+
+ gpio_set_value(setup->pdad_pin, 1);
+ gpio_set_value(setup->pdda_pin, 1);
+
+ return 0;
+}
+#else
+#define pcm3008_soc_suspend NULL
+#define pcm3008_soc_resume NULL
+#endif
+
+struct snd_soc_codec_device soc_codec_dev_pcm3008 = {
+ .probe = pcm3008_soc_probe,
+ .remove = pcm3008_soc_remove,
+ .suspend = pcm3008_soc_suspend,
+ .resume = pcm3008_soc_resume,
+};
+EXPORT_SYMBOL_GPL(soc_codec_dev_pcm3008);
+
+static int __init pcm3008_init(void)
+{
+ return snd_soc_register_dai(&pcm3008_dai);
+}
+module_init(pcm3008_init);
+
+static void __exit pcm3008_exit(void)
+{
+ snd_soc_unregister_dai(&pcm3008_dai);
+}
+module_exit(pcm3008_exit);
+
+MODULE_DESCRIPTION("Soc PCM3008 driver");
+MODULE_AUTHOR("Hugo Villeneuve");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/pcm3008.h b/sound/soc/codecs/pcm3008.h
new file mode 100644
index 00000000000..d04e87d3c06
--- /dev/null
+++ b/sound/soc/codecs/pcm3008.h
@@ -0,0 +1,25 @@
+/*
+ * PCM3008 ALSA SoC Layer
+ *
+ * Author: Hugo Villeneuve
+ * Copyright (C) 2008 Lyrtech inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_SND_SOC_PCM3008_H
+#define __LINUX_SND_SOC_PCM3008_H
+
+struct pcm3008_setup_data {
+ unsigned dem0_pin;
+ unsigned dem1_pin;
+ unsigned pdad_pin;
+ unsigned pdda_pin;
+};
+
+extern struct snd_soc_codec_device soc_codec_dev_pcm3008;
+extern struct snd_soc_dai pcm3008_dai;
+
+#endif
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c
index 44ef0dacd56..cac37361676 100644
--- a/sound/soc/codecs/ssm2602.c
+++ b/sound/soc/codecs/ssm2602.c
@@ -285,16 +285,23 @@ static inline int get_coeff(int mclk, int rate)
}
static int ssm2602_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
u16 srate;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->codec;
struct ssm2602_priv *ssm2602 = codec->private_data;
+ struct i2c_client *i2c = codec->control_data;
u16 iface = ssm2602_read_reg_cache(codec, SSM2602_IFACE) & 0xfff3;
int i = get_coeff(ssm2602->sysclk, params_rate(params));
+ if (substream == ssm2602->slave_substream) {
+ dev_dbg(&i2c->dev, "Ignoring hw_params for slave substream\n");
+ return 0;
+ }
+
/*no match is found*/
if (i == ARRAY_SIZE(coeff_div))
return -EINVAL;
@@ -324,19 +331,26 @@ static int ssm2602_hw_params(struct snd_pcm_substream *substream,
return 0;
}
-static int ssm2602_startup(struct snd_pcm_substream *substream)
+static int ssm2602_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->codec;
struct ssm2602_priv *ssm2602 = codec->private_data;
+ struct i2c_client *i2c = codec->control_data;
struct snd_pcm_runtime *master_runtime;
/* The DAI has shared clocks so if we already have a playback or
* capture going then constrain this substream to match it.
+ * TODO: the ssm2602 allows pairs of non-matching PB/REC rates
*/
if (ssm2602->master_substream) {
master_runtime = ssm2602->master_substream->runtime;
+ dev_dbg(&i2c->dev, "Constraining to %d bits at %dHz\n",
+ master_runtime->sample_bits,
+ master_runtime->rate);
+
snd_pcm_hw_constraint_minmax(substream->runtime,
SNDRV_PCM_HW_PARAM_RATE,
master_runtime->rate,
@@ -354,7 +368,8 @@ static int ssm2602_startup(struct snd_pcm_substream *substream)
return 0;
}
-static int ssm2602_pcm_prepare(struct snd_pcm_substream *substream)
+static int ssm2602_pcm_prepare(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
@@ -365,14 +380,21 @@ static int ssm2602_pcm_prepare(struct snd_pcm_substream *substream)
return 0;
}
-static void ssm2602_shutdown(struct snd_pcm_substream *substream)
+static void ssm2602_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->codec;
+ struct ssm2602_priv *ssm2602 = codec->private_data;
/* deactivate */
if (!codec->active)
ssm2602_write(codec, SSM2602_ACTIVE, 0);
+
+ if (ssm2602->master_substream == substream)
+ ssm2602->master_substream = ssm2602->slave_substream;
+
+ ssm2602->slave_substream = NULL;
}
static int ssm2602_mute(struct snd_soc_dai *dai, int mute)
@@ -432,10 +454,10 @@ static int ssm2602_set_dai_fmt(struct snd_soc_dai *codec_dai,
iface |= 0x0001;
break;
case SND_SOC_DAIFMT_DSP_A:
- iface |= 0x0003;
+ iface |= 0x0013;
break;
case SND_SOC_DAIFMT_DSP_B:
- iface |= 0x0013;
+ iface |= 0x0003;
break;
default:
return -EINVAL;
@@ -496,6 +518,9 @@ static int ssm2602_set_bias_level(struct snd_soc_codec *codec,
SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\
SNDRV_PCM_RATE_96000)
+#define SSM2602_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
+
struct snd_soc_dai ssm2602_dai = {
.name = "SSM2602",
.playback = {
@@ -503,20 +528,18 @@ struct snd_soc_dai ssm2602_dai = {
.channels_min = 2,
.channels_max = 2,
.rates = SSM2602_RATES,
- .formats = SNDRV_PCM_FMTBIT_S32_LE,},
+ .formats = SSM2602_FORMATS,},
.capture = {
.stream_name = "Capture",
.channels_min = 2,
.channels_max = 2,
.rates = SSM2602_RATES,
- .formats = SNDRV_PCM_FMTBIT_S32_LE,},
+ .formats = SSM2602_FORMATS,},
.ops = {
.startup = ssm2602_startup,
.prepare = ssm2602_pcm_prepare,
.hw_params = ssm2602_hw_params,
.shutdown = ssm2602_shutdown,
- },
- .dai_ops = {
.digital_mute = ssm2602_mute,
.set_sysclk = ssm2602_set_dai_sysclk,
.set_fmt = ssm2602_set_dai_fmt,
@@ -601,7 +624,7 @@ static int ssm2602_init(struct snd_soc_device *socdev)
ssm2602_add_controls(codec);
ssm2602_add_widgets(codec);
- ret = snd_soc_register_card(socdev);
+ ret = snd_soc_init_card(socdev);
if (ret < 0) {
pr_err("ssm2602: failed to register card\n");
goto card_err;
@@ -770,6 +793,18 @@ struct snd_soc_codec_device soc_codec_dev_ssm2602 = {
};
EXPORT_SYMBOL_GPL(soc_codec_dev_ssm2602);
+static int __init ssm2602_modinit(void)
+{
+ return snd_soc_register_dai(&ssm2602_dai);
+}
+module_init(ssm2602_modinit);
+
+static void __exit ssm2602_exit(void)
+{
+ snd_soc_unregister_dai(&ssm2602_dai);
+}
+module_exit(ssm2602_exit);
+
MODULE_DESCRIPTION("ASoC ssm2602 driver");
MODULE_AUTHOR("Cliff Cai");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c
index 44308dac9e1..cfdea007c4c 100644
--- a/sound/soc/codecs/tlv320aic23.c
+++ b/sound/soc/codecs/tlv320aic23.c
@@ -37,12 +37,6 @@
#define AIC23_VERSION "0.1"
-struct tlv320aic23_srate_reg_info {
- u32 sample_rate;
- u8 control; /* SR3, SR2, SR1, SR0 and BOSR */
- u8 divider; /* if 0 CLKIN = MCLK, if 1 CLKIN = MCLK/2 */
-};
-
/*
* AIC23 register cache
*/
@@ -261,20 +255,156 @@ static const struct snd_soc_dapm_route intercon[] = {
};
-/* tlv320aic23 related */
-static const struct tlv320aic23_srate_reg_info srate_reg_info[] = {
- {4000, 0x06, 1}, /* 4000 */
- {8000, 0x06, 0}, /* 8000 */
- {16000, 0x0C, 1}, /* 16000 */
- {22050, 0x11, 1}, /* 22050 */
- {24000, 0x00, 1}, /* 24000 */
- {32000, 0x0C, 0}, /* 32000 */
- {44100, 0x11, 0}, /* 44100 */
- {48000, 0x00, 0}, /* 48000 */
- {88200, 0x1F, 0}, /* 88200 */
- {96000, 0x0E, 0}, /* 96000 */
+/* AIC23 driver data */
+struct aic23 {
+ struct snd_soc_codec codec;
+ int mclk;
+ int requested_adc;
+ int requested_dac;
+};
+
+/*
+ * Common Crystals used
+ * 11.2896 Mhz /128 = *88.2k /192 = 58.8k
+ * 12.0000 Mhz /125 = *96k /136 = 88.235K
+ * 12.2880 Mhz /128 = *96k /192 = 64k
+ * 16.9344 Mhz /128 = 132.3k /192 = *88.2k
+ * 18.4320 Mhz /128 = 144k /192 = *96k
+ */
+
+/*
+ * Normal BOSR 0-256/2 = 128, 1-384/2 = 192
+ * USB BOSR 0-250/2 = 125, 1-272/2 = 136
+ */
+static const int bosr_usb_divisor_table[] = {
+ 128, 125, 192, 136
+};
+#define LOWER_GROUP ((1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<6) | (1<<7))
+#define UPPER_GROUP ((1<<8) | (1<<9) | (1<<10) | (1<<11) | (1<<15))
+static const unsigned short sr_valid_mask[] = {
+ LOWER_GROUP|UPPER_GROUP, /* Normal, bosr - 0*/
+ LOWER_GROUP|UPPER_GROUP, /* Normal, bosr - 1*/
+ LOWER_GROUP, /* Usb, bosr - 0*/
+ UPPER_GROUP, /* Usb, bosr - 1*/
+};
+/*
+ * Every divisor is a factor of 11*12
+ */
+#define SR_MULT (11*12)
+#define A(x) (x) ? (SR_MULT/x) : 0
+static const unsigned char sr_adc_mult_table[] = {
+ A(2), A(2), A(12), A(12), A(0), A(0), A(3), A(1),
+ A(2), A(2), A(11), A(11), A(0), A(0), A(0), A(1)
+};
+static const unsigned char sr_dac_mult_table[] = {
+ A(2), A(12), A(2), A(12), A(0), A(0), A(3), A(1),
+ A(2), A(11), A(2), A(11), A(0), A(0), A(0), A(1)
};
+static unsigned get_score(int adc, int adc_l, int adc_h, int need_adc,
+ int dac, int dac_l, int dac_h, int need_dac)
+{
+ if ((adc >= adc_l) && (adc <= adc_h) &&
+ (dac >= dac_l) && (dac <= dac_h)) {
+ int diff_adc = need_adc - adc;
+ int diff_dac = need_dac - dac;
+ return abs(diff_adc) + abs(diff_dac);
+ }
+ return UINT_MAX;
+}
+
+static int find_rate(int mclk, u32 need_adc, u32 need_dac)
+{
+ int i, j;
+ int best_i = -1;
+ int best_j = -1;
+ int best_div = 0;
+ unsigned best_score = UINT_MAX;
+ int adc_l, adc_h, dac_l, dac_h;
+
+ need_adc *= SR_MULT;
+ need_dac *= SR_MULT;
+ /*
+ * rates given are +/- 1/32
+ */
+ adc_l = need_adc - (need_adc >> 5);
+ adc_h = need_adc + (need_adc >> 5);
+ dac_l = need_dac - (need_dac >> 5);
+ dac_h = need_dac + (need_dac >> 5);
+ for (i = 0; i < ARRAY_SIZE(bosr_usb_divisor_table); i++) {
+ int base = mclk / bosr_usb_divisor_table[i];
+ int mask = sr_valid_mask[i];
+ for (j = 0; j < ARRAY_SIZE(sr_adc_mult_table);
+ j++, mask >>= 1) {
+ int adc;
+ int dac;
+ int score;
+ if ((mask & 1) == 0)
+ continue;
+ adc = base * sr_adc_mult_table[j];
+ dac = base * sr_dac_mult_table[j];
+ score = get_score(adc, adc_l, adc_h, need_adc,
+ dac, dac_l, dac_h, need_dac);
+ if (best_score > score) {
+ best_score = score;
+ best_i = i;
+ best_j = j;
+ best_div = 0;
+ }
+ score = get_score((adc >> 1), adc_l, adc_h, need_adc,
+ (dac >> 1), dac_l, dac_h, need_dac);
+ /* prefer to have a /2 */
+ if ((score != UINT_MAX) && (best_score >= score)) {
+ best_score = score;
+ best_i = i;
+ best_j = j;
+ best_div = 1;
+ }
+ }
+ }
+ return (best_j << 2) | best_i | (best_div << TLV320AIC23_CLKIN_SHIFT);
+}
+
+#ifdef DEBUG
+static void get_current_sample_rates(struct snd_soc_codec *codec, int mclk,
+ u32 *sample_rate_adc, u32 *sample_rate_dac)
+{
+ int src = tlv320aic23_read_reg_cache(codec, TLV320AIC23_SRATE);
+ int sr = (src >> 2) & 0x0f;
+ int val = (mclk / bosr_usb_divisor_table[src & 3]);
+ int adc = (val * sr_adc_mult_table[sr]) / SR_MULT;
+ int dac = (val * sr_dac_mult_table[sr]) / SR_MULT;
+ if (src & TLV320AIC23_CLKIN_HALF) {
+ adc >>= 1;
+ dac >>= 1;
+ }
+ *sample_rate_adc = adc;
+ *sample_rate_dac = dac;
+}
+#endif
+
+static int set_sample_rate_control(struct snd_soc_codec *codec, int mclk,
+ u32 sample_rate_adc, u32 sample_rate_dac)
+{
+ /* Search for the right sample rate */
+ int data = find_rate(mclk, sample_rate_adc, sample_rate_dac);
+ if (data < 0) {
+ printk(KERN_ERR "%s:Invalid rate %u,%u requested\n",
+ __func__, sample_rate_adc, sample_rate_dac);
+ return -EINVAL;
+ }
+ tlv320aic23_write(codec, TLV320AIC23_SRATE, data);
+#ifdef DEBUG
+ {
+ u32 adc, dac;
+ get_current_sample_rates(codec, mclk, &adc, &dac);
+ printk(KERN_DEBUG "actual samplerate = %u,%u reg=%x\n",
+ adc, dac, data);
+ }
+#endif
+ return 0;
+}
+
static int tlv320aic23_add_widgets(struct snd_soc_codec *codec)
{
snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets,
@@ -288,32 +418,36 @@ static int tlv320aic23_add_widgets(struct snd_soc_codec *codec)
}
static int tlv320aic23_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->codec;
- u16 iface_reg, data;
- u8 count = 0;
+ u16 iface_reg;
+ int ret;
+ struct aic23 *aic23 = container_of(codec, struct aic23, codec);
+ u32 sample_rate_adc = aic23->requested_adc;
+ u32 sample_rate_dac = aic23->requested_dac;
+ u32 sample_rate = params_rate(params);
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ aic23->requested_dac = sample_rate_dac = sample_rate;
+ if (!sample_rate_adc)
+ sample_rate_adc = sample_rate;
+ } else {
+ aic23->requested_adc = sample_rate_adc = sample_rate;
+ if (!sample_rate_dac)
+ sample_rate_dac = sample_rate;
+ }
+ ret = set_sample_rate_control(codec, aic23->mclk, sample_rate_adc,
+ sample_rate_dac);
+ if (ret < 0)
+ return ret;
iface_reg =
tlv320aic23_read_reg_cache(codec,
TLV320AIC23_DIGT_FMT) & ~(0x03 << 2);
-
- /* Search for the right sample rate */
- /* Verify what happens if the rate is not supported
- * now it goes to 96Khz */
- while ((srate_reg_info[count].sample_rate != params_rate(params)) &&
- (count < ARRAY_SIZE(srate_reg_info))) {
- count++;
- }
-
- data = (srate_reg_info[count].divider << TLV320AIC23_CLKIN_SHIFT) |
- (srate_reg_info[count]. control << TLV320AIC23_BOSR_SHIFT) |
- TLV320AIC23_USB_CLK_ON;
-
- tlv320aic23_write(codec, TLV320AIC23_SRATE, data);
-
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
break;
@@ -332,7 +466,8 @@ static int tlv320aic23_hw_params(struct snd_pcm_substream *substream,
return 0;
}
-static int tlv320aic23_pcm_prepare(struct snd_pcm_substream *substream)
+static int tlv320aic23_pcm_prepare(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
@@ -344,17 +479,23 @@ static int tlv320aic23_pcm_prepare(struct snd_pcm_substream *substream)
return 0;
}
-static void tlv320aic23_shutdown(struct snd_pcm_substream *substream)
+static void tlv320aic23_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->codec;
+ struct aic23 *aic23 = container_of(codec, struct aic23, codec);
/* deactivate */
if (!codec->active) {
udelay(50);
tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0);
}
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ aic23->requested_dac = 0;
+ else
+ aic23->requested_adc = 0;
}
static int tlv320aic23_mute(struct snd_soc_dai *dai, int mute)
@@ -400,7 +541,7 @@ static int tlv320aic23_set_dai_fmt(struct snd_soc_dai *codec_dai,
case SND_SOC_DAIFMT_I2S:
iface_reg |= TLV320AIC23_FOR_I2S;
break;
- case SND_SOC_DAIFMT_DSP_A:
+ case SND_SOC_DAIFMT_DSP_B:
iface_reg |= TLV320AIC23_FOR_DSP;
break;
case SND_SOC_DAIFMT_RIGHT_J:
@@ -422,12 +563,9 @@ static int tlv320aic23_set_dai_sysclk(struct snd_soc_dai *codec_dai,
int clk_id, unsigned int freq, int dir)
{
struct snd_soc_codec *codec = codec_dai->codec;
-
- switch (freq) {
- case 12000000:
- return 0;
- }
- return -EINVAL;
+ struct aic23 *aic23 = container_of(codec, struct aic23, codec);
+ aic23->mclk = freq;
+ return 0;
}
static int tlv320aic23_set_bias_level(struct snd_soc_codec *codec,
@@ -478,12 +616,10 @@ struct snd_soc_dai tlv320aic23_dai = {
.prepare = tlv320aic23_pcm_prepare,
.hw_params = tlv320aic23_hw_params,
.shutdown = tlv320aic23_shutdown,
- },
- .dai_ops = {
- .digital_mute = tlv320aic23_mute,
- .set_fmt = tlv320aic23_set_dai_fmt,
- .set_sysclk = tlv320aic23_set_dai_sysclk,
- }
+ .digital_mute = tlv320aic23_mute,
+ .set_fmt = tlv320aic23_set_dai_fmt,
+ .set_sysclk = tlv320aic23_set_dai_sysclk,
+ }
};
EXPORT_SYMBOL_GPL(tlv320aic23_dai);
@@ -584,7 +720,7 @@ static int tlv320aic23_init(struct snd_soc_device *socdev)
tlv320aic23_add_controls(codec);
tlv320aic23_add_widgets(codec);
- ret = snd_soc_register_card(socdev);
+ ret = snd_soc_init_card(socdev);
if (ret < 0) {
printk(KERN_ERR "tlv320aic23: failed to register card\n");
goto card_err;
@@ -659,14 +795,15 @@ static int tlv320aic23_probe(struct platform_device *pdev)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
struct snd_soc_codec *codec;
+ struct aic23 *aic23;
int ret = 0;
printk(KERN_INFO "AIC23 Audio Codec %s\n", AIC23_VERSION);
- codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
- if (codec == NULL)
+ aic23 = kzalloc(sizeof(struct aic23), GFP_KERNEL);
+ if (aic23 == NULL)
return -ENOMEM;
-
+ codec = &aic23->codec;
socdev->codec = codec;
mutex_init(&codec->mutex);
INIT_LIST_HEAD(&codec->dapm_widgets);
@@ -687,6 +824,7 @@ static int tlv320aic23_remove(struct platform_device *pdev)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
struct snd_soc_codec *codec = socdev->codec;
+ struct aic23 *aic23 = container_of(codec, struct aic23, codec);
if (codec->control_data)
tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF);
@@ -697,7 +835,7 @@ static int tlv320aic23_remove(struct platform_device *pdev)
i2c_del_driver(&tlv320aic23_i2c_driver);
#endif
kfree(codec->reg_cache);
- kfree(codec);
+ kfree(aic23);
return 0;
}
@@ -709,6 +847,18 @@ struct snd_soc_codec_device soc_codec_dev_tlv320aic23 = {
};
EXPORT_SYMBOL_GPL(soc_codec_dev_tlv320aic23);
+static int __init tlv320aic23_modinit(void)
+{
+ return snd_soc_register_dai(&tlv320aic23_dai);
+}
+module_init(tlv320aic23_modinit);
+
+static void __exit tlv320aic23_exit(void)
+{
+ snd_soc_unregister_dai(&tlv320aic23_dai);
+}
+module_exit(tlv320aic23_exit);
+
MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver");
MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c
index bed8a9e63dd..29f2f1a017f 100644
--- a/sound/soc/codecs/tlv320aic26.c
+++ b/sound/soc/codecs/tlv320aic26.c
@@ -125,7 +125,8 @@ static int aic26_reg_write(struct snd_soc_codec *codec, unsigned int reg,
* Digital Audio Interface Operations
*/
static int aic26_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
@@ -287,8 +288,6 @@ struct snd_soc_dai aic26_dai = {
},
.ops = {
.hw_params = aic26_hw_params,
- },
- .dai_ops = {
.digital_mute = aic26_mute,
.set_sysclk = aic26_set_sysclk,
.set_fmt = aic26_set_fmt,
@@ -360,7 +359,7 @@ static int aic26_probe(struct platform_device *pdev)
/* CODEC is setup, we can register the card now */
dev_dbg(&pdev->dev, "Registering card\n");
- ret = snd_soc_register_card(socdev);
+ ret = snd_soc_init_card(socdev);
if (ret < 0) {
dev_err(&pdev->dev, "aic26: failed to register card\n");
goto card_err;
@@ -427,7 +426,7 @@ static DEVICE_ATTR(keyclick, 0644, aic26_keyclick_show, aic26_keyclick_set);
static int aic26_spi_probe(struct spi_device *spi)
{
struct aic26 *aic26;
- int rc, i, reg;
+ int ret, i, reg;
dev_dbg(&spi->dev, "probing tlv320aic26 spi device\n");
@@ -457,6 +456,14 @@ static int aic26_spi_probe(struct spi_device *spi)
aic26->codec.reg_cache_size = AIC26_NUM_REGS;
aic26->codec.reg_cache = aic26->reg_cache;
+ aic26_dai.dev = &spi->dev;
+ ret = snd_soc_register_dai(&aic26_dai);
+ if (ret != 0) {
+ dev_err(&spi->dev, "Failed to register DAI: %d\n", ret);
+ kfree(aic26);
+ return ret;
+ }
+
/* Reset the codec to power on defaults */
aic26_reg_write(&aic26->codec, AIC26_REG_RESET, 0xBB00);
@@ -475,8 +482,8 @@ static int aic26_spi_probe(struct spi_device *spi)
/* Register the sysfs files for debugging */
/* Create SysFS files */
- rc = device_create_file(&spi->dev, &dev_attr_keyclick);
- if (rc)
+ ret = device_create_file(&spi->dev, &dev_attr_keyclick);
+ if (ret)
dev_info(&spi->dev, "error creating sysfs files\n");
#if defined(CONFIG_SND_SOC_OF_SIMPLE)
@@ -493,6 +500,7 @@ static int aic26_spi_remove(struct spi_device *spi)
{
struct aic26 *aic26 = dev_get_drvdata(&spi->dev);
+ snd_soc_unregister_dai(&aic26_dai);
kfree(aic26);
return 0;
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index cff276ee261..b47a749c5ea 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -253,11 +253,17 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = {
SOC_DOUBLE_R("Line DAC Playback Volume", DACL1_2_LLOPM_VOL,
DACR1_2_RLOPM_VOL, 0, 0x7f, 1),
- SOC_DOUBLE_R("Line DAC Playback Switch", LLOPM_CTRL, RLOPM_CTRL, 3,
- 0x01, 0),
- SOC_DOUBLE_R("Line PGA Bypass Playback Volume", PGAL_2_LLOPM_VOL,
- PGAR_2_RLOPM_VOL, 0, 0x7f, 1),
- SOC_DOUBLE_R("Line Line2 Bypass Playback Volume", LINE2L_2_LLOPM_VOL,
+ SOC_SINGLE("LineL Playback Switch", LLOPM_CTRL, 3, 0x01, 0),
+ SOC_SINGLE("LineR Playback Switch", RLOPM_CTRL, 3, 0x01, 0),
+ SOC_DOUBLE_R("LineL DAC Playback Volume", DACL1_2_LLOPM_VOL,
+ DACR1_2_LLOPM_VOL, 0, 0x7f, 1),
+ SOC_SINGLE("LineL Left PGA Bypass Playback Volume", PGAL_2_LLOPM_VOL,
+ 0, 0x7f, 1),
+ SOC_SINGLE("LineR Right PGA Bypass Playback Volume", PGAR_2_RLOPM_VOL,
+ 0, 0x7f, 1),
+ SOC_DOUBLE_R("LineL Line2 Bypass Playback Volume", LINE2L_2_LLOPM_VOL,
+ LINE2R_2_LLOPM_VOL, 0, 0x7f, 1),
+ SOC_DOUBLE_R("LineR Line2 Bypass Playback Volume", LINE2L_2_RLOPM_VOL,
LINE2R_2_RLOPM_VOL, 0, 0x7f, 1),
SOC_DOUBLE_R("Mono DAC Playback Volume", DACL1_2_MONOLOPM_VOL,
@@ -272,8 +278,12 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = {
DACR1_2_HPROUT_VOL, 0, 0x7f, 1),
SOC_DOUBLE_R("HP DAC Playback Switch", HPLOUT_CTRL, HPROUT_CTRL, 3,
0x01, 0),
- SOC_DOUBLE_R("HP PGA Bypass Playback Volume", PGAL_2_HPLOUT_VOL,
+ SOC_DOUBLE_R("HP Right PGA Bypass Playback Volume", PGAR_2_HPLOUT_VOL,
PGAR_2_HPROUT_VOL, 0, 0x7f, 1),
+ SOC_SINGLE("HPL PGA Bypass Playback Volume", PGAL_2_HPLOUT_VOL,
+ 0, 0x7f, 1),
+ SOC_SINGLE("HPR PGA Bypass Playback Volume", PGAL_2_HPROUT_VOL,
+ 0, 0x7f, 1),
SOC_DOUBLE_R("HP Line2 Bypass Playback Volume", LINE2L_2_HPLOUT_VOL,
LINE2R_2_HPROUT_VOL, 0, 0x7f, 1),
@@ -281,8 +291,10 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = {
DACR1_2_HPRCOM_VOL, 0, 0x7f, 1),
SOC_DOUBLE_R("HPCOM DAC Playback Switch", HPLCOM_CTRL, HPRCOM_CTRL, 3,
0x01, 0),
- SOC_DOUBLE_R("HPCOM PGA Bypass Playback Volume", PGAL_2_HPLCOM_VOL,
- PGAR_2_HPRCOM_VOL, 0, 0x7f, 1),
+ SOC_SINGLE("HPLCOM PGA Bypass Playback Volume", PGAL_2_HPLCOM_VOL,
+ 0, 0x7f, 1),
+ SOC_SINGLE("HPRCOM PGA Bypass Playback Volume", PGAL_2_HPRCOM_VOL,
+ 0, 0x7f, 1),
SOC_DOUBLE_R("HPCOM Line2 Bypass Playback Volume", LINE2L_2_HPLCOM_VOL,
LINE2R_2_HPRCOM_VOL, 0, 0x7f, 1),
@@ -333,7 +345,8 @@ SOC_DAPM_ENUM("Route", aic3x_enum[RHPCOM_ENUM]);
/* Left DAC_L1 Mixer */
static const struct snd_kcontrol_new aic3x_left_dac_mixer_controls[] = {
- SOC_DAPM_SINGLE("Line Switch", DACL1_2_LLOPM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("LineL Switch", DACL1_2_LLOPM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("LineR Switch", DACL1_2_RLOPM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("Mono Switch", DACL1_2_MONOLOPM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("HP Switch", DACL1_2_HPLOUT_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("HPCOM Switch", DACL1_2_HPLCOM_VOL, 7, 1, 0),
@@ -341,7 +354,8 @@ static const struct snd_kcontrol_new aic3x_left_dac_mixer_controls[] = {
/* Right DAC_R1 Mixer */
static const struct snd_kcontrol_new aic3x_right_dac_mixer_controls[] = {
- SOC_DAPM_SINGLE("Line Switch", DACR1_2_RLOPM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("LineL Switch", DACR1_2_LLOPM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("LineR Switch", DACR1_2_RLOPM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("Mono Switch", DACR1_2_MONOLOPM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("HP Switch", DACR1_2_HPROUT_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("HPCOM Switch", DACR1_2_HPRCOM_VOL, 7, 1, 0),
@@ -350,14 +364,18 @@ static const struct snd_kcontrol_new aic3x_right_dac_mixer_controls[] = {
/* Left PGA Mixer */
static const struct snd_kcontrol_new aic3x_left_pga_mixer_controls[] = {
SOC_DAPM_SINGLE_AIC3X("Line1L Switch", LINE1L_2_LADC_CTRL, 3, 1, 1),
+ SOC_DAPM_SINGLE_AIC3X("Line1R Switch", LINE1R_2_LADC_CTRL, 3, 1, 1),
SOC_DAPM_SINGLE_AIC3X("Line2L Switch", LINE2L_2_LADC_CTRL, 3, 1, 1),
SOC_DAPM_SINGLE_AIC3X("Mic3L Switch", MIC3LR_2_LADC_CTRL, 4, 1, 1),
+ SOC_DAPM_SINGLE_AIC3X("Mic3R Switch", MIC3LR_2_LADC_CTRL, 0, 1, 1),
};
/* Right PGA Mixer */
static const struct snd_kcontrol_new aic3x_right_pga_mixer_controls[] = {
SOC_DAPM_SINGLE_AIC3X("Line1R Switch", LINE1R_2_RADC_CTRL, 3, 1, 1),
+ SOC_DAPM_SINGLE_AIC3X("Line1L Switch", LINE1L_2_RADC_CTRL, 3, 1, 1),
SOC_DAPM_SINGLE_AIC3X("Line2R Switch", LINE2R_2_RADC_CTRL, 3, 1, 1),
+ SOC_DAPM_SINGLE_AIC3X("Mic3L Switch", MIC3LR_2_RADC_CTRL, 4, 1, 1),
SOC_DAPM_SINGLE_AIC3X("Mic3R Switch", MIC3LR_2_RADC_CTRL, 0, 1, 1),
};
@@ -379,34 +397,42 @@ SOC_DAPM_ENUM("Route", aic3x_enum[LINE2R_ENUM]);
/* Left PGA Bypass Mixer */
static const struct snd_kcontrol_new aic3x_left_pga_bp_mixer_controls[] = {
- SOC_DAPM_SINGLE("Line Switch", PGAL_2_LLOPM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("LineL Switch", PGAL_2_LLOPM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("LineR Switch", PGAL_2_RLOPM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("Mono Switch", PGAL_2_MONOLOPM_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("HP Switch", PGAL_2_HPLOUT_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("HPCOM Switch", PGAL_2_HPLCOM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("HPL Switch", PGAL_2_HPLOUT_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("HPR Switch", PGAL_2_HPROUT_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("HPLCOM Switch", PGAL_2_HPLCOM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("HPRCOM Switch", PGAL_2_HPRCOM_VOL, 7, 1, 0),
};
/* Right PGA Bypass Mixer */
static const struct snd_kcontrol_new aic3x_right_pga_bp_mixer_controls[] = {
- SOC_DAPM_SINGLE("Line Switch", PGAR_2_RLOPM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("LineL Switch", PGAR_2_LLOPM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("LineR Switch", PGAR_2_RLOPM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("Mono Switch", PGAR_2_MONOLOPM_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("HP Switch", PGAR_2_HPROUT_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("HPCOM Switch", PGAR_2_HPRCOM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("HPL Switch", PGAR_2_HPLOUT_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("HPR Switch", PGAR_2_HPROUT_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("HPLCOM Switch", PGAR_2_HPLCOM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("HPRCOM Switch", PGAR_2_HPRCOM_VOL, 7, 1, 0),
};
/* Left Line2 Bypass Mixer */
static const struct snd_kcontrol_new aic3x_left_line2_bp_mixer_controls[] = {
- SOC_DAPM_SINGLE("Line Switch", LINE2L_2_LLOPM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("LineL Switch", LINE2L_2_LLOPM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("LineR Switch", LINE2L_2_RLOPM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("Mono Switch", LINE2L_2_MONOLOPM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("HP Switch", LINE2L_2_HPLOUT_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("HPCOM Switch", LINE2L_2_HPLCOM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("HPLCOM Switch", LINE2L_2_HPLCOM_VOL, 7, 1, 0),
};
/* Right Line2 Bypass Mixer */
static const struct snd_kcontrol_new aic3x_right_line2_bp_mixer_controls[] = {
- SOC_DAPM_SINGLE("Line Switch", LINE2R_2_RLOPM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("LineL Switch", LINE2R_2_LLOPM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("LineR Switch", LINE2R_2_RLOPM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("Mono Switch", LINE2R_2_MONOLOPM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("HP Switch", LINE2R_2_HPROUT_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("HPCOM Switch", LINE2R_2_HPRCOM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("HPRCOM Switch", LINE2R_2_HPRCOM_VOL, 7, 1, 0),
};
static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
@@ -439,22 +465,26 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
/* Mono Output */
SND_SOC_DAPM_PGA("Mono Out", MONOLOPM_CTRL, 0, 0, NULL, 0),
- /* Left Inputs to Left ADC */
+ /* Inputs to Left ADC */
SND_SOC_DAPM_ADC("Left ADC", "Left Capture", LINE1L_2_LADC_CTRL, 2, 0),
SND_SOC_DAPM_MIXER("Left PGA Mixer", SND_SOC_NOPM, 0, 0,
&aic3x_left_pga_mixer_controls[0],
ARRAY_SIZE(aic3x_left_pga_mixer_controls)),
SND_SOC_DAPM_MUX("Left Line1L Mux", SND_SOC_NOPM, 0, 0,
&aic3x_left_line1_mux_controls),
+ SND_SOC_DAPM_MUX("Left Line1R Mux", SND_SOC_NOPM, 0, 0,
+ &aic3x_left_line1_mux_controls),
SND_SOC_DAPM_MUX("Left Line2L Mux", SND_SOC_NOPM, 0, 0,
&aic3x_left_line2_mux_controls),
- /* Right Inputs to Right ADC */
+ /* Inputs to Right ADC */
SND_SOC_DAPM_ADC("Right ADC", "Right Capture",
LINE1R_2_RADC_CTRL, 2, 0),
SND_SOC_DAPM_MIXER("Right PGA Mixer", SND_SOC_NOPM, 0, 0,
&aic3x_right_pga_mixer_controls[0],
ARRAY_SIZE(aic3x_right_pga_mixer_controls)),
+ SND_SOC_DAPM_MUX("Right Line1L Mux", SND_SOC_NOPM, 0, 0,
+ &aic3x_right_line1_mux_controls),
SND_SOC_DAPM_MUX("Right Line1R Mux", SND_SOC_NOPM, 0, 0,
&aic3x_right_line1_mux_controls),
SND_SOC_DAPM_MUX("Right Line2R Mux", SND_SOC_NOPM, 0, 0,
@@ -531,7 +561,8 @@ static const struct snd_soc_dapm_route intercon[] = {
{"Left DAC Mux", "DAC_L2", "Left DAC"},
{"Left DAC Mux", "DAC_L3", "Left DAC"},
- {"Left DAC_L1 Mixer", "Line Switch", "Left DAC Mux"},
+ {"Left DAC_L1 Mixer", "LineL Switch", "Left DAC Mux"},
+ {"Left DAC_L1 Mixer", "LineR Switch", "Left DAC Mux"},
{"Left DAC_L1 Mixer", "Mono Switch", "Left DAC Mux"},
{"Left DAC_L1 Mixer", "HP Switch", "Left DAC Mux"},
{"Left DAC_L1 Mixer", "HPCOM Switch", "Left DAC Mux"},
@@ -557,7 +588,8 @@ static const struct snd_soc_dapm_route intercon[] = {
{"Right DAC Mux", "DAC_R2", "Right DAC"},
{"Right DAC Mux", "DAC_R3", "Right DAC"},
- {"Right DAC_R1 Mixer", "Line Switch", "Right DAC Mux"},
+ {"Right DAC_R1 Mixer", "LineL Switch", "Right DAC Mux"},
+ {"Right DAC_R1 Mixer", "LineR Switch", "Right DAC Mux"},
{"Right DAC_R1 Mixer", "Mono Switch", "Right DAC Mux"},
{"Right DAC_R1 Mixer", "HP Switch", "Right DAC Mux"},
{"Right DAC_R1 Mixer", "HPCOM Switch", "Right DAC Mux"},
@@ -592,8 +624,10 @@ static const struct snd_soc_dapm_route intercon[] = {
{"Left Line2L Mux", "differential", "LINE2L"},
{"Left PGA Mixer", "Line1L Switch", "Left Line1L Mux"},
+ {"Left PGA Mixer", "Line1R Switch", "Left Line1R Mux"},
{"Left PGA Mixer", "Line2L Switch", "Left Line2L Mux"},
{"Left PGA Mixer", "Mic3L Switch", "MIC3L"},
+ {"Left PGA Mixer", "Mic3R Switch", "MIC3R"},
{"Left ADC", NULL, "Left PGA Mixer"},
{"Left ADC", NULL, "GPIO1 dmic modclk"},
@@ -605,18 +639,23 @@ static const struct snd_soc_dapm_route intercon[] = {
{"Right Line2R Mux", "single-ended", "LINE2R"},
{"Right Line2R Mux", "differential", "LINE2R"},
+ {"Right PGA Mixer", "Line1L Switch", "Right Line1L Mux"},
{"Right PGA Mixer", "Line1R Switch", "Right Line1R Mux"},
{"Right PGA Mixer", "Line2R Switch", "Right Line2R Mux"},
+ {"Right PGA Mixer", "Mic3L Switch", "MIC3L"},
{"Right PGA Mixer", "Mic3R Switch", "MIC3R"},
{"Right ADC", NULL, "Right PGA Mixer"},
{"Right ADC", NULL, "GPIO1 dmic modclk"},
/* Left PGA Bypass */
- {"Left PGA Bypass Mixer", "Line Switch", "Left PGA Mixer"},
+ {"Left PGA Bypass Mixer", "LineL Switch", "Left PGA Mixer"},
+ {"Left PGA Bypass Mixer", "LineR Switch", "Left PGA Mixer"},
{"Left PGA Bypass Mixer", "Mono Switch", "Left PGA Mixer"},
- {"Left PGA Bypass Mixer", "HP Switch", "Left PGA Mixer"},
- {"Left PGA Bypass Mixer", "HPCOM Switch", "Left PGA Mixer"},
+ {"Left PGA Bypass Mixer", "HPL Switch", "Left PGA Mixer"},
+ {"Left PGA Bypass Mixer", "HPR Switch", "Left PGA Mixer"},
+ {"Left PGA Bypass Mixer", "HPLCOM Switch", "Left PGA Mixer"},
+ {"Left PGA Bypass Mixer", "HPRCOM Switch", "Left PGA Mixer"},
{"Left HPCOM Mux", "differential of HPLOUT", "Left PGA Bypass Mixer"},
{"Left HPCOM Mux", "constant VCM", "Left PGA Bypass Mixer"},
@@ -627,10 +666,13 @@ static const struct snd_soc_dapm_route intercon[] = {
{"Left HP Out", NULL, "Left PGA Bypass Mixer"},
/* Right PGA Bypass */
- {"Right PGA Bypass Mixer", "Line Switch", "Right PGA Mixer"},
+ {"Right PGA Bypass Mixer", "LineL Switch", "Right PGA Mixer"},
+ {"Right PGA Bypass Mixer", "LineR Switch", "Right PGA Mixer"},
{"Right PGA Bypass Mixer", "Mono Switch", "Right PGA Mixer"},
- {"Right PGA Bypass Mixer", "HP Switch", "Right PGA Mixer"},
- {"Right PGA Bypass Mixer", "HPCOM Switch", "Right PGA Mixer"},
+ {"Right PGA Bypass Mixer", "HPL Switch", "Right PGA Mixer"},
+ {"Right PGA Bypass Mixer", "HPR Switch", "Right PGA Mixer"},
+ {"Right PGA Bypass Mixer", "HPLCOM Switch", "Right PGA Mixer"},
+ {"Right PGA Bypass Mixer", "HPRCOM Switch", "Right PGA Mixer"},
{"Right HPCOM Mux", "differential of HPROUT", "Right PGA Bypass Mixer"},
{"Right HPCOM Mux", "constant VCM", "Right PGA Bypass Mixer"},
@@ -643,10 +685,11 @@ static const struct snd_soc_dapm_route intercon[] = {
{"Right HP Out", NULL, "Right PGA Bypass Mixer"},
/* Left Line2 Bypass */
- {"Left Line2 Bypass Mixer", "Line Switch", "Left Line2L Mux"},
+ {"Left Line2 Bypass Mixer", "LineL Switch", "Left Line2L Mux"},
+ {"Left Line2 Bypass Mixer", "LineR Switch", "Left Line2L Mux"},
{"Left Line2 Bypass Mixer", "Mono Switch", "Left Line2L Mux"},
{"Left Line2 Bypass Mixer", "HP Switch", "Left Line2L Mux"},
- {"Left Line2 Bypass Mixer", "HPCOM Switch", "Left Line2L Mux"},
+ {"Left Line2 Bypass Mixer", "HPLCOM Switch", "Left Line2L Mux"},
{"Left HPCOM Mux", "differential of HPLOUT", "Left Line2 Bypass Mixer"},
{"Left HPCOM Mux", "constant VCM", "Left Line2 Bypass Mixer"},
@@ -657,10 +700,11 @@ static const struct snd_soc_dapm_route intercon[] = {
{"Left HP Out", NULL, "Left Line2 Bypass Mixer"},
/* Right Line2 Bypass */
- {"Right Line2 Bypass Mixer", "Line Switch", "Right Line2R Mux"},
+ {"Right Line2 Bypass Mixer", "LineL Switch", "Right Line2R Mux"},
+ {"Right Line2 Bypass Mixer", "LineR Switch", "Right Line2R Mux"},
{"Right Line2 Bypass Mixer", "Mono Switch", "Right Line2R Mux"},
{"Right Line2 Bypass Mixer", "HP Switch", "Right Line2R Mux"},
- {"Right Line2 Bypass Mixer", "HPCOM Switch", "Right Line2R Mux"},
+ {"Right Line2 Bypass Mixer", "HPRCOM Switch", "Right Line2R Mux"},
{"Right HPCOM Mux", "differential of HPROUT", "Right Line2 Bypass Mixer"},
{"Right HPCOM Mux", "constant VCM", "Right Line2 Bypass Mixer"},
@@ -694,7 +738,8 @@ static int aic3x_add_widgets(struct snd_soc_codec *codec)
}
static int aic3x_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
@@ -846,6 +891,7 @@ static int aic3x_set_dai_fmt(struct snd_soc_dai *codec_dai,
struct snd_soc_codec *codec = codec_dai->codec;
struct aic3x_priv *aic3x = codec->private_data;
u8 iface_areg, iface_breg;
+ int delay = 0;
iface_areg = aic3x_read_reg_cache(codec, AIC3X_ASD_INTF_CTRLA) & 0x3f;
iface_breg = aic3x_read_reg_cache(codec, AIC3X_ASD_INTF_CTRLB) & 0x3f;
@@ -871,6 +917,8 @@ static int aic3x_set_dai_fmt(struct snd_soc_dai *codec_dai,
SND_SOC_DAIFMT_INV_MASK)) {
case (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF):
break;
+ case (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF):
+ delay = 1;
case (SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF):
iface_breg |= (0x01 << 6);
break;
@@ -887,6 +935,7 @@ static int aic3x_set_dai_fmt(struct snd_soc_dai *codec_dai,
/* set iface */
aic3x_write(codec, AIC3X_ASD_INTF_CTRLA, iface_areg);
aic3x_write(codec, AIC3X_ASD_INTF_CTRLB, iface_breg);
+ aic3x_write(codec, AIC3X_ASD_INTF_CTRLC, delay);
return 0;
}
@@ -981,14 +1030,41 @@ int aic3x_get_gpio(struct snd_soc_codec *codec, int gpio)
}
EXPORT_SYMBOL_GPL(aic3x_get_gpio);
+void aic3x_set_headset_detection(struct snd_soc_codec *codec, int detect,
+ int headset_debounce, int button_debounce)
+{
+ u8 val;
+
+ val = ((detect & AIC3X_HEADSET_DETECT_MASK)
+ << AIC3X_HEADSET_DETECT_SHIFT) |
+ ((headset_debounce & AIC3X_HEADSET_DEBOUNCE_MASK)
+ << AIC3X_HEADSET_DEBOUNCE_SHIFT) |
+ ((button_debounce & AIC3X_BUTTON_DEBOUNCE_MASK)
+ << AIC3X_BUTTON_DEBOUNCE_SHIFT);
+
+ if (detect & AIC3X_HEADSET_DETECT_MASK)
+ val |= AIC3X_HEADSET_DETECT_ENABLED;
+
+ aic3x_write(codec, AIC3X_HEADSET_DETECT_CTRL_A, val);
+}
+EXPORT_SYMBOL_GPL(aic3x_set_headset_detection);
+
int aic3x_headset_detected(struct snd_soc_codec *codec)
{
u8 val;
- aic3x_read(codec, AIC3X_RT_IRQ_FLAGS_REG, &val);
- return (val >> 2) & 1;
+ aic3x_read(codec, AIC3X_HEADSET_DETECT_CTRL_B, &val);
+ return (val >> 4) & 1;
}
EXPORT_SYMBOL_GPL(aic3x_headset_detected);
+int aic3x_button_pressed(struct snd_soc_codec *codec)
+{
+ u8 val;
+ aic3x_read(codec, AIC3X_HEADSET_DETECT_CTRL_B, &val);
+ return (val >> 5) & 1;
+}
+EXPORT_SYMBOL_GPL(aic3x_button_pressed);
+
#define AIC3X_RATES SNDRV_PCM_RATE_8000_96000
#define AIC3X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
@@ -1009,8 +1085,6 @@ struct snd_soc_dai aic3x_dai = {
.formats = AIC3X_FORMATS,},
.ops = {
.hw_params = aic3x_hw_params,
- },
- .dai_ops = {
.digital_mute = aic3x_mute,
.set_sysclk = aic3x_set_dai_sysclk,
.set_fmt = aic3x_set_dai_fmt,
@@ -1152,7 +1226,7 @@ static int aic3x_init(struct snd_soc_device *socdev)
aic3x_add_controls(codec);
aic3x_add_widgets(codec);
- ret = snd_soc_register_card(socdev);
+ ret = snd_soc_init_card(socdev);
if (ret < 0) {
printk(KERN_ERR "aic3x: failed to register card\n");
goto card_err;
@@ -1341,6 +1415,18 @@ struct snd_soc_codec_device soc_codec_dev_aic3x = {
};
EXPORT_SYMBOL_GPL(soc_codec_dev_aic3x);
+static int __init aic3x_modinit(void)
+{
+ return snd_soc_register_dai(&aic3x_dai);
+}
+module_init(aic3x_modinit);
+
+static void __exit aic3x_exit(void)
+{
+ snd_soc_unregister_dai(&aic3x_dai);
+}
+module_exit(aic3x_exit);
+
MODULE_DESCRIPTION("ASoC TLV320AIC3X codec driver");
MODULE_AUTHOR("Vladimir Barinov");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/tlv320aic3x.h b/sound/soc/codecs/tlv320aic3x.h
index 00a195aa02e..ac827e578c4 100644
--- a/sound/soc/codecs/tlv320aic3x.h
+++ b/sound/soc/codecs/tlv320aic3x.h
@@ -35,11 +35,15 @@
#define AIC3X_ASD_INTF_CTRLA 8
/* Audio serial data interface control register B */
#define AIC3X_ASD_INTF_CTRLB 9
+/* Audio serial data interface control register C */
+#define AIC3X_ASD_INTF_CTRLC 10
/* Audio overflow status and PLL R value programming register */
#define AIC3X_OVRF_STATUS_AND_PLLR_REG 11
/* Audio codec digital filter control register */
#define AIC3X_CODEC_DFILT_CTRL 12
-
+/* Headset/button press detection register */
+#define AIC3X_HEADSET_DETECT_CTRL_A 13
+#define AIC3X_HEADSET_DETECT_CTRL_B 14
/* ADC PGA Gain control registers */
#define LADC_VOL 15
#define RADC_VOL 16
@@ -48,7 +52,9 @@
#define MIC3LR_2_RADC_CTRL 18
/* Line1 Input control registers */
#define LINE1L_2_LADC_CTRL 19
+#define LINE1R_2_LADC_CTRL 21
#define LINE1R_2_RADC_CTRL 22
+#define LINE1L_2_RADC_CTRL 24
/* Line2 Input control registers */
#define LINE2L_2_LADC_CTRL 20
#define LINE2R_2_RADC_CTRL 23
@@ -79,6 +85,8 @@
#define LINE2L_2_HPLOUT_VOL 45
#define LINE2R_2_HPROUT_VOL 62
#define PGAL_2_HPLOUT_VOL 46
+#define PGAL_2_HPROUT_VOL 60
+#define PGAR_2_HPLOUT_VOL 49
#define PGAR_2_HPROUT_VOL 63
#define DACL1_2_HPLOUT_VOL 47
#define DACR1_2_HPROUT_VOL 64
@@ -88,6 +96,8 @@
#define LINE2L_2_HPLCOM_VOL 52
#define LINE2R_2_HPRCOM_VOL 69
#define PGAL_2_HPLCOM_VOL 53
+#define PGAR_2_HPLCOM_VOL 56
+#define PGAL_2_HPRCOM_VOL 67
#define PGAR_2_HPRCOM_VOL 70
#define DACL1_2_HPLCOM_VOL 54
#define DACR1_2_HPRCOM_VOL 71
@@ -103,11 +113,17 @@
#define MONOLOPM_CTRL 79
/* Line Output Plus/Minus control registers */
#define LINE2L_2_LLOPM_VOL 80
+#define LINE2L_2_RLOPM_VOL 87
+#define LINE2R_2_LLOPM_VOL 83
#define LINE2R_2_RLOPM_VOL 90
#define PGAL_2_LLOPM_VOL 81
+#define PGAL_2_RLOPM_VOL 88
+#define PGAR_2_LLOPM_VOL 84
#define PGAR_2_RLOPM_VOL 91
#define DACL1_2_LLOPM_VOL 82
+#define DACL1_2_RLOPM_VOL 89
#define DACR1_2_RLOPM_VOL 92
+#define DACR1_2_LLOPM_VOL 85
#define LLOPM_CTRL 86
#define RLOPM_CTRL 93
/* GPIO/IRQ registers */
@@ -221,7 +237,49 @@ enum {
void aic3x_set_gpio(struct snd_soc_codec *codec, int gpio, int state);
int aic3x_get_gpio(struct snd_soc_codec *codec, int gpio);
+
+/* headset detection / button API */
+
+/* The AIC3x supports detection of stereo headsets (GND + left + right signal)
+ * and cellular headsets (GND + speaker output + microphone input).
+ * It is recommended to enable MIC bias for this function to work properly.
+ * For more information, please refer to the datasheet. */
+enum {
+ AIC3X_HEADSET_DETECT_OFF = 0,
+ AIC3X_HEADSET_DETECT_STEREO = 1,
+ AIC3X_HEADSET_DETECT_CELLULAR = 2,
+ AIC3X_HEADSET_DETECT_BOTH = 3
+};
+
+enum {
+ AIC3X_HEADSET_DEBOUNCE_16MS = 0,
+ AIC3X_HEADSET_DEBOUNCE_32MS = 1,
+ AIC3X_HEADSET_DEBOUNCE_64MS = 2,
+ AIC3X_HEADSET_DEBOUNCE_128MS = 3,
+ AIC3X_HEADSET_DEBOUNCE_256MS = 4,
+ AIC3X_HEADSET_DEBOUNCE_512MS = 5
+};
+
+enum {
+ AIC3X_BUTTON_DEBOUNCE_0MS = 0,
+ AIC3X_BUTTON_DEBOUNCE_8MS = 1,
+ AIC3X_BUTTON_DEBOUNCE_16MS = 2,
+ AIC3X_BUTTON_DEBOUNCE_32MS = 3
+};
+
+#define AIC3X_HEADSET_DETECT_ENABLED 0x80
+#define AIC3X_HEADSET_DETECT_SHIFT 5
+#define AIC3X_HEADSET_DETECT_MASK 3
+#define AIC3X_HEADSET_DEBOUNCE_SHIFT 2
+#define AIC3X_HEADSET_DEBOUNCE_MASK 7
+#define AIC3X_BUTTON_DEBOUNCE_SHIFT 0
+#define AIC3X_BUTTON_DEBOUNCE_MASK 3
+
+/* see the enums above for valid parameters to this function */
+void aic3x_set_headset_detection(struct snd_soc_codec *codec, int detect,
+ int headset_debounce, int button_debounce);
int aic3x_headset_detected(struct snd_soc_codec *codec);
+int aic3x_button_pressed(struct snd_soc_codec *codec);
struct aic3x_setup_data {
int i2c_bus;
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
new file mode 100644
index 00000000000..51848880504
--- /dev/null
+++ b/sound/soc/codecs/twl4030.c
@@ -0,0 +1,1317 @@
+/*
+ * ALSA SoC TWL4030 codec driver
+ *
+ * Author: Steve Sakoman, <steve@sakoman.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/i2c/twl4030.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include "twl4030.h"
+
+/*
+ * twl4030 register cache & default register settings
+ */
+static const u8 twl4030_reg[TWL4030_CACHEREGNUM] = {
+ 0x00, /* this register not used */
+ 0x93, /* REG_CODEC_MODE (0x1) */
+ 0xc3, /* REG_OPTION (0x2) */
+ 0x00, /* REG_UNKNOWN (0x3) */
+ 0x00, /* REG_MICBIAS_CTL (0x4) */
+ 0x20, /* REG_ANAMICL (0x5) */
+ 0x00, /* REG_ANAMICR (0x6) */
+ 0x00, /* REG_AVADC_CTL (0x7) */
+ 0x00, /* REG_ADCMICSEL (0x8) */
+ 0x00, /* REG_DIGMIXING (0x9) */
+ 0x0c, /* REG_ATXL1PGA (0xA) */
+ 0x0c, /* REG_ATXR1PGA (0xB) */
+ 0x00, /* REG_AVTXL2PGA (0xC) */
+ 0x00, /* REG_AVTXR2PGA (0xD) */
+ 0x01, /* REG_AUDIO_IF (0xE) */
+ 0x00, /* REG_VOICE_IF (0xF) */
+ 0x00, /* REG_ARXR1PGA (0x10) */
+ 0x00, /* REG_ARXL1PGA (0x11) */
+ 0x6c, /* REG_ARXR2PGA (0x12) */
+ 0x6c, /* REG_ARXL2PGA (0x13) */
+ 0x00, /* REG_VRXPGA (0x14) */
+ 0x00, /* REG_VSTPGA (0x15) */
+ 0x00, /* REG_VRX2ARXPGA (0x16) */
+ 0x0c, /* REG_AVDAC_CTL (0x17) */
+ 0x00, /* REG_ARX2VTXPGA (0x18) */
+ 0x00, /* REG_ARXL1_APGA_CTL (0x19) */
+ 0x00, /* REG_ARXR1_APGA_CTL (0x1A) */
+ 0x4b, /* REG_ARXL2_APGA_CTL (0x1B) */
+ 0x4b, /* REG_ARXR2_APGA_CTL (0x1C) */
+ 0x00, /* REG_ATX2ARXPGA (0x1D) */
+ 0x00, /* REG_BT_IF (0x1E) */
+ 0x00, /* REG_BTPGA (0x1F) */
+ 0x00, /* REG_BTSTPGA (0x20) */
+ 0x00, /* REG_EAR_CTL (0x21) */
+ 0x24, /* REG_HS_SEL (0x22) */
+ 0x0a, /* REG_HS_GAIN_SET (0x23) */
+ 0x00, /* REG_HS_POPN_SET (0x24) */
+ 0x00, /* REG_PREDL_CTL (0x25) */
+ 0x00, /* REG_PREDR_CTL (0x26) */
+ 0x00, /* REG_PRECKL_CTL (0x27) */
+ 0x00, /* REG_PRECKR_CTL (0x28) */
+ 0x00, /* REG_HFL_CTL (0x29) */
+ 0x00, /* REG_HFR_CTL (0x2A) */
+ 0x00, /* REG_ALC_CTL (0x2B) */
+ 0x00, /* REG_ALC_SET1 (0x2C) */
+ 0x00, /* REG_ALC_SET2 (0x2D) */
+ 0x00, /* REG_BOOST_CTL (0x2E) */
+ 0x00, /* REG_SOFTVOL_CTL (0x2F) */
+ 0x00, /* REG_DTMF_FREQSEL (0x30) */
+ 0x00, /* REG_DTMF_TONEXT1H (0x31) */
+ 0x00, /* REG_DTMF_TONEXT1L (0x32) */
+ 0x00, /* REG_DTMF_TONEXT2H (0x33) */
+ 0x00, /* REG_DTMF_TONEXT2L (0x34) */
+ 0x00, /* REG_DTMF_TONOFF (0x35) */
+ 0x00, /* REG_DTMF_WANONOFF (0x36) */
+ 0x00, /* REG_I2S_RX_SCRAMBLE_H (0x37) */
+ 0x00, /* REG_I2S_RX_SCRAMBLE_M (0x38) */
+ 0x00, /* REG_I2S_RX_SCRAMBLE_L (0x39) */
+ 0x16, /* REG_APLL_CTL (0x3A) */
+ 0x00, /* REG_DTMF_CTL (0x3B) */
+ 0x00, /* REG_DTMF_PGA_CTL2 (0x3C) */
+ 0x00, /* REG_DTMF_PGA_CTL1 (0x3D) */
+ 0x00, /* REG_MISC_SET_1 (0x3E) */
+ 0x00, /* REG_PCMBTMUX (0x3F) */
+ 0x00, /* not used (0x40) */
+ 0x00, /* not used (0x41) */
+ 0x00, /* not used (0x42) */
+ 0x00, /* REG_RX_PATH_SEL (0x43) */
+ 0x00, /* REG_VDL_APGA_CTL (0x44) */
+ 0x00, /* REG_VIBRA_CTL (0x45) */
+ 0x00, /* REG_VIBRA_SET (0x46) */
+ 0x00, /* REG_VIBRA_PWM_SET (0x47) */
+ 0x00, /* REG_ANAMIC_GAIN (0x48) */
+ 0x00, /* REG_MISC_SET_2 (0x49) */
+};
+
+/*
+ * read twl4030 register cache
+ */
+static inline unsigned int twl4030_read_reg_cache(struct snd_soc_codec *codec,
+ unsigned int reg)
+{
+ u8 *cache = codec->reg_cache;
+
+ return cache[reg];
+}
+
+/*
+ * write twl4030 register cache
+ */
+static inline void twl4030_write_reg_cache(struct snd_soc_codec *codec,
+ u8 reg, u8 value)
+{
+ u8 *cache = codec->reg_cache;
+
+ if (reg >= TWL4030_CACHEREGNUM)
+ return;
+ cache[reg] = value;
+}
+
+/*
+ * write to the twl4030 register space
+ */
+static int twl4030_write(struct snd_soc_codec *codec,
+ unsigned int reg, unsigned int value)
+{
+ twl4030_write_reg_cache(codec, reg, value);
+ return twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, value, reg);
+}
+
+static void twl4030_clear_codecpdz(struct snd_soc_codec *codec)
+{
+ u8 mode;
+
+ mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE);
+ twl4030_write(codec, TWL4030_REG_CODEC_MODE,
+ mode & ~TWL4030_CODECPDZ);
+
+ /* REVISIT: this delay is present in TI sample drivers */
+ /* but there seems to be no TRM requirement for it */
+ udelay(10);
+}
+
+static void twl4030_set_codecpdz(struct snd_soc_codec *codec)
+{
+ u8 mode;
+
+ mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE);
+ twl4030_write(codec, TWL4030_REG_CODEC_MODE,
+ mode | TWL4030_CODECPDZ);
+
+ /* REVISIT: this delay is present in TI sample drivers */
+ /* but there seems to be no TRM requirement for it */
+ udelay(10);
+}
+
+static void twl4030_init_chip(struct snd_soc_codec *codec)
+{
+ int i;
+
+ /* clear CODECPDZ prior to setting register defaults */
+ twl4030_clear_codecpdz(codec);
+
+ /* set all audio section registers to reasonable defaults */
+ for (i = TWL4030_REG_OPTION; i <= TWL4030_REG_MISC_SET_2; i++)
+ twl4030_write(codec, i, twl4030_reg[i]);
+
+}
+
+/* Earpiece */
+static const char *twl4030_earpiece_texts[] =
+ {"Off", "DACL1", "DACL2", "Invalid", "DACR1"};
+
+static const struct soc_enum twl4030_earpiece_enum =
+ SOC_ENUM_SINGLE(TWL4030_REG_EAR_CTL, 1,
+ ARRAY_SIZE(twl4030_earpiece_texts),
+ twl4030_earpiece_texts);
+
+static const struct snd_kcontrol_new twl4030_dapm_earpiece_control =
+SOC_DAPM_ENUM("Route", twl4030_earpiece_enum);
+
+/* PreDrive Left */
+static const char *twl4030_predrivel_texts[] =
+ {"Off", "DACL1", "DACL2", "Invalid", "DACR2"};
+
+static const struct soc_enum twl4030_predrivel_enum =
+ SOC_ENUM_SINGLE(TWL4030_REG_PREDL_CTL, 1,
+ ARRAY_SIZE(twl4030_predrivel_texts),
+ twl4030_predrivel_texts);
+
+static const struct snd_kcontrol_new twl4030_dapm_predrivel_control =
+SOC_DAPM_ENUM("Route", twl4030_predrivel_enum);
+
+/* PreDrive Right */
+static const char *twl4030_predriver_texts[] =
+ {"Off", "DACR1", "DACR2", "Invalid", "DACL2"};
+
+static const struct soc_enum twl4030_predriver_enum =
+ SOC_ENUM_SINGLE(TWL4030_REG_PREDR_CTL, 1,
+ ARRAY_SIZE(twl4030_predriver_texts),
+ twl4030_predriver_texts);
+
+static const struct snd_kcontrol_new twl4030_dapm_predriver_control =
+SOC_DAPM_ENUM("Route", twl4030_predriver_enum);
+
+/* Headset Left */
+static const char *twl4030_hsol_texts[] =
+ {"Off", "DACL1", "DACL2"};
+
+static const struct soc_enum twl4030_hsol_enum =
+ SOC_ENUM_SINGLE(TWL4030_REG_HS_SEL, 1,
+ ARRAY_SIZE(twl4030_hsol_texts),
+ twl4030_hsol_texts);
+
+static const struct snd_kcontrol_new twl4030_dapm_hsol_control =
+SOC_DAPM_ENUM("Route", twl4030_hsol_enum);
+
+/* Headset Right */
+static const char *twl4030_hsor_texts[] =
+ {"Off", "DACR1", "DACR2"};
+
+static const struct soc_enum twl4030_hsor_enum =
+ SOC_ENUM_SINGLE(TWL4030_REG_HS_SEL, 4,
+ ARRAY_SIZE(twl4030_hsor_texts),
+ twl4030_hsor_texts);
+
+static const struct snd_kcontrol_new twl4030_dapm_hsor_control =
+SOC_DAPM_ENUM("Route", twl4030_hsor_enum);
+
+/* Carkit Left */
+static const char *twl4030_carkitl_texts[] =
+ {"Off", "DACL1", "DACL2"};
+
+static const struct soc_enum twl4030_carkitl_enum =
+ SOC_ENUM_SINGLE(TWL4030_REG_PRECKL_CTL, 1,
+ ARRAY_SIZE(twl4030_carkitl_texts),
+ twl4030_carkitl_texts);
+
+static const struct snd_kcontrol_new twl4030_dapm_carkitl_control =
+SOC_DAPM_ENUM("Route", twl4030_carkitl_enum);
+
+/* Carkit Right */
+static const char *twl4030_carkitr_texts[] =
+ {"Off", "DACR1", "DACR2"};
+
+static const struct soc_enum twl4030_carkitr_enum =
+ SOC_ENUM_SINGLE(TWL4030_REG_PRECKR_CTL, 1,
+ ARRAY_SIZE(twl4030_carkitr_texts),
+ twl4030_carkitr_texts);
+
+static const struct snd_kcontrol_new twl4030_dapm_carkitr_control =
+SOC_DAPM_ENUM("Route", twl4030_carkitr_enum);
+
+/* Handsfree Left */
+static const char *twl4030_handsfreel_texts[] =
+ {"Voice", "DACL1", "DACL2", "DACR2"};
+
+static const struct soc_enum twl4030_handsfreel_enum =
+ SOC_ENUM_SINGLE(TWL4030_REG_HFL_CTL, 0,
+ ARRAY_SIZE(twl4030_handsfreel_texts),
+ twl4030_handsfreel_texts);
+
+static const struct snd_kcontrol_new twl4030_dapm_handsfreel_control =
+SOC_DAPM_ENUM("Route", twl4030_handsfreel_enum);
+
+/* Handsfree Right */
+static const char *twl4030_handsfreer_texts[] =
+ {"Voice", "DACR1", "DACR2", "DACL2"};
+
+static const struct soc_enum twl4030_handsfreer_enum =
+ SOC_ENUM_SINGLE(TWL4030_REG_HFR_CTL, 0,
+ ARRAY_SIZE(twl4030_handsfreer_texts),
+ twl4030_handsfreer_texts);
+
+static const struct snd_kcontrol_new twl4030_dapm_handsfreer_control =
+SOC_DAPM_ENUM("Route", twl4030_handsfreer_enum);
+
+static int outmixer_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+ int ret = 0;
+ int val;
+
+ switch (e->reg) {
+ case TWL4030_REG_PREDL_CTL:
+ case TWL4030_REG_PREDR_CTL:
+ case TWL4030_REG_EAR_CTL:
+ val = w->value >> e->shift_l;
+ if (val == 3) {
+ printk(KERN_WARNING
+ "Invalid MUX setting for register 0x%02x (%d)\n",
+ e->reg, val);
+ ret = -1;
+ }
+ break;
+ }
+
+ return ret;
+}
+
+static int handsfree_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct soc_enum *e = (struct soc_enum *)w->kcontrols->private_value;
+ unsigned char hs_ctl;
+
+ hs_ctl = twl4030_read_reg_cache(w->codec, e->reg);
+
+ if (hs_ctl & TWL4030_HF_CTL_REF_EN) {
+ hs_ctl |= TWL4030_HF_CTL_RAMP_EN;
+ twl4030_write(w->codec, e->reg, hs_ctl);
+ hs_ctl |= TWL4030_HF_CTL_LOOP_EN;
+ twl4030_write(w->codec, e->reg, hs_ctl);
+ hs_ctl |= TWL4030_HF_CTL_HB_EN;
+ twl4030_write(w->codec, e->reg, hs_ctl);
+ } else {
+ hs_ctl &= ~(TWL4030_HF_CTL_RAMP_EN | TWL4030_HF_CTL_LOOP_EN
+ | TWL4030_HF_CTL_HB_EN);
+ twl4030_write(w->codec, e->reg, hs_ctl);
+ }
+
+ return 0;
+}
+
+/*
+ * Some of the gain controls in TWL (mostly those which are associated with
+ * the outputs) are implemented in an interesting way:
+ * 0x0 : Power down (mute)
+ * 0x1 : 6dB
+ * 0x2 : 0 dB
+ * 0x3 : -6 dB
+ * Inverting not going to help with these.
+ * Custom volsw and volsw_2r get/put functions to handle these gain bits.
+ */
+#define SOC_DOUBLE_TLV_TWL4030(xname, xreg, shift_left, shift_right, xmax,\
+ xinvert, tlv_array) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
+ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
+ SNDRV_CTL_ELEM_ACCESS_READWRITE,\
+ .tlv.p = (tlv_array), \
+ .info = snd_soc_info_volsw, \
+ .get = snd_soc_get_volsw_twl4030, \
+ .put = snd_soc_put_volsw_twl4030, \
+ .private_value = (unsigned long)&(struct soc_mixer_control) \
+ {.reg = xreg, .shift = shift_left, .rshift = shift_right,\
+ .max = xmax, .invert = xinvert} }
+#define SOC_DOUBLE_R_TLV_TWL4030(xname, reg_left, reg_right, xshift, xmax,\
+ xinvert, tlv_array) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
+ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
+ SNDRV_CTL_ELEM_ACCESS_READWRITE,\
+ .tlv.p = (tlv_array), \
+ .info = snd_soc_info_volsw_2r, \
+ .get = snd_soc_get_volsw_r2_twl4030,\
+ .put = snd_soc_put_volsw_r2_twl4030, \
+ .private_value = (unsigned long)&(struct soc_mixer_control) \
+ {.reg = reg_left, .rreg = reg_right, .shift = xshift, \
+ .rshift = xshift, .max = xmax, .invert = xinvert} }
+#define SOC_SINGLE_TLV_TWL4030(xname, xreg, xshift, xmax, xinvert, tlv_array) \
+ SOC_DOUBLE_TLV_TWL4030(xname, xreg, xshift, xshift, xmax, \
+ xinvert, tlv_array)
+
+static int snd_soc_get_volsw_twl4030(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ unsigned int reg = mc->reg;
+ unsigned int shift = mc->shift;
+ unsigned int rshift = mc->rshift;
+ int max = mc->max;
+ int mask = (1 << fls(max)) - 1;
+
+ ucontrol->value.integer.value[0] =
+ (snd_soc_read(codec, reg) >> shift) & mask;
+ if (ucontrol->value.integer.value[0])
+ ucontrol->value.integer.value[0] =
+ max + 1 - ucontrol->value.integer.value[0];
+
+ if (shift != rshift) {
+ ucontrol->value.integer.value[1] =
+ (snd_soc_read(codec, reg) >> rshift) & mask;
+ if (ucontrol->value.integer.value[1])
+ ucontrol->value.integer.value[1] =
+ max + 1 - ucontrol->value.integer.value[1];
+ }
+
+ return 0;
+}
+
+static int snd_soc_put_volsw_twl4030(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ unsigned int reg = mc->reg;
+ unsigned int shift = mc->shift;
+ unsigned int rshift = mc->rshift;
+ int max = mc->max;
+ int mask = (1 << fls(max)) - 1;
+ unsigned short val, val2, val_mask;
+
+ val = (ucontrol->value.integer.value[0] & mask);
+
+ val_mask = mask << shift;
+ if (val)
+ val = max + 1 - val;
+ val = val << shift;
+ if (shift != rshift) {
+ val2 = (ucontrol->value.integer.value[1] & mask);
+ val_mask |= mask << rshift;
+ if (val2)
+ val2 = max + 1 - val2;
+ val |= val2 << rshift;
+ }
+ return snd_soc_update_bits(codec, reg, val_mask, val);
+}
+
+static int snd_soc_get_volsw_r2_twl4030(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ unsigned int reg = mc->reg;
+ unsigned int reg2 = mc->rreg;
+ unsigned int shift = mc->shift;
+ int max = mc->max;
+ int mask = (1<<fls(max))-1;
+
+ ucontrol->value.integer.value[0] =
+ (snd_soc_read(codec, reg) >> shift) & mask;
+ ucontrol->value.integer.value[1] =
+ (snd_soc_read(codec, reg2) >> shift) & mask;
+
+ if (ucontrol->value.integer.value[0])
+ ucontrol->value.integer.value[0] =
+ max + 1 - ucontrol->value.integer.value[0];
+ if (ucontrol->value.integer.value[1])
+ ucontrol->value.integer.value[1] =
+ max + 1 - ucontrol->value.integer.value[1];
+
+ return 0;
+}
+
+static int snd_soc_put_volsw_r2_twl4030(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ unsigned int reg = mc->reg;
+ unsigned int reg2 = mc->rreg;
+ unsigned int shift = mc->shift;
+ int max = mc->max;
+ int mask = (1 << fls(max)) - 1;
+ int err;
+ unsigned short val, val2, val_mask;
+
+ val_mask = mask << shift;
+ val = (ucontrol->value.integer.value[0] & mask);
+ val2 = (ucontrol->value.integer.value[1] & mask);
+
+ if (val)
+ val = max + 1 - val;
+ if (val2)
+ val2 = max + 1 - val2;
+
+ val = val << shift;
+ val2 = val2 << shift;
+
+ err = snd_soc_update_bits(codec, reg, val_mask, val);
+ if (err < 0)
+ return err;
+
+ err = snd_soc_update_bits(codec, reg2, val_mask, val2);
+ return err;
+}
+
+static int twl4030_get_left_input(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = kcontrol->private_data;
+ u8 reg = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICL);
+ int result = 0;
+
+ /* one bit must be set a time */
+ reg &= TWL4030_CKMIC_EN | TWL4030_AUXL_EN | TWL4030_HSMIC_EN
+ | TWL4030_MAINMIC_EN;
+ if (reg != 0) {
+ result++;
+ while ((reg & 1) == 0) {
+ result++;
+ reg >>= 1;
+ }
+ }
+
+ ucontrol->value.integer.value[0] = result;
+ return 0;
+}
+
+static int twl4030_put_left_input(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = kcontrol->private_data;
+ int value = ucontrol->value.integer.value[0];
+ u8 anamicl, micbias, avadc_ctl;
+
+ anamicl = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICL);
+ anamicl &= ~(TWL4030_CKMIC_EN | TWL4030_AUXL_EN | TWL4030_HSMIC_EN
+ | TWL4030_MAINMIC_EN);
+ micbias = twl4030_read_reg_cache(codec, TWL4030_REG_MICBIAS_CTL);
+ micbias &= ~(TWL4030_HSMICBIAS_EN | TWL4030_MICBIAS1_EN);
+ avadc_ctl = twl4030_read_reg_cache(codec, TWL4030_REG_AVADC_CTL);
+
+ switch (value) {
+ case 1:
+ anamicl |= TWL4030_MAINMIC_EN;
+ micbias |= TWL4030_MICBIAS1_EN;
+ break;
+ case 2:
+ anamicl |= TWL4030_HSMIC_EN;
+ micbias |= TWL4030_HSMICBIAS_EN;
+ break;
+ case 3:
+ anamicl |= TWL4030_AUXL_EN;
+ break;
+ case 4:
+ anamicl |= TWL4030_CKMIC_EN;
+ break;
+ default:
+ break;
+ }
+
+ /* If some input is selected, enable amp and ADC */
+ if (value != 0) {
+ anamicl |= TWL4030_MICAMPL_EN;
+ avadc_ctl |= TWL4030_ADCL_EN;
+ } else {
+ anamicl &= ~TWL4030_MICAMPL_EN;
+ avadc_ctl &= ~TWL4030_ADCL_EN;
+ }
+
+ twl4030_write(codec, TWL4030_REG_ANAMICL, anamicl);
+ twl4030_write(codec, TWL4030_REG_MICBIAS_CTL, micbias);
+ twl4030_write(codec, TWL4030_REG_AVADC_CTL, avadc_ctl);
+
+ return 1;
+}
+
+static int twl4030_get_right_input(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = kcontrol->private_data;
+ u8 reg = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICR);
+ int value = 0;
+
+ reg &= TWL4030_SUBMIC_EN|TWL4030_AUXR_EN;
+ switch (reg) {
+ case TWL4030_SUBMIC_EN:
+ value = 1;
+ break;
+ case TWL4030_AUXR_EN:
+ value = 2;
+ break;
+ default:
+ break;
+ }
+
+ ucontrol->value.integer.value[0] = value;
+ return 0;
+}
+
+static int twl4030_put_right_input(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = kcontrol->private_data;
+ int value = ucontrol->value.integer.value[0];
+ u8 anamicr, micbias, avadc_ctl;
+
+ anamicr = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICR);
+ anamicr &= ~(TWL4030_SUBMIC_EN|TWL4030_AUXR_EN);
+ micbias = twl4030_read_reg_cache(codec, TWL4030_REG_MICBIAS_CTL);
+ micbias &= ~TWL4030_MICBIAS2_EN;
+ avadc_ctl = twl4030_read_reg_cache(codec, TWL4030_REG_AVADC_CTL);
+
+ switch (value) {
+ case 1:
+ anamicr |= TWL4030_SUBMIC_EN;
+ micbias |= TWL4030_MICBIAS2_EN;
+ break;
+ case 2:
+ anamicr |= TWL4030_AUXR_EN;
+ break;
+ default:
+ break;
+ }
+
+ if (value != 0) {
+ anamicr |= TWL4030_MICAMPR_EN;
+ avadc_ctl |= TWL4030_ADCR_EN;
+ } else {
+ anamicr &= ~TWL4030_MICAMPR_EN;
+ avadc_ctl &= ~TWL4030_ADCR_EN;
+ }
+
+ twl4030_write(codec, TWL4030_REG_ANAMICR, anamicr);
+ twl4030_write(codec, TWL4030_REG_MICBIAS_CTL, micbias);
+ twl4030_write(codec, TWL4030_REG_AVADC_CTL, avadc_ctl);
+
+ return 1;
+}
+
+static const char *twl4030_left_in_sel[] = {
+ "None",
+ "Main Mic",
+ "Headset Mic",
+ "Line In",
+ "Carkit Mic",
+};
+
+static const char *twl4030_right_in_sel[] = {
+ "None",
+ "Sub Mic",
+ "Line In",
+};
+
+static const struct soc_enum twl4030_left_input_mux =
+ SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(twl4030_left_in_sel),
+ twl4030_left_in_sel);
+
+static const struct soc_enum twl4030_right_input_mux =
+ SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(twl4030_right_in_sel),
+ twl4030_right_in_sel);
+
+/*
+ * FGAIN volume control:
+ * from -62 to 0 dB in 1 dB steps (mute instead of -63 dB)
+ */
+static DECLARE_TLV_DB_SCALE(digital_fine_tlv, -6300, 100, 1);
+
+/*
+ * CGAIN volume control:
+ * 0 dB to 12 dB in 6 dB steps
+ * value 2 and 3 means 12 dB
+ */
+static DECLARE_TLV_DB_SCALE(digital_coarse_tlv, 0, 600, 0);
+
+/*
+ * Analog playback gain
+ * -24 dB to 12 dB in 2 dB steps
+ */
+static DECLARE_TLV_DB_SCALE(analog_tlv, -2400, 200, 0);
+
+/*
+ * Gain controls tied to outputs
+ * -6 dB to 6 dB in 6 dB steps (mute instead of -12)
+ */
+static DECLARE_TLV_DB_SCALE(output_tvl, -1200, 600, 1);
+
+/*
+ * Capture gain after the ADCs
+ * from 0 dB to 31 dB in 1 dB steps
+ */
+static DECLARE_TLV_DB_SCALE(digital_capture_tlv, 0, 100, 0);
+
+/*
+ * Gain control for input amplifiers
+ * 0 dB to 30 dB in 6 dB steps
+ */
+static DECLARE_TLV_DB_SCALE(input_gain_tlv, 0, 600, 0);
+
+static const struct snd_kcontrol_new twl4030_snd_controls[] = {
+ /* Common playback gain controls */
+ SOC_DOUBLE_R_TLV("DAC1 Digital Fine Playback Volume",
+ TWL4030_REG_ARXL1PGA, TWL4030_REG_ARXR1PGA,
+ 0, 0x3f, 0, digital_fine_tlv),
+ SOC_DOUBLE_R_TLV("DAC2 Digital Fine Playback Volume",
+ TWL4030_REG_ARXL2PGA, TWL4030_REG_ARXR2PGA,
+ 0, 0x3f, 0, digital_fine_tlv),
+
+ SOC_DOUBLE_R_TLV("DAC1 Digital Coarse Playback Volume",
+ TWL4030_REG_ARXL1PGA, TWL4030_REG_ARXR1PGA,
+ 6, 0x2, 0, digital_coarse_tlv),
+ SOC_DOUBLE_R_TLV("DAC2 Digital Coarse Playback Volume",
+ TWL4030_REG_ARXL2PGA, TWL4030_REG_ARXR2PGA,
+ 6, 0x2, 0, digital_coarse_tlv),
+
+ SOC_DOUBLE_R_TLV("DAC1 Analog Playback Volume",
+ TWL4030_REG_ARXL1_APGA_CTL, TWL4030_REG_ARXR1_APGA_CTL,
+ 3, 0x12, 1, analog_tlv),
+ SOC_DOUBLE_R_TLV("DAC2 Analog Playback Volume",
+ TWL4030_REG_ARXL2_APGA_CTL, TWL4030_REG_ARXR2_APGA_CTL,
+ 3, 0x12, 1, analog_tlv),
+ SOC_DOUBLE_R("DAC1 Analog Playback Switch",
+ TWL4030_REG_ARXL1_APGA_CTL, TWL4030_REG_ARXR1_APGA_CTL,
+ 1, 1, 0),
+ SOC_DOUBLE_R("DAC2 Analog Playback Switch",
+ TWL4030_REG_ARXL2_APGA_CTL, TWL4030_REG_ARXR2_APGA_CTL,
+ 1, 1, 0),
+
+ /* Separate output gain controls */
+ SOC_DOUBLE_R_TLV_TWL4030("PreDriv Playback Volume",
+ TWL4030_REG_PREDL_CTL, TWL4030_REG_PREDR_CTL,
+ 4, 3, 0, output_tvl),
+
+ SOC_DOUBLE_TLV_TWL4030("Headset Playback Volume",
+ TWL4030_REG_HS_GAIN_SET, 0, 2, 3, 0, output_tvl),
+
+ SOC_DOUBLE_R_TLV_TWL4030("Carkit Playback Volume",
+ TWL4030_REG_PRECKL_CTL, TWL4030_REG_PRECKR_CTL,
+ 4, 3, 0, output_tvl),
+
+ SOC_SINGLE_TLV_TWL4030("Earpiece Playback Volume",
+ TWL4030_REG_EAR_CTL, 4, 3, 0, output_tvl),
+
+ /* Common capture gain controls */
+ SOC_DOUBLE_R_TLV("Capture Volume",
+ TWL4030_REG_ATXL1PGA, TWL4030_REG_ATXR1PGA,
+ 0, 0x1f, 0, digital_capture_tlv),
+
+ SOC_DOUBLE_TLV("Input Boost Volume", TWL4030_REG_ANAMIC_GAIN,
+ 0, 3, 5, 0, input_gain_tlv),
+
+ /* Input source controls */
+ SOC_ENUM_EXT("Left Input Source", twl4030_left_input_mux,
+ twl4030_get_left_input, twl4030_put_left_input),
+ SOC_ENUM_EXT("Right Input Source", twl4030_right_input_mux,
+ twl4030_get_right_input, twl4030_put_right_input),
+};
+
+/* add non dapm controls */
+static int twl4030_add_controls(struct snd_soc_codec *codec)
+{
+ int err, i;
+
+ for (i = 0; i < ARRAY_SIZE(twl4030_snd_controls); i++) {
+ err = snd_ctl_add(codec->card,
+ snd_soc_cnew(&twl4030_snd_controls[i],
+ codec, NULL));
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
+ SND_SOC_DAPM_INPUT("INL"),
+ SND_SOC_DAPM_INPUT("INR"),
+
+ SND_SOC_DAPM_OUTPUT("OUTL"),
+ SND_SOC_DAPM_OUTPUT("OUTR"),
+ SND_SOC_DAPM_OUTPUT("EARPIECE"),
+ SND_SOC_DAPM_OUTPUT("PREDRIVEL"),
+ SND_SOC_DAPM_OUTPUT("PREDRIVER"),
+ SND_SOC_DAPM_OUTPUT("HSOL"),
+ SND_SOC_DAPM_OUTPUT("HSOR"),
+ SND_SOC_DAPM_OUTPUT("CARKITL"),
+ SND_SOC_DAPM_OUTPUT("CARKITR"),
+ SND_SOC_DAPM_OUTPUT("HFL"),
+ SND_SOC_DAPM_OUTPUT("HFR"),
+
+ /* DACs */
+ SND_SOC_DAPM_DAC("DAC Right1", "Right Front Playback",
+ TWL4030_REG_AVDAC_CTL, 0, 0),
+ SND_SOC_DAPM_DAC("DAC Left1", "Left Front Playback",
+ TWL4030_REG_AVDAC_CTL, 1, 0),
+ SND_SOC_DAPM_DAC("DAC Right2", "Right Rear Playback",
+ TWL4030_REG_AVDAC_CTL, 2, 0),
+ SND_SOC_DAPM_DAC("DAC Left2", "Left Rear Playback",
+ TWL4030_REG_AVDAC_CTL, 3, 0),
+
+ /* Analog PGAs */
+ SND_SOC_DAPM_PGA("ARXR1_APGA", TWL4030_REG_ARXR1_APGA_CTL,
+ 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("ARXL1_APGA", TWL4030_REG_ARXL1_APGA_CTL,
+ 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("ARXR2_APGA", TWL4030_REG_ARXR2_APGA_CTL,
+ 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("ARXL2_APGA", TWL4030_REG_ARXL2_APGA_CTL,
+ 0, 0, NULL, 0),
+
+ /* Output MUX controls */
+ /* Earpiece */
+ SND_SOC_DAPM_MUX_E("Earpiece Mux", SND_SOC_NOPM, 0, 0,
+ &twl4030_dapm_earpiece_control, outmixer_event,
+ SND_SOC_DAPM_PRE_REG),
+ /* PreDrivL/R */
+ SND_SOC_DAPM_MUX_E("PredriveL Mux", SND_SOC_NOPM, 0, 0,
+ &twl4030_dapm_predrivel_control, outmixer_event,
+ SND_SOC_DAPM_PRE_REG),
+ SND_SOC_DAPM_MUX_E("PredriveR Mux", SND_SOC_NOPM, 0, 0,
+ &twl4030_dapm_predriver_control, outmixer_event,
+ SND_SOC_DAPM_PRE_REG),
+ /* HeadsetL/R */
+ SND_SOC_DAPM_MUX("HeadsetL Mux", SND_SOC_NOPM, 0, 0,
+ &twl4030_dapm_hsol_control),
+ SND_SOC_DAPM_MUX("HeadsetR Mux", SND_SOC_NOPM, 0, 0,
+ &twl4030_dapm_hsor_control),
+ /* CarkitL/R */
+ SND_SOC_DAPM_MUX("CarkitL Mux", SND_SOC_NOPM, 0, 0,
+ &twl4030_dapm_carkitl_control),
+ SND_SOC_DAPM_MUX("CarkitR Mux", SND_SOC_NOPM, 0, 0,
+ &twl4030_dapm_carkitr_control),
+ /* HandsfreeL/R */
+ SND_SOC_DAPM_MUX_E("HandsfreeL Mux", TWL4030_REG_HFL_CTL, 5, 0,
+ &twl4030_dapm_handsfreel_control, handsfree_event,
+ SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("HandsfreeR Mux", TWL4030_REG_HFR_CTL, 5, 0,
+ &twl4030_dapm_handsfreer_control, handsfree_event,
+ SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_ADC("ADCL", "Left Capture", SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_ADC("ADCR", "Right Capture", SND_SOC_NOPM, 0, 0),
+};
+
+static const struct snd_soc_dapm_route intercon[] = {
+ {"ARXL1_APGA", NULL, "DAC Left1"},
+ {"ARXR1_APGA", NULL, "DAC Right1"},
+ {"ARXL2_APGA", NULL, "DAC Left2"},
+ {"ARXR2_APGA", NULL, "DAC Right2"},
+
+ /* Internal playback routings */
+ /* Earpiece */
+ {"Earpiece Mux", "DACL1", "ARXL1_APGA"},
+ {"Earpiece Mux", "DACL2", "ARXL2_APGA"},
+ {"Earpiece Mux", "DACR1", "ARXR1_APGA"},
+ /* PreDrivL */
+ {"PredriveL Mux", "DACL1", "ARXL1_APGA"},
+ {"PredriveL Mux", "DACL2", "ARXL2_APGA"},
+ {"PredriveL Mux", "DACR2", "ARXR2_APGA"},
+ /* PreDrivR */
+ {"PredriveR Mux", "DACR1", "ARXR1_APGA"},
+ {"PredriveR Mux", "DACR2", "ARXR2_APGA"},
+ {"PredriveR Mux", "DACL2", "ARXL2_APGA"},
+ /* HeadsetL */
+ {"HeadsetL Mux", "DACL1", "ARXL1_APGA"},
+ {"HeadsetL Mux", "DACL2", "ARXL2_APGA"},
+ /* HeadsetR */
+ {"HeadsetR Mux", "DACR1", "ARXR1_APGA"},
+ {"HeadsetR Mux", "DACR2", "ARXR2_APGA"},
+ /* CarkitL */
+ {"CarkitL Mux", "DACL1", "ARXL1_APGA"},
+ {"CarkitL Mux", "DACL2", "ARXL2_APGA"},
+ /* CarkitR */
+ {"CarkitR Mux", "DACR1", "ARXR1_APGA"},
+ {"CarkitR Mux", "DACR2", "ARXR2_APGA"},
+ /* HandsfreeL */
+ {"HandsfreeL Mux", "DACL1", "ARXL1_APGA"},
+ {"HandsfreeL Mux", "DACL2", "ARXL2_APGA"},
+ {"HandsfreeL Mux", "DACR2", "ARXR2_APGA"},
+ /* HandsfreeR */
+ {"HandsfreeR Mux", "DACR1", "ARXR1_APGA"},
+ {"HandsfreeR Mux", "DACR2", "ARXR2_APGA"},
+ {"HandsfreeR Mux", "DACL2", "ARXL2_APGA"},
+
+ /* outputs */
+ {"OUTL", NULL, "ARXL2_APGA"},
+ {"OUTR", NULL, "ARXR2_APGA"},
+ {"EARPIECE", NULL, "Earpiece Mux"},
+ {"PREDRIVEL", NULL, "PredriveL Mux"},
+ {"PREDRIVER", NULL, "PredriveR Mux"},
+ {"HSOL", NULL, "HeadsetL Mux"},
+ {"HSOR", NULL, "HeadsetR Mux"},
+ {"CARKITL", NULL, "CarkitL Mux"},
+ {"CARKITR", NULL, "CarkitR Mux"},
+ {"HFL", NULL, "HandsfreeL Mux"},
+ {"HFR", NULL, "HandsfreeR Mux"},
+
+ /* inputs */
+ {"ADCL", NULL, "INL"},
+ {"ADCR", NULL, "INR"},
+};
+
+static int twl4030_add_widgets(struct snd_soc_codec *codec)
+{
+ snd_soc_dapm_new_controls(codec, twl4030_dapm_widgets,
+ ARRAY_SIZE(twl4030_dapm_widgets));
+
+ snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
+
+ snd_soc_dapm_new_widgets(codec);
+ return 0;
+}
+
+static void twl4030_power_up(struct snd_soc_codec *codec)
+{
+ u8 anamicl, regmisc1, byte, popn;
+ int i = 0;
+
+ /* set CODECPDZ to turn on codec */
+ twl4030_set_codecpdz(codec);
+
+ /* initiate offset cancellation */
+ anamicl = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICL);
+ twl4030_write(codec, TWL4030_REG_ANAMICL,
+ anamicl | TWL4030_CNCL_OFFSET_START);
+
+ /* wait for offset cancellation to complete */
+ do {
+ /* this takes a little while, so don't slam i2c */
+ udelay(2000);
+ twl4030_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &byte,
+ TWL4030_REG_ANAMICL);
+ } while ((i++ < 100) &&
+ ((byte & TWL4030_CNCL_OFFSET_START) ==
+ TWL4030_CNCL_OFFSET_START));
+
+ /* anti-pop when changing analog gain */
+ regmisc1 = twl4030_read_reg_cache(codec, TWL4030_REG_MISC_SET_1);
+ twl4030_write(codec, TWL4030_REG_MISC_SET_1,
+ regmisc1 | TWL4030_SMOOTH_ANAVOL_EN);
+
+ /* toggle CODECPDZ as per TRM */
+ twl4030_clear_codecpdz(codec);
+ twl4030_set_codecpdz(codec);
+
+ /* program anti-pop with bias ramp delay */
+ popn = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET);
+ popn &= TWL4030_RAMP_DELAY;
+ popn |= TWL4030_RAMP_DELAY_645MS;
+ twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn);
+ popn |= TWL4030_VMID_EN;
+ twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn);
+
+ /* enable anti-pop ramp */
+ popn |= TWL4030_RAMP_EN;
+ twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn);
+}
+
+static void twl4030_power_down(struct snd_soc_codec *codec)
+{
+ u8 popn;
+
+ /* disable anti-pop ramp */
+ popn = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET);
+ popn &= ~TWL4030_RAMP_EN;
+ twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn);
+
+ /* disable bias out */
+ popn &= ~TWL4030_VMID_EN;
+ twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn);
+
+ /* power down */
+ twl4030_clear_codecpdz(codec);
+}
+
+static int twl4030_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ switch (level) {
+ case SND_SOC_BIAS_ON:
+ twl4030_power_up(codec);
+ break;
+ case SND_SOC_BIAS_PREPARE:
+ /* TODO: develop a twl4030_prepare function */
+ break;
+ case SND_SOC_BIAS_STANDBY:
+ /* TODO: develop a twl4030_standby function */
+ twl4030_power_down(codec);
+ break;
+ case SND_SOC_BIAS_OFF:
+ twl4030_power_down(codec);
+ break;
+ }
+ codec->bias_level = level;
+
+ return 0;
+}
+
+static int twl4030_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_device *socdev = rtd->socdev;
+ struct snd_soc_codec *codec = socdev->codec;
+ u8 mode, old_mode, format, old_format;
+
+
+ /* bit rate */
+ old_mode = twl4030_read_reg_cache(codec,
+ TWL4030_REG_CODEC_MODE) & ~TWL4030_CODECPDZ;
+ mode = old_mode & ~TWL4030_APLL_RATE;
+
+ switch (params_rate(params)) {
+ case 8000:
+ mode |= TWL4030_APLL_RATE_8000;
+ break;
+ case 11025:
+ mode |= TWL4030_APLL_RATE_11025;
+ break;
+ case 12000:
+ mode |= TWL4030_APLL_RATE_12000;
+ break;
+ case 16000:
+ mode |= TWL4030_APLL_RATE_16000;
+ break;
+ case 22050:
+ mode |= TWL4030_APLL_RATE_22050;
+ break;
+ case 24000:
+ mode |= TWL4030_APLL_RATE_24000;
+ break;
+ case 32000:
+ mode |= TWL4030_APLL_RATE_32000;
+ break;
+ case 44100:
+ mode |= TWL4030_APLL_RATE_44100;
+ break;
+ case 48000:
+ mode |= TWL4030_APLL_RATE_48000;
+ break;
+ default:
+ printk(KERN_ERR "TWL4030 hw params: unknown rate %d\n",
+ params_rate(params));
+ return -EINVAL;
+ }
+
+ if (mode != old_mode) {
+ /* change rate and set CODECPDZ */
+ twl4030_write(codec, TWL4030_REG_CODEC_MODE, mode);
+ twl4030_set_codecpdz(codec);
+ }
+
+ /* sample size */
+ old_format = twl4030_read_reg_cache(codec, TWL4030_REG_AUDIO_IF);
+ format = old_format;
+ format &= ~TWL4030_DATA_WIDTH;
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ format |= TWL4030_DATA_WIDTH_16S_16W;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ format |= TWL4030_DATA_WIDTH_32S_24W;
+ break;
+ default:
+ printk(KERN_ERR "TWL4030 hw params: unknown format %d\n",
+ params_format(params));
+ return -EINVAL;
+ }
+
+ if (format != old_format) {
+
+ /* clear CODECPDZ before changing format (codec requirement) */
+ twl4030_clear_codecpdz(codec);
+
+ /* change format */
+ twl4030_write(codec, TWL4030_REG_AUDIO_IF, format);
+
+ /* set CODECPDZ afterwards */
+ twl4030_set_codecpdz(codec);
+ }
+ return 0;
+}
+
+static int twl4030_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ u8 infreq;
+
+ switch (freq) {
+ case 19200000:
+ infreq = TWL4030_APLL_INFREQ_19200KHZ;
+ break;
+ case 26000000:
+ infreq = TWL4030_APLL_INFREQ_26000KHZ;
+ break;
+ case 38400000:
+ infreq = TWL4030_APLL_INFREQ_38400KHZ;
+ break;
+ default:
+ printk(KERN_ERR "TWL4030 set sysclk: unknown rate %d\n",
+ freq);
+ return -EINVAL;
+ }
+
+ infreq |= TWL4030_APLL_EN;
+ twl4030_write(codec, TWL4030_REG_APLL_CTL, infreq);
+
+ return 0;
+}
+
+static int twl4030_set_dai_fmt(struct snd_soc_dai *codec_dai,
+ unsigned int fmt)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ u8 old_format, format;
+
+ /* get format */
+ old_format = twl4030_read_reg_cache(codec, TWL4030_REG_AUDIO_IF);
+ format = old_format;
+
+ /* set master/slave audio interface */
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ format &= ~(TWL4030_AIF_SLAVE_EN);
+ format &= ~(TWL4030_CLK256FS_EN);
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ format |= TWL4030_AIF_SLAVE_EN;
+ format |= TWL4030_CLK256FS_EN;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* interface format */
+ format &= ~TWL4030_AIF_FORMAT;
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ format |= TWL4030_AIF_FORMAT_CODEC;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (format != old_format) {
+
+ /* clear CODECPDZ before changing format (codec requirement) */
+ twl4030_clear_codecpdz(codec);
+
+ /* change format */
+ twl4030_write(codec, TWL4030_REG_AUDIO_IF, format);
+
+ /* set CODECPDZ afterwards */
+ twl4030_set_codecpdz(codec);
+ }
+
+ return 0;
+}
+
+#define TWL4030_RATES (SNDRV_PCM_RATE_8000_48000)
+#define TWL4030_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE)
+
+struct snd_soc_dai twl4030_dai = {
+ .name = "twl4030",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = TWL4030_RATES,
+ .formats = TWL4030_FORMATS,},
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = TWL4030_RATES,
+ .formats = TWL4030_FORMATS,},
+ .ops = {
+ .hw_params = twl4030_hw_params,
+ .set_sysclk = twl4030_set_dai_sysclk,
+ .set_fmt = twl4030_set_dai_fmt,
+ }
+};
+EXPORT_SYMBOL_GPL(twl4030_dai);
+
+static int twl4030_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec = socdev->codec;
+
+ twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+ return 0;
+}
+
+static int twl4030_resume(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec = socdev->codec;
+
+ twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+ twl4030_set_bias_level(codec, codec->suspend_bias_level);
+ return 0;
+}
+
+/*
+ * initialize the driver
+ * register the mixer and dsp interfaces with the kernel
+ */
+
+static int twl4030_init(struct snd_soc_device *socdev)
+{
+ struct snd_soc_codec *codec = socdev->codec;
+ int ret = 0;
+
+ printk(KERN_INFO "TWL4030 Audio Codec init \n");
+
+ codec->name = "twl4030";
+ codec->owner = THIS_MODULE;
+ codec->read = twl4030_read_reg_cache;
+ codec->write = twl4030_write;
+ codec->set_bias_level = twl4030_set_bias_level;
+ codec->dai = &twl4030_dai;
+ codec->num_dai = 1;
+ codec->reg_cache_size = sizeof(twl4030_reg);
+ codec->reg_cache = kmemdup(twl4030_reg, sizeof(twl4030_reg),
+ GFP_KERNEL);
+ if (codec->reg_cache == NULL)
+ return -ENOMEM;
+
+ /* register pcms */
+ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+ if (ret < 0) {
+ printk(KERN_ERR "twl4030: failed to create pcms\n");
+ goto pcm_err;
+ }
+
+ twl4030_init_chip(codec);
+
+ /* power on device */
+ twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+ twl4030_add_controls(codec);
+ twl4030_add_widgets(codec);
+
+ ret = snd_soc_init_card(socdev);
+ if (ret < 0) {
+ printk(KERN_ERR "twl4030: failed to register card\n");
+ goto card_err;
+ }
+
+ return ret;
+
+card_err:
+ snd_soc_free_pcms(socdev);
+ snd_soc_dapm_free(socdev);
+pcm_err:
+ kfree(codec->reg_cache);
+ return ret;
+}
+
+static struct snd_soc_device *twl4030_socdev;
+
+static int twl4030_probe(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec;
+
+ codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
+ if (codec == NULL)
+ return -ENOMEM;
+
+ socdev->codec = codec;
+ mutex_init(&codec->mutex);
+ INIT_LIST_HEAD(&codec->dapm_widgets);
+ INIT_LIST_HEAD(&codec->dapm_paths);
+
+ twl4030_socdev = socdev;
+ twl4030_init(socdev);
+
+ return 0;
+}
+
+static int twl4030_remove(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec = socdev->codec;
+
+ printk(KERN_INFO "TWL4030 Audio Codec remove\n");
+ kfree(codec);
+
+ return 0;
+}
+
+struct snd_soc_codec_device soc_codec_dev_twl4030 = {
+ .probe = twl4030_probe,
+ .remove = twl4030_remove,
+ .suspend = twl4030_suspend,
+ .resume = twl4030_resume,
+};
+EXPORT_SYMBOL_GPL(soc_codec_dev_twl4030);
+
+static int __init twl4030_modinit(void)
+{
+ return snd_soc_register_dai(&twl4030_dai);
+}
+module_init(twl4030_modinit);
+
+static void __exit twl4030_exit(void)
+{
+ snd_soc_unregister_dai(&twl4030_dai);
+}
+module_exit(twl4030_exit);
+
+MODULE_DESCRIPTION("ASoC TWL4030 codec driver");
+MODULE_AUTHOR("Steve Sakoman");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/twl4030.h b/sound/soc/codecs/twl4030.h
new file mode 100644
index 00000000000..54615c76802
--- /dev/null
+++ b/sound/soc/codecs/twl4030.h
@@ -0,0 +1,219 @@
+/*
+ * ALSA SoC TWL4030 codec driver
+ *
+ * Author: Steve Sakoman <steve@sakoman.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __TWL4030_AUDIO_H__
+#define __TWL4030_AUDIO_H__
+
+#define TWL4030_REG_CODEC_MODE 0x1
+#define TWL4030_REG_OPTION 0x2
+#define TWL4030_REG_UNKNOWN 0x3
+#define TWL4030_REG_MICBIAS_CTL 0x4
+#define TWL4030_REG_ANAMICL 0x5
+#define TWL4030_REG_ANAMICR 0x6
+#define TWL4030_REG_AVADC_CTL 0x7
+#define TWL4030_REG_ADCMICSEL 0x8
+#define TWL4030_REG_DIGMIXING 0x9
+#define TWL4030_REG_ATXL1PGA 0xA
+#define TWL4030_REG_ATXR1PGA 0xB
+#define TWL4030_REG_AVTXL2PGA 0xC
+#define TWL4030_REG_AVTXR2PGA 0xD
+#define TWL4030_REG_AUDIO_IF 0xE
+#define TWL4030_REG_VOICE_IF 0xF
+#define TWL4030_REG_ARXR1PGA 0x10
+#define TWL4030_REG_ARXL1PGA 0x11
+#define TWL4030_REG_ARXR2PGA 0x12
+#define TWL4030_REG_ARXL2PGA 0x13
+#define TWL4030_REG_VRXPGA 0x14
+#define TWL4030_REG_VSTPGA 0x15
+#define TWL4030_REG_VRX2ARXPGA 0x16
+#define TWL4030_REG_AVDAC_CTL 0x17
+#define TWL4030_REG_ARX2VTXPGA 0x18
+#define TWL4030_REG_ARXL1_APGA_CTL 0x19
+#define TWL4030_REG_ARXR1_APGA_CTL 0x1A
+#define TWL4030_REG_ARXL2_APGA_CTL 0x1B
+#define TWL4030_REG_ARXR2_APGA_CTL 0x1C
+#define TWL4030_REG_ATX2ARXPGA 0x1D
+#define TWL4030_REG_BT_IF 0x1E
+#define TWL4030_REG_BTPGA 0x1F
+#define TWL4030_REG_BTSTPGA 0x20
+#define TWL4030_REG_EAR_CTL 0x21
+#define TWL4030_REG_HS_SEL 0x22
+#define TWL4030_REG_HS_GAIN_SET 0x23
+#define TWL4030_REG_HS_POPN_SET 0x24
+#define TWL4030_REG_PREDL_CTL 0x25
+#define TWL4030_REG_PREDR_CTL 0x26
+#define TWL4030_REG_PRECKL_CTL 0x27
+#define TWL4030_REG_PRECKR_CTL 0x28
+#define TWL4030_REG_HFL_CTL 0x29
+#define TWL4030_REG_HFR_CTL 0x2A
+#define TWL4030_REG_ALC_CTL 0x2B
+#define TWL4030_REG_ALC_SET1 0x2C
+#define TWL4030_REG_ALC_SET2 0x2D
+#define TWL4030_REG_BOOST_CTL 0x2E
+#define TWL4030_REG_SOFTVOL_CTL 0x2F
+#define TWL4030_REG_DTMF_FREQSEL 0x30
+#define TWL4030_REG_DTMF_TONEXT1H 0x31
+#define TWL4030_REG_DTMF_TONEXT1L 0x32
+#define TWL4030_REG_DTMF_TONEXT2H 0x33
+#define TWL4030_REG_DTMF_TONEXT2L 0x34
+#define TWL4030_REG_DTMF_TONOFF 0x35
+#define TWL4030_REG_DTMF_WANONOFF 0x36
+#define TWL4030_REG_I2S_RX_SCRAMBLE_H 0x37
+#define TWL4030_REG_I2S_RX_SCRAMBLE_M 0x38
+#define TWL4030_REG_I2S_RX_SCRAMBLE_L 0x39
+#define TWL4030_REG_APLL_CTL 0x3A
+#define TWL4030_REG_DTMF_CTL 0x3B
+#define TWL4030_REG_DTMF_PGA_CTL2 0x3C
+#define TWL4030_REG_DTMF_PGA_CTL1 0x3D
+#define TWL4030_REG_MISC_SET_1 0x3E
+#define TWL4030_REG_PCMBTMUX 0x3F
+#define TWL4030_REG_RX_PATH_SEL 0x43
+#define TWL4030_REG_VDL_APGA_CTL 0x44
+#define TWL4030_REG_VIBRA_CTL 0x45
+#define TWL4030_REG_VIBRA_SET 0x46
+#define TWL4030_REG_VIBRA_PWM_SET 0x47
+#define TWL4030_REG_ANAMIC_GAIN 0x48
+#define TWL4030_REG_MISC_SET_2 0x49
+
+#define TWL4030_CACHEREGNUM (TWL4030_REG_MISC_SET_2 + 1)
+
+/* Bitfield Definitions */
+
+/* TWL4030_CODEC_MODE (0x01) Fields */
+
+#define TWL4030_APLL_RATE 0xF0
+#define TWL4030_APLL_RATE_8000 0x00
+#define TWL4030_APLL_RATE_11025 0x10
+#define TWL4030_APLL_RATE_12000 0x20
+#define TWL4030_APLL_RATE_16000 0x40
+#define TWL4030_APLL_RATE_22050 0x50
+#define TWL4030_APLL_RATE_24000 0x60
+#define TWL4030_APLL_RATE_32000 0x80
+#define TWL4030_APLL_RATE_44100 0x90
+#define TWL4030_APLL_RATE_48000 0xA0
+#define TWL4030_SEL_16K 0x04
+#define TWL4030_CODECPDZ 0x02
+#define TWL4030_OPT_MODE 0x01
+
+/* TWL4030_REG_MICBIAS_CTL (0x04) Fields */
+
+#define TWL4030_MICBIAS2_CTL 0x40
+#define TWL4030_MICBIAS1_CTL 0x20
+#define TWL4030_HSMICBIAS_EN 0x04
+#define TWL4030_MICBIAS2_EN 0x02
+#define TWL4030_MICBIAS1_EN 0x01
+
+/* ANAMICL (0x05) Fields */
+
+#define TWL4030_CNCL_OFFSET_START 0x80
+#define TWL4030_OFFSET_CNCL_SEL 0x60
+#define TWL4030_OFFSET_CNCL_SEL_ARX1 0x00
+#define TWL4030_OFFSET_CNCL_SEL_ARX2 0x20
+#define TWL4030_OFFSET_CNCL_SEL_VRX 0x40
+#define TWL4030_OFFSET_CNCL_SEL_ALL 0x60
+#define TWL4030_MICAMPL_EN 0x10
+#define TWL4030_CKMIC_EN 0x08
+#define TWL4030_AUXL_EN 0x04
+#define TWL4030_HSMIC_EN 0x02
+#define TWL4030_MAINMIC_EN 0x01
+
+/* ANAMICR (0x06) Fields */
+
+#define TWL4030_MICAMPR_EN 0x10
+#define TWL4030_AUXR_EN 0x04
+#define TWL4030_SUBMIC_EN 0x01
+
+/* AVADC_CTL (0x07) Fields */
+
+#define TWL4030_ADCL_EN 0x08
+#define TWL4030_AVADC_CLK_PRIORITY 0x04
+#define TWL4030_ADCR_EN 0x02
+
+/* AUDIO_IF (0x0E) Fields */
+
+#define TWL4030_AIF_SLAVE_EN 0x80
+#define TWL4030_DATA_WIDTH 0x60
+#define TWL4030_DATA_WIDTH_16S_16W 0x00
+#define TWL4030_DATA_WIDTH_32S_16W 0x40
+#define TWL4030_DATA_WIDTH_32S_24W 0x60
+#define TWL4030_AIF_FORMAT 0x18
+#define TWL4030_AIF_FORMAT_CODEC 0x00
+#define TWL4030_AIF_FORMAT_LEFT 0x08
+#define TWL4030_AIF_FORMAT_RIGHT 0x10
+#define TWL4030_AIF_FORMAT_TDM 0x18
+#define TWL4030_AIF_TRI_EN 0x04
+#define TWL4030_CLK256FS_EN 0x02
+#define TWL4030_AIF_EN 0x01
+
+/* HS_GAIN_SET (0x23) Fields */
+
+#define TWL4030_HSR_GAIN 0x0C
+#define TWL4030_HSR_GAIN_PWR_DOWN 0x00
+#define TWL4030_HSR_GAIN_PLUS_6DB 0x04
+#define TWL4030_HSR_GAIN_0DB 0x08
+#define TWL4030_HSR_GAIN_MINUS_6DB 0x0C
+#define TWL4030_HSL_GAIN 0x03
+#define TWL4030_HSL_GAIN_PWR_DOWN 0x00
+#define TWL4030_HSL_GAIN_PLUS_6DB 0x01
+#define TWL4030_HSL_GAIN_0DB 0x02
+#define TWL4030_HSL_GAIN_MINUS_6DB 0x03
+
+/* HS_POPN_SET (0x24) Fields */
+
+#define TWL4030_VMID_EN 0x40
+#define TWL4030_EXTMUTE 0x20
+#define TWL4030_RAMP_DELAY 0x1C
+#define TWL4030_RAMP_DELAY_20MS 0x00
+#define TWL4030_RAMP_DELAY_40MS 0x04
+#define TWL4030_RAMP_DELAY_81MS 0x08
+#define TWL4030_RAMP_DELAY_161MS 0x0C
+#define TWL4030_RAMP_DELAY_323MS 0x10
+#define TWL4030_RAMP_DELAY_645MS 0x14
+#define TWL4030_RAMP_DELAY_1291MS 0x18
+#define TWL4030_RAMP_DELAY_2581MS 0x1C
+#define TWL4030_RAMP_EN 0x02
+
+/* HFL_CTL (0x29, 0x2A) Fields */
+#define TWL4030_HF_CTL_HB_EN 0x04
+#define TWL4030_HF_CTL_LOOP_EN 0x08
+#define TWL4030_HF_CTL_RAMP_EN 0x10
+#define TWL4030_HF_CTL_REF_EN 0x20
+
+/* APLL_CTL (0x3A) Fields */
+
+#define TWL4030_APLL_EN 0x10
+#define TWL4030_APLL_INFREQ 0x0F
+#define TWL4030_APLL_INFREQ_19200KHZ 0x05
+#define TWL4030_APLL_INFREQ_26000KHZ 0x06
+#define TWL4030_APLL_INFREQ_38400KHZ 0x0F
+
+/* REG_MISC_SET_1 (0x3E) Fields */
+
+#define TWL4030_CLK64_EN 0x80
+#define TWL4030_SCRAMBLE_EN 0x40
+#define TWL4030_FMLOOP_EN 0x20
+#define TWL4030_SMOOTH_ANAVOL_EN 0x02
+#define TWL4030_DIGMIC_LR_SWAP_EN 0x01
+
+extern struct snd_soc_dai twl4030_dai;
+extern struct snd_soc_codec_device soc_codec_dev_twl4030;
+
+#endif /* End of __TWL4030_AUDIO_H__ */
diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c
new file mode 100644
index 00000000000..a2c5064a774
--- /dev/null
+++ b/sound/soc/codecs/uda134x.c
@@ -0,0 +1,668 @@
+/*
+ * uda134x.c -- UDA134X ALSA SoC Codec driver
+ *
+ * Modifications by Christian Pellegrin <chripell@evolware.org>
+ *
+ * Copyright 2007 Dension Audio Systems Ltd.
+ * Author: Zoltan Devai
+ *
+ * Based on the WM87xx drivers by Liam Girdwood and Richard Purdie
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+
+#include <sound/uda134x.h>
+#include <sound/l3.h>
+
+#include "uda134x.h"
+
+
+#define POWER_OFF_ON_STANDBY 1
+/*
+ ALSA SOC usually puts the device in standby mode when it's not used
+ for sometime. If you define POWER_OFF_ON_STANDBY the driver will
+ turn off the ADC/DAC when this callback is invoked and turn it back
+ on when needed. Unfortunately this will result in a very light bump
+ (it can be audible only with good earphones). If this bothers you
+ just comment this line, you will have slightly higher power
+ consumption . Please note that sending the L3 command for ADC is
+ enough to make the bump, so it doesn't make difference if you
+ completely take off power from the codec.
+ */
+
+#define UDA134X_RATES SNDRV_PCM_RATE_8000_48000
+#define UDA134X_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S20_3LE)
+
+struct uda134x_priv {
+ int sysclk;
+ int dai_fmt;
+
+ struct snd_pcm_substream *master_substream;
+ struct snd_pcm_substream *slave_substream;
+};
+
+/* In-data addresses are hard-coded into the reg-cache values */
+static const char uda134x_reg[UDA134X_REGS_NUM] = {
+ /* Extended address registers */
+ 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+ /* Status, data regs */
+ 0x00, 0x83, 0x00, 0x40, 0x80, 0x00,
+};
+
+/*
+ * The codec has no support for reading its registers except for peak level...
+ */
+static inline unsigned int uda134x_read_reg_cache(struct snd_soc_codec *codec,
+ unsigned int reg)
+{
+ u8 *cache = codec->reg_cache;
+
+ if (reg >= UDA134X_REGS_NUM)
+ return -1;
+ return cache[reg];
+}
+
+/*
+ * Write the register cache
+ */
+static inline void uda134x_write_reg_cache(struct snd_soc_codec *codec,
+ u8 reg, unsigned int value)
+{
+ u8 *cache = codec->reg_cache;
+
+ if (reg >= UDA134X_REGS_NUM)
+ return;
+ cache[reg] = value;
+}
+
+/*
+ * Write to the uda134x registers
+ *
+ */
+static int uda134x_write(struct snd_soc_codec *codec, unsigned int reg,
+ unsigned int value)
+{
+ int ret;
+ u8 addr;
+ u8 data = value;
+ struct uda134x_platform_data *pd = codec->control_data;
+
+ pr_debug("%s reg: %02X, value:%02X\n", __func__, reg, value);
+
+ if (reg >= UDA134X_REGS_NUM) {
+ printk(KERN_ERR "%s unkown register: reg: %d",
+ __func__, reg);
+ return -EINVAL;
+ }
+
+ uda134x_write_reg_cache(codec, reg, value);
+
+ switch (reg) {
+ case UDA134X_STATUS0:
+ case UDA134X_STATUS1:
+ addr = UDA134X_STATUS_ADDR;
+ break;
+ case UDA134X_DATA000:
+ case UDA134X_DATA001:
+ case UDA134X_DATA010:
+ addr = UDA134X_DATA0_ADDR;
+ break;
+ case UDA134X_DATA1:
+ addr = UDA134X_DATA1_ADDR;
+ break;
+ default:
+ /* It's an extended address register */
+ addr = (reg | UDA134X_EXTADDR_PREFIX);
+
+ ret = l3_write(&pd->l3,
+ UDA134X_DATA0_ADDR, &addr, 1);
+ if (ret != 1)
+ return -EIO;
+
+ addr = UDA134X_DATA0_ADDR;
+ data = (value | UDA134X_EXTDATA_PREFIX);
+ break;
+ }
+
+ ret = l3_write(&pd->l3,
+ addr, &data, 1);
+ if (ret != 1)
+ return -EIO;
+
+ return 0;
+}
+
+static inline void uda134x_reset(struct snd_soc_codec *codec)
+{
+ u8 reset_reg = uda134x_read_reg_cache(codec, UDA134X_STATUS0);
+ uda134x_write(codec, UDA134X_STATUS0, reset_reg | (1<<6));
+ msleep(1);
+ uda134x_write(codec, UDA134X_STATUS0, reset_reg & ~(1<<6));
+}
+
+static int uda134x_mute(struct snd_soc_dai *dai, int mute)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ u8 mute_reg = uda134x_read_reg_cache(codec, UDA134X_DATA010);
+
+ pr_debug("%s mute: %d\n", __func__, mute);
+
+ if (mute)
+ mute_reg |= (1<<2);
+ else
+ mute_reg &= ~(1<<2);
+
+ uda134x_write(codec, UDA134X_DATA010, mute_reg & ~(1<<2));
+
+ return 0;
+}
+
+static int uda134x_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_device *socdev = rtd->socdev;
+ struct snd_soc_codec *codec = socdev->codec;
+ struct uda134x_priv *uda134x = codec->private_data;
+ struct snd_pcm_runtime *master_runtime;
+
+ if (uda134x->master_substream) {
+ master_runtime = uda134x->master_substream->runtime;
+
+ pr_debug("%s constraining to %d bits at %d\n", __func__,
+ master_runtime->sample_bits,
+ master_runtime->rate);
+
+ snd_pcm_hw_constraint_minmax(substream->runtime,
+ SNDRV_PCM_HW_PARAM_RATE,
+ master_runtime->rate,
+ master_runtime->rate);
+
+ snd_pcm_hw_constraint_minmax(substream->runtime,
+ SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
+ master_runtime->sample_bits,
+ master_runtime->sample_bits);
+
+ uda134x->slave_substream = substream;
+ } else
+ uda134x->master_substream = substream;
+
+ return 0;
+}
+
+static void uda134x_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_device *socdev = rtd->socdev;
+ struct snd_soc_codec *codec = socdev->codec;
+ struct uda134x_priv *uda134x = codec->private_data;
+
+ if (uda134x->master_substream == substream)
+ uda134x->master_substream = uda134x->slave_substream;
+
+ uda134x->slave_substream = NULL;
+}
+
+static int uda134x_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_device *socdev = rtd->socdev;
+ struct snd_soc_codec *codec = socdev->codec;
+ struct uda134x_priv *uda134x = codec->private_data;
+ u8 hw_params;
+
+ if (substream == uda134x->slave_substream) {
+ pr_debug("%s ignoring hw_params for slave substream\n",
+ __func__);
+ return 0;
+ }
+
+ hw_params = uda134x_read_reg_cache(codec, UDA134X_STATUS0);
+ hw_params &= STATUS0_SYSCLK_MASK;
+ hw_params &= STATUS0_DAIFMT_MASK;
+
+ pr_debug("%s sysclk: %d, rate:%d\n", __func__,
+ uda134x->sysclk, params_rate(params));
+
+ /* set SYSCLK / fs ratio */
+ switch (uda134x->sysclk / params_rate(params)) {
+ case 512:
+ break;
+ case 384:
+ hw_params |= (1<<4);
+ break;
+ case 256:
+ hw_params |= (1<<5);
+ break;
+ default:
+ printk(KERN_ERR "%s unsupported fs\n", __func__);
+ return -EINVAL;
+ }
+
+ pr_debug("%s dai_fmt: %d, params_format:%d\n", __func__,
+ uda134x->dai_fmt, params_format(params));
+
+ /* set DAI format and word length */
+ switch (uda134x->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ hw_params |= (1<<1);
+ break;
+ case SNDRV_PCM_FORMAT_S18_3LE:
+ hw_params |= (1<<2);
+ break;
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ hw_params |= ((1<<2) | (1<<1));
+ break;
+ default:
+ printk(KERN_ERR "%s unsupported format (right)\n",
+ __func__);
+ return -EINVAL;
+ }
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ hw_params |= (1<<3);
+ break;
+ default:
+ printk(KERN_ERR "%s unsupported format\n", __func__);
+ return -EINVAL;
+ }
+
+ uda134x_write(codec, UDA134X_STATUS0, hw_params);
+
+ return 0;
+}
+
+static int uda134x_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct uda134x_priv *uda134x = codec->private_data;
+
+ pr_debug("%s clk_id: %d, freq: %d, dir: %d\n", __func__,
+ clk_id, freq, dir);
+
+ /* Anything between 256fs*8Khz and 512fs*48Khz should be acceptable
+ because the codec is slave. Of course limitations of the clock
+ master (the IIS controller) apply.
+ We'll error out on set_hw_params if it's not OK */
+ if ((freq >= (256 * 8000)) && (freq <= (512 * 48000))) {
+ uda134x->sysclk = freq;
+ return 0;
+ }
+
+ printk(KERN_ERR "%s unsupported sysclk\n", __func__);
+ return -EINVAL;
+}
+
+static int uda134x_set_dai_fmt(struct snd_soc_dai *codec_dai,
+ unsigned int fmt)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct uda134x_priv *uda134x = codec->private_data;
+
+ pr_debug("%s fmt: %08X\n", __func__, fmt);
+
+ /* codec supports only full slave mode */
+ if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) {
+ printk(KERN_ERR "%s unsupported slave mode\n", __func__);
+ return -EINVAL;
+ }
+
+ /* no support for clock inversion */
+ if ((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_NF) {
+ printk(KERN_ERR "%s unsupported clock inversion\n", __func__);
+ return -EINVAL;
+ }
+
+ /* We can't setup DAI format here as it depends on the word bit num */
+ /* so let's just store the value for later */
+ uda134x->dai_fmt = fmt;
+
+ return 0;
+}
+
+static int uda134x_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ u8 reg;
+ struct uda134x_platform_data *pd = codec->control_data;
+ int i;
+ u8 *cache = codec->reg_cache;
+
+ pr_debug("%s bias level %d\n", __func__, level);
+
+ switch (level) {
+ case SND_SOC_BIAS_ON:
+ /* ADC, DAC on */
+ reg = uda134x_read_reg_cache(codec, UDA134X_STATUS1);
+ uda134x_write(codec, UDA134X_STATUS1, reg | 0x03);
+ break;
+ case SND_SOC_BIAS_PREPARE:
+ /* power on */
+ if (pd->power) {
+ pd->power(1);
+ /* Sync reg_cache with the hardware */
+ for (i = 0; i < ARRAY_SIZE(uda134x_reg); i++)
+ codec->write(codec, i, *cache++);
+ }
+ break;
+ case SND_SOC_BIAS_STANDBY:
+ /* ADC, DAC power off */
+ reg = uda134x_read_reg_cache(codec, UDA134X_STATUS1);
+ uda134x_write(codec, UDA134X_STATUS1, reg & ~(0x03));
+ break;
+ case SND_SOC_BIAS_OFF:
+ /* power off */
+ if (pd->power)
+ pd->power(0);
+ break;
+ }
+ codec->bias_level = level;
+ return 0;
+}
+
+static const char *uda134x_dsp_setting[] = {"Flat", "Minimum1",
+ "Minimum2", "Maximum"};
+static const char *uda134x_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"};
+static const char *uda134x_mixmode[] = {"Differential", "Analog1",
+ "Analog2", "Both"};
+
+static const struct soc_enum uda134x_mixer_enum[] = {
+SOC_ENUM_SINGLE(UDA134X_DATA010, 0, 0x04, uda134x_dsp_setting),
+SOC_ENUM_SINGLE(UDA134X_DATA010, 3, 0x04, uda134x_deemph),
+SOC_ENUM_SINGLE(UDA134X_EA010, 0, 0x04, uda134x_mixmode),
+};
+
+static const struct snd_kcontrol_new uda1341_snd_controls[] = {
+SOC_SINGLE("Master Playback Volume", UDA134X_DATA000, 0, 0x3F, 1),
+SOC_SINGLE("Capture Volume", UDA134X_EA010, 2, 0x07, 0),
+SOC_SINGLE("Analog1 Volume", UDA134X_EA000, 0, 0x1F, 1),
+SOC_SINGLE("Analog2 Volume", UDA134X_EA001, 0, 0x1F, 1),
+
+SOC_SINGLE("Mic Sensitivity", UDA134X_EA010, 2, 7, 0),
+SOC_SINGLE("Mic Volume", UDA134X_EA101, 0, 0x1F, 0),
+
+SOC_SINGLE("Tone Control - Bass", UDA134X_DATA001, 2, 0xF, 0),
+SOC_SINGLE("Tone Control - Treble", UDA134X_DATA001, 0, 3, 0),
+
+SOC_ENUM("Sound Processing Filter", uda134x_mixer_enum[0]),
+SOC_ENUM("PCM Playback De-emphasis", uda134x_mixer_enum[1]),
+SOC_ENUM("Input Mux", uda134x_mixer_enum[2]),
+
+SOC_SINGLE("AGC Switch", UDA134X_EA100, 4, 1, 0),
+SOC_SINGLE("AGC Target Volume", UDA134X_EA110, 0, 0x03, 1),
+SOC_SINGLE("AGC Timing", UDA134X_EA110, 2, 0x07, 0),
+
+SOC_SINGLE("DAC +6dB Switch", UDA134X_STATUS1, 6, 1, 0),
+SOC_SINGLE("ADC +6dB Switch", UDA134X_STATUS1, 5, 1, 0),
+SOC_SINGLE("ADC Polarity Switch", UDA134X_STATUS1, 4, 1, 0),
+SOC_SINGLE("DAC Polarity Switch", UDA134X_STATUS1, 3, 1, 0),
+SOC_SINGLE("Double Speed Playback Switch", UDA134X_STATUS1, 2, 1, 0),
+SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new uda1340_snd_controls[] = {
+SOC_SINGLE("Master Playback Volume", UDA134X_DATA000, 0, 0x3F, 1),
+
+SOC_SINGLE("Tone Control - Bass", UDA134X_DATA001, 2, 0xF, 0),
+SOC_SINGLE("Tone Control - Treble", UDA134X_DATA001, 0, 3, 0),
+
+SOC_ENUM("Sound Processing Filter", uda134x_mixer_enum[0]),
+SOC_ENUM("PCM Playback De-emphasis", uda134x_mixer_enum[1]),
+
+SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0),
+};
+
+static int uda134x_add_controls(struct snd_soc_codec *codec)
+{
+ int err, i, n;
+ const struct snd_kcontrol_new *ctrls;
+ struct uda134x_platform_data *pd = codec->control_data;
+
+ switch (pd->model) {
+ case UDA134X_UDA1340:
+ case UDA134X_UDA1344:
+ n = ARRAY_SIZE(uda1340_snd_controls);
+ ctrls = uda1340_snd_controls;
+ break;
+ case UDA134X_UDA1341:
+ n = ARRAY_SIZE(uda1341_snd_controls);
+ ctrls = uda1341_snd_controls;
+ break;
+ default:
+ printk(KERN_ERR "%s unkown codec type: %d",
+ __func__, pd->model);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < n; i++) {
+ err = snd_ctl_add(codec->card,
+ snd_soc_cnew(&ctrls[i],
+ codec, NULL));
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
+struct snd_soc_dai uda134x_dai = {
+ .name = "UDA134X",
+ /* playback capabilities */
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = UDA134X_RATES,
+ .formats = UDA134X_FORMATS,
+ },
+ /* capture capabilities */
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = UDA134X_RATES,
+ .formats = UDA134X_FORMATS,
+ },
+ /* pcm operations */
+ .ops = {
+ .startup = uda134x_startup,
+ .shutdown = uda134x_shutdown,
+ .hw_params = uda134x_hw_params,
+ .digital_mute = uda134x_mute,
+ .set_sysclk = uda134x_set_dai_sysclk,
+ .set_fmt = uda134x_set_dai_fmt,
+ }
+};
+EXPORT_SYMBOL(uda134x_dai);
+
+
+static int uda134x_soc_probe(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec;
+ struct uda134x_priv *uda134x;
+ void *codec_setup_data = socdev->codec_data;
+ int ret = -ENOMEM;
+ struct uda134x_platform_data *pd;
+
+ printk(KERN_INFO "UDA134X SoC Audio Codec\n");
+
+ if (!codec_setup_data) {
+ printk(KERN_ERR "UDA134X SoC codec: "
+ "missing L3 bitbang function\n");
+ return -ENODEV;
+ }
+
+ pd = codec_setup_data;
+ switch (pd->model) {
+ case UDA134X_UDA1340:
+ case UDA134X_UDA1341:
+ case UDA134X_UDA1344:
+ break;
+ default:
+ printk(KERN_ERR "UDA134X SoC codec: "
+ "unsupported model %d\n",
+ pd->model);
+ return -EINVAL;
+ }
+
+ socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
+ if (socdev->codec == NULL)
+ return ret;
+
+ codec = socdev->codec;
+
+ uda134x = kzalloc(sizeof(struct uda134x_priv), GFP_KERNEL);
+ if (uda134x == NULL)
+ goto priv_err;
+ codec->private_data = uda134x;
+
+ codec->reg_cache = kmemdup(uda134x_reg, sizeof(uda134x_reg),
+ GFP_KERNEL);
+ if (codec->reg_cache == NULL)
+ goto reg_err;
+
+ mutex_init(&codec->mutex);
+
+ codec->reg_cache_size = sizeof(uda134x_reg);
+ codec->reg_cache_step = 1;
+
+ codec->name = "UDA134X";
+ codec->owner = THIS_MODULE;
+ codec->dai = &uda134x_dai;
+ codec->num_dai = 1;
+ codec->read = uda134x_read_reg_cache;
+ codec->write = uda134x_write;
+#ifdef POWER_OFF_ON_STANDBY
+ codec->set_bias_level = uda134x_set_bias_level;
+#endif
+ INIT_LIST_HEAD(&codec->dapm_widgets);
+ INIT_LIST_HEAD(&codec->dapm_paths);
+
+ codec->control_data = codec_setup_data;
+
+ if (pd->power)
+ pd->power(1);
+
+ uda134x_reset(codec);
+
+ /* register pcms */
+ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+ if (ret < 0) {
+ printk(KERN_ERR "UDA134X: failed to register pcms\n");
+ goto pcm_err;
+ }
+
+ ret = uda134x_add_controls(codec);
+ if (ret < 0) {
+ printk(KERN_ERR "UDA134X: failed to register controls\n");
+ goto pcm_err;
+ }
+
+ ret = snd_soc_init_card(socdev);
+ if (ret < 0) {
+ printk(KERN_ERR "UDA134X: failed to register card\n");
+ goto card_err;
+ }
+
+ return 0;
+
+card_err:
+ snd_soc_free_pcms(socdev);
+ snd_soc_dapm_free(socdev);
+pcm_err:
+ kfree(codec->reg_cache);
+reg_err:
+ kfree(codec->private_data);
+priv_err:
+ kfree(codec);
+ return ret;
+}
+
+/* power down chip */
+static int uda134x_soc_remove(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec = socdev->codec;
+
+ uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+ uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+ snd_soc_free_pcms(socdev);
+ snd_soc_dapm_free(socdev);
+
+ kfree(codec->private_data);
+ kfree(codec->reg_cache);
+ kfree(codec);
+
+ return 0;
+}
+
+#if defined(CONFIG_PM)
+static int uda134x_soc_suspend(struct platform_device *pdev,
+ pm_message_t state)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec = socdev->codec;
+
+ uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+ uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ return 0;
+}
+
+static int uda134x_soc_resume(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec = socdev->codec;
+
+ uda134x_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
+ uda134x_set_bias_level(codec, SND_SOC_BIAS_ON);
+ return 0;
+}
+#else
+#define uda134x_soc_suspend NULL
+#define uda134x_soc_resume NULL
+#endif /* CONFIG_PM */
+
+struct snd_soc_codec_device soc_codec_dev_uda134x = {
+ .probe = uda134x_soc_probe,
+ .remove = uda134x_soc_remove,
+ .suspend = uda134x_soc_suspend,
+ .resume = uda134x_soc_resume,
+};
+EXPORT_SYMBOL_GPL(soc_codec_dev_uda134x);
+
+static int __init uda134x_init(void)
+{
+ return snd_soc_register_dai(&uda134x_dai);
+}
+module_init(uda134x_init);
+
+static void __exit uda134x_exit(void)
+{
+ snd_soc_unregister_dai(&uda134x_dai);
+}
+module_exit(uda134x_exit);
+
+MODULE_DESCRIPTION("UDA134X ALSA soc codec driver");
+MODULE_AUTHOR("Zoltan Devai, Christian Pellegrin <chripell@evolware.org>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/uda134x.h b/sound/soc/codecs/uda134x.h
new file mode 100644
index 00000000000..94f440490b3
--- /dev/null
+++ b/sound/soc/codecs/uda134x.h
@@ -0,0 +1,36 @@
+#ifndef _UDA134X_CODEC_H
+#define _UDA134X_CODEC_H
+
+#define UDA134X_L3ADDR 5
+#define UDA134X_DATA0_ADDR ((UDA134X_L3ADDR << 2) | 0)
+#define UDA134X_DATA1_ADDR ((UDA134X_L3ADDR << 2) | 1)
+#define UDA134X_STATUS_ADDR ((UDA134X_L3ADDR << 2) | 2)
+
+#define UDA134X_EXTADDR_PREFIX 0xC0
+#define UDA134X_EXTDATA_PREFIX 0xE0
+
+/* UDA134X registers */
+#define UDA134X_EA000 0
+#define UDA134X_EA001 1
+#define UDA134X_EA010 2
+#define UDA134X_EA011 3
+#define UDA134X_EA100 4
+#define UDA134X_EA101 5
+#define UDA134X_EA110 6
+#define UDA134X_EA111 7
+#define UDA134X_STATUS0 8
+#define UDA134X_STATUS1 9
+#define UDA134X_DATA000 10
+#define UDA134X_DATA001 11
+#define UDA134X_DATA010 12
+#define UDA134X_DATA1 13
+
+#define UDA134X_REGS_NUM 14
+
+#define STATUS0_DAIFMT_MASK (~(7<<1))
+#define STATUS0_SYSCLK_MASK (~(3<<4))
+
+extern struct snd_soc_dai uda134x_dai;
+extern struct snd_soc_codec_device soc_codec_dev_uda134x;
+
+#endif
diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c
index a69ee72a7af..e6bf0844fbf 100644
--- a/sound/soc/codecs/uda1380.c
+++ b/sound/soc/codecs/uda1380.c
@@ -407,7 +407,8 @@ static int uda1380_set_dai_fmt(struct snd_soc_dai *codec_dai,
* when the DAI is being clocked by the CPU DAI. It's up to the
* machine and cpu DAI driver to do this before we are called.
*/
-static int uda1380_pcm_prepare(struct snd_pcm_substream *substream)
+static int uda1380_pcm_prepare(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
@@ -439,7 +440,8 @@ static int uda1380_pcm_prepare(struct snd_pcm_substream *substream)
}
static int uda1380_pcm_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
@@ -477,7 +479,8 @@ static int uda1380_pcm_hw_params(struct snd_pcm_substream *substream,
return 0;
}
-static void uda1380_pcm_shutdown(struct snd_pcm_substream *substream)
+static void uda1380_pcm_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
@@ -560,8 +563,6 @@ struct snd_soc_dai uda1380_dai[] = {
.hw_params = uda1380_pcm_hw_params,
.shutdown = uda1380_pcm_shutdown,
.prepare = uda1380_pcm_prepare,
- },
- .dai_ops = {
.digital_mute = uda1380_mute,
.set_fmt = uda1380_set_dai_fmt,
},
@@ -579,8 +580,6 @@ struct snd_soc_dai uda1380_dai[] = {
.hw_params = uda1380_pcm_hw_params,
.shutdown = uda1380_pcm_shutdown,
.prepare = uda1380_pcm_prepare,
- },
- .dai_ops = {
.digital_mute = uda1380_mute,
.set_fmt = uda1380_set_dai_fmt,
},
@@ -598,8 +597,6 @@ struct snd_soc_dai uda1380_dai[] = {
.hw_params = uda1380_pcm_hw_params,
.shutdown = uda1380_pcm_shutdown,
.prepare = uda1380_pcm_prepare,
- },
- .dai_ops = {
.set_fmt = uda1380_set_dai_fmt,
},
},
@@ -680,7 +677,7 @@ static int uda1380_init(struct snd_soc_device *socdev, int dac_clk)
/* uda1380 init */
uda1380_add_controls(codec);
uda1380_add_widgets(codec);
- ret = snd_soc_register_card(socdev);
+ ret = snd_soc_init_card(socdev);
if (ret < 0) {
pr_err("uda1380: failed to register card\n");
goto card_err;
@@ -844,6 +841,18 @@ struct snd_soc_codec_device soc_codec_dev_uda1380 = {
};
EXPORT_SYMBOL_GPL(soc_codec_dev_uda1380);
+static int __init uda1380_modinit(void)
+{
+ return snd_soc_register_dais(uda1380_dai, ARRAY_SIZE(uda1380_dai));
+}
+module_init(uda1380_modinit);
+
+static void __exit uda1380_exit(void)
+{
+ snd_soc_unregister_dais(uda1380_dai, ARRAY_SIZE(uda1380_dai));
+}
+module_exit(uda1380_exit);
+
MODULE_AUTHOR("Giorgio Padrin");
MODULE_DESCRIPTION("Audio support for codec Philips UDA1380");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c
new file mode 100644
index 00000000000..e3989d406f5
--- /dev/null
+++ b/sound/soc/codecs/wm8350.c
@@ -0,0 +1,1583 @@
+/*
+ * wm8350.c -- WM8350 ALSA SoC audio driver
+ *
+ * Copyright (C) 2007, 2008 Wolfson Microelectronics PLC.
+ *
+ * Author: Liam Girdwood <lg@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/wm8350/audio.h>
+#include <linux/mfd/wm8350/core.h>
+#include <linux/regulator/consumer.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include "wm8350.h"
+
+#define WM8350_OUTn_0dB 0x39
+
+#define WM8350_RAMP_NONE 0
+#define WM8350_RAMP_UP 1
+#define WM8350_RAMP_DOWN 2
+
+/* We only include the analogue supplies here; the digital supplies
+ * need to be available well before this driver can be probed.
+ */
+static const char *supply_names[] = {
+ "AVDD",
+ "HPVDD",
+};
+
+struct wm8350_output {
+ u16 active;
+ u16 left_vol;
+ u16 right_vol;
+ u16 ramp;
+ u16 mute;
+};
+
+struct wm8350_data {
+ struct snd_soc_codec codec;
+ struct wm8350_output out1;
+ struct wm8350_output out2;
+ struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)];
+};
+
+static unsigned int wm8350_codec_cache_read(struct snd_soc_codec *codec,
+ unsigned int reg)
+{
+ struct wm8350 *wm8350 = codec->control_data;
+ return wm8350->reg_cache[reg];
+}
+
+static unsigned int wm8350_codec_read(struct snd_soc_codec *codec,
+ unsigned int reg)
+{
+ struct wm8350 *wm8350 = codec->control_data;
+ return wm8350_reg_read(wm8350, reg);
+}
+
+static int wm8350_codec_write(struct snd_soc_codec *codec, unsigned int reg,
+ unsigned int value)
+{
+ struct wm8350 *wm8350 = codec->control_data;
+ return wm8350_reg_write(wm8350, reg, value);
+}
+
+/*
+ * Ramp OUT1 PGA volume to minimise pops at stream startup and shutdown.
+ */
+static inline int wm8350_out1_ramp_step(struct snd_soc_codec *codec)
+{
+ struct wm8350_data *wm8350_data = codec->private_data;
+ struct wm8350_output *out1 = &wm8350_data->out1;
+ struct wm8350 *wm8350 = codec->control_data;
+ int left_complete = 0, right_complete = 0;
+ u16 reg, val;
+
+ /* left channel */
+ reg = wm8350_reg_read(wm8350, WM8350_LOUT1_VOLUME);
+ val = (reg & WM8350_OUT1L_VOL_MASK) >> WM8350_OUT1L_VOL_SHIFT;
+
+ if (out1->ramp == WM8350_RAMP_UP) {
+ /* ramp step up */
+ if (val < out1->left_vol) {
+ val++;
+ reg &= ~WM8350_OUT1L_VOL_MASK;
+ wm8350_reg_write(wm8350, WM8350_LOUT1_VOLUME,
+ reg | (val << WM8350_OUT1L_VOL_SHIFT));
+ } else
+ left_complete = 1;
+ } else if (out1->ramp == WM8350_RAMP_DOWN) {
+ /* ramp step down */
+ if (val > 0) {
+ val--;
+ reg &= ~WM8350_OUT1L_VOL_MASK;
+ wm8350_reg_write(wm8350, WM8350_LOUT1_VOLUME,
+ reg | (val << WM8350_OUT1L_VOL_SHIFT));
+ } else
+ left_complete = 1;
+ } else
+ return 1;
+
+ /* right channel */
+ reg = wm8350_reg_read(wm8350, WM8350_ROUT1_VOLUME);
+ val = (reg & WM8350_OUT1R_VOL_MASK) >> WM8350_OUT1R_VOL_SHIFT;
+ if (out1->ramp == WM8350_RAMP_UP) {
+ /* ramp step up */
+ if (val < out1->right_vol) {
+ val++;
+ reg &= ~WM8350_OUT1R_VOL_MASK;
+ wm8350_reg_write(wm8350, WM8350_ROUT1_VOLUME,
+ reg | (val << WM8350_OUT1R_VOL_SHIFT));
+ } else
+ right_complete = 1;
+ } else if (out1->ramp == WM8350_RAMP_DOWN) {
+ /* ramp step down */
+ if (val > 0) {
+ val--;
+ reg &= ~WM8350_OUT1R_VOL_MASK;
+ wm8350_reg_write(wm8350, WM8350_ROUT1_VOLUME,
+ reg | (val << WM8350_OUT1R_VOL_SHIFT));
+ } else
+ right_complete = 1;
+ }
+
+ /* only hit the update bit if either volume has changed this step */
+ if (!left_complete || !right_complete)
+ wm8350_set_bits(wm8350, WM8350_LOUT1_VOLUME, WM8350_OUT1_VU);
+
+ return left_complete & right_complete;
+}
+
+/*
+ * Ramp OUT2 PGA volume to minimise pops at stream startup and shutdown.
+ */
+static inline int wm8350_out2_ramp_step(struct snd_soc_codec *codec)
+{
+ struct wm8350_data *wm8350_data = codec->private_data;
+ struct wm8350_output *out2 = &wm8350_data->out2;
+ struct wm8350 *wm8350 = codec->control_data;
+ int left_complete = 0, right_complete = 0;
+ u16 reg, val;
+
+ /* left channel */
+ reg = wm8350_reg_read(wm8350, WM8350_LOUT2_VOLUME);
+ val = (reg & WM8350_OUT2L_VOL_MASK) >> WM8350_OUT1L_VOL_SHIFT;
+ if (out2->ramp == WM8350_RAMP_UP) {
+ /* ramp step up */
+ if (val < out2->left_vol) {
+ val++;
+ reg &= ~WM8350_OUT2L_VOL_MASK;
+ wm8350_reg_write(wm8350, WM8350_LOUT2_VOLUME,
+ reg | (val << WM8350_OUT1L_VOL_SHIFT));
+ } else
+ left_complete = 1;
+ } else if (out2->ramp == WM8350_RAMP_DOWN) {
+ /* ramp step down */
+ if (val > 0) {
+ val--;
+ reg &= ~WM8350_OUT2L_VOL_MASK;
+ wm8350_reg_write(wm8350, WM8350_LOUT2_VOLUME,
+ reg | (val << WM8350_OUT1L_VOL_SHIFT));
+ } else
+ left_complete = 1;
+ } else
+ return 1;
+
+ /* right channel */
+ reg = wm8350_reg_read(wm8350, WM8350_ROUT2_VOLUME);
+ val = (reg & WM8350_OUT2R_VOL_MASK) >> WM8350_OUT1R_VOL_SHIFT;
+ if (out2->ramp == WM8350_RAMP_UP) {
+ /* ramp step up */
+ if (val < out2->right_vol) {
+ val++;
+ reg &= ~WM8350_OUT2R_VOL_MASK;
+ wm8350_reg_write(wm8350, WM8350_ROUT2_VOLUME,
+ reg | (val << WM8350_OUT1R_VOL_SHIFT));
+ } else
+ right_complete = 1;
+ } else if (out2->ramp == WM8350_RAMP_DOWN) {
+ /* ramp step down */
+ if (val > 0) {
+ val--;
+ reg &= ~WM8350_OUT2R_VOL_MASK;
+ wm8350_reg_write(wm8350, WM8350_ROUT2_VOLUME,
+ reg | (val << WM8350_OUT1R_VOL_SHIFT));
+ } else
+ right_complete = 1;
+ }
+
+ /* only hit the update bit if either volume has changed this step */
+ if (!left_complete || !right_complete)
+ wm8350_set_bits(wm8350, WM8350_LOUT2_VOLUME, WM8350_OUT2_VU);
+
+ return left_complete & right_complete;
+}
+
+/*
+ * This work ramps both output PGAs at stream start/stop time to
+ * minimise pop associated with DAPM power switching.
+ * It's best to enable Zero Cross when ramping occurs to minimise any
+ * zipper noises.
+ */
+static void wm8350_pga_work(struct work_struct *work)
+{
+ struct snd_soc_codec *codec =
+ container_of(work, struct snd_soc_codec, delayed_work.work);
+ struct wm8350_data *wm8350_data = codec->private_data;
+ struct wm8350_output *out1 = &wm8350_data->out1,
+ *out2 = &wm8350_data->out2;
+ int i, out1_complete, out2_complete;
+
+ /* do we need to ramp at all ? */
+ if (out1->ramp == WM8350_RAMP_NONE && out2->ramp == WM8350_RAMP_NONE)
+ return;
+
+ /* PGA volumes have 6 bits of resolution to ramp */
+ for (i = 0; i <= 63; i++) {
+ out1_complete = 1, out2_complete = 1;
+ if (out1->ramp != WM8350_RAMP_NONE)
+ out1_complete = wm8350_out1_ramp_step(codec);
+ if (out2->ramp != WM8350_RAMP_NONE)
+ out2_complete = wm8350_out2_ramp_step(codec);
+
+ /* ramp finished ? */
+ if (out1_complete && out2_complete)
+ break;
+
+ /* we need to delay longer on the up ramp */
+ if (out1->ramp == WM8350_RAMP_UP ||
+ out2->ramp == WM8350_RAMP_UP) {
+ /* delay is longer over 0dB as increases are larger */
+ if (i >= WM8350_OUTn_0dB)
+ schedule_timeout_interruptible(msecs_to_jiffies
+ (2));
+ else
+ schedule_timeout_interruptible(msecs_to_jiffies
+ (1));
+ } else
+ udelay(50); /* doesn't matter if we delay longer */
+ }
+
+ out1->ramp = WM8350_RAMP_NONE;
+ out2->ramp = WM8350_RAMP_NONE;
+}
+
+/*
+ * WM8350 Controls
+ */
+
+static int pga_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct wm8350_data *wm8350_data = codec->private_data;
+ struct wm8350_output *out;
+
+ switch (w->shift) {
+ case 0:
+ case 1:
+ out = &wm8350_data->out1;
+ break;
+ case 2:
+ case 3:
+ out = &wm8350_data->out2;
+ break;
+
+ default:
+ BUG();
+ return -1;
+ }
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ out->ramp = WM8350_RAMP_UP;
+ out->active = 1;
+
+ if (!delayed_work_pending(&codec->delayed_work))
+ schedule_delayed_work(&codec->delayed_work,
+ msecs_to_jiffies(1));
+ break;
+
+ case SND_SOC_DAPM_PRE_PMD:
+ out->ramp = WM8350_RAMP_DOWN;
+ out->active = 0;
+
+ if (!delayed_work_pending(&codec->delayed_work))
+ schedule_delayed_work(&codec->delayed_work,
+ msecs_to_jiffies(1));
+ break;
+ }
+
+ return 0;
+}
+
+static int wm8350_put_volsw_2r_vu(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct wm8350_data *wm8350_priv = codec->private_data;
+ struct wm8350_output *out = NULL;
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ int ret;
+ unsigned int reg = mc->reg;
+ u16 val;
+
+ /* For OUT1 and OUT2 we shadow the values and only actually write
+ * them out when active in order to ensure the amplifier comes on
+ * as quietly as possible. */
+ switch (reg) {
+ case WM8350_LOUT1_VOLUME:
+ out = &wm8350_priv->out1;
+ break;
+ case WM8350_LOUT2_VOLUME:
+ out = &wm8350_priv->out2;
+ break;
+ default:
+ break;
+ }
+
+ if (out) {
+ out->left_vol = ucontrol->value.integer.value[0];
+ out->right_vol = ucontrol->value.integer.value[1];
+ if (!out->active)
+ return 1;
+ }
+
+ ret = snd_soc_put_volsw_2r(kcontrol, ucontrol);
+ if (ret < 0)
+ return ret;
+
+ /* now hit the volume update bits (always bit 8) */
+ val = wm8350_codec_read(codec, reg);
+ wm8350_codec_write(codec, reg, val | WM8350_OUT1_VU);
+ return 1;
+}
+
+static int wm8350_get_volsw_2r(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct wm8350_data *wm8350_priv = codec->private_data;
+ struct wm8350_output *out1 = &wm8350_priv->out1;
+ struct wm8350_output *out2 = &wm8350_priv->out2;
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ unsigned int reg = mc->reg;
+
+ /* If these are cached registers use the cache */
+ switch (reg) {
+ case WM8350_LOUT1_VOLUME:
+ ucontrol->value.integer.value[0] = out1->left_vol;
+ ucontrol->value.integer.value[1] = out1->right_vol;
+ return 0;
+
+ case WM8350_LOUT2_VOLUME:
+ ucontrol->value.integer.value[0] = out2->left_vol;
+ ucontrol->value.integer.value[1] = out2->right_vol;
+ return 0;
+
+ default:
+ break;
+ }
+
+ return snd_soc_get_volsw_2r(kcontrol, ucontrol);
+}
+
+/* double control with volume update */
+#define SOC_WM8350_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, \
+ xinvert, tlv_array) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
+ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
+ SNDRV_CTL_ELEM_ACCESS_READWRITE | \
+ SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
+ .tlv.p = (tlv_array), \
+ .info = snd_soc_info_volsw_2r, \
+ .get = wm8350_get_volsw_2r, .put = wm8350_put_volsw_2r_vu, \
+ .private_value = (unsigned long)&(struct soc_mixer_control) \
+ {.reg = reg_left, .rreg = reg_right, .shift = xshift, \
+ .rshift = xshift, .max = xmax, .invert = xinvert}, }
+
+static const char *wm8350_deemp[] = { "None", "32kHz", "44.1kHz", "48kHz" };
+static const char *wm8350_pol[] = { "Normal", "Inv R", "Inv L", "Inv L & R" };
+static const char *wm8350_dacmutem[] = { "Normal", "Soft" };
+static const char *wm8350_dacmutes[] = { "Fast", "Slow" };
+static const char *wm8350_dacfilter[] = { "Normal", "Sloping" };
+static const char *wm8350_adcfilter[] = { "None", "High Pass" };
+static const char *wm8350_adchp[] = { "44.1kHz", "8kHz", "16kHz", "32kHz" };
+static const char *wm8350_lr[] = { "Left", "Right" };
+
+static const struct soc_enum wm8350_enum[] = {
+ SOC_ENUM_SINGLE(WM8350_DAC_CONTROL, 4, 4, wm8350_deemp),
+ SOC_ENUM_SINGLE(WM8350_DAC_CONTROL, 0, 4, wm8350_pol),
+ SOC_ENUM_SINGLE(WM8350_DAC_MUTE_VOLUME, 14, 2, wm8350_dacmutem),
+ SOC_ENUM_SINGLE(WM8350_DAC_MUTE_VOLUME, 13, 2, wm8350_dacmutes),
+ SOC_ENUM_SINGLE(WM8350_DAC_MUTE_VOLUME, 12, 2, wm8350_dacfilter),
+ SOC_ENUM_SINGLE(WM8350_ADC_CONTROL, 15, 2, wm8350_adcfilter),
+ SOC_ENUM_SINGLE(WM8350_ADC_CONTROL, 8, 4, wm8350_adchp),
+ SOC_ENUM_SINGLE(WM8350_ADC_CONTROL, 0, 4, wm8350_pol),
+ SOC_ENUM_SINGLE(WM8350_INPUT_MIXER_VOLUME, 15, 2, wm8350_lr),
+};
+
+static DECLARE_TLV_DB_LINEAR(pre_amp_tlv, -1200, 3525);
+static DECLARE_TLV_DB_LINEAR(out_pga_tlv, -5700, 600);
+static DECLARE_TLV_DB_SCALE(dac_pcm_tlv, -7163, 36, 1);
+static DECLARE_TLV_DB_SCALE(adc_pcm_tlv, -12700, 50, 1);
+static DECLARE_TLV_DB_SCALE(out_mix_tlv, -1500, 300, 1);
+
+static const unsigned int capture_sd_tlv[] = {
+ TLV_DB_RANGE_HEAD(2),
+ 0, 12, TLV_DB_SCALE_ITEM(-3600, 300, 1),
+ 13, 15, TLV_DB_SCALE_ITEM(0, 0, 0),
+};
+
+static const struct snd_kcontrol_new wm8350_snd_controls[] = {
+ SOC_ENUM("Playback Deemphasis", wm8350_enum[0]),
+ SOC_ENUM("Playback DAC Inversion", wm8350_enum[1]),
+ SOC_WM8350_DOUBLE_R_TLV("Playback PCM Volume",
+ WM8350_DAC_DIGITAL_VOLUME_L,
+ WM8350_DAC_DIGITAL_VOLUME_R,
+ 0, 255, 0, dac_pcm_tlv),
+ SOC_ENUM("Playback PCM Mute Function", wm8350_enum[2]),
+ SOC_ENUM("Playback PCM Mute Speed", wm8350_enum[3]),
+ SOC_ENUM("Playback PCM Filter", wm8350_enum[4]),
+ SOC_ENUM("Capture PCM Filter", wm8350_enum[5]),
+ SOC_ENUM("Capture PCM HP Filter", wm8350_enum[6]),
+ SOC_ENUM("Capture ADC Inversion", wm8350_enum[7]),
+ SOC_WM8350_DOUBLE_R_TLV("Capture PCM Volume",
+ WM8350_ADC_DIGITAL_VOLUME_L,
+ WM8350_ADC_DIGITAL_VOLUME_R,
+ 0, 255, 0, adc_pcm_tlv),
+ SOC_DOUBLE_TLV("Capture Sidetone Volume",
+ WM8350_ADC_DIVIDER,
+ 8, 4, 15, 1, capture_sd_tlv),
+ SOC_WM8350_DOUBLE_R_TLV("Capture Volume",
+ WM8350_LEFT_INPUT_VOLUME,
+ WM8350_RIGHT_INPUT_VOLUME,
+ 2, 63, 0, pre_amp_tlv),
+ SOC_DOUBLE_R("Capture ZC Switch",
+ WM8350_LEFT_INPUT_VOLUME,
+ WM8350_RIGHT_INPUT_VOLUME, 13, 1, 0),
+ SOC_SINGLE_TLV("Left Input Left Sidetone Volume",
+ WM8350_OUTPUT_LEFT_MIXER_VOLUME, 1, 7, 0, out_mix_tlv),
+ SOC_SINGLE_TLV("Left Input Right Sidetone Volume",
+ WM8350_OUTPUT_LEFT_MIXER_VOLUME,
+ 5, 7, 0, out_mix_tlv),
+ SOC_SINGLE_TLV("Left Input Bypass Volume",
+ WM8350_OUTPUT_LEFT_MIXER_VOLUME,
+ 9, 7, 0, out_mix_tlv),
+ SOC_SINGLE_TLV("Right Input Left Sidetone Volume",
+ WM8350_OUTPUT_RIGHT_MIXER_VOLUME,
+ 1, 7, 0, out_mix_tlv),
+ SOC_SINGLE_TLV("Right Input Right Sidetone Volume",
+ WM8350_OUTPUT_RIGHT_MIXER_VOLUME,
+ 5, 7, 0, out_mix_tlv),
+ SOC_SINGLE_TLV("Right Input Bypass Volume",
+ WM8350_OUTPUT_RIGHT_MIXER_VOLUME,
+ 13, 7, 0, out_mix_tlv),
+ SOC_SINGLE("Left Input Mixer +20dB Switch",
+ WM8350_INPUT_MIXER_VOLUME_L, 0, 1, 0),
+ SOC_SINGLE("Right Input Mixer +20dB Switch",
+ WM8350_INPUT_MIXER_VOLUME_R, 0, 1, 0),
+ SOC_SINGLE_TLV("Out4 Capture Volume",
+ WM8350_INPUT_MIXER_VOLUME,
+ 1, 7, 0, out_mix_tlv),
+ SOC_WM8350_DOUBLE_R_TLV("Out1 Playback Volume",
+ WM8350_LOUT1_VOLUME,
+ WM8350_ROUT1_VOLUME,
+ 2, 63, 0, out_pga_tlv),
+ SOC_DOUBLE_R("Out1 Playback ZC Switch",
+ WM8350_LOUT1_VOLUME,
+ WM8350_ROUT1_VOLUME, 13, 1, 0),
+ SOC_WM8350_DOUBLE_R_TLV("Out2 Playback Volume",
+ WM8350_LOUT2_VOLUME,
+ WM8350_ROUT2_VOLUME,
+ 2, 63, 0, out_pga_tlv),
+ SOC_DOUBLE_R("Out2 Playback ZC Switch", WM8350_LOUT2_VOLUME,
+ WM8350_ROUT2_VOLUME, 13, 1, 0),
+ SOC_SINGLE("Out2 Right Invert Switch", WM8350_ROUT2_VOLUME, 10, 1, 0),
+ SOC_SINGLE_TLV("Out2 Beep Volume", WM8350_BEEP_VOLUME,
+ 5, 7, 0, out_mix_tlv),
+
+ SOC_DOUBLE_R("Out1 Playback Switch",
+ WM8350_LOUT1_VOLUME,
+ WM8350_ROUT1_VOLUME,
+ 14, 1, 1),
+ SOC_DOUBLE_R("Out2 Playback Switch",
+ WM8350_LOUT2_VOLUME,
+ WM8350_ROUT2_VOLUME,
+ 14, 1, 1),
+};
+
+/*
+ * DAPM Controls
+ */
+
+/* Left Playback Mixer */
+static const struct snd_kcontrol_new wm8350_left_play_mixer_controls[] = {
+ SOC_DAPM_SINGLE("Playback Switch",
+ WM8350_LEFT_MIXER_CONTROL, 11, 1, 0),
+ SOC_DAPM_SINGLE("Left Bypass Switch",
+ WM8350_LEFT_MIXER_CONTROL, 2, 1, 0),
+ SOC_DAPM_SINGLE("Right Playback Switch",
+ WM8350_LEFT_MIXER_CONTROL, 12, 1, 0),
+ SOC_DAPM_SINGLE("Left Sidetone Switch",
+ WM8350_LEFT_MIXER_CONTROL, 0, 1, 0),
+ SOC_DAPM_SINGLE("Right Sidetone Switch",
+ WM8350_LEFT_MIXER_CONTROL, 1, 1, 0),
+};
+
+/* Right Playback Mixer */
+static const struct snd_kcontrol_new wm8350_right_play_mixer_controls[] = {
+ SOC_DAPM_SINGLE("Playback Switch",
+ WM8350_RIGHT_MIXER_CONTROL, 12, 1, 0),
+ SOC_DAPM_SINGLE("Right Bypass Switch",
+ WM8350_RIGHT_MIXER_CONTROL, 3, 1, 0),
+ SOC_DAPM_SINGLE("Left Playback Switch",
+ WM8350_RIGHT_MIXER_CONTROL, 11, 1, 0),
+ SOC_DAPM_SINGLE("Left Sidetone Switch",
+ WM8350_RIGHT_MIXER_CONTROL, 0, 1, 0),
+ SOC_DAPM_SINGLE("Right Sidetone Switch",
+ WM8350_RIGHT_MIXER_CONTROL, 1, 1, 0),
+};
+
+/* Out4 Mixer */
+static const struct snd_kcontrol_new wm8350_out4_mixer_controls[] = {
+ SOC_DAPM_SINGLE("Right Playback Switch",
+ WM8350_OUT4_MIXER_CONTROL, 12, 1, 0),
+ SOC_DAPM_SINGLE("Left Playback Switch",
+ WM8350_OUT4_MIXER_CONTROL, 11, 1, 0),
+ SOC_DAPM_SINGLE("Right Capture Switch",
+ WM8350_OUT4_MIXER_CONTROL, 9, 1, 0),
+ SOC_DAPM_SINGLE("Out3 Playback Switch",
+ WM8350_OUT4_MIXER_CONTROL, 2, 1, 0),
+ SOC_DAPM_SINGLE("Right Mixer Switch",
+ WM8350_OUT4_MIXER_CONTROL, 1, 1, 0),
+ SOC_DAPM_SINGLE("Left Mixer Switch",
+ WM8350_OUT4_MIXER_CONTROL, 0, 1, 0),
+};
+
+/* Out3 Mixer */
+static const struct snd_kcontrol_new wm8350_out3_mixer_controls[] = {
+ SOC_DAPM_SINGLE("Left Playback Switch",
+ WM8350_OUT3_MIXER_CONTROL, 11, 1, 0),
+ SOC_DAPM_SINGLE("Left Capture Switch",
+ WM8350_OUT3_MIXER_CONTROL, 8, 1, 0),
+ SOC_DAPM_SINGLE("Out4 Playback Switch",
+ WM8350_OUT3_MIXER_CONTROL, 3, 1, 0),
+ SOC_DAPM_SINGLE("Left Mixer Switch",
+ WM8350_OUT3_MIXER_CONTROL, 0, 1, 0),
+};
+
+/* Left Input Mixer */
+static const struct snd_kcontrol_new wm8350_left_capt_mixer_controls[] = {
+ SOC_DAPM_SINGLE_TLV("L2 Capture Volume",
+ WM8350_INPUT_MIXER_VOLUME_L, 1, 7, 0, out_mix_tlv),
+ SOC_DAPM_SINGLE_TLV("L3 Capture Volume",
+ WM8350_INPUT_MIXER_VOLUME_L, 9, 7, 0, out_mix_tlv),
+ SOC_DAPM_SINGLE("PGA Capture Switch",
+ WM8350_LEFT_INPUT_VOLUME, 14, 1, 0),
+};
+
+/* Right Input Mixer */
+static const struct snd_kcontrol_new wm8350_right_capt_mixer_controls[] = {
+ SOC_DAPM_SINGLE_TLV("L2 Capture Volume",
+ WM8350_INPUT_MIXER_VOLUME_R, 5, 7, 0, out_mix_tlv),
+ SOC_DAPM_SINGLE_TLV("L3 Capture Volume",
+ WM8350_INPUT_MIXER_VOLUME_R, 13, 7, 0, out_mix_tlv),
+ SOC_DAPM_SINGLE("PGA Capture Switch",
+ WM8350_RIGHT_INPUT_VOLUME, 14, 1, 0),
+};
+
+/* Left Mic Mixer */
+static const struct snd_kcontrol_new wm8350_left_mic_mixer_controls[] = {
+ SOC_DAPM_SINGLE("INN Capture Switch", WM8350_INPUT_CONTROL, 1, 1, 0),
+ SOC_DAPM_SINGLE("INP Capture Switch", WM8350_INPUT_CONTROL, 0, 1, 0),
+ SOC_DAPM_SINGLE("IN2 Capture Switch", WM8350_INPUT_CONTROL, 2, 1, 0),
+};
+
+/* Right Mic Mixer */
+static const struct snd_kcontrol_new wm8350_right_mic_mixer_controls[] = {
+ SOC_DAPM_SINGLE("INN Capture Switch", WM8350_INPUT_CONTROL, 9, 1, 0),
+ SOC_DAPM_SINGLE("INP Capture Switch", WM8350_INPUT_CONTROL, 8, 1, 0),
+ SOC_DAPM_SINGLE("IN2 Capture Switch", WM8350_INPUT_CONTROL, 10, 1, 0),
+};
+
+/* Beep Switch */
+static const struct snd_kcontrol_new wm8350_beep_switch_controls =
+SOC_DAPM_SINGLE("Switch", WM8350_BEEP_VOLUME, 15, 1, 1);
+
+/* Out4 Capture Mux */
+static const struct snd_kcontrol_new wm8350_out4_capture_controls =
+SOC_DAPM_ENUM("Route", wm8350_enum[8]);
+
+static const struct snd_soc_dapm_widget wm8350_dapm_widgets[] = {
+
+ SND_SOC_DAPM_PGA("IN3R PGA", WM8350_POWER_MGMT_2, 11, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IN3L PGA", WM8350_POWER_MGMT_2, 10, 0, NULL, 0),
+ SND_SOC_DAPM_PGA_E("Right Out2 PGA", WM8350_POWER_MGMT_3, 3, 0, NULL,
+ 0, pga_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+ SND_SOC_DAPM_PGA_E("Left Out2 PGA", WM8350_POWER_MGMT_3, 2, 0, NULL, 0,
+ pga_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+ SND_SOC_DAPM_PGA_E("Right Out1 PGA", WM8350_POWER_MGMT_3, 1, 0, NULL,
+ 0, pga_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+ SND_SOC_DAPM_PGA_E("Left Out1 PGA", WM8350_POWER_MGMT_3, 0, 0, NULL, 0,
+ pga_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+
+ SND_SOC_DAPM_MIXER("Right Capture Mixer", WM8350_POWER_MGMT_2,
+ 7, 0, &wm8350_right_capt_mixer_controls[0],
+ ARRAY_SIZE(wm8350_right_capt_mixer_controls)),
+
+ SND_SOC_DAPM_MIXER("Left Capture Mixer", WM8350_POWER_MGMT_2,
+ 6, 0, &wm8350_left_capt_mixer_controls[0],
+ ARRAY_SIZE(wm8350_left_capt_mixer_controls)),
+
+ SND_SOC_DAPM_MIXER("Out4 Mixer", WM8350_POWER_MGMT_2, 5, 0,
+ &wm8350_out4_mixer_controls[0],
+ ARRAY_SIZE(wm8350_out4_mixer_controls)),
+
+ SND_SOC_DAPM_MIXER("Out3 Mixer", WM8350_POWER_MGMT_2, 4, 0,
+ &wm8350_out3_mixer_controls[0],
+ ARRAY_SIZE(wm8350_out3_mixer_controls)),
+
+ SND_SOC_DAPM_MIXER("Right Playback Mixer", WM8350_POWER_MGMT_2, 1, 0,
+ &wm8350_right_play_mixer_controls[0],
+ ARRAY_SIZE(wm8350_right_play_mixer_controls)),
+
+ SND_SOC_DAPM_MIXER("Left Playback Mixer", WM8350_POWER_MGMT_2, 0, 0,
+ &wm8350_left_play_mixer_controls[0],
+ ARRAY_SIZE(wm8350_left_play_mixer_controls)),
+
+ SND_SOC_DAPM_MIXER("Left Mic Mixer", WM8350_POWER_MGMT_2, 8, 0,
+ &wm8350_left_mic_mixer_controls[0],
+ ARRAY_SIZE(wm8350_left_mic_mixer_controls)),
+
+ SND_SOC_DAPM_MIXER("Right Mic Mixer", WM8350_POWER_MGMT_2, 9, 0,
+ &wm8350_right_mic_mixer_controls[0],
+ ARRAY_SIZE(wm8350_right_mic_mixer_controls)),
+
+ /* virtual mixer for Beep and Out2R */
+ SND_SOC_DAPM_MIXER("Out2 Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_SWITCH("Beep", WM8350_POWER_MGMT_3, 7, 0,
+ &wm8350_beep_switch_controls),
+
+ SND_SOC_DAPM_ADC("Right ADC", "Right Capture",
+ WM8350_POWER_MGMT_4, 3, 0),
+ SND_SOC_DAPM_ADC("Left ADC", "Left Capture",
+ WM8350_POWER_MGMT_4, 2, 0),
+ SND_SOC_DAPM_DAC("Right DAC", "Right Playback",
+ WM8350_POWER_MGMT_4, 5, 0),
+ SND_SOC_DAPM_DAC("Left DAC", "Left Playback",
+ WM8350_POWER_MGMT_4, 4, 0),
+
+ SND_SOC_DAPM_MICBIAS("Mic Bias", WM8350_POWER_MGMT_1, 4, 0),
+
+ SND_SOC_DAPM_MUX("Out4 Capture Channel", SND_SOC_NOPM, 0, 0,
+ &wm8350_out4_capture_controls),
+
+ SND_SOC_DAPM_OUTPUT("OUT1R"),
+ SND_SOC_DAPM_OUTPUT("OUT1L"),
+ SND_SOC_DAPM_OUTPUT("OUT2R"),
+ SND_SOC_DAPM_OUTPUT("OUT2L"),
+ SND_SOC_DAPM_OUTPUT("OUT3"),
+ SND_SOC_DAPM_OUTPUT("OUT4"),
+
+ SND_SOC_DAPM_INPUT("IN1RN"),
+ SND_SOC_DAPM_INPUT("IN1RP"),
+ SND_SOC_DAPM_INPUT("IN2R"),
+ SND_SOC_DAPM_INPUT("IN1LP"),
+ SND_SOC_DAPM_INPUT("IN1LN"),
+ SND_SOC_DAPM_INPUT("IN2L"),
+ SND_SOC_DAPM_INPUT("IN3R"),
+ SND_SOC_DAPM_INPUT("IN3L"),
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+
+ /* left playback mixer */
+ {"Left Playback Mixer", "Playback Switch", "Left DAC"},
+ {"Left Playback Mixer", "Left Bypass Switch", "IN3L PGA"},
+ {"Left Playback Mixer", "Right Playback Switch", "Right DAC"},
+ {"Left Playback Mixer", "Left Sidetone Switch", "Left Mic Mixer"},
+ {"Left Playback Mixer", "Right Sidetone Switch", "Right Mic Mixer"},
+
+ /* right playback mixer */
+ {"Right Playback Mixer", "Playback Switch", "Right DAC"},
+ {"Right Playback Mixer", "Right Bypass Switch", "IN3R PGA"},
+ {"Right Playback Mixer", "Left Playback Switch", "Left DAC"},
+ {"Right Playback Mixer", "Left Sidetone Switch", "Left Mic Mixer"},
+ {"Right Playback Mixer", "Right Sidetone Switch", "Right Mic Mixer"},
+
+ /* out4 playback mixer */
+ {"Out4 Mixer", "Right Playback Switch", "Right DAC"},
+ {"Out4 Mixer", "Left Playback Switch", "Left DAC"},
+ {"Out4 Mixer", "Right Capture Switch", "Right Capture Mixer"},
+ {"Out4 Mixer", "Out3 Playback Switch", "Out3 Mixer"},
+ {"Out4 Mixer", "Right Mixer Switch", "Right Playback Mixer"},
+ {"Out4 Mixer", "Left Mixer Switch", "Left Playback Mixer"},
+ {"OUT4", NULL, "Out4 Mixer"},
+
+ /* out3 playback mixer */
+ {"Out3 Mixer", "Left Playback Switch", "Left DAC"},
+ {"Out3 Mixer", "Left Capture Switch", "Left Capture Mixer"},
+ {"Out3 Mixer", "Left Mixer Switch", "Left Playback Mixer"},
+ {"Out3 Mixer", "Out4 Playback Switch", "Out4 Mixer"},
+ {"OUT3", NULL, "Out3 Mixer"},
+
+ /* out2 */
+ {"Right Out2 PGA", NULL, "Right Playback Mixer"},
+ {"Left Out2 PGA", NULL, "Left Playback Mixer"},
+ {"OUT2L", NULL, "Left Out2 PGA"},
+ {"OUT2R", NULL, "Right Out2 PGA"},
+
+ /* out1 */
+ {"Right Out1 PGA", NULL, "Right Playback Mixer"},
+ {"Left Out1 PGA", NULL, "Left Playback Mixer"},
+ {"OUT1L", NULL, "Left Out1 PGA"},
+ {"OUT1R", NULL, "Right Out1 PGA"},
+
+ /* ADCs */
+ {"Left ADC", NULL, "Left Capture Mixer"},
+ {"Right ADC", NULL, "Right Capture Mixer"},
+
+ /* Left capture mixer */
+ {"Left Capture Mixer", "L2 Capture Volume", "IN2L"},
+ {"Left Capture Mixer", "L3 Capture Volume", "IN3L PGA"},
+ {"Left Capture Mixer", "PGA Capture Switch", "Left Mic Mixer"},
+ {"Left Capture Mixer", NULL, "Out4 Capture Channel"},
+
+ /* Right capture mixer */
+ {"Right Capture Mixer", "L2 Capture Volume", "IN2R"},
+ {"Right Capture Mixer", "L3 Capture Volume", "IN3R PGA"},
+ {"Right Capture Mixer", "PGA Capture Switch", "Right Mic Mixer"},
+ {"Right Capture Mixer", NULL, "Out4 Capture Channel"},
+
+ /* L3 Inputs */
+ {"IN3L PGA", NULL, "IN3L"},
+ {"IN3R PGA", NULL, "IN3R"},
+
+ /* Left Mic mixer */
+ {"Left Mic Mixer", "INN Capture Switch", "IN1LN"},
+ {"Left Mic Mixer", "INP Capture Switch", "IN1LP"},
+ {"Left Mic Mixer", "IN2 Capture Switch", "IN2L"},
+
+ /* Right Mic mixer */
+ {"Right Mic Mixer", "INN Capture Switch", "IN1RN"},
+ {"Right Mic Mixer", "INP Capture Switch", "IN1RP"},
+ {"Right Mic Mixer", "IN2 Capture Switch", "IN2R"},
+
+ /* out 4 capture */
+ {"Out4 Capture Channel", NULL, "Out4 Mixer"},
+
+ /* Beep */
+ {"Beep", NULL, "IN3R PGA"},
+};
+
+static int wm8350_add_controls(struct snd_soc_codec *codec)
+{
+ int err, i;
+
+ for (i = 0; i < ARRAY_SIZE(wm8350_snd_controls); i++) {
+ err = snd_ctl_add(codec->card,
+ snd_soc_cnew(&wm8350_snd_controls[i],
+ codec, NULL));
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
+static int wm8350_add_widgets(struct snd_soc_codec *codec)
+{
+ int ret;
+
+ ret = snd_soc_dapm_new_controls(codec,
+ wm8350_dapm_widgets,
+ ARRAY_SIZE(wm8350_dapm_widgets));
+ if (ret != 0) {
+ dev_err(codec->dev, "dapm control register failed\n");
+ return ret;
+ }
+
+ /* set up audio paths */
+ ret = snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+ if (ret != 0) {
+ dev_err(codec->dev, "DAPM route register failed\n");
+ return ret;
+ }
+
+ return snd_soc_dapm_new_widgets(codec);
+}
+
+static int wm8350_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct wm8350 *wm8350 = codec->control_data;
+ u16 fll_4;
+
+ switch (clk_id) {
+ case WM8350_MCLK_SEL_MCLK:
+ wm8350_clear_bits(wm8350, WM8350_CLOCK_CONTROL_1,
+ WM8350_MCLK_SEL);
+ break;
+ case WM8350_MCLK_SEL_PLL_MCLK:
+ case WM8350_MCLK_SEL_PLL_DAC:
+ case WM8350_MCLK_SEL_PLL_ADC:
+ case WM8350_MCLK_SEL_PLL_32K:
+ wm8350_set_bits(wm8350, WM8350_CLOCK_CONTROL_1,
+ WM8350_MCLK_SEL);
+ fll_4 = wm8350_codec_read(codec, WM8350_FLL_CONTROL_4) &
+ ~WM8350_FLL_CLK_SRC_MASK;
+ wm8350_codec_write(codec, WM8350_FLL_CONTROL_4, fll_4 | clk_id);
+ break;
+ }
+
+ /* MCLK direction */
+ if (dir == WM8350_MCLK_DIR_OUT)
+ wm8350_set_bits(wm8350, WM8350_CLOCK_CONTROL_2,
+ WM8350_MCLK_DIR);
+ else
+ wm8350_clear_bits(wm8350, WM8350_CLOCK_CONTROL_2,
+ WM8350_MCLK_DIR);
+
+ return 0;
+}
+
+static int wm8350_set_clkdiv(struct snd_soc_dai *codec_dai, int div_id, int div)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ u16 val;
+
+ switch (div_id) {
+ case WM8350_ADC_CLKDIV:
+ val = wm8350_codec_read(codec, WM8350_ADC_DIVIDER) &
+ ~WM8350_ADC_CLKDIV_MASK;
+ wm8350_codec_write(codec, WM8350_ADC_DIVIDER, val | div);
+ break;
+ case WM8350_DAC_CLKDIV:
+ val = wm8350_codec_read(codec, WM8350_DAC_CLOCK_CONTROL) &
+ ~WM8350_DAC_CLKDIV_MASK;
+ wm8350_codec_write(codec, WM8350_DAC_CLOCK_CONTROL, val | div);
+ break;
+ case WM8350_BCLK_CLKDIV:
+ val = wm8350_codec_read(codec, WM8350_CLOCK_CONTROL_1) &
+ ~WM8350_BCLK_DIV_MASK;
+ wm8350_codec_write(codec, WM8350_CLOCK_CONTROL_1, val | div);
+ break;
+ case WM8350_OPCLK_CLKDIV:
+ val = wm8350_codec_read(codec, WM8350_CLOCK_CONTROL_1) &
+ ~WM8350_OPCLK_DIV_MASK;
+ wm8350_codec_write(codec, WM8350_CLOCK_CONTROL_1, val | div);
+ break;
+ case WM8350_SYS_CLKDIV:
+ val = wm8350_codec_read(codec, WM8350_CLOCK_CONTROL_1) &
+ ~WM8350_MCLK_DIV_MASK;
+ wm8350_codec_write(codec, WM8350_CLOCK_CONTROL_1, val | div);
+ break;
+ case WM8350_DACLR_CLKDIV:
+ val = wm8350_codec_read(codec, WM8350_DAC_LR_RATE) &
+ ~WM8350_DACLRC_RATE_MASK;
+ wm8350_codec_write(codec, WM8350_DAC_LR_RATE, val | div);
+ break;
+ case WM8350_ADCLR_CLKDIV:
+ val = wm8350_codec_read(codec, WM8350_ADC_LR_RATE) &
+ ~WM8350_ADCLRC_RATE_MASK;
+ wm8350_codec_write(codec, WM8350_ADC_LR_RATE, val | div);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int wm8350_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ u16 iface = wm8350_codec_read(codec, WM8350_AI_FORMATING) &
+ ~(WM8350_AIF_BCLK_INV | WM8350_AIF_LRCLK_INV | WM8350_AIF_FMT_MASK);
+ u16 master = wm8350_codec_read(codec, WM8350_AI_DAC_CONTROL) &
+ ~WM8350_BCLK_MSTR;
+ u16 dac_lrc = wm8350_codec_read(codec, WM8350_DAC_LR_RATE) &
+ ~WM8350_DACLRC_ENA;
+ u16 adc_lrc = wm8350_codec_read(codec, WM8350_ADC_LR_RATE) &
+ ~WM8350_ADCLRC_ENA;
+
+ /* set master/slave audio interface */
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ master |= WM8350_BCLK_MSTR;
+ dac_lrc |= WM8350_DACLRC_ENA;
+ adc_lrc |= WM8350_ADCLRC_ENA;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* interface format */
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ iface |= 0x2 << 8;
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ iface |= 0x1 << 8;
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ iface |= 0x3 << 8;
+ break;
+ case SND_SOC_DAIFMT_DSP_B:
+ iface |= 0x3 << 8; /* lg not sure which mode */
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* clock inversion */
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+ case SND_SOC_DAIFMT_IB_IF:
+ iface |= WM8350_AIF_LRCLK_INV | WM8350_AIF_BCLK_INV;
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ iface |= WM8350_AIF_BCLK_INV;
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ iface |= WM8350_AIF_LRCLK_INV;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ wm8350_codec_write(codec, WM8350_AI_FORMATING, iface);
+ wm8350_codec_write(codec, WM8350_AI_DAC_CONTROL, master);
+ wm8350_codec_write(codec, WM8350_DAC_LR_RATE, dac_lrc);
+ wm8350_codec_write(codec, WM8350_ADC_LR_RATE, adc_lrc);
+ return 0;
+}
+
+static int wm8350_pcm_trigger(struct snd_pcm_substream *substream,
+ int cmd, struct snd_soc_dai *codec_dai)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ int master = wm8350_codec_cache_read(codec, WM8350_AI_DAC_CONTROL) &
+ WM8350_BCLK_MSTR;
+ int enabled = 0;
+
+ /* Check that the DACs or ADCs are enabled since they are
+ * required for LRC in master mode. The DACs or ADCs need a
+ * valid audio path i.e. pin -> ADC or DAC -> pin before
+ * the LRC will be enabled in master mode. */
+ if (!master && cmd != SNDRV_PCM_TRIGGER_START)
+ return 0;
+
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+ enabled = wm8350_codec_cache_read(codec, WM8350_POWER_MGMT_4) &
+ (WM8350_ADCR_ENA | WM8350_ADCL_ENA);
+ } else {
+ enabled = wm8350_codec_cache_read(codec, WM8350_POWER_MGMT_4) &
+ (WM8350_DACR_ENA | WM8350_DACL_ENA);
+ }
+
+ if (!enabled) {
+ dev_err(codec->dev,
+ "%s: invalid audio path - no clocks available\n",
+ __func__);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int wm8350_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *codec_dai)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ u16 iface = wm8350_codec_read(codec, WM8350_AI_FORMATING) &
+ ~WM8350_AIF_WL_MASK;
+
+ /* bit size */
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ break;
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ iface |= 0x1 << 10;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ iface |= 0x2 << 10;
+ break;
+ case SNDRV_PCM_FORMAT_S32_LE:
+ iface |= 0x3 << 10;
+ break;
+ }
+
+ wm8350_codec_write(codec, WM8350_AI_FORMATING, iface);
+ return 0;
+}
+
+static int wm8350_mute(struct snd_soc_dai *dai, int mute)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct wm8350 *wm8350 = codec->control_data;
+
+ if (mute)
+ wm8350_set_bits(wm8350, WM8350_DAC_MUTE, WM8350_DAC_MUTE_ENA);
+ else
+ wm8350_clear_bits(wm8350, WM8350_DAC_MUTE, WM8350_DAC_MUTE_ENA);
+ return 0;
+}
+
+/* FLL divisors */
+struct _fll_div {
+ int div; /* FLL_OUTDIV */
+ int n;
+ int k;
+ int ratio; /* FLL_FRATIO */
+};
+
+/* The size in bits of the fll divide multiplied by 10
+ * to allow rounding later */
+#define FIXED_FLL_SIZE ((1 << 16) * 10)
+
+static inline int fll_factors(struct _fll_div *fll_div, unsigned int input,
+ unsigned int output)
+{
+ u64 Kpart;
+ unsigned int t1, t2, K, Nmod;
+
+ if (output >= 2815250 && output <= 3125000)
+ fll_div->div = 0x4;
+ else if (output >= 5625000 && output <= 6250000)
+ fll_div->div = 0x3;
+ else if (output >= 11250000 && output <= 12500000)
+ fll_div->div = 0x2;
+ else if (output >= 22500000 && output <= 25000000)
+ fll_div->div = 0x1;
+ else {
+ printk(KERN_ERR "wm8350: fll freq %d out of range\n", output);
+ return -EINVAL;
+ }
+
+ if (input > 48000)
+ fll_div->ratio = 1;
+ else
+ fll_div->ratio = 8;
+
+ t1 = output * (1 << (fll_div->div + 1));
+ t2 = input * fll_div->ratio;
+
+ fll_div->n = t1 / t2;
+ Nmod = t1 % t2;
+
+ if (Nmod) {
+ Kpart = FIXED_FLL_SIZE * (long long)Nmod;
+ do_div(Kpart, t2);
+ K = Kpart & 0xFFFFFFFF;
+
+ /* Check if we need to round */
+ if ((K % 10) >= 5)
+ K += 5;
+
+ /* Move down to proper range now rounding is done */
+ K /= 10;
+ fll_div->k = K;
+ } else
+ fll_div->k = 0;
+
+ return 0;
+}
+
+static int wm8350_set_fll(struct snd_soc_dai *codec_dai,
+ int pll_id, unsigned int freq_in,
+ unsigned int freq_out)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct wm8350 *wm8350 = codec->control_data;
+ struct _fll_div fll_div;
+ int ret = 0;
+ u16 fll_1, fll_4;
+
+ /* power down FLL - we need to do this for reconfiguration */
+ wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_4,
+ WM8350_FLL_ENA | WM8350_FLL_OSC_ENA);
+
+ if (freq_out == 0 || freq_in == 0)
+ return ret;
+
+ ret = fll_factors(&fll_div, freq_in, freq_out);
+ if (ret < 0)
+ return ret;
+ dev_dbg(wm8350->dev,
+ "FLL in %d FLL out %d N 0x%x K 0x%x div %d ratio %d",
+ freq_in, freq_out, fll_div.n, fll_div.k, fll_div.div,
+ fll_div.ratio);
+
+ /* set up N.K & dividers */
+ fll_1 = wm8350_codec_read(codec, WM8350_FLL_CONTROL_1) &
+ ~(WM8350_FLL_OUTDIV_MASK | WM8350_FLL_RSP_RATE_MASK | 0xc000);
+ wm8350_codec_write(codec, WM8350_FLL_CONTROL_1,
+ fll_1 | (fll_div.div << 8) | 0x50);
+ wm8350_codec_write(codec, WM8350_FLL_CONTROL_2,
+ (fll_div.ratio << 11) | (fll_div.
+ n & WM8350_FLL_N_MASK));
+ wm8350_codec_write(codec, WM8350_FLL_CONTROL_3, fll_div.k);
+ fll_4 = wm8350_codec_read(codec, WM8350_FLL_CONTROL_4) &
+ ~(WM8350_FLL_FRAC | WM8350_FLL_SLOW_LOCK_REF);
+ wm8350_codec_write(codec, WM8350_FLL_CONTROL_4,
+ fll_4 | (fll_div.k ? WM8350_FLL_FRAC : 0) |
+ (fll_div.ratio == 8 ? WM8350_FLL_SLOW_LOCK_REF : 0));
+
+ /* power FLL on */
+ wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_FLL_OSC_ENA);
+ wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_FLL_ENA);
+
+ return 0;
+}
+
+static int wm8350_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ struct wm8350 *wm8350 = codec->control_data;
+ struct wm8350_data *priv = codec->private_data;
+ struct wm8350_audio_platform_data *platform =
+ wm8350->codec.platform_data;
+ u16 pm1;
+ int ret;
+
+ switch (level) {
+ case SND_SOC_BIAS_ON:
+ pm1 = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_1) &
+ ~(WM8350_VMID_MASK | WM8350_CODEC_ISEL_MASK);
+ wm8350_reg_write(wm8350, WM8350_POWER_MGMT_1,
+ pm1 | WM8350_VMID_50K |
+ platform->codec_current_on << 14);
+ break;
+
+ case SND_SOC_BIAS_PREPARE:
+ pm1 = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_1);
+ pm1 &= ~WM8350_VMID_MASK;
+ wm8350_reg_write(wm8350, WM8350_POWER_MGMT_1,
+ pm1 | WM8350_VMID_50K);
+ break;
+
+ case SND_SOC_BIAS_STANDBY:
+ if (codec->bias_level == SND_SOC_BIAS_OFF) {
+ ret = regulator_bulk_enable(ARRAY_SIZE(priv->supplies),
+ priv->supplies);
+ if (ret != 0)
+ return ret;
+
+ /* Enable the system clock */
+ wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4,
+ WM8350_SYSCLK_ENA);
+
+ /* mute DAC & outputs */
+ wm8350_set_bits(wm8350, WM8350_DAC_MUTE,
+ WM8350_DAC_MUTE_ENA);
+
+ /* discharge cap memory */
+ wm8350_reg_write(wm8350, WM8350_ANTI_POP_CONTROL,
+ platform->dis_out1 |
+ (platform->dis_out2 << 2) |
+ (platform->dis_out3 << 4) |
+ (platform->dis_out4 << 6));
+
+ /* wait for discharge */
+ schedule_timeout_interruptible(msecs_to_jiffies
+ (platform->
+ cap_discharge_msecs));
+
+ /* enable antipop */
+ wm8350_reg_write(wm8350, WM8350_ANTI_POP_CONTROL,
+ (platform->vmid_s_curve << 8));
+
+ /* ramp up vmid */
+ wm8350_reg_write(wm8350, WM8350_POWER_MGMT_1,
+ (platform->
+ codec_current_charge << 14) |
+ WM8350_VMID_5K | WM8350_VMIDEN |
+ WM8350_VBUFEN);
+
+ /* wait for vmid */
+ schedule_timeout_interruptible(msecs_to_jiffies
+ (platform->
+ vmid_charge_msecs));
+
+ /* turn on vmid 300k */
+ pm1 = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_1) &
+ ~(WM8350_VMID_MASK | WM8350_CODEC_ISEL_MASK);
+ pm1 |= WM8350_VMID_300K |
+ (platform->codec_current_standby << 14);
+ wm8350_reg_write(wm8350, WM8350_POWER_MGMT_1,
+ pm1);
+
+
+ /* enable analogue bias */
+ pm1 |= WM8350_BIASEN;
+ wm8350_reg_write(wm8350, WM8350_POWER_MGMT_1, pm1);
+
+ /* disable antipop */
+ wm8350_reg_write(wm8350, WM8350_ANTI_POP_CONTROL, 0);
+
+ } else {
+ /* turn on vmid 300k and reduce current */
+ pm1 = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_1) &
+ ~(WM8350_VMID_MASK | WM8350_CODEC_ISEL_MASK);
+ wm8350_reg_write(wm8350, WM8350_POWER_MGMT_1,
+ pm1 | WM8350_VMID_300K |
+ (platform->
+ codec_current_standby << 14));
+
+ }
+ break;
+
+ case SND_SOC_BIAS_OFF:
+
+ /* mute DAC & enable outputs */
+ wm8350_set_bits(wm8350, WM8350_DAC_MUTE, WM8350_DAC_MUTE_ENA);
+
+ wm8350_set_bits(wm8350, WM8350_POWER_MGMT_3,
+ WM8350_OUT1L_ENA | WM8350_OUT1R_ENA |
+ WM8350_OUT2L_ENA | WM8350_OUT2R_ENA);
+
+ /* enable anti pop S curve */
+ wm8350_reg_write(wm8350, WM8350_ANTI_POP_CONTROL,
+ (platform->vmid_s_curve << 8));
+
+ /* turn off vmid */
+ pm1 = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_1) &
+ ~WM8350_VMIDEN;
+ wm8350_reg_write(wm8350, WM8350_POWER_MGMT_1, pm1);
+
+ /* wait */
+ schedule_timeout_interruptible(msecs_to_jiffies
+ (platform->
+ vmid_discharge_msecs));
+
+ wm8350_reg_write(wm8350, WM8350_ANTI_POP_CONTROL,
+ (platform->vmid_s_curve << 8) |
+ platform->dis_out1 |
+ (platform->dis_out2 << 2) |
+ (platform->dis_out3 << 4) |
+ (platform->dis_out4 << 6));
+
+ /* turn off VBuf and drain */
+ pm1 = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_1) &
+ ~(WM8350_VBUFEN | WM8350_VMID_MASK);
+ wm8350_reg_write(wm8350, WM8350_POWER_MGMT_1,
+ pm1 | WM8350_OUTPUT_DRAIN_EN);
+
+ /* wait */
+ schedule_timeout_interruptible(msecs_to_jiffies
+ (platform->drain_msecs));
+
+ pm1 &= ~WM8350_BIASEN;
+ wm8350_reg_write(wm8350, WM8350_POWER_MGMT_1, pm1);
+
+ /* disable anti-pop */
+ wm8350_reg_write(wm8350, WM8350_ANTI_POP_CONTROL, 0);
+
+ wm8350_clear_bits(wm8350, WM8350_LOUT1_VOLUME,
+ WM8350_OUT1L_ENA);
+ wm8350_clear_bits(wm8350, WM8350_ROUT1_VOLUME,
+ WM8350_OUT1R_ENA);
+ wm8350_clear_bits(wm8350, WM8350_LOUT2_VOLUME,
+ WM8350_OUT2L_ENA);
+ wm8350_clear_bits(wm8350, WM8350_ROUT2_VOLUME,
+ WM8350_OUT2R_ENA);
+
+ /* disable clock gen */
+ wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_4,
+ WM8350_SYSCLK_ENA);
+
+ regulator_bulk_disable(ARRAY_SIZE(priv->supplies),
+ priv->supplies);
+ break;
+ }
+ codec->bias_level = level;
+ return 0;
+}
+
+static int wm8350_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec = socdev->codec;
+
+ wm8350_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ return 0;
+}
+
+static int wm8350_resume(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec = socdev->codec;
+
+ wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+ if (codec->suspend_bias_level == SND_SOC_BIAS_ON)
+ wm8350_set_bias_level(codec, SND_SOC_BIAS_ON);
+
+ return 0;
+}
+
+static struct snd_soc_codec *wm8350_codec;
+
+static int wm8350_probe(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec;
+ struct wm8350 *wm8350;
+ struct wm8350_data *priv;
+ int ret;
+ struct wm8350_output *out1;
+ struct wm8350_output *out2;
+
+ BUG_ON(!wm8350_codec);
+
+ socdev->codec = wm8350_codec;
+ codec = socdev->codec;
+ wm8350 = codec->control_data;
+ priv = codec->private_data;
+
+ /* Enable the codec */
+ wm8350_set_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA);
+
+ /* Enable robust clocking mode in ADC */
+ wm8350_codec_write(codec, WM8350_SECURITY, 0xa7);
+ wm8350_codec_write(codec, 0xde, 0x13);
+ wm8350_codec_write(codec, WM8350_SECURITY, 0);
+
+ /* read OUT1 & OUT2 volumes */
+ out1 = &priv->out1;
+ out2 = &priv->out2;
+ out1->left_vol = (wm8350_reg_read(wm8350, WM8350_LOUT1_VOLUME) &
+ WM8350_OUT1L_VOL_MASK) >> WM8350_OUT1L_VOL_SHIFT;
+ out1->right_vol = (wm8350_reg_read(wm8350, WM8350_ROUT1_VOLUME) &
+ WM8350_OUT1R_VOL_MASK) >> WM8350_OUT1R_VOL_SHIFT;
+ out2->left_vol = (wm8350_reg_read(wm8350, WM8350_LOUT2_VOLUME) &
+ WM8350_OUT2L_VOL_MASK) >> WM8350_OUT1L_VOL_SHIFT;
+ out2->right_vol = (wm8350_reg_read(wm8350, WM8350_ROUT2_VOLUME) &
+ WM8350_OUT2R_VOL_MASK) >> WM8350_OUT1R_VOL_SHIFT;
+ wm8350_reg_write(wm8350, WM8350_LOUT1_VOLUME, 0);
+ wm8350_reg_write(wm8350, WM8350_ROUT1_VOLUME, 0);
+ wm8350_reg_write(wm8350, WM8350_LOUT2_VOLUME, 0);
+ wm8350_reg_write(wm8350, WM8350_ROUT2_VOLUME, 0);
+
+ /* Latch VU bits & mute */
+ wm8350_set_bits(wm8350, WM8350_LOUT1_VOLUME,
+ WM8350_OUT1_VU | WM8350_OUT1L_MUTE);
+ wm8350_set_bits(wm8350, WM8350_LOUT2_VOLUME,
+ WM8350_OUT2_VU | WM8350_OUT2L_MUTE);
+ wm8350_set_bits(wm8350, WM8350_ROUT1_VOLUME,
+ WM8350_OUT1_VU | WM8350_OUT1R_MUTE);
+ wm8350_set_bits(wm8350, WM8350_ROUT2_VOLUME,
+ WM8350_OUT2_VU | WM8350_OUT2R_MUTE);
+
+ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to create pcms\n");
+ return ret;
+ }
+
+ wm8350_add_controls(codec);
+ wm8350_add_widgets(codec);
+
+ wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+ ret = snd_soc_init_card(socdev);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to register card\n");
+ goto card_err;
+ }
+
+ return 0;
+
+card_err:
+ snd_soc_free_pcms(socdev);
+ snd_soc_dapm_free(socdev);
+ return ret;
+}
+
+static int wm8350_remove(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec = socdev->codec;
+ struct wm8350 *wm8350 = codec->control_data;
+ int ret;
+
+ /* cancel any work waiting to be queued. */
+ ret = cancel_delayed_work(&codec->delayed_work);
+
+ /* if there was any work waiting then we run it now and
+ * wait for its completion */
+ if (ret) {
+ schedule_delayed_work(&codec->delayed_work, 0);
+ flush_scheduled_work();
+ }
+
+ wm8350_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+ wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA);
+
+ return 0;
+}
+
+#define WM8350_RATES (SNDRV_PCM_RATE_8000_96000)
+
+#define WM8350_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+ SNDRV_PCM_FMTBIT_S20_3LE |\
+ SNDRV_PCM_FMTBIT_S24_LE)
+
+struct snd_soc_dai wm8350_dai = {
+ .name = "WM8350",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = WM8350_RATES,
+ .formats = WM8350_FORMATS,
+ },
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = WM8350_RATES,
+ .formats = WM8350_FORMATS,
+ },
+ .ops = {
+ .hw_params = wm8350_pcm_hw_params,
+ .digital_mute = wm8350_mute,
+ .trigger = wm8350_pcm_trigger,
+ .set_fmt = wm8350_set_dai_fmt,
+ .set_sysclk = wm8350_set_dai_sysclk,
+ .set_pll = wm8350_set_fll,
+ .set_clkdiv = wm8350_set_clkdiv,
+ },
+};
+EXPORT_SYMBOL_GPL(wm8350_dai);
+
+struct snd_soc_codec_device soc_codec_dev_wm8350 = {
+ .probe = wm8350_probe,
+ .remove = wm8350_remove,
+ .suspend = wm8350_suspend,
+ .resume = wm8350_resume,
+};
+EXPORT_SYMBOL_GPL(soc_codec_dev_wm8350);
+
+static int wm8350_codec_probe(struct platform_device *pdev)
+{
+ struct wm8350 *wm8350 = platform_get_drvdata(pdev);
+ struct wm8350_data *priv;
+ struct snd_soc_codec *codec;
+ int ret, i;
+
+ if (wm8350->codec.platform_data == NULL) {
+ dev_err(&pdev->dev, "No audio platform data supplied\n");
+ return -EINVAL;
+ }
+
+ priv = kzalloc(sizeof(struct wm8350_data), GFP_KERNEL);
+ if (priv == NULL)
+ return -ENOMEM;
+
+ for (i = 0; i < ARRAY_SIZE(supply_names); i++)
+ priv->supplies[i].supply = supply_names[i];
+
+ ret = regulator_bulk_get(wm8350->dev, ARRAY_SIZE(priv->supplies),
+ priv->supplies);
+ if (ret != 0)
+ goto err_priv;
+
+ codec = &priv->codec;
+ wm8350->codec.codec = codec;
+
+ wm8350_dai.dev = &pdev->dev;
+
+ mutex_init(&codec->mutex);
+ INIT_LIST_HEAD(&codec->dapm_widgets);
+ INIT_LIST_HEAD(&codec->dapm_paths);
+ codec->dev = &pdev->dev;
+ codec->name = "WM8350";
+ codec->owner = THIS_MODULE;
+ codec->read = wm8350_codec_read;
+ codec->write = wm8350_codec_write;
+ codec->bias_level = SND_SOC_BIAS_OFF;
+ codec->set_bias_level = wm8350_set_bias_level;
+ codec->dai = &wm8350_dai;
+ codec->num_dai = 1;
+ codec->reg_cache_size = WM8350_MAX_REGISTER;
+ codec->private_data = priv;
+ codec->control_data = wm8350;
+
+ /* Put the codec into reset if it wasn't already */
+ wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA);
+
+ INIT_DELAYED_WORK(&codec->delayed_work, wm8350_pga_work);
+ ret = snd_soc_register_codec(codec);
+ if (ret != 0)
+ goto err_supply;
+
+ wm8350_codec = codec;
+
+ ret = snd_soc_register_dai(&wm8350_dai);
+ if (ret != 0)
+ goto err_codec;
+ return 0;
+
+err_codec:
+ snd_soc_unregister_codec(codec);
+err_supply:
+ regulator_bulk_free(ARRAY_SIZE(priv->supplies), priv->supplies);
+err_priv:
+ kfree(priv);
+ wm8350_codec = NULL;
+ return ret;
+}
+
+static int __devexit wm8350_codec_remove(struct platform_device *pdev)
+{
+ struct wm8350 *wm8350 = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec = wm8350->codec.codec;
+ struct wm8350_data *priv = codec->private_data;
+
+ snd_soc_unregister_dai(&wm8350_dai);
+ snd_soc_unregister_codec(codec);
+ regulator_bulk_free(ARRAY_SIZE(priv->supplies), priv->supplies);
+ kfree(priv);
+ wm8350_codec = NULL;
+ return 0;
+}
+
+static struct platform_driver wm8350_codec_driver = {
+ .driver = {
+ .name = "wm8350-codec",
+ .owner = THIS_MODULE,
+ },
+ .probe = wm8350_codec_probe,
+ .remove = __devexit_p(wm8350_codec_remove),
+};
+
+static __init int wm8350_init(void)
+{
+ return platform_driver_register(&wm8350_codec_driver);
+}
+module_init(wm8350_init);
+
+static __exit void wm8350_exit(void)
+{
+ platform_driver_unregister(&wm8350_codec_driver);
+}
+module_exit(wm8350_exit);
+
+MODULE_DESCRIPTION("ASoC WM8350 driver");
+MODULE_AUTHOR("Liam Girdwood");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:wm8350-codec");
diff --git a/sound/soc/codecs/wm8350.h b/sound/soc/codecs/wm8350.h
new file mode 100644
index 00000000000..cc2887aa6c3
--- /dev/null
+++ b/sound/soc/codecs/wm8350.h
@@ -0,0 +1,20 @@
+/*
+ * wm8350.h - WM8903 audio codec interface
+ *
+ * Copyright 2008 Wolfson Microelectronics PLC.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef _WM8350_H
+#define _WM8350_H
+
+#include <sound/soc.h>
+
+extern struct snd_soc_dai wm8350_dai;
+extern struct snd_soc_codec_device soc_codec_dev_wm8350;
+
+#endif
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c
index d8ca2da8d63..40f8238df71 100644
--- a/sound/soc/codecs/wm8510.c
+++ b/sound/soc/codecs/wm8510.c
@@ -463,7 +463,8 @@ static int wm8510_set_dai_fmt(struct snd_soc_dai *codec_dai,
}
static int wm8510_pcm_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
@@ -585,8 +586,6 @@ struct snd_soc_dai wm8510_dai = {
.formats = WM8510_FORMATS,},
.ops = {
.hw_params = wm8510_pcm_hw_params,
- },
- .dai_ops = {
.digital_mute = wm8510_mute,
.set_fmt = wm8510_set_dai_fmt,
.set_clkdiv = wm8510_set_dai_clkdiv,
@@ -659,7 +658,7 @@ static int wm8510_init(struct snd_soc_device *socdev)
wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
wm8510_add_controls(codec);
wm8510_add_widgets(codec);
- ret = snd_soc_register_card(socdev);
+ ret = snd_soc_init_card(socdev);
if (ret < 0) {
printk(KERN_ERR "wm8510: failed to register card\n");
goto card_err;
@@ -890,6 +889,18 @@ struct snd_soc_codec_device soc_codec_dev_wm8510 = {
};
EXPORT_SYMBOL_GPL(soc_codec_dev_wm8510);
+static int __init wm8510_modinit(void)
+{
+ return snd_soc_register_dai(&wm8510_dai);
+}
+module_init(wm8510_modinit);
+
+static void __exit wm8510_exit(void)
+{
+ snd_soc_unregister_dai(&wm8510_dai);
+}
+module_exit(wm8510_exit);
+
MODULE_DESCRIPTION("ASoC WM8510 driver");
MODULE_AUTHOR("Liam Girdwood");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c
index 627ebfb4209..d004e584529 100644
--- a/sound/soc/codecs/wm8580.c
+++ b/sound/soc/codecs/wm8580.c
@@ -548,13 +548,13 @@ static int wm8580_set_dai_pll(struct snd_soc_dai *codec_dai,
* Set PCM DAI bit size and sample rate.
*/
static int wm8580_paif_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai_link *dai = rtd->dai;
struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->codec;
- u16 paifb = wm8580_read(codec, WM8580_PAIF3 + dai->codec_dai->id);
+ u16 paifb = wm8580_read(codec, WM8580_PAIF3 + dai->id);
paifb &= ~WM8580_AIF_LENGTH_MASK;
/* bit size */
@@ -574,7 +574,7 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
- wm8580_write(codec, WM8580_PAIF3 + dai->codec_dai->id, paifb);
+ wm8580_write(codec, WM8580_PAIF3 + dai->id, paifb);
return 0;
}
@@ -798,8 +798,6 @@ struct snd_soc_dai wm8580_dai[] = {
},
.ops = {
.hw_params = wm8580_paif_hw_params,
- },
- .dai_ops = {
.set_fmt = wm8580_set_paif_dai_fmt,
.set_clkdiv = wm8580_set_dai_clkdiv,
.set_pll = wm8580_set_dai_pll,
@@ -818,8 +816,6 @@ struct snd_soc_dai wm8580_dai[] = {
},
.ops = {
.hw_params = wm8580_paif_hw_params,
- },
- .dai_ops = {
.set_fmt = wm8580_set_paif_dai_fmt,
.set_clkdiv = wm8580_set_dai_clkdiv,
.set_pll = wm8580_set_dai_pll,
@@ -873,7 +869,7 @@ static int wm8580_init(struct snd_soc_device *socdev)
wm8580_add_controls(codec);
wm8580_add_widgets(codec);
- ret = snd_soc_register_card(socdev);
+ ret = snd_soc_init_card(socdev);
if (ret < 0) {
printk(KERN_ERR "wm8580: failed to register card\n");
goto card_err;
@@ -900,85 +896,85 @@ static struct snd_soc_device *wm8580_socdev;
* low = 0x1a
* high = 0x1b
*/
-static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END };
-
-/* Magic definition of all other variables and things */
-I2C_CLIENT_INSMOD;
-static struct i2c_driver wm8580_i2c_driver;
-static struct i2c_client client_template;
-
-static int wm8580_codec_probe(struct i2c_adapter *adap, int addr, int kind)
+static int wm8580_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct snd_soc_device *socdev = wm8580_socdev;
- struct wm8580_setup_data *setup = socdev->codec_data;
struct snd_soc_codec *codec = socdev->codec;
- struct i2c_client *i2c;
int ret;
- if (addr != setup->i2c_address)
- return -ENODEV;
-
- client_template.adapter = adap;
- client_template.addr = addr;
-
- i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
- if (i2c == NULL) {
- kfree(codec);
- return -ENOMEM;
- }
i2c_set_clientdata(i2c, codec);
codec->control_data = i2c;
- ret = i2c_attach_client(i2c);
- if (ret < 0) {
- dev_err(&i2c->dev, "failed to attach codec at addr %x\n", addr);
- goto err;
- }
-
ret = wm8580_init(socdev);
- if (ret < 0) {
+ if (ret < 0)
dev_err(&i2c->dev, "failed to initialise WM8580\n");
- goto err;
- }
-
- return ret;
-
-err:
- kfree(codec);
- kfree(i2c);
return ret;
}
-static int wm8580_i2c_detach(struct i2c_client *client)
+static int wm8580_i2c_remove(struct i2c_client *client)
{
struct snd_soc_codec *codec = i2c_get_clientdata(client);
- i2c_detach_client(client);
kfree(codec->reg_cache);
- kfree(client);
return 0;
}
-static int wm8580_i2c_attach(struct i2c_adapter *adap)
-{
- return i2c_probe(adap, &addr_data, wm8580_codec_probe);
-}
+static const struct i2c_device_id wm8580_i2c_id[] = {
+ { "wm8580", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, wm8580_i2c_id);
-/* corgi i2c codec control layer */
static struct i2c_driver wm8580_i2c_driver = {
.driver = {
.name = "WM8580 I2C Codec",
.owner = THIS_MODULE,
},
- .attach_adapter = wm8580_i2c_attach,
- .detach_client = wm8580_i2c_detach,
- .command = NULL,
+ .probe = wm8580_i2c_probe,
+ .remove = wm8580_i2c_remove,
+ .id_table = wm8580_i2c_id,
};
-static struct i2c_client client_template = {
- .name = "WM8580",
- .driver = &wm8580_i2c_driver,
-};
+static int wm8580_add_i2c_device(struct platform_device *pdev,
+ const struct wm8580_setup_data *setup)
+{
+ struct i2c_board_info info;
+ struct i2c_adapter *adapter;
+ struct i2c_client *client;
+ int ret;
+
+ ret = i2c_add_driver(&wm8580_i2c_driver);
+ if (ret != 0) {
+ dev_err(&pdev->dev, "can't add i2c driver\n");
+ return ret;
+ }
+
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ info.addr = setup->i2c_address;
+ strlcpy(info.type, "wm8580", I2C_NAME_SIZE);
+
+ adapter = i2c_get_adapter(setup->i2c_bus);
+ if (!adapter) {
+ dev_err(&pdev->dev, "can't get i2c adapter %d\n",
+ setup->i2c_bus);
+ goto err_driver;
+ }
+
+ client = i2c_new_device(adapter, &info);
+ i2c_put_adapter(adapter);
+ if (!client) {
+ dev_err(&pdev->dev, "can't add i2c device at 0x%x\n",
+ (unsigned int)info.addr);
+ goto err_driver;
+ }
+
+ return 0;
+
+err_driver:
+ i2c_del_driver(&wm8580_i2c_driver);
+ return -ENODEV;
+}
#endif
static int wm8580_probe(struct platform_device *pdev)
@@ -1011,11 +1007,8 @@ static int wm8580_probe(struct platform_device *pdev)
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
if (setup->i2c_address) {
- normal_i2c[0] = setup->i2c_address;
codec->hw_write = (hw_write_t)i2c_master_send;
- ret = i2c_add_driver(&wm8580_i2c_driver);
- if (ret != 0)
- printk(KERN_ERR "can't add i2c driver");
+ ret = wm8580_add_i2c_device(pdev, setup);
}
#else
/* Add other interfaces here */
@@ -1034,6 +1027,7 @@ static int wm8580_remove(struct platform_device *pdev)
snd_soc_free_pcms(socdev);
snd_soc_dapm_free(socdev);
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+ i2c_unregister_device(codec->control_data);
i2c_del_driver(&wm8580_i2c_driver);
#endif
kfree(codec->private_data);
@@ -1048,6 +1042,18 @@ struct snd_soc_codec_device soc_codec_dev_wm8580 = {
};
EXPORT_SYMBOL_GPL(soc_codec_dev_wm8580);
+static int __init wm8580_modinit(void)
+{
+ return snd_soc_register_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai));
+}
+module_init(wm8580_modinit);
+
+static void __exit wm8580_exit(void)
+{
+ snd_soc_unregister_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai));
+}
+module_exit(wm8580_exit);
+
MODULE_DESCRIPTION("ASoC WM8580 driver");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8580.h b/sound/soc/codecs/wm8580.h
index 589ddaba21d..09e4422f6f2 100644
--- a/sound/soc/codecs/wm8580.h
+++ b/sound/soc/codecs/wm8580.h
@@ -29,6 +29,7 @@
#define WM8580_CLKSRC_NONE 5
struct wm8580_setup_data {
+ int i2c_bus;
unsigned short i2c_address;
};
diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c
new file mode 100644
index 00000000000..80b11983e13
--- /dev/null
+++ b/sound/soc/codecs/wm8728.c
@@ -0,0 +1,585 @@
+/*
+ * wm8728.c -- WM8728 ALSA SoC Audio driver
+ *
+ * Copyright 2008 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include "wm8728.h"
+
+struct snd_soc_codec_device soc_codec_dev_wm8728;
+
+/*
+ * We can't read the WM8728 register space so we cache them instead.
+ * Note that the defaults here aren't the physical defaults, we latch
+ * the volume update bits, mute the output and enable infinite zero
+ * detect.
+ */
+static const u16 wm8728_reg_defaults[] = {
+ 0x1ff,
+ 0x1ff,
+ 0x001,
+ 0x100,
+};
+
+static inline unsigned int wm8728_read_reg_cache(struct snd_soc_codec *codec,
+ unsigned int reg)
+{
+ u16 *cache = codec->reg_cache;
+ BUG_ON(reg > ARRAY_SIZE(wm8728_reg_defaults));
+ return cache[reg];
+}
+
+static inline void wm8728_write_reg_cache(struct snd_soc_codec *codec,
+ u16 reg, unsigned int value)
+{
+ u16 *cache = codec->reg_cache;
+ BUG_ON(reg > ARRAY_SIZE(wm8728_reg_defaults));
+ cache[reg] = value;
+}
+
+/*
+ * write to the WM8728 register space
+ */
+static int wm8728_write(struct snd_soc_codec *codec, unsigned int reg,
+ unsigned int value)
+{
+ u8 data[2];
+
+ /* data is
+ * D15..D9 WM8728 register offset
+ * D8...D0 register data
+ */
+ data[0] = (reg << 1) | ((value >> 8) & 0x0001);
+ data[1] = value & 0x00ff;
+
+ wm8728_write_reg_cache(codec, reg, value);
+
+ if (codec->hw_write(codec->control_data, data, 2) == 2)
+ return 0;
+ else
+ return -EIO;
+}
+
+static const DECLARE_TLV_DB_SCALE(wm8728_tlv, -12750, 50, 1);
+
+static const struct snd_kcontrol_new wm8728_snd_controls[] = {
+
+SOC_DOUBLE_R_TLV("Digital Playback Volume", WM8728_DACLVOL, WM8728_DACRVOL,
+ 0, 255, 0, wm8728_tlv),
+
+SOC_SINGLE("Deemphasis", WM8728_DACCTL, 1, 1, 0),
+};
+
+static int wm8728_add_controls(struct snd_soc_codec *codec)
+{
+ int err, i;
+
+ for (i = 0; i < ARRAY_SIZE(wm8728_snd_controls); i++) {
+ err = snd_ctl_add(codec->card,
+ snd_soc_cnew(&wm8728_snd_controls[i],
+ codec, NULL));
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
+/*
+ * DAPM controls.
+ */
+static const struct snd_soc_dapm_widget wm8728_dapm_widgets[] = {
+SND_SOC_DAPM_DAC("DAC", "HiFi Playback", SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_OUTPUT("VOUTL"),
+SND_SOC_DAPM_OUTPUT("VOUTR"),
+};
+
+static const struct snd_soc_dapm_route intercon[] = {
+ {"VOUTL", NULL, "DAC"},
+ {"VOUTR", NULL, "DAC"},
+};
+
+static int wm8728_add_widgets(struct snd_soc_codec *codec)
+{
+ snd_soc_dapm_new_controls(codec, wm8728_dapm_widgets,
+ ARRAY_SIZE(wm8728_dapm_widgets));
+
+ snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
+
+ snd_soc_dapm_new_widgets(codec);
+
+ return 0;
+}
+
+static int wm8728_mute(struct snd_soc_dai *dai, int mute)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ u16 mute_reg = wm8728_read_reg_cache(codec, WM8728_DACCTL);
+
+ if (mute)
+ wm8728_write(codec, WM8728_DACCTL, mute_reg | 1);
+ else
+ wm8728_write(codec, WM8728_DACCTL, mute_reg & ~1);
+
+ return 0;
+}
+
+static int wm8728_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_device *socdev = rtd->socdev;
+ struct snd_soc_codec *codec = socdev->codec;
+ u16 dac = wm8728_read_reg_cache(codec, WM8728_DACCTL);
+
+ dac &= ~0x18;
+
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ break;
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ dac |= 0x10;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ dac |= 0x08;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ wm8728_write(codec, WM8728_DACCTL, dac);
+
+ return 0;
+}
+
+static int wm8728_set_dai_fmt(struct snd_soc_dai *codec_dai,
+ unsigned int fmt)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ u16 iface = wm8728_read_reg_cache(codec, WM8728_IFCTL);
+
+ /* Currently only I2S is supported by the driver, though the
+ * hardware is more flexible.
+ */
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ iface |= 1;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* The hardware only support full slave mode */
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBS_CFS:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ iface &= ~0x22;
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ iface |= 0x20;
+ iface &= ~0x02;
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ iface |= 0x02;
+ iface &= ~0x20;
+ break;
+ case SND_SOC_DAIFMT_IB_IF:
+ iface |= 0x22;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ wm8728_write(codec, WM8728_IFCTL, iface);
+ return 0;
+}
+
+static int wm8728_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ u16 reg;
+ int i;
+
+ switch (level) {
+ case SND_SOC_BIAS_ON:
+ case SND_SOC_BIAS_PREPARE:
+ case SND_SOC_BIAS_STANDBY:
+ if (codec->bias_level == SND_SOC_BIAS_OFF) {
+ /* Power everything up... */
+ reg = wm8728_read_reg_cache(codec, WM8728_DACCTL);
+ wm8728_write(codec, WM8728_DACCTL, reg & ~0x4);
+
+ /* ..then sync in the register cache. */
+ for (i = 0; i < ARRAY_SIZE(wm8728_reg_defaults); i++)
+ wm8728_write(codec, i,
+ wm8728_read_reg_cache(codec, i));
+ }
+ break;
+
+ case SND_SOC_BIAS_OFF:
+ reg = wm8728_read_reg_cache(codec, WM8728_DACCTL);
+ wm8728_write(codec, WM8728_DACCTL, reg | 0x4);
+ break;
+ }
+ codec->bias_level = level;
+ return 0;
+}
+
+#define WM8728_RATES (SNDRV_PCM_RATE_8000_192000)
+
+#define WM8728_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
+ SNDRV_PCM_FMTBIT_S24_LE)
+
+struct snd_soc_dai wm8728_dai = {
+ .name = "WM8728",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = WM8728_RATES,
+ .formats = WM8728_FORMATS,
+ },
+ .ops = {
+ .hw_params = wm8728_hw_params,
+ .digital_mute = wm8728_mute,
+ .set_fmt = wm8728_set_dai_fmt,
+ }
+};
+EXPORT_SYMBOL_GPL(wm8728_dai);
+
+static int wm8728_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec = socdev->codec;
+
+ wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+ return 0;
+}
+
+static int wm8728_resume(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec = socdev->codec;
+
+ wm8728_set_bias_level(codec, codec->suspend_bias_level);
+
+ return 0;
+}
+
+/*
+ * initialise the WM8728 driver
+ * register the mixer and dsp interfaces with the kernel
+ */
+static int wm8728_init(struct snd_soc_device *socdev)
+{
+ struct snd_soc_codec *codec = socdev->codec;
+ int ret = 0;
+
+ codec->name = "WM8728";
+ codec->owner = THIS_MODULE;
+ codec->read = wm8728_read_reg_cache;
+ codec->write = wm8728_write;
+ codec->set_bias_level = wm8728_set_bias_level;
+ codec->dai = &wm8728_dai;
+ codec->num_dai = 1;
+ codec->bias_level = SND_SOC_BIAS_OFF;
+ codec->reg_cache_size = ARRAY_SIZE(wm8728_reg_defaults);
+ codec->reg_cache = kmemdup(wm8728_reg_defaults,
+ sizeof(wm8728_reg_defaults),
+ GFP_KERNEL);
+ if (codec->reg_cache == NULL)
+ return -ENOMEM;
+
+ /* register pcms */
+ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+ if (ret < 0) {
+ printk(KERN_ERR "wm8728: failed to create pcms\n");
+ goto pcm_err;
+ }
+
+ /* power on device */
+ wm8728_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+ wm8728_add_controls(codec);
+ wm8728_add_widgets(codec);
+ ret = snd_soc_init_card(socdev);
+ if (ret < 0) {
+ printk(KERN_ERR "wm8728: failed to register card\n");
+ goto card_err;
+ }
+
+ return ret;
+
+card_err:
+ snd_soc_free_pcms(socdev);
+ snd_soc_dapm_free(socdev);
+pcm_err:
+ kfree(codec->reg_cache);
+ return ret;
+}
+
+static struct snd_soc_device *wm8728_socdev;
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+
+/*
+ * WM8728 2 wire address is determined by GPIO5
+ * state during powerup.
+ * low = 0x1a
+ * high = 0x1b
+ */
+
+static int wm8728_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct snd_soc_device *socdev = wm8728_socdev;
+ struct snd_soc_codec *codec = socdev->codec;
+ int ret;
+
+ i2c_set_clientdata(i2c, codec);
+ codec->control_data = i2c;
+
+ ret = wm8728_init(socdev);
+ if (ret < 0)
+ pr_err("failed to initialise WM8728\n");
+
+ return ret;
+}
+
+static int wm8728_i2c_remove(struct i2c_client *client)
+{
+ struct snd_soc_codec *codec = i2c_get_clientdata(client);
+ kfree(codec->reg_cache);
+ return 0;
+}
+
+static const struct i2c_device_id wm8728_i2c_id[] = {
+ { "wm8728", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, wm8728_i2c_id);
+
+static struct i2c_driver wm8728_i2c_driver = {
+ .driver = {
+ .name = "WM8728 I2C Codec",
+ .owner = THIS_MODULE,
+ },
+ .probe = wm8728_i2c_probe,
+ .remove = wm8728_i2c_remove,
+ .id_table = wm8728_i2c_id,
+};
+
+static int wm8728_add_i2c_device(struct platform_device *pdev,
+ const struct wm8728_setup_data *setup)
+{
+ struct i2c_board_info info;
+ struct i2c_adapter *adapter;
+ struct i2c_client *client;
+ int ret;
+
+ ret = i2c_add_driver(&wm8728_i2c_driver);
+ if (ret != 0) {
+ dev_err(&pdev->dev, "can't add i2c driver\n");
+ return ret;
+ }
+
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ info.addr = setup->i2c_address;
+ strlcpy(info.type, "wm8728", I2C_NAME_SIZE);
+
+ adapter = i2c_get_adapter(setup->i2c_bus);
+ if (!adapter) {
+ dev_err(&pdev->dev, "can't get i2c adapter %d\n",
+ setup->i2c_bus);
+ goto err_driver;
+ }
+
+ client = i2c_new_device(adapter, &info);
+ i2c_put_adapter(adapter);
+ if (!client) {
+ dev_err(&pdev->dev, "can't add i2c device at 0x%x\n",
+ (unsigned int)info.addr);
+ goto err_driver;
+ }
+
+ return 0;
+
+err_driver:
+ i2c_del_driver(&wm8728_i2c_driver);
+ return -ENODEV;
+}
+#endif
+
+#if defined(CONFIG_SPI_MASTER)
+static int __devinit wm8728_spi_probe(struct spi_device *spi)
+{
+ struct snd_soc_device *socdev = wm8728_socdev;
+ struct snd_soc_codec *codec = socdev->codec;
+ int ret;
+
+ codec->control_data = spi;
+
+ ret = wm8728_init(socdev);
+ if (ret < 0)
+ dev_err(&spi->dev, "failed to initialise WM8728\n");
+
+ return ret;
+}
+
+static int __devexit wm8728_spi_remove(struct spi_device *spi)
+{
+ return 0;
+}
+
+static struct spi_driver wm8728_spi_driver = {
+ .driver = {
+ .name = "wm8728",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ .probe = wm8728_spi_probe,
+ .remove = __devexit_p(wm8728_spi_remove),
+};
+
+static int wm8728_spi_write(struct spi_device *spi, const char *data, int len)
+{
+ struct spi_transfer t;
+ struct spi_message m;
+ u8 msg[2];
+
+ if (len <= 0)
+ return 0;
+
+ msg[0] = data[0];
+ msg[1] = data[1];
+
+ spi_message_init(&m);
+ memset(&t, 0, (sizeof t));
+
+ t.tx_buf = &msg[0];
+ t.len = len;
+
+ spi_message_add_tail(&t, &m);
+ spi_sync(spi, &m);
+
+ return len;
+}
+#endif /* CONFIG_SPI_MASTER */
+
+static int wm8728_probe(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct wm8728_setup_data *setup;
+ struct snd_soc_codec *codec;
+ int ret = 0;
+
+ setup = socdev->codec_data;
+ codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
+ if (codec == NULL)
+ return -ENOMEM;
+
+ socdev->codec = codec;
+ mutex_init(&codec->mutex);
+ INIT_LIST_HEAD(&codec->dapm_widgets);
+ INIT_LIST_HEAD(&codec->dapm_paths);
+
+ wm8728_socdev = socdev;
+ ret = -ENODEV;
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+ if (setup->i2c_address) {
+ codec->hw_write = (hw_write_t)i2c_master_send;
+ ret = wm8728_add_i2c_device(pdev, setup);
+ }
+#endif
+#if defined(CONFIG_SPI_MASTER)
+ if (setup->spi) {
+ codec->hw_write = (hw_write_t)wm8728_spi_write;
+ ret = spi_register_driver(&wm8728_spi_driver);
+ if (ret != 0)
+ printk(KERN_ERR "can't add spi driver");
+ }
+#endif
+
+ if (ret != 0)
+ kfree(codec);
+
+ return ret;
+}
+
+/* power down chip */
+static int wm8728_remove(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec = socdev->codec;
+
+ if (codec->control_data)
+ wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+ snd_soc_free_pcms(socdev);
+ snd_soc_dapm_free(socdev);
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+ i2c_unregister_device(codec->control_data);
+ i2c_del_driver(&wm8728_i2c_driver);
+#endif
+#if defined(CONFIG_SPI_MASTER)
+ spi_unregister_driver(&wm8728_spi_driver);
+#endif
+ kfree(codec);
+
+ return 0;
+}
+
+struct snd_soc_codec_device soc_codec_dev_wm8728 = {
+ .probe = wm8728_probe,
+ .remove = wm8728_remove,
+ .suspend = wm8728_suspend,
+ .resume = wm8728_resume,
+};
+EXPORT_SYMBOL_GPL(soc_codec_dev_wm8728);
+
+static int __init wm8728_modinit(void)
+{
+ return snd_soc_register_dai(&wm8728_dai);
+}
+module_init(wm8728_modinit);
+
+static void __exit wm8728_exit(void)
+{
+ snd_soc_unregister_dai(&wm8728_dai);
+}
+module_exit(wm8728_exit);
+
+MODULE_DESCRIPTION("ASoC WM8728 driver");
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8728.h b/sound/soc/codecs/wm8728.h
new file mode 100644
index 00000000000..d269c132474
--- /dev/null
+++ b/sound/soc/codecs/wm8728.h
@@ -0,0 +1,30 @@
+/*
+ * wm8728.h -- WM8728 ASoC codec driver
+ *
+ * Copyright 2008 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * 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 _WM8728_H
+#define _WM8728_H
+
+#define WM8728_DACLVOL 0x00
+#define WM8728_DACRVOL 0x01
+#define WM8728_DACCTL 0x02
+#define WM8728_IFCTL 0x03
+
+struct wm8728_setup_data {
+ int spi;
+ int i2c_bus;
+ unsigned short i2c_address;
+};
+
+extern struct snd_soc_dai wm8728_dai;
+extern struct snd_soc_codec_device soc_codec_dev_wm8728;
+
+#endif
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index 7f8a7e36b33..c444b9f2701 100644
--- a/sound/soc/codecs/wm8731.c
+++ b/sound/soc/codecs/wm8731.c
@@ -264,7 +264,8 @@ static inline int get_coeff(int mclk, int rate)
}
static int wm8731_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
@@ -293,7 +294,8 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream,
return 0;
}
-static int wm8731_pcm_prepare(struct snd_pcm_substream *substream)
+static int wm8731_pcm_prepare(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
@@ -305,7 +307,8 @@ static int wm8731_pcm_prepare(struct snd_pcm_substream *substream)
return 0;
}
-static void wm8731_shutdown(struct snd_pcm_substream *substream)
+static void wm8731_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
@@ -461,8 +464,6 @@ struct snd_soc_dai wm8731_dai = {
.prepare = wm8731_pcm_prepare,
.hw_params = wm8731_hw_params,
.shutdown = wm8731_shutdown,
- },
- .dai_ops = {
.digital_mute = wm8731_mute,
.set_sysclk = wm8731_set_dai_sysclk,
.set_fmt = wm8731_set_dai_fmt,
@@ -544,7 +545,7 @@ static int wm8731_init(struct snd_soc_device *socdev)
wm8731_add_controls(codec);
wm8731_add_widgets(codec);
- ret = snd_soc_register_card(socdev);
+ ret = snd_soc_init_card(socdev);
if (ret < 0) {
printk(KERN_ERR "wm8731: failed to register card\n");
goto card_err;
@@ -792,6 +793,18 @@ struct snd_soc_codec_device soc_codec_dev_wm8731 = {
};
EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731);
+static int __init wm8731_modinit(void)
+{
+ return snd_soc_register_dai(&wm8731_dai);
+}
+module_init(wm8731_modinit);
+
+static void __exit wm8731_exit(void)
+{
+ snd_soc_unregister_dai(&wm8731_dai);
+}
+module_exit(wm8731_exit);
+
MODULE_DESCRIPTION("ASoC WM8731 driver");
MODULE_AUTHOR("Richard Purdie");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c
index 9b7296ee5b0..5997fa68e0d 100644
--- a/sound/soc/codecs/wm8750.c
+++ b/sound/soc/codecs/wm8750.c
@@ -614,7 +614,8 @@ static int wm8750_set_dai_fmt(struct snd_soc_dai *codec_dai,
}
static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
@@ -709,8 +710,6 @@ struct snd_soc_dai wm8750_dai = {
.formats = WM8750_FORMATS,},
.ops = {
.hw_params = wm8750_pcm_hw_params,
- },
- .dai_ops = {
.digital_mute = wm8750_mute,
.set_fmt = wm8750_set_dai_fmt,
.set_sysclk = wm8750_set_dai_sysclk,
@@ -819,7 +818,7 @@ static int wm8750_init(struct snd_soc_device *socdev)
wm8750_add_controls(codec);
wm8750_add_widgets(codec);
- ret = snd_soc_register_card(socdev);
+ ret = snd_soc_init_card(socdev);
if (ret < 0) {
printk(KERN_ERR "wm8750: failed to register card\n");
goto card_err;
@@ -1086,6 +1085,18 @@ struct snd_soc_codec_device soc_codec_dev_wm8750 = {
};
EXPORT_SYMBOL_GPL(soc_codec_dev_wm8750);
+static int __init wm8750_modinit(void)
+{
+ return snd_soc_register_dai(&wm8750_dai);
+}
+module_init(wm8750_modinit);
+
+static void __exit wm8750_exit(void)
+{
+ snd_soc_unregister_dai(&wm8750_dai);
+}
+module_exit(wm8750_exit);
+
MODULE_DESCRIPTION("ASoC WM8750 driver");
MODULE_AUTHOR("Liam Girdwood");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index d426eaa2218..6c21b50c937 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -922,7 +922,8 @@ static int wm8753_vdac_adc_set_dai_fmt(struct snd_soc_dai *codec_dai,
* Set PCM DAI bit size and sample rate.
*/
static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
@@ -1155,7 +1156,8 @@ static int wm8753_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai,
* Set PCM DAI bit size and sample rate.
*/
static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
@@ -1323,16 +1325,15 @@ static const struct snd_soc_dai wm8753_all_dai[] = {
.channels_min = 1,
.channels_max = 2,
.rates = WM8753_RATES,
- .formats = WM8753_FORMATS,},
+ .formats = WM8753_FORMATS},
.capture = { /* dummy for fast DAI switching */
.stream_name = "Capture",
.channels_min = 1,
.channels_max = 2,
.rates = WM8753_RATES,
- .formats = WM8753_FORMATS,},
+ .formats = WM8753_FORMATS},
.ops = {
- .hw_params = wm8753_i2s_hw_params,},
- .dai_ops = {
+ .hw_params = wm8753_i2s_hw_params,
.digital_mute = wm8753_mute,
.set_fmt = wm8753_mode1h_set_dai_fmt,
.set_clkdiv = wm8753_set_dai_clkdiv,
@@ -1356,8 +1357,7 @@ static const struct snd_soc_dai wm8753_all_dai[] = {
.rates = WM8753_RATES,
.formats = WM8753_FORMATS,},
.ops = {
- .hw_params = wm8753_pcm_hw_params,},
- .dai_ops = {
+ .hw_params = wm8753_pcm_hw_params,
.digital_mute = wm8753_mute,
.set_fmt = wm8753_mode1v_set_dai_fmt,
.set_clkdiv = wm8753_set_dai_clkdiv,
@@ -1385,8 +1385,7 @@ static const struct snd_soc_dai wm8753_all_dai[] = {
.rates = WM8753_RATES,
.formats = WM8753_FORMATS,},
.ops = {
- .hw_params = wm8753_pcm_hw_params,},
- .dai_ops = {
+ .hw_params = wm8753_pcm_hw_params,
.digital_mute = wm8753_mute,
.set_fmt = wm8753_mode2_set_dai_fmt,
.set_clkdiv = wm8753_set_dai_clkdiv,
@@ -1410,8 +1409,7 @@ static const struct snd_soc_dai wm8753_all_dai[] = {
.rates = WM8753_RATES,
.formats = WM8753_FORMATS,},
.ops = {
- .hw_params = wm8753_i2s_hw_params,},
- .dai_ops = {
+ .hw_params = wm8753_i2s_hw_params,
.digital_mute = wm8753_mute,
.set_fmt = wm8753_mode3_4_set_dai_fmt,
.set_clkdiv = wm8753_set_dai_clkdiv,
@@ -1439,8 +1437,7 @@ static const struct snd_soc_dai wm8753_all_dai[] = {
.rates = WM8753_RATES,
.formats = WM8753_FORMATS,},
.ops = {
- .hw_params = wm8753_i2s_hw_params,},
- .dai_ops = {
+ .hw_params = wm8753_i2s_hw_params,
.digital_mute = wm8753_mute,
.set_fmt = wm8753_mode3_4_set_dai_fmt,
.set_clkdiv = wm8753_set_dai_clkdiv,
@@ -1608,7 +1605,7 @@ static int wm8753_init(struct snd_soc_device *socdev)
wm8753_add_controls(codec);
wm8753_add_widgets(codec);
- ret = snd_soc_register_card(socdev);
+ ret = snd_soc_init_card(socdev);
if (ret < 0) {
printk(KERN_ERR "wm8753: failed to register card\n");
goto card_err;
@@ -1877,6 +1874,18 @@ struct snd_soc_codec_device soc_codec_dev_wm8753 = {
};
EXPORT_SYMBOL_GPL(soc_codec_dev_wm8753);
+static int __init wm8753_modinit(void)
+{
+ return snd_soc_register_dais(wm8753_dai, ARRAY_SIZE(wm8753_dai));
+}
+module_init(wm8753_modinit);
+
+static void __exit wm8753_exit(void)
+{
+ snd_soc_unregister_dais(wm8753_dai, ARRAY_SIZE(wm8753_dai));
+}
+module_exit(wm8753_exit);
+
MODULE_DESCRIPTION("ASoC WM8753 driver");
MODULE_AUTHOR("Liam Girdwood");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c
index 3b326c9b558..6767de10ded 100644
--- a/sound/soc/codecs/wm8900.c
+++ b/sound/soc/codecs/wm8900.c
@@ -138,6 +138,10 @@
struct snd_soc_codec_device soc_codec_dev_wm8900;
struct wm8900_priv {
+ struct snd_soc_codec codec;
+
+ u16 reg_cache[WM8900_MAXREG];
+
u32 fll_in; /* FLL input frequency */
u32 fll_out; /* FLL output frequency */
};
@@ -727,7 +731,8 @@ static int wm8900_add_widgets(struct snd_soc_codec *codec)
}
static int wm8900_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
@@ -1117,8 +1122,6 @@ struct snd_soc_dai wm8900_dai = {
},
.ops = {
.hw_params = wm8900_hw_params,
- },
- .dai_ops = {
.set_clkdiv = wm8900_set_dai_clkdiv,
.set_pll = wm8900_set_dai_pll,
.set_fmt = wm8900_set_dai_fmt,
@@ -1283,16 +1286,28 @@ static int wm8900_resume(struct platform_device *pdev)
return 0;
}
-/*
- * initialise the WM8900 driver
- * register the mixer and dsp interfaces with the kernel
- */
-static int wm8900_init(struct snd_soc_device *socdev)
+static struct snd_soc_codec *wm8900_codec;
+
+static int wm8900_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
- struct snd_soc_codec *codec = socdev->codec;
- int ret = 0;
+ struct wm8900_priv *wm8900;
+ struct snd_soc_codec *codec;
unsigned int reg;
- struct i2c_client *i2c_client = socdev->codec->control_data;
+ int ret;
+
+ wm8900 = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL);
+ if (wm8900 == NULL)
+ return -ENOMEM;
+
+ codec = &wm8900->codec;
+ codec->private_data = wm8900;
+ codec->reg_cache = &wm8900->reg_cache[0];
+ codec->reg_cache_size = WM8900_MAXREG;
+
+ mutex_init(&codec->mutex);
+ INIT_LIST_HEAD(&codec->dapm_widgets);
+ INIT_LIST_HEAD(&codec->dapm_paths);
codec->name = "WM8900";
codec->owner = THIS_MODULE;
@@ -1300,33 +1315,28 @@ static int wm8900_init(struct snd_soc_device *socdev)
codec->write = wm8900_write;
codec->dai = &wm8900_dai;
codec->num_dai = 1;
- codec->reg_cache_size = WM8900_MAXREG;
- codec->reg_cache = kmemdup(wm8900_reg_defaults,
- sizeof(wm8900_reg_defaults), GFP_KERNEL);
-
- if (codec->reg_cache == NULL)
- return -ENOMEM;
+ codec->hw_write = (hw_write_t)i2c_master_send;
+ codec->control_data = i2c;
+ codec->set_bias_level = wm8900_set_bias_level;
+ codec->dev = &i2c->dev;
reg = wm8900_read(codec, WM8900_REG_ID);
if (reg != 0x8900) {
- dev_err(&i2c_client->dev, "Device is not a WM8900 - ID %x\n",
- reg);
- return -ENODEV;
- }
-
- codec->private_data = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL);
- if (codec->private_data == NULL) {
- ret = -ENOMEM;
- goto priv_err;
+ dev_err(&i2c->dev, "Device is not a WM8900 - ID %x\n", reg);
+ ret = -ENODEV;
+ goto err;
}
/* Read back from the chip */
reg = wm8900_chip_read(codec, WM8900_REG_POWER1);
reg = (reg >> 12) & 0xf;
- dev_info(&i2c_client->dev, "WM8900 revision %d\n", reg);
+ dev_info(&i2c->dev, "WM8900 revision %d\n", reg);
wm8900_reset(codec);
+ /* Turn the chip on */
+ wm8900_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
/* Latch the volume update bits */
wm8900_write(codec, WM8900_REG_LINVOL,
wm8900_read(codec, WM8900_REG_LINVOL) | 0x100);
@@ -1352,160 +1362,98 @@ static int wm8900_init(struct snd_soc_device *socdev)
/* Set the DAC and mixer output bias */
wm8900_write(codec, WM8900_REG_OUTBIASCTL, 0x81);
- /* Register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- dev_err(&i2c_client->dev, "Failed to register new PCMs\n");
- goto pcm_err;
- }
-
- /* Turn the chip on */
- codec->bias_level = SND_SOC_BIAS_OFF;
- wm8900_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
- wm8900_add_controls(codec);
- wm8900_add_widgets(codec);
-
- ret = snd_soc_register_card(socdev);
- if (ret < 0) {
- dev_err(&i2c_client->dev, "Failed to register card\n");
- goto card_err;
- }
- return ret;
-
-card_err:
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
-pcm_err:
- kfree(codec->reg_cache);
-priv_err:
- kfree(codec->private_data);
- return ret;
-}
+ wm8900_dai.dev = &i2c->dev;
-static struct snd_soc_device *wm8900_socdev;
+ wm8900_codec = codec;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-
-static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END };
-
-/* Magic definition of all other variables and things */
-I2C_CLIENT_INSMOD;
-
-static struct i2c_driver wm8900_i2c_driver;
-static struct i2c_client client_template;
-
-/* If the i2c layer weren't so broken, we could pass this kind of data
- around */
-static int wm8900_codec_probe(struct i2c_adapter *adap, int addr, int kind)
-{
- struct snd_soc_device *socdev = wm8900_socdev;
- struct wm8900_setup_data *setup = socdev->codec_data;
- struct snd_soc_codec *codec = socdev->codec;
- struct i2c_client *i2c;
- int ret;
-
- if (addr != setup->i2c_address)
- return -ENODEV;
-
- dev_err(&adap->dev, "Probe on %x\n", addr);
-
- client_template.adapter = adap;
- client_template.addr = addr;
-
- i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
- if (i2c == NULL) {
- kfree(codec);
- return -ENOMEM;
- }
- i2c_set_clientdata(i2c, codec);
- codec->control_data = i2c;
-
- ret = i2c_attach_client(i2c);
- if (ret < 0) {
- dev_err(&adap->dev,
- "failed to attach codec at addr %x\n", addr);
+ ret = snd_soc_register_codec(codec);
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to register codec: %d\n", ret);
goto err;
}
- ret = wm8900_init(socdev);
- if (ret < 0) {
- dev_err(&adap->dev, "failed to initialise WM8900\n");
- goto err;
+ ret = snd_soc_register_dai(&wm8900_dai);
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to register DAI: %d\n", ret);
+ goto err_codec;
}
+
return ret;
+err_codec:
+ snd_soc_unregister_codec(codec);
err:
- kfree(codec);
- kfree(i2c);
+ kfree(wm8900);
+ wm8900_codec = NULL;
return ret;
}
-static int wm8900_i2c_detach(struct i2c_client *client)
+static int wm8900_i2c_remove(struct i2c_client *client)
{
- struct snd_soc_codec *codec = i2c_get_clientdata(client);
- i2c_detach_client(client);
- kfree(codec->reg_cache);
- kfree(client);
+ snd_soc_unregister_dai(&wm8900_dai);
+ snd_soc_unregister_codec(wm8900_codec);
+
+ wm8900_set_bias_level(wm8900_codec, SND_SOC_BIAS_OFF);
+
+ wm8900_dai.dev = NULL;
+ kfree(wm8900_codec->private_data);
+ wm8900_codec = NULL;
+
return 0;
}
-static int wm8900_i2c_attach(struct i2c_adapter *adap)
-{
- return i2c_probe(adap, &addr_data, wm8900_codec_probe);
-}
+static const struct i2c_device_id wm8900_i2c_id[] = {
+ { "wm8900", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, wm8900_i2c_id);
-/* corgi i2c codec control layer */
static struct i2c_driver wm8900_i2c_driver = {
.driver = {
- .name = "WM8900 I2C codec",
+ .name = "WM8900",
.owner = THIS_MODULE,
},
- .attach_adapter = wm8900_i2c_attach,
- .detach_client = wm8900_i2c_detach,
- .command = NULL,
-};
-
-static struct i2c_client client_template = {
- .name = "WM8900",
- .driver = &wm8900_i2c_driver,
+ .probe = wm8900_i2c_probe,
+ .remove = wm8900_i2c_remove,
+ .id_table = wm8900_i2c_id,
};
-#endif
static int wm8900_probe(struct platform_device *pdev)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct wm8900_setup_data *setup;
struct snd_soc_codec *codec;
int ret = 0;
- dev_info(&pdev->dev, "WM8900 Audio Codec\n");
-
- setup = socdev->codec_data;
- codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
- if (codec == NULL)
- return -ENOMEM;
-
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
+ if (!wm8900_codec) {
+ dev_err(&pdev->dev, "I2C client not yet instantiated\n");
+ return -ENODEV;
+ }
+ codec = wm8900_codec;
socdev->codec = codec;
- codec->set_bias_level = wm8900_set_bias_level;
+ /* Register pcms */
+ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to register new PCMs\n");
+ goto pcm_err;
+ }
- wm8900_socdev = socdev;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
- if (setup->i2c_address) {
- normal_i2c[0] = setup->i2c_address;
- codec->hw_write = (hw_write_t)i2c_master_send;
- ret = i2c_add_driver(&wm8900_i2c_driver);
- if (ret != 0)
- printk(KERN_ERR "can't add i2c driver");
+ wm8900_add_controls(codec);
+ wm8900_add_widgets(codec);
+
+ ret = snd_soc_init_card(socdev);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to register card\n");
+ goto card_err;
}
-#else
-#error Non-I2C interfaces not yet supported
-#endif
+
+ return ret;
+
+card_err:
+ snd_soc_free_pcms(socdev);
+ snd_soc_dapm_free(socdev);
+pcm_err:
return ret;
}
@@ -1513,17 +1461,9 @@ static int wm8900_probe(struct platform_device *pdev)
static int wm8900_remove(struct platform_device *pdev)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->codec;
-
- if (codec->control_data)
- wm8900_set_bias_level(codec, SND_SOC_BIAS_OFF);
snd_soc_free_pcms(socdev);
snd_soc_dapm_free(socdev);
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
- i2c_del_driver(&wm8900_i2c_driver);
-#endif
- kfree(codec);
return 0;
}
@@ -1536,6 +1476,18 @@ struct snd_soc_codec_device soc_codec_dev_wm8900 = {
};
EXPORT_SYMBOL_GPL(soc_codec_dev_wm8900);
+static int __init wm8900_modinit(void)
+{
+ return i2c_add_driver(&wm8900_i2c_driver);
+}
+module_init(wm8900_modinit);
+
+static void __exit wm8900_exit(void)
+{
+ i2c_del_driver(&wm8900_i2c_driver);
+}
+module_exit(wm8900_exit);
+
MODULE_DESCRIPTION("ASoC WM8900 driver");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfonmicro.com>");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8900.h b/sound/soc/codecs/wm8900.h
index ba450d99e90..fd15007d10c 100644
--- a/sound/soc/codecs/wm8900.h
+++ b/sound/soc/codecs/wm8900.h
@@ -52,12 +52,6 @@
#define WM8900_DAC_CLKDIV_5_5 0x14
#define WM8900_DAC_CLKDIV_6 0x18
-#define WM8900_
-
-struct wm8900_setup_data {
- unsigned short i2c_address;
-};
-
extern struct snd_soc_dai wm8900_dai;
extern struct snd_soc_codec_device soc_codec_dev_wm8900;
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
index ce40d787760..bde74546db4 100644
--- a/sound/soc/codecs/wm8903.c
+++ b/sound/soc/codecs/wm8903.c
@@ -33,19 +33,6 @@
#include "wm8903.h"
-struct wm8903_priv {
- int sysclk;
-
- /* Reference counts */
- int charge_pump_users;
- int class_w_users;
- int playback_active;
- int capture_active;
-
- struct snd_pcm_substream *master_substream;
- struct snd_pcm_substream *slave_substream;
-};
-
/* Register defaults at reset */
static u16 wm8903_reg_defaults[] = {
0x8903, /* R0 - SW Reset and ID */
@@ -223,6 +210,23 @@ static u16 wm8903_reg_defaults[] = {
0x0000, /* R172 - Analogue Output Bias 0 */
};
+struct wm8903_priv {
+ struct snd_soc_codec codec;
+ u16 reg_cache[ARRAY_SIZE(wm8903_reg_defaults)];
+
+ int sysclk;
+
+ /* Reference counts */
+ int charge_pump_users;
+ int class_w_users;
+ int playback_active;
+ int capture_active;
+
+ struct snd_pcm_substream *master_substream;
+ struct snd_pcm_substream *slave_substream;
+};
+
+
static unsigned int wm8903_read_reg_cache(struct snd_soc_codec *codec,
unsigned int reg)
{
@@ -360,6 +364,8 @@ static void wm8903_sync_reg_cache(struct snd_soc_codec *codec, u16 *cache)
static void wm8903_reset(struct snd_soc_codec *codec)
{
wm8903_write(codec, WM8903_SW_RESET_AND_ID, 0);
+ memcpy(codec->reg_cache, wm8903_reg_defaults,
+ sizeof(wm8903_reg_defaults));
}
#define WM8903_OUTPUT_SHORT 0x8
@@ -392,6 +398,7 @@ static int wm8903_output_event(struct snd_soc_dapm_widget *w,
break;
default:
BUG();
+ return -EINVAL; /* Spurious warning from some compilers */
}
switch (w->shift) {
@@ -403,6 +410,7 @@ static int wm8903_output_event(struct snd_soc_dapm_widget *w,
break;
default:
BUG();
+ return -EINVAL; /* Spurious warning from some compilers */
}
if (event & SND_SOC_DAPM_PRE_PMU) {
@@ -773,14 +781,14 @@ static const struct snd_kcontrol_new left_output_mixer[] = {
SOC_DAPM_SINGLE("DACL Switch", WM8903_ANALOGUE_LEFT_MIX_0, 3, 1, 0),
SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_LEFT_MIX_0, 2, 1, 0),
SOC_DAPM_SINGLE_W("Left Bypass Switch", WM8903_ANALOGUE_LEFT_MIX_0, 1, 1, 0),
-SOC_DAPM_SINGLE_W("Right Bypass Switch", WM8903_ANALOGUE_LEFT_MIX_0, 1, 1, 0),
+SOC_DAPM_SINGLE_W("Right Bypass Switch", WM8903_ANALOGUE_LEFT_MIX_0, 0, 1, 0),
};
static const struct snd_kcontrol_new right_output_mixer[] = {
SOC_DAPM_SINGLE("DACL Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 3, 1, 0),
SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 2, 1, 0),
SOC_DAPM_SINGLE_W("Left Bypass Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 1, 1, 0),
-SOC_DAPM_SINGLE_W("Right Bypass Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 1, 1, 0),
+SOC_DAPM_SINGLE_W("Right Bypass Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 0, 1, 0),
};
static const struct snd_kcontrol_new left_speaker_mixer[] = {
@@ -788,7 +796,7 @@ SOC_DAPM_SINGLE("DACL Switch", WM8903_ANALOGUE_SPK_MIX_LEFT_0, 3, 1, 0),
SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_SPK_MIX_LEFT_0, 2, 1, 0),
SOC_DAPM_SINGLE("Left Bypass Switch", WM8903_ANALOGUE_SPK_MIX_LEFT_0, 1, 1, 0),
SOC_DAPM_SINGLE("Right Bypass Switch", WM8903_ANALOGUE_SPK_MIX_LEFT_0,
- 1, 1, 0),
+ 0, 1, 0),
};
static const struct snd_kcontrol_new right_speaker_mixer[] = {
@@ -797,7 +805,7 @@ SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_SPK_MIX_RIGHT_0, 2, 1, 0),
SOC_DAPM_SINGLE("Left Bypass Switch", WM8903_ANALOGUE_SPK_MIX_RIGHT_0,
1, 1, 0),
SOC_DAPM_SINGLE("Right Bypass Switch", WM8903_ANALOGUE_SPK_MIX_RIGHT_0,
- 1, 1, 0),
+ 0, 1, 0),
};
static const struct snd_soc_dapm_widget wm8903_dapm_widgets[] = {
@@ -989,6 +997,9 @@ static int wm8903_set_bias_level(struct snd_soc_codec *codec,
case SND_SOC_BIAS_STANDBY:
if (codec->bias_level == SND_SOC_BIAS_OFF) {
+ wm8903_write(codec, WM8903_CLOCK_RATES_2,
+ WM8903_CLK_SYS_ENA);
+
wm8903_run_sequence(codec, 0);
wm8903_sync_reg_cache(codec, codec->reg_cache);
@@ -1019,6 +1030,9 @@ static int wm8903_set_bias_level(struct snd_soc_codec *codec,
case SND_SOC_BIAS_OFF:
wm8903_run_sequence(codec, 32);
+ reg = wm8903_read(codec, WM8903_CLOCK_RATES_2);
+ reg &= ~WM8903_CLK_SYS_ENA;
+ wm8903_write(codec, WM8903_CLOCK_RATES_2, reg);
break;
}
@@ -1257,7 +1271,8 @@ static struct {
{ 0, 0 },
};
-static int wm8903_startup(struct snd_pcm_substream *substream)
+static int wm8903_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
@@ -1298,7 +1313,8 @@ static int wm8903_startup(struct snd_pcm_substream *substream)
return 0;
}
-static void wm8903_shutdown(struct snd_pcm_substream *substream)
+static void wm8903_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
@@ -1317,7 +1333,8 @@ static void wm8903_shutdown(struct snd_pcm_substream *substream)
}
static int wm8903_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
@@ -1515,8 +1532,6 @@ struct snd_soc_dai wm8903_dai = {
.startup = wm8903_startup,
.shutdown = wm8903_shutdown,
.hw_params = wm8903_hw_params,
- },
- .dai_ops = {
.digital_mute = wm8903_digital_mute,
.set_fmt = wm8903_set_dai_fmt,
.set_sysclk = wm8903_set_dai_sysclk
@@ -1560,39 +1575,48 @@ static int wm8903_resume(struct platform_device *pdev)
return 0;
}
-/*
- * initialise the WM8903 driver
- * register the mixer and dsp interfaces with the kernel
- */
-static int wm8903_init(struct snd_soc_device *socdev)
+static struct snd_soc_codec *wm8903_codec;
+
+static int wm8903_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
- struct snd_soc_codec *codec = socdev->codec;
- struct i2c_client *i2c = codec->control_data;
- int ret = 0;
+ struct wm8903_priv *wm8903;
+ struct snd_soc_codec *codec;
+ int ret;
u16 val;
- val = wm8903_hw_read(codec, WM8903_SW_RESET_AND_ID);
- if (val != wm8903_reg_defaults[WM8903_SW_RESET_AND_ID]) {
- dev_err(&i2c->dev,
- "Device with ID register %x is not a WM8903\n", val);
- return -ENODEV;
- }
+ wm8903 = kzalloc(sizeof(struct wm8903_priv), GFP_KERNEL);
+ if (wm8903 == NULL)
+ return -ENOMEM;
+
+ codec = &wm8903->codec;
+ mutex_init(&codec->mutex);
+ INIT_LIST_HEAD(&codec->dapm_widgets);
+ INIT_LIST_HEAD(&codec->dapm_paths);
+
+ codec->dev = &i2c->dev;
codec->name = "WM8903";
codec->owner = THIS_MODULE;
codec->read = wm8903_read;
codec->write = wm8903_write;
+ codec->hw_write = (hw_write_t)i2c_master_send;
codec->bias_level = SND_SOC_BIAS_OFF;
codec->set_bias_level = wm8903_set_bias_level;
codec->dai = &wm8903_dai;
codec->num_dai = 1;
- codec->reg_cache_size = ARRAY_SIZE(wm8903_reg_defaults);
- codec->reg_cache = kmemdup(wm8903_reg_defaults,
- sizeof(wm8903_reg_defaults),
- GFP_KERNEL);
- if (codec->reg_cache == NULL) {
- dev_err(&i2c->dev, "Failed to allocate register cache\n");
- return -ENOMEM;
+ codec->reg_cache_size = ARRAY_SIZE(wm8903->reg_cache);
+ codec->reg_cache = &wm8903->reg_cache[0];
+ codec->private_data = wm8903;
+
+ i2c_set_clientdata(i2c, codec);
+ codec->control_data = i2c;
+
+ val = wm8903_hw_read(codec, WM8903_SW_RESET_AND_ID);
+ if (val != wm8903_reg_defaults[WM8903_SW_RESET_AND_ID]) {
+ dev_err(&i2c->dev,
+ "Device with ID register %x is not a WM8903\n", val);
+ return -ENODEV;
}
val = wm8903_read(codec, WM8903_REVISION_NUMBER);
@@ -1601,16 +1625,6 @@ static int wm8903_init(struct snd_soc_device *socdev)
wm8903_reset(codec);
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- dev_err(&i2c->dev, "failed to create pcms\n");
- goto pcm_err;
- }
-
- /* SYSCLK is required for pretty much anything */
- wm8903_write(codec, WM8903_CLOCK_RATES_2, WM8903_CLK_SYS_ENA);
-
/* power on device */
wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -1645,47 +1659,45 @@ static int wm8903_init(struct snd_soc_device *socdev)
val |= WM8903_DAC_MUTEMODE;
wm8903_write(codec, WM8903_DAC_DIGITAL_1, val);
- wm8903_add_controls(codec);
- wm8903_add_widgets(codec);
- ret = snd_soc_register_card(socdev);
- if (ret < 0) {
- dev_err(&i2c->dev, "wm8903: failed to register card\n");
- goto card_err;
+ wm8903_dai.dev = &i2c->dev;
+ wm8903_codec = codec;
+
+ ret = snd_soc_register_codec(codec);
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to register codec: %d\n", ret);
+ goto err;
+ }
+
+ ret = snd_soc_register_dai(&wm8903_dai);
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to register DAI: %d\n", ret);
+ goto err_codec;
}
return ret;
-card_err:
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
-pcm_err:
- kfree(codec->reg_cache);
+err_codec:
+ snd_soc_unregister_codec(codec);
+err:
+ wm8903_codec = NULL;
+ kfree(wm8903);
return ret;
}
-static struct snd_soc_device *wm8903_socdev;
-
-static int wm8903_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8903_i2c_remove(struct i2c_client *client)
{
- struct snd_soc_device *socdev = wm8903_socdev;
- struct snd_soc_codec *codec = socdev->codec;
- int ret;
+ struct snd_soc_codec *codec = i2c_get_clientdata(client);
- i2c_set_clientdata(i2c, codec);
- codec->control_data = i2c;
+ snd_soc_unregister_dai(&wm8903_dai);
+ snd_soc_unregister_codec(codec);
- ret = wm8903_init(socdev);
- if (ret < 0)
- dev_err(&i2c->dev, "Device initialisation failed\n");
+ wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF);
- return ret;
-}
+ kfree(codec->private_data);
+
+ wm8903_codec = NULL;
+ wm8903_dai.dev = NULL;
-static int wm8903_i2c_remove(struct i2c_client *client)
-{
- struct snd_soc_codec *codec = i2c_get_clientdata(client);
- kfree(codec->reg_cache);
return 0;
}
@@ -1709,75 +1721,37 @@ static struct i2c_driver wm8903_i2c_driver = {
static int wm8903_probe(struct platform_device *pdev)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct wm8903_setup_data *setup;
- struct snd_soc_codec *codec;
- struct wm8903_priv *wm8903;
- struct i2c_board_info board_info;
- struct i2c_adapter *adapter;
- struct i2c_client *i2c_client;
int ret = 0;
- setup = socdev->codec_data;
-
- if (!setup->i2c_address) {
- dev_err(&pdev->dev, "No codec address provided\n");
- return -ENODEV;
+ if (!wm8903_codec) {
+ dev_err(&pdev->dev, "I2C device not yet probed\n");
+ goto err;
}
- codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
- if (codec == NULL)
- return -ENOMEM;
+ socdev->codec = wm8903_codec;
- wm8903 = kzalloc(sizeof(struct wm8903_priv), GFP_KERNEL);
- if (wm8903 == NULL) {
- ret = -ENOMEM;
- goto err_codec;
+ /* register pcms */
+ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to create pcms\n");
+ goto err;
}
- codec->private_data = wm8903;
- socdev->codec = codec;
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- wm8903_socdev = socdev;
+ wm8903_add_controls(socdev->codec);
+ wm8903_add_widgets(socdev->codec);
- codec->hw_write = (hw_write_t)i2c_master_send;
- ret = i2c_add_driver(&wm8903_i2c_driver);
- if (ret != 0) {
- dev_err(&pdev->dev, "can't add i2c driver\n");
- goto err_priv;
- } else {
- memset(&board_info, 0, sizeof(board_info));
- strlcpy(board_info.type, "wm8903", I2C_NAME_SIZE);
- board_info.addr = setup->i2c_address;
-
- adapter = i2c_get_adapter(setup->i2c_bus);
- if (!adapter) {
- dev_err(&pdev->dev, "Can't get I2C bus %d\n",
- setup->i2c_bus);
- ret = -ENODEV;
- goto err_adapter;
- }
-
- i2c_client = i2c_new_device(adapter, &board_info);
- i2c_put_adapter(adapter);
- if (i2c_client == NULL) {
- dev_err(&pdev->dev,
- "I2C driver registration failed\n");
- ret = -ENODEV;
- goto err_adapter;
- }
+ ret = snd_soc_init_card(socdev);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "wm8903: failed to register card\n");
+ goto card_err;
}
return ret;
-err_adapter:
- i2c_del_driver(&wm8903_i2c_driver);
-err_priv:
- kfree(codec->private_data);
-err_codec:
- kfree(codec);
+card_err:
+ snd_soc_free_pcms(socdev);
+ snd_soc_dapm_free(socdev);
+err:
return ret;
}
@@ -1792,10 +1766,6 @@ static int wm8903_remove(struct platform_device *pdev)
snd_soc_free_pcms(socdev);
snd_soc_dapm_free(socdev);
- i2c_unregister_device(socdev->codec->control_data);
- i2c_del_driver(&wm8903_i2c_driver);
- kfree(codec->private_data);
- kfree(codec);
return 0;
}
@@ -1808,6 +1778,18 @@ struct snd_soc_codec_device soc_codec_dev_wm8903 = {
};
EXPORT_SYMBOL_GPL(soc_codec_dev_wm8903);
+static int __init wm8903_modinit(void)
+{
+ return i2c_add_driver(&wm8903_i2c_driver);
+}
+module_init(wm8903_modinit);
+
+static void __exit wm8903_exit(void)
+{
+ i2c_del_driver(&wm8903_i2c_driver);
+}
+module_exit(wm8903_exit);
+
MODULE_DESCRIPTION("ASoC WM8903 driver");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.cm>");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8903.h b/sound/soc/codecs/wm8903.h
index cec622f2f66..0ea27e2b996 100644
--- a/sound/soc/codecs/wm8903.h
+++ b/sound/soc/codecs/wm8903.h
@@ -18,11 +18,6 @@
extern struct snd_soc_dai wm8903_dai;
extern struct snd_soc_codec_device soc_codec_dev_wm8903;
-struct wm8903_setup_data {
- int i2c_bus;
- int i2c_address;
-};
-
#define WM8903_MCLK_DIV_2 1
#define WM8903_CLK_SYS 2
#define WM8903_BCLK 3
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c
index f41a578ddd4..88ead7f8dd9 100644
--- a/sound/soc/codecs/wm8971.c
+++ b/sound/soc/codecs/wm8971.c
@@ -541,7 +541,8 @@ static int wm8971_set_dai_fmt(struct snd_soc_dai *codec_dai,
}
static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
@@ -634,8 +635,6 @@ struct snd_soc_dai wm8971_dai = {
.formats = WM8971_FORMATS,},
.ops = {
.hw_params = wm8971_pcm_hw_params,
- },
- .dai_ops = {
.digital_mute = wm8971_mute,
.set_fmt = wm8971_set_dai_fmt,
.set_sysclk = wm8971_set_dai_sysclk,
@@ -748,7 +747,7 @@ static int wm8971_init(struct snd_soc_device *socdev)
wm8971_add_controls(codec);
wm8971_add_widgets(codec);
- ret = snd_soc_register_card(socdev);
+ ret = snd_soc_init_card(socdev);
if (ret < 0) {
printk(KERN_ERR "wm8971: failed to register card\n");
goto card_err;
@@ -936,6 +935,18 @@ struct snd_soc_codec_device soc_codec_dev_wm8971 = {
EXPORT_SYMBOL_GPL(soc_codec_dev_wm8971);
+static int __init wm8971_modinit(void)
+{
+ return snd_soc_register_dai(&wm8971_dai);
+}
+module_init(wm8971_modinit);
+
+static void __exit wm8971_exit(void)
+{
+ snd_soc_unregister_dai(&wm8971_dai);
+}
+module_exit(wm8971_exit);
+
MODULE_DESCRIPTION("ASoC WM8971 driver");
MODULE_AUTHOR("Lab126");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c
index 572d22b0880..5b5afc14447 100644
--- a/sound/soc/codecs/wm8990.c
+++ b/sound/soc/codecs/wm8990.c
@@ -106,6 +106,7 @@ static const u16 wm8990_reg[] = {
0x0008, /* R60 - PLL1 */
0x0031, /* R61 - PLL2 */
0x0026, /* R62 - PLL3 */
+ 0x0000, /* R63 - Driver internal */
};
/*
@@ -126,10 +127,9 @@ static inline void wm8990_write_reg_cache(struct snd_soc_codec *codec,
unsigned int reg, unsigned int value)
{
u16 *cache = codec->reg_cache;
- BUG_ON(reg > (ARRAY_SIZE(wm8990_reg)) - 1);
- /* Reset register is uncached */
- if (reg == 0)
+ /* Reset register and reserved registers are uncached */
+ if (reg == 0 || reg > ARRAY_SIZE(wm8990_reg) - 1)
return;
cache[reg] = value;
@@ -1172,7 +1172,8 @@ static int wm8990_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
* Set PCM DAI bit size and sample rate.
*/
static int wm8990_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
@@ -1222,8 +1223,14 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec,
switch (level) {
case SND_SOC_BIAS_ON:
break;
+
case SND_SOC_BIAS_PREPARE:
+ /* VMID=2*50k */
+ val = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_1) &
+ ~WM8990_VMID_MODE_MASK;
+ wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, val | 0x2);
break;
+
case SND_SOC_BIAS_STANDBY:
if (codec->bias_level == SND_SOC_BIAS_OFF) {
/* Enable all output discharge bits */
@@ -1272,10 +1279,17 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec,
/* disable POBCTRL, SOFT_ST and BUFDCOPEN */
wm8990_write(codec, WM8990_ANTIPOP2, WM8990_BUFIOEN);
- } else {
- /* ON -> standby */
+ /* Enable workaround for ADC clocking issue. */
+ wm8990_write(codec, WM8990_EXT_ACCESS_ENA, 0x2);
+ wm8990_write(codec, WM8990_EXT_CTL1, 0xa003);
+ wm8990_write(codec, WM8990_EXT_ACCESS_ENA, 0);
}
+
+ /* VMID=2*250k */
+ val = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_1) &
+ ~WM8990_VMID_MODE_MASK;
+ wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, val | 0x4);
break;
case SND_SOC_BIAS_OFF:
@@ -1349,8 +1363,7 @@ struct snd_soc_dai wm8990_dai = {
.rates = WM8990_RATES,
.formats = WM8990_FORMATS,},
.ops = {
- .hw_params = wm8990_hw_params,},
- .dai_ops = {
+ .hw_params = wm8990_hw_params,
.digital_mute = wm8990_mute,
.set_fmt = wm8990_set_dai_fmt,
.set_clkdiv = wm8990_set_dai_clkdiv,
@@ -1449,7 +1462,7 @@ static int wm8990_init(struct snd_soc_device *socdev)
wm8990_add_controls(codec);
wm8990_add_widgets(codec);
- ret = snd_soc_register_card(socdev);
+ ret = snd_soc_init_card(socdev);
if (ret < 0) {
printk(KERN_ERR "wm8990: failed to register card\n");
goto card_err;
@@ -1630,6 +1643,18 @@ struct snd_soc_codec_device soc_codec_dev_wm8990 = {
};
EXPORT_SYMBOL_GPL(soc_codec_dev_wm8990);
+static int __init wm8990_modinit(void)
+{
+ return snd_soc_register_dai(&wm8990_dai);
+}
+module_init(wm8990_modinit);
+
+static void __exit wm8990_exit(void)
+{
+ snd_soc_unregister_dai(&wm8990_dai);
+}
+module_exit(wm8990_exit);
+
MODULE_DESCRIPTION("ASoC WM8990 driver");
MODULE_AUTHOR("Liam Girdwood");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8990.h b/sound/soc/codecs/wm8990.h
index 0e192f3b078..7114ddc88b4 100644
--- a/sound/soc/codecs/wm8990.h
+++ b/sound/soc/codecs/wm8990.h
@@ -80,8 +80,8 @@
#define WM8990_PLL3 0x3E
#define WM8990_INTDRIVBITS 0x3F
-#define WM8990_REGISTER_COUNT 60
-#define WM8990_MAX_REGISTER 0x3F
+#define WM8990_EXT_ACCESS_ENA 0x75
+#define WM8990_EXT_CTL1 0x7a
/*
* Field Definitions.
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c
index ffb471e420e..af83d629078 100644
--- a/sound/soc/codecs/wm9712.c
+++ b/sound/soc/codecs/wm9712.c
@@ -487,7 +487,8 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
return 0;
}
-static int ac97_prepare(struct snd_pcm_substream *substream)
+static int ac97_prepare(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
@@ -507,7 +508,8 @@ static int ac97_prepare(struct snd_pcm_substream *substream)
return ac97_write(codec, reg, runtime->rate);
}
-static int ac97_aux_prepare(struct snd_pcm_substream *substream)
+static int ac97_aux_prepare(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
@@ -533,7 +535,7 @@ static int ac97_aux_prepare(struct snd_pcm_substream *substream)
struct snd_soc_dai wm9712_dai[] = {
{
.name = "AC97 HiFi",
- .type = SND_SOC_DAI_AC97_BUS,
+ .ac97_control = 1,
.playback = {
.stream_name = "HiFi Playback",
.channels_min = 1,
@@ -688,7 +690,7 @@ static int wm9712_soc_probe(struct platform_device *pdev)
ret = wm9712_reset(codec, 0);
if (ret < 0) {
- printk(KERN_ERR "AC97 link error\n");
+ printk(KERN_ERR "Failed to reset WM9712: AC97 link error\n");
goto reset_err;
}
@@ -698,7 +700,7 @@ static int wm9712_soc_probe(struct platform_device *pdev)
wm9712_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
wm9712_add_controls(codec);
wm9712_add_widgets(codec);
- ret = snd_soc_register_card(socdev);
+ ret = snd_soc_init_card(socdev);
if (ret < 0) {
printk(KERN_ERR "wm9712: failed to register card\n");
goto reset_err;
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
index 945b32ed988..f3ca8aaf013 100644
--- a/sound/soc/codecs/wm9713.c
+++ b/sound/soc/codecs/wm9713.c
@@ -928,11 +928,10 @@ static int wm9713_set_dai_fmt(struct snd_soc_dai *codec_dai,
}
static int wm9713_pcm_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->codec;
+ struct snd_soc_codec *codec = dai->codec;
u16 reg = ac97_read(codec, AC97_CENTER_LFE_MASTER) & 0xfff3;
switch (params_format(params)) {
@@ -954,11 +953,10 @@ static int wm9713_pcm_hw_params(struct snd_pcm_substream *substream,
return 0;
}
-static void wm9713_voiceshutdown(struct snd_pcm_substream *substream)
+static void wm9713_voiceshutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->codec;
+ struct snd_soc_codec *codec = dai->codec;
u16 status;
/* Gracefully shut down the voice interface. */
@@ -969,12 +967,11 @@ static void wm9713_voiceshutdown(struct snd_pcm_substream *substream)
ac97_write(codec, AC97_EXTENDED_MID, status);
}
-static int ac97_hifi_prepare(struct snd_pcm_substream *substream)
+static int ac97_hifi_prepare(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
+ struct snd_soc_codec *codec = dai->codec;
struct snd_pcm_runtime *runtime = substream->runtime;
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->codec;
int reg;
u16 vra;
@@ -989,12 +986,11 @@ static int ac97_hifi_prepare(struct snd_pcm_substream *substream)
return ac97_write(codec, reg, runtime->rate);
}
-static int ac97_aux_prepare(struct snd_pcm_substream *substream)
+static int ac97_aux_prepare(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
+ struct snd_soc_codec *codec = dai->codec;
struct snd_pcm_runtime *runtime = substream->runtime;
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->codec;
u16 vra, xsle;
vra = ac97_read(codec, AC97_EXTENDED_STATUS);
@@ -1028,7 +1024,7 @@ static int ac97_aux_prepare(struct snd_pcm_substream *substream)
struct snd_soc_dai wm9713_dai[] = {
{
.name = "AC97 HiFi",
- .type = SND_SOC_DAI_AC97_BUS,
+ .ac97_control = 1,
.playback = {
.stream_name = "HiFi Playback",
.channels_min = 1,
@@ -1042,8 +1038,7 @@ struct snd_soc_dai wm9713_dai[] = {
.rates = WM9713_RATES,
.formats = SNDRV_PCM_FMTBIT_S16_LE,},
.ops = {
- .prepare = ac97_hifi_prepare,},
- .dai_ops = {
+ .prepare = ac97_hifi_prepare,
.set_clkdiv = wm9713_set_dai_clkdiv,
.set_pll = wm9713_set_dai_pll,},
},
@@ -1056,8 +1051,7 @@ struct snd_soc_dai wm9713_dai[] = {
.rates = WM9713_RATES,
.formats = SNDRV_PCM_FMTBIT_S16_LE,},
.ops = {
- .prepare = ac97_aux_prepare,},
- .dai_ops = {
+ .prepare = ac97_aux_prepare,
.set_clkdiv = wm9713_set_dai_clkdiv,
.set_pll = wm9713_set_dai_pll,},
},
@@ -1077,8 +1071,7 @@ struct snd_soc_dai wm9713_dai[] = {
.formats = WM9713_PCM_FORMATS,},
.ops = {
.hw_params = wm9713_pcm_hw_params,
- .shutdown = wm9713_voiceshutdown,},
- .dai_ops = {
+ .shutdown = wm9713_voiceshutdown,
.set_clkdiv = wm9713_set_dai_clkdiv,
.set_pll = wm9713_set_dai_pll,
.set_fmt = wm9713_set_dai_fmt,
@@ -1097,6 +1090,8 @@ int wm9713_reset(struct snd_soc_codec *codec, int try_warm)
}
soc_ac97_ops.reset(codec->ac97);
+ if (soc_ac97_ops.warm_reset)
+ soc_ac97_ops.warm_reset(codec->ac97);
if (ac97_read(codec, 0) != wm9713_reg[0])
return -EIO;
return 0;
@@ -1240,7 +1235,7 @@ static int wm9713_soc_probe(struct platform_device *pdev)
wm9713_reset(codec, 0);
ret = wm9713_reset(codec, 1);
if (ret < 0) {
- printk(KERN_ERR "AC97 link error\n");
+ printk(KERN_ERR "Failed to reset WM9713: AC97 link error\n");
goto reset_err;
}
@@ -1252,7 +1247,7 @@ static int wm9713_soc_probe(struct platform_device *pdev)
wm9713_add_controls(codec);
wm9713_add_widgets(codec);
- ret = snd_soc_register_card(socdev);
+ ret = snd_soc_init_card(socdev);
if (ret < 0)
goto reset_err;
return 0;
@@ -1288,7 +1283,6 @@ static int wm9713_soc_remove(struct platform_device *pdev)
snd_soc_free_ac97_codec(codec);
kfree(codec->private_data);
kfree(codec->reg_cache);
- kfree(codec->dai);
kfree(codec);
return 0;
}
diff --git a/sound/soc/davinci/Kconfig b/sound/soc/davinci/Kconfig
index 8f7e3383490..b502741692d 100644
--- a/sound/soc/davinci/Kconfig
+++ b/sound/soc/davinci/Kconfig
@@ -17,3 +17,13 @@ config SND_DAVINCI_SOC_EVM
help
Say Y if you want to add support for SoC audio on TI
DaVinci EVM platform.
+
+config SND_DAVINCI_SOC_SFFSDR
+ tristate "SoC Audio support for SFFSDR"
+ depends on SND_DAVINCI_SOC && MACH_DAVINCI_SFFSDR
+ select SND_DAVINCI_SOC_I2S
+ select SND_SOC_PCM3008
+ select SFFSDR_FPGA
+ help
+ Say Y if you want to add support for SoC audio on
+ Lyrtech SFFSDR board.
diff --git a/sound/soc/davinci/Makefile b/sound/soc/davinci/Makefile
index ca772e5b463..ca8bae1fc3f 100644
--- a/sound/soc/davinci/Makefile
+++ b/sound/soc/davinci/Makefile
@@ -7,5 +7,7 @@ obj-$(CONFIG_SND_DAVINCI_SOC_I2S) += snd-soc-davinci-i2s.o
# DAVINCI Machine Support
snd-soc-evm-objs := davinci-evm.o
+snd-soc-sffsdr-objs := davinci-sffsdr.o
obj-$(CONFIG_SND_DAVINCI_SOC_EVM) += snd-soc-evm.o
+obj-$(CONFIG_SND_DAVINCI_SOC_SFFSDR) += snd-soc-sffsdr.o
diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c
index 9e6062cd6b5..01b948bb55a 100644
--- a/sound/soc/davinci/davinci-evm.c
+++ b/sound/soc/davinci/davinci-evm.c
@@ -28,6 +28,8 @@
#define EVM_CODEC_CLOCK 22579200
+#define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \
+ SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF)
static int evm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
@@ -37,14 +39,12 @@ static int evm_hw_params(struct snd_pcm_substream *substream,
int ret = 0;
/* set codec DAI configuration */
- ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_CBM_CFM);
+ ret = snd_soc_dai_set_fmt(codec_dai, AUDIO_FORMAT);
if (ret < 0)
return ret;
/* set cpu DAI configuration */
- ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBM_CFM |
- SND_SOC_DAIFMT_IB_NF);
+ ret = snd_soc_dai_set_fmt(cpu_dai, AUDIO_FORMAT);
if (ret < 0)
return ret;
@@ -128,8 +128,9 @@ static struct snd_soc_dai_link evm_dai = {
};
/* davinci-evm audio machine driver */
-static struct snd_soc_machine snd_soc_machine_evm = {
+static struct snd_soc_card snd_soc_card_evm = {
.name = "DaVinci EVM",
+ .platform = &davinci_soc_platform,
.dai_link = &evm_dai,
.num_links = 1,
};
@@ -142,8 +143,7 @@ static struct aic3x_setup_data evm_aic3x_setup = {
/* evm audio subsystem */
static struct snd_soc_device evm_snd_devdata = {
- .machine = &snd_soc_machine_evm,
- .platform = &davinci_soc_platform,
+ .card = &snd_soc_card_evm,
.codec_dev = &soc_codec_dev_aic3x,
.codec_data = &evm_aic3x_setup,
};
diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c
index abb5fedb0b1..0fee779e3c7 100644
--- a/sound/soc/davinci/davinci-i2s.c
+++ b/sound/soc/davinci/davinci-i2s.c
@@ -59,6 +59,7 @@
#define DAVINCI_MCBSP_PCR_CLKXP (1 << 1)
#define DAVINCI_MCBSP_PCR_FSRP (1 << 2)
#define DAVINCI_MCBSP_PCR_FSXP (1 << 3)
+#define DAVINCI_MCBSP_PCR_SCLKME (1 << 7)
#define DAVINCI_MCBSP_PCR_CLKRM (1 << 8)
#define DAVINCI_MCBSP_PCR_CLKXM (1 << 9)
#define DAVINCI_MCBSP_PCR_FSRM (1 << 10)
@@ -110,16 +111,59 @@ static void davinci_mcbsp_start(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data;
+ struct snd_soc_device *socdev = rtd->socdev;
+ struct snd_soc_platform *platform = socdev->card->platform;
u32 w;
+ int ret;
/* Start the sample generator and enable transmitter/receiver */
w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_GRST, 1);
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ /* Stop the DMA to avoid data loss */
+ /* while the transmitter is out of reset to handle XSYNCERR */
+ if (platform->pcm_ops->trigger) {
+ ret = platform->pcm_ops->trigger(substream,
+ SNDRV_PCM_TRIGGER_STOP);
+ if (ret < 0)
+ printk(KERN_DEBUG "Playback DMA stop failed\n");
+ }
+
+ /* Enable the transmitter */
+ w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 1);
- else
+ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
+
+ /* wait for any unexpected frame sync error to occur */
+ udelay(100);
+
+ /* Disable the transmitter to clear any outstanding XSYNCERR */
+ w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
+ MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 0);
+ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
+
+ /* Restart the DMA */
+ if (platform->pcm_ops->trigger) {
+ ret = platform->pcm_ops->trigger(substream,
+ SNDRV_PCM_TRIGGER_START);
+ if (ret < 0)
+ printk(KERN_DEBUG "Playback DMA start failed\n");
+ }
+ /* Enable the transmitter */
+ w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
+ MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 1);
+ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
+
+ } else {
+
+ /* Enable the reciever */
+ w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_RRST, 1);
- davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
+ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
+ }
+
/* Start frame sync */
w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
@@ -144,7 +188,8 @@ static void davinci_mcbsp_stop(struct snd_pcm_substream *substream)
davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
}
-static int davinci_i2s_startup(struct snd_pcm_substream *substream)
+static int davinci_i2s_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
@@ -155,61 +200,138 @@ static int davinci_i2s_startup(struct snd_pcm_substream *substream)
return 0;
}
+#define DEFAULT_BITPERSAMPLE 16
+
static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
unsigned int fmt)
{
struct davinci_mcbsp_dev *dev = cpu_dai->private_data;
- u32 w;
+ unsigned int pcr;
+ unsigned int srgr;
+ unsigned int rcr;
+ unsigned int xcr;
+ srgr = DAVINCI_MCBSP_SRGR_FSGM |
+ DAVINCI_MCBSP_SRGR_FPER(DEFAULT_BITPERSAMPLE * 2 - 1) |
+ DAVINCI_MCBSP_SRGR_FWID(DEFAULT_BITPERSAMPLE - 1);
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBS_CFS:
- davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG,
- DAVINCI_MCBSP_PCR_FSXM |
- DAVINCI_MCBSP_PCR_FSRM |
- DAVINCI_MCBSP_PCR_CLKXM |
- DAVINCI_MCBSP_PCR_CLKRM);
- davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG,
- DAVINCI_MCBSP_SRGR_FSGM);
+ /* cpu is master */
+ pcr = DAVINCI_MCBSP_PCR_FSXM |
+ DAVINCI_MCBSP_PCR_FSRM |
+ DAVINCI_MCBSP_PCR_CLKXM |
+ DAVINCI_MCBSP_PCR_CLKRM;
+ break;
+ case SND_SOC_DAIFMT_CBM_CFS:
+ /* McBSP CLKR pin is the input for the Sample Rate Generator.
+ * McBSP FSR and FSX are driven by the Sample Rate Generator. */
+ pcr = DAVINCI_MCBSP_PCR_SCLKME |
+ DAVINCI_MCBSP_PCR_FSXM |
+ DAVINCI_MCBSP_PCR_FSRM;
break;
case SND_SOC_DAIFMT_CBM_CFM:
- davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, 0);
+ /* codec is master */
+ pcr = 0;
break;
default:
+ printk(KERN_ERR "%s:bad master\n", __func__);
return -EINVAL;
}
- switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
- case SND_SOC_DAIFMT_IB_NF:
- w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_PCR_REG);
- MOD_REG_BIT(w, DAVINCI_MCBSP_PCR_CLKXP |
- DAVINCI_MCBSP_PCR_CLKRP, 1);
- davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, w);
+ rcr = DAVINCI_MCBSP_RCR_RFRLEN1(1);
+ xcr = DAVINCI_MCBSP_XCR_XFIG | DAVINCI_MCBSP_XCR_XFRLEN1(1);
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_DSP_B:
break;
- case SND_SOC_DAIFMT_NB_IF:
- w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_PCR_REG);
- MOD_REG_BIT(w, DAVINCI_MCBSP_PCR_FSXP |
- DAVINCI_MCBSP_PCR_FSRP, 1);
- davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, w);
+ case SND_SOC_DAIFMT_I2S:
+ /* Davinci doesn't support TRUE I2S, but some codecs will have
+ * the left and right channels contiguous. This allows
+ * dsp_a mode to be used with an inverted normal frame clk.
+ * If your codec is master and does not have contiguous
+ * channels, then you will have sound on only one channel.
+ * Try using a different mode, or codec as slave.
+ *
+ * The TLV320AIC33 is an example of a codec where this works.
+ * It has a variable bit clock frequency allowing it to have
+ * valid data on every bit clock.
+ *
+ * The TLV320AIC23 is an example of a codec where this does not
+ * work. It has a fixed bit clock frequency with progressively
+ * more empty bit clock slots between channels as the sample
+ * rate is lowered.
+ */
+ fmt ^= SND_SOC_DAIFMT_NB_IF;
+ case SND_SOC_DAIFMT_DSP_A:
+ rcr |= DAVINCI_MCBSP_RCR_RDATDLY(1);
+ xcr |= DAVINCI_MCBSP_XCR_XDATDLY(1);
+ break;
+ default:
+ printk(KERN_ERR "%s:bad format\n", __func__);
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ /* CLKRP Receive clock polarity,
+ * 1 - sampled on rising edge of CLKR
+ * valid on rising edge
+ * CLKXP Transmit clock polarity,
+ * 1 - clocked on falling edge of CLKX
+ * valid on rising edge
+ * FSRP Receive frame sync pol, 0 - active high
+ * FSXP Transmit frame sync pol, 0 - active high
+ */
+ pcr |= (DAVINCI_MCBSP_PCR_CLKXP | DAVINCI_MCBSP_PCR_CLKRP);
break;
case SND_SOC_DAIFMT_IB_IF:
- w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_PCR_REG);
- MOD_REG_BIT(w, DAVINCI_MCBSP_PCR_CLKXP |
- DAVINCI_MCBSP_PCR_CLKRP |
- DAVINCI_MCBSP_PCR_FSXP |
- DAVINCI_MCBSP_PCR_FSRP, 1);
- davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, w);
+ /* CLKRP Receive clock polarity,
+ * 0 - sampled on falling edge of CLKR
+ * valid on falling edge
+ * CLKXP Transmit clock polarity,
+ * 0 - clocked on rising edge of CLKX
+ * valid on falling edge
+ * FSRP Receive frame sync pol, 1 - active low
+ * FSXP Transmit frame sync pol, 1 - active low
+ */
+ pcr |= (DAVINCI_MCBSP_PCR_FSXP | DAVINCI_MCBSP_PCR_FSRP);
break;
- case SND_SOC_DAIFMT_NB_NF:
+ case SND_SOC_DAIFMT_NB_IF:
+ /* CLKRP Receive clock polarity,
+ * 1 - sampled on rising edge of CLKR
+ * valid on rising edge
+ * CLKXP Transmit clock polarity,
+ * 1 - clocked on falling edge of CLKX
+ * valid on rising edge
+ * FSRP Receive frame sync pol, 1 - active low
+ * FSXP Transmit frame sync pol, 1 - active low
+ */
+ pcr |= (DAVINCI_MCBSP_PCR_CLKXP | DAVINCI_MCBSP_PCR_CLKRP |
+ DAVINCI_MCBSP_PCR_FSXP | DAVINCI_MCBSP_PCR_FSRP);
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ /* CLKRP Receive clock polarity,
+ * 0 - sampled on falling edge of CLKR
+ * valid on falling edge
+ * CLKXP Transmit clock polarity,
+ * 0 - clocked on rising edge of CLKX
+ * valid on falling edge
+ * FSRP Receive frame sync pol, 0 - active high
+ * FSXP Transmit frame sync pol, 0 - active high
+ */
break;
default:
return -EINVAL;
}
-
+ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr);
+ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, pcr);
+ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, rcr);
+ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, xcr);
return 0;
}
static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct davinci_pcm_dma_params *dma_params = rtd->dai->cpu_dai->dma_data;
@@ -219,25 +341,20 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
u32 w;
/* general line settings */
- davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG,
- DAVINCI_MCBSP_SPCR_RINTM(3) |
- DAVINCI_MCBSP_SPCR_XINTM(3) |
- DAVINCI_MCBSP_SPCR_FREE);
- davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG,
- DAVINCI_MCBSP_RCR_RFRLEN1(1) |
- DAVINCI_MCBSP_RCR_RDATDLY(1));
- davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG,
- DAVINCI_MCBSP_XCR_XFRLEN1(1) |
- DAVINCI_MCBSP_XCR_XDATDLY(1) |
- DAVINCI_MCBSP_XCR_XFIG);
+ w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+ w |= DAVINCI_MCBSP_SPCR_RINTM(3) | DAVINCI_MCBSP_SPCR_FREE;
+ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
+ } else {
+ w |= DAVINCI_MCBSP_SPCR_XINTM(3) | DAVINCI_MCBSP_SPCR_FREE;
+ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
+ }
i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS);
- w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SRGR_REG);
+ w = DAVINCI_MCBSP_SRGR_FSGM;
MOD_REG_BIT(w, DAVINCI_MCBSP_SRGR_FWID(snd_interval_value(i) - 1), 1);
- davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, w);
i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_FRAME_BITS);
- w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SRGR_REG);
MOD_REG_BIT(w, DAVINCI_MCBSP_SRGR_FPER(snd_interval_value(i) - 1), 1);
davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, w);
@@ -260,20 +377,24 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
- w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_RCR_REG);
- MOD_REG_BIT(w, DAVINCI_MCBSP_RCR_RWDLEN1(mcbsp_word_length) |
- DAVINCI_MCBSP_RCR_RWDLEN2(mcbsp_word_length), 1);
- davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, w);
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+ w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_RCR_REG);
+ MOD_REG_BIT(w, DAVINCI_MCBSP_RCR_RWDLEN1(mcbsp_word_length) |
+ DAVINCI_MCBSP_RCR_RWDLEN2(mcbsp_word_length), 1);
+ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, w);
- w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_XCR_REG);
- MOD_REG_BIT(w, DAVINCI_MCBSP_XCR_XWDLEN1(mcbsp_word_length) |
- DAVINCI_MCBSP_XCR_XWDLEN2(mcbsp_word_length), 1);
- davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, w);
+ } else {
+ w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_XCR_REG);
+ MOD_REG_BIT(w, DAVINCI_MCBSP_XCR_XWDLEN1(mcbsp_word_length) |
+ DAVINCI_MCBSP_XCR_XWDLEN2(mcbsp_word_length), 1);
+ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, w);
+ }
return 0;
}
-static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd)
+static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
{
int ret = 0;
@@ -299,8 +420,8 @@ static int davinci_i2s_probe(struct platform_device *pdev,
struct snd_soc_dai *dai)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_machine *machine = socdev->machine;
- struct snd_soc_dai *cpu_dai = machine->dai_link[pdev->id].cpu_dai;
+ struct snd_soc_card *card = socdev->card;
+ struct snd_soc_dai *cpu_dai = card->dai_link[pdev->id].cpu_dai;
struct davinci_mcbsp_dev *dev;
struct resource *mem, *ioarea;
struct evm_snd_platform_data *pdata;
@@ -361,8 +482,8 @@ static void davinci_i2s_remove(struct platform_device *pdev,
struct snd_soc_dai *dai)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_machine *machine = socdev->machine;
- struct snd_soc_dai *cpu_dai = machine->dai_link[pdev->id].cpu_dai;
+ struct snd_soc_card *card = socdev->card;
+ struct snd_soc_dai *cpu_dai = card->dai_link[pdev->id].cpu_dai;
struct davinci_mcbsp_dev *dev = cpu_dai->private_data;
struct resource *mem;
@@ -381,7 +502,6 @@ static void davinci_i2s_remove(struct platform_device *pdev,
struct snd_soc_dai davinci_i2s_dai = {
.name = "davinci-i2s",
.id = 0,
- .type = SND_SOC_DAI_I2S,
.probe = davinci_i2s_probe,
.remove = davinci_i2s_remove,
.playback = {
@@ -397,13 +517,24 @@ struct snd_soc_dai davinci_i2s_dai = {
.ops = {
.startup = davinci_i2s_startup,
.trigger = davinci_i2s_trigger,
- .hw_params = davinci_i2s_hw_params,},
- .dai_ops = {
+ .hw_params = davinci_i2s_hw_params,
.set_fmt = davinci_i2s_set_dai_fmt,
},
};
EXPORT_SYMBOL_GPL(davinci_i2s_dai);
+static int __init davinci_i2s_init(void)
+{
+ return snd_soc_register_dai(&davinci_i2s_dai);
+}
+module_init(davinci_i2s_init);
+
+static void __exit davinci_i2s_exit(void)
+{
+ snd_soc_unregister_dai(&davinci_i2s_dai);
+}
+module_exit(davinci_i2s_exit);
+
MODULE_AUTHOR("Vladimir Barinov");
MODULE_DESCRIPTION("TI DAVINCI I2S (McBSP) SoC Interface");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c
index 76feaa65737..74abc9b4f1c 100644
--- a/sound/soc/davinci/davinci-pcm.c
+++ b/sound/soc/davinci/davinci-pcm.c
@@ -14,6 +14,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/dma-mapping.h>
+#include <linux/kernel.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -24,13 +25,6 @@
#include "davinci-pcm.h"
-#define DAVINCI_PCM_DEBUG 0
-#if DAVINCI_PCM_DEBUG
-#define DPRINTK(x...) printk(KERN_DEBUG x)
-#else
-#define DPRINTK(x...)
-#endif
-
static struct snd_pcm_hardware davinci_pcm_hardware = {
.info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
@@ -78,8 +72,8 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
dma_offset = prtd->period * period_size;
dma_pos = runtime->dma_addr + dma_offset;
- DPRINTK("audio_set_dma_params_play channel = %d dma_ptr = %x "
- "period_size=%x\n", lch, dma_pos, period_size);
+ pr_debug("davinci_pcm: audio_set_dma_params_play channel = %d "
+ "dma_ptr = %x period_size=%x\n", lch, dma_pos, period_size);
data_type = prtd->params->data_type;
count = period_size / data_type;
@@ -112,7 +106,7 @@ static void davinci_pcm_dma_irq(int lch, u16 ch_status, void *data)
struct snd_pcm_substream *substream = data;
struct davinci_runtime_data *prtd = substream->runtime->private_data;
- DPRINTK("lch=%d, status=0x%x\n", lch, ch_status);
+ pr_debug("davinci_pcm: lch=%d, status=0x%x\n", lch, ch_status);
if (unlikely(ch_status != DMA_COMPLETE))
return;
@@ -316,8 +310,8 @@ static int davinci_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
buf->area = dma_alloc_writecombine(pcm->card->dev, size,
&buf->addr, GFP_KERNEL);
- DPRINTK("preallocate_dma_buffer: area=%p, addr=%p, size=%d\n",
- (void *) buf->area, (void *) buf->addr, size);
+ pr_debug("davinci_pcm: preallocate_dma_buffer: area=%p, addr=%p, "
+ "size=%d\n", (void *) buf->area, (void *) buf->addr, size);
if (!buf->area)
return -ENOMEM;
@@ -384,6 +378,18 @@ struct snd_soc_platform davinci_soc_platform = {
};
EXPORT_SYMBOL_GPL(davinci_soc_platform);
+static int __init davinci_soc_platform_init(void)
+{
+ return snd_soc_register_platform(&davinci_soc_platform);
+}
+module_init(davinci_soc_platform_init);
+
+static void __exit davinci_soc_platform_exit(void)
+{
+ snd_soc_unregister_platform(&davinci_soc_platform);
+}
+module_exit(davinci_soc_platform_exit);
+
MODULE_AUTHOR("Vladimir Barinov");
MODULE_DESCRIPTION("TI DAVINCI PCM DMA module");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/davinci/davinci-sffsdr.c b/sound/soc/davinci/davinci-sffsdr.c
new file mode 100644
index 00000000000..f67579d5276
--- /dev/null
+++ b/sound/soc/davinci/davinci-sffsdr.c
@@ -0,0 +1,157 @@
+/*
+ * ASoC driver for Lyrtech SFFSDR board.
+ *
+ * Author: Hugo Villeneuve
+ * Copyright (C) 2008 Lyrtech inc
+ *
+ * Based on ASoC driver for TI DAVINCI EVM platform, original copyright follow:
+ * Copyright: (C) 2007 MontaVista Software, Inc., <source@mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <asm/dma.h>
+#include <asm/plat-sffsdr/sffsdr-fpga.h>
+
+#include <mach/mcbsp.h>
+#include <mach/edma.h>
+
+#include "../codecs/pcm3008.h"
+#include "davinci-pcm.h"
+#include "davinci-i2s.h"
+
+static int sffsdr_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+ int fs;
+ int ret = 0;
+
+ /* Set cpu DAI configuration:
+ * CLKX and CLKR are the inputs for the Sample Rate Generator.
+ * FSX and FSR are outputs, driven by the sample Rate Generator. */
+ ret = snd_soc_dai_set_fmt(cpu_dai,
+ SND_SOC_DAIFMT_RIGHT_J |
+ SND_SOC_DAIFMT_CBM_CFS |
+ SND_SOC_DAIFMT_IB_NF);
+ if (ret < 0)
+ return ret;
+
+ /* Fsref can be 32000, 44100 or 48000. */
+ fs = params_rate(params);
+
+ pr_debug("sffsdr_hw_params: rate = %d Hz\n", fs);
+
+ return sffsdr_fpga_set_codec_fs(fs);
+}
+
+static struct snd_soc_ops sffsdr_ops = {
+ .hw_params = sffsdr_hw_params,
+};
+
+/* davinci-sffsdr digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link sffsdr_dai = {
+ .name = "PCM3008", /* Codec name */
+ .stream_name = "PCM3008 HiFi",
+ .cpu_dai = &davinci_i2s_dai,
+ .codec_dai = &pcm3008_dai,
+ .ops = &sffsdr_ops,
+};
+
+/* davinci-sffsdr audio machine driver */
+static struct snd_soc_card snd_soc_sffsdr = {
+ .name = "DaVinci SFFSDR",
+ .platform = &davinci_soc_platform,
+ .dai_link = &sffsdr_dai,
+ .num_links = 1,
+};
+
+/* sffsdr audio private data */
+static struct pcm3008_setup_data sffsdr_pcm3008_setup = {
+ .dem0_pin = GPIO(45),
+ .dem1_pin = GPIO(46),
+ .pdad_pin = GPIO(47),
+ .pdda_pin = GPIO(38),
+};
+
+/* sffsdr audio subsystem */
+static struct snd_soc_device sffsdr_snd_devdata = {
+ .card = &snd_soc_sffsdr,
+ .codec_dev = &soc_codec_dev_pcm3008,
+ .codec_data = &sffsdr_pcm3008_setup,
+};
+
+static struct resource sffsdr_snd_resources[] = {
+ {
+ .start = DAVINCI_MCBSP_BASE,
+ .end = DAVINCI_MCBSP_BASE + SZ_8K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct evm_snd_platform_data sffsdr_snd_data = {
+ .tx_dma_ch = DAVINCI_DMA_MCBSP_TX,
+ .rx_dma_ch = DAVINCI_DMA_MCBSP_RX,
+};
+
+static struct platform_device *sffsdr_snd_device;
+
+static int __init sffsdr_init(void)
+{
+ int ret;
+
+ sffsdr_snd_device = platform_device_alloc("soc-audio", 0);
+ if (!sffsdr_snd_device) {
+ printk(KERN_ERR "platform device allocation failed\n");
+ return -ENOMEM;
+ }
+
+ platform_set_drvdata(sffsdr_snd_device, &sffsdr_snd_devdata);
+ sffsdr_snd_devdata.dev = &sffsdr_snd_device->dev;
+ sffsdr_snd_device->dev.platform_data = &sffsdr_snd_data;
+
+ ret = platform_device_add_resources(sffsdr_snd_device,
+ sffsdr_snd_resources,
+ ARRAY_SIZE(sffsdr_snd_resources));
+ if (ret) {
+ printk(KERN_ERR "platform device add ressources failed\n");
+ goto error;
+ }
+
+ ret = platform_device_add(sffsdr_snd_device);
+ if (ret)
+ goto error;
+
+ return ret;
+
+error:
+ platform_device_put(sffsdr_snd_device);
+ return ret;
+}
+
+static void __exit sffsdr_exit(void)
+{
+ platform_device_unregister(sffsdr_snd_device);
+}
+
+module_init(sffsdr_init);
+module_exit(sffsdr_exit);
+
+MODULE_AUTHOR("Hugo Villeneuve");
+MODULE_DESCRIPTION("Lyrtech SFFSDR ASoC driver");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index bba9546ba5f..95c12b26fe3 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -20,7 +20,8 @@ config SND_SOC_MPC8610_HPCD
config SND_SOC_MPC5200_I2S
tristate "Freescale MPC5200 PSC in I2S mode driver"
+ depends on PPC_MPC52xx && PPC_BESTCOMM
select SND_SOC_OF_SIMPLE
- depends on SND_SOC && PPC_MPC52xx
+ select PPC_BESTCOMM_GEN_BD
help
Say Y here to support the MPC5200 PSCs in I2S mode.
diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c
index d2d3da9729f..64993eda567 100644
--- a/sound/soc/fsl/fsl_dma.c
+++ b/sound/soc/fsl/fsl_dma.c
@@ -284,7 +284,7 @@ static irqreturn_t fsl_dma_isr(int irq, void *dev_id)
* fsl_dma_new: initialize this PCM driver.
*
* This function is called when the codec driver calls snd_soc_new_pcms(),
- * once for each .dai_link in the machine driver's snd_soc_machine
+ * once for each .dai_link in the machine driver's snd_soc_card
* structure.
*/
static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai,
@@ -853,6 +853,18 @@ int fsl_dma_configure(struct fsl_dma_info *dma_info)
}
EXPORT_SYMBOL_GPL(fsl_dma_configure);
+static int __init fsl_soc_platform_init(void)
+{
+ return snd_soc_register_platform(&fsl_soc_platform);
+}
+module_init(fsl_soc_platform_init);
+
+static void __exit fsl_soc_platform_exit(void)
+{
+ snd_soc_unregister_platform(&fsl_soc_platform);
+}
+module_exit(fsl_soc_platform_exit);
+
MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
MODULE_DESCRIPTION("Freescale Elo DMA ASoC PCM module");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 157a7895ffa..c6d6eb71dc1 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -266,7 +266,8 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id)
* If this is the first stream open, then grab the IRQ and program most of
* the SSI registers.
*/
-static int fsl_ssi_startup(struct snd_pcm_substream *substream)
+static int fsl_ssi_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data;
@@ -411,7 +412,8 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream)
* Note: The SxCCR.DC and SxCCR.PM bits are only used if the SSI is the
* clock master.
*/
-static int fsl_ssi_prepare(struct snd_pcm_substream *substream)
+static int fsl_ssi_prepare(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
@@ -441,7 +443,8 @@ static int fsl_ssi_prepare(struct snd_pcm_substream *substream)
* The DMA channel is in external master start and pause mode, which
* means the SSI completely controls the flow of data.
*/
-static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd)
+static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data;
@@ -490,7 +493,8 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd)
*
* Shutdown the SSI if there are no other substreams open.
*/
-static void fsl_ssi_shutdown(struct snd_pcm_substream *substream)
+static void fsl_ssi_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data;
@@ -578,8 +582,6 @@ static struct snd_soc_dai fsl_ssi_dai_template = {
.prepare = fsl_ssi_prepare,
.shutdown = fsl_ssi_shutdown,
.trigger = fsl_ssi_trigger,
- },
- .dai_ops = {
.set_sysclk = fsl_ssi_set_sysclk,
.set_fmt = fsl_ssi_set_fmt,
},
@@ -671,6 +673,14 @@ struct snd_soc_dai *fsl_ssi_create_dai(struct fsl_ssi_info *ssi_info)
fsl_ssi_dai->private_data = ssi_private;
fsl_ssi_dai->name = ssi_private->name;
fsl_ssi_dai->id = ssi_info->id;
+ fsl_ssi_dai->dev = ssi_info->dev;
+
+ ret = snd_soc_register_dai(fsl_ssi_dai);
+ if (ret != 0) {
+ dev_err(ssi_info->dev, "failed to register DAI: %d\n", ret);
+ kfree(fsl_ssi_dai);
+ return NULL;
+ }
return fsl_ssi_dai;
}
@@ -688,6 +698,8 @@ void fsl_ssi_destroy_dai(struct snd_soc_dai *fsl_ssi_dai)
device_remove_file(ssi_private->dev, &ssi_private->dev_attr);
+ snd_soc_unregister_dai(&ssi_private->cpu_dai);
+
kfree(ssi_private);
}
EXPORT_SYMBOL_GPL(fsl_ssi_destroy_dai);
diff --git a/sound/soc/fsl/mpc5200_psc_i2s.c b/sound/soc/fsl/mpc5200_psc_i2s.c
index 94a02eaa482..9eb1ce185bd 100644
--- a/sound/soc/fsl/mpc5200_psc_i2s.c
+++ b/sound/soc/fsl/mpc5200_psc_i2s.c
@@ -187,7 +187,8 @@ static irqreturn_t psc_i2s_bcom_irq(int irq, void *_psc_i2s_stream)
* If this is the first stream open, then grab the IRQ and program most of
* the PSC registers.
*/
-static int psc_i2s_startup(struct snd_pcm_substream *substream)
+static int psc_i2s_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data;
@@ -220,7 +221,8 @@ static int psc_i2s_startup(struct snd_pcm_substream *substream)
}
static int psc_i2s_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data;
@@ -256,7 +258,8 @@ static int psc_i2s_hw_params(struct snd_pcm_substream *substream,
return 0;
}
-static int psc_i2s_hw_free(struct snd_pcm_substream *substream)
+static int psc_i2s_hw_free(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
snd_pcm_set_runtime_buffer(substream, NULL);
return 0;
@@ -268,7 +271,8 @@ static int psc_i2s_hw_free(struct snd_pcm_substream *substream)
* This function is called by ALSA to start, stop, pause, and resume the DMA
* transfer of data.
*/
-static int psc_i2s_trigger(struct snd_pcm_substream *substream, int cmd)
+static int psc_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data;
@@ -383,7 +387,8 @@ static int psc_i2s_trigger(struct snd_pcm_substream *substream, int cmd)
*
* Shutdown the PSC if there are no other substreams open.
*/
-static void psc_i2s_shutdown(struct snd_pcm_substream *substream)
+static void psc_i2s_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data;
@@ -464,7 +469,6 @@ static int psc_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int format)
* psc_i2s_dai_template: template CPU Digital Audio Interface
*/
static struct snd_soc_dai psc_i2s_dai_template = {
- .type = SND_SOC_DAI_I2S,
.playback = {
.channels_min = 2,
.channels_max = 2,
@@ -483,8 +487,6 @@ static struct snd_soc_dai psc_i2s_dai_template = {
.hw_free = psc_i2s_hw_free,
.shutdown = psc_i2s_shutdown,
.trigger = psc_i2s_trigger,
- },
- .dai_ops = {
.set_sysclk = psc_i2s_set_sysclk,
.set_fmt = psc_i2s_set_fmt,
},
@@ -826,6 +828,8 @@ static int __devinit psc_i2s_of_probe(struct of_device *op,
if (rc)
dev_info(psc_i2s->dev, "error creating sysfs files\n");
+ snd_soc_register_platform(&psc_i2s_pcm_soc_platform);
+
/* Tell the ASoC OF helpers about it */
of_snd_soc_register_platform(&psc_i2s_pcm_soc_platform, op->node,
&psc_i2s->dai);
@@ -839,6 +843,8 @@ static int __devexit psc_i2s_of_remove(struct of_device *op)
dev_dbg(&op->dev, "psc_i2s_remove()\n");
+ snd_soc_unregister_platform(&psc_i2s_pcm_soc_platform);
+
bcom_gen_bd_rx_release(psc_i2s->capture.bcom_task);
bcom_gen_bd_tx_release(psc_i2s->playback.bcom_task);
diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c
index 94f89debde1..bcec3f60bad 100644
--- a/sound/soc/fsl/mpc8610_hpcd.c
+++ b/sound/soc/fsl/mpc8610_hpcd.c
@@ -29,7 +29,7 @@
struct mpc8610_hpcd_data {
struct snd_soc_device sound_devdata;
struct snd_soc_dai_link dai;
- struct snd_soc_machine machine;
+ struct snd_soc_card machine;
unsigned int dai_format;
unsigned int codec_clk_direction;
unsigned int cpu_clk_direction;
@@ -185,7 +185,7 @@ static struct snd_soc_ops mpc8610_hpcd_ops = {
/**
* mpc8610_hpcd_machine: ASoC machine data
*/
-static struct snd_soc_machine mpc8610_hpcd_machine = {
+static struct snd_soc_card mpc8610_hpcd_machine = {
.probe = mpc8610_hpcd_machine_probe,
.remove = mpc8610_hpcd_machine_remove,
.name = "MPC8610 HPCD",
@@ -465,9 +465,9 @@ static int mpc8610_hpcd_probe(struct of_device *ofdev,
goto error;
}
- machine_data->sound_devdata.machine = &mpc8610_hpcd_machine;
+ machine_data->sound_devdata.card = &mpc8610_hpcd_machine;
machine_data->sound_devdata.codec_dev = &soc_codec_device_cs4270;
- machine_data->sound_devdata.platform = &fsl_soc_platform;
+ machine_data->machine.platform = &fsl_soc_platform;
sound_device->dev.platform_data = machine_data;
diff --git a/sound/soc/fsl/soc-of-simple.c b/sound/soc/fsl/soc-of-simple.c
index 0382fdac51c..8bc5cd9e972 100644
--- a/sound/soc/fsl/soc-of-simple.c
+++ b/sound/soc/fsl/soc-of-simple.c
@@ -31,7 +31,7 @@ struct of_snd_soc_device {
int id;
struct list_head list;
struct snd_soc_device device;
- struct snd_soc_machine machine;
+ struct snd_soc_card card;
struct snd_soc_dai_link dai_link;
struct platform_device *pdev;
struct device_node *platform_node;
@@ -58,9 +58,9 @@ of_snd_soc_get_device(struct device_node *codec_node)
/* Initialize the structure and add it to the global list */
of_soc->codec_node = codec_node;
of_soc->id = of_snd_soc_next_index++;
- of_soc->machine.dai_link = &of_soc->dai_link;
- of_soc->machine.num_links = 1;
- of_soc->device.machine = &of_soc->machine;
+ of_soc->card.dai_link = &of_soc->dai_link;
+ of_soc->card.num_links = 1;
+ of_soc->device.card = &of_soc->card;
of_soc->dai_link.ops = &of_snd_soc_ops;
list_add(&of_soc->list, &of_snd_soc_device_list);
@@ -158,8 +158,8 @@ int of_snd_soc_register_platform(struct snd_soc_platform *platform,
of_soc->platform_node = node;
of_soc->dai_link.cpu_dai = cpu_dai;
- of_soc->device.platform = platform;
- of_soc->machine.name = of_soc->dai_link.cpu_dai->name;
+ of_soc->card.platform = platform;
+ of_soc->card.name = of_soc->dai_link.cpu_dai->name;
/* Now try to register the SoC device */
of_snd_soc_register_device(of_soc);
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
index 8b7766b998d..a7b1d77b210 100644
--- a/sound/soc/omap/Kconfig
+++ b/sound/soc/omap/Kconfig
@@ -1,6 +1,6 @@
config SND_OMAP_SOC
tristate "SoC Audio for the Texas Instruments OMAP chips"
- depends on ARCH_OMAP && SND_SOC
+ depends on ARCH_OMAP
config SND_OMAP_SOC_MCBSP
tristate
@@ -21,3 +21,36 @@ config SND_OMAP_SOC_OSK5912
select SND_SOC_TLV320AIC23
help
Say Y if you want to add support for SoC audio on osk5912.
+
+config SND_OMAP_SOC_OVERO
+ tristate "SoC Audio support for Gumstix Overo"
+ depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OVERO
+ select SND_OMAP_SOC_MCBSP
+ select SND_SOC_TWL4030
+ help
+ Say Y if you want to add support for SoC audio on the Gumstix Overo.
+
+config SND_OMAP_SOC_OMAP2EVM
+ tristate "SoC Audio support for OMAP2EVM board"
+ depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP2EVM
+ select SND_OMAP_SOC_MCBSP
+ select SND_SOC_TWL4030
+ help
+ Say Y if you want to add support for SoC audio on the omap2evm board.
+
+config SND_OMAP_SOC_SDP3430
+ tristate "SoC Audio support for Texas Instruments SDP3430"
+ depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP_3430SDP
+ select SND_OMAP_SOC_MCBSP
+ select SND_SOC_TWL4030
+ help
+ Say Y if you want to add support for SoC audio on Texas Instruments
+ SDP3430.
+
+config SND_OMAP_SOC_OMAP3_PANDORA
+ tristate "SoC Audio support for OMAP3 Pandora"
+ depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP3_PANDORA
+ select SND_OMAP_SOC_MCBSP
+ select SND_SOC_TWL4030
+ help
+ Say Y if you want to add support for SoC audio on the OMAP3 Pandora.
diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile
index e09d1f297f6..76fedd96e36 100644
--- a/sound/soc/omap/Makefile
+++ b/sound/soc/omap/Makefile
@@ -8,6 +8,14 @@ obj-$(CONFIG_SND_OMAP_SOC_MCBSP) += snd-soc-omap-mcbsp.o
# OMAP Machine Support
snd-soc-n810-objs := n810.o
snd-soc-osk5912-objs := osk5912.o
+snd-soc-overo-objs := overo.o
+snd-soc-omap2evm-objs := omap2evm.o
+snd-soc-sdp3430-objs := sdp3430.o
+snd-soc-omap3pandora-objs := omap3pandora.o
obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o
obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o
+obj-$(CONFIG_SND_OMAP_SOC_OVERO) += snd-soc-overo.o
+obj-$(CONFIG_MACH_OMAP2EVM) += snd-soc-omap2evm.o
+obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o
+obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o
diff --git a/sound/soc/omap/n810.c b/sound/soc/omap/n810.c
index fae3ad36e0b..25593fee912 100644
--- a/sound/soc/omap/n810.c
+++ b/sound/soc/omap/n810.c
@@ -70,9 +70,13 @@ static void n810_ext_control(struct snd_soc_codec *codec)
static int n810_startup(struct snd_pcm_substream *substream)
{
+ struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_codec *codec = rtd->socdev->codec;
+ snd_pcm_hw_constraint_minmax(runtime,
+ SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2);
+
n810_ext_control(codec);
return clk_enable(sys_clkout2);
}
@@ -282,8 +286,9 @@ static struct snd_soc_dai_link n810_dai = {
};
/* Audio machine driver */
-static struct snd_soc_machine snd_soc_machine_n810 = {
+static struct snd_soc_card snd_soc_n810 = {
.name = "N810",
+ .platform = &omap_soc_platform,
.dai_link = &n810_dai,
.num_links = 1,
};
@@ -298,8 +303,7 @@ static struct aic3x_setup_data n810_aic33_setup = {
/* Audio subsystem */
static struct snd_soc_device n810_snd_devdata = {
- .machine = &snd_soc_machine_n810,
- .platform = &omap_soc_platform,
+ .card = &snd_soc_n810,
.codec_dev = &soc_codec_dev_aic3x,
.codec_data = &n810_aic33_setup,
};
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index 8485a8a9d0f..ec5e18a7875 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -36,9 +36,7 @@
#include "omap-mcbsp.h"
#include "omap-pcm.h"
-#define OMAP_MCBSP_RATES (SNDRV_PCM_RATE_44100 | \
- SNDRV_PCM_RATE_48000 | \
- SNDRV_PCM_RATE_KNOT)
+#define OMAP_MCBSP_RATES (SNDRV_PCM_RATE_8000_96000)
struct omap_mcbsp_data {
unsigned int bus_id;
@@ -140,7 +138,8 @@ static const unsigned long omap34xx_mcbsp_port[][2] = {
static const unsigned long omap34xx_mcbsp_port[][2] = {};
#endif
-static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream)
+static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
@@ -153,7 +152,8 @@ static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream)
return err;
}
-static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream)
+static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
@@ -165,7 +165,8 @@ static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream)
}
}
-static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd)
+static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
@@ -194,14 +195,15 @@ static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd)
}
static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id;
- int wlen;
+ int wlen, channels;
unsigned long port;
if (cpu_class_is_omap1()) {
@@ -230,12 +232,17 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
return 0;
}
- switch (params_channels(params)) {
+ channels = params_channels(params);
+ switch (channels) {
case 2:
- /* Set 1 word per (McBPSP) frame and use dual-phase frames */
- regs->rcr2 |= RFRLEN2(1 - 1) | RPHASE;
+ /* Use dual-phase frames */
+ regs->rcr2 |= RPHASE;
+ regs->xcr2 |= XPHASE;
+ case 1:
+ /* Set 1 word per (McBSP) frame */
+ regs->rcr2 |= RFRLEN2(1 - 1);
regs->rcr1 |= RFRLEN1(1 - 1);
- regs->xcr2 |= XFRLEN2(1 - 1) | XPHASE;
+ regs->xcr2 |= XFRLEN2(1 - 1);
regs->xcr1 |= XFRLEN1(1 - 1);
break;
default:
@@ -263,9 +270,9 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
regs->srgr2 |= FPER(wlen * 2 - 1);
regs->srgr1 |= FWID(wlen - 1);
break;
- case SND_SOC_DAIFMT_DSP_A:
- regs->srgr2 |= FPER(wlen * 2 - 1);
- regs->srgr1 |= FWID(wlen * 2 - 2);
+ case SND_SOC_DAIFMT_DSP_B:
+ regs->srgr2 |= FPER(wlen * channels - 1);
+ regs->srgr1 |= FWID(wlen * channels - 2);
break;
}
@@ -302,7 +309,7 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
regs->rcr2 |= RDATDLY(1);
regs->xcr2 |= XDATDLY(1);
break;
- case SND_SOC_DAIFMT_DSP_A:
+ case SND_SOC_DAIFMT_DSP_B:
/* 0-bit data delay */
regs->rcr2 |= RDATDLY(0);
regs->xcr2 |= XDATDLY(0);
@@ -452,17 +459,16 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
#define OMAP_MCBSP_DAI_BUILDER(link_id) \
{ \
- .name = "omap-mcbsp-dai-(link_id)", \
+ .name = "omap-mcbsp-dai-"#link_id, \
.id = (link_id), \
- .type = SND_SOC_DAI_I2S, \
.playback = { \
- .channels_min = 2, \
+ .channels_min = 1, \
.channels_max = 2, \
.rates = OMAP_MCBSP_RATES, \
.formats = SNDRV_PCM_FMTBIT_S16_LE, \
}, \
.capture = { \
- .channels_min = 2, \
+ .channels_min = 1, \
.channels_max = 2, \
.rates = OMAP_MCBSP_RATES, \
.formats = SNDRV_PCM_FMTBIT_S16_LE, \
@@ -472,8 +478,6 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
.shutdown = omap_mcbsp_dai_shutdown, \
.trigger = omap_mcbsp_dai_trigger, \
.hw_params = omap_mcbsp_dai_hw_params, \
- }, \
- .dai_ops = { \
.set_fmt = omap_mcbsp_dai_set_dai_fmt, \
.set_clkdiv = omap_mcbsp_dai_set_clkdiv, \
.set_sysclk = omap_mcbsp_dai_set_dai_sysclk, \
@@ -495,6 +499,19 @@ struct snd_soc_dai omap_mcbsp_dai[] = {
EXPORT_SYMBOL_GPL(omap_mcbsp_dai);
+static int __init snd_omap_mcbsp_init(void)
+{
+ return snd_soc_register_dais(omap_mcbsp_dai,
+ ARRAY_SIZE(omap_mcbsp_dai));
+}
+module_init(snd_omap_mcbsp_init);
+
+static void __exit snd_omap_mcbsp_exit(void)
+{
+ snd_soc_unregister_dais(omap_mcbsp_dai, ARRAY_SIZE(omap_mcbsp_dai));
+}
+module_exit(snd_omap_mcbsp_exit);
+
MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@nokia.com>");
MODULE_DESCRIPTION("OMAP I2S SoC Interface");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c
index e9084fdd208..b0362dfd5b7 100644
--- a/sound/soc/omap/omap-pcm.c
+++ b/sound/soc/omap/omap-pcm.c
@@ -97,7 +97,7 @@ static int omap_pcm_hw_params(struct snd_pcm_substream *substream,
prtd->dma_data = dma_data;
err = omap_request_dma(dma_data->dma_req, dma_data->name,
omap_pcm_dma_irq, substream, &prtd->dma_ch);
- if (!err & !cpu_is_omap1510()) {
+ if (!err && !cpu_is_omap1510()) {
/*
* Link channel with itself so DMA doesn't need any
* reprogramming while looping the buffer
@@ -233,7 +233,7 @@ static int omap_pcm_open(struct snd_pcm_substream *substream)
if (ret < 0)
goto out;
- prtd = kzalloc(sizeof(prtd), GFP_KERNEL);
+ prtd = kzalloc(sizeof(*prtd), GFP_KERNEL);
if (prtd == NULL) {
ret = -ENOMEM;
goto out;
@@ -354,6 +354,18 @@ struct snd_soc_platform omap_soc_platform = {
};
EXPORT_SYMBOL_GPL(omap_soc_platform);
+static int __init omap_soc_platform_init(void)
+{
+ return snd_soc_register_platform(&omap_soc_platform);
+}
+module_init(omap_soc_platform_init);
+
+static void __exit omap_soc_platform_exit(void)
+{
+ snd_soc_unregister_platform(&omap_soc_platform);
+}
+module_exit(omap_soc_platform_exit);
+
MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@nokia.com>");
MODULE_DESCRIPTION("OMAP PCM DMA module");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/omap2evm.c b/sound/soc/omap/omap2evm.c
new file mode 100644
index 00000000000..0c2322dcf02
--- /dev/null
+++ b/sound/soc/omap/omap2evm.c
@@ -0,0 +1,151 @@
+/*
+ * omap2evm.c -- SoC audio machine driver for omap2evm board
+ *
+ * Author: Arun KS <arunks@mistralsolutions.com>
+ *
+ * Based on sound/soc/omap/overo.c by Steve Sakoman
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+#include <mach/gpio.h>
+#include <mach/mcbsp.h>
+
+#include "omap-mcbsp.h"
+#include "omap-pcm.h"
+#include "../codecs/twl4030.h"
+
+static int omap2evm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+ int ret;
+
+ /* Set codec DAI configuration */
+ ret = snd_soc_dai_set_fmt(codec_dai,
+ SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM);
+ if (ret < 0) {
+ printk(KERN_ERR "can't set codec DAI configuration\n");
+ return ret;
+ }
+
+ /* Set cpu DAI configuration */
+ ret = snd_soc_dai_set_fmt(cpu_dai,
+ SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM);
+ if (ret < 0) {
+ printk(KERN_ERR "can't set cpu DAI configuration\n");
+ return ret;
+ }
+
+ /* Set the codec system clock for DAC and ADC */
+ ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
+ SND_SOC_CLOCK_IN);
+ if (ret < 0) {
+ printk(KERN_ERR "can't set codec system clock\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static struct snd_soc_ops omap2evm_ops = {
+ .hw_params = omap2evm_hw_params,
+};
+
+/* Digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link omap2evm_dai = {
+ .name = "TWL4030",
+ .stream_name = "TWL4030",
+ .cpu_dai = &omap_mcbsp_dai[0],
+ .codec_dai = &twl4030_dai,
+ .ops = &omap2evm_ops,
+};
+
+/* Audio machine driver */
+static struct snd_soc_card snd_soc_omap2evm = {
+ .name = "omap2evm",
+ .platform = &omap_soc_platform,
+ .dai_link = &omap2evm_dai,
+ .num_links = 1,
+};
+
+/* Audio subsystem */
+static struct snd_soc_device omap2evm_snd_devdata = {
+ .card = &snd_soc_omap2evm,
+ .codec_dev = &soc_codec_dev_twl4030,
+};
+
+static struct platform_device *omap2evm_snd_device;
+
+static int __init omap2evm_soc_init(void)
+{
+ int ret;
+
+ if (!machine_is_omap2evm()) {
+ pr_debug("Not omap2evm!\n");
+ return -ENODEV;
+ }
+ printk(KERN_INFO "omap2evm SoC init\n");
+
+ omap2evm_snd_device = platform_device_alloc("soc-audio", -1);
+ if (!omap2evm_snd_device) {
+ printk(KERN_ERR "Platform device allocation failed\n");
+ return -ENOMEM;
+ }
+
+ platform_set_drvdata(omap2evm_snd_device, &omap2evm_snd_devdata);
+ omap2evm_snd_devdata.dev = &omap2evm_snd_device->dev;
+ *(unsigned int *)omap2evm_dai.cpu_dai->private_data = 1; /* McBSP2 */
+
+ ret = platform_device_add(omap2evm_snd_device);
+ if (ret)
+ goto err1;
+
+ return 0;
+
+err1:
+ printk(KERN_ERR "Unable to add platform device\n");
+ platform_device_put(omap2evm_snd_device);
+
+ return ret;
+}
+module_init(omap2evm_soc_init);
+
+static void __exit omap2evm_soc_exit(void)
+{
+ platform_device_unregister(omap2evm_snd_device);
+}
+module_exit(omap2evm_soc_exit);
+
+MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>");
+MODULE_DESCRIPTION("ALSA SoC omap2evm");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/omap3beagle.c b/sound/soc/omap/omap3beagle.c
new file mode 100644
index 00000000000..fd24a4acd2f
--- /dev/null
+++ b/sound/soc/omap/omap3beagle.c
@@ -0,0 +1,149 @@
+/*
+ * omap3beagle.c -- SoC audio for OMAP3 Beagle
+ *
+ * Author: Steve Sakoman <steve@sakoman.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+#include <mach/gpio.h>
+#include <mach/mcbsp.h>
+
+#include "omap-mcbsp.h"
+#include "omap-pcm.h"
+#include "../codecs/twl4030.h"
+
+static int omap3beagle_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+ int ret;
+
+ /* Set codec DAI configuration */
+ ret = snd_soc_dai_set_fmt(codec_dai,
+ SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM);
+ if (ret < 0) {
+ printk(KERN_ERR "can't set codec DAI configuration\n");
+ return ret;
+ }
+
+ /* Set cpu DAI configuration */
+ ret = snd_soc_dai_set_fmt(cpu_dai,
+ SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM);
+ if (ret < 0) {
+ printk(KERN_ERR "can't set cpu DAI configuration\n");
+ return ret;
+ }
+
+ /* Set the codec system clock for DAC and ADC */
+ ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
+ SND_SOC_CLOCK_IN);
+ if (ret < 0) {
+ printk(KERN_ERR "can't set codec system clock\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static struct snd_soc_ops omap3beagle_ops = {
+ .hw_params = omap3beagle_hw_params,
+};
+
+/* Digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link omap3beagle_dai = {
+ .name = "TWL4030",
+ .stream_name = "TWL4030",
+ .cpu_dai = &omap_mcbsp_dai[0],
+ .codec_dai = &twl4030_dai,
+ .ops = &omap3beagle_ops,
+};
+
+/* Audio machine driver */
+static struct snd_soc_card snd_soc_omap3beagle = {
+ .name = "omap3beagle",
+ .platform = &omap_soc_platform,
+ .dai_link = &omap3beagle_dai,
+ .num_links = 1,
+};
+
+/* Audio subsystem */
+static struct snd_soc_device omap3beagle_snd_devdata = {
+ .card = &snd_soc_omap3beagle,
+ .codec_dev = &soc_codec_dev_twl4030,
+};
+
+static struct platform_device *omap3beagle_snd_device;
+
+static int __init omap3beagle_soc_init(void)
+{
+ int ret;
+
+ if (!machine_is_omap3_beagle()) {
+ pr_debug("Not OMAP3 Beagle!\n");
+ return -ENODEV;
+ }
+ pr_info("OMAP3 Beagle SoC init\n");
+
+ omap3beagle_snd_device = platform_device_alloc("soc-audio", -1);
+ if (!omap3beagle_snd_device) {
+ printk(KERN_ERR "Platform device allocation failed\n");
+ return -ENOMEM;
+ }
+
+ platform_set_drvdata(omap3beagle_snd_device, &omap3beagle_snd_devdata);
+ omap3beagle_snd_devdata.dev = &omap3beagle_snd_device->dev;
+ *(unsigned int *)omap3beagle_dai.cpu_dai->private_data = 1; /* McBSP2 */
+
+ ret = platform_device_add(omap3beagle_snd_device);
+ if (ret)
+ goto err1;
+
+ return 0;
+
+err1:
+ printk(KERN_ERR "Unable to add platform device\n");
+ platform_device_put(omap3beagle_snd_device);
+
+ return ret;
+}
+
+static void __exit omap3beagle_soc_exit(void)
+{
+ platform_device_unregister(omap3beagle_snd_device);
+}
+
+module_init(omap3beagle_soc_init);
+module_exit(omap3beagle_soc_exit);
+
+MODULE_AUTHOR("Steve Sakoman <steve@sakoman.com>");
+MODULE_DESCRIPTION("ALSA SoC OMAP3 Beagle");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/omap3pandora.c b/sound/soc/omap/omap3pandora.c
new file mode 100644
index 00000000000..bd91594496b
--- /dev/null
+++ b/sound/soc/omap/omap3pandora.c
@@ -0,0 +1,311 @@
+/*
+ * omap3pandora.c -- SoC audio for Pandora Handheld Console
+ *
+ * Author: Gražvydas Ignotas <notasas@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <asm/mach-types.h>
+
+#include "omap-mcbsp.h"
+#include "omap-pcm.h"
+#include "../codecs/twl4030.h"
+
+#define OMAP3_PANDORA_DAC_POWER_GPIO 118
+#define OMAP3_PANDORA_AMP_POWER_GPIO 14
+
+#define PREFIX "ASoC omap3pandora: "
+
+static int omap3pandora_cmn_hw_params(struct snd_soc_dai *codec_dai,
+ struct snd_soc_dai *cpu_dai, unsigned int fmt)
+{
+ int ret;
+
+ /* Set codec DAI configuration */
+ ret = snd_soc_dai_set_fmt(codec_dai, fmt);
+ if (ret < 0) {
+ pr_err(PREFIX "can't set codec DAI configuration\n");
+ return ret;
+ }
+
+ /* Set cpu DAI configuration */
+ ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
+ if (ret < 0) {
+ pr_err(PREFIX "can't set cpu DAI configuration\n");
+ return ret;
+ }
+
+ /* Set the codec system clock for DAC and ADC */
+ ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
+ SND_SOC_CLOCK_IN);
+ if (ret < 0) {
+ pr_err(PREFIX "can't set codec system clock\n");
+ return ret;
+ }
+
+ /* Set McBSP clock to external */
+ ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_SYSCLK_CLKS_EXT, 0,
+ SND_SOC_CLOCK_IN);
+ if (ret < 0) {
+ pr_err(PREFIX "can't set cpu system clock\n");
+ return ret;
+ }
+
+ ret = snd_soc_dai_set_clkdiv(cpu_dai, OMAP_MCBSP_CLKGDV, 8);
+ if (ret < 0) {
+ pr_err(PREFIX "can't set SRG clock divider\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int omap3pandora_out_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+
+ return omap3pandora_cmn_hw_params(codec_dai, cpu_dai,
+ SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_IB_NF |
+ SND_SOC_DAIFMT_CBS_CFS);
+}
+
+static int omap3pandora_in_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+
+ return omap3pandora_cmn_hw_params(codec_dai, cpu_dai,
+ SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBS_CFS);
+}
+
+static int omap3pandora_hp_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *k, int event)
+{
+ if (SND_SOC_DAPM_EVENT_ON(event)) {
+ gpio_set_value(OMAP3_PANDORA_DAC_POWER_GPIO, 1);
+ gpio_set_value(OMAP3_PANDORA_AMP_POWER_GPIO, 1);
+ } else {
+ gpio_set_value(OMAP3_PANDORA_AMP_POWER_GPIO, 0);
+ mdelay(1);
+ gpio_set_value(OMAP3_PANDORA_DAC_POWER_GPIO, 0);
+ }
+
+ return 0;
+}
+
+/*
+ * Audio paths on Pandora board:
+ *
+ * |O| ---> PCM DAC +-> AMP -> Headphone Jack
+ * |M| A +--------> Line Out
+ * |A| <~~clk~~+
+ * |P| <--- TWL4030 <--------- Line In and MICs
+ */
+static const struct snd_soc_dapm_widget omap3pandora_out_dapm_widgets[] = {
+ SND_SOC_DAPM_DAC("PCM DAC", "Playback", SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_PGA_E("Headphone Amplifier", SND_SOC_NOPM,
+ 0, 0, NULL, 0, omap3pandora_hp_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+ SND_SOC_DAPM_HP("Headphone Jack", NULL),
+ SND_SOC_DAPM_LINE("Line Out", NULL),
+};
+
+static const struct snd_soc_dapm_widget omap3pandora_in_dapm_widgets[] = {
+ SND_SOC_DAPM_MIC("Mic (Internal)", NULL),
+ SND_SOC_DAPM_MIC("Mic (external)", NULL),
+ SND_SOC_DAPM_LINE("Line In", NULL),
+};
+
+static const struct snd_soc_dapm_route omap3pandora_out_map[] = {
+ {"Headphone Amplifier", NULL, "PCM DAC"},
+ {"Line Out", NULL, "PCM DAC"},
+ {"Headphone Jack", NULL, "Headphone Amplifier"},
+};
+
+static const struct snd_soc_dapm_route omap3pandora_in_map[] = {
+ {"INL", NULL, "Line In"},
+ {"INR", NULL, "Line In"},
+ {"INL", NULL, "Mic (Internal)"},
+ {"INR", NULL, "Mic (external)"},
+};
+
+static int omap3pandora_out_init(struct snd_soc_codec *codec)
+{
+ int ret;
+
+ ret = snd_soc_dapm_new_controls(codec, omap3pandora_out_dapm_widgets,
+ ARRAY_SIZE(omap3pandora_out_dapm_widgets));
+ if (ret < 0)
+ return ret;
+
+ snd_soc_dapm_add_routes(codec, omap3pandora_out_map,
+ ARRAY_SIZE(omap3pandora_out_map));
+
+ return snd_soc_dapm_sync(codec);
+}
+
+static int omap3pandora_in_init(struct snd_soc_codec *codec)
+{
+ int ret;
+
+ ret = snd_soc_dapm_new_controls(codec, omap3pandora_in_dapm_widgets,
+ ARRAY_SIZE(omap3pandora_in_dapm_widgets));
+ if (ret < 0)
+ return ret;
+
+ snd_soc_dapm_add_routes(codec, omap3pandora_in_map,
+ ARRAY_SIZE(omap3pandora_in_map));
+
+ return snd_soc_dapm_sync(codec);
+}
+
+static struct snd_soc_ops omap3pandora_out_ops = {
+ .hw_params = omap3pandora_out_hw_params,
+};
+
+static struct snd_soc_ops omap3pandora_in_ops = {
+ .hw_params = omap3pandora_in_hw_params,
+};
+
+/* Digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link omap3pandora_dai[] = {
+ {
+ .name = "PCM1773",
+ .stream_name = "HiFi Out",
+ .cpu_dai = &omap_mcbsp_dai[0],
+ .codec_dai = &twl4030_dai,
+ .ops = &omap3pandora_out_ops,
+ .init = omap3pandora_out_init,
+ }, {
+ .name = "TWL4030",
+ .stream_name = "Line/Mic In",
+ .cpu_dai = &omap_mcbsp_dai[1],
+ .codec_dai = &twl4030_dai,
+ .ops = &omap3pandora_in_ops,
+ .init = omap3pandora_in_init,
+ }
+};
+
+/* SoC card */
+static struct snd_soc_card snd_soc_card_omap3pandora = {
+ .name = "omap3pandora",
+ .platform = &omap_soc_platform,
+ .dai_link = omap3pandora_dai,
+ .num_links = ARRAY_SIZE(omap3pandora_dai),
+};
+
+/* Audio subsystem */
+static struct snd_soc_device omap3pandora_snd_data = {
+ .card = &snd_soc_card_omap3pandora,
+ .codec_dev = &soc_codec_dev_twl4030,
+};
+
+static struct platform_device *omap3pandora_snd_device;
+
+static int __init omap3pandora_soc_init(void)
+{
+ int ret;
+
+ if (!machine_is_omap3_pandora()) {
+ pr_debug(PREFIX "Not OMAP3 Pandora\n");
+ return -ENODEV;
+ }
+ pr_info("OMAP3 Pandora SoC init\n");
+
+ ret = gpio_request(OMAP3_PANDORA_DAC_POWER_GPIO, "dac_power");
+ if (ret) {
+ pr_err(PREFIX "Failed to get DAC power GPIO\n");
+ return ret;
+ }
+
+ ret = gpio_direction_output(OMAP3_PANDORA_DAC_POWER_GPIO, 0);
+ if (ret) {
+ pr_err(PREFIX "Failed to set DAC power GPIO direction\n");
+ goto fail0;
+ }
+
+ ret = gpio_request(OMAP3_PANDORA_AMP_POWER_GPIO, "amp_power");
+ if (ret) {
+ pr_err(PREFIX "Failed to get amp power GPIO\n");
+ goto fail0;
+ }
+
+ ret = gpio_direction_output(OMAP3_PANDORA_AMP_POWER_GPIO, 0);
+ if (ret) {
+ pr_err(PREFIX "Failed to set amp power GPIO direction\n");
+ goto fail1;
+ }
+
+ omap3pandora_snd_device = platform_device_alloc("soc-audio", -1);
+ if (omap3pandora_snd_device == NULL) {
+ pr_err(PREFIX "Platform device allocation failed\n");
+ ret = -ENOMEM;
+ goto fail1;
+ }
+
+ platform_set_drvdata(omap3pandora_snd_device, &omap3pandora_snd_data);
+ omap3pandora_snd_data.dev = &omap3pandora_snd_device->dev;
+ *(unsigned int *)omap_mcbsp_dai[0].private_data = 1; /* McBSP2 */
+ *(unsigned int *)omap_mcbsp_dai[1].private_data = 3; /* McBSP4 */
+
+ ret = platform_device_add(omap3pandora_snd_device);
+ if (ret) {
+ pr_err(PREFIX "Unable to add platform device\n");
+ goto fail2;
+ }
+
+ return 0;
+
+fail2:
+ platform_device_put(omap3pandora_snd_device);
+fail1:
+ gpio_free(OMAP3_PANDORA_AMP_POWER_GPIO);
+fail0:
+ gpio_free(OMAP3_PANDORA_DAC_POWER_GPIO);
+ return ret;
+}
+module_init(omap3pandora_soc_init);
+
+static void __exit omap3pandora_soc_exit(void)
+{
+ platform_device_unregister(omap3pandora_snd_device);
+ gpio_free(OMAP3_PANDORA_AMP_POWER_GPIO);
+ gpio_free(OMAP3_PANDORA_DAC_POWER_GPIO);
+}
+module_exit(omap3pandora_soc_exit);
+
+MODULE_AUTHOR("Grazvydas Ignotas <notasas@gmail.com>");
+MODULE_DESCRIPTION("ALSA SoC OMAP3 Pandora");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/osk5912.c b/sound/soc/omap/osk5912.c
index 0fe73379689..cd41a948df7 100644
--- a/sound/soc/omap/osk5912.c
+++ b/sound/soc/omap/osk5912.c
@@ -61,7 +61,7 @@ static int osk_hw_params(struct snd_pcm_substream *substream,
/* Set codec DAI configuration */
err = snd_soc_dai_set_fmt(codec_dai,
- SND_SOC_DAIFMT_DSP_A |
+ SND_SOC_DAIFMT_DSP_B |
SND_SOC_DAIFMT_NB_IF |
SND_SOC_DAIFMT_CBM_CFM);
if (err < 0) {
@@ -71,7 +71,7 @@ static int osk_hw_params(struct snd_pcm_substream *substream,
/* Set cpu DAI configuration */
err = snd_soc_dai_set_fmt(cpu_dai,
- SND_SOC_DAIFMT_DSP_A |
+ SND_SOC_DAIFMT_DSP_B |
SND_SOC_DAIFMT_NB_IF |
SND_SOC_DAIFMT_CBM_CFM);
if (err < 0) {
@@ -143,16 +143,16 @@ static struct snd_soc_dai_link osk_dai = {
};
/* Audio machine driver */
-static struct snd_soc_machine snd_soc_machine_osk = {
+static struct snd_soc_card snd_soc_card_osk = {
.name = "OSK5912",
+ .platform = &omap_soc_platform,
.dai_link = &osk_dai,
.num_links = 1,
};
/* Audio subsystem */
static struct snd_soc_device osk_snd_devdata = {
- .machine = &snd_soc_machine_osk,
- .platform = &omap_soc_platform,
+ .card = &snd_soc_card_osk,
.codec_dev = &soc_codec_dev_tlv320aic23,
};
diff --git a/sound/soc/omap/overo.c b/sound/soc/omap/overo.c
new file mode 100644
index 00000000000..a72dc4e159e
--- /dev/null
+++ b/sound/soc/omap/overo.c
@@ -0,0 +1,148 @@
+/*
+ * overo.c -- SoC audio for Gumstix Overo
+ *
+ * Author: Steve Sakoman <steve@sakoman.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+#include <mach/gpio.h>
+#include <mach/mcbsp.h>
+
+#include "omap-mcbsp.h"
+#include "omap-pcm.h"
+#include "../codecs/twl4030.h"
+
+static int overo_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+ int ret;
+
+ /* Set codec DAI configuration */
+ ret = snd_soc_dai_set_fmt(codec_dai,
+ SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM);
+ if (ret < 0) {
+ printk(KERN_ERR "can't set codec DAI configuration\n");
+ return ret;
+ }
+
+ /* Set cpu DAI configuration */
+ ret = snd_soc_dai_set_fmt(cpu_dai,
+ SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM);
+ if (ret < 0) {
+ printk(KERN_ERR "can't set cpu DAI configuration\n");
+ return ret;
+ }
+
+ /* Set the codec system clock for DAC and ADC */
+ ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
+ SND_SOC_CLOCK_IN);
+ if (ret < 0) {
+ printk(KERN_ERR "can't set codec system clock\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static struct snd_soc_ops overo_ops = {
+ .hw_params = overo_hw_params,
+};
+
+/* Digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link overo_dai = {
+ .name = "TWL4030",
+ .stream_name = "TWL4030",
+ .cpu_dai = &omap_mcbsp_dai[0],
+ .codec_dai = &twl4030_dai,
+ .ops = &overo_ops,
+};
+
+/* Audio machine driver */
+static struct snd_soc_card snd_soc_card_overo = {
+ .name = "overo",
+ .platform = &omap_soc_platform,
+ .dai_link = &overo_dai,
+ .num_links = 1,
+};
+
+/* Audio subsystem */
+static struct snd_soc_device overo_snd_devdata = {
+ .card = &snd_soc_card_overo,
+ .codec_dev = &soc_codec_dev_twl4030,
+};
+
+static struct platform_device *overo_snd_device;
+
+static int __init overo_soc_init(void)
+{
+ int ret;
+
+ if (!machine_is_overo()) {
+ pr_debug("Not Overo!\n");
+ return -ENODEV;
+ }
+ printk(KERN_INFO "overo SoC init\n");
+
+ overo_snd_device = platform_device_alloc("soc-audio", -1);
+ if (!overo_snd_device) {
+ printk(KERN_ERR "Platform device allocation failed\n");
+ return -ENOMEM;
+ }
+
+ platform_set_drvdata(overo_snd_device, &overo_snd_devdata);
+ overo_snd_devdata.dev = &overo_snd_device->dev;
+ *(unsigned int *)overo_dai.cpu_dai->private_data = 1; /* McBSP2 */
+
+ ret = platform_device_add(overo_snd_device);
+ if (ret)
+ goto err1;
+
+ return 0;
+
+err1:
+ printk(KERN_ERR "Unable to add platform device\n");
+ platform_device_put(overo_snd_device);
+
+ return ret;
+}
+module_init(overo_soc_init);
+
+static void __exit overo_soc_exit(void)
+{
+ platform_device_unregister(overo_snd_device);
+}
+module_exit(overo_soc_exit);
+
+MODULE_AUTHOR("Steve Sakoman <steve@sakoman.com>");
+MODULE_DESCRIPTION("ALSA SoC overo");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/sdp3430.c b/sound/soc/omap/sdp3430.c
new file mode 100644
index 00000000000..ad97836818b
--- /dev/null
+++ b/sound/soc/omap/sdp3430.c
@@ -0,0 +1,152 @@
+/*
+ * sdp3430.c -- SoC audio for TI OMAP3430 SDP
+ *
+ * Author: Misael Lopez Cruz <x0052729@ti.com>
+ *
+ * Based on:
+ * Author: Steve Sakoman <steve@sakoman.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+#include <mach/gpio.h>
+#include <mach/mcbsp.h>
+
+#include "omap-mcbsp.h"
+#include "omap-pcm.h"
+#include "../codecs/twl4030.h"
+
+static int sdp3430_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+ int ret;
+
+ /* Set codec DAI configuration */
+ ret = snd_soc_dai_set_fmt(codec_dai,
+ SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM);
+ if (ret < 0) {
+ printk(KERN_ERR "can't set codec DAI configuration\n");
+ return ret;
+ }
+
+ /* Set cpu DAI configuration */
+ ret = snd_soc_dai_set_fmt(cpu_dai,
+ SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM);
+ if (ret < 0) {
+ printk(KERN_ERR "can't set cpu DAI configuration\n");
+ return ret;
+ }
+
+ /* Set the codec system clock for DAC and ADC */
+ ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
+ SND_SOC_CLOCK_IN);
+ if (ret < 0) {
+ printk(KERN_ERR "can't set codec system clock\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static struct snd_soc_ops sdp3430_ops = {
+ .hw_params = sdp3430_hw_params,
+};
+
+/* Digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link sdp3430_dai = {
+ .name = "TWL4030",
+ .stream_name = "TWL4030",
+ .cpu_dai = &omap_mcbsp_dai[0],
+ .codec_dai = &twl4030_dai,
+ .ops = &sdp3430_ops,
+};
+
+/* Audio machine driver */
+static struct snd_soc_machine snd_soc_machine_sdp3430 = {
+ .name = "SDP3430",
+ .platform = &omap_soc_platform,
+ .dai_link = &sdp3430_dai,
+ .num_links = 1,
+};
+
+/* Audio subsystem */
+static struct snd_soc_device sdp3430_snd_devdata = {
+ .machine = &snd_soc_machine_sdp3430,
+ .codec_dev = &soc_codec_dev_twl4030,
+};
+
+static struct platform_device *sdp3430_snd_device;
+
+static int __init sdp3430_soc_init(void)
+{
+ int ret;
+
+ if (!machine_is_omap_3430sdp()) {
+ pr_debug("Not SDP3430!\n");
+ return -ENODEV;
+ }
+ printk(KERN_INFO "SDP3430 SoC init\n");
+
+ sdp3430_snd_device = platform_device_alloc("soc-audio", -1);
+ if (!sdp3430_snd_device) {
+ printk(KERN_ERR "Platform device allocation failed\n");
+ return -ENOMEM;
+ }
+
+ platform_set_drvdata(sdp3430_snd_device, &sdp3430_snd_devdata);
+ sdp3430_snd_devdata.dev = &sdp3430_snd_device->dev;
+ *(unsigned int *)sdp3430_dai.cpu_dai->private_data = 1; /* McBSP2 */
+
+ ret = platform_device_add(sdp3430_snd_device);
+ if (ret)
+ goto err1;
+
+ return 0;
+
+err1:
+ printk(KERN_ERR "Unable to add platform device\n");
+ platform_device_put(sdp3430_snd_device);
+
+ return ret;
+}
+module_init(sdp3430_soc_init);
+
+static void __exit sdp3430_soc_exit(void)
+{
+ platform_device_unregister(sdp3430_snd_device);
+}
+module_exit(sdp3430_soc_exit);
+
+MODULE_AUTHOR("Misael Lopez Cruz <x0052729@ti.com>");
+MODULE_DESCRIPTION("ALSA SoC SDP3430");
+MODULE_LICENSE("GPL");
+
diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig
index f8c1cdd940a..f82e1069947 100644
--- a/sound/soc/pxa/Kconfig
+++ b/sound/soc/pxa/Kconfig
@@ -21,6 +21,9 @@ config SND_PXA2XX_SOC_AC97
config SND_PXA2XX_SOC_I2S
tristate
+config SND_PXA_SOC_SSP
+ tristate
+
config SND_PXA2XX_SOC_CORGI
tristate "SoC Audio support for Sharp Zaurus SL-C7x0"
depends on SND_PXA2XX_SOC && PXA_SHARP_C7xx
@@ -75,3 +78,22 @@ config SND_PXA2XX_SOC_EM_X270
help
Say Y if you want to add support for SoC audio on
CompuLab EM-x270.
+
+config SND_PXA2XX_SOC_PALM27X
+ bool "SoC Audio support for Palm T|X, T5 and LifeDrive"
+ depends on SND_PXA2XX_SOC && (MACH_PALMLD || MACH_PALMTX || MACH_PALMT5)
+ select SND_PXA2XX_SOC_AC97
+ select SND_SOC_WM9712
+ help
+ Say Y if you want to add support for SoC audio on
+ Palm T|X, T5 or LifeDrive handheld computer.
+
+config SND_SOC_ZYLONITE
+ tristate "SoC Audio support for Marvell Zylonite"
+ depends on SND_PXA2XX_SOC && MACH_ZYLONITE
+ select SND_PXA2XX_SOC_AC97
+ select SND_PXA_SOC_SSP
+ select SND_SOC_WM9713
+ help
+ Say Y if you want to add support for SoC audio on the
+ Marvell Zylonite reference platform.
diff --git a/sound/soc/pxa/Makefile b/sound/soc/pxa/Makefile
index 5bc8edf9dca..08a9f279772 100644
--- a/sound/soc/pxa/Makefile
+++ b/sound/soc/pxa/Makefile
@@ -2,10 +2,12 @@
snd-soc-pxa2xx-objs := pxa2xx-pcm.o
snd-soc-pxa2xx-ac97-objs := pxa2xx-ac97.o
snd-soc-pxa2xx-i2s-objs := pxa2xx-i2s.o
+snd-soc-pxa-ssp-objs := pxa-ssp.o
obj-$(CONFIG_SND_PXA2XX_SOC) += snd-soc-pxa2xx.o
obj-$(CONFIG_SND_PXA2XX_SOC_AC97) += snd-soc-pxa2xx-ac97.o
obj-$(CONFIG_SND_PXA2XX_SOC_I2S) += snd-soc-pxa2xx-i2s.o
+obj-$(CONFIG_SND_PXA_SOC_SSP) += snd-soc-pxa-ssp.o
# PXA Machine Support
snd-soc-corgi-objs := corgi.o
@@ -14,6 +16,8 @@ snd-soc-tosa-objs := tosa.o
snd-soc-e800-objs := e800_wm9712.o
snd-soc-spitz-objs := spitz.o
snd-soc-em-x270-objs := em-x270.o
+snd-soc-palm27x-objs := palm27x.o
+snd-soc-zylonite-objs := zylonite.o
obj-$(CONFIG_SND_PXA2XX_SOC_CORGI) += snd-soc-corgi.o
obj-$(CONFIG_SND_PXA2XX_SOC_POODLE) += snd-soc-poodle.o
@@ -21,3 +25,5 @@ obj-$(CONFIG_SND_PXA2XX_SOC_TOSA) += snd-soc-tosa.o
obj-$(CONFIG_SND_PXA2XX_SOC_E800) += snd-soc-e800.o
obj-$(CONFIG_SND_PXA2XX_SOC_SPITZ) += snd-soc-spitz.o
obj-$(CONFIG_SND_PXA2XX_SOC_EM_X270) += snd-soc-em-x270.o
+obj-$(CONFIG_SND_PXA2XX_SOC_PALM27X) += snd-soc-palm27x.o
+obj-$(CONFIG_SND_SOC_ZYLONITE) += snd-soc-zylonite.o
diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c
index 2718eaf7895..1ba25a55952 100644
--- a/sound/soc/pxa/corgi.c
+++ b/sound/soc/pxa/corgi.c
@@ -108,15 +108,11 @@ static int corgi_startup(struct snd_pcm_substream *substream)
}
/* we need to unmute the HP at shutdown as the mute burns power on corgi */
-static int corgi_shutdown(struct snd_pcm_substream *substream)
+static void corgi_shutdown(struct snd_pcm_substream *substream)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->socdev->codec;
-
/* set = unmute headphone */
gpio_set_value(CORGI_GPIO_MUTE_L, 1);
gpio_set_value(CORGI_GPIO_MUTE_R, 1);
- return 0;
}
static int corgi_hw_params(struct snd_pcm_substream *substream,
@@ -314,8 +310,9 @@ static struct snd_soc_dai_link corgi_dai = {
};
/* corgi audio machine driver */
-static struct snd_soc_machine snd_soc_machine_corgi = {
+static struct snd_soc_card snd_soc_corgi = {
.name = "Corgi",
+ .platform = &pxa2xx_soc_platform,
.dai_link = &corgi_dai,
.num_links = 1,
};
@@ -328,8 +325,7 @@ static struct wm8731_setup_data corgi_wm8731_setup = {
/* corgi audio subsystem */
static struct snd_soc_device corgi_snd_devdata = {
- .machine = &snd_soc_machine_corgi,
- .platform = &pxa2xx_soc_platform,
+ .card = &snd_soc_corgi,
.codec_dev = &soc_codec_dev_wm8731,
.codec_data = &corgi_wm8731_setup,
};
diff --git a/sound/soc/pxa/e800_wm9712.c b/sound/soc/pxa/e800_wm9712.c
index 6781c5be242..2e3386dfa0f 100644
--- a/sound/soc/pxa/e800_wm9712.c
+++ b/sound/soc/pxa/e800_wm9712.c
@@ -29,7 +29,7 @@
#include "pxa2xx-pcm.h"
#include "pxa2xx-ac97.h"
-static struct snd_soc_machine e800;
+static struct snd_soc_card e800;
static struct snd_soc_dai_link e800_dai[] = {
{
@@ -40,15 +40,15 @@ static struct snd_soc_dai_link e800_dai[] = {
},
};
-static struct snd_soc_machine e800 = {
+static struct snd_soc_card e800 = {
.name = "Toshiba e800",
+ .platform = &pxa2xx_soc_platform,
.dai_link = e800_dai,
.num_links = ARRAY_SIZE(e800_dai),
};
static struct snd_soc_device e800_snd_devdata = {
- .machine = &e800,
- .platform = &pxa2xx_soc_platform,
+ .card = &e800,
.codec_dev = &soc_codec_dev_wm9712,
};
diff --git a/sound/soc/pxa/em-x270.c b/sound/soc/pxa/em-x270.c
index e6ff6929ab4..fe4a729ea64 100644
--- a/sound/soc/pxa/em-x270.c
+++ b/sound/soc/pxa/em-x270.c
@@ -23,7 +23,6 @@
#include <linux/moduleparam.h>
#include <linux/device.h>
-#include <sound/driver.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/soc.h>
@@ -53,15 +52,15 @@ static struct snd_soc_dai_link em_x270_dai[] = {
},
};
-static struct snd_soc_machine em_x270 = {
+static struct snd_soc_card em_x270 = {
.name = "EM-X270",
+ .platform = &pxa2xx_soc_platform,
.dai_link = em_x270_dai,
.num_links = ARRAY_SIZE(em_x270_dai),
};
static struct snd_soc_device em_x270_snd_devdata = {
- .machine = &em_x270,
- .platform = &pxa2xx_soc_platform,
+ .card = &em_x270,
.codec_dev = &soc_codec_dev_wm9712,
};
diff --git a/sound/soc/pxa/palm27x.c b/sound/soc/pxa/palm27x.c
new file mode 100644
index 00000000000..4a9cf3083af
--- /dev/null
+++ b/sound/soc/pxa/palm27x.c
@@ -0,0 +1,269 @@
+/*
+ * linux/sound/soc/pxa/palm27x.c
+ *
+ * SoC Audio driver for Palm T|X, T5 and LifeDrive
+ *
+ * based on tosa.c
+ *
+ * Copyright (C) 2008 Marek Vasut <marek.vasut@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <asm/mach-types.h>
+#include <mach/audio.h>
+#include <mach/palmasoc.h>
+
+#include "../codecs/wm9712.h"
+#include "pxa2xx-pcm.h"
+#include "pxa2xx-ac97.h"
+
+static int palm27x_jack_func = 1;
+static int palm27x_spk_func = 1;
+static int palm27x_ep_gpio = -1;
+
+static void palm27x_ext_control(struct snd_soc_codec *codec)
+{
+ if (!palm27x_spk_func)
+ snd_soc_dapm_enable_pin(codec, "Speaker");
+ else
+ snd_soc_dapm_disable_pin(codec, "Speaker");
+
+ if (!palm27x_jack_func)
+ snd_soc_dapm_enable_pin(codec, "Headphone Jack");
+ else
+ snd_soc_dapm_disable_pin(codec, "Headphone Jack");
+
+ snd_soc_dapm_sync(codec);
+}
+
+static int palm27x_startup(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_codec *codec = rtd->socdev->codec;
+
+ /* check the jack status at stream startup */
+ palm27x_ext_control(codec);
+ return 0;
+}
+
+static struct snd_soc_ops palm27x_ops = {
+ .startup = palm27x_startup,
+};
+
+static irqreturn_t palm27x_interrupt(int irq, void *v)
+{
+ palm27x_spk_func = gpio_get_value(palm27x_ep_gpio);
+ palm27x_jack_func = !palm27x_spk_func;
+ return IRQ_HANDLED;
+}
+
+static int palm27x_get_jack(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.integer.value[0] = palm27x_jack_func;
+ return 0;
+}
+
+static int palm27x_set_jack(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+ if (palm27x_jack_func == ucontrol->value.integer.value[0])
+ return 0;
+
+ palm27x_jack_func = ucontrol->value.integer.value[0];
+ palm27x_ext_control(codec);
+ return 1;
+}
+
+static int palm27x_get_spk(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.integer.value[0] = palm27x_spk_func;
+ return 0;
+}
+
+static int palm27x_set_spk(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+ if (palm27x_spk_func == ucontrol->value.integer.value[0])
+ return 0;
+
+ palm27x_spk_func = ucontrol->value.integer.value[0];
+ palm27x_ext_control(codec);
+ return 1;
+}
+
+/* PalmTX machine dapm widgets */
+static const struct snd_soc_dapm_widget palm27x_dapm_widgets[] = {
+ SND_SOC_DAPM_HP("Headphone Jack", NULL),
+ SND_SOC_DAPM_SPK("Speaker", NULL),
+};
+
+/* PalmTX audio map */
+static const struct snd_soc_dapm_route audio_map[] = {
+ /* headphone connected to HPOUTL, HPOUTR */
+ {"Headphone Jack", NULL, "HPOUTL"},
+ {"Headphone Jack", NULL, "HPOUTR"},
+
+ /* ext speaker connected to ROUT2, LOUT2 */
+ {"Speaker", NULL, "LOUT2"},
+ {"Speaker", NULL, "ROUT2"},
+};
+
+static const char *jack_function[] = {"Headphone", "Off"};
+static const char *spk_function[] = {"On", "Off"};
+static const struct soc_enum palm27x_enum[] = {
+ SOC_ENUM_SINGLE_EXT(2, jack_function),
+ SOC_ENUM_SINGLE_EXT(2, spk_function),
+};
+
+static const struct snd_kcontrol_new palm27x_controls[] = {
+ SOC_ENUM_EXT("Jack Function", palm27x_enum[0], palm27x_get_jack,
+ palm27x_set_jack),
+ SOC_ENUM_EXT("Speaker Function", palm27x_enum[1], palm27x_get_spk,
+ palm27x_set_spk),
+};
+
+static int palm27x_ac97_init(struct snd_soc_codec *codec)
+{
+ int i, err;
+
+ snd_soc_dapm_nc_pin(codec, "OUT3");
+ snd_soc_dapm_nc_pin(codec, "MONOOUT");
+
+ /* add palm27x specific controls */
+ for (i = 0; i < ARRAY_SIZE(palm27x_controls); i++) {
+ err = snd_ctl_add(codec->card,
+ snd_soc_cnew(&palm27x_controls[i],
+ codec, NULL));
+ if (err < 0)
+ return err;
+ }
+
+ /* add palm27x specific widgets */
+ snd_soc_dapm_new_controls(codec, palm27x_dapm_widgets,
+ ARRAY_SIZE(palm27x_dapm_widgets));
+
+ /* set up palm27x specific audio path audio_map */
+ snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+
+ snd_soc_dapm_sync(codec);
+ return 0;
+}
+
+static struct snd_soc_dai_link palm27x_dai[] = {
+{
+ .name = "AC97 HiFi",
+ .stream_name = "AC97 HiFi",
+ .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI],
+ .codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI],
+ .init = palm27x_ac97_init,
+ .ops = &palm27x_ops,
+},
+{
+ .name = "AC97 Aux",
+ .stream_name = "AC97 Aux",
+ .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX],
+ .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX],
+ .ops = &palm27x_ops,
+},
+};
+
+static struct snd_soc_card palm27x_asoc = {
+ .name = "Palm/PXA27x",
+ .platform = &pxa2xx_soc_platform,
+ .dai_link = palm27x_dai,
+ .num_links = ARRAY_SIZE(palm27x_dai),
+};
+
+static struct snd_soc_device palm27x_snd_devdata = {
+ .card = &palm27x_asoc,
+ .codec_dev = &soc_codec_dev_wm9712,
+};
+
+static struct platform_device *palm27x_snd_device;
+
+static int __init palm27x_asoc_init(void)
+{
+ int ret;
+
+ if (!(machine_is_palmtx() || machine_is_palmt5() ||
+ machine_is_palmld()))
+ return -ENODEV;
+
+ ret = gpio_request(palm27x_ep_gpio, "Headphone Jack");
+ if (ret)
+ return ret;
+ ret = gpio_direction_input(palm27x_ep_gpio);
+ if (ret)
+ goto err_alloc;
+
+ if (request_irq(gpio_to_irq(palm27x_ep_gpio), palm27x_interrupt,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ "Headphone jack", NULL))
+ goto err_alloc;
+
+ palm27x_snd_device = platform_device_alloc("soc-audio", -1);
+ if (!palm27x_snd_device) {
+ ret = -ENOMEM;
+ goto err_dev;
+ }
+
+ platform_set_drvdata(palm27x_snd_device, &palm27x_snd_devdata);
+ palm27x_snd_devdata.dev = &palm27x_snd_device->dev;
+ ret = platform_device_add(palm27x_snd_device);
+
+ if (ret != 0)
+ goto put_device;
+
+ return 0;
+
+put_device:
+ platform_device_put(palm27x_snd_device);
+err_dev:
+ free_irq(gpio_to_irq(palm27x_ep_gpio), NULL);
+err_alloc:
+ gpio_free(palm27x_ep_gpio);
+
+ return ret;
+}
+
+static void __exit palm27x_asoc_exit(void)
+{
+ free_irq(gpio_to_irq(palm27x_ep_gpio), NULL);
+ gpio_free(palm27x_ep_gpio);
+ platform_device_unregister(palm27x_snd_device);
+}
+
+void __init palm27x_asoc_set_pdata(struct palm27x_asoc_info *data)
+{
+ palm27x_ep_gpio = data->jack_gpio;
+}
+
+module_init(palm27x_asoc_init);
+module_exit(palm27x_asoc_exit);
+
+/* Module information */
+MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
+MODULE_DESCRIPTION("ALSA SoC Palm T|X, T5 and LifeDrive");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c
index 4d9930c5278..6e9827189ff 100644
--- a/sound/soc/pxa/poodle.c
+++ b/sound/soc/pxa/poodle.c
@@ -276,8 +276,9 @@ static struct snd_soc_dai_link poodle_dai = {
};
/* poodle audio machine driver */
-static struct snd_soc_machine snd_soc_machine_poodle = {
+static struct snd_soc_card snd_soc_poodle = {
.name = "Poodle",
+ .platform = &pxa2xx_soc_platform,
.dai_link = &poodle_dai,
.num_links = 1,
};
@@ -290,8 +291,7 @@ static struct wm8731_setup_data poodle_wm8731_setup = {
/* poodle audio subsystem */
static struct snd_soc_device poodle_snd_devdata = {
- .machine = &snd_soc_machine_poodle,
- .platform = &pxa2xx_soc_platform,
+ .card = &snd_soc_poodle,
.codec_dev = &soc_codec_dev_wm8731,
.codec_data = &poodle_wm8731_setup,
};
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
new file mode 100644
index 00000000000..73cb6b4c2f2
--- /dev/null
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -0,0 +1,931 @@
+#define DEBUG
+/*
+ * pxa-ssp.c -- ALSA Soc Audio Layer
+ *
+ * Copyright 2005,2008 Wolfson Microelectronics PLC.
+ * Author: Liam Girdwood
+ * Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * TODO:
+ * o Test network mode for > 16bit sample size
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/initval.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/pxa2xx-lib.h>
+
+#include <mach/hardware.h>
+#include <mach/pxa-regs.h>
+#include <mach/regs-ssp.h>
+#include <mach/audio.h>
+#include <mach/ssp.h>
+
+#include "pxa2xx-pcm.h"
+#include "pxa-ssp.h"
+
+/*
+ * SSP audio private data
+ */
+struct ssp_priv {
+ struct ssp_dev dev;
+ unsigned int sysclk;
+ int dai_fmt;
+#ifdef CONFIG_PM
+ struct ssp_state state;
+#endif
+};
+
+#define PXA2xx_SSP1_BASE 0x41000000
+#define PXA27x_SSP2_BASE 0x41700000
+#define PXA27x_SSP3_BASE 0x41900000
+#define PXA3xx_SSP4_BASE 0x41a00000
+
+static struct pxa2xx_pcm_dma_params pxa_ssp1_pcm_mono_out = {
+ .name = "SSP1 PCM Mono out",
+ .dev_addr = PXA2xx_SSP1_BASE + SSDR,
+ .drcmr = &DRCMR(14),
+ .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
+ DCMD_BURST16 | DCMD_WIDTH2,
+};
+
+static struct pxa2xx_pcm_dma_params pxa_ssp1_pcm_mono_in = {
+ .name = "SSP1 PCM Mono in",
+ .dev_addr = PXA2xx_SSP1_BASE + SSDR,
+ .drcmr = &DRCMR(13),
+ .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
+ DCMD_BURST16 | DCMD_WIDTH2,
+};
+
+static struct pxa2xx_pcm_dma_params pxa_ssp1_pcm_stereo_out = {
+ .name = "SSP1 PCM Stereo out",
+ .dev_addr = PXA2xx_SSP1_BASE + SSDR,
+ .drcmr = &DRCMR(14),
+ .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
+ DCMD_BURST16 | DCMD_WIDTH4,
+};
+
+static struct pxa2xx_pcm_dma_params pxa_ssp1_pcm_stereo_in = {
+ .name = "SSP1 PCM Stereo in",
+ .dev_addr = PXA2xx_SSP1_BASE + SSDR,
+ .drcmr = &DRCMR(13),
+ .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
+ DCMD_BURST16 | DCMD_WIDTH4,
+};
+
+static struct pxa2xx_pcm_dma_params pxa_ssp2_pcm_mono_out = {
+ .name = "SSP2 PCM Mono out",
+ .dev_addr = PXA27x_SSP2_BASE + SSDR,
+ .drcmr = &DRCMR(16),
+ .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
+ DCMD_BURST16 | DCMD_WIDTH2,
+};
+
+static struct pxa2xx_pcm_dma_params pxa_ssp2_pcm_mono_in = {
+ .name = "SSP2 PCM Mono in",
+ .dev_addr = PXA27x_SSP2_BASE + SSDR,
+ .drcmr = &DRCMR(15),
+ .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
+ DCMD_BURST16 | DCMD_WIDTH2,
+};
+
+static struct pxa2xx_pcm_dma_params pxa_ssp2_pcm_stereo_out = {
+ .name = "SSP2 PCM Stereo out",
+ .dev_addr = PXA27x_SSP2_BASE + SSDR,
+ .drcmr = &DRCMR(16),
+ .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
+ DCMD_BURST16 | DCMD_WIDTH4,
+};
+
+static struct pxa2xx_pcm_dma_params pxa_ssp2_pcm_stereo_in = {
+ .name = "SSP2 PCM Stereo in",
+ .dev_addr = PXA27x_SSP2_BASE + SSDR,
+ .drcmr = &DRCMR(15),
+ .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
+ DCMD_BURST16 | DCMD_WIDTH4,
+};
+
+static struct pxa2xx_pcm_dma_params pxa_ssp3_pcm_mono_out = {
+ .name = "SSP3 PCM Mono out",
+ .dev_addr = PXA27x_SSP3_BASE + SSDR,
+ .drcmr = &DRCMR(67),
+ .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
+ DCMD_BURST16 | DCMD_WIDTH2,
+};
+
+static struct pxa2xx_pcm_dma_params pxa_ssp3_pcm_mono_in = {
+ .name = "SSP3 PCM Mono in",
+ .dev_addr = PXA27x_SSP3_BASE + SSDR,
+ .drcmr = &DRCMR(66),
+ .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
+ DCMD_BURST16 | DCMD_WIDTH2,
+};
+
+static struct pxa2xx_pcm_dma_params pxa_ssp3_pcm_stereo_out = {
+ .name = "SSP3 PCM Stereo out",
+ .dev_addr = PXA27x_SSP3_BASE + SSDR,
+ .drcmr = &DRCMR(67),
+ .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
+ DCMD_BURST16 | DCMD_WIDTH4,
+};
+
+static struct pxa2xx_pcm_dma_params pxa_ssp3_pcm_stereo_in = {
+ .name = "SSP3 PCM Stereo in",
+ .dev_addr = PXA27x_SSP3_BASE + SSDR,
+ .drcmr = &DRCMR(66),
+ .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
+ DCMD_BURST16 | DCMD_WIDTH4,
+};
+
+static struct pxa2xx_pcm_dma_params pxa_ssp4_pcm_mono_out = {
+ .name = "SSP4 PCM Mono out",
+ .dev_addr = PXA3xx_SSP4_BASE + SSDR,
+ .drcmr = &DRCMR(67),
+ .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
+ DCMD_BURST16 | DCMD_WIDTH2,
+};
+
+static struct pxa2xx_pcm_dma_params pxa_ssp4_pcm_mono_in = {
+ .name = "SSP4 PCM Mono in",
+ .dev_addr = PXA3xx_SSP4_BASE + SSDR,
+ .drcmr = &DRCMR(66),
+ .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
+ DCMD_BURST16 | DCMD_WIDTH2,
+};
+
+static struct pxa2xx_pcm_dma_params pxa_ssp4_pcm_stereo_out = {
+ .name = "SSP4 PCM Stereo out",
+ .dev_addr = PXA3xx_SSP4_BASE + SSDR,
+ .drcmr = &DRCMR(67),
+ .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
+ DCMD_BURST16 | DCMD_WIDTH4,
+};
+
+static struct pxa2xx_pcm_dma_params pxa_ssp4_pcm_stereo_in = {
+ .name = "SSP4 PCM Stereo in",
+ .dev_addr = PXA3xx_SSP4_BASE + SSDR,
+ .drcmr = &DRCMR(66),
+ .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
+ DCMD_BURST16 | DCMD_WIDTH4,
+};
+
+static void dump_registers(struct ssp_device *ssp)
+{
+ dev_dbg(&ssp->pdev->dev, "SSCR0 0x%08x SSCR1 0x%08x SSTO 0x%08x\n",
+ ssp_read_reg(ssp, SSCR0), ssp_read_reg(ssp, SSCR1),
+ ssp_read_reg(ssp, SSTO));
+
+ dev_dbg(&ssp->pdev->dev, "SSPSP 0x%08x SSSR 0x%08x SSACD 0x%08x\n",
+ ssp_read_reg(ssp, SSPSP), ssp_read_reg(ssp, SSSR),
+ ssp_read_reg(ssp, SSACD));
+}
+
+static struct pxa2xx_pcm_dma_params *ssp_dma_params[4][4] = {
+ {
+ &pxa_ssp1_pcm_mono_out, &pxa_ssp1_pcm_mono_in,
+ &pxa_ssp1_pcm_stereo_out, &pxa_ssp1_pcm_stereo_in,
+ },
+ {
+ &pxa_ssp2_pcm_mono_out, &pxa_ssp2_pcm_mono_in,
+ &pxa_ssp2_pcm_stereo_out, &pxa_ssp2_pcm_stereo_in,
+ },
+ {
+ &pxa_ssp3_pcm_mono_out, &pxa_ssp3_pcm_mono_in,
+ &pxa_ssp3_pcm_stereo_out, &pxa_ssp3_pcm_stereo_in,
+ },
+ {
+ &pxa_ssp4_pcm_mono_out, &pxa_ssp4_pcm_mono_in,
+ &pxa_ssp4_pcm_stereo_out, &pxa_ssp4_pcm_stereo_in,
+ },
+};
+
+static int pxa_ssp_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+ struct ssp_priv *priv = cpu_dai->private_data;
+ int ret = 0;
+
+ if (!cpu_dai->active) {
+ ret = ssp_init(&priv->dev, cpu_dai->id + 1, SSP_NO_IRQ);
+ if (ret < 0)
+ return ret;
+ ssp_disable(&priv->dev);
+ }
+ return ret;
+}
+
+static void pxa_ssp_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+ struct ssp_priv *priv = cpu_dai->private_data;
+
+ if (!cpu_dai->active) {
+ ssp_disable(&priv->dev);
+ ssp_exit(&priv->dev);
+ }
+}
+
+#ifdef CONFIG_PM
+
+static int pxa_ssp_suspend(struct snd_soc_dai *cpu_dai)
+{
+ struct ssp_priv *priv = cpu_dai->private_data;
+
+ if (!cpu_dai->active)
+ return 0;
+
+ ssp_save_state(&priv->dev, &priv->state);
+ clk_disable(priv->dev.ssp->clk);
+ return 0;
+}
+
+static int pxa_ssp_resume(struct snd_soc_dai *cpu_dai)
+{
+ struct ssp_priv *priv = cpu_dai->private_data;
+
+ if (!cpu_dai->active)
+ return 0;
+
+ clk_enable(priv->dev.ssp->clk);
+ ssp_restore_state(&priv->dev, &priv->state);
+ ssp_enable(&priv->dev);
+
+ return 0;
+}
+
+#else
+#define pxa_ssp_suspend NULL
+#define pxa_ssp_resume NULL
+#endif
+
+/**
+ * ssp_set_clkdiv - set SSP clock divider
+ * @div: serial clock rate divider
+ */
+static void ssp_set_scr(struct ssp_dev *dev, u32 div)
+{
+ struct ssp_device *ssp = dev->ssp;
+ u32 sscr0 = ssp_read_reg(dev->ssp, SSCR0) & ~SSCR0_SCR;
+
+ ssp_write_reg(ssp, SSCR0, (sscr0 | SSCR0_SerClkDiv(div)));
+}
+
+/*
+ * Set the SSP ports SYSCLK.
+ */
+static int pxa_ssp_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct ssp_priv *priv = cpu_dai->private_data;
+ struct ssp_device *ssp = priv->dev.ssp;
+ int val;
+
+ u32 sscr0 = ssp_read_reg(ssp, SSCR0) &
+ ~(SSCR0_ECS | SSCR0_NCS | SSCR0_MOD | SSCR0_ADC);
+
+ dev_dbg(&ssp->pdev->dev,
+ "pxa_ssp_set_dai_sysclk id: %d, clk_id %d, freq %d\n",
+ cpu_dai->id, clk_id, freq);
+
+ switch (clk_id) {
+ case PXA_SSP_CLK_NET_PLL:
+ sscr0 |= SSCR0_MOD;
+ break;
+ case PXA_SSP_CLK_PLL:
+ /* Internal PLL is fixed */
+ if (cpu_is_pxa25x())
+ priv->sysclk = 1843200;
+ else
+ priv->sysclk = 13000000;
+ break;
+ case PXA_SSP_CLK_EXT:
+ priv->sysclk = freq;
+ sscr0 |= SSCR0_ECS;
+ break;
+ case PXA_SSP_CLK_NET:
+ priv->sysclk = freq;
+ sscr0 |= SSCR0_NCS | SSCR0_MOD;
+ break;
+ case PXA_SSP_CLK_AUDIO:
+ priv->sysclk = 0;
+ ssp_set_scr(&priv->dev, 1);
+ sscr0 |= SSCR0_ADC;
+ break;
+ default:
+ return -ENODEV;
+ }
+
+ /* The SSP clock must be disabled when changing SSP clock mode
+ * on PXA2xx. On PXA3xx it must be enabled when doing so. */
+ if (!cpu_is_pxa3xx())
+ clk_disable(priv->dev.ssp->clk);
+ val = ssp_read_reg(ssp, SSCR0) | sscr0;
+ ssp_write_reg(ssp, SSCR0, val);
+ if (!cpu_is_pxa3xx())
+ clk_enable(priv->dev.ssp->clk);
+
+ return 0;
+}
+
+/*
+ * Set the SSP clock dividers.
+ */
+static int pxa_ssp_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
+ int div_id, int div)
+{
+ struct ssp_priv *priv = cpu_dai->private_data;
+ struct ssp_device *ssp = priv->dev.ssp;
+ int val;
+
+ switch (div_id) {
+ case PXA_SSP_AUDIO_DIV_ACDS:
+ val = (ssp_read_reg(ssp, SSACD) & ~0x7) | SSACD_ACDS(div);
+ ssp_write_reg(ssp, SSACD, val);
+ break;
+ case PXA_SSP_AUDIO_DIV_SCDB:
+ val = ssp_read_reg(ssp, SSACD);
+ val &= ~SSACD_SCDB;
+#if defined(CONFIG_PXA3xx)
+ if (cpu_is_pxa3xx())
+ val &= ~SSACD_SCDX8;
+#endif
+ switch (div) {
+ case PXA_SSP_CLK_SCDB_1:
+ val |= SSACD_SCDB;
+ break;
+ case PXA_SSP_CLK_SCDB_4:
+ break;
+#if defined(CONFIG_PXA3xx)
+ case PXA_SSP_CLK_SCDB_8:
+ if (cpu_is_pxa3xx())
+ val |= SSACD_SCDX8;
+ else
+ return -EINVAL;
+ break;
+#endif
+ default:
+ return -EINVAL;
+ }
+ ssp_write_reg(ssp, SSACD, val);
+ break;
+ case PXA_SSP_DIV_SCR:
+ ssp_set_scr(&priv->dev, div);
+ break;
+ default:
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+/*
+ * Configure the PLL frequency pxa27x and (afaik - pxa320 only)
+ */
+static int pxa_ssp_set_dai_pll(struct snd_soc_dai *cpu_dai,
+ int pll_id, unsigned int freq_in, unsigned int freq_out)
+{
+ struct ssp_priv *priv = cpu_dai->private_data;
+ struct ssp_device *ssp = priv->dev.ssp;
+ u32 ssacd = ssp_read_reg(ssp, SSACD) & ~0x70;
+
+#if defined(CONFIG_PXA3xx)
+ if (cpu_is_pxa3xx())
+ ssp_write_reg(ssp, SSACDD, 0);
+#endif
+
+ switch (freq_out) {
+ case 5622000:
+ break;
+ case 11345000:
+ ssacd |= (0x1 << 4);
+ break;
+ case 12235000:
+ ssacd |= (0x2 << 4);
+ break;
+ case 14857000:
+ ssacd |= (0x3 << 4);
+ break;
+ case 32842000:
+ ssacd |= (0x4 << 4);
+ break;
+ case 48000000:
+ ssacd |= (0x5 << 4);
+ break;
+ case 0:
+ /* Disable */
+ break;
+
+ default:
+#ifdef CONFIG_PXA3xx
+ /* PXA3xx has a clock ditherer which can be used to generate
+ * a wider range of frequencies - calculate a value for it.
+ */
+ if (cpu_is_pxa3xx()) {
+ u32 val;
+ u64 tmp = 19968;
+ tmp *= 1000000;
+ do_div(tmp, freq_out);
+ val = tmp;
+
+ val = (val << 16) | 64;;
+ ssp_write_reg(ssp, SSACDD, val);
+
+ ssacd |= (0x6 << 4);
+
+ dev_dbg(&ssp->pdev->dev,
+ "Using SSACDD %x to supply %dHz\n",
+ val, freq_out);
+ break;
+ }
+#endif
+
+ return -EINVAL;
+ }
+
+ ssp_write_reg(ssp, SSACD, ssacd);
+
+ return 0;
+}
+
+/*
+ * Set the active slots in TDM/Network mode
+ */
+static int pxa_ssp_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai,
+ unsigned int mask, int slots)
+{
+ struct ssp_priv *priv = cpu_dai->private_data;
+ struct ssp_device *ssp = priv->dev.ssp;
+ u32 sscr0;
+
+ sscr0 = ssp_read_reg(ssp, SSCR0) & ~SSCR0_SlotsPerFrm(7);
+
+ /* set number of active slots */
+ sscr0 |= SSCR0_SlotsPerFrm(slots);
+ ssp_write_reg(ssp, SSCR0, sscr0);
+
+ /* set active slot mask */
+ ssp_write_reg(ssp, SSTSA, mask);
+ ssp_write_reg(ssp, SSRSA, mask);
+ return 0;
+}
+
+/*
+ * Tristate the SSP DAI lines
+ */
+static int pxa_ssp_set_dai_tristate(struct snd_soc_dai *cpu_dai,
+ int tristate)
+{
+ struct ssp_priv *priv = cpu_dai->private_data;
+ struct ssp_device *ssp = priv->dev.ssp;
+ u32 sscr1;
+
+ sscr1 = ssp_read_reg(ssp, SSCR1);
+ if (tristate)
+ sscr1 &= ~SSCR1_TTE;
+ else
+ sscr1 |= SSCR1_TTE;
+ ssp_write_reg(ssp, SSCR1, sscr1);
+
+ return 0;
+}
+
+/*
+ * Set up the SSP DAI format.
+ * The SSP Port must be inactive before calling this function as the
+ * physical interface format is changed.
+ */
+static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
+ unsigned int fmt)
+{
+ struct ssp_priv *priv = cpu_dai->private_data;
+ struct ssp_device *ssp = priv->dev.ssp;
+ u32 sscr0;
+ u32 sscr1;
+ u32 sspsp;
+
+ /* reset port settings */
+ sscr0 = ssp_read_reg(ssp, SSCR0) &
+ (SSCR0_ECS | SSCR0_NCS | SSCR0_MOD | SSCR0_ADC);
+ sscr1 = SSCR1_RxTresh(8) | SSCR1_TxTresh(7);
+ sspsp = 0;
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ sscr1 |= SSCR1_SCLKDIR | SSCR1_SFRMDIR;
+ break;
+ case SND_SOC_DAIFMT_CBM_CFS:
+ sscr1 |= SSCR1_SCLKDIR;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ssp_write_reg(ssp, SSCR0, sscr0);
+ ssp_write_reg(ssp, SSCR1, sscr1);
+ ssp_write_reg(ssp, SSPSP, sspsp);
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ sscr0 |= SSCR0_MOD | SSCR0_PSP;
+ sscr1 |= SSCR1_RWOT | SSCR1_TRAIL;
+
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ sspsp |= SSPSP_FSRT;
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ sspsp |= SSPSP_SFRMP | SSPSP_FSRT;
+ break;
+ case SND_SOC_DAIFMT_IB_IF:
+ sspsp |= SSPSP_SFRMP;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+
+ case SND_SOC_DAIFMT_DSP_A:
+ sspsp |= SSPSP_FSRT;
+ case SND_SOC_DAIFMT_DSP_B:
+ sscr0 |= SSCR0_MOD | SSCR0_PSP;
+ sscr1 |= SSCR1_TRAIL | SSCR1_RWOT;
+
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ sspsp |= SSPSP_SFRMP;
+ break;
+ case SND_SOC_DAIFMT_IB_IF:
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ ssp_write_reg(ssp, SSCR0, sscr0);
+ ssp_write_reg(ssp, SSCR1, sscr1);
+ ssp_write_reg(ssp, SSPSP, sspsp);
+
+ dump_registers(ssp);
+
+ /* Since we are configuring the timings for the format by hand
+ * we have to defer some things until hw_params() where we
+ * know parameters like the sample size.
+ */
+ priv->dai_fmt = fmt;
+
+ return 0;
+}
+
+/*
+ * Set the SSP audio DMA parameters and sample size.
+ * Can be called multiple times by oss emulation.
+ */
+static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+ struct ssp_priv *priv = cpu_dai->private_data;
+ struct ssp_device *ssp = priv->dev.ssp;
+ int dma = 0, chn = params_channels(params);
+ u32 sscr0;
+ u32 sspsp;
+ int width = snd_pcm_format_physical_width(params_format(params));
+
+ /* select correct DMA params */
+ if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
+ dma = 1; /* capture DMA offset is 1,3 */
+ if (chn == 2)
+ dma += 2; /* stereo DMA offset is 2, mono is 0 */
+ cpu_dai->dma_data = ssp_dma_params[cpu_dai->id][dma];
+
+ dev_dbg(&ssp->pdev->dev, "pxa_ssp_hw_params: dma %d\n", dma);
+
+ /* we can only change the settings if the port is not in use */
+ if (ssp_read_reg(ssp, SSCR0) & SSCR0_SSE)
+ return 0;
+
+ /* clear selected SSP bits */
+ sscr0 = ssp_read_reg(ssp, SSCR0) & ~(SSCR0_DSS | SSCR0_EDSS);
+ ssp_write_reg(ssp, SSCR0, sscr0);
+
+ /* bit size */
+ sscr0 = ssp_read_reg(ssp, SSCR0);
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+#ifdef CONFIG_PXA3xx
+ if (cpu_is_pxa3xx())
+ sscr0 |= SSCR0_FPCKE;
+#endif
+ sscr0 |= SSCR0_DataSize(16);
+ if (params_channels(params) > 1)
+ sscr0 |= SSCR0_EDSS;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ sscr0 |= (SSCR0_EDSS | SSCR0_DataSize(8));
+ /* we must be in network mode (2 slots) for 24 bit stereo */
+ break;
+ case SNDRV_PCM_FORMAT_S32_LE:
+ sscr0 |= (SSCR0_EDSS | SSCR0_DataSize(16));
+ /* we must be in network mode (2 slots) for 32 bit stereo */
+ break;
+ }
+ ssp_write_reg(ssp, SSCR0, sscr0);
+
+ switch (priv->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ /* Cleared when the DAI format is set */
+ sspsp = ssp_read_reg(ssp, SSPSP) | SSPSP_SFRMWDTH(width);
+ ssp_write_reg(ssp, SSPSP, sspsp);
+ break;
+ default:
+ break;
+ }
+
+ /* We always use a network mode so we always require TDM slots
+ * - complain loudly and fail if they've not been set up yet.
+ */
+ if (!(ssp_read_reg(ssp, SSTSA) & 0xf)) {
+ dev_err(&ssp->pdev->dev, "No TDM timeslot configured\n");
+ return -EINVAL;
+ }
+
+ dump_registers(ssp);
+
+ return 0;
+}
+
+static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+ int ret = 0;
+ struct ssp_priv *priv = cpu_dai->private_data;
+ struct ssp_device *ssp = priv->dev.ssp;
+ int val;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_RESUME:
+ ssp_enable(&priv->dev);
+ break;
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ val = ssp_read_reg(ssp, SSCR1);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ val |= SSCR1_TSRE;
+ else
+ val |= SSCR1_RSRE;
+ ssp_write_reg(ssp, SSCR1, val);
+ val = ssp_read_reg(ssp, SSSR);
+ ssp_write_reg(ssp, SSSR, val);
+ break;
+ case SNDRV_PCM_TRIGGER_START:
+ val = ssp_read_reg(ssp, SSCR1);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ val |= SSCR1_TSRE;
+ else
+ val |= SSCR1_RSRE;
+ ssp_write_reg(ssp, SSCR1, val);
+ ssp_enable(&priv->dev);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ val = ssp_read_reg(ssp, SSCR1);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ val &= ~SSCR1_TSRE;
+ else
+ val &= ~SSCR1_RSRE;
+ ssp_write_reg(ssp, SSCR1, val);
+ break;
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ ssp_disable(&priv->dev);
+ break;
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ val = ssp_read_reg(ssp, SSCR1);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ val &= ~SSCR1_TSRE;
+ else
+ val &= ~SSCR1_RSRE;
+ ssp_write_reg(ssp, SSCR1, val);
+ break;
+
+ default:
+ ret = -EINVAL;
+ }
+
+ dump_registers(ssp);
+
+ return ret;
+}
+
+static int pxa_ssp_probe(struct platform_device *pdev,
+ struct snd_soc_dai *dai)
+{
+ struct ssp_priv *priv;
+ int ret;
+
+ priv = kzalloc(sizeof(struct ssp_priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->dev.ssp = ssp_request(dai->id, "SoC audio");
+ if (priv->dev.ssp == NULL) {
+ ret = -ENODEV;
+ goto err_priv;
+ }
+
+ dai->private_data = priv;
+
+ return 0;
+
+err_priv:
+ kfree(priv);
+ return ret;
+}
+
+static void pxa_ssp_remove(struct platform_device *pdev,
+ struct snd_soc_dai *dai)
+{
+ struct ssp_priv *priv = dai->private_data;
+ ssp_free(priv->dev.ssp);
+}
+
+#define PXA_SSP_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
+ SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \
+ SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | \
+ SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
+
+#define PXA_SSP_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+ SNDRV_PCM_FMTBIT_S24_LE | \
+ SNDRV_PCM_FMTBIT_S32_LE)
+
+struct snd_soc_dai pxa_ssp_dai[] = {
+ {
+ .name = "pxa2xx-ssp1",
+ .id = 0,
+ .probe = pxa_ssp_probe,
+ .remove = pxa_ssp_remove,
+ .suspend = pxa_ssp_suspend,
+ .resume = pxa_ssp_resume,
+ .playback = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = PXA_SSP_RATES,
+ .formats = PXA_SSP_FORMATS,
+ },
+ .capture = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = PXA_SSP_RATES,
+ .formats = PXA_SSP_FORMATS,
+ },
+ .ops = {
+ .startup = pxa_ssp_startup,
+ .shutdown = pxa_ssp_shutdown,
+ .trigger = pxa_ssp_trigger,
+ .hw_params = pxa_ssp_hw_params,
+ .set_sysclk = pxa_ssp_set_dai_sysclk,
+ .set_clkdiv = pxa_ssp_set_dai_clkdiv,
+ .set_pll = pxa_ssp_set_dai_pll,
+ .set_fmt = pxa_ssp_set_dai_fmt,
+ .set_tdm_slot = pxa_ssp_set_dai_tdm_slot,
+ .set_tristate = pxa_ssp_set_dai_tristate,
+ },
+ },
+ { .name = "pxa2xx-ssp2",
+ .id = 1,
+ .probe = pxa_ssp_probe,
+ .remove = pxa_ssp_remove,
+ .suspend = pxa_ssp_suspend,
+ .resume = pxa_ssp_resume,
+ .playback = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = PXA_SSP_RATES,
+ .formats = PXA_SSP_FORMATS,
+ },
+ .capture = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = PXA_SSP_RATES,
+ .formats = PXA_SSP_FORMATS,
+ },
+ .ops = {
+ .startup = pxa_ssp_startup,
+ .shutdown = pxa_ssp_shutdown,
+ .trigger = pxa_ssp_trigger,
+ .hw_params = pxa_ssp_hw_params,
+ .set_sysclk = pxa_ssp_set_dai_sysclk,
+ .set_clkdiv = pxa_ssp_set_dai_clkdiv,
+ .set_pll = pxa_ssp_set_dai_pll,
+ .set_fmt = pxa_ssp_set_dai_fmt,
+ .set_tdm_slot = pxa_ssp_set_dai_tdm_slot,
+ .set_tristate = pxa_ssp_set_dai_tristate,
+ },
+ },
+ {
+ .name = "pxa2xx-ssp3",
+ .id = 2,
+ .probe = pxa_ssp_probe,
+ .remove = pxa_ssp_remove,
+ .suspend = pxa_ssp_suspend,
+ .resume = pxa_ssp_resume,
+ .playback = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = PXA_SSP_RATES,
+ .formats = PXA_SSP_FORMATS,
+ },
+ .capture = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = PXA_SSP_RATES,
+ .formats = PXA_SSP_FORMATS,
+ },
+ .ops = {
+ .startup = pxa_ssp_startup,
+ .shutdown = pxa_ssp_shutdown,
+ .trigger = pxa_ssp_trigger,
+ .hw_params = pxa_ssp_hw_params,
+ .set_sysclk = pxa_ssp_set_dai_sysclk,
+ .set_clkdiv = pxa_ssp_set_dai_clkdiv,
+ .set_pll = pxa_ssp_set_dai_pll,
+ .set_fmt = pxa_ssp_set_dai_fmt,
+ .set_tdm_slot = pxa_ssp_set_dai_tdm_slot,
+ .set_tristate = pxa_ssp_set_dai_tristate,
+ },
+ },
+ {
+ .name = "pxa2xx-ssp4",
+ .id = 3,
+ .probe = pxa_ssp_probe,
+ .remove = pxa_ssp_remove,
+ .suspend = pxa_ssp_suspend,
+ .resume = pxa_ssp_resume,
+ .playback = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = PXA_SSP_RATES,
+ .formats = PXA_SSP_FORMATS,
+ },
+ .capture = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = PXA_SSP_RATES,
+ .formats = PXA_SSP_FORMATS,
+ },
+ .ops = {
+ .startup = pxa_ssp_startup,
+ .shutdown = pxa_ssp_shutdown,
+ .trigger = pxa_ssp_trigger,
+ .hw_params = pxa_ssp_hw_params,
+ .set_sysclk = pxa_ssp_set_dai_sysclk,
+ .set_clkdiv = pxa_ssp_set_dai_clkdiv,
+ .set_pll = pxa_ssp_set_dai_pll,
+ .set_fmt = pxa_ssp_set_dai_fmt,
+ .set_tdm_slot = pxa_ssp_set_dai_tdm_slot,
+ .set_tristate = pxa_ssp_set_dai_tristate,
+ },
+ },
+};
+EXPORT_SYMBOL_GPL(pxa_ssp_dai);
+
+static int __init pxa_ssp_init(void)
+{
+ return snd_soc_register_dais(pxa_ssp_dai, ARRAY_SIZE(pxa_ssp_dai));
+}
+module_init(pxa_ssp_init);
+
+static void __exit pxa_ssp_exit(void)
+{
+ snd_soc_unregister_dais(pxa_ssp_dai, ARRAY_SIZE(pxa_ssp_dai));
+}
+module_exit(pxa_ssp_exit);
+
+/* Module information */
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_DESCRIPTION("PXA SSP/PCM SoC Interface");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/pxa-ssp.h b/sound/soc/pxa/pxa-ssp.h
new file mode 100644
index 00000000000..91deadd5567
--- /dev/null
+++ b/sound/soc/pxa/pxa-ssp.h
@@ -0,0 +1,47 @@
+/*
+ * ASoC PXA SSP port support
+ *
+ * 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 _PXA_SSP_H
+#define _PXA_SSP_H
+
+/* pxa DAI SSP IDs */
+#define PXA_DAI_SSP1 0
+#define PXA_DAI_SSP2 1
+#define PXA_DAI_SSP3 2
+#define PXA_DAI_SSP4 3
+
+/* SSP clock sources */
+#define PXA_SSP_CLK_PLL 0
+#define PXA_SSP_CLK_EXT 1
+#define PXA_SSP_CLK_NET 2
+#define PXA_SSP_CLK_AUDIO 3
+#define PXA_SSP_CLK_NET_PLL 4
+
+/* SSP audio dividers */
+#define PXA_SSP_AUDIO_DIV_ACDS 0
+#define PXA_SSP_AUDIO_DIV_SCDB 1
+#define PXA_SSP_DIV_SCR 2
+
+/* SSP ACDS audio dividers values */
+#define PXA_SSP_CLK_AUDIO_DIV_1 0
+#define PXA_SSP_CLK_AUDIO_DIV_2 1
+#define PXA_SSP_CLK_AUDIO_DIV_4 2
+#define PXA_SSP_CLK_AUDIO_DIV_8 3
+#define PXA_SSP_CLK_AUDIO_DIV_16 4
+#define PXA_SSP_CLK_AUDIO_DIV_32 5
+
+/* SSP divider bypass */
+#define PXA_SSP_CLK_SCDB_4 0
+#define PXA_SSP_CLK_SCDB_1 1
+#define PXA_SSP_CLK_SCDB_8 2
+
+#define PXA_SSP_PLL_OUT 0
+
+extern struct snd_soc_dai pxa_ssp_dai[4];
+
+#endif
diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c
index a7a3a9c5c6f..780db6757ad 100644
--- a/sound/soc/pxa/pxa2xx-ac97.c
+++ b/sound/soc/pxa/pxa2xx-ac97.c
@@ -87,14 +87,12 @@ static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_mic_mono_in = {
};
#ifdef CONFIG_PM
-static int pxa2xx_ac97_suspend(struct platform_device *pdev,
- struct snd_soc_dai *dai)
+static int pxa2xx_ac97_suspend(struct snd_soc_dai *dai)
{
return pxa2xx_ac97_hw_suspend();
}
-static int pxa2xx_ac97_resume(struct platform_device *pdev,
- struct snd_soc_dai *dai)
+static int pxa2xx_ac97_resume(struct snd_soc_dai *dai)
{
return pxa2xx_ac97_hw_resume();
}
@@ -117,7 +115,8 @@ static void pxa2xx_ac97_remove(struct platform_device *pdev,
}
static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
@@ -131,7 +130,8 @@ static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream,
}
static int pxa2xx_ac97_hw_aux_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
@@ -145,7 +145,8 @@ static int pxa2xx_ac97_hw_aux_params(struct snd_pcm_substream *substream,
}
static int pxa2xx_ac97_hw_mic_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
@@ -170,7 +171,7 @@ struct snd_soc_dai pxa_ac97_dai[] = {
{
.name = "pxa2xx-ac97",
.id = 0,
- .type = SND_SOC_DAI_AC97,
+ .ac97_control = 1,
.probe = pxa2xx_ac97_probe,
.remove = pxa2xx_ac97_remove,
.suspend = pxa2xx_ac97_suspend,
@@ -193,7 +194,7 @@ struct snd_soc_dai pxa_ac97_dai[] = {
{
.name = "pxa2xx-ac97-aux",
.id = 1,
- .type = SND_SOC_DAI_AC97,
+ .ac97_control = 1,
.playback = {
.stream_name = "AC97 Aux Playback",
.channels_min = 1,
@@ -212,7 +213,7 @@ struct snd_soc_dai pxa_ac97_dai[] = {
{
.name = "pxa2xx-ac97-mic",
.id = 2,
- .type = SND_SOC_DAI_AC97,
+ .ac97_control = 1,
.capture = {
.stream_name = "AC97 Mic Capture",
.channels_min = 1,
@@ -227,6 +228,18 @@ struct snd_soc_dai pxa_ac97_dai[] = {
EXPORT_SYMBOL_GPL(pxa_ac97_dai);
EXPORT_SYMBOL_GPL(soc_ac97_ops);
+static int __init pxa_ac97_init(void)
+{
+ return snd_soc_register_dais(pxa_ac97_dai, ARRAY_SIZE(pxa_ac97_dai));
+}
+module_init(pxa_ac97_init);
+
+static void __exit pxa_ac97_exit(void)
+{
+ snd_soc_unregister_dais(pxa_ac97_dai, ARRAY_SIZE(pxa_ac97_dai));
+}
+module_exit(pxa_ac97_exit);
+
MODULE_AUTHOR("Nicolas Pitre");
MODULE_DESCRIPTION("AC97 driver for the Intel PXA2xx chip");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c
index e758034db5c..517991fb109 100644
--- a/sound/soc/pxa/pxa2xx-i2s.c
+++ b/sound/soc/pxa/pxa2xx-i2s.c
@@ -121,7 +121,8 @@ static struct pxa2xx_gpio gpio_bus[] = {
},
};
-static int pxa2xx_i2s_startup(struct snd_pcm_substream *substream)
+static int pxa2xx_i2s_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
@@ -187,7 +188,8 @@ static int pxa2xx_i2s_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
}
static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
@@ -248,7 +250,8 @@ static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream,
return 0;
}
-static int pxa2xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd)
+static int pxa2xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
{
int ret = 0;
@@ -269,7 +272,8 @@ static int pxa2xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd)
return ret;
}
-static void pxa2xx_i2s_shutdown(struct snd_pcm_substream *substream)
+static void pxa2xx_i2s_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
SACR1 |= SACR1_DRPL;
@@ -289,8 +293,7 @@ static void pxa2xx_i2s_shutdown(struct snd_pcm_substream *substream)
}
#ifdef CONFIG_PM
-static int pxa2xx_i2s_suspend(struct platform_device *dev,
- struct snd_soc_dai *dai)
+static int pxa2xx_i2s_suspend(struct snd_soc_dai *dai)
{
if (!dai->active)
return 0;
@@ -307,8 +310,7 @@ static int pxa2xx_i2s_suspend(struct platform_device *dev,
return 0;
}
-static int pxa2xx_i2s_resume(struct platform_device *pdev,
- struct snd_soc_dai *dai)
+static int pxa2xx_i2s_resume(struct snd_soc_dai *dai)
{
if (!dai->active)
return 0;
@@ -336,7 +338,6 @@ static int pxa2xx_i2s_resume(struct platform_device *pdev,
struct snd_soc_dai pxa_i2s_dai = {
.name = "pxa2xx-i2s",
.id = 0,
- .type = SND_SOC_DAI_I2S,
.suspend = pxa2xx_i2s_suspend,
.resume = pxa2xx_i2s_resume,
.playback = {
@@ -353,8 +354,7 @@ struct snd_soc_dai pxa_i2s_dai = {
.startup = pxa2xx_i2s_startup,
.shutdown = pxa2xx_i2s_shutdown,
.trigger = pxa2xx_i2s_trigger,
- .hw_params = pxa2xx_i2s_hw_params,},
- .dai_ops = {
+ .hw_params = pxa2xx_i2s_hw_params,
.set_fmt = pxa2xx_i2s_set_dai_fmt,
.set_sysclk = pxa2xx_i2s_set_dai_sysclk,
},
@@ -364,12 +364,23 @@ EXPORT_SYMBOL_GPL(pxa_i2s_dai);
static int pxa2xx_i2s_probe(struct platform_device *dev)
{
+ int ret;
+
clk_i2s = clk_get(&dev->dev, "I2SCLK");
- return IS_ERR(clk_i2s) ? PTR_ERR(clk_i2s) : 0;
+ if (IS_ERR(clk_i2s))
+ return PTR_ERR(clk_i2s);
+
+ pxa_i2s_dai.dev = &dev->dev;
+ ret = snd_soc_register_dai(&pxa_i2s_dai);
+ if (ret != 0)
+ clk_put(clk_i2s);
+
+ return ret;
}
static int __devexit pxa2xx_i2s_remove(struct platform_device *dev)
{
+ snd_soc_unregister_dai(&pxa_i2s_dai);
clk_put(clk_i2s);
clk_i2s = ERR_PTR(-ENOENT);
return 0;
diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c
index afcd892cd2f..c670d08e7c9 100644
--- a/sound/soc/pxa/pxa2xx-pcm.c
+++ b/sound/soc/pxa/pxa2xx-pcm.c
@@ -69,7 +69,7 @@ static int pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream)
return 0;
}
-struct snd_pcm_ops pxa2xx_pcm_ops = {
+static struct snd_pcm_ops pxa2xx_pcm_ops = {
.open = __pxa2xx_pcm_open,
.close = __pxa2xx_pcm_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -118,6 +118,18 @@ struct snd_soc_platform pxa2xx_soc_platform = {
};
EXPORT_SYMBOL_GPL(pxa2xx_soc_platform);
+static int __init pxa2xx_soc_platform_init(void)
+{
+ return snd_soc_register_platform(&pxa2xx_soc_platform);
+}
+module_init(pxa2xx_soc_platform_init);
+
+static void __exit pxa2xx_soc_platform_exit(void)
+{
+ snd_soc_unregister_platform(&pxa2xx_soc_platform);
+}
+module_exit(pxa2xx_soc_platform_exit);
+
MODULE_AUTHOR("Nicolas Pitre");
MODULE_DESCRIPTION("Intel PXA2xx PCM DMA module");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c
index d307b6757e9..a3b9e6bdf97 100644
--- a/sound/soc/pxa/spitz.c
+++ b/sound/soc/pxa/spitz.c
@@ -319,8 +319,9 @@ static struct snd_soc_dai_link spitz_dai = {
};
/* spitz audio machine driver */
-static struct snd_soc_machine snd_soc_machine_spitz = {
+static struct snd_soc_card snd_soc_spitz = {
.name = "Spitz",
+ .platform = &pxa2xx_soc_platform,
.dai_link = &spitz_dai,
.num_links = 1,
};
@@ -333,8 +334,7 @@ static struct wm8750_setup_data spitz_wm8750_setup = {
/* spitz audio subsystem */
static struct snd_soc_device spitz_snd_devdata = {
- .machine = &snd_soc_machine_spitz,
- .platform = &pxa2xx_soc_platform,
+ .card = &snd_soc_spitz,
.codec_dev = &soc_codec_dev_wm8750,
.codec_data = &spitz_wm8750_setup,
};
diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c
index afefe41b8c4..c77194f74c9 100644
--- a/sound/soc/pxa/tosa.c
+++ b/sound/soc/pxa/tosa.c
@@ -38,7 +38,7 @@
#include "pxa2xx-pcm.h"
#include "pxa2xx-ac97.h"
-static struct snd_soc_machine tosa;
+static struct snd_soc_card tosa;
#define TOSA_HP 0
#define TOSA_MIC_INT 1
@@ -230,15 +230,37 @@ static struct snd_soc_dai_link tosa_dai[] = {
},
};
-static struct snd_soc_machine tosa = {
+static int tosa_probe(struct platform_device *dev)
+{
+ int ret;
+
+ ret = gpio_request(TOSA_GPIO_L_MUTE, "Headphone Jack");
+ if (ret)
+ return ret;
+ ret = gpio_direction_output(TOSA_GPIO_L_MUTE, 0);
+ if (ret)
+ gpio_free(TOSA_GPIO_L_MUTE);
+
+ return ret;
+}
+
+static int tosa_remove(struct platform_device *dev)
+{
+ gpio_free(TOSA_GPIO_L_MUTE);
+ return 0;
+}
+
+static struct snd_soc_card tosa = {
.name = "Tosa",
+ .platform = &pxa2xx_soc_platform,
.dai_link = tosa_dai,
.num_links = ARRAY_SIZE(tosa_dai),
+ .probe = tosa_probe,
+ .remove = tosa_remove,
};
static struct snd_soc_device tosa_snd_devdata = {
- .machine = &tosa,
- .platform = &pxa2xx_soc_platform,
+ .card = &tosa,
.codec_dev = &soc_codec_dev_wm9712,
};
@@ -251,11 +273,6 @@ static int __init tosa_init(void)
if (!machine_is_tosa())
return -ENODEV;
- ret = gpio_request(TOSA_GPIO_L_MUTE, "Headphone Jack");
- if (ret)
- return ret;
- gpio_direction_output(TOSA_GPIO_L_MUTE, 0);
-
tosa_snd_device = platform_device_alloc("soc-audio", -1);
if (!tosa_snd_device) {
ret = -ENOMEM;
@@ -272,15 +289,12 @@ static int __init tosa_init(void)
platform_device_put(tosa_snd_device);
err_alloc:
- gpio_free(TOSA_GPIO_L_MUTE);
-
return ret;
}
static void __exit tosa_exit(void)
{
platform_device_unregister(tosa_snd_device);
- gpio_free(TOSA_GPIO_L_MUTE);
}
module_init(tosa_init);
diff --git a/sound/soc/pxa/zylonite.c b/sound/soc/pxa/zylonite.c
new file mode 100644
index 00000000000..f8e9ecd589d
--- /dev/null
+++ b/sound/soc/pxa/zylonite.c
@@ -0,0 +1,219 @@
+/*
+ * zylonite.c -- SoC audio for Zylonite
+ *
+ * Copyright 2008 Wolfson Microelectronics PLC.
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include "../codecs/wm9713.h"
+#include "pxa2xx-pcm.h"
+#include "pxa2xx-ac97.h"
+#include "pxa-ssp.h"
+
+static struct snd_soc_card zylonite;
+
+static const struct snd_soc_dapm_widget zylonite_dapm_widgets[] = {
+ SND_SOC_DAPM_HP("Headphone", NULL),
+ SND_SOC_DAPM_MIC("Headset Microphone", NULL),
+ SND_SOC_DAPM_MIC("Handset Microphone", NULL),
+ SND_SOC_DAPM_SPK("Multiactor", NULL),
+ SND_SOC_DAPM_SPK("Headset Earpiece", NULL),
+};
+
+/* Currently supported audio map */
+static const struct snd_soc_dapm_route audio_map[] = {
+
+ /* Headphone output connected to HPL/HPR */
+ { "Headphone", NULL, "HPL" },
+ { "Headphone", NULL, "HPR" },
+
+ /* On-board earpiece */
+ { "Headset Earpiece", NULL, "OUT3" },
+
+ /* Headphone mic */
+ { "MIC2A", NULL, "Mic Bias" },
+ { "Mic Bias", NULL, "Headset Microphone" },
+
+ /* On-board mic */
+ { "MIC1", NULL, "Mic Bias" },
+ { "Mic Bias", NULL, "Handset Microphone" },
+
+ /* Multiactor differentially connected over SPKL/SPKR */
+ { "Multiactor", NULL, "SPKL" },
+ { "Multiactor", NULL, "SPKR" },
+};
+
+static int zylonite_wm9713_init(struct snd_soc_codec *codec)
+{
+ /* Currently we only support use of the AC97 clock here. If
+ * CLK_POUT is selected by SW15 then the clock API will need
+ * to be used to request and enable it here.
+ */
+
+ snd_soc_dapm_new_controls(codec, zylonite_dapm_widgets,
+ ARRAY_SIZE(zylonite_dapm_widgets));
+
+ snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+
+ /* Static setup for now */
+ snd_soc_dapm_enable_pin(codec, "Headphone");
+ snd_soc_dapm_enable_pin(codec, "Headset Earpiece");
+
+ snd_soc_dapm_sync(codec);
+ return 0;
+}
+
+static int zylonite_voice_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+ unsigned int pll_out = 0;
+ unsigned int acds = 0;
+ unsigned int wm9713_div = 0;
+ int ret = 0;
+
+ switch (params_rate(params)) {
+ case 8000:
+ wm9713_div = 12;
+ pll_out = 2048000;
+ break;
+ case 16000:
+ wm9713_div = 6;
+ pll_out = 4096000;
+ break;
+ case 48000:
+ default:
+ wm9713_div = 2;
+ pll_out = 12288000;
+ acds = 1;
+ break;
+ }
+
+ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_dai_set_tdm_slot(cpu_dai,
+ params_channels(params),
+ params_channels(params));
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_dai_set_pll(cpu_dai, 0, 0, pll_out);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_dai_set_clkdiv(cpu_dai, PXA_SSP_AUDIO_DIV_ACDS, acds);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_AUDIO, 0, 1);
+ if (ret < 0)
+ return ret;
+
+ /* Note that if the PLL is in use the WM9713_PCMCLK_PLL_DIV needs
+ * to be set instead.
+ */
+ ret = snd_soc_dai_set_clkdiv(codec_dai, WM9713_PCMCLK_DIV,
+ WM9713_PCMDIV(wm9713_div));
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static struct snd_soc_ops zylonite_voice_ops = {
+ .hw_params = zylonite_voice_hw_params,
+};
+
+static struct snd_soc_dai_link zylonite_dai[] = {
+{
+ .name = "AC97",
+ .stream_name = "AC97 HiFi",
+ .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI],
+ .codec_dai = &wm9713_dai[WM9713_DAI_AC97_HIFI],
+ .init = zylonite_wm9713_init,
+},
+{
+ .name = "AC97 Aux",
+ .stream_name = "AC97 Aux",
+ .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX],
+ .codec_dai = &wm9713_dai[WM9713_DAI_AC97_AUX],
+},
+{
+ .name = "WM9713 Voice",
+ .stream_name = "WM9713 Voice",
+ .cpu_dai = &pxa_ssp_dai[PXA_DAI_SSP3],
+ .codec_dai = &wm9713_dai[WM9713_DAI_PCM_VOICE],
+ .ops = &zylonite_voice_ops,
+},
+};
+
+static struct snd_soc_card zylonite = {
+ .name = "Zylonite",
+ .platform = &pxa2xx_soc_platform,
+ .dai_link = zylonite_dai,
+ .num_links = ARRAY_SIZE(zylonite_dai),
+};
+
+static struct snd_soc_device zylonite_snd_ac97_devdata = {
+ .card = &zylonite,
+ .codec_dev = &soc_codec_dev_wm9713,
+};
+
+static struct platform_device *zylonite_snd_ac97_device;
+
+static int __init zylonite_init(void)
+{
+ int ret;
+
+ zylonite_snd_ac97_device = platform_device_alloc("soc-audio", -1);
+ if (!zylonite_snd_ac97_device)
+ return -ENOMEM;
+
+ platform_set_drvdata(zylonite_snd_ac97_device,
+ &zylonite_snd_ac97_devdata);
+ zylonite_snd_ac97_devdata.dev = &zylonite_snd_ac97_device->dev;
+
+ ret = platform_device_add(zylonite_snd_ac97_device);
+ if (ret != 0)
+ platform_device_put(zylonite_snd_ac97_device);
+
+ return ret;
+}
+
+static void __exit zylonite_exit(void)
+{
+ platform_device_unregister(zylonite_snd_ac97_device);
+}
+
+module_init(zylonite_init);
+module_exit(zylonite_exit);
+
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_DESCRIPTION("ALSA SoC WM9713 Zylonite");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/Kconfig b/sound/soc/s3c24xx/Kconfig
index b9f2353effe..fcd03acf10f 100644
--- a/sound/soc/s3c24xx/Kconfig
+++ b/sound/soc/s3c24xx/Kconfig
@@ -44,3 +44,8 @@ config SND_S3C24XX_SOC_LN2440SBC_ALC650
Say Y if you want to add support for SoC audio on ln2440sbc
with the ALC650.
+config SND_S3C24XX_SOC_S3C24XX_UDA134X
+ tristate "SoC I2S Audio support UDA134X wired to a S3C24XX"
+ depends on SND_S3C24XX_SOC
+ select SND_S3C24XX_SOC_I2S
+ select SND_SOC_UDA134X
diff --git a/sound/soc/s3c24xx/Makefile b/sound/soc/s3c24xx/Makefile
index 0aa5fb0b970..96b3f3f617d 100644
--- a/sound/soc/s3c24xx/Makefile
+++ b/sound/soc/s3c24xx/Makefile
@@ -13,7 +13,9 @@ obj-$(CONFIG_SND_S3C2412_SOC_I2S) += snd-soc-s3c2412-i2s.o
snd-soc-neo1973-wm8753-objs := neo1973_wm8753.o
snd-soc-smdk2443-wm9710-objs := smdk2443_wm9710.o
snd-soc-ln2440sbc-alc650-objs := ln2440sbc_alc650.o
+snd-soc-s3c24xx-uda134x-objs := s3c24xx_uda134x.o
obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o
obj-$(CONFIG_SND_S3C24XX_SOC_SMDK2443_WM9710) += snd-soc-smdk2443-wm9710.o
obj-$(CONFIG_SND_S3C24XX_SOC_LN2440SBC_ALC650) += snd-soc-ln2440sbc-alc650.o
+obj-$(CONFIG_SND_S3C24XX_SOC_S3C24XX_UDA134X) += snd-soc-s3c24xx-uda134x.o
diff --git a/sound/soc/s3c24xx/ln2440sbc_alc650.c b/sound/soc/s3c24xx/ln2440sbc_alc650.c
index 4eab2c19c45..12c71482d25 100644
--- a/sound/soc/s3c24xx/ln2440sbc_alc650.c
+++ b/sound/soc/s3c24xx/ln2440sbc_alc650.c
@@ -27,7 +27,7 @@
#include "s3c24xx-pcm.h"
#include "s3c24xx-ac97.h"
-static struct snd_soc_machine ln2440sbc;
+static struct snd_soc_card ln2440sbc;
static struct snd_soc_dai_link ln2440sbc_dai[] = {
{
@@ -38,15 +38,15 @@ static struct snd_soc_dai_link ln2440sbc_dai[] = {
},
};
-static struct snd_soc_machine ln2440sbc = {
+static struct snd_soc_card ln2440sbc = {
.name = "LN2440SBC",
+ .platform = &s3c24xx_soc_platform,
.dai_link = ln2440sbc_dai,
.num_links = ARRAY_SIZE(ln2440sbc_dai),
};
static struct snd_soc_device ln2440sbc_snd_ac97_devdata = {
- .machine = &ln2440sbc,
- .platform = &s3c24xx_soc_platform,
+ .card = &ln2440sbc,
.codec_dev = &soc_codec_dev_ac97,
};
diff --git a/sound/soc/s3c24xx/neo1973_wm8753.c b/sound/soc/s3c24xx/neo1973_wm8753.c
index 87ddfefcc2f..45bb12e8ea4 100644
--- a/sound/soc/s3c24xx/neo1973_wm8753.c
+++ b/sound/soc/s3c24xx/neo1973_wm8753.c
@@ -59,7 +59,7 @@
#define NEO_CAPTURE_HEADSET 7
#define NEO_CAPTURE_BLUETOOTH 8
-static struct snd_soc_machine neo1973;
+static struct snd_soc_card neo1973;
static struct i2c_client *i2c;
static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream,
@@ -548,7 +548,6 @@ static int neo1973_wm8753_init(struct snd_soc_codec *codec)
static struct snd_soc_dai bt_dai = {
.name = "Bluetooth",
.id = 0,
- .type = SND_SOC_DAI_PCM,
.playback = {
.channels_min = 1,
.channels_max = 1,
@@ -579,8 +578,9 @@ static struct snd_soc_dai_link neo1973_dai[] = {
},
};
-static struct snd_soc_machine neo1973 = {
+static struct snd_soc_card neo1973 = {
.name = "neo1973",
+ .platform = &s3c24xx_soc_platform,
.dai_link = neo1973_dai,
.num_links = ARRAY_SIZE(neo1973_dai),
};
@@ -591,8 +591,7 @@ static struct wm8753_setup_data neo1973_wm8753_setup = {
};
static struct snd_soc_device neo1973_snd_devdata = {
- .machine = &neo1973,
- .platform = &s3c24xx_soc_platform,
+ .card = &neo1973,
.codec_dev = &soc_codec_dev_wm8753,
.codec_data = &neo1973_wm8753_setup,
};
diff --git a/sound/soc/s3c24xx/s3c2412-i2s.c b/sound/soc/s3c24xx/s3c2412-i2s.c
index ded7d995a92..f3fc0aba0aa 100644
--- a/sound/soc/s3c24xx/s3c2412-i2s.c
+++ b/sound/soc/s3c24xx/s3c2412-i2s.c
@@ -343,7 +343,8 @@ static int s3c2412_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
}
static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
u32 iismod;
@@ -373,7 +374,8 @@ static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream,
return 0;
}
-static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd)
+static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
{
int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
unsigned long irqs;
@@ -647,8 +649,7 @@ static int s3c2412_i2s_probe(struct platform_device *pdev,
}
#ifdef CONFIG_PM
-static int s3c2412_i2s_suspend(struct platform_device *dev,
- struct snd_soc_dai *dai)
+static int s3c2412_i2s_suspend(struct snd_soc_dai *dai)
{
struct s3c2412_i2s_info *i2s = &s3c2412_i2s;
u32 iismod;
@@ -663,25 +664,24 @@ static int s3c2412_i2s_suspend(struct platform_device *dev,
iismod = readl(i2s->regs + S3C2412_IISMOD);
if (iismod & S3C2412_IISCON_RXDMA_ACTIVE)
- dev_warn(&dev->dev, "%s: RXDMA active?\n", __func__);
+ pr_warning("%s: RXDMA active?\n", __func__);
if (iismod & S3C2412_IISCON_TXDMA_ACTIVE)
- dev_warn(&dev->dev, "%s: TXDMA active?\n", __func__);
+ pr_warning("%s: TXDMA active?\n", __func__);
if (iismod & S3C2412_IISCON_IIS_ACTIVE)
- dev_warn(&dev->dev, "%s: IIS active\n", __func__);
+ pr_warning("%s: IIS active\n", __func__);
}
return 0;
}
-static int s3c2412_i2s_resume(struct platform_device *pdev,
- struct snd_soc_dai *dai)
+static int s3c2412_i2s_resume(struct snd_soc_dai *dai)
{
struct s3c2412_i2s_info *i2s = &s3c2412_i2s;
- dev_info(&pdev->dev, "dai_active %d, IISMOD %08x, IISCON %08x\n",
- dai->active, i2s->suspend_iismod, i2s->suspend_iiscon);
+ pr_info("dai_active %d, IISMOD %08x, IISCON %08x\n",
+ dai->active, i2s->suspend_iismod, i2s->suspend_iiscon);
if (dai->active) {
writel(i2s->suspend_iiscon, i2s->regs + S3C2412_IISCON);
@@ -711,7 +711,6 @@ static int s3c2412_i2s_resume(struct platform_device *pdev,
struct snd_soc_dai s3c2412_i2s_dai = {
.name = "s3c2412-i2s",
.id = 0,
- .type = SND_SOC_DAI_I2S,
.probe = s3c2412_i2s_probe,
.suspend = s3c2412_i2s_suspend,
.resume = s3c2412_i2s_resume,
@@ -730,8 +729,6 @@ struct snd_soc_dai s3c2412_i2s_dai = {
.ops = {
.trigger = s3c2412_i2s_trigger,
.hw_params = s3c2412_i2s_hw_params,
- },
- .dai_ops = {
.set_fmt = s3c2412_i2s_set_fmt,
.set_clkdiv = s3c2412_i2s_set_clkdiv,
.set_sysclk = s3c2412_i2s_set_sysclk,
@@ -739,6 +736,19 @@ struct snd_soc_dai s3c2412_i2s_dai = {
};
EXPORT_SYMBOL_GPL(s3c2412_i2s_dai);
+static int __init s3c2412_i2s_init(void)
+{
+ return snd_soc_register_dai(&s3c2412_i2s_dai);
+}
+module_init(s3c2412_i2s_init);
+
+static void __exit s3c2412_i2s_exit(void)
+{
+ snd_soc_unregister_dai(&s3c2412_i2s_dai);
+}
+module_exit(s3c2412_i2s_exit);
+
+
/* Module information */
MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
MODULE_DESCRIPTION("S3C2412 I2S SoC Interface");
diff --git a/sound/soc/s3c24xx/s3c2443-ac97.c b/sound/soc/s3c24xx/s3c2443-ac97.c
index 19c5c3cf5d8..1bfce40bb2e 100644
--- a/sound/soc/s3c24xx/s3c2443-ac97.c
+++ b/sound/soc/s3c24xx/s3c2443-ac97.c
@@ -271,7 +271,8 @@ static void s3c2443_ac97_remove(struct platform_device *pdev,
}
static int s3c2443_ac97_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
@@ -284,7 +285,8 @@ static int s3c2443_ac97_hw_params(struct snd_pcm_substream *substream,
return 0;
}
-static int s3c2443_ac97_trigger(struct snd_pcm_substream *substream, int cmd)
+static int s3c2443_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
{
u32 ac_glbctrl;
@@ -313,7 +315,8 @@ static int s3c2443_ac97_trigger(struct snd_pcm_substream *substream, int cmd)
}
static int s3c2443_ac97_hw_mic_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
@@ -327,7 +330,7 @@ static int s3c2443_ac97_hw_mic_params(struct snd_pcm_substream *substream,
}
static int s3c2443_ac97_mic_trigger(struct snd_pcm_substream *substream,
- int cmd)
+ int cmd, struct snd_soc_dai *dai)
{
u32 ac_glbctrl;
@@ -356,7 +359,7 @@ struct snd_soc_dai s3c2443_ac97_dai[] = {
{
.name = "s3c2443-ac97",
.id = 0,
- .type = SND_SOC_DAI_AC97,
+ .ac97_control = 1,
.probe = s3c2443_ac97_probe,
.remove = s3c2443_ac97_remove,
.playback = {
@@ -378,7 +381,7 @@ struct snd_soc_dai s3c2443_ac97_dai[] = {
{
.name = "pxa2xx-ac97-mic",
.id = 1,
- .type = SND_SOC_DAI_AC97,
+ .ac97_control = 1,
.capture = {
.stream_name = "AC97 Mic Capture",
.channels_min = 1,
@@ -393,6 +396,21 @@ struct snd_soc_dai s3c2443_ac97_dai[] = {
EXPORT_SYMBOL_GPL(s3c2443_ac97_dai);
EXPORT_SYMBOL_GPL(soc_ac97_ops);
+static int __init s3c2443_ac97_init(void)
+{
+ return snd_soc_register_dais(s3c2443_ac97_dai,
+ ARRAY_SIZE(s3c2443_ac97_dai));
+}
+module_init(s3c2443_ac97_init);
+
+static void __exit s3c2443_ac97_exit(void)
+{
+ snd_soc_unregister_dais(s3c2443_ac97_dai,
+ ARRAY_SIZE(s3c2443_ac97_dai));
+}
+module_exit(s3c2443_ac97_exit);
+
+
MODULE_AUTHOR("Graeme Gregory");
MODULE_DESCRIPTION("AC97 driver for the Samsung s3c2443 chip");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/s3c24xx-i2s.c b/sound/soc/s3c24xx/s3c24xx-i2s.c
index ba4476b55fb..6f4d439b57a 100644
--- a/sound/soc/s3c24xx/s3c24xx-i2s.c
+++ b/sound/soc/s3c24xx/s3c24xx-i2s.c
@@ -243,7 +243,8 @@ static int s3c24xx_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
}
static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
u32 iismod;
@@ -261,10 +262,17 @@ static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream,
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S8:
+ iismod &= ~S3C2410_IISMOD_16BIT;
+ ((struct s3c24xx_pcm_dma_params *)
+ rtd->dai->cpu_dai->dma_data)->dma_size = 1;
break;
case SNDRV_PCM_FORMAT_S16_LE:
iismod |= S3C2410_IISMOD_16BIT;
+ ((struct s3c24xx_pcm_dma_params *)
+ rtd->dai->cpu_dai->dma_data)->dma_size = 2;
break;
+ default:
+ return -EINVAL;
}
writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD);
@@ -272,7 +280,8 @@ static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream,
return 0;
}
-static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd)
+static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
{
int ret = 0;
@@ -410,8 +419,7 @@ static int s3c24xx_i2s_probe(struct platform_device *pdev,
}
#ifdef CONFIG_PM
-static int s3c24xx_i2s_suspend(struct platform_device *pdev,
- struct snd_soc_dai *cpu_dai)
+static int s3c24xx_i2s_suspend(struct snd_soc_dai *cpu_dai)
{
DBG("Entered %s\n", __func__);
@@ -425,8 +433,7 @@ static int s3c24xx_i2s_suspend(struct platform_device *pdev,
return 0;
}
-static int s3c24xx_i2s_resume(struct platform_device *pdev,
- struct snd_soc_dai *cpu_dai)
+static int s3c24xx_i2s_resume(struct snd_soc_dai *cpu_dai)
{
DBG("Entered %s\n", __func__);
clk_enable(s3c24xx_i2s.iis_clk);
@@ -452,7 +459,6 @@ static int s3c24xx_i2s_resume(struct platform_device *pdev,
struct snd_soc_dai s3c24xx_i2s_dai = {
.name = "s3c24xx-i2s",
.id = 0,
- .type = SND_SOC_DAI_I2S,
.probe = s3c24xx_i2s_probe,
.suspend = s3c24xx_i2s_suspend,
.resume = s3c24xx_i2s_resume,
@@ -468,8 +474,7 @@ struct snd_soc_dai s3c24xx_i2s_dai = {
.formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,},
.ops = {
.trigger = s3c24xx_i2s_trigger,
- .hw_params = s3c24xx_i2s_hw_params,},
- .dai_ops = {
+ .hw_params = s3c24xx_i2s_hw_params,
.set_fmt = s3c24xx_i2s_set_fmt,
.set_clkdiv = s3c24xx_i2s_set_clkdiv,
.set_sysclk = s3c24xx_i2s_set_sysclk,
@@ -477,6 +482,18 @@ struct snd_soc_dai s3c24xx_i2s_dai = {
};
EXPORT_SYMBOL_GPL(s3c24xx_i2s_dai);
+static int __init s3c24xx_i2s_init(void)
+{
+ return snd_soc_register_dai(&s3c24xx_i2s_dai);
+}
+module_init(s3c24xx_i2s_init);
+
+static void __exit s3c24xx_i2s_exit(void)
+{
+ snd_soc_unregister_dai(&s3c24xx_i2s_dai);
+}
+module_exit(s3c24xx_i2s_exit);
+
/* Module information */
MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
MODULE_DESCRIPTION("s3c24xx I2S SoC Interface");
diff --git a/sound/soc/s3c24xx/s3c24xx-pcm.c b/sound/soc/s3c24xx/s3c24xx-pcm.c
index e13e614bada..7c64d31d067 100644
--- a/sound/soc/s3c24xx/s3c24xx-pcm.c
+++ b/sound/soc/s3c24xx/s3c24xx-pcm.c
@@ -465,6 +465,18 @@ struct snd_soc_platform s3c24xx_soc_platform = {
};
EXPORT_SYMBOL_GPL(s3c24xx_soc_platform);
+static int __init s3c24xx_soc_platform_init(void)
+{
+ return snd_soc_register_platform(&s3c24xx_soc_platform);
+}
+module_init(s3c24xx_soc_platform_init);
+
+static void __exit s3c24xx_soc_platform_exit(void)
+{
+ snd_soc_unregister_platform(&s3c24xx_soc_platform);
+}
+module_exit(s3c24xx_soc_platform_exit);
+
MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
MODULE_DESCRIPTION("Samsung S3C24XX PCM DMA module");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/s3c24xx_uda134x.c b/sound/soc/s3c24xx/s3c24xx_uda134x.c
new file mode 100644
index 00000000000..a0a4d1832a1
--- /dev/null
+++ b/sound/soc/s3c24xx/s3c24xx_uda134x.c
@@ -0,0 +1,373 @@
+/*
+ * Modifications by Christian Pellegrin <chripell@evolware.org>
+ *
+ * s3c24xx_uda134x.c -- S3C24XX_UDA134X ALSA SoC Audio board driver
+ *
+ * Copyright 2007 Dension Audio Systems Ltd.
+ * Author: Zoltan Devai
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/mutex.h>
+#include <linux/gpio.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/s3c24xx_uda134x.h>
+#include <sound/uda134x.h>
+
+#include <asm/plat-s3c24xx/regs-iis.h>
+
+#include "s3c24xx-pcm.h"
+#include "s3c24xx-i2s.h"
+#include "../codecs/uda134x.h"
+
+
+/* #define ENFORCE_RATES 1 */
+/*
+ Unfortunately the S3C24XX in master mode has a limited capacity of
+ generating the clock for the codec. If you define this only rates
+ that are really available will be enforced. But be careful, most
+ user level application just want the usual sampling frequencies (8,
+ 11.025, 22.050, 44.1 kHz) and anyway resampling is a costly
+ operation for embedded systems. So if you aren't very lucky or your
+ hardware engineer wasn't very forward-looking it's better to leave
+ this undefined. If you do so an approximate value for the requested
+ sampling rate in the range -/+ 5% will be chosen. If this in not
+ possible an error will be returned.
+*/
+
+static struct clk *xtal;
+static struct clk *pclk;
+/* this is need because we don't have a place where to keep the
+ * pointers to the clocks in each substream. We get the clocks only
+ * when we are actually using them so we don't block stuff like
+ * frequency change or oscillator power-off */
+static int clk_users;
+static DEFINE_MUTEX(clk_lock);
+
+static unsigned int rates[33 * 2];
+#ifdef ENFORCE_RATES
+static struct snd_pcm_hw_constraint_list hw_constraints_rates = {
+ .count = ARRAY_SIZE(rates),
+ .list = rates,
+ .mask = 0,
+};
+#endif
+
+static struct platform_device *s3c24xx_uda134x_snd_device;
+
+static int s3c24xx_uda134x_startup(struct snd_pcm_substream *substream)
+{
+ int ret = 0;
+#ifdef ENFORCE_RATES
+ struct snd_pcm_runtime *runtime = substream->runtime;;
+#endif
+
+ mutex_lock(&clk_lock);
+ pr_debug("%s %d\n", __func__, clk_users);
+ if (clk_users == 0) {
+ xtal = clk_get(&s3c24xx_uda134x_snd_device->dev, "xtal");
+ if (!xtal) {
+ printk(KERN_ERR "%s cannot get xtal\n", __func__);
+ ret = -EBUSY;
+ } else {
+ pclk = clk_get(&s3c24xx_uda134x_snd_device->dev,
+ "pclk");
+ if (!pclk) {
+ printk(KERN_ERR "%s cannot get pclk\n",
+ __func__);
+ clk_put(xtal);
+ ret = -EBUSY;
+ }
+ }
+ if (!ret) {
+ int i, j;
+
+ for (i = 0; i < 2; i++) {
+ int fs = i ? 256 : 384;
+
+ rates[i*33] = clk_get_rate(xtal) / fs;
+ for (j = 1; j < 33; j++)
+ rates[i*33 + j] = clk_get_rate(pclk) /
+ (j * fs);
+ }
+ }
+ }
+ clk_users += 1;
+ mutex_unlock(&clk_lock);
+ if (!ret) {
+#ifdef ENFORCE_RATES
+ ret = snd_pcm_hw_constraint_list(runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE,
+ &hw_constraints_rates);
+ if (ret < 0)
+ printk(KERN_ERR "%s cannot set constraints\n",
+ __func__);
+#endif
+ }
+ return ret;
+}
+
+static void s3c24xx_uda134x_shutdown(struct snd_pcm_substream *substream)
+{
+ mutex_lock(&clk_lock);
+ pr_debug("%s %d\n", __func__, clk_users);
+ clk_users -= 1;
+ if (clk_users == 0) {
+ clk_put(xtal);
+ xtal = NULL;
+ clk_put(pclk);
+ pclk = NULL;
+ }
+ mutex_unlock(&clk_lock);
+}
+
+static int s3c24xx_uda134x_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+ unsigned int clk = 0;
+ int ret = 0;
+ int clk_source, fs_mode;
+ unsigned long rate = params_rate(params);
+ long err, cerr;
+ unsigned int div;
+ int i, bi;
+
+ err = 999999;
+ bi = 0;
+ for (i = 0; i < 2*33; i++) {
+ cerr = rates[i] - rate;
+ if (cerr < 0)
+ cerr = -cerr;
+ if (cerr < err) {
+ err = cerr;
+ bi = i;
+ }
+ }
+ if (bi / 33 == 1)
+ fs_mode = S3C2410_IISMOD_256FS;
+ else
+ fs_mode = S3C2410_IISMOD_384FS;
+ if (bi % 33 == 0) {
+ clk_source = S3C24XX_CLKSRC_MPLL;
+ div = 1;
+ } else {
+ clk_source = S3C24XX_CLKSRC_PCLK;
+ div = bi % 33;
+ }
+ pr_debug("%s desired rate %lu, %d\n", __func__, rate, bi);
+
+ clk = (fs_mode == S3C2410_IISMOD_384FS ? 384 : 256) * rate;
+ pr_debug("%s will use: %s %s %d sysclk %d err %ld\n", __func__,
+ fs_mode == S3C2410_IISMOD_384FS ? "384FS" : "256FS",
+ clk_source == S3C24XX_CLKSRC_MPLL ? "MPLLin" : "PCLK",
+ div, clk, err);
+
+ if ((err * 100 / rate) > 5) {
+ printk(KERN_ERR "S3C24XX_UDA134X: effective frequency "
+ "too different from desired (%ld%%)\n",
+ err * 100 / rate);
+ return -EINVAL;
+ }
+
+ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_dai_set_sysclk(cpu_dai, clk_source , clk,
+ SND_SOC_CLOCK_IN);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK, fs_mode);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_BCLK,
+ S3C2410_IISMOD_32FS);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER,
+ S3C24XX_PRESCALE(div, div));
+ if (ret < 0)
+ return ret;
+
+ /* set the codec system clock for DAC and ADC */
+ ret = snd_soc_dai_set_sysclk(codec_dai, 0, clk,
+ SND_SOC_CLOCK_OUT);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static struct snd_soc_ops s3c24xx_uda134x_ops = {
+ .startup = s3c24xx_uda134x_startup,
+ .shutdown = s3c24xx_uda134x_shutdown,
+ .hw_params = s3c24xx_uda134x_hw_params,
+};
+
+static struct snd_soc_dai_link s3c24xx_uda134x_dai_link = {
+ .name = "UDA134X",
+ .stream_name = "UDA134X",
+ .codec_dai = &uda134x_dai,
+ .cpu_dai = &s3c24xx_i2s_dai,
+ .ops = &s3c24xx_uda134x_ops,
+};
+
+static struct snd_soc_card snd_soc_s3c24xx_uda134x = {
+ .name = "S3C24XX_UDA134X",
+ .platform = &s3c24xx_soc_platform,
+ .dai_link = &s3c24xx_uda134x_dai_link,
+ .num_links = 1,
+};
+
+static struct s3c24xx_uda134x_platform_data *s3c24xx_uda134x_l3_pins;
+
+static void setdat(int v)
+{
+ gpio_set_value(s3c24xx_uda134x_l3_pins->l3_data, v > 0);
+}
+
+static void setclk(int v)
+{
+ gpio_set_value(s3c24xx_uda134x_l3_pins->l3_clk, v > 0);
+}
+
+static void setmode(int v)
+{
+ gpio_set_value(s3c24xx_uda134x_l3_pins->l3_mode, v > 0);
+}
+
+static struct uda134x_platform_data s3c24xx_uda134x = {
+ .l3 = {
+ .setdat = setdat,
+ .setclk = setclk,
+ .setmode = setmode,
+ .data_hold = 1,
+ .data_setup = 1,
+ .clock_high = 1,
+ .mode_hold = 1,
+ .mode = 1,
+ .mode_setup = 1,
+ },
+};
+
+static struct snd_soc_device s3c24xx_uda134x_snd_devdata = {
+ .card = &snd_soc_s3c24xx_uda134x,
+ .codec_dev = &soc_codec_dev_uda134x,
+ .codec_data = &s3c24xx_uda134x,
+};
+
+static int s3c24xx_uda134x_setup_pin(int pin, char *fun)
+{
+ if (gpio_request(pin, "s3c24xx_uda134x") < 0) {
+ printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: "
+ "l3 %s pin already in use", fun);
+ return -EBUSY;
+ }
+ gpio_direction_output(pin, 0);
+ return 0;
+}
+
+static int s3c24xx_uda134x_probe(struct platform_device *pdev)
+{
+ int ret;
+
+ printk(KERN_INFO "S3C24XX_UDA134X SoC Audio driver\n");
+
+ s3c24xx_uda134x_l3_pins = pdev->dev.platform_data;
+ if (s3c24xx_uda134x_l3_pins == NULL) {
+ printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: "
+ "unable to find platform data\n");
+ return -ENODEV;
+ }
+ s3c24xx_uda134x.power = s3c24xx_uda134x_l3_pins->power;
+ s3c24xx_uda134x.model = s3c24xx_uda134x_l3_pins->model;
+
+ if (s3c24xx_uda134x_setup_pin(s3c24xx_uda134x_l3_pins->l3_data,
+ "data") < 0)
+ return -EBUSY;
+ if (s3c24xx_uda134x_setup_pin(s3c24xx_uda134x_l3_pins->l3_clk,
+ "clk") < 0) {
+ gpio_free(s3c24xx_uda134x_l3_pins->l3_data);
+ return -EBUSY;
+ }
+ if (s3c24xx_uda134x_setup_pin(s3c24xx_uda134x_l3_pins->l3_mode,
+ "mode") < 0) {
+ gpio_free(s3c24xx_uda134x_l3_pins->l3_data);
+ gpio_free(s3c24xx_uda134x_l3_pins->l3_clk);
+ return -EBUSY;
+ }
+
+ s3c24xx_uda134x_snd_device = platform_device_alloc("soc-audio", -1);
+ if (!s3c24xx_uda134x_snd_device) {
+ printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: "
+ "Unable to register\n");
+ return -ENOMEM;
+ }
+
+ platform_set_drvdata(s3c24xx_uda134x_snd_device,
+ &s3c24xx_uda134x_snd_devdata);
+ s3c24xx_uda134x_snd_devdata.dev = &s3c24xx_uda134x_snd_device->dev;
+ ret = platform_device_add(s3c24xx_uda134x_snd_device);
+ if (ret) {
+ printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: Unable to add\n");
+ platform_device_put(s3c24xx_uda134x_snd_device);
+ }
+
+ return ret;
+}
+
+static int s3c24xx_uda134x_remove(struct platform_device *pdev)
+{
+ platform_device_unregister(s3c24xx_uda134x_snd_device);
+ gpio_free(s3c24xx_uda134x_l3_pins->l3_data);
+ gpio_free(s3c24xx_uda134x_l3_pins->l3_clk);
+ gpio_free(s3c24xx_uda134x_l3_pins->l3_mode);
+ return 0;
+}
+
+static struct platform_driver s3c24xx_uda134x_driver = {
+ .probe = s3c24xx_uda134x_probe,
+ .remove = s3c24xx_uda134x_remove,
+ .driver = {
+ .name = "s3c24xx_uda134x",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init s3c24xx_uda134x_init(void)
+{
+ return platform_driver_register(&s3c24xx_uda134x_driver);
+}
+
+static void __exit s3c24xx_uda134x_exit(void)
+{
+ platform_driver_unregister(&s3c24xx_uda134x_driver);
+}
+
+
+module_init(s3c24xx_uda134x_init);
+module_exit(s3c24xx_uda134x_exit);
+
+MODULE_AUTHOR("Zoltan Devai, Christian Pellegrin <chripell@evolware.org>");
+MODULE_DESCRIPTION("S3C24XX_UDA134X ALSA SoC audio driver");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/smdk2443_wm9710.c b/sound/soc/s3c24xx/smdk2443_wm9710.c
index 8515d6ff03f..a2a4f5323c1 100644
--- a/sound/soc/s3c24xx/smdk2443_wm9710.c
+++ b/sound/soc/s3c24xx/smdk2443_wm9710.c
@@ -23,7 +23,7 @@
#include "s3c24xx-pcm.h"
#include "s3c24xx-ac97.h"
-static struct snd_soc_machine smdk2443;
+static struct snd_soc_card smdk2443;
static struct snd_soc_dai_link smdk2443_dai[] = {
{
@@ -34,15 +34,15 @@ static struct snd_soc_dai_link smdk2443_dai[] = {
},
};
-static struct snd_soc_machine smdk2443 = {
+static struct snd_soc_card smdk2443 = {
.name = "SMDK2443",
+ .platform = &s3c24xx_soc_platform,
.dai_link = smdk2443_dai,
.num_links = ARRAY_SIZE(smdk2443_dai),
};
static struct snd_soc_device smdk2443_snd_ac97_devdata = {
- .machine = &smdk2443,
- .platform = &s3c24xx_soc_platform,
+ .card = &smdk2443,
.codec_dev = &soc_codec_dev_ac97,
};
diff --git a/sound/soc/sh/dma-sh7760.c b/sound/soc/sh/dma-sh7760.c
index 9faa12622d0..0dad3a0bb92 100644
--- a/sound/soc/sh/dma-sh7760.c
+++ b/sound/soc/sh/dma-sh7760.c
@@ -348,6 +348,18 @@ struct snd_soc_platform sh7760_soc_platform = {
};
EXPORT_SYMBOL_GPL(sh7760_soc_platform);
+static int __init sh7760_soc_platform_init(void)
+{
+ return snd_soc_register_platform(&sh7760_soc_platform);
+}
+module_init(sh7760_soc_platform_init);
+
+static void __exit sh7760_soc_platform_exit(void)
+{
+ snd_soc_unregister_platform(&sh7760_soc_platform);
+}
+module_exit(sh7760_soc_platform_exit);
+
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("SH7760 Audio DMA (DMABRG) driver");
MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>");
diff --git a/sound/soc/sh/hac.c b/sound/soc/sh/hac.c
index df7bc345c32..eab31838bad 100644
--- a/sound/soc/sh/hac.c
+++ b/sound/soc/sh/hac.c
@@ -236,7 +236,8 @@ struct snd_ac97_bus_ops soc_ac97_ops = {
EXPORT_SYMBOL_GPL(soc_ac97_ops);
static int hac_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct hac_priv *hac = &hac_cpu_data[rtd->dai->cpu_dai->id];
@@ -270,7 +271,7 @@ struct snd_soc_dai sh4_hac_dai[] = {
{
.name = "HAC0",
.id = 0,
- .type = SND_SOC_DAI_AC97,
+ .ac97_control = 1,
.playback = {
.rates = AC97_RATES,
.formats = AC97_FMTS,
@@ -290,8 +291,8 @@ struct snd_soc_dai sh4_hac_dai[] = {
#ifdef CONFIG_CPU_SUBTYPE_SH7760
{
.name = "HAC1",
+ .ac97_control = 1,
.id = 1,
- .type = SND_SOC_DAI_AC97,
.playback = {
.rates = AC97_RATES,
.formats = AC97_FMTS,
@@ -313,6 +314,18 @@ struct snd_soc_dai sh4_hac_dai[] = {
};
EXPORT_SYMBOL_GPL(sh4_hac_dai);
+static int __init sh4_hac_init(void)
+{
+ return snd_soc_register_dais(sh4_hac_dai, ARRAY_SIZE(sh4_hac_dai));
+}
+module_init(sh4_hac_init);
+
+static void __exit sh4_hac_exit(void)
+{
+ snd_soc_unregister_dais(sh4_hac_dai, ARRAY_SIZE(sh4_hac_dai));
+}
+module_exit(sh4_hac_exit);
+
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("SuperH onchip HAC (AC97) audio driver");
MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>");
diff --git a/sound/soc/sh/sh7760-ac97.c b/sound/soc/sh/sh7760-ac97.c
index 92bfaf4774a..ce7f95b59de 100644
--- a/sound/soc/sh/sh7760-ac97.c
+++ b/sound/soc/sh/sh7760-ac97.c
@@ -38,15 +38,15 @@ static struct snd_soc_dai_link sh7760_ac97_dai = {
.ops = NULL,
};
-static struct snd_soc_machine sh7760_ac97_soc_machine = {
+static struct snd_soc_card sh7760_ac97_soc_machine = {
.name = "SH7760 AC97",
+ .platform = &sh7760_soc_platform,
.dai_link = &sh7760_ac97_dai,
.num_links = 1,
};
static struct snd_soc_device sh7760_ac97_snd_devdata = {
- .machine = &sh7760_ac97_soc_machine,
- .platform = &sh7760_soc_platform,
+ .card = &sh7760_ac97_soc_machine,
.codec_dev = &soc_codec_dev_ac97,
};
diff --git a/sound/soc/sh/ssi.c b/sound/soc/sh/ssi.c
index 55c3464163a..d1e5390fdde 100644
--- a/sound/soc/sh/ssi.c
+++ b/sound/soc/sh/ssi.c
@@ -89,7 +89,8 @@ struct ssi_priv {
* track usage of the SSI; it is simplex-only so prevent attempts of
* concurrent playback + capture. FIXME: any locking required?
*/
-static int ssi_startup(struct snd_pcm_substream *substream)
+static int ssi_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id];
@@ -101,7 +102,8 @@ static int ssi_startup(struct snd_pcm_substream *substream)
return 0;
}
-static void ssi_shutdown(struct snd_pcm_substream *substream)
+static void ssi_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id];
@@ -109,7 +111,8 @@ static void ssi_shutdown(struct snd_pcm_substream *substream)
ssi->inuse = 0;
}
-static int ssi_trigger(struct snd_pcm_substream *substream, int cmd)
+static int ssi_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id];
@@ -129,7 +132,8 @@ static int ssi_trigger(struct snd_pcm_substream *substream, int cmd)
}
static int ssi_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id];
@@ -336,7 +340,6 @@ struct snd_soc_dai sh4_ssi_dai[] = {
{
.name = "SSI0",
.id = 0,
- .type = SND_SOC_DAI_I2S,
.playback = {
.rates = SSI_RATES,
.formats = SSI_FMTS,
@@ -354,8 +357,6 @@ struct snd_soc_dai sh4_ssi_dai[] = {
.shutdown = ssi_shutdown,
.trigger = ssi_trigger,
.hw_params = ssi_hw_params,
- },
- .dai_ops = {
.set_sysclk = ssi_set_sysclk,
.set_clkdiv = ssi_set_clkdiv,
.set_fmt = ssi_set_fmt,
@@ -365,7 +366,6 @@ struct snd_soc_dai sh4_ssi_dai[] = {
{
.name = "SSI1",
.id = 1,
- .type = SND_SOC_DAI_I2S,
.playback = {
.rates = SSI_RATES,
.formats = SSI_FMTS,
@@ -383,8 +383,6 @@ struct snd_soc_dai sh4_ssi_dai[] = {
.shutdown = ssi_shutdown,
.trigger = ssi_trigger,
.hw_params = ssi_hw_params,
- },
- .dai_ops = {
.set_sysclk = ssi_set_sysclk,
.set_clkdiv = ssi_set_clkdiv,
.set_fmt = ssi_set_fmt,
@@ -394,6 +392,18 @@ struct snd_soc_dai sh4_ssi_dai[] = {
};
EXPORT_SYMBOL_GPL(sh4_ssi_dai);
+static int __init sh4_ssi_init(void)
+{
+ return snd_soc_register_dais(sh4_ssi_dai, ARRAY_SIZE(sh4_ssi_dai));
+}
+module_init(sh4_ssi_init);
+
+static void __exit sh4_ssi_exit(void)
+{
+ snd_soc_unregister_dais(sh4_ssi_dai, ARRAY_SIZE(sh4_ssi_dai));
+}
+module_exit(sh4_ssi_exit);
+
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("SuperH onchip SSI (I2S) audio driver");
MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>");
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 16c7453f494..b098c0b4c58 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -26,6 +26,7 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/bitops.h>
+#include <linux/debugfs.h>
#include <linux/platform_device.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -34,18 +35,23 @@
#include <sound/soc-dapm.h>
#include <sound/initval.h>
-/* debug */
-#define SOC_DEBUG 0
-#if SOC_DEBUG
-#define dbg(format, arg...) printk(format, ## arg)
-#else
-#define dbg(format, arg...)
-#endif
-
static DEFINE_MUTEX(pcm_mutex);
static DEFINE_MUTEX(io_mutex);
static DECLARE_WAIT_QUEUE_HEAD(soc_pm_waitq);
+#ifdef CONFIG_DEBUG_FS
+static struct dentry *debugfs_root;
+#endif
+
+static DEFINE_MUTEX(client_mutex);
+static LIST_HEAD(card_list);
+static LIST_HEAD(dai_list);
+static LIST_HEAD(platform_list);
+static LIST_HEAD(codec_list);
+
+static int snd_soc_register_card(struct snd_soc_card *card);
+static int snd_soc_unregister_card(struct snd_soc_card *card);
+
/*
* This is a timeout to do a DAPM powerdown after a stream is closed().
* It can be used to eliminate pops between different playback streams, e.g.
@@ -107,20 +113,6 @@ static int soc_ac97_dev_register(struct snd_soc_codec *codec)
}
#endif
-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:
- return "I2S";
- case SND_SOC_DAI_PCM:
- return "PCM";
- }
- return NULL;
-}
-
/*
* Called by ALSA when a PCM substream is opened, the runtime->hw record is
* then initialized and any private data can be allocated. This also calls
@@ -130,9 +122,10 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
+ struct snd_soc_card *card = socdev->card;
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_dai_link *machine = rtd->dai;
- struct snd_soc_platform *platform = socdev->platform;
+ struct snd_soc_platform *platform = card->platform;
struct snd_soc_dai *cpu_dai = machine->cpu_dai;
struct snd_soc_dai *codec_dai = machine->codec_dai;
int ret = 0;
@@ -141,7 +134,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
/* startup the audio subsystem */
if (cpu_dai->ops.startup) {
- ret = cpu_dai->ops.startup(substream);
+ ret = cpu_dai->ops.startup(substream, cpu_dai);
if (ret < 0) {
printk(KERN_ERR "asoc: can't open interface %s\n",
cpu_dai->name);
@@ -158,7 +151,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
}
if (codec_dai->ops.startup) {
- ret = codec_dai->ops.startup(substream);
+ ret = codec_dai->ops.startup(substream, codec_dai);
if (ret < 0) {
printk(KERN_ERR "asoc: can't open codec %s\n",
codec_dai->name);
@@ -228,12 +221,12 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
goto machine_err;
}
- dbg("asoc: %s <-> %s info:\n", codec_dai->name, cpu_dai->name);
- dbg("asoc: rate mask 0x%x\n", runtime->hw.rates);
- dbg("asoc: min ch %d max ch %d\n", runtime->hw.channels_min,
- runtime->hw.channels_max);
- dbg("asoc: min rate %d max rate %d\n", runtime->hw.rate_min,
- runtime->hw.rate_max);
+ pr_debug("asoc: %s <-> %s info:\n", codec_dai->name, cpu_dai->name);
+ pr_debug("asoc: rate mask 0x%x\n", runtime->hw.rates);
+ pr_debug("asoc: min ch %d max ch %d\n", runtime->hw.channels_min,
+ runtime->hw.channels_max);
+ pr_debug("asoc: min rate %d max rate %d\n", runtime->hw.rate_min,
+ runtime->hw.rate_max);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
cpu_dai->playback.active = codec_dai->playback.active = 1;
@@ -255,7 +248,7 @@ codec_dai_err:
platform_err:
if (cpu_dai->ops.shutdown)
- cpu_dai->ops.shutdown(substream);
+ cpu_dai->ops.shutdown(substream, cpu_dai);
out:
mutex_unlock(&pcm_mutex);
return ret;
@@ -268,8 +261,9 @@ out:
*/
static void close_delayed_work(struct work_struct *work)
{
- struct snd_soc_device *socdev =
- container_of(work, struct snd_soc_device, delayed_work.work);
+ struct snd_soc_card *card = container_of(work, struct snd_soc_card,
+ delayed_work.work);
+ struct snd_soc_device *socdev = card->socdev;
struct snd_soc_codec *codec = socdev->codec;
struct snd_soc_dai *codec_dai;
int i;
@@ -278,18 +272,18 @@ static void close_delayed_work(struct work_struct *work)
for (i = 0; i < codec->num_dai; i++) {
codec_dai = &codec->dai[i];
- dbg("pop wq checking: %s status: %s waiting: %s\n",
- codec_dai->playback.stream_name,
- codec_dai->playback.active ? "active" : "inactive",
- codec_dai->pop_wait ? "yes" : "no");
+ pr_debug("pop wq checking: %s status: %s waiting: %s\n",
+ codec_dai->playback.stream_name,
+ codec_dai->playback.active ? "active" : "inactive",
+ codec_dai->pop_wait ? "yes" : "no");
/* are we waiting on this codec DAI stream */
if (codec_dai->pop_wait == 1) {
/* Reduce power if no longer active */
if (codec->active == 0) {
- dbg("pop wq D1 %s %s\n", codec->name,
- codec_dai->playback.stream_name);
+ pr_debug("pop wq D1 %s %s\n", codec->name,
+ codec_dai->playback.stream_name);
snd_soc_dapm_set_bias_level(socdev,
SND_SOC_BIAS_PREPARE);
}
@@ -301,8 +295,8 @@ static void close_delayed_work(struct work_struct *work)
/* Fall into standby if no longer active */
if (codec->active == 0) {
- dbg("pop wq D3 %s %s\n", codec->name,
- codec_dai->playback.stream_name);
+ pr_debug("pop wq D3 %s %s\n", codec->name,
+ codec_dai->playback.stream_name);
snd_soc_dapm_set_bias_level(socdev,
SND_SOC_BIAS_STANDBY);
}
@@ -320,8 +314,9 @@ static int soc_codec_close(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
+ struct snd_soc_card *card = socdev->card;
struct snd_soc_dai_link *machine = rtd->dai;
- struct snd_soc_platform *platform = socdev->platform;
+ struct snd_soc_platform *platform = card->platform;
struct snd_soc_dai *cpu_dai = machine->cpu_dai;
struct snd_soc_dai *codec_dai = machine->codec_dai;
struct snd_soc_codec *codec = socdev->codec;
@@ -346,10 +341,10 @@ static int soc_codec_close(struct snd_pcm_substream *substream)
snd_soc_dai_digital_mute(codec_dai, 1);
if (cpu_dai->ops.shutdown)
- cpu_dai->ops.shutdown(substream);
+ cpu_dai->ops.shutdown(substream, cpu_dai);
if (codec_dai->ops.shutdown)
- codec_dai->ops.shutdown(substream);
+ codec_dai->ops.shutdown(substream, codec_dai);
if (machine->ops && machine->ops->shutdown)
machine->ops->shutdown(substream);
@@ -361,7 +356,7 @@ static int soc_codec_close(struct snd_pcm_substream *substream)
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
/* start delayed pop wq here for playback streams */
codec_dai->pop_wait = 1;
- schedule_delayed_work(&socdev->delayed_work,
+ schedule_delayed_work(&card->delayed_work,
msecs_to_jiffies(pmdown_time));
} else {
/* capture streams can be powered down now */
@@ -387,8 +382,9 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
+ struct snd_soc_card *card = socdev->card;
struct snd_soc_dai_link *machine = rtd->dai;
- struct snd_soc_platform *platform = socdev->platform;
+ struct snd_soc_platform *platform = card->platform;
struct snd_soc_dai *cpu_dai = machine->cpu_dai;
struct snd_soc_dai *codec_dai = machine->codec_dai;
struct snd_soc_codec *codec = socdev->codec;
@@ -413,7 +409,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
}
if (codec_dai->ops.prepare) {
- ret = codec_dai->ops.prepare(substream);
+ ret = codec_dai->ops.prepare(substream, codec_dai);
if (ret < 0) {
printk(KERN_ERR "asoc: codec DAI prepare error\n");
goto out;
@@ -421,58 +417,49 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
}
if (cpu_dai->ops.prepare) {
- ret = cpu_dai->ops.prepare(substream);
+ ret = cpu_dai->ops.prepare(substream, cpu_dai);
if (ret < 0) {
printk(KERN_ERR "asoc: cpu DAI prepare error\n");
goto out;
}
}
- /* we only want to start a DAPM playback stream if we are not waiting
- * on an existing one stopping */
- if (codec_dai->pop_wait) {
- /* we are waiting for the delayed work to start */
- if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
- snd_soc_dapm_stream_event(socdev->codec,
- codec_dai->capture.stream_name,
- SND_SOC_DAPM_STREAM_START);
- else {
- codec_dai->pop_wait = 0;
- cancel_delayed_work(&socdev->delayed_work);
- snd_soc_dai_digital_mute(codec_dai, 0);
- }
- } else {
- /* no delayed work - do we need to power up codec */
- if (codec->bias_level != SND_SOC_BIAS_ON) {
+ /* cancel any delayed stream shutdown that is pending */
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
+ codec_dai->pop_wait) {
+ codec_dai->pop_wait = 0;
+ cancel_delayed_work(&card->delayed_work);
+ }
- snd_soc_dapm_set_bias_level(socdev,
- SND_SOC_BIAS_PREPARE);
+ /* do we need to power up codec */
+ if (codec->bias_level != SND_SOC_BIAS_ON) {
+ snd_soc_dapm_set_bias_level(socdev,
+ SND_SOC_BIAS_PREPARE);
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- snd_soc_dapm_stream_event(codec,
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ snd_soc_dapm_stream_event(codec,
codec_dai->playback.stream_name,
SND_SOC_DAPM_STREAM_START);
- else
- snd_soc_dapm_stream_event(codec,
+ else
+ snd_soc_dapm_stream_event(codec,
codec_dai->capture.stream_name,
SND_SOC_DAPM_STREAM_START);
- snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_ON);
- snd_soc_dai_digital_mute(codec_dai, 0);
+ snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_ON);
+ snd_soc_dai_digital_mute(codec_dai, 0);
- } else {
- /* codec already powered - power on widgets */
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- snd_soc_dapm_stream_event(codec,
+ } else {
+ /* codec already powered - power on widgets */
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ snd_soc_dapm_stream_event(codec,
codec_dai->playback.stream_name,
SND_SOC_DAPM_STREAM_START);
- else
- snd_soc_dapm_stream_event(codec,
+ else
+ snd_soc_dapm_stream_event(codec,
codec_dai->capture.stream_name,
SND_SOC_DAPM_STREAM_START);
- snd_soc_dai_digital_mute(codec_dai, 0);
- }
+ snd_soc_dai_digital_mute(codec_dai, 0);
}
out:
@@ -491,7 +478,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_dai_link *machine = rtd->dai;
- struct snd_soc_platform *platform = socdev->platform;
+ struct snd_soc_card *card = socdev->card;
+ struct snd_soc_platform *platform = card->platform;
struct snd_soc_dai *cpu_dai = machine->cpu_dai;
struct snd_soc_dai *codec_dai = machine->codec_dai;
int ret = 0;
@@ -507,7 +495,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
}
if (codec_dai->ops.hw_params) {
- ret = codec_dai->ops.hw_params(substream, params);
+ ret = codec_dai->ops.hw_params(substream, params, codec_dai);
if (ret < 0) {
printk(KERN_ERR "asoc: can't set codec %s hw params\n",
codec_dai->name);
@@ -516,7 +504,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
}
if (cpu_dai->ops.hw_params) {
- ret = cpu_dai->ops.hw_params(substream, params);
+ ret = cpu_dai->ops.hw_params(substream, params, cpu_dai);
if (ret < 0) {
printk(KERN_ERR "asoc: interface %s hw params failed\n",
cpu_dai->name);
@@ -539,11 +527,11 @@ out:
platform_err:
if (cpu_dai->ops.hw_free)
- cpu_dai->ops.hw_free(substream);
+ cpu_dai->ops.hw_free(substream, cpu_dai);
interface_err:
if (codec_dai->ops.hw_free)
- codec_dai->ops.hw_free(substream);
+ codec_dai->ops.hw_free(substream, codec_dai);
codec_err:
if (machine->ops && machine->ops->hw_free)
@@ -561,7 +549,8 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_dai_link *machine = rtd->dai;
- struct snd_soc_platform *platform = socdev->platform;
+ struct snd_soc_card *card = socdev->card;
+ struct snd_soc_platform *platform = card->platform;
struct snd_soc_dai *cpu_dai = machine->cpu_dai;
struct snd_soc_dai *codec_dai = machine->codec_dai;
struct snd_soc_codec *codec = socdev->codec;
@@ -582,10 +571,10 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
/* now free hw params for the DAI's */
if (codec_dai->ops.hw_free)
- codec_dai->ops.hw_free(substream);
+ codec_dai->ops.hw_free(substream, codec_dai);
if (cpu_dai->ops.hw_free)
- cpu_dai->ops.hw_free(substream);
+ cpu_dai->ops.hw_free(substream, cpu_dai);
mutex_unlock(&pcm_mutex);
return 0;
@@ -595,14 +584,15 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
+ struct snd_soc_card *card= socdev->card;
struct snd_soc_dai_link *machine = rtd->dai;
- struct snd_soc_platform *platform = socdev->platform;
+ struct snd_soc_platform *platform = card->platform;
struct snd_soc_dai *cpu_dai = machine->cpu_dai;
struct snd_soc_dai *codec_dai = machine->codec_dai;
int ret;
if (codec_dai->ops.trigger) {
- ret = codec_dai->ops.trigger(substream, cmd);
+ ret = codec_dai->ops.trigger(substream, cmd, codec_dai);
if (ret < 0)
return ret;
}
@@ -614,7 +604,7 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
}
if (cpu_dai->ops.trigger) {
- ret = cpu_dai->ops.trigger(substream, cmd);
+ ret = cpu_dai->ops.trigger(substream, cmd, cpu_dai);
if (ret < 0)
return ret;
}
@@ -636,8 +626,8 @@ static struct snd_pcm_ops soc_pcm_ops = {
static int soc_suspend(struct platform_device *pdev, pm_message_t state)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_machine *machine = socdev->machine;
- struct snd_soc_platform *platform = socdev->platform;
+ struct snd_soc_card *card = socdev->card;
+ struct snd_soc_platform *platform = card->platform;
struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
struct snd_soc_codec *codec = socdev->codec;
int i;
@@ -653,29 +643,29 @@ static int soc_suspend(struct platform_device *pdev, pm_message_t state)
snd_power_change_state(codec->card, SNDRV_CTL_POWER_D3hot);
/* mute any active DAC's */
- for (i = 0; i < machine->num_links; i++) {
- struct snd_soc_dai *dai = machine->dai_link[i].codec_dai;
- if (dai->dai_ops.digital_mute && dai->playback.active)
- dai->dai_ops.digital_mute(dai, 1);
+ for (i = 0; i < card->num_links; i++) {
+ struct snd_soc_dai *dai = card->dai_link[i].codec_dai;
+ if (dai->ops.digital_mute && dai->playback.active)
+ dai->ops.digital_mute(dai, 1);
}
/* suspend all pcms */
- for (i = 0; i < machine->num_links; i++)
- snd_pcm_suspend_all(machine->dai_link[i].pcm);
+ for (i = 0; i < card->num_links; i++)
+ snd_pcm_suspend_all(card->dai_link[i].pcm);
- if (machine->suspend_pre)
- machine->suspend_pre(pdev, state);
+ if (card->suspend_pre)
+ card->suspend_pre(pdev, state);
- for (i = 0; i < machine->num_links; i++) {
- struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai;
- if (cpu_dai->suspend && cpu_dai->type != SND_SOC_DAI_AC97)
- cpu_dai->suspend(pdev, cpu_dai);
+ for (i = 0; i < card->num_links; i++) {
+ struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
+ if (cpu_dai->suspend && !cpu_dai->ac97_control)
+ cpu_dai->suspend(cpu_dai);
if (platform->suspend)
- platform->suspend(pdev, cpu_dai);
+ platform->suspend(cpu_dai);
}
/* close any waiting streams and save state */
- run_delayed_work(&socdev->delayed_work);
+ run_delayed_work(&card->delayed_work);
codec->suspend_bias_level = codec->bias_level;
for (i = 0; i < codec->num_dai; i++) {
@@ -692,14 +682,14 @@ static int soc_suspend(struct platform_device *pdev, pm_message_t state)
if (codec_dev->suspend)
codec_dev->suspend(pdev, state);
- for (i = 0; i < machine->num_links; i++) {
- struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai;
- if (cpu_dai->suspend && cpu_dai->type == SND_SOC_DAI_AC97)
- cpu_dai->suspend(pdev, cpu_dai);
+ for (i = 0; i < card->num_links; i++) {
+ struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
+ if (cpu_dai->suspend && cpu_dai->ac97_control)
+ cpu_dai->suspend(cpu_dai);
}
- if (machine->suspend_post)
- machine->suspend_post(pdev, state);
+ if (card->suspend_post)
+ card->suspend_post(pdev, state);
return 0;
}
@@ -709,11 +699,11 @@ static int soc_suspend(struct platform_device *pdev, pm_message_t state)
*/
static void soc_resume_deferred(struct work_struct *work)
{
- struct snd_soc_device *socdev = container_of(work,
- struct snd_soc_device,
- deferred_resume_work);
- struct snd_soc_machine *machine = socdev->machine;
- struct snd_soc_platform *platform = socdev->platform;
+ struct snd_soc_card *card = container_of(work,
+ struct snd_soc_card,
+ deferred_resume_work);
+ struct snd_soc_device *socdev = card->socdev;
+ struct snd_soc_platform *platform = card->platform;
struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
struct snd_soc_codec *codec = socdev->codec;
struct platform_device *pdev = to_platform_device(socdev->dev);
@@ -723,15 +713,15 @@ static void soc_resume_deferred(struct work_struct *work)
* so userspace apps are blocked from touching us
*/
- dev_info(socdev->dev, "starting resume work\n");
+ dev_dbg(socdev->dev, "starting resume work\n");
- if (machine->resume_pre)
- machine->resume_pre(pdev);
+ if (card->resume_pre)
+ card->resume_pre(pdev);
- for (i = 0; i < machine->num_links; i++) {
- struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai;
- if (cpu_dai->resume && cpu_dai->type == SND_SOC_DAI_AC97)
- cpu_dai->resume(pdev, cpu_dai);
+ for (i = 0; i < card->num_links; i++) {
+ struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
+ if (cpu_dai->resume && cpu_dai->ac97_control)
+ cpu_dai->resume(cpu_dai);
}
if (codec_dev->resume)
@@ -749,24 +739,24 @@ static void soc_resume_deferred(struct work_struct *work)
}
/* unmute any active DACs */
- for (i = 0; i < machine->num_links; i++) {
- struct snd_soc_dai *dai = machine->dai_link[i].codec_dai;
- if (dai->dai_ops.digital_mute && dai->playback.active)
- dai->dai_ops.digital_mute(dai, 0);
+ for (i = 0; i < card->num_links; i++) {
+ struct snd_soc_dai *dai = card->dai_link[i].codec_dai;
+ if (dai->ops.digital_mute && dai->playback.active)
+ dai->ops.digital_mute(dai, 0);
}
- for (i = 0; i < machine->num_links; i++) {
- struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai;
- if (cpu_dai->resume && cpu_dai->type != SND_SOC_DAI_AC97)
- cpu_dai->resume(pdev, cpu_dai);
+ for (i = 0; i < card->num_links; i++) {
+ struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
+ if (cpu_dai->resume && !cpu_dai->ac97_control)
+ cpu_dai->resume(cpu_dai);
if (platform->resume)
- platform->resume(pdev, cpu_dai);
+ platform->resume(cpu_dai);
}
- if (machine->resume_post)
- machine->resume_post(pdev);
+ if (card->resume_post)
+ card->resume_post(pdev);
- dev_info(socdev->dev, "resume work completed\n");
+ dev_dbg(socdev->dev, "resume work completed\n");
/* userspace can access us now we are back as we were before */
snd_power_change_state(codec->card, SNDRV_CTL_POWER_D0);
@@ -776,11 +766,12 @@ static void soc_resume_deferred(struct work_struct *work)
static int soc_resume(struct platform_device *pdev)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_card *card = socdev->card;
- dev_info(socdev->dev, "scheduling resume work\n");
+ dev_dbg(socdev->dev, "scheduling resume work\n");
- if (!schedule_work(&socdev->deferred_resume_work))
- dev_err(socdev->dev, "work item may be lost\n");
+ if (!schedule_work(&card->deferred_resume_work))
+ dev_err(socdev->dev, "resume work item may be lost\n");
return 0;
}
@@ -790,23 +781,83 @@ static int soc_resume(struct platform_device *pdev)
#define soc_resume NULL
#endif
-/* probes a new socdev */
-static int soc_probe(struct platform_device *pdev)
+static void snd_soc_instantiate_card(struct snd_soc_card *card)
{
- int ret = 0, i;
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_machine *machine = socdev->machine;
- struct snd_soc_platform *platform = socdev->platform;
- struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
+ struct platform_device *pdev = container_of(card->dev,
+ struct platform_device,
+ dev);
+ struct snd_soc_codec_device *codec_dev = card->socdev->codec_dev;
+ struct snd_soc_platform *platform;
+ struct snd_soc_dai *dai;
+ int i, found, ret, ac97;
+
+ if (card->instantiated)
+ return;
+
+ found = 0;
+ list_for_each_entry(platform, &platform_list, list)
+ if (card->platform == platform) {
+ found = 1;
+ break;
+ }
+ if (!found) {
+ dev_dbg(card->dev, "Platform %s not registered\n",
+ card->platform->name);
+ return;
+ }
+
+ ac97 = 0;
+ for (i = 0; i < card->num_links; i++) {
+ found = 0;
+ list_for_each_entry(dai, &dai_list, list)
+ if (card->dai_link[i].cpu_dai == dai) {
+ found = 1;
+ break;
+ }
+ if (!found) {
+ dev_dbg(card->dev, "DAI %s not registered\n",
+ card->dai_link[i].cpu_dai->name);
+ return;
+ }
- if (machine->probe) {
- ret = machine->probe(pdev);
+ if (card->dai_link[i].cpu_dai->ac97_control)
+ ac97 = 1;
+ }
+
+ /* If we have AC97 in the system then don't wait for the
+ * codec. This will need revisiting if we have to handle
+ * systems with mixed AC97 and non-AC97 parts. Only check for
+ * DAIs currently; we can't do this per link since some AC97
+ * codecs have non-AC97 DAIs.
+ */
+ if (!ac97)
+ for (i = 0; i < card->num_links; i++) {
+ found = 0;
+ list_for_each_entry(dai, &dai_list, list)
+ if (card->dai_link[i].codec_dai == dai) {
+ found = 1;
+ break;
+ }
+ if (!found) {
+ dev_dbg(card->dev, "DAI %s not registered\n",
+ card->dai_link[i].codec_dai->name);
+ return;
+ }
+ }
+
+ /* Note that we do not current check for codec components */
+
+ dev_dbg(card->dev, "All components present, instantiating\n");
+
+ /* Found everything, bring it up */
+ if (card->probe) {
+ ret = card->probe(pdev);
if (ret < 0)
- return ret;
+ return;
}
- for (i = 0; i < machine->num_links; i++) {
- struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai;
+ for (i = 0; i < card->num_links; i++) {
+ struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
if (cpu_dai->probe) {
ret = cpu_dai->probe(pdev, cpu_dai);
if (ret < 0)
@@ -827,13 +878,15 @@ static int soc_probe(struct platform_device *pdev)
}
/* DAPM stream work */
- INIT_DELAYED_WORK(&socdev->delayed_work, close_delayed_work);
+ INIT_DELAYED_WORK(&card->delayed_work, close_delayed_work);
#ifdef CONFIG_PM
/* deferred resume work */
- INIT_WORK(&socdev->deferred_resume_work, soc_resume_deferred);
+ INIT_WORK(&card->deferred_resume_work, soc_resume_deferred);
#endif
- return 0;
+ card->instantiated = 1;
+
+ return;
platform_err:
if (codec_dev->remove)
@@ -841,15 +894,45 @@ platform_err:
cpu_dai_err:
for (i--; i >= 0; i--) {
- struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai;
+ struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
if (cpu_dai->remove)
cpu_dai->remove(pdev, cpu_dai);
}
- if (machine->remove)
- machine->remove(pdev);
+ if (card->remove)
+ card->remove(pdev);
+}
- return ret;
+/*
+ * Attempt to initialise any uninitalised cards. Must be called with
+ * client_mutex.
+ */
+static void snd_soc_instantiate_cards(void)
+{
+ struct snd_soc_card *card;
+ list_for_each_entry(card, &card_list, list)
+ snd_soc_instantiate_card(card);
+}
+
+/* probes a new socdev */
+static int soc_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_card *card = socdev->card;
+
+ /* Bodge while we push things out of socdev */
+ card->socdev = socdev;
+
+ /* Bodge while we unpick instantiation */
+ card->dev = &pdev->dev;
+ ret = snd_soc_register_card(card);
+ if (ret != 0) {
+ dev_err(&pdev->dev, "Failed to register card\n");
+ return ret;
+ }
+
+ return 0;
}
/* removes a socdev */
@@ -857,11 +940,11 @@ static int soc_remove(struct platform_device *pdev)
{
int i;
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_machine *machine = socdev->machine;
- struct snd_soc_platform *platform = socdev->platform;
+ struct snd_soc_card *card = socdev->card;
+ struct snd_soc_platform *platform = card->platform;
struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
- run_delayed_work(&socdev->delayed_work);
+ run_delayed_work(&card->delayed_work);
if (platform->remove)
platform->remove(pdev);
@@ -869,14 +952,16 @@ static int soc_remove(struct platform_device *pdev)
if (codec_dev->remove)
codec_dev->remove(pdev);
- for (i = 0; i < machine->num_links; i++) {
- struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai;
+ for (i = 0; i < card->num_links; i++) {
+ struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
if (cpu_dai->remove)
cpu_dai->remove(pdev, cpu_dai);
}
- if (machine->remove)
- machine->remove(pdev);
+ if (card->remove)
+ card->remove(pdev);
+
+ snd_soc_unregister_card(card);
return 0;
}
@@ -898,6 +983,8 @@ static int soc_new_pcm(struct snd_soc_device *socdev,
struct snd_soc_dai_link *dai_link, int num)
{
struct snd_soc_codec *codec = socdev->codec;
+ struct snd_soc_card *card = socdev->card;
+ struct snd_soc_platform *platform = card->platform;
struct snd_soc_dai *codec_dai = dai_link->codec_dai;
struct snd_soc_dai *cpu_dai = dai_link->cpu_dai;
struct snd_soc_pcm_runtime *rtd;
@@ -914,8 +1001,8 @@ static int soc_new_pcm(struct snd_soc_device *socdev,
codec_dai->codec = socdev->codec;
/* check client and interface hw capabilities */
- sprintf(new_name, "%s %s-%s-%d", dai_link->stream_name, codec_dai->name,
- get_dai_name(cpu_dai->type), num);
+ sprintf(new_name, "%s %s-%d", dai_link->stream_name, codec_dai->name,
+ num);
if (codec_dai->playback.channels_min)
playback = 1;
@@ -933,13 +1020,13 @@ static int soc_new_pcm(struct snd_soc_device *socdev,
dai_link->pcm = pcm;
pcm->private_data = rtd;
- soc_pcm_ops.mmap = socdev->platform->pcm_ops->mmap;
- soc_pcm_ops.pointer = socdev->platform->pcm_ops->pointer;
- soc_pcm_ops.ioctl = socdev->platform->pcm_ops->ioctl;
- soc_pcm_ops.copy = socdev->platform->pcm_ops->copy;
- soc_pcm_ops.silence = socdev->platform->pcm_ops->silence;
- soc_pcm_ops.ack = socdev->platform->pcm_ops->ack;
- soc_pcm_ops.page = socdev->platform->pcm_ops->page;
+ soc_pcm_ops.mmap = platform->pcm_ops->mmap;
+ soc_pcm_ops.pointer = platform->pcm_ops->pointer;
+ soc_pcm_ops.ioctl = platform->pcm_ops->ioctl;
+ soc_pcm_ops.copy = platform->pcm_ops->copy;
+ soc_pcm_ops.silence = platform->pcm_ops->silence;
+ soc_pcm_ops.ack = platform->pcm_ops->ack;
+ soc_pcm_ops.page = platform->pcm_ops->page;
if (playback)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &soc_pcm_ops);
@@ -947,24 +1034,22 @@ static int soc_new_pcm(struct snd_soc_device *socdev,
if (capture)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &soc_pcm_ops);
- ret = socdev->platform->pcm_new(codec->card, codec_dai, pcm);
+ ret = platform->pcm_new(codec->card, codec_dai, pcm);
if (ret < 0) {
printk(KERN_ERR "asoc: platform pcm constructor failed\n");
kfree(rtd);
return ret;
}
- pcm->private_free = socdev->platform->pcm_free;
+ pcm->private_free = platform->pcm_free;
printk(KERN_INFO "asoc: %s <-> %s mapping ok\n", codec_dai->name,
cpu_dai->name);
return ret;
}
/* codec register dump */
-static ssize_t codec_reg_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t soc_codec_reg_show(struct snd_soc_device *devdata, char *buf)
{
- struct snd_soc_device *devdata = dev_get_drvdata(dev);
struct snd_soc_codec *codec = devdata->codec;
int i, step = 1, count = 0;
@@ -1001,8 +1086,110 @@ static ssize_t codec_reg_show(struct device *dev,
return count;
}
+static ssize_t codec_reg_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct snd_soc_device *devdata = dev_get_drvdata(dev);
+ return soc_codec_reg_show(devdata, buf);
+}
+
static DEVICE_ATTR(codec_reg, 0444, codec_reg_show, NULL);
+#ifdef CONFIG_DEBUG_FS
+static int codec_reg_open_file(struct inode *inode, struct file *file)
+{
+ file->private_data = inode->i_private;
+ return 0;
+}
+
+static ssize_t codec_reg_read_file(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ ssize_t ret;
+ struct snd_soc_codec *codec = file->private_data;
+ struct device *card_dev = codec->card->dev;
+ struct snd_soc_device *devdata = card_dev->driver_data;
+ char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+ ret = soc_codec_reg_show(devdata, buf);
+ if (ret >= 0)
+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
+ kfree(buf);
+ return ret;
+}
+
+static ssize_t codec_reg_write_file(struct file *file,
+ const char __user *user_buf, size_t count, loff_t *ppos)
+{
+ char buf[32];
+ int buf_size;
+ char *start = buf;
+ unsigned long reg, value;
+ int step = 1;
+ struct snd_soc_codec *codec = file->private_data;
+
+ buf_size = min(count, (sizeof(buf)-1));
+ if (copy_from_user(buf, user_buf, buf_size))
+ return -EFAULT;
+ buf[buf_size] = 0;
+
+ if (codec->reg_cache_step)
+ step = codec->reg_cache_step;
+
+ while (*start == ' ')
+ start++;
+ reg = simple_strtoul(start, &start, 16);
+ if ((reg >= codec->reg_cache_size) || (reg % step))
+ return -EINVAL;
+ while (*start == ' ')
+ start++;
+ if (strict_strtoul(start, 16, &value))
+ return -EINVAL;
+ codec->write(codec, reg, value);
+ return buf_size;
+}
+
+static const struct file_operations codec_reg_fops = {
+ .open = codec_reg_open_file,
+ .read = codec_reg_read_file,
+ .write = codec_reg_write_file,
+};
+
+static void soc_init_codec_debugfs(struct snd_soc_codec *codec)
+{
+ codec->debugfs_reg = debugfs_create_file("codec_reg", 0644,
+ debugfs_root, codec,
+ &codec_reg_fops);
+ if (!codec->debugfs_reg)
+ printk(KERN_WARNING
+ "ASoC: Failed to create codec register debugfs file\n");
+
+ codec->debugfs_pop_time = debugfs_create_u32("dapm_pop_time", 0744,
+ debugfs_root,
+ &codec->pop_time);
+ if (!codec->debugfs_pop_time)
+ printk(KERN_WARNING
+ "Failed to create pop time debugfs file\n");
+}
+
+static void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec)
+{
+ debugfs_remove(codec->debugfs_pop_time);
+ debugfs_remove(codec->debugfs_reg);
+}
+
+#else
+
+static inline void soc_init_codec_debugfs(struct snd_soc_codec *codec)
+{
+}
+
+static inline void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec)
+{
+}
+#endif
+
/**
* snd_soc_new_ac97_codec - initailise AC97 device
* @codec: audio codec
@@ -1121,7 +1308,7 @@ EXPORT_SYMBOL_GPL(snd_soc_test_bits);
int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid)
{
struct snd_soc_codec *codec = socdev->codec;
- struct snd_soc_machine *machine = socdev->machine;
+ struct snd_soc_card *card = socdev->card;
int ret = 0, i;
mutex_lock(&codec->mutex);
@@ -1140,11 +1327,11 @@ int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid)
strncpy(codec->card->driver, codec->name, sizeof(codec->card->driver));
/* create the pcms */
- for (i = 0; i < machine->num_links; i++) {
- ret = soc_new_pcm(socdev, &machine->dai_link[i], i);
+ for (i = 0; i < card->num_links; i++) {
+ ret = soc_new_pcm(socdev, &card->dai_link[i], i);
if (ret < 0) {
printk(KERN_ERR "asoc: can't create pcm %s\n",
- machine->dai_link[i].stream_name);
+ card->dai_link[i].stream_name);
mutex_unlock(&codec->mutex);
return ret;
}
@@ -1156,7 +1343,7 @@ int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid)
EXPORT_SYMBOL_GPL(snd_soc_new_pcms);
/**
- * snd_soc_register_card - register sound card
+ * snd_soc_init_card - register sound card
* @socdev: the SoC audio device
*
* Register a SoC sound card. Also registers an AC97 device if the
@@ -1164,29 +1351,28 @@ EXPORT_SYMBOL_GPL(snd_soc_new_pcms);
*
* Returns 0 for success, else error.
*/
-int snd_soc_register_card(struct snd_soc_device *socdev)
+int snd_soc_init_card(struct snd_soc_device *socdev)
{
struct snd_soc_codec *codec = socdev->codec;
- struct snd_soc_machine *machine = socdev->machine;
+ struct snd_soc_card *card = socdev->card;
int ret = 0, i, ac97 = 0, err = 0;
- for (i = 0; i < machine->num_links; i++) {
- if (socdev->machine->dai_link[i].init) {
- err = socdev->machine->dai_link[i].init(codec);
+ for (i = 0; i < card->num_links; i++) {
+ if (card->dai_link[i].init) {
+ err = card->dai_link[i].init(codec);
if (err < 0) {
printk(KERN_ERR "asoc: failed to init %s\n",
- socdev->machine->dai_link[i].stream_name);
+ card->dai_link[i].stream_name);
continue;
}
}
- if (socdev->machine->dai_link[i].codec_dai->type ==
- SND_SOC_DAI_AC97_BUS)
+ if (card->dai_link[i].codec_dai->ac97_control)
ac97 = 1;
}
snprintf(codec->card->shortname, sizeof(codec->card->shortname),
- "%s", machine->name);
+ "%s", card->name);
snprintf(codec->card->longname, sizeof(codec->card->longname),
- "%s (%s)", machine->name, codec->name);
+ "%s (%s)", card->name, codec->name);
ret = snd_card_register(codec->card);
if (ret < 0) {
@@ -1216,12 +1402,13 @@ int snd_soc_register_card(struct snd_soc_device *socdev)
if (err < 0)
printk(KERN_WARNING "asoc: failed to add codec sysfs files\n");
+ soc_init_codec_debugfs(socdev->codec);
mutex_unlock(&codec->mutex);
out:
return ret;
}
-EXPORT_SYMBOL_GPL(snd_soc_register_card);
+EXPORT_SYMBOL_GPL(snd_soc_init_card);
/**
* snd_soc_free_pcms - free sound card and pcms
@@ -1239,10 +1426,11 @@ void snd_soc_free_pcms(struct snd_soc_device *socdev)
#endif
mutex_lock(&codec->mutex);
+ soc_cleanup_codec_debugfs(socdev->codec);
#ifdef CONFIG_SND_SOC_AC97_BUS
for (i = 0; i < codec->num_dai; i++) {
codec_dai = &codec->dai[i];
- if (codec_dai->type == SND_SOC_DAI_AC97_BUS && codec->ac97) {
+ if (codec_dai->ac97_control && codec->ac97) {
soc_ac97_dev_unregister(codec);
goto free_card;
}
@@ -1756,8 +1944,8 @@ EXPORT_SYMBOL_GPL(snd_soc_put_volsw_s8);
int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
unsigned int freq, int dir)
{
- if (dai->dai_ops.set_sysclk)
- return dai->dai_ops.set_sysclk(dai, clk_id, freq, dir);
+ if (dai->ops.set_sysclk)
+ return dai->ops.set_sysclk(dai, clk_id, freq, dir);
else
return -EINVAL;
}
@@ -1776,8 +1964,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk);
int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai,
int div_id, int div)
{
- if (dai->dai_ops.set_clkdiv)
- return dai->dai_ops.set_clkdiv(dai, div_id, div);
+ if (dai->ops.set_clkdiv)
+ return dai->ops.set_clkdiv(dai, div_id, div);
else
return -EINVAL;
}
@@ -1795,8 +1983,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_clkdiv);
int snd_soc_dai_set_pll(struct snd_soc_dai *dai,
int pll_id, unsigned int freq_in, unsigned int freq_out)
{
- if (dai->dai_ops.set_pll)
- return dai->dai_ops.set_pll(dai, pll_id, freq_in, freq_out);
+ if (dai->ops.set_pll)
+ return dai->ops.set_pll(dai, pll_id, freq_in, freq_out);
else
return -EINVAL;
}
@@ -1805,15 +1993,14 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_pll);
/**
* snd_soc_dai_set_fmt - configure DAI hardware audio format.
* @dai: DAI
- * @clk_id: DAI specific clock ID
* @fmt: SND_SOC_DAIFMT_ format value.
*
* Configures the DAI hardware format and clocking.
*/
int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
- if (dai->dai_ops.set_fmt)
- return dai->dai_ops.set_fmt(dai, fmt);
+ if (dai->ops.set_fmt)
+ return dai->ops.set_fmt(dai, fmt);
else
return -EINVAL;
}
@@ -1831,8 +2018,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt);
int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
unsigned int mask, int slots)
{
- if (dai->dai_ops.set_sysclk)
- return dai->dai_ops.set_tdm_slot(dai, mask, slots);
+ if (dai->ops.set_sysclk)
+ return dai->ops.set_tdm_slot(dai, mask, slots);
else
return -EINVAL;
}
@@ -1847,8 +2034,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot);
*/
int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate)
{
- if (dai->dai_ops.set_sysclk)
- return dai->dai_ops.set_tristate(dai, tristate);
+ if (dai->ops.set_sysclk)
+ return dai->ops.set_tristate(dai, tristate);
else
return -EINVAL;
}
@@ -1863,21 +2050,242 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_tristate);
*/
int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute)
{
- if (dai->dai_ops.digital_mute)
- return dai->dai_ops.digital_mute(dai, mute);
+ if (dai->ops.digital_mute)
+ return dai->ops.digital_mute(dai, mute);
else
return -EINVAL;
}
EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute);
-static int __devinit snd_soc_init(void)
+/**
+ * snd_soc_register_card - Register a card with the ASoC core
+ *
+ * @param card Card to register
+ *
+ * Note that currently this is an internal only function: it will be
+ * exposed to machine drivers after further backporting of ASoC v2
+ * registration APIs.
+ */
+static int snd_soc_register_card(struct snd_soc_card *card)
+{
+ if (!card->name || !card->dev)
+ return -EINVAL;
+
+ INIT_LIST_HEAD(&card->list);
+ card->instantiated = 0;
+
+ mutex_lock(&client_mutex);
+ list_add(&card->list, &card_list);
+ snd_soc_instantiate_cards();
+ mutex_unlock(&client_mutex);
+
+ dev_dbg(card->dev, "Registered card '%s'\n", card->name);
+
+ return 0;
+}
+
+/**
+ * snd_soc_unregister_card - Unregister a card with the ASoC core
+ *
+ * @param card Card to unregister
+ *
+ * Note that currently this is an internal only function: it will be
+ * exposed to machine drivers after further backporting of ASoC v2
+ * registration APIs.
+ */
+static int snd_soc_unregister_card(struct snd_soc_card *card)
+{
+ mutex_lock(&client_mutex);
+ list_del(&card->list);
+ mutex_unlock(&client_mutex);
+
+ dev_dbg(card->dev, "Unregistered card '%s'\n", card->name);
+
+ return 0;
+}
+
+/**
+ * snd_soc_register_dai - Register a DAI with the ASoC core
+ *
+ * @param dai DAI to register
+ */
+int snd_soc_register_dai(struct snd_soc_dai *dai)
+{
+ if (!dai->name)
+ return -EINVAL;
+
+ /* The device should become mandatory over time */
+ if (!dai->dev)
+ printk(KERN_WARNING "No device for DAI %s\n", dai->name);
+
+ INIT_LIST_HEAD(&dai->list);
+
+ mutex_lock(&client_mutex);
+ list_add(&dai->list, &dai_list);
+ snd_soc_instantiate_cards();
+ mutex_unlock(&client_mutex);
+
+ pr_debug("Registered DAI '%s'\n", dai->name);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_register_dai);
+
+/**
+ * snd_soc_unregister_dai - Unregister a DAI from the ASoC core
+ *
+ * @param dai DAI to unregister
+ */
+void snd_soc_unregister_dai(struct snd_soc_dai *dai)
+{
+ mutex_lock(&client_mutex);
+ list_del(&dai->list);
+ mutex_unlock(&client_mutex);
+
+ pr_debug("Unregistered DAI '%s'\n", dai->name);
+}
+EXPORT_SYMBOL_GPL(snd_soc_unregister_dai);
+
+/**
+ * snd_soc_register_dais - Register multiple DAIs with the ASoC core
+ *
+ * @param dai Array of DAIs to register
+ * @param count Number of DAIs
+ */
+int snd_soc_register_dais(struct snd_soc_dai *dai, size_t count)
+{
+ int i, ret;
+
+ for (i = 0; i < count; i++) {
+ ret = snd_soc_register_dai(&dai[i]);
+ if (ret != 0)
+ goto err;
+ }
+
+ return 0;
+
+err:
+ for (i--; i >= 0; i--)
+ snd_soc_unregister_dai(&dai[i]);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(snd_soc_register_dais);
+
+/**
+ * snd_soc_unregister_dais - Unregister multiple DAIs from the ASoC core
+ *
+ * @param dai Array of DAIs to unregister
+ * @param count Number of DAIs
+ */
+void snd_soc_unregister_dais(struct snd_soc_dai *dai, size_t count)
+{
+ int i;
+
+ for (i = 0; i < count; i++)
+ snd_soc_unregister_dai(&dai[i]);
+}
+EXPORT_SYMBOL_GPL(snd_soc_unregister_dais);
+
+/**
+ * snd_soc_register_platform - Register a platform with the ASoC core
+ *
+ * @param platform platform to register
+ */
+int snd_soc_register_platform(struct snd_soc_platform *platform)
+{
+ if (!platform->name)
+ return -EINVAL;
+
+ INIT_LIST_HEAD(&platform->list);
+
+ mutex_lock(&client_mutex);
+ list_add(&platform->list, &platform_list);
+ snd_soc_instantiate_cards();
+ mutex_unlock(&client_mutex);
+
+ pr_debug("Registered platform '%s'\n", platform->name);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_register_platform);
+
+/**
+ * snd_soc_unregister_platform - Unregister a platform from the ASoC core
+ *
+ * @param platform platform to unregister
+ */
+void snd_soc_unregister_platform(struct snd_soc_platform *platform)
{
- printk(KERN_INFO "ASoC version %s\n", SND_SOC_VERSION);
+ mutex_lock(&client_mutex);
+ list_del(&platform->list);
+ mutex_unlock(&client_mutex);
+
+ pr_debug("Unregistered platform '%s'\n", platform->name);
+}
+EXPORT_SYMBOL_GPL(snd_soc_unregister_platform);
+
+/**
+ * snd_soc_register_codec - Register a codec with the ASoC core
+ *
+ * @param codec codec to register
+ */
+int snd_soc_register_codec(struct snd_soc_codec *codec)
+{
+ if (!codec->name)
+ return -EINVAL;
+
+ /* The device should become mandatory over time */
+ if (!codec->dev)
+ printk(KERN_WARNING "No device for codec %s\n", codec->name);
+
+ INIT_LIST_HEAD(&codec->list);
+
+ mutex_lock(&client_mutex);
+ list_add(&codec->list, &codec_list);
+ snd_soc_instantiate_cards();
+ mutex_unlock(&client_mutex);
+
+ pr_debug("Registered codec '%s'\n", codec->name);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_register_codec);
+
+/**
+ * snd_soc_unregister_codec - Unregister a codec from the ASoC core
+ *
+ * @param codec codec to unregister
+ */
+void snd_soc_unregister_codec(struct snd_soc_codec *codec)
+{
+ mutex_lock(&client_mutex);
+ list_del(&codec->list);
+ mutex_unlock(&client_mutex);
+
+ pr_debug("Unregistered codec '%s'\n", codec->name);
+}
+EXPORT_SYMBOL_GPL(snd_soc_unregister_codec);
+
+static int __init snd_soc_init(void)
+{
+#ifdef CONFIG_DEBUG_FS
+ debugfs_root = debugfs_create_dir("asoc", NULL);
+ if (IS_ERR(debugfs_root) || !debugfs_root) {
+ printk(KERN_WARNING
+ "ASoC: Failed to create debugfs directory\n");
+ debugfs_root = NULL;
+ }
+#endif
+
return platform_driver_register(&soc_driver);
}
-static void snd_soc_exit(void)
+static void __exit snd_soc_exit(void)
{
+#ifdef CONFIG_DEBUG_FS
+ debugfs_remove_recursive(debugfs_root);
+#endif
platform_driver_unregister(&soc_driver);
}
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 7351db9606e..8863eddbac0 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -37,7 +37,6 @@
#include <linux/bitops.h>
#include <linux/platform_device.h>
#include <linux/jiffies.h>
-#include <linux/debugfs.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -67,17 +66,13 @@ static int dapm_status = 1;
module_param(dapm_status, int, 0);
MODULE_PARM_DESC(dapm_status, "enable DPM sysfs entries");
-static struct dentry *asoc_debugfs;
-
-static u32 pop_time;
-
-static void pop_wait(void)
+static void pop_wait(u32 pop_time)
{
if (pop_time)
schedule_timeout_uninterruptible(msecs_to_jiffies(pop_time));
}
-static void pop_dbg(const char *fmt, ...)
+static void pop_dbg(u32 pop_time, const char *fmt, ...)
{
va_list args;
@@ -85,7 +80,7 @@ static void pop_dbg(const char *fmt, ...)
if (pop_time) {
vprintk(fmt, args);
- pop_wait();
+ pop_wait(pop_time);
}
va_end(args);
@@ -230,10 +225,11 @@ static int dapm_update_bits(struct snd_soc_dapm_widget *widget)
change = old != new;
if (change) {
- pop_dbg("pop test %s : %s in %d ms\n", widget->name,
- widget->power ? "on" : "off", pop_time);
+ pop_dbg(codec->pop_time, "pop test %s : %s in %d ms\n",
+ widget->name, widget->power ? "on" : "off",
+ codec->pop_time);
snd_soc_write(codec, widget->reg, new);
- pop_wait();
+ pop_wait(codec->pop_time);
}
pr_debug("reg %x old %x new %x change %d\n", widget->reg,
old, new, change);
@@ -293,7 +289,7 @@ static int dapm_new_mixer(struct snd_soc_codec *codec,
struct snd_soc_dapm_widget *w)
{
int i, ret = 0;
- char name[32];
+ size_t name_len;
struct snd_soc_dapm_path *path;
/* add kcontrol */
@@ -307,11 +303,16 @@ static int dapm_new_mixer(struct snd_soc_codec *codec,
continue;
/* add dapm control with long name */
- snprintf(name, 32, "%s %s", w->name, w->kcontrols[i].name);
- path->long_name = kstrdup (name, GFP_KERNEL);
+ name_len = 2 + strlen(w->name)
+ + strlen(w->kcontrols[i].name);
+ path->long_name = kmalloc(name_len, GFP_KERNEL);
if (path->long_name == NULL)
return -ENOMEM;
+ snprintf(path->long_name, name_len, "%s %s",
+ w->name, w->kcontrols[i].name);
+ path->long_name[name_len - 1] = '\0';
+
path->kcontrol = snd_soc_cnew(&w->kcontrols[i], w,
path->long_name);
ret = snd_ctl_add(codec->card, path->kcontrol);
@@ -821,23 +822,9 @@ static DEVICE_ATTR(dapm_widget, 0444, dapm_widget_show, NULL);
int snd_soc_dapm_sys_add(struct device *dev)
{
- int ret = 0;
-
if (!dapm_status)
return 0;
-
- ret = device_create_file(dev, &dev_attr_dapm_widget);
- if (ret != 0)
- return ret;
-
- asoc_debugfs = debugfs_create_dir("asoc", NULL);
- if (!IS_ERR(asoc_debugfs) && asoc_debugfs)
- debugfs_create_u32("dapm_pop_time", 0744, asoc_debugfs,
- &pop_time);
- else
- asoc_debugfs = NULL;
-
- return 0;
+ return device_create_file(dev, &dev_attr_dapm_widget);
}
static void snd_soc_dapm_sys_remove(struct device *dev)
@@ -845,9 +832,6 @@ static void snd_soc_dapm_sys_remove(struct device *dev)
if (dapm_status) {
device_remove_file(dev, &dev_attr_dapm_widget);
}
-
- if (asoc_debugfs)
- debugfs_remove_recursive(asoc_debugfs);
}
/* free all dapm widgets and resources */
@@ -1007,28 +991,6 @@ err:
}
/**
- * snd_soc_dapm_connect_input - connect dapm widgets
- * @codec: audio codec
- * @sink: name of target widget
- * @control: mixer control name
- * @source: name of source name
- *
- * Connects 2 dapm widgets together via a named audio path. The sink is
- * the widget receiving the audio signal, whilst the source is the sender
- * of the audio signal.
- *
- * This function has been deprecated in favour of snd_soc_dapm_add_routes().
- *
- * Returns 0 for success else error.
- */
-int snd_soc_dapm_connect_input(struct snd_soc_codec *codec, const char *sink,
- const char *control, const char *source)
-{
- return snd_soc_dapm_add_route(codec, sink, control, source);
-}
-EXPORT_SYMBOL_GPL(snd_soc_dapm_connect_input);
-
-/**
* snd_soc_dapm_add_routes - Add routes between DAPM widgets
* @codec: codec
* @route: audio routes
@@ -1358,8 +1320,12 @@ int snd_soc_dapm_new_controls(struct snd_soc_codec *codec,
for (i = 0; i < num; i++) {
ret = snd_soc_dapm_new_control(codec, widget);
- if (ret < 0)
+ if (ret < 0) {
+ printk(KERN_ERR
+ "ASoC: Failed to create DAPM control %s: %d\n",
+ widget->name, ret);
return ret;
+ }
widget++;
}
return 0;
@@ -1440,11 +1406,11 @@ int snd_soc_dapm_set_bias_level(struct snd_soc_device *socdev,
enum snd_soc_bias_level level)
{
struct snd_soc_codec *codec = socdev->codec;
- struct snd_soc_machine *machine = socdev->machine;
+ struct snd_soc_card *card = socdev->card;
int ret = 0;
- if (machine->set_bias_level)
- ret = machine->set_bias_level(machine, level);
+ if (card->set_bias_level)
+ ret = card->set_bias_level(card, level);
if (ret == 0 && codec->set_bias_level)
ret = codec->set_bias_level(codec, level);
diff --git a/sound/sound_core.c b/sound/sound_core.c
index a75b289a5d7..2b302bbffe7 100644
--- a/sound/sound_core.c
+++ b/sound/sound_core.c
@@ -10,6 +10,7 @@
#include <linux/module.h>
#include <linux/device.h>
#include <linux/err.h>
+#include <sound/core.h>
#ifdef CONFIG_SOUND_OSS_CORE
static int __init init_oss_soundcore(void);
@@ -457,7 +458,7 @@ EXPORT_SYMBOL(unregister_sound_mixer);
void unregister_sound_midi(int unit)
{
- return sound_remove_unit(&chains[2], unit);
+ sound_remove_unit(&chains[2], unit);
}
EXPORT_SYMBOL(unregister_sound_midi);
@@ -474,7 +475,7 @@ EXPORT_SYMBOL(unregister_sound_midi);
void unregister_sound_dsp(int unit)
{
- return sound_remove_unit(&chains[3], unit);
+ sound_remove_unit(&chains[3], unit);
}
@@ -507,7 +508,7 @@ static struct sound_unit *__look_for_unit(int chain, int unit)
return NULL;
}
-int soundcore_open(struct inode *inode, struct file *file)
+static int soundcore_open(struct inode *inode, struct file *file)
{
int chain;
int unit = iminor(inode);
diff --git a/sound/usb/caiaq/caiaq-control.c b/sound/usb/caiaq/caiaq-control.c
index 798ca124da5..ccd763dd716 100644
--- a/sound/usb/caiaq/caiaq-control.c
+++ b/sound/usb/caiaq/caiaq-control.c
@@ -247,69 +247,56 @@ static struct caiaq_controller a8dj_controller[] = {
{ "Software lock", 40 }
};
-int __devinit snd_usb_caiaq_control_init(struct snd_usb_caiaqdev *dev)
+static int __devinit add_controls(struct caiaq_controller *c, int num,
+ struct snd_usb_caiaqdev *dev)
{
- int i;
+ int i, ret;
struct snd_kcontrol *kc;
+ for (i = 0; i < num; i++, c++) {
+ kcontrol_template.name = c->name;
+ kcontrol_template.private_value = c->index;
+ kc = snd_ctl_new1(&kcontrol_template, dev);
+ ret = snd_ctl_add(dev->chip.card, kc);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+int __devinit snd_usb_caiaq_control_init(struct snd_usb_caiaqdev *dev)
+{
+ int ret = 0;
+
switch (dev->chip.usb_id) {
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1):
- for (i = 0; i < ARRAY_SIZE(ak1_controller); i++) {
- struct caiaq_controller *c = ak1_controller + i;
- kcontrol_template.name = c->name;
- kcontrol_template.private_value = c->index;
- kc = snd_ctl_new1(&kcontrol_template, dev);
- snd_ctl_add(dev->chip.card, kc);
- }
-
+ ret = add_controls(ak1_controller,
+ ARRAY_SIZE(ak1_controller), dev);
break;
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL2):
- for (i = 0; i < ARRAY_SIZE(rk2_controller); i++) {
- struct caiaq_controller *c = rk2_controller + i;
- kcontrol_template.name = c->name;
- kcontrol_template.private_value = c->index;
- kc = snd_ctl_new1(&kcontrol_template, dev);
- snd_ctl_add(dev->chip.card, kc);
- }
-
+ ret = add_controls(rk2_controller,
+ ARRAY_SIZE(rk2_controller), dev);
break;
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3):
- for (i = 0; i < ARRAY_SIZE(rk3_controller); i++) {
- struct caiaq_controller *c = rk3_controller + i;
- kcontrol_template.name = c->name;
- kcontrol_template.private_value = c->index;
- kc = snd_ctl_new1(&kcontrol_template, dev);
- snd_ctl_add(dev->chip.card, kc);
- }
-
+ ret = add_controls(rk3_controller,
+ ARRAY_SIZE(rk3_controller), dev);
break;
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER):
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2):
- for (i = 0; i < ARRAY_SIZE(kore_controller); i++) {
- struct caiaq_controller *c = kore_controller + i;
- kcontrol_template.name = c->name;
- kcontrol_template.private_value = c->index;
- kc = snd_ctl_new1(&kcontrol_template, dev);
- snd_ctl_add(dev->chip.card, kc);
- }
-
+ ret = add_controls(kore_controller,
+ ARRAY_SIZE(kore_controller), dev);
break;
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ):
- for (i = 0; i < ARRAY_SIZE(a8dj_controller); i++) {
- struct caiaq_controller *c = a8dj_controller + i;
- kcontrol_template.name = c->name;
- kcontrol_template.private_value = c->index;
- kc = snd_ctl_new1(&kcontrol_template, dev);
- snd_ctl_add(dev->chip.card, kc);
- }
-
+ ret = add_controls(a8dj_controller,
+ ARRAY_SIZE(a8dj_controller), dev);
break;
}
- return 0;
+ return ret;
}
diff --git a/sound/usb/caiaq/caiaq-device.c b/sound/usb/caiaq/caiaq-device.c
index 83175083e50..b143ef7152f 100644
--- a/sound/usb/caiaq/caiaq-device.c
+++ b/sound/usb/caiaq/caiaq-device.c
@@ -42,7 +42,7 @@
#endif
MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
-MODULE_DESCRIPTION("caiaq USB audio, version 1.3.8");
+MODULE_DESCRIPTION("caiaq USB audio, version 1.3.9");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2},"
"{Native Instruments, RigKontrol3},"
diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c
index 5962e4b8442..6d9f9b135c6 100644
--- a/sound/usb/usbmidi.c
+++ b/sound/usb/usbmidi.c
@@ -880,7 +880,7 @@ static void snd_usbmidi_output_trigger(struct snd_rawmidi_substream *substream,
snd_rawmidi_transmit_ack(substream, 1);
return;
}
- tasklet_hi_schedule(&port->ep->tasklet);
+ tasklet_schedule(&port->ep->tasklet);
}
}
diff --git a/sound/usb/usx2y/usb_stream.c b/sound/usb/usx2y/usb_stream.c
index ff23cc1ce3b..70b96355ca4 100644
--- a/sound/usb/usx2y/usb_stream.c
+++ b/sound/usb/usx2y/usb_stream.c
@@ -276,7 +276,8 @@ static void subs_set_complete(struct urb **urbs, void (*complete)(struct urb *))
}
}
-int usb_stream_prepare_playback(struct usb_stream_kernel *sk, struct urb *inurb)
+static int usb_stream_prepare_playback(struct usb_stream_kernel *sk,
+ struct urb *inurb)
{
struct usb_stream *s = sk->s;
struct urb *io;