]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge current mainline tree into linux-omap tree
authorTony Lindgren <tony@atomide.com>
Fri, 25 Apr 2008 18:49:52 +0000 (11:49 -0700)
committerTony Lindgren <tony@atomide.com>
Fri, 25 Apr 2008 18:49:52 +0000 (11:49 -0700)
Merge branches 'master' and 'linus'

Conflicts:

sound/soc/Kconfig
sound/soc/Makefile

962 files changed:
CREDITS
Documentation/filesystems/nfs-rdma.txt [new file with mode: 0644]
Documentation/sound/alsa/ALSA-Configuration.txt
Documentation/video4linux/CARDLIST.au0828 [new file with mode: 0644]
Documentation/video4linux/CARDLIST.bttv
Documentation/video4linux/CARDLIST.cx23885
Documentation/video4linux/CARDLIST.cx88
Documentation/video4linux/CARDLIST.saa7134
Documentation/video4linux/extract_xc3028.pl
MAINTAINERS
arch/alpha/kernel/osf_sys.c
arch/alpha/kernel/pci.c
arch/alpha/kernel/sys_nautilus.c
arch/arm/mach-integrator/time.c
arch/arm/mach-lh7a40x/arch-kev7a400.c
arch/arm/mm/Kconfig
arch/arm/mm/proc-arm1020.S
arch/arm/mm/proc-arm1020e.S
arch/arm/mm/proc-arm1022.S
arch/arm/mm/proc-arm1026.S
arch/arm/mm/proc-arm6_7.S
arch/arm/mm/proc-arm720.S
arch/arm/mm/proc-arm740.S
arch/arm/mm/proc-arm7tdmi.S
arch/arm/mm/proc-arm920.S
arch/arm/mm/proc-arm922.S
arch/arm/mm/proc-arm925.S
arch/arm/mm/proc-arm926.S
arch/arm/mm/proc-arm940.S
arch/arm/mm/proc-arm946.S
arch/arm/mm/proc-arm9tdmi.S
arch/arm/mm/proc-feroceon.S
arch/arm/mm/proc-sa110.S
arch/arm/mm/proc-sa1100.S
arch/arm/mm/proc-v6.S
arch/arm/mm/proc-v7.S
arch/arm/mm/proc-xsc3.S
arch/arm/mm/proc-xscale.S
arch/blackfin/Kconfig
arch/blackfin/Makefile
arch/blackfin/boot/.gitignore [new file with mode: 0644]
arch/blackfin/configs/BF527-EZKIT_defconfig
arch/blackfin/configs/BF533-EZKIT_defconfig
arch/blackfin/configs/BF533-STAMP_defconfig
arch/blackfin/configs/BF537-STAMP_defconfig
arch/blackfin/configs/BF548-EZKIT_defconfig
arch/blackfin/configs/BF561-EZKIT_defconfig
arch/blackfin/configs/CM-BF533_defconfig [new file with mode: 0644]
arch/blackfin/configs/CM-BF537E_defconfig [new file with mode: 0644]
arch/blackfin/configs/CM-BF537U_defconfig [new file with mode: 0644]
arch/blackfin/configs/CM-BF548_defconfig [new file with mode: 0644]
arch/blackfin/configs/CM-BF561_defconfig [new file with mode: 0644]
arch/blackfin/configs/H8606_defconfig
arch/blackfin/configs/IP0X_defconfig [new file with mode: 0644]
arch/blackfin/configs/PNAV-10_defconfig
arch/blackfin/configs/SRV1_defconfig [new file with mode: 0644]
arch/blackfin/kernel/Makefile
arch/blackfin/kernel/bfin_dma_5xx.c
arch/blackfin/kernel/bfin_gpio.c
arch/blackfin/kernel/cplb-mpu/cplbinfo.c
arch/blackfin/kernel/cplb-mpu/cplbinit.c
arch/blackfin/kernel/cplb-mpu/cplbmgr.c
arch/blackfin/kernel/cplb-nompu/cplbinfo.c
arch/blackfin/kernel/cplb-nompu/cplbinit.c
arch/blackfin/kernel/dma-mapping.c
arch/blackfin/kernel/gptimers.c
arch/blackfin/kernel/process.c
arch/blackfin/kernel/ptrace.c
arch/blackfin/kernel/reboot.c
arch/blackfin/kernel/setup.c
arch/blackfin/kernel/signal.c
arch/blackfin/kernel/sys_bfin.c
arch/blackfin/kernel/time-ts.c [new file with mode: 0644]
arch/blackfin/kernel/time.c
arch/blackfin/kernel/traps.c
arch/blackfin/kernel/vmlinux.lds.S
arch/blackfin/mach-bf527/Makefile
arch/blackfin/mach-bf527/boards/ezkit.c
arch/blackfin/mach-bf527/cpu.c [deleted file]
arch/blackfin/mach-bf527/dma.c
arch/blackfin/mach-bf527/head.S
arch/blackfin/mach-bf533/Makefile
arch/blackfin/mach-bf533/boards/H8606.c
arch/blackfin/mach-bf533/boards/Kconfig
arch/blackfin/mach-bf533/boards/Makefile
arch/blackfin/mach-bf533/boards/cm_bf533.c
arch/blackfin/mach-bf533/boards/ezkit.c
arch/blackfin/mach-bf533/boards/generic_board.c
arch/blackfin/mach-bf533/boards/ip0x.c [new file with mode: 0644]
arch/blackfin/mach-bf533/boards/stamp.c
arch/blackfin/mach-bf533/cpu.c [deleted file]
arch/blackfin/mach-bf533/dma.c
arch/blackfin/mach-bf533/head.S
arch/blackfin/mach-bf537/Makefile
arch/blackfin/mach-bf537/boards/cm_bf537.c
arch/blackfin/mach-bf537/boards/generic_board.c
arch/blackfin/mach-bf537/boards/minotaur.c
arch/blackfin/mach-bf537/boards/pnav10.c
arch/blackfin/mach-bf537/boards/stamp.c
arch/blackfin/mach-bf537/cpu.c [deleted file]
arch/blackfin/mach-bf537/dma.c
arch/blackfin/mach-bf537/head.S
arch/blackfin/mach-bf548/Makefile
arch/blackfin/mach-bf548/boards/Kconfig
arch/blackfin/mach-bf548/boards/Makefile
arch/blackfin/mach-bf548/boards/cm_bf548.c [new file with mode: 0644]
arch/blackfin/mach-bf548/boards/ezkit.c
arch/blackfin/mach-bf548/cpu.c [deleted file]
arch/blackfin/mach-bf548/dma.c
arch/blackfin/mach-bf548/head.S
arch/blackfin/mach-bf561/boards/cm_bf561.c
arch/blackfin/mach-bf561/boards/ezkit.c
arch/blackfin/mach-bf561/boards/generic_board.c
arch/blackfin/mach-bf561/boards/tepla.c
arch/blackfin/mach-bf561/dma.c
arch/blackfin/mach-bf561/head.S
arch/blackfin/mach-common/Makefile
arch/blackfin/mach-common/arch_checks.c
arch/blackfin/mach-common/cpufreq.c [new file with mode: 0644]
arch/blackfin/mach-common/entry.S
arch/blackfin/mach-common/ints-priority.c
arch/blackfin/mach-common/lock.S
arch/blackfin/mm/blackfin_sram.c
arch/blackfin/oprofile/common.c
arch/blackfin/oprofile/op_model_bf533.c
arch/sparc/kernel/entry.S
arch/sparc/kernel/signal.c
arch/sparc64/Kconfig
arch/sparc64/defconfig
arch/sparc64/kernel/ebus.c
arch/sparc64/kernel/entry.S
arch/sparc64/kernel/entry.h
arch/sparc64/kernel/etrap.S
arch/sparc64/kernel/iommu.c
arch/sparc64/kernel/isa.c
arch/sparc64/kernel/mdesc.c
arch/sparc64/kernel/of_device.c
arch/sparc64/kernel/pci.c
arch/sparc64/kernel/pci_fire.c
arch/sparc64/kernel/pci_impl.h
arch/sparc64/kernel/pci_msi.c
arch/sparc64/kernel/pci_psycho.c
arch/sparc64/kernel/pci_sabre.c
arch/sparc64/kernel/pci_schizo.c
arch/sparc64/kernel/pci_sun4v.c
arch/sparc64/kernel/prom.c
arch/sparc64/kernel/rtrap.S
arch/sparc64/kernel/sbus.c
arch/sparc64/kernel/setup.c
arch/sparc64/kernel/signal.c
arch/sparc64/kernel/signal32.c
arch/sparc64/kernel/smp.c
arch/sparc64/kernel/sparc64_ksyms.c
arch/sparc64/kernel/stacktrace.c
arch/sparc64/kernel/sun4v_tlb_miss.S
arch/sparc64/kernel/sysfs.c
arch/sparc64/kernel/traps.c
arch/sparc64/kernel/tsb.S
arch/sparc64/kernel/winfixup.S
arch/sparc64/mm/init.c
arch/sparc64/mm/tsb.c
arch/sparc64/mm/ultra.S
arch/x86/Kconfig
arch/x86/kernel/apic_32.c
arch/x86/kernel/apic_64.c
arch/x86/kernel/process_32.c
arch/x86/kernel/process_64.c
arch/x86/kernel/setup.c
arch/x86/kernel/setup_32.c
arch/x86/kernel/smpboot.c
arch/x86/kernel/tlb_64.c
arch/x86/kernel/vsyscall_64.c
arch/x86/mach-visws/mpparse.c
arch/x86/mach-voyager/voyager_smp.c
arch/x86/mm/dump_pagetables.c
arch/x86/mm/pageattr.c
arch/x86/mm/srat_64.c
drivers/char/Kconfig
drivers/char/Makefile
drivers/char/bfin-otp.c [new file with mode: 0644]
drivers/char/mwave/tp3780i.c
drivers/input/misc/Kconfig
drivers/media/Kconfig
drivers/media/common/ir-functions.c
drivers/media/common/ir-keymaps.c
drivers/media/common/saa7146_core.c
drivers/media/common/saa7146_i2c.c
drivers/media/common/saa7146_vbi.c
drivers/media/common/saa7146_video.c
drivers/media/dvb/b2c2/Kconfig
drivers/media/dvb/b2c2/Makefile
drivers/media/dvb/b2c2/flexcop-common.h
drivers/media/dvb/b2c2/flexcop-dma.c
drivers/media/dvb/b2c2/flexcop-eeprom.c
drivers/media/dvb/b2c2/flexcop-fe-tuner.c
drivers/media/dvb/b2c2/flexcop-i2c.c
drivers/media/dvb/b2c2/flexcop-misc.c
drivers/media/dvb/b2c2/flexcop-pci.c
drivers/media/dvb/b2c2/flexcop-reg.h
drivers/media/dvb/b2c2/flexcop-sram.c
drivers/media/dvb/b2c2/flexcop-usb.c
drivers/media/dvb/b2c2/flexcop.c
drivers/media/dvb/bt8xx/Kconfig
drivers/media/dvb/bt8xx/Makefile
drivers/media/dvb/bt8xx/dst.c
drivers/media/dvb/bt8xx/dst_ca.c
drivers/media/dvb/bt8xx/dvb-bt8xx.c
drivers/media/dvb/bt8xx/dvb-bt8xx.h
drivers/media/dvb/cinergyT2/cinergyT2.c
drivers/media/dvb/dvb-core/demux.h
drivers/media/dvb/dvb-core/dmxdev.c
drivers/media/dvb/dvb-core/dvb_ca_en50221.c
drivers/media/dvb/dvb-core/dvb_demux.c
drivers/media/dvb/dvb-core/dvb_frontend.c
drivers/media/dvb/dvb-core/dvb_net.c
drivers/media/dvb/dvb-core/dvb_ringbuffer.c
drivers/media/dvb/dvb-core/dvb_ringbuffer.h
drivers/media/dvb/dvb-core/dvbdev.c
drivers/media/dvb/dvb-core/dvbdev.h
drivers/media/dvb/dvb-usb/Kconfig
drivers/media/dvb/dvb-usb/a800.c
drivers/media/dvb/dvb-usb/af9005.c
drivers/media/dvb/dvb-usb/au6610.c
drivers/media/dvb/dvb-usb/cxusb.c
drivers/media/dvb/dvb-usb/dib0700.h
drivers/media/dvb/dvb-usb/dib0700_core.c
drivers/media/dvb/dvb-usb/dib0700_devices.c
drivers/media/dvb/dvb-usb/dibusb-mb.c
drivers/media/dvb/dvb-usb/dibusb-mc.c
drivers/media/dvb/dvb-usb/digitv.c
drivers/media/dvb/dvb-usb/dtt200u.c
drivers/media/dvb/dvb-usb/dvb-usb-common.h
drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
drivers/media/dvb/dvb-usb/dvb-usb-ids.h
drivers/media/dvb/dvb-usb/dvb-usb-init.c
drivers/media/dvb/dvb-usb/dvb-usb.h
drivers/media/dvb/dvb-usb/gl861.c
drivers/media/dvb/dvb-usb/gp8psk-fe.c
drivers/media/dvb/dvb-usb/gp8psk.c
drivers/media/dvb/dvb-usb/m920x.c
drivers/media/dvb/dvb-usb/nova-t-usb2.c
drivers/media/dvb/dvb-usb/opera1.c
drivers/media/dvb/dvb-usb/ttusb2.c
drivers/media/dvb/dvb-usb/umt-010.c
drivers/media/dvb/dvb-usb/vp702x-fe.c
drivers/media/dvb/dvb-usb/vp702x.c
drivers/media/dvb/dvb-usb/vp7045.c
drivers/media/dvb/frontends/Kconfig
drivers/media/dvb/frontends/Makefile
drivers/media/dvb/frontends/au8522.c [new file with mode: 0644]
drivers/media/dvb/frontends/au8522.h [new file with mode: 0644]
drivers/media/dvb/frontends/bcm3510.c
drivers/media/dvb/frontends/bcm3510.h
drivers/media/dvb/frontends/bsbe1.h
drivers/media/dvb/frontends/bsru6.h
drivers/media/dvb/frontends/cx22700.c
drivers/media/dvb/frontends/cx22700.h
drivers/media/dvb/frontends/cx22702.c
drivers/media/dvb/frontends/cx22702.h
drivers/media/dvb/frontends/cx24110.c
drivers/media/dvb/frontends/cx24110.h
drivers/media/dvb/frontends/cx24113.h [new file with mode: 0644]
drivers/media/dvb/frontends/cx24123.c
drivers/media/dvb/frontends/cx24123.h
drivers/media/dvb/frontends/dib3000.h
drivers/media/dvb/frontends/dib3000mc.h
drivers/media/dvb/frontends/dib7000p.c
drivers/media/dvb/frontends/dib7000p.h
drivers/media/dvb/frontends/dvb-pll.c
drivers/media/dvb/frontends/dvb-pll.h
drivers/media/dvb/frontends/isl6405.c [new file with mode: 0644]
drivers/media/dvb/frontends/isl6405.h [new file with mode: 0644]
drivers/media/dvb/frontends/isl6421.h
drivers/media/dvb/frontends/itd1000.c [new file with mode: 0644]
drivers/media/dvb/frontends/itd1000.h [new file with mode: 0644]
drivers/media/dvb/frontends/itd1000_priv.h [new file with mode: 0644]
drivers/media/dvb/frontends/l64781.c
drivers/media/dvb/frontends/l64781.h
drivers/media/dvb/frontends/lgdt330x.c
drivers/media/dvb/frontends/lgdt330x.h
drivers/media/dvb/frontends/lnbp21.h
drivers/media/dvb/frontends/mt2060.h
drivers/media/dvb/frontends/mt2131.c
drivers/media/dvb/frontends/mt2131.h
drivers/media/dvb/frontends/mt2266.h
drivers/media/dvb/frontends/mt312.c
drivers/media/dvb/frontends/mt312.h
drivers/media/dvb/frontends/mt312_priv.h
drivers/media/dvb/frontends/mt352.c
drivers/media/dvb/frontends/mt352.h
drivers/media/dvb/frontends/nxt200x.c
drivers/media/dvb/frontends/nxt200x.h
drivers/media/dvb/frontends/nxt6000.c
drivers/media/dvb/frontends/nxt6000.h
drivers/media/dvb/frontends/or51132.c
drivers/media/dvb/frontends/or51132.h
drivers/media/dvb/frontends/or51211.c
drivers/media/dvb/frontends/or51211.h
drivers/media/dvb/frontends/qt1010.h
drivers/media/dvb/frontends/s5h1409.c
drivers/media/dvb/frontends/s5h1409.h
drivers/media/dvb/frontends/s5h1420.c
drivers/media/dvb/frontends/s5h1420.h
drivers/media/dvb/frontends/s5h1420_priv.h [new file with mode: 0644]
drivers/media/dvb/frontends/sp8870.c
drivers/media/dvb/frontends/sp8870.h
drivers/media/dvb/frontends/sp887x.c
drivers/media/dvb/frontends/sp887x.h
drivers/media/dvb/frontends/stv0297.c
drivers/media/dvb/frontends/stv0297.h
drivers/media/dvb/frontends/stv0299.c
drivers/media/dvb/frontends/stv0299.h
drivers/media/dvb/frontends/tda10021.c
drivers/media/dvb/frontends/tda10023.c
drivers/media/dvb/frontends/tda1002x.h
drivers/media/dvb/frontends/tda10048.c [new file with mode: 0644]
drivers/media/dvb/frontends/tda10048.h [new file with mode: 0644]
drivers/media/dvb/frontends/tda1004x.c
drivers/media/dvb/frontends/tda1004x.h
drivers/media/dvb/frontends/tda10086.c
drivers/media/dvb/frontends/tda10086.h
drivers/media/dvb/frontends/tda18271-common.c
drivers/media/dvb/frontends/tda18271-fe.c
drivers/media/dvb/frontends/tda18271-priv.h
drivers/media/dvb/frontends/tda18271-tables.c
drivers/media/dvb/frontends/tda18271.h
drivers/media/dvb/frontends/tda8083.c
drivers/media/dvb/frontends/tda8083.h
drivers/media/dvb/frontends/tda826x.c
drivers/media/dvb/frontends/tda826x.h
drivers/media/dvb/frontends/tda827x.c
drivers/media/dvb/frontends/tda827x.h
drivers/media/dvb/frontends/tua6100.c
drivers/media/dvb/frontends/tua6100.h
drivers/media/dvb/frontends/ves1820.c
drivers/media/dvb/frontends/ves1820.h
drivers/media/dvb/frontends/ves1x93.c
drivers/media/dvb/frontends/ves1x93.h
drivers/media/dvb/frontends/xc5000.c
drivers/media/dvb/frontends/xc5000.h
drivers/media/dvb/frontends/zl10353.c
drivers/media/dvb/frontends/zl10353.h
drivers/media/dvb/pluto2/pluto2.c
drivers/media/dvb/ttpci/av7110.c
drivers/media/dvb/ttpci/av7110.h
drivers/media/dvb/ttpci/av7110_hw.c
drivers/media/dvb/ttpci/av7110_ir.c
drivers/media/dvb/ttpci/av7110_v4l.c
drivers/media/dvb/ttpci/budget-av.c
drivers/media/dvb/ttpci/budget-ci.c
drivers/media/dvb/ttpci/budget-core.c
drivers/media/dvb/ttpci/budget.c
drivers/media/dvb/ttpci/budget.h
drivers/media/dvb/ttpci/ttpci-eeprom.c
drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
drivers/media/dvb/ttusb-dec/ttusb_dec.c
drivers/media/dvb/ttusb-dec/ttusbdecfe.c
drivers/media/radio/dsbr100.c
drivers/media/radio/miropcm20-radio.c
drivers/media/radio/miropcm20-rds.c
drivers/media/radio/radio-aimslab.c
drivers/media/radio/radio-aztech.c
drivers/media/radio/radio-cadet.c
drivers/media/radio/radio-gemtek-pci.c
drivers/media/radio/radio-gemtek.c
drivers/media/radio/radio-maestro.c
drivers/media/radio/radio-maxiradio.c
drivers/media/radio/radio-rtrack2.c
drivers/media/radio/radio-sf16fmi.c
drivers/media/radio/radio-sf16fmr2.c
drivers/media/radio/radio-si470x.c
drivers/media/radio/radio-terratec.c
drivers/media/radio/radio-trust.c
drivers/media/radio/radio-typhoon.c
drivers/media/radio/radio-zoltrix.c
drivers/media/video/Kconfig
drivers/media/video/Makefile
drivers/media/video/adv7170.c
drivers/media/video/adv7175.c
drivers/media/video/arv.c
drivers/media/video/au0828/Kconfig [new file with mode: 0644]
drivers/media/video/au0828/Makefile [new file with mode: 0644]
drivers/media/video/au0828/au0828-cards.c [new file with mode: 0644]
drivers/media/video/au0828/au0828-cards.h [new file with mode: 0644]
drivers/media/video/au0828/au0828-core.c [new file with mode: 0644]
drivers/media/video/au0828/au0828-dvb.c [new file with mode: 0644]
drivers/media/video/au0828/au0828-i2c.c [new file with mode: 0644]
drivers/media/video/au0828/au0828-reg.h [new file with mode: 0644]
drivers/media/video/au0828/au0828.h [new file with mode: 0644]
drivers/media/video/bt819.c
drivers/media/video/bt856.c
drivers/media/video/bt8xx/bttv-cards.c
drivers/media/video/bt8xx/bttv-driver.c
drivers/media/video/bt8xx/bttv-input.c
drivers/media/video/bt8xx/bttv-vbi.c
drivers/media/video/bt8xx/bttv.h
drivers/media/video/bt8xx/bttvp.h
drivers/media/video/bw-qcam.c
drivers/media/video/c-qcam.c
drivers/media/video/cafe_ccic.c
drivers/media/video/cpia.c
drivers/media/video/cpia.h
drivers/media/video/cpia2/cpia2_core.c
drivers/media/video/cpia2/cpia2_usb.c
drivers/media/video/cpia2/cpia2_v4l.c
drivers/media/video/cpia_usb.c
drivers/media/video/cx23885/Kconfig
drivers/media/video/cx23885/Makefile
drivers/media/video/cx23885/cx23885-417.c [new file with mode: 0644]
drivers/media/video/cx23885/cx23885-cards.c
drivers/media/video/cx23885/cx23885-core.c
drivers/media/video/cx23885/cx23885-dvb.c
drivers/media/video/cx23885/cx23885-i2c.c
drivers/media/video/cx23885/cx23885-video.c
drivers/media/video/cx23885/cx23885.h
drivers/media/video/cx25840/cx25840-core.c
drivers/media/video/cx25840/cx25840-core.h
drivers/media/video/cx25840/cx25840-firmware.c
drivers/media/video/cx25840/cx25840-vbi.c
drivers/media/video/cx88/Kconfig
drivers/media/video/cx88/cx88-alsa.c
drivers/media/video/cx88/cx88-blackbird.c
drivers/media/video/cx88/cx88-cards.c
drivers/media/video/cx88/cx88-core.c
drivers/media/video/cx88/cx88-dvb.c
drivers/media/video/cx88/cx88-i2c.c
drivers/media/video/cx88/cx88-input.c
drivers/media/video/cx88/cx88-mpeg.c
drivers/media/video/cx88/cx88-tvaudio.c
drivers/media/video/cx88/cx88-vbi.c
drivers/media/video/cx88/cx88-video.c
drivers/media/video/cx88/cx88.h
drivers/media/video/dabfirmware.h
drivers/media/video/dabusb.c
drivers/media/video/dpc7146.c
drivers/media/video/em28xx/Kconfig
drivers/media/video/em28xx/Makefile
drivers/media/video/em28xx/em28xx-audio.c
drivers/media/video/em28xx/em28xx-cards.c
drivers/media/video/em28xx/em28xx-core.c
drivers/media/video/em28xx/em28xx-dvb.c [new file with mode: 0644]
drivers/media/video/em28xx/em28xx-i2c.c
drivers/media/video/em28xx/em28xx-input.c
drivers/media/video/em28xx/em28xx-reg.h [new file with mode: 0644]
drivers/media/video/em28xx/em28xx-video.c
drivers/media/video/em28xx/em28xx.h
drivers/media/video/et61x251/et61x251.h
drivers/media/video/et61x251/et61x251_core.c
drivers/media/video/hexium_gemini.c
drivers/media/video/hexium_orion.c
drivers/media/video/ir-kbd-i2c.c
drivers/media/video/ivtv/Kconfig
drivers/media/video/ivtv/ivtv-cards.c
drivers/media/video/ivtv/ivtv-cards.h
drivers/media/video/ivtv/ivtv-driver.c
drivers/media/video/ivtv/ivtv-driver.h
drivers/media/video/ivtv/ivtv-fileops.c
drivers/media/video/ivtv/ivtv-i2c.c
drivers/media/video/ivtv/ivtv-ioctl.c
drivers/media/video/ivtv/ivtv-irq.c
drivers/media/video/ivtv/ivtv-mailbox.c
drivers/media/video/ivtv/ivtv-queue.c
drivers/media/video/ivtv/ivtv-streams.c
drivers/media/video/ivtv/ivtv-yuv.c
drivers/media/video/meye.c
drivers/media/video/msp3400-driver.c
drivers/media/video/msp3400-kthreads.c
drivers/media/video/mt20xx.c
drivers/media/video/mt20xx.h
drivers/media/video/mt9m001.c [new file with mode: 0644]
drivers/media/video/mt9v022.c [new file with mode: 0644]
drivers/media/video/mxb.c
drivers/media/video/ov511.c
drivers/media/video/ov511.h
drivers/media/video/ovcamchip/ovcamchip_priv.h
drivers/media/video/pms.c
drivers/media/video/pvrusb2/Kconfig
drivers/media/video/pvrusb2/Makefile
drivers/media/video/pvrusb2/pvrusb2-context.c
drivers/media/video/pvrusb2/pvrusb2-context.h
drivers/media/video/pvrusb2/pvrusb2-ctrl.c
drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
drivers/media/video/pvrusb2/pvrusb2-debug.h
drivers/media/video/pvrusb2/pvrusb2-debugifc.c
drivers/media/video/pvrusb2/pvrusb2-devattr.c
drivers/media/video/pvrusb2/pvrusb2-devattr.h
drivers/media/video/pvrusb2/pvrusb2-dvb.c [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-dvb.h [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-encoder.c
drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h
drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
drivers/media/video/pvrusb2/pvrusb2-hdw.c
drivers/media/video/pvrusb2/pvrusb2-hdw.h
drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
drivers/media/video/pvrusb2/pvrusb2-io.c
drivers/media/video/pvrusb2/pvrusb2-io.h
drivers/media/video/pvrusb2/pvrusb2-main.c
drivers/media/video/pvrusb2/pvrusb2-std.c
drivers/media/video/pvrusb2/pvrusb2-sysfs.c
drivers/media/video/pvrusb2/pvrusb2-v4l2.c
drivers/media/video/pwc/pwc-if.c
drivers/media/video/pwc/pwc-v4l.c
drivers/media/video/pxa_camera.c [new file with mode: 0644]
drivers/media/video/saa5249.c
drivers/media/video/saa6588.c
drivers/media/video/saa7110.c
drivers/media/video/saa7111.c
drivers/media/video/saa7114.c
drivers/media/video/saa7115.c
drivers/media/video/saa711x.c
drivers/media/video/saa7134/Kconfig
drivers/media/video/saa7134/saa7134-alsa.c
drivers/media/video/saa7134/saa7134-cards.c
drivers/media/video/saa7134/saa7134-core.c
drivers/media/video/saa7134/saa7134-dvb.c
drivers/media/video/saa7134/saa7134-empress.c
drivers/media/video/saa7134/saa7134-i2c.c
drivers/media/video/saa7134/saa7134-input.c
drivers/media/video/saa7134/saa7134-reg.h
drivers/media/video/saa7134/saa7134-ts.c
drivers/media/video/saa7134/saa7134-tvaudio.c
drivers/media/video/saa7134/saa7134-vbi.c
drivers/media/video/saa7134/saa7134-video.c
drivers/media/video/saa7134/saa7134.h
drivers/media/video/saa717x.c [new file with mode: 0644]
drivers/media/video/saa7185.c
drivers/media/video/se401.c
drivers/media/video/sn9c102/sn9c102.h
drivers/media/video/sn9c102/sn9c102_core.c
drivers/media/video/sn9c102/sn9c102_sensor.h
drivers/media/video/soc_camera.c [new file with mode: 0644]
drivers/media/video/stk-webcam.c
drivers/media/video/stradis.c
drivers/media/video/stv680.c
drivers/media/video/tcm825x.c
drivers/media/video/tda8290.c
drivers/media/video/tda8290.h
drivers/media/video/tda9840.c
drivers/media/video/tda9887.c
drivers/media/video/tda9887.h
drivers/media/video/tea5761.c
drivers/media/video/tea5761.h
drivers/media/video/tea5767.c
drivers/media/video/tea5767.h
drivers/media/video/tea6415c.c
drivers/media/video/tea6420.c
drivers/media/video/tuner-core.c
drivers/media/video/tuner-i2c.h
drivers/media/video/tuner-simple.c
drivers/media/video/tuner-simple.h
drivers/media/video/tuner-types.c
drivers/media/video/tuner-xc2028-types.h
drivers/media/video/tuner-xc2028.c
drivers/media/video/tuner-xc2028.h
drivers/media/video/tvaudio.c
drivers/media/video/tveeprom.c
drivers/media/video/tvp5150.c
drivers/media/video/usbvideo/ibmcam.c
drivers/media/video/usbvideo/konicawc.c
drivers/media/video/usbvideo/quickcam_messenger.c
drivers/media/video/usbvideo/ultracam.c
drivers/media/video/usbvideo/usbvideo.c
drivers/media/video/usbvideo/vicam.c
drivers/media/video/usbvision/usbvision-core.c
drivers/media/video/usbvision/usbvision-i2c.c
drivers/media/video/usbvision/usbvision-video.c
drivers/media/video/v4l1-compat.c
drivers/media/video/videobuf-core.c
drivers/media/video/videobuf-dma-sg.c
drivers/media/video/videobuf-dvb.c
drivers/media/video/videobuf-vmalloc.c
drivers/media/video/videocodec.c
drivers/media/video/videodev.c
drivers/media/video/vino.c
drivers/media/video/vivi.c
drivers/media/video/vpx3220.c
drivers/media/video/w9966.c
drivers/media/video/w9968cf.c
drivers/media/video/w9968cf.h
drivers/media/video/zc0301/zc0301.h
drivers/media/video/zc0301/zc0301_core.c
drivers/media/video/zoran.h
drivers/media/video/zoran_card.c
drivers/media/video/zoran_card.h
drivers/media/video/zoran_device.c
drivers/media/video/zoran_driver.c
drivers/media/video/zr36016.c
drivers/media/video/zr36050.c
drivers/media/video/zr36060.c
drivers/media/video/zr364xx.c
drivers/mfd/htc-pasic3.c
drivers/net/Kconfig
drivers/net/ppp_generic.c
drivers/net/tun.c
drivers/net/wireless/Makefile
drivers/net/wireless/ath5k/hw.c
drivers/net/wireless/b43/dma.c
drivers/net/wireless/b43/main.c
drivers/net/wireless/b43/phy.c
drivers/net/wireless/iwlwifi/iwl3945-base.c
drivers/net/wireless/iwlwifi/iwl4965-base.c
drivers/net/wireless/prism54/isl_ioctl.c
drivers/net/wireless/rndis_wlan.c
drivers/pci/intel-iommu.c
drivers/pcmcia/Kconfig
drivers/serial/bfin_5xx.c
drivers/serial/sunzilog.c
drivers/ssb/pci.c
fs/Kconfig
fs/cifs/CHANGES
fs/cifs/README
fs/cifs/cifs_dfs_ref.c
fs/cifs/cifsacl.c
fs/cifs/cifsacl.h
fs/cifs/cifsfs.h
fs/cifs/cifspdu.h
fs/cifs/cifsproto.h
fs/cifs/cifssmb.c
fs/cifs/connect.c
fs/cifs/inode.c
fs/cifs/transport.c
fs/lockd/clntproc.c
fs/lockd/host.c
fs/lockd/mon.c
fs/lockd/svc.c
fs/lockd/svclock.c
fs/lockd/svcshare.c
fs/nfs/Makefile
fs/nfs/callback.c
fs/nfs/client.c
fs/nfs/dir.c
fs/nfs/direct.c
fs/nfs/file.c
fs/nfs/inode.c
fs/nfs/internal.h
fs/nfs/namespace.c
fs/nfs/nfs2xdr.c
fs/nfs/nfs3xdr.c
fs/nfs/nfs4proc.c
fs/nfs/nfs4state.c
fs/nfs/nfs4xdr.c
fs/nfs/read.c
fs/nfs/super.c
fs/nfs/symlink.c
fs/nfs/unlink.c
fs/nfs/write.c
fs/nfsd/auth.c
fs/nfsd/export.c
fs/nfsd/nfs4callback.c
fs/nfsd/nfs4idmap.c
fs/nfsd/nfs4state.c
fs/nfsd/nfs4xdr.c
fs/nfsd/nfsctl.c
fs/nfsd/nfsfh.c
fs/nfsd/nfssvc.c
fs/nfsd/vfs.c
include/asm-blackfin/.gitignore [new file with mode: 0644]
include/asm-blackfin/bfin-global.h
include/asm-blackfin/bug.h
include/asm-blackfin/cplb.h
include/asm-blackfin/dma-mapping.h
include/asm-blackfin/dma.h
include/asm-blackfin/gptimers.h
include/asm-blackfin/mach-bf527/anomaly.h
include/asm-blackfin/mach-bf527/bfin_serial_5xx.h
include/asm-blackfin/mach-bf527/bfin_sir.h [new file with mode: 0644]
include/asm-blackfin/mach-bf527/blackfin.h
include/asm-blackfin/mach-bf527/cdefBF52x_base.h
include/asm-blackfin/mach-bf527/dma.h
include/asm-blackfin/mach-bf533/anomaly.h
include/asm-blackfin/mach-bf533/bfin_serial_5xx.h
include/asm-blackfin/mach-bf533/bfin_sir.h [new file with mode: 0644]
include/asm-blackfin/mach-bf533/blackfin.h
include/asm-blackfin/mach-bf533/cdefBF532.h
include/asm-blackfin/mach-bf533/defBF532.h
include/asm-blackfin/mach-bf533/dma.h
include/asm-blackfin/mach-bf533/mem_init.h
include/asm-blackfin/mach-bf537/anomaly.h
include/asm-blackfin/mach-bf537/bfin_serial_5xx.h
include/asm-blackfin/mach-bf537/bfin_sir.h [new file with mode: 0644]
include/asm-blackfin/mach-bf537/blackfin.h
include/asm-blackfin/mach-bf537/cdefBF534.h
include/asm-blackfin/mach-bf537/dma.h
include/asm-blackfin/mach-bf548/anomaly.h
include/asm-blackfin/mach-bf548/bfin_serial_5xx.h
include/asm-blackfin/mach-bf548/bfin_sir.h [new file with mode: 0644]
include/asm-blackfin/mach-bf548/blackfin.h
include/asm-blackfin/mach-bf548/cdefBF542.h
include/asm-blackfin/mach-bf548/cdefBF544.h
include/asm-blackfin/mach-bf548/cdefBF547.h
include/asm-blackfin/mach-bf548/cdefBF548.h
include/asm-blackfin/mach-bf548/cdefBF549.h
include/asm-blackfin/mach-bf548/cdefBF54x_base.h
include/asm-blackfin/mach-bf548/dma.h
include/asm-blackfin/mach-bf548/mem_init.h
include/asm-blackfin/mach-bf561/anomaly.h
include/asm-blackfin/mach-bf561/bfin_serial_5xx.h
include/asm-blackfin/mach-bf561/bfin_sir.h [new file with mode: 0644]
include/asm-blackfin/mach-bf561/blackfin.h
include/asm-blackfin/mach-bf561/cdefBF561.h
include/asm-blackfin/mach-bf561/defBF561.h
include/asm-blackfin/mach-bf561/dma.h
include/asm-blackfin/portmux.h
include/asm-blackfin/processor.h
include/asm-blackfin/signal.h
include/asm-blackfin/thread_info.h
include/asm-blackfin/time.h [new file with mode: 0644]
include/asm-blackfin/timex.h
include/asm-blackfin/trace.h
include/asm-blackfin/uaccess.h
include/asm-blackfin/unistd.h
include/asm-sparc/device.h
include/asm-sparc/prom.h
include/asm-sparc64/iommu.h
include/asm-sparc64/mmzone.h [new file with mode: 0644]
include/asm-sparc64/numnodes.h [deleted file]
include/asm-sparc64/ptrace.h
include/asm-sparc64/sparsemem.h
include/asm-sparc64/topology.h
include/asm-sparc64/ttable.h
include/asm-x86/smp.h
include/asm-x86/tsc.h
include/linux/dvb/dmx.h
include/linux/exportfs.h
include/linux/i2c-id.h
include/linux/ieee80211.h
include/linux/lockd/lockd.h
include/linux/lockd/sm_inter.h
include/linux/meye.h
include/linux/nfs3.h
include/linux/nfs_fs.h
include/linux/nfs_fs_sb.h
include/linux/nfs_xdr.h
include/linux/nfsd/Kbuild
include/linux/nfsd/cache.h
include/linux/nfsd/nfsd.h
include/linux/rtnetlink.h
include/linux/sunrpc/auth.h
include/linux/sunrpc/auth_gss.h
include/linux/sunrpc/cache.h
include/linux/sunrpc/clnt.h
include/linux/sunrpc/gss_krb5.h
include/linux/sunrpc/sched.h
include/linux/sunrpc/svc.h
include/linux/sunrpc/svcauth.h
include/linux/sunrpc/svcsock.h
include/linux/sunrpc/xprt.h
include/linux/videodev2.h
include/media/ir-common.h
include/media/soc_camera.h [new file with mode: 0644]
include/media/tuner-types.h
include/media/tuner.h
include/media/v4l2-chip-ident.h
include/media/v4l2-dev.h
include/media/videobuf-core.h
include/media/videobuf-dma-sg.h
include/media/videobuf-dvb.h
include/media/videobuf-vmalloc.h
include/net/ipv6.h
include/sound/ac97_codec.h
include/sound/ak4114.h
include/sound/ak4xxx-adda.h
include/sound/asoundef.h
include/sound/control.h
include/sound/core.h
include/sound/mpu401.h
include/sound/version.h
lib/lmb.c
net/core/rtnetlink.c
net/ipv4/fib_hash.c
net/ipv4/fib_trie.c
net/ipv4/route.c
net/ipv4/tcp_ipv4.c
net/ipv4/udp.c
net/mac80211/mlme.c
net/mac80211/rx.c
net/mac80211/wme.c
net/rxrpc/rxkad.c
net/sctp/objcnt.c
net/sunrpc/Makefile
net/sunrpc/auth.c
net/sunrpc/auth_generic.c [new file with mode: 0644]
net/sunrpc/auth_gss/auth_gss.c
net/sunrpc/auth_gss/gss_generic_token.c
net/sunrpc/auth_gss/gss_krb5_crypto.c
net/sunrpc/auth_gss/gss_krb5_seal.c
net/sunrpc/auth_gss/gss_krb5_seqnum.c
net/sunrpc/auth_gss/gss_krb5_unseal.c
net/sunrpc/auth_gss/gss_krb5_wrap.c
net/sunrpc/auth_gss/gss_spkm3_seal.c
net/sunrpc/auth_gss/svcauth_gss.c
net/sunrpc/auth_null.c
net/sunrpc/auth_unix.c
net/sunrpc/cache.c
net/sunrpc/clnt.c
net/sunrpc/rpcb_clnt.c
net/sunrpc/sched.c
net/sunrpc/svc.c
net/sunrpc/svc_xprt.c
net/sunrpc/svcauth_unix.c
net/sunrpc/svcsock.c
net/sunrpc/xprt.c
net/sunrpc/xprtrdma/svc_rdma_transport.c
net/sunrpc/xprtsock.c
net/unix/af_unix.c
sound/arm/pxa2xx-ac97.c
sound/core/Kconfig
sound/core/Makefile
sound/core/init.c
sound/core/misc.c
sound/core/oss/mixer_oss.c
sound/core/seq/oss/seq_oss_synth.c
sound/core/vmaster.c [moved from sound/pci/hda/vmaster.c with 97% similarity]
sound/drivers/Kconfig
sound/drivers/Makefile
sound/drivers/dummy.c
sound/drivers/ml403-ac97cr.c
sound/drivers/mpu401/mpu401_uart.c
sound/drivers/pcsp/Makefile [new file with mode: 0644]
sound/drivers/pcsp/pcsp.c [new file with mode: 0644]
sound/drivers/pcsp/pcsp.h [new file with mode: 0644]
sound/drivers/pcsp/pcsp_input.c [new file with mode: 0644]
sound/drivers/pcsp/pcsp_input.h [new file with mode: 0644]
sound/drivers/pcsp/pcsp_lib.c [new file with mode: 0644]
sound/drivers/pcsp/pcsp_mixer.c [new file with mode: 0644]
sound/i2c/other/ak4114.c
sound/i2c/other/ak4xxx-adda.c
sound/isa/sb/sb16_csp.c
sound/isa/sb/sb_common.c
sound/oss/dmabuf.c
sound/oss/trident.c
sound/oss/trident.h
sound/oss/vwsnd.c
sound/pci/Kconfig
sound/pci/Makefile
sound/pci/ac97/ac97_patch.c
sound/pci/ac97/ac97_pcm.c
sound/pci/ad1889.c
sound/pci/ali5451/ali5451.c
sound/pci/als300.c
sound/pci/atiixp.c
sound/pci/atiixp_modem.c
sound/pci/au88x0/au88x0.c
sound/pci/au88x0/au88x0_pcm.c
sound/pci/aw2/Makefile [new file with mode: 0644]
sound/pci/aw2/aw2-alsa.c [new file with mode: 0644]
sound/pci/aw2/aw2-saa7146.c [new file with mode: 0644]
sound/pci/aw2/aw2-saa7146.h [new file with mode: 0644]
sound/pci/aw2/aw2-tsl.c [new file with mode: 0644]
sound/pci/aw2/saa7146.h [new file with mode: 0644]
sound/pci/azt3328.c
sound/pci/ca0106/ca0106_main.c
sound/pci/ca0106/ca0106_mixer.c
sound/pci/cmipci.c
sound/pci/cs46xx/cs46xx_lib.c
sound/pci/echoaudio/echoaudio.c
sound/pci/emu10k1/emu10k1_main.c
sound/pci/emu10k1/emu10k1x.c
sound/pci/emu10k1/emuproc.c
sound/pci/ens1370.c
sound/pci/es1938.c
sound/pci/es1968.c
sound/pci/fm801.c
sound/pci/hda/Makefile
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_codec.h
sound/pci/hda/hda_generic.c
sound/pci/hda/hda_intel.c
sound/pci/hda/hda_local.h
sound/pci/hda/hda_patch.h
sound/pci/hda/patch_analog.c
sound/pci/hda/patch_atihdmi.c
sound/pci/hda/patch_cmedia.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_si3054.c
sound/pci/hda/patch_sigmatel.c
sound/pci/hda/patch_via.c
sound/pci/ice1712/delta.c
sound/pci/ice1712/delta.h
sound/pci/ice1712/ews.c
sound/pci/ice1712/ews.h
sound/pci/ice1712/hoontech.c
sound/pci/ice1712/ice1712.c
sound/pci/ice1712/ice1712.h
sound/pci/ice1712/ice1724.c
sound/pci/ice1712/juli.c
sound/pci/ice1712/pontis.c
sound/pci/ice1712/prodigy192.c
sound/pci/ice1712/revo.c
sound/pci/intel8x0.c
sound/pci/intel8x0m.c
sound/pci/korg1212/korg1212.c
sound/pci/maestro3.c
sound/pci/nm256/nm256.c
sound/pci/oxygen/cs4362a.h [new file with mode: 0644]
sound/pci/oxygen/cs4398.h [new file with mode: 0644]
sound/pci/oxygen/hifier.c
sound/pci/oxygen/oxygen.c
sound/pci/oxygen/oxygen.h
sound/pci/oxygen/oxygen_io.c
sound/pci/oxygen/oxygen_lib.c
sound/pci/oxygen/oxygen_mixer.c
sound/pci/oxygen/oxygen_pcm.c
sound/pci/oxygen/pcm1796.h [new file with mode: 0644]
sound/pci/oxygen/virtuoso.c
sound/pci/oxygen/wm8785.h [new file with mode: 0644]
sound/pci/pcxhr/pcxhr.c
sound/pci/pcxhr/pcxhr_core.c
sound/pci/riptide/riptide.c
sound/pci/rme32.c
sound/pci/rme96.c
sound/pci/rme9652/hdsp.c
sound/pci/rme9652/hdspm.c
sound/pci/sis7019.c
sound/pci/trident/trident_main.c
sound/pci/via82xx.c
sound/pci/via82xx_modem.c
sound/pci/ymfpci/ymfpci_main.c
sound/ppc/awacs.c
sound/ppc/awacs.h
sound/ppc/burgundy.c
sound/ppc/burgundy.h
sound/ppc/pmac.c
sound/soc/Kconfig
sound/soc/Makefile
sound/soc/codecs/Kconfig
sound/soc/codecs/Makefile
sound/soc/codecs/ac97.c
sound/soc/codecs/cs4270.c
sound/soc/codecs/tlv320aic3x.c
sound/soc/codecs/wm8731.c
sound/soc/codecs/wm8750.c
sound/soc/codecs/wm8753.c
sound/soc/codecs/wm9712.c
sound/soc/codecs/wm9713.c [new file with mode: 0644]
sound/soc/codecs/wm9713.h [new file with mode: 0644]
sound/soc/davinci/Kconfig [new file with mode: 0644]
sound/soc/davinci/Makefile [new file with mode: 0644]
sound/soc/davinci/davinci-evm.c [new file with mode: 0644]
sound/soc/davinci/davinci-i2s.c [new file with mode: 0644]
sound/soc/davinci/davinci-i2s.h [new file with mode: 0644]
sound/soc/davinci/davinci-pcm.c [new file with mode: 0644]
sound/soc/davinci/davinci-pcm.h [new file with mode: 0644]
sound/soc/fsl/fsl_dma.c
sound/soc/fsl/fsl_ssi.c
sound/soc/pxa/corgi.c
sound/soc/pxa/poodle.c
sound/soc/pxa/pxa2xx-ac97.c
sound/soc/pxa/pxa2xx-pcm.c
sound/soc/pxa/spitz.c
sound/soc/s3c24xx/neo1973_wm8753.c
sound/soc/s3c24xx/s3c24xx-i2s.c
sound/soc/s3c24xx/s3c24xx-pcm.c
sound/soc/sh/Kconfig
sound/soc/soc-core.c
sound/soc/soc-dapm.c
sound/spi/at73c213.c
sound/usb/caiaq/caiaq-audio.c
sound/usb/caiaq/caiaq-device.c
sound/usb/usbaudio.c
sound/usb/usbquirks.h

diff --git a/CREDITS b/CREDITS
index da0a56e23beeca7512d80c762425c4fedfaf45b8..8fec7b3f96d5668fa441bd50fc81626d34f0f0c2 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -403,6 +403,8 @@ D: Linux CD and Support Giveaway List
 N: Erik Inge Bolsø
 E: knan@mo.himolde.no
 D: Misc kernel hacks
+D: Updated PC speaker driver for 2.3
+S: Norway
 
 N: Andreas E. Bombe
 E: andreas.bombe@munich.netsurf.de
@@ -3116,6 +3118,12 @@ S: Post Office Box 64132
 S: Sunnyvale, California 94088-4132
 S: USA
 
+N: Stas Sergeev
+E: stsp@users.sourceforge.net
+D: PCM PC-Speaker driver
+D: misc fixes
+S: Russia
+
 N: Simon Shapiro
 E: shimon@i-Connect.Net
 W: http://www.-i-Connect.Net/~shimon
diff --git a/Documentation/filesystems/nfs-rdma.txt b/Documentation/filesystems/nfs-rdma.txt
new file mode 100644 (file)
index 0000000..1ae3487
--- /dev/null
@@ -0,0 +1,252 @@
+################################################################################
+#                                                                             #
+#                              NFS/RDMA README                                #
+#                                                                             #
+################################################################################
+
+ Author: NetApp and Open Grid Computing
+ Date: February 25, 2008
+
+Table of Contents
+~~~~~~~~~~~~~~~~~
+ - Overview
+ - Getting Help
+ - Installation
+ - Check RDMA and NFS Setup
+ - NFS/RDMA Setup
+
+Overview
+~~~~~~~~
+
+  This document describes how to install and setup the Linux NFS/RDMA client
+  and server software.
+
+  The NFS/RDMA client was first included in Linux 2.6.24. The NFS/RDMA server
+  was first included in the following release, Linux 2.6.25.
+
+  In our testing, we have obtained excellent performance results (full 10Gbit
+  wire bandwidth at minimal client CPU) under many workloads. The code passes
+  the full Connectathon test suite and operates over both Infiniband and iWARP
+  RDMA adapters.
+
+Getting Help
+~~~~~~~~~~~~
+
+  If you get stuck, you can ask questions on the
+
+                nfs-rdma-devel@lists.sourceforge.net
+
+  mailing list.
+
+Installation
+~~~~~~~~~~~~
+
+  These instructions are a step by step guide to building a machine for
+  use with NFS/RDMA.
+
+  - Install an RDMA device
+
+    Any device supported by the drivers in drivers/infiniband/hw is acceptable.
+
+    Testing has been performed using several Mellanox-based IB cards, the
+    Ammasso AMS1100 iWARP adapter, and the Chelsio cxgb3 iWARP adapter.
+
+  - Install a Linux distribution and tools
+
+    The first kernel release to contain both the NFS/RDMA client and server was
+    Linux 2.6.25  Therefore, a distribution compatible with this and subsequent
+    Linux kernel release should be installed.
+
+    The procedures described in this document have been tested with
+    distributions from Red Hat's Fedora Project (http://fedora.redhat.com/).
+
+  - Install nfs-utils-1.1.1 or greater on the client
+
+    An NFS/RDMA mount point can only be obtained by using the mount.nfs
+    command in nfs-utils-1.1.1 or greater. To see which version of mount.nfs
+    you are using, type:
+
+    > /sbin/mount.nfs -V
+
+    If the version is less than 1.1.1 or the command does not exist,
+    then you will need to install the latest version of nfs-utils.
+
+    Download the latest package from:
+
+    http://www.kernel.org/pub/linux/utils/nfs
+
+    Uncompress the package and follow the installation instructions.
+
+    If you will not be using GSS and NFSv4, the installation process
+    can be simplified by disabling these features when running configure:
+
+    > ./configure --disable-gss --disable-nfsv4
+
+    For more information on this see the package's README and INSTALL files.
+
+    After building the nfs-utils package, there will be a mount.nfs binary in
+    the utils/mount directory. This binary can be used to initiate NFS v2, v3,
+    or v4 mounts. To initiate a v4 mount, the binary must be called mount.nfs4.
+    The standard technique is to create a symlink called mount.nfs4 to mount.nfs.
+
+    NOTE: mount.nfs and therefore nfs-utils-1.1.1 or greater is only needed
+    on the NFS client machine. You do not need this specific version of
+    nfs-utils on the server. Furthermore, only the mount.nfs command from
+    nfs-utils-1.1.1 is needed on the client.
+
+  - Install a Linux kernel with NFS/RDMA
+
+    The NFS/RDMA client and server are both included in the mainline Linux
+    kernel version 2.6.25 and later. This and other versions of the 2.6 Linux
+    kernel can be found at:
+
+    ftp://ftp.kernel.org/pub/linux/kernel/v2.6/
+
+    Download the sources and place them in an appropriate location.
+
+  - Configure the RDMA stack
+
+    Make sure your kernel configuration has RDMA support enabled. Under
+    Device Drivers -> InfiniBand support, update the kernel configuration
+    to enable InfiniBand support [NOTE: the option name is misleading. Enabling
+    InfiniBand support is required for all RDMA devices (IB, iWARP, etc.)].
+
+    Enable the appropriate IB HCA support (mlx4, mthca, ehca, ipath, etc.) or
+    iWARP adapter support (amso, cxgb3, etc.).
+
+    If you are using InfiniBand, be sure to enable IP-over-InfiniBand support.
+
+  - Configure the NFS client and server
+
+    Your kernel configuration must also have NFS file system support and/or
+    NFS server support enabled. These and other NFS related configuration
+    options can be found under File Systems -> Network File Systems.
+
+  - Build, install, reboot
+
+    The NFS/RDMA code will be enabled automatically if NFS and RDMA
+    are turned on. The NFS/RDMA client and server are configured via the hidden
+    SUNRPC_XPRT_RDMA config option that depends on SUNRPC and INFINIBAND. The
+    value of SUNRPC_XPRT_RDMA will be:
+
+     - N if either SUNRPC or INFINIBAND are N, in this case the NFS/RDMA client
+       and server will not be built
+     - M if both SUNRPC and INFINIBAND are on (M or Y) and at least one is M,
+       in this case the NFS/RDMA client and server will be built as modules
+     - Y if both SUNRPC and INFINIBAND are Y, in this case the NFS/RDMA client
+       and server will be built into the kernel
+
+    Therefore, if you have followed the steps above and turned no NFS and RDMA,
+    the NFS/RDMA client and server will be built.
+
+    Build a new kernel, install it, boot it.
+
+Check RDMA and NFS Setup
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+    Before configuring the NFS/RDMA software, it is a good idea to test
+    your new kernel to ensure that the kernel is working correctly.
+    In particular, it is a good idea to verify that the RDMA stack
+    is functioning as expected and standard NFS over TCP/IP and/or UDP/IP
+    is working properly.
+
+  - Check RDMA Setup
+
+    If you built the RDMA components as modules, load them at
+    this time. For example, if you are using a Mellanox Tavor/Sinai/Arbel
+    card:
+
+    > modprobe ib_mthca
+    > modprobe ib_ipoib
+
+    If you are using InfiniBand, make sure there is a Subnet Manager (SM)
+    running on the network. If your IB switch has an embedded SM, you can
+    use it. Otherwise, you will need to run an SM, such as OpenSM, on one
+    of your end nodes.
+
+    If an SM is running on your network, you should see the following:
+
+    > cat /sys/class/infiniband/driverX/ports/1/state
+    4: ACTIVE
+
+    where driverX is mthca0, ipath5, ehca3, etc.
+
+    To further test the InfiniBand software stack, use IPoIB (this
+    assumes you have two IB hosts named host1 and host2):
+
+    host1> ifconfig ib0 a.b.c.x
+    host2> ifconfig ib0 a.b.c.y
+    host1> ping a.b.c.y
+    host2> ping a.b.c.x
+
+    For other device types, follow the appropriate procedures.
+
+  - Check NFS Setup
+
+    For the NFS components enabled above (client and/or server),
+    test their functionality over standard Ethernet using TCP/IP or UDP/IP.
+
+NFS/RDMA Setup
+~~~~~~~~~~~~~~
+
+  We recommend that you use two machines, one to act as the client and
+  one to act as the server.
+
+  One time configuration:
+
+  - On the server system, configure the /etc/exports file and
+    start the NFS/RDMA server.
+
+    Exports entries with the following format have been tested:
+
+    /vol0   10.97.103.47(rw,async) 192.168.0.47(rw,async,insecure,no_root_squash)
+
+    Here the first IP address is the client's Ethernet address and the second
+    IP address is the clients IPoIB address.
+
+ Each time a machine boots:
+
+  - Load and configure the RDMA drivers
+
+    For InfiniBand using a Mellanox adapter:
+
+    > modprobe ib_mthca
+    > modprobe ib_ipoib
+    > ifconfig ib0 a.b.c.d
+
+    NOTE: use unique addresses for the client and server
+
+  - Start the NFS server
+
+    If the NFS/RDMA server was built as a module (CONFIG_SUNRPC_XPRT_RDMA=m in kernel config),
+    load the RDMA transport module:
+
+    > modprobe svcrdma
+
+    Regardless of how the server was built (module or built-in), start the server:
+
+    > /etc/init.d/nfs start
+
+    or
+
+    > service nfs start
+
+    Instruct the server to listen on the RDMA transport:
+
+    > echo rdma 2050 > /proc/fs/nfsd/portlist
+
+  - On the client system
+
+    If the NFS/RDMA client was built as a module (CONFIG_SUNRPC_XPRT_RDMA=m in kernel config),
+    load the RDMA client module:
+
+    > modprobe xprtrdma.ko
+
+    Regardless of how the client was built (module or built-in), issue the mount.nfs command:
+
+    > /path/to/your/mount.nfs <IPoIB-server-name-or-address>:/<export> /mnt -i -o rdma,port=2050
+
+    To verify that the mount is using RDMA, run "cat /proc/mounts" and check the
+    "proto" field for the given mount.
+
+  Congratulations! You're using NFS/RDMA!
index e985cf5e04107798a4f079260486a1793c061623..fd4c32a031c9f5e5381b440379ea70ca9e85ff7e 100644 (file)
@@ -284,6 +284,13 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
            control correctly. If you have problems regarding this, try
            another ALSA compliant mixer (alsamixer works).
 
+  Module snd-aw2
+  --------------
+
+    Module for Audiowerk2 sound card
+
+    This module supports multiple cards.
+
   Module snd-azt2320
   ------------------
 
@@ -818,19 +825,25 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
          hippo_1       Hippo (Benq) with jack detection
          sony-assamd   Sony ASSAMD
          ultra         Samsung Q1 Ultra Vista model
+         lenovo-3000   Lenovo 3000 y410
          basic         fixed pin assignment w/o SPDIF
          auto          auto-config reading BIOS (default)
 
-       ALC268
+       ALC267/268
+         quanta-il1    Quanta IL1 mini-notebook
          3stack        3-stack model
          toshiba       Toshiba A205
          acer          Acer laptops
          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
+
        ALC662
          3stack-dig    3-stack (2-channel) with SPDIF
          3stack-6ch     3-stack (6-channel)
@@ -871,10 +884,11 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
          lenovo-nb0763 Lenovo NB0763
          lenovo-ms7195-dig Lenovo MS7195
          haier-w66     Haier W66
-         6stack-hp     HP machines with 6stack (Nettle boards)
          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
          auto          auto-config reading BIOS (default)
 
        ALC861/660
@@ -911,6 +925,12 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
          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
 
@@ -936,7 +956,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
          laptop-automute 2-channel with EAPD and HP-automute (Lenovo N100)
          ultra         2-channel with EAPD (Samsung Ultra tablet PC)
 
-       AD1988
+       AD1988/AD1988B/AD1989A/AD1989B
          6stack        6-jack
          6stack-dig    ditto with SPDIF
          3stack        3-jack
@@ -979,6 +999,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
          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
@@ -1017,6 +1038,16 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
          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
@@ -1590,6 +1621,16 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
 
     Power management is _not_ supported.
 
+  Module snd-pcsp
+  -----------------
+
+    Module for internal PC-Speaker.
+
+    nforce_wa  - enable NForce chipset workaround. Expect bad sound.
+
+    This module supports system beeps, some kind of PCM playback and
+    even a few mixer controls.
+
   Module snd-pcxhr
   ----------------
 
diff --git a/Documentation/video4linux/CARDLIST.au0828 b/Documentation/video4linux/CARDLIST.au0828
new file mode 100644 (file)
index 0000000..aaae360
--- /dev/null
@@ -0,0 +1,4 @@
+  0 -> Unknown board                            (au0828)
+  1 -> Hauppauge HVR950Q                        (au0828)        [2040:7200]
+  2 -> Hauppauge HVR850                         (au0828)        [2040:7240]
+  3 -> DViCO FusionHDTV USB                     (au0828)        [0fe9:d620]
index d97cf7cc60889e637f2772023e752fda4d44c5a3..f32efb6fb12c5111de62f875ec8361af5152e091 100644 (file)
 147 -> VoodooTV 200 (USA)                                  [121a:3000]
 148 -> DViCO FusionHDTV 2                                  [dbc0:d200]
 149 -> Typhoon TV-Tuner PCI (50684)
+150 -> Geovision GV-600                                    [008a:763c]
+151 -> Kozumi KTV-01C
index 0924e6e142c40a2f7d6a5dec0ae107ff5d616d8c..929b90c8387fafc30ed3e0715171a504e257b0e7 100644 (file)
@@ -5,3 +5,6 @@
   4 -> DViCO FusionHDTV5 Express                           [18ac:d500]
   5 -> Hauppauge WinTV-HVR1500Q                            [0070:7790,0070:7797]
   6 -> Hauppauge WinTV-HVR1500                             [0070:7710,0070:7717]
+  7 -> Hauppauge WinTV-HVR1200                             [0070:71d1]
+  8 -> Hauppauge WinTV-HVR1700                             [0070:8101]
+  9 -> Hauppauge WinTV-HVR1400                             [0070:8010]
index bc5593bd9704dc8497d6d69d01642938bb20f5b9..5439573464693ca9c3ac29ba9d10b0dd27a2fdf9 100644 (file)
  56 -> Hauppauge WinTV-HVR1300 DVB-T/Hybrid MPEG Encoder   [0070:9600,0070:9601,0070:9602]
  57 -> ADS Tech Instant Video PCI                          [1421:0390]
  58 -> Pinnacle PCTV HD 800i                               [11bd:0051]
+ 59 -> DViCO FusionHDTV 5 PCI nano                         [18ac:d530]
+ 60 -> Pinnacle Hybrid PCTV                                [12ab:1788]
+ 61 -> Winfast TV2000 XP Global                            [107d:6f18]
+ 62 -> PowerColor Real Angel 330                           [14f1:ea3d]
+ 63 -> Geniatech X8000-MT DVBT                             [14f1:8852]
+ 64 -> DViCO FusionHDTV DVB-T PRO                          [18ac:db30]
+ 65 -> DViCO FusionHDTV 7 Gold                             [18ac:d610]
+ 66 -> Prolink Pixelview MPEG 8000GT                       [1554:4935]
+ 67 -> Kworld PlusTV HD PCI 120 (ATSC 120)                 [17de:08c1]
index 0424901ebc78b0a11f700a21d926e1b4b3fe4d2f..44d84dd15ad672d55b4a93db652f34d74cb3a664 100644 (file)
@@ -25,8 +25,8 @@
  24 -> KNC One TV-Station DVR                   [1894:a006]
  25 -> ASUS TV-FM 7133                          [1043:4843]
  26 -> Pinnacle PCTV Stereo (saa7134)           [11bd:002b]
- 27 -> Manli MuchTV M-TV002/Behold TV 403 FM
- 28 -> Manli MuchTV M-TV001/Behold TV 401
+ 27 -> Manli MuchTV M-TV002
+ 28 -> Manli MuchTV M-TV001
  29 -> Nagase Sangyo TransGear 3000TV           [1461:050c]
  30 -> Elitegroup ECS TVP3XP FM1216 Tuner Card(PAL-BG,FM)  [1019:4cb4]
  31 -> Elitegroup ECS TVP3XP FM1236 Tuner Card (NTSC,FM) [1019:4cb5]
 130 -> Beholder BeholdTV M6 / BeholdTV M6 Extra [5ace:6190,5ace:6193]
 131 -> Twinhan Hybrid DTV-DVB 3056 PCI          [1822:0022]
 132 -> Genius TVGO AM11MCE
+133 -> NXP Snake DVB-S reference design
+134 -> Medion/Creatix CTX953 Hybrid             [16be:0010]
+135 -> MSI TV@nywhere A/D v1.1                  [1462:8625]
+136 -> AVerMedia Cardbus TV/Radio (E506R)       [1461:f436]
+137 -> AVerMedia Hybrid TV/Radio (A16D)         [1461:f936]
+138 -> Avermedia M115                           [1461:a836]
+139 -> Compro VideoMate T750                    [185b:c900]
+140 -> Avermedia DVB-S Pro A700                 [1461:a7a1]
+141 -> Avermedia DVB-S Hybrid+FM A700           [1461:a7a2]
index cced8ac5c543b462c7cbc329c5ddac921bb05774..2cb816047fc128bb67323c00ffcd982fe5d174fc 100644 (file)
@@ -686,11 +686,11 @@ sub main_firmware($$$$)
        write_hunk(812664, 192);
 
        #
-       # Firmware 58, type: SCODE FW  HAS IF (0x60000000), IF = 4.50 MHz id: NTSC/M Jp (0000000000002000), size: 192
+       # Firmware 58, type: SCODE FW  MTS LCD NOGD MONO IF HAS IF (0x6002b004), IF = 4.50 MHz id: NTSC PAL/M PAL/N (000000000000b700), size: 192
        #
 
-       write_le32(0x60000000);                 # Type
-       write_le64(0x00000000, 0x00002000);     # ID
+       write_le32(0x6002b004);                 # Type
+       write_le64(0x00000000, 0x0000b700);     # ID
        write_le16(4500);                       # IF
        write_le32(192);                        # Size
        write_hunk(807672, 192);
@@ -706,10 +706,10 @@ sub main_firmware($$$$)
        write_hunk(807864, 192);
 
        #
-       # Firmware 60, type: SCODE FW  DTV78 ZARLINK456 HAS IF (0x62000100), IF = 4.76 MHz id: (0000000000000000), size: 192
+       # Firmware 60, type: SCODE FW  DTV6 QAM DTV7 DTV78 DTV8 ZARLINK456 HAS IF (0x620003e0), IF = 4.76 MHz id: (0000000000000000), size: 192
        #
 
-       write_le32(0x62000100);                 # Type
+       write_le32(0x620003e0);                 # Type
        write_le64(0x00000000, 0x00000000);     # ID
        write_le16(4760);                       # IF
        write_le32(192);                        # Size
@@ -726,30 +726,30 @@ sub main_firmware($$$$)
        write_hunk(811512, 192);
 
        #
-       # Firmware 62, type: SCODE FW  DTV7 ZARLINK456 HAS IF (0x62000080), IF = 5.26 MHz id: (0000000000000000), size: 192
+       # Firmware 62, type: SCODE FW  HAS IF (0x60000000), IF = 5.26 MHz id: (0000000000000000), size: 192
        #
 
-       write_le32(0x62000080);                 # Type
+       write_le32(0x60000000);                 # Type
        write_le64(0x00000000, 0x00000000);     # ID
        write_le16(5260);                       # IF
        write_le32(192);                        # Size
        write_hunk(810552, 192);
 
        #
-       # Firmware 63, type: SCODE FW  MONO HAS IF (0x60008000), IF = 5.32 MHz id: PAL/BG NICAM/B (0000000800000007), size: 192
+       # Firmware 63, type: SCODE FW  MONO HAS IF (0x60008000), IF = 5.32 MHz id: PAL/BG A2 NICAM (0000000f00000007), size: 192
        #
 
        write_le32(0x60008000);                 # Type
-       write_le64(0x00000008, 0x00000007);     # ID
+       write_le64(0x0000000f, 0x00000007);     # ID
        write_le16(5320);                       # IF
        write_le32(192);                        # Size
        write_hunk(810744, 192);
 
        #
-       # Firmware 64, type: SCODE FW  DTV8 CHINA HAS IF (0x64000200), IF = 5.40 MHz id: (0000000000000000), size: 192
+       # Firmware 64, type: SCODE FW  DTV7 DTV78 DTV8 DIBCOM52 CHINA HAS IF (0x65000380), IF = 5.40 MHz id: (0000000000000000), size: 192
        #
 
-       write_le32(0x64000200);                 # Type
+       write_le32(0x65000380);                 # Type
        write_le64(0x00000000, 0x00000000);     # ID
        write_le16(5400);                       # IF
        write_le32(192);                        # Size
@@ -766,50 +766,50 @@ sub main_firmware($$$$)
        write_hunk(809592, 192);
 
        #
-       # Firmware 66, type: SCODE FW  HAS IF (0x60000000), IF = 5.64 MHz id: PAL/BG A2/B (0000000200000007), size: 192
+       # Firmware 66, type: SCODE FW  HAS IF (0x60000000), IF = 5.64 MHz id: PAL/BG A2 (0000000300000007), size: 192
        #
 
        write_le32(0x60000000);                 # Type
-       write_le64(0x00000002, 0x00000007);     # ID
+       write_le64(0x00000003, 0x00000007);     # ID
        write_le16(5640);                       # IF
        write_le32(192);                        # Size
        write_hunk(808440, 192);
 
        #
-       # Firmware 67, type: SCODE FW  HAS IF (0x60000000), IF = 5.74 MHz id: PAL/BG NICAM/B (0000000800000007), size: 192
+       # Firmware 67, type: SCODE FW  HAS IF (0x60000000), IF = 5.74 MHz id: PAL/BG NICAM (0000000c00000007), size: 192
        #
 
        write_le32(0x60000000);                 # Type
-       write_le64(0x00000008, 0x00000007);     # ID
+       write_le64(0x0000000c, 0x00000007);     # ID
        write_le16(5740);                       # IF
        write_le32(192);                        # Size
        write_hunk(808632, 192);
 
        #
-       # Firmware 68, type: SCODE FW  DTV7 DIBCOM52 HAS IF (0x61000080), IF = 5.90 MHz id: (0000000000000000), size: 192
+       # Firmware 68, type: SCODE FW  HAS IF (0x60000000), IF = 5.90 MHz id: (0000000000000000), size: 192
        #
 
-       write_le32(0x61000080);                 # Type
+       write_le32(0x60000000);                 # Type
        write_le64(0x00000000, 0x00000000);     # ID
        write_le16(5900);                       # IF
        write_le32(192);                        # Size
        write_hunk(810360, 192);
 
        #
-       # Firmware 69, type: SCODE FW  MONO HAS IF (0x60008000), IF = 6.00 MHz id: PAL/I (0000000000000010), size: 192
+       # Firmware 69, type: SCODE FW  MONO HAS IF (0x60008000), IF = 6.00 MHz id: PAL/DK PAL/I SECAM/K3 SECAM/L SECAM/Lc NICAM (0000000c04c000f0), size: 192
        #
 
        write_le32(0x60008000);                 # Type
-       write_le64(0x00000000, 0x00000010);     # ID
+       write_le64(0x0000000c, 0x04c000f0);     # ID
        write_le16(6000);                       # IF
        write_le32(192);                        # Size
        write_hunk(808824, 192);
 
        #
-       # Firmware 70, type: SCODE FW  DTV6 QAM F6MHZ HAS IF (0x68000060), IF = 6.20 MHz id: (0000000000000000), size: 192
+       # Firmware 70, type: SCODE FW  DTV6 QAM ATSC LG60 F6MHZ HAS IF (0x68050060), IF = 6.20 MHz id: (0000000000000000), size: 192
        #
 
-       write_le32(0x68000060);                 # Type
+       write_le32(0x68050060);                 # Type
        write_le64(0x00000000, 0x00000000);     # ID
        write_le16(6200);                       # IF
        write_le32(192);                        # Size
@@ -846,11 +846,11 @@ sub main_firmware($$$$)
        write_hunk(809208, 192);
 
        #
-       # Firmware 74, type: SCODE FW  MONO HAS IF (0x60008000), IF = 6.50 MHz id: SECAM/K3 (0000000004000000), size: 192
+       # Firmware 74, type: SCODE FW  MONO HAS IF (0x60008000), IF = 6.50 MHz id: PAL/DK SECAM/K3 SECAM/L NICAM (0000000c044000e0), size: 192
        #
 
        write_le32(0x60008000);                 # Type
-       write_le64(0x00000000, 0x04000000);     # ID
+       write_le64(0x0000000c, 0x044000e0);     # ID
        write_le16(6500);                       # IF
        write_le32(192);                        # Size
        write_hunk(811128, 192);
index 11800c33ea84760575944dbca4e5fd3458ff3086..9dee3ce27fc7672766ce27430e5b0fc76293b473 100644 (file)
@@ -2558,12 +2558,10 @@ W:      http://www.tazenda.demon.co.uk/phil/linux-hp
 S:     Maintained
 
 MAC80211
-P:     Michael Wu
-M:     flamingice@sourmilk.net
 P:     Johannes Berg
 M:     johannes@sipsolutions.net
-P:     Jiri Benc
-M:     jbenc@suse.cz
+P:     Michael Wu
+M:     flamingice@sourmilk.net
 L:     linux-wireless@vger.kernel.org
 W:     http://linuxwireless.org/
 T:     git kernel.org:/pub/scm/linux/kernel/git/linville/wireless-2.6.git
index 8c71daf94a59ce0f27537a4c8352ab362152dbbe..9fee37e2596f34fe8d3c22558b87d248396b4dca 100644 (file)
@@ -75,6 +75,7 @@ osf_set_program_attributes(unsigned long text_start, unsigned long text_len,
        lock_kernel();
        mm = current->mm;
        mm->end_code = bss_start + bss_len;
+       mm->start_brk = bss_start + bss_len;
        mm->brk = bss_start + bss_len;
 #if 0
        printk("set_program_attributes(%lx %lx %lx %lx)\n",
index c107cc08daf47f130136fcb3dda342dac0926cdc..78357798b6fd100d3964f20232fa974fc241b26f 100644 (file)
@@ -71,25 +71,13 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82378, quirk_i
 static void __init
 quirk_cypress(struct pci_dev *dev)
 {
-       /* The Notorious Cy82C693 chip.  */
-
-       /* The Cypress IDE controller doesn't support native mode, but it
-          has programmable addresses of IDE command/control registers.
-          This violates PCI specifications, confuses the IDE subsystem and
-          causes resource conflicts between the primary HD_CMD register and
-          the floppy controller.  Ugh.  Fix that.  */
-       if (dev->class >> 8 == PCI_CLASS_STORAGE_IDE) {
-               dev->resource[0].flags = 0;
-               dev->resource[1].flags = 0;
-       }
-
        /* The Cypress bridge responds on the PCI bus in the address range
           0xffff0000-0xffffffff (conventional x86 BIOS ROM).  There is no
           way to turn this off.  The bridge also supports several extended
           BIOS ranges (disabled after power-up), and some consoles do turn
           them on.  So if we use a large direct-map window, or a large SG
           window, we must avoid the entire 0xfff00000-0xffffffff region.  */
-       else if (dev->class >> 8 == PCI_CLASS_BRIDGE_ISA) {
+       if (dev->class >> 8 == PCI_CLASS_BRIDGE_ISA) {
                if (__direct_map_base + __direct_map_size >= 0xfff00000UL)
                        __direct_map_size = 0xfff00000UL - __direct_map_base;
                else {
@@ -391,7 +379,7 @@ pcibios_set_master(struct pci_dev *dev)
        pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
 }
 
-static void __init
+void __init
 pcibios_claim_one_bus(struct pci_bus *b)
 {
        struct pci_dev *dev;
@@ -405,7 +393,8 @@ pcibios_claim_one_bus(struct pci_bus *b)
 
                        if (r->parent || !r->start || !r->flags)
                                continue;
-                       pci_claim_resource(dev, i);
+                       if (pci_probe_only || (r->flags & IORESOURCE_PCI_FIXED))
+                               pci_claim_resource(dev, i);
                }
        }
 
@@ -444,8 +433,7 @@ common_init_pci(void)
                }
        }
 
-       if (pci_probe_only)
-               pcibios_claim_console_setup();
+       pcibios_claim_console_setup();
 
        pci_assign_unassigned_resources();
        pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq);
index 920196bcbb6168fb4227a745aec38923051ad201..a7f23b5ab814580a480bb5c7b6b932d3227f828c 100644 (file)
@@ -187,6 +187,7 @@ nautilus_machine_check(unsigned long vector, unsigned long la_ptr)
 }
 
 extern void free_reserved_mem(void *, void *);
+extern void pcibios_claim_one_bus(struct pci_bus *);
 
 static struct resource irongate_mem = {
        .name   = "Irongate PCI MEM",
@@ -205,6 +206,7 @@ nautilus_init_pci(void)
        /* Scan our single hose.  */
        bus = pci_scan_bus(0, alpha_mv.pci_ops, hose);
        hose->bus = bus;
+       pcibios_claim_one_bus(bus);
 
        irongate = pci_get_bus_and_slot(0, 0);
        bus->self = irongate;
index 5235f64f235b87f4b66355025a3d06a86dcaedfc..8508a0db3eaf53ce213a5190ac0877c057e2f791 100644 (file)
@@ -124,8 +124,11 @@ static int rtc_probe(struct amba_device *dev, void *id)
 
        xtime.tv_sec = __raw_readl(rtc_base + RTC_DR);
 
+       /* note that 'dev' is merely used for irq disambiguation;
+        * it is not actually referenced in the irq handler
+        */
        ret = request_irq(dev->irq[0], arm_rtc_interrupt, IRQF_DISABLED,
-                         "rtc-pl030", NULL);
+                         "rtc-pl030", dev);
        if (ret)
                goto map_out;
 
index 6d26661d99f634b0f631dc866804f8211f5cb5aa..2ef7d0097b38b251924f307f6d9a1af1cb1a34cd 100644 (file)
@@ -75,10 +75,9 @@ static void kev7a400_cpld_handler (unsigned int irq, struct irq_desc *desc)
 {
        u32 mask = CPLD_LATCHED_INTS;
        irq = IRQ_KEV7A400_CPLD;
-       for (; mask; mask >>= 1, ++irq) {
+       for (; mask; mask >>= 1, ++irq)
                if (mask & 1)
-                       desc[irq].handle (irq, desc);
-       }
+                       desc_handle_irq(irq, desc);
 }
 
 void __init lh7a40x_init_board_irq (void)
index 15066c29a8498197777139a85aee056c6ce675e6..2fa8ce8b0cc69f3d34264b1301aa059df44c2276 100644 (file)
@@ -32,6 +32,7 @@ config CPU_ARM7TDMI
        depends on !MMU
        select CPU_32v4T
        select CPU_ABRT_LV4T
+       select CPU_PABRT_NOIFAR
        select CPU_CACHE_V4
        help
          A 32-bit RISC microprocessor based on the ARM7 processor core
@@ -85,6 +86,7 @@ config CPU_ARM740T
        depends on !MMU
        select CPU_32v4T
        select CPU_ABRT_LV4T
+       select CPU_PABRT_NOIFAR
        select CPU_CACHE_V3     # although the core is v4t
        select CPU_CP15_MPU
        help
@@ -101,6 +103,7 @@ config CPU_ARM9TDMI
        depends on !MMU
        select CPU_32v4T
        select CPU_ABRT_NOMMU
+       select CPU_PABRT_NOIFAR
        select CPU_CACHE_V4
        help
          A 32-bit RISC microprocessor based on the ARM9 processor core
@@ -200,6 +203,7 @@ config CPU_ARM940T
        depends on !MMU
        select CPU_32v4T
        select CPU_ABRT_NOMMU
+       select CPU_PABRT_NOIFAR
        select CPU_CACHE_VIVT
        select CPU_CP15_MPU
        help
@@ -217,6 +221,7 @@ config CPU_ARM946E
        depends on !MMU
        select CPU_32v5
        select CPU_ABRT_NOMMU
+       select CPU_PABRT_NOIFAR
        select CPU_CACHE_VIVT
        select CPU_CP15_MPU
        help
@@ -351,6 +356,7 @@ config CPU_XSC3
        default y
        select CPU_32v5
        select CPU_ABRT_EV5T
+       select CPU_PABRT_NOIFAR
        select CPU_CACHE_VIVT
        select CPU_CP15_MMU
        select CPU_TLB_V4WBI if MMU
index 32fd7ea533f21d6387c65f1b1dbb50f269139d6e..5673f4d6113ba94e7f05954f790489428d4eec8c 100644 (file)
@@ -471,6 +471,7 @@ arm1020_crval:
        .type   arm1020_processor_functions, #object
 arm1020_processor_functions:
        .word   v4t_early_abort
+       .word   pabort_noifar
        .word   cpu_arm1020_proc_init
        .word   cpu_arm1020_proc_fin
        .word   cpu_arm1020_reset
@@ -478,7 +479,6 @@ arm1020_processor_functions:
        .word   cpu_arm1020_dcache_clean_area
        .word   cpu_arm1020_switch_mm
        .word   cpu_arm1020_set_pte_ext
-       .word   pabort_noifar
        .size   arm1020_processor_functions, . - arm1020_processor_functions
 
        .section ".rodata"
index fe2b0ae70274a9ca48ffc5442c7b16259550e90c..4343fdb0e9e55f453129f24b37c41e7d29e56cf8 100644 (file)
@@ -452,6 +452,7 @@ arm1020e_crval:
        .type   arm1020e_processor_functions, #object
 arm1020e_processor_functions:
        .word   v4t_early_abort
+       .word   pabort_noifar
        .word   cpu_arm1020e_proc_init
        .word   cpu_arm1020e_proc_fin
        .word   cpu_arm1020e_reset
@@ -459,7 +460,6 @@ arm1020e_processor_functions:
        .word   cpu_arm1020e_dcache_clean_area
        .word   cpu_arm1020e_switch_mm
        .word   cpu_arm1020e_set_pte_ext
-       .word   pabort_noifar
        .size   arm1020e_processor_functions, . - arm1020e_processor_functions
 
        .section ".rodata"
index 06dde678e19dc51b314dc082a98cefad66ce10d1..2a4ea1659e963321cae90278949cf036c216ae17 100644 (file)
@@ -435,6 +435,7 @@ arm1022_crval:
        .type   arm1022_processor_functions, #object
 arm1022_processor_functions:
        .word   v4t_early_abort
+       .word   pabort_noifar
        .word   cpu_arm1022_proc_init
        .word   cpu_arm1022_proc_fin
        .word   cpu_arm1022_reset
@@ -442,7 +443,6 @@ arm1022_processor_functions:
        .word   cpu_arm1022_dcache_clean_area
        .word   cpu_arm1022_switch_mm
        .word   cpu_arm1022_set_pte_ext
-       .word   pabort_noifar
        .size   arm1022_processor_functions, . - arm1022_processor_functions
 
        .section ".rodata"
index f5506e6e681e251b2154248e8be510f770cb6c65..77a1babd421c9d6f5c235299632ae57d5e0dc1cf 100644 (file)
@@ -430,6 +430,7 @@ arm1026_crval:
        .type   arm1026_processor_functions, #object
 arm1026_processor_functions:
        .word   v5t_early_abort
+       .word   pabort_noifar
        .word   cpu_arm1026_proc_init
        .word   cpu_arm1026_proc_fin
        .word   cpu_arm1026_reset
@@ -437,7 +438,6 @@ arm1026_processor_functions:
        .word   cpu_arm1026_dcache_clean_area
        .word   cpu_arm1026_switch_mm
        .word   cpu_arm1026_set_pte_ext
-       .word   pabort_noifar
        .size   arm1026_processor_functions, . - arm1026_processor_functions
 
        .section .rodata
index 14b6a95c8d45a96490072967c15d147f0d220845..c371fc87776ef0c6b7fffdf4f2d7a7f47a1d32d4 100644 (file)
@@ -293,6 +293,7 @@ __arm7_setup:       mov     r0, #0
                .type   arm6_processor_functions, #object
 ENTRY(arm6_processor_functions)
                .word   cpu_arm6_data_abort
+               .word   pabort_noifar
                .word   cpu_arm6_proc_init
                .word   cpu_arm6_proc_fin
                .word   cpu_arm6_reset
@@ -300,7 +301,6 @@ ENTRY(arm6_processor_functions)
                .word   cpu_arm6_dcache_clean_area
                .word   cpu_arm6_switch_mm
                .word   cpu_arm6_set_pte_ext
-               .word   pabort_noifar
                .size   arm6_processor_functions, . - arm6_processor_functions
 
 /*
@@ -310,6 +310,7 @@ ENTRY(arm6_processor_functions)
                .type   arm7_processor_functions, #object
 ENTRY(arm7_processor_functions)
                .word   cpu_arm7_data_abort
+               .word   pabort_noifar
                .word   cpu_arm7_proc_init
                .word   cpu_arm7_proc_fin
                .word   cpu_arm7_reset
@@ -317,7 +318,6 @@ ENTRY(arm7_processor_functions)
                .word   cpu_arm7_dcache_clean_area
                .word   cpu_arm7_switch_mm
                .word   cpu_arm7_set_pte_ext
-               .word   pabort_noifar
                .size   arm7_processor_functions, . - arm7_processor_functions
 
                .section ".rodata"
index ca5e7aac2da7d711518ae74cd828b4a483828028..d64f8e6f75ab19f889c4cf93586f66bb64008e37 100644 (file)
@@ -198,6 +198,7 @@ arm720_crval:
                .type   arm720_processor_functions, #object
 ENTRY(arm720_processor_functions)
                .word   v4t_late_abort
+               .word   pabort_noifar
                .word   cpu_arm720_proc_init
                .word   cpu_arm720_proc_fin
                .word   cpu_arm720_reset
@@ -205,7 +206,6 @@ ENTRY(arm720_processor_functions)
                .word   cpu_arm720_dcache_clean_area
                .word   cpu_arm720_switch_mm
                .word   cpu_arm720_set_pte_ext
-               .word   pabort_noifar
                .size   arm720_processor_functions, . - arm720_processor_functions
 
                .section ".rodata"
index 7069f495cf9bfa663120b5ec79e2a011b981638e..3a57376c8bc970f71a1673dd636b8462d3724a79 100644 (file)
@@ -126,6 +126,7 @@ __arm740_setup:
        .type   arm740_processor_functions, #object
 ENTRY(arm740_processor_functions)
        .word   v4t_late_abort
+       .word   pabort_noifar
        .word   cpu_arm740_proc_init
        .word   cpu_arm740_proc_fin
        .word   cpu_arm740_reset
index d091c25718235f47e06ebeac9bda8426029ab777..7b3ecdeb537003a9e2dd183f0f45f31b0e767b09 100644 (file)
@@ -64,6 +64,7 @@ __arm7tdmi_setup:
                .type   arm7tdmi_processor_functions, #object
 ENTRY(arm7tdmi_processor_functions)
                .word   v4t_late_abort
+               .word   pabort_noifar
                .word   cpu_arm7tdmi_proc_init
                .word   cpu_arm7tdmi_proc_fin
                .word   cpu_arm7tdmi_reset
index 0170d4f466eacdfde844905d4a7b05194eb7db15..28cdb060df454cf352ac9797092e9d0a8012e3f9 100644 (file)
@@ -417,6 +417,7 @@ arm920_crval:
        .type   arm920_processor_functions, #object
 arm920_processor_functions:
        .word   v4t_early_abort
+       .word   pabort_noifar
        .word   cpu_arm920_proc_init
        .word   cpu_arm920_proc_fin
        .word   cpu_arm920_reset
@@ -424,7 +425,6 @@ arm920_processor_functions:
        .word   cpu_arm920_dcache_clean_area
        .word   cpu_arm920_switch_mm
        .word   cpu_arm920_set_pte_ext
-       .word   pabort_noifar
        .size   arm920_processor_functions, . - arm920_processor_functions
 
        .section ".rodata"
index b7952493d4049deae3ba251785bdad043a008a37..94ddcb4a4b76d630f4e94d5048f27bdfb253c04a 100644 (file)
@@ -421,6 +421,7 @@ arm922_crval:
        .type   arm922_processor_functions, #object
 arm922_processor_functions:
        .word   v4t_early_abort
+       .word   pabort_noifar
        .word   cpu_arm922_proc_init
        .word   cpu_arm922_proc_fin
        .word   cpu_arm922_reset
@@ -428,7 +429,6 @@ arm922_processor_functions:
        .word   cpu_arm922_dcache_clean_area
        .word   cpu_arm922_switch_mm
        .word   cpu_arm922_set_pte_ext
-       .word   pabort_noifar
        .size   arm922_processor_functions, . - arm922_processor_functions
 
        .section ".rodata"
index e2988eba4cf605e8dd1a456ad723a8f8a6c09bd5..065087afb7720375736329576ad0e22968dab533 100644 (file)
@@ -484,6 +484,7 @@ arm925_crval:
        .type   arm925_processor_functions, #object
 arm925_processor_functions:
        .word   v4t_early_abort
+       .word   pabort_noifar
        .word   cpu_arm925_proc_init
        .word   cpu_arm925_proc_fin
        .word   cpu_arm925_reset
@@ -491,7 +492,6 @@ arm925_processor_functions:
        .word   cpu_arm925_dcache_clean_area
        .word   cpu_arm925_switch_mm
        .word   cpu_arm925_set_pte_ext
-       .word   pabort_noifar
        .size   arm925_processor_functions, . - arm925_processor_functions
 
        .section ".rodata"
index 62f7d1dfe01695a003b104a58b92818c85e77f74..997db8472b5c3c6aca4b0e99f6baba97036e21b7 100644 (file)
@@ -437,6 +437,7 @@ arm926_crval:
        .type   arm926_processor_functions, #object
 arm926_processor_functions:
        .word   v5tj_early_abort
+       .word   pabort_noifar
        .word   cpu_arm926_proc_init
        .word   cpu_arm926_proc_fin
        .word   cpu_arm926_reset
@@ -444,7 +445,6 @@ arm926_processor_functions:
        .word   cpu_arm926_dcache_clean_area
        .word   cpu_arm926_switch_mm
        .word   cpu_arm926_set_pte_ext
-       .word   pabort_noifar
        .size   arm926_processor_functions, . - arm926_processor_functions
 
        .section ".rodata"
index 786c593778f0a0b91e5b5c8bb8f4ae1a1e3cdb95..44ead902bd54f5347aa877f25bb98af2a4547f43 100644 (file)
@@ -321,6 +321,7 @@ __arm940_setup:
        .type   arm940_processor_functions, #object
 ENTRY(arm940_processor_functions)
        .word   nommu_early_abort
+       .word   pabort_noifar
        .word   cpu_arm940_proc_init
        .word   cpu_arm940_proc_fin
        .word   cpu_arm940_reset
index a60c1421d450ed9ebca2230762db9ec3df70d06a..2218b0c01330a8f96a5ea4ef6b360cb596ec4ffe 100644 (file)
@@ -376,6 +376,7 @@ __arm946_setup:
        .type   arm946_processor_functions, #object
 ENTRY(arm946_processor_functions)
        .word   nommu_early_abort
+       .word   pabort_noifar
        .word   cpu_arm946_proc_init
        .word   cpu_arm946_proc_fin
        .word   cpu_arm946_reset
index 4848eeac86b653416a24f6bf6fca478c0cd3f153..c85c1f50e396ef1d82e6ba6f7ef736ddbd3f22d8 100644 (file)
@@ -64,6 +64,7 @@ __arm9tdmi_setup:
                .type   arm9tdmi_processor_functions, #object
 ENTRY(arm9tdmi_processor_functions)
                .word   nommu_early_abort
+               .word   pabort_noifar
                .word   cpu_arm9tdmi_proc_init
                .word   cpu_arm9tdmi_proc_fin
                .word   cpu_arm9tdmi_reset
index 2f169b28e93849883ff08cdb296f79084ebf25ce..90e7594e29b182123f1831d329418bd16228909a 100644 (file)
@@ -423,6 +423,7 @@ feroceon_crval:
        .type   feroceon_processor_functions, #object
 feroceon_processor_functions:
        .word   v5t_early_abort
+       .word   pabort_noifar
        .word   cpu_feroceon_proc_init
        .word   cpu_feroceon_proc_fin
        .word   cpu_feroceon_reset
@@ -430,7 +431,6 @@ feroceon_processor_functions:
        .word   cpu_feroceon_dcache_clean_area
        .word   cpu_feroceon_switch_mm
        .word   cpu_feroceon_set_pte_ext
-       .word   pabort_noifar
        .size   feroceon_processor_functions, . - feroceon_processor_functions
 
        .section ".rodata"
index 4db3d6299a2bd5830d7cd52e276062cb1f8c21d6..9818195dbf11b745cff005b79ef978eedc7068d3 100644 (file)
@@ -216,6 +216,7 @@ sa110_crval:
        .type   sa110_processor_functions, #object
 ENTRY(sa110_processor_functions)
        .word   v4_early_abort
+       .word   pabort_noifar
        .word   cpu_sa110_proc_init
        .word   cpu_sa110_proc_fin
        .word   cpu_sa110_reset
@@ -223,7 +224,6 @@ ENTRY(sa110_processor_functions)
        .word   cpu_sa110_dcache_clean_area
        .word   cpu_sa110_switch_mm
        .word   cpu_sa110_set_pte_ext
-       .word   pabort_noifar
        .size   sa110_processor_functions, . - sa110_processor_functions
 
        .section ".rodata"
index 3cdef043760fce46d4de813df4e859b61243a106..c5fe27ad2892e991d89e18401fbe5da840c9c9b3 100644 (file)
@@ -231,6 +231,7 @@ sa1100_crval:
        .type   sa1100_processor_functions, #object
 ENTRY(sa1100_processor_functions)
        .word   v4_early_abort
+       .word   pabort_noifar
        .word   cpu_sa1100_proc_init
        .word   cpu_sa1100_proc_fin
        .word   cpu_sa1100_reset
@@ -238,7 +239,6 @@ ENTRY(sa1100_processor_functions)
        .word   cpu_sa1100_dcache_clean_area
        .word   cpu_sa1100_switch_mm
        .word   cpu_sa1100_set_pte_ext
-       .word   pabort_noifar
        .size   sa1100_processor_functions, . - sa1100_processor_functions
 
        .section ".rodata"
index bf760ea2f789ee5796ef9c6702dec5ba3bfec1b7..5702ec58b2a2a9ae8f8e120ad59aabec0c65e049 100644 (file)
@@ -219,6 +219,7 @@ v6_crval:
        .type   v6_processor_functions, #object
 ENTRY(v6_processor_functions)
        .word   v6_early_abort
+       .word   pabort_noifar
        .word   cpu_v6_proc_init
        .word   cpu_v6_proc_fin
        .word   cpu_v6_reset
@@ -226,7 +227,6 @@ ENTRY(v6_processor_functions)
        .word   cpu_v6_dcache_clean_area
        .word   cpu_v6_switch_mm
        .word   cpu_v6_set_pte_ext
-       .word   pabort_noifar
        .size   v6_processor_functions, . - v6_processor_functions
 
        .type   cpu_arch_name, #object
index a1d7331cd64c4cf17715315a5675ec1dcec55fe0..b49f9a4c82c8e4375f8449bfed5f2527b36598c2 100644 (file)
@@ -205,6 +205,7 @@ __v7_setup_stack:
        .type   v7_processor_functions, #object
 ENTRY(v7_processor_functions)
        .word   v7_early_abort
+       .word   pabort_ifar
        .word   cpu_v7_proc_init
        .word   cpu_v7_proc_fin
        .word   cpu_v7_reset
@@ -212,7 +213,6 @@ ENTRY(v7_processor_functions)
        .word   cpu_v7_dcache_clean_area
        .word   cpu_v7_switch_mm
        .word   cpu_v7_set_pte_ext
-       .word   pabort_ifar
        .size   v7_processor_functions, . - v7_processor_functions
 
        .type   cpu_arch_name, #object
index d95921a2ab99b81cc0c17cdab5cc433df6b9a9cc..3533741a76f6713b8f0229570dd49123d040331b 100644 (file)
@@ -450,6 +450,7 @@ xsc3_crval:
        .type   xsc3_processor_functions, #object
 ENTRY(xsc3_processor_functions)
        .word   v5t_early_abort
+       .word   pabort_noifar
        .word   cpu_xsc3_proc_init
        .word   cpu_xsc3_proc_fin
        .word   cpu_xsc3_reset
index 1a6d89823dffb581a21c8908f6586f46b95eb1a4..2dd85273976fcf4aa29e6066ad0975cd4de3582b 100644 (file)
@@ -527,6 +527,7 @@ xscale_crval:
        .type   xscale_processor_functions, #object
 ENTRY(xscale_processor_functions)
        .word   v5t_early_abort
+       .word   pabort_noifar
        .word   cpu_xscale_proc_init
        .word   cpu_xscale_proc_fin
        .word   cpu_xscale_reset
@@ -534,7 +535,6 @@ ENTRY(xscale_processor_functions)
        .word   cpu_xscale_dcache_clean_area
        .word   cpu_xscale_switch_mm
        .word   cpu_xscale_set_pte_ext
-       .word   pabort_noifar
        .size   xscale_processor_functions, . - xscale_processor_functions
 
        .section ".rodata"
index 2dd1f300a5cfe8fe9c81758304f1575ed849fe72..795d0ac67c2192a93c6fd0404bb3e9fed92c45d7 100644 (file)
@@ -47,10 +47,6 @@ config GENERIC_IRQ_PROBE
        bool
        default y
 
-config GENERIC_TIME
-       bool
-       default n
-
 config GENERIC_GPIO
        bool
        default y
@@ -224,16 +220,6 @@ config BF54x
        depends on (BF542 || BF544 || BF547 || BF548 || BF549)
        default y
 
-config BFIN_DUAL_CORE
-       bool
-       depends on (BF561)
-       default y
-
-config BFIN_SINGLE_CORE
-       bool
-       depends on !BFIN_DUAL_CORE
-       default y
-
 config MEM_GENERIC_BOARD
        bool
        depends on GENERIC_BOARD
@@ -263,7 +249,7 @@ config MEM_MT48LC8M32B2B5_7
 
 config MEM_MT48LC32M16A2TG_75
        bool
-       depends on (BFIN527_EZKIT)
+       depends on (BFIN527_EZKIT || BFIN532_IP0X)
        default y
 
 source "arch/blackfin/mach-bf527/Kconfig"
@@ -286,17 +272,34 @@ config CMDLINE
          to the kernel, you may specify one here. As a minimum, you should specify
          the memory size and the root device (e.g., mem=8M, root=/dev/nfs).
 
+config BOOT_LOAD
+       hex "Kernel load address for booting"
+       default "0x1000"
+       range 0x1000 0x20000000
+       help
+         This option allows you to set the load address of the kernel.
+         This can be useful if you are on a board which has a small amount
+         of memory or you wish to reserve some memory at the beginning of
+         the address space.
+
+         Note that you need to keep this value above 4k (0x1000) as this
+         memory region is used to capture NULL pointer references as well
+         as some core kernel functions.
+
 comment "Clock/PLL Setup"
 
 config CLKIN_HZ
-       int "Crystal Frequency in Hz"
+       int "Frequency of the crystal on the board in Hz"
        default "11059200" if BFIN533_STAMP
        default "27000000" if BFIN533_EZKIT
        default "25000000" if (BFIN537_STAMP || BFIN527_EZKIT || H8606_HVSISTEMAS)
        default "30000000" if BFIN561_EZKIT
        default "24576000" if PNAV10
+       default "10000000" if BFIN532_IP0X
        help
          The frequency of CLKIN crystal oscillator on the board in Hz.
+         Warning: This value should match the crystal on the board. Otherwise,
+         peripherals won't work properly.
 
 config BFIN_KERNEL_CLOCK
        bool "Re-program Clocks while Kernel boots?"
@@ -307,6 +310,25 @@ config BFIN_KERNEL_CLOCK
          are also not changed, and the Bootloader does 100% of the hardware
          configuration.
 
+config MEM_SIZE
+       int "SDRAM Memory Size in MBytes"
+       depends on BFIN_KERNEL_CLOCK
+       default 64
+
+config MEM_ADD_WIDTH
+       int "Memory Address Width"
+       depends on BFIN_KERNEL_CLOCK
+       depends on (!BF54x)
+       range 8 11
+       default  9 if BFIN533_EZKIT
+       default  9 if BFIN561_EZKIT
+       default  9 if H8606_HVSISTEMAS
+       default 10 if BFIN527_EZKIT
+       default 10 if BFIN537_STAMP
+       default 11 if BFIN533_STAMP
+       default 10 if PNAV10
+       default 10 if BFIN532_IP0X
+
 config PLL_BYPASS
        bool "Bypass PLL"
        depends on BFIN_KERNEL_CLOCK
@@ -325,7 +347,7 @@ config VCO_MULT
        range 1 64
        default "22" if BFIN533_EZKIT
        default "45" if BFIN533_STAMP
-       default "20" if (BFIN537_STAMP || BFIN527_EZKIT || BFIN548_EZKIT)
+       default "20" if (BFIN537_STAMP || BFIN527_EZKIT || BFIN548_EZKIT || BFIN548_BLUETECHNIX_CM)
        default "22" if BFIN533_BLUETECHNIX_CM
        default "20" if BFIN537_BLUETECHNIX_CM
        default "20" if BFIN561_BLUETECHNIX_CM
@@ -360,19 +382,33 @@ config SCLK_DIV
        int "System Clock Divider"
        depends on BFIN_KERNEL_CLOCK
        range 1 15
-       default 5 if BFIN533_EZKIT
-       default 5 if BFIN533_STAMP
-       default 4 if (BFIN537_STAMP || BFIN527_EZKIT || BFIN548_EZKIT)
-       default 5 if BFIN533_BLUETECHNIX_CM
-       default 4 if BFIN537_BLUETECHNIX_CM
-       default 4 if BFIN561_BLUETECHNIX_CM
-       default 5 if BFIN561_EZKIT
-       default 3 if H8606_HVSISTEMAS
+       default 5
        help
          This sets the frequency of the system clock (including SDRAM or DDR).
          This can be between 1 and 15
          System Clock = (PLL frequency) / (this setting)
 
+config MAX_MEM_SIZE
+       int "Max SDRAM Memory Size in MBytes"
+       depends on !BFIN_KERNEL_CLOCK && !MPU
+       default 512
+       help
+         This is the max memory size that the kernel will create CPLB
+         tables for.  Your system will not be able to handle any more.
+
+choice
+       prompt "DDR SDRAM Chip Type"
+       depends on BFIN_KERNEL_CLOCK
+       depends on BF54x
+       default MEM_MT46V32M16_5B
+
+config MEM_MT46V32M16_6T
+       bool "MT46V32M16_6T"
+
+config MEM_MT46V32M16_5B
+       bool "MT46V32M16_5B"
+endchoice
+
 #
 # Max & Min Speeds for various Chips
 #
@@ -415,42 +451,33 @@ comment "Kernel Timer/Scheduler"
 
 source kernel/Kconfig.hz
 
-comment "Memory Setup"
-
-config MEM_SIZE
-       int "SDRAM Memory Size in MBytes"
-       default  32 if BFIN533_EZKIT
-       default  64 if BFIN527_EZKIT
-       default  64 if BFIN537_STAMP
-       default  64 if BFIN548_EZKIT
-       default  64 if BFIN561_EZKIT
-       default 128 if BFIN533_STAMP
-       default  64 if PNAV10
-       default  32 if H8606_HVSISTEMAS
+config GENERIC_TIME
+       bool "Generic time"
+       default y
 
-config MEM_ADD_WIDTH
-       int "SDRAM Memory Address Width"
-       depends on (!BF54x)
-       default  9 if BFIN533_EZKIT
-       default  9 if BFIN561_EZKIT
-       default  9 if H8606_HVSISTEMAS
-       default 10 if BFIN527_EZKIT
-       default 10 if BFIN537_STAMP
-       default 11 if BFIN533_STAMP
-       default 10 if PNAV10
+config GENERIC_CLOCKEVENTS
+       bool "Generic clock events"
+       depends on GENERIC_TIME
+       default y
 
+config CYCLES_CLOCKSOURCE
+       bool "Use 'CYCLES' as a clocksource (EXPERIMENTAL)"
+       depends on EXPERIMENTAL
+       depends on GENERIC_CLOCKEVENTS
+       depends on !BFIN_SCRATCH_REG_CYCLES
+       default n
+       help
+         If you say Y here, you will enable support for using the 'cycles'
+         registers as a clock source.  Doing so means you will be unable to
+         safely write to the 'cycles' register during runtime.  You will
+         still be able to read it (such as for performance monitoring), but
+         writing the registers will most likely crash the kernel.
 
-choice
-       prompt "DDR SDRAM Chip Type"
-       depends on BFIN548_EZKIT
-       default MEM_MT46V32M16_5B
+source kernel/time/Kconfig
 
-config MEM_MT46V32M16_6T
-        bool "MT46V32M16_6T"
+comment "Memory Setup"
 
-config MEM_MT46V32M16_5B
-        bool "MT46V32M16_5B"
-endchoice
+comment "Misc"
 
 config ENET_FLASH_PIN
        int "PF port/pin used for flash and ethernet sharing"
@@ -462,20 +489,6 @@ config ENET_FLASH_PIN
          code.
          For example: PF0 --> 0,PF1 --> 1,PF2 --> 2, etc.
 
-config BOOT_LOAD
-       hex "Kernel load address for booting"
-       default "0x1000"
-       range 0x1000 0x20000000
-       help
-         This option allows you to set the load address of the kernel.
-         This can be useful if you are on a board which has a small amount
-         of memory or you wish to reserve some memory at the beginning of
-         the address space.
-
-         Note that you need to keep this value above 4k (0x1000) as this
-         memory region is used to capture NULL pointer references as well
-         as some core kernel functions.
-
 choice
        prompt "Blackfin Exception Scratch Register"
        default BFIN_SCRATCH_REG_RETN
@@ -661,14 +674,6 @@ endchoice
 
 source "mm/Kconfig"
 
-config LARGE_ALLOCS
-       bool "Allow allocating large blocks (> 1MB) of memory"
-       help
-         Allow the slab memory allocator to keep chains for very large
-         memory sizes - upto 32MB. You may need this if your system has
-         a lot of RAM, and you need to able to allocate very large
-         contiguous chunks. If unsure, say N.
-
 config BFIN_GPTIMERS
        tristate "Enable Blackfin General Purpose Timers API"
        default n
index 75eba2ca788149fb610f3b91ff63aa2286e013bf..3cbe16caad4b98c8e0b2f376c4e954fe4903cc29 100644 (file)
@@ -72,6 +72,11 @@ rev-$(CONFIG_BF_REV_ANY)  := any
 KBUILD_CFLAGS += -mcpu=$(cpu-y)-$(rev-y)
 KBUILD_AFLAGS += -mcpu=$(cpu-y)-$(rev-y)
 
+# - we utilize the silicon rev from the toolchain, so move it over to the checkflags
+# - the l1_text attribute is Blackfin specific, so fake it out as used to kill warnings
+CHECKFLAGS_SILICON = $(shell echo "" | $(CPP) $(KBUILD_CFLAGS) -dD - 2>/dev/null | awk '$$2 == "__SILICON_REVISION__" { print $$3 }')
+CHECKFLAGS += -D__SILICON_REVISION__=$(CHECKFLAGS_SILICON) -Dl1_text=__used__
+
 head-y   := arch/$(ARCH)/mach-$(MACHINE)/head.o arch/$(ARCH)/kernel/init_task.o
 
 core-y   += arch/$(ARCH)/kernel/ arch/$(ARCH)/mm/ arch/$(ARCH)/mach-common/
diff --git a/arch/blackfin/boot/.gitignore b/arch/blackfin/boot/.gitignore
new file mode 100644 (file)
index 0000000..3ae0399
--- /dev/null
@@ -0,0 +1 @@
++vmImage
index ae320dcfedefe9b064bdeddfdf45ae052d340c27..64876dfc2e550b57eb9a8b015295f49bc3a560d8 100644 (file)
@@ -13,7 +13,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
-# CONFIG_GENERIC_TIME is not set
+CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_GPIO=y
 CONFIG_FORCE_MAX_ZONEORDER=14
 CONFIG_GENERIC_CALIBRATE_DELAY=y
@@ -250,7 +250,7 @@ CONFIG_HZ=250
 #
 # Memory Setup
 #
-CONFIG_MEM_SIZE=64
+CONFIG_MAX_MEM_SIZE=512
 CONFIG_MEM_ADD_WIDTH=10
 CONFIG_BOOT_LOAD=0x1000
 CONFIG_BFIN_SCRATCH_REG_RETN=y
@@ -720,8 +720,8 @@ CONFIG_BFIN_OTP=y
 #
 CONFIG_SERIAL_BFIN=y
 CONFIG_SERIAL_BFIN_CONSOLE=y
-# CONFIG_SERIAL_BFIN_DMA is not set
-CONFIG_SERIAL_BFIN_PIO=y
+CONFIG_SERIAL_BFIN_DMA=y
+# CONFIG_SERIAL_BFIN_PIO is not set
 # CONFIG_SERIAL_BFIN_UART0 is not set
 CONFIG_SERIAL_BFIN_UART1=y
 # CONFIG_BFIN_UART1_CTSRTS is not set
index 9621caa60b5fc36a5ff0a26d06294f40cb71ae26..8d817ba01945dc67f2c4400e342419dcfebaa234 100644 (file)
@@ -13,7 +13,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
-# CONFIG_GENERIC_TIME is not set
+CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_GPIO=y
 CONFIG_FORCE_MAX_ZONEORDER=14
 CONFIG_GENERIC_CALIBRATE_DELAY=y
@@ -212,7 +212,7 @@ CONFIG_HZ=250
 #
 # Memory Setup
 #
-CONFIG_MEM_SIZE=32
+CONFIG_MAX_MEM_SIZE=512
 CONFIG_MEM_ADD_WIDTH=9
 CONFIG_BOOT_LOAD=0x1000
 CONFIG_BFIN_SCRATCH_REG_RETN=y
index b51e76ce7f4f9812c4e6676e60890842f3300c18..20d598d17bd14b8f6d0401ff217163848aae4bd0 100644 (file)
@@ -13,7 +13,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
-# CONFIG_GENERIC_TIME is not set
+CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_GPIO=y
 CONFIG_FORCE_MAX_ZONEORDER=14
 CONFIG_GENERIC_CALIBRATE_DELAY=y
@@ -212,7 +212,7 @@ CONFIG_HZ=250
 #
 # Memory Setup
 #
-CONFIG_MEM_SIZE=128
+CONFIG_MAX_MEM_SIZE=512
 CONFIG_MEM_ADD_WIDTH=11
 CONFIG_ENET_FLASH_PIN=0
 CONFIG_BOOT_LOAD=0x1000
index d45fa535dad7d4c8494cd279dff63cd51c6bb54d..b5189c8ba263a3755ce725445727b230ec4a195c 100644 (file)
@@ -13,7 +13,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
-# CONFIG_GENERIC_TIME is not set
+CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_GPIO=y
 CONFIG_FORCE_MAX_ZONEORDER=14
 CONFIG_GENERIC_CALIBRATE_DELAY=y
@@ -220,7 +220,7 @@ CONFIG_HZ=250
 #
 # Memory Setup
 #
-CONFIG_MEM_SIZE=64
+CONFIG_MAX_MEM_SIZE=512
 CONFIG_MEM_ADD_WIDTH=10
 CONFIG_BOOT_LOAD=0x1000
 CONFIG_BFIN_SCRATCH_REG_RETN=y
index c9707f7665ad8ca021bbfe9819a1dec06af40471..5bfdfb287d138537b7125116ae4988436926bf21 100644 (file)
@@ -13,7 +13,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
-# CONFIG_GENERIC_TIME is not set
+CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_GPIO=y
 CONFIG_FORCE_MAX_ZONEORDER=14
 CONFIG_GENERIC_CALIBRATE_DELAY=y
@@ -285,7 +285,7 @@ CONFIG_HZ=250
 #
 # Memory Setup
 #
-CONFIG_MEM_SIZE=64
+CONFIG_MAX_MEM_SIZE=512
 # CONFIG_MEM_MT46V32M16_6T is not set
 CONFIG_MEM_MT46V32M16_5B=y
 CONFIG_BOOT_LOAD=0x1000
@@ -813,8 +813,8 @@ CONFIG_HW_CONSOLE=y
 #
 CONFIG_SERIAL_BFIN=y
 CONFIG_SERIAL_BFIN_CONSOLE=y
-# CONFIG_SERIAL_BFIN_DMA is not set
-CONFIG_SERIAL_BFIN_PIO=y
+CONFIG_SERIAL_BFIN_DMA=y
+# CONFIG_SERIAL_BFIN_PIO is not set
 # CONFIG_SERIAL_BFIN_UART0 is not set
 CONFIG_SERIAL_BFIN_UART1=y
 # CONFIG_BFIN_UART1_CTSRTS is not set
index 4d8a633313091b95189547d1be6d50d9ea1cce59..b4a20c8908165000f8375c97214dc67b1c260daa 100644 (file)
@@ -13,7 +13,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
-# CONFIG_GENERIC_TIME is not set
+CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_GPIO=y
 CONFIG_FORCE_MAX_ZONEORDER=14
 CONFIG_GENERIC_CALIBRATE_DELAY=y
@@ -256,7 +256,7 @@ CONFIG_HZ=250
 #
 # Memory Setup
 #
-CONFIG_MEM_SIZE=64
+CONFIG_MAX_MEM_SIZE=512
 CONFIG_MEM_ADD_WIDTH=9
 CONFIG_BOOT_LOAD=0x1000
 CONFIG_BFIN_SCRATCH_REG_RETN=y
diff --git a/arch/blackfin/configs/CM-BF533_defconfig b/arch/blackfin/configs/CM-BF533_defconfig
new file mode 100644 (file)
index 0000000..560890f
--- /dev/null
@@ -0,0 +1,912 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.22.16
+#
+# CONFIG_MMU is not set
+# CONFIG_FPU is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_BLACKFIN=y
+CONFIG_ZONE_DMA=y
+CONFIG_SEMAPHORE_SLEEPERS=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_FORCE_MAX_ZONEORDER=14
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT 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_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+# CONFIG_UID16 is not set
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_EVENTFD=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3
+# CONFIG_NP2 is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_RT_MUTEXES=y
+CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+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
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+
+#
+# Blackfin Processor Options
+#
+
+#
+# Processor and Board Settings
+#
+# CONFIG_BF522 is not set
+# CONFIG_BF523 is not set
+# CONFIG_BF524 is not set
+# CONFIG_BF525 is not set
+# CONFIG_BF526 is not set
+# CONFIG_BF527 is not set
+# CONFIG_BF531 is not set
+# CONFIG_BF532 is not set
+CONFIG_BF533=y
+# CONFIG_BF534 is not set
+# CONFIG_BF536 is not set
+# CONFIG_BF537 is not set
+# CONFIG_BF542 is not set
+# CONFIG_BF544 is not set
+# CONFIG_BF547 is not set
+# CONFIG_BF548 is not set
+# CONFIG_BF549 is not set
+# CONFIG_BF561 is not set
+# CONFIG_BF_REV_0_0 is not set
+# CONFIG_BF_REV_0_1 is not set
+# CONFIG_BF_REV_0_2 is not set
+CONFIG_BF_REV_0_3=y
+# CONFIG_BF_REV_0_4 is not set
+# CONFIG_BF_REV_0_5 is not set
+# CONFIG_BF_REV_ANY is not set
+# CONFIG_BF_REV_NONE is not set
+CONFIG_BF53x=y
+CONFIG_BFIN_SINGLE_CORE=y
+CONFIG_MEM_MT48LC16M16A2TG_75=y
+# CONFIG_BFIN533_EZKIT is not set
+# CONFIG_BFIN533_STAMP is not set
+CONFIG_BFIN533_BLUETECHNIX_CM=y
+# CONFIG_H8606_HVSISTEMAS is not set
+# CONFIG_GENERIC_BF533_BOARD is not set
+
+#
+# BF533/2/1 Specific Configuration
+#
+
+#
+# Interrupt Priority Assignment
+#
+
+#
+# Priority
+#
+CONFIG_UART_ERROR=7
+CONFIG_SPORT0_ERROR=7
+CONFIG_SPI_ERROR=7
+CONFIG_SPORT1_ERROR=7
+CONFIG_PPI_ERROR=7
+CONFIG_DMA_ERROR=7
+CONFIG_PLLWAKE_ERROR=7
+CONFIG_RTC_ERROR=8
+CONFIG_DMA0_PPI=8
+CONFIG_DMA1_SPORT0RX=9
+CONFIG_DMA2_SPORT0TX=9
+CONFIG_DMA3_SPORT1RX=9
+CONFIG_DMA4_SPORT1TX=9
+CONFIG_DMA5_SPI=10
+CONFIG_DMA6_UARTRX=10
+CONFIG_DMA7_UARTTX=10
+CONFIG_TIMER0=11
+CONFIG_TIMER1=11
+CONFIG_TIMER2=11
+CONFIG_PFA=12
+CONFIG_PFB=12
+CONFIG_MEMDMA0=13
+CONFIG_MEMDMA1=13
+CONFIG_WDTIMER=13
+
+#
+# Board customizations
+#
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Clock/PLL Setup
+#
+CONFIG_CLKIN_HZ=25000000
+# CONFIG_BFIN_KERNEL_CLOCK is not set
+CONFIG_MAX_VCO_HZ=750000000
+CONFIG_MIN_VCO_HZ=50000000
+CONFIG_MAX_SCLK_HZ=133333333
+CONFIG_MIN_SCLK_HZ=27000000
+
+#
+# Kernel Timer/Scheduler
+#
+# 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
+
+#
+# Memory Setup
+#
+CONFIG_MAX_MEM_SIZE=32
+CONFIG_MEM_ADD_WIDTH=9
+CONFIG_BOOT_LOAD=0x1000
+CONFIG_BFIN_SCRATCH_REG_RETN=y
+# CONFIG_BFIN_SCRATCH_REG_RETE is not set
+# CONFIG_BFIN_SCRATCH_REG_CYCLES is not set
+
+#
+# Blackfin Kernel Optimizations
+#
+
+#
+# Memory Optimizations
+#
+CONFIG_I_ENTRY_L1=y
+CONFIG_EXCPT_IRQ_SYSC_L1=y
+CONFIG_DO_IRQ_L1=y
+CONFIG_CORE_TIMER_IRQ_L1=y
+CONFIG_IDLE_L1=y
+CONFIG_SCHEDULE_L1=y
+CONFIG_ARITHMETIC_OPS_L1=y
+CONFIG_ACCESS_OK_L1=y
+CONFIG_MEMSET_L1=y
+CONFIG_MEMCPY_L1=y
+CONFIG_SYS_BFIN_SPINLOCK_L1=y
+CONFIG_IP_CHECKSUM_L1=y
+CONFIG_CACHELINE_ALIGNED_L1=y
+CONFIG_SYSCALL_TAB_L1=y
+CONFIG_CPLB_SWITCH_TAB_L1=y
+CONFIG_RAMKERNEL=y
+# CONFIG_ROMKERNEL is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_LARGE_ALLOCS=y
+# CONFIG_BFIN_GPTIMERS is not set
+CONFIG_BFIN_DMA_5XX=y
+# CONFIG_DMA_UNCACHED_2M is not set
+CONFIG_DMA_UNCACHED_1M=y
+# CONFIG_DMA_UNCACHED_NONE is not set
+
+#
+# Cache Support
+#
+CONFIG_BFIN_ICACHE=y
+CONFIG_BFIN_DCACHE=y
+# CONFIG_BFIN_DCACHE_BANKA is not set
+# CONFIG_BFIN_ICACHE_LOCK is not set
+CONFIG_BFIN_WB=y
+# CONFIG_BFIN_WT is not set
+CONFIG_L1_MAX_PIECE=16
+# CONFIG_MPU is not set
+
+#
+# Asynchonous Memory Configuration
+#
+
+#
+# EBIU_AMGCTL Global Control
+#
+CONFIG_C_AMCKEN=y
+CONFIG_C_CDPRIO=y
+# CONFIG_C_AMBEN is not set
+# CONFIG_C_AMBEN_B0 is not set
+# CONFIG_C_AMBEN_B0_B1 is not set
+# CONFIG_C_AMBEN_B0_B1_B2 is not set
+CONFIG_C_AMBEN_ALL=y
+
+#
+# EBIU_AMBCTL Control
+#
+CONFIG_BANK_0=0x7BB0
+CONFIG_BANK_1=0x7BB0
+CONFIG_BANK_2=0x7BB0
+CONFIG_BANK_3=0xFFC3
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF_FDPIC=y
+CONFIG_BINFMT_FLAT=y
+CONFIG_BINFMT_ZFLAT=y
+CONFIG_BINFMT_SHARED_FLAT=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+# CONFIG_PM_WAKEUP_BY_GPIO is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Networking
+#
+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_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# 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_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETLABEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE 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
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO 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_RFKILL is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_RAM=y
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_UCLINUX=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI 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_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# Misc devices
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_SMC91X=y
+# CONFIG_SMSC911X is not set
+# CONFIG_DM9000 is not set
+CONFIG_NETDEV_1000=y
+# CONFIG_AX88180 is not set
+CONFIG_NETDEV_10000=y
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 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
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_AD9960 is not set
+# CONFIG_SPI_ADC_BF533 is not set
+# CONFIG_BF5xx_PFLAGS is not set
+# CONFIG_BF5xx_PPIFCD is not set
+# CONFIG_BFIN_SIMPLE_TIMER is not set
+# CONFIG_BF5xx_PPI is not set
+CONFIG_BFIN_SPORT=y
+# CONFIG_BFIN_TIMER_LATENCY is not set
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_BFIN=y
+CONFIG_SERIAL_BFIN_CONSOLE=y
+CONFIG_SERIAL_BFIN_DMA=y
+# CONFIG_SERIAL_BFIN_PIO is not set
+CONFIG_SERIAL_BFIN_UART0=y
+# CONFIG_BFIN_UART0_CTSRTS is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_BFIN_SPORT is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# CAN, the car bus and industrial fieldbus
+#
+# CONFIG_CAN4LINUX is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
+
+#
+# Graphics support
+#
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+# CONFIG_USB is not set
+
+#
+# Enable Host or Gadget support to see Inventra options
+#
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# PBX support
+#
+# CONFIG_PBX is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+# CONFIG_EXT2_FS_POSIX_ACL is not set
+# CONFIG_EXT2_FS_SECURITY is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+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
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# 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_YAFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+# CONFIG_NFS_FS is not set
+# CONFIG_NFSD 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
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+# 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_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_MMRS is not set
+CONFIG_DEBUG_HUNT_FOR_ZERO=y
+CONFIG_DEBUG_BFIN_HWTRACE_ON=y
+CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
+# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE is not set
+# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_TWO is not set
+CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0
+# CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set
+# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
+# CONFIG_EARLY_PRINTK is not set
+CONFIG_CPLB_INFO=y
+CONFIG_ACCESS_CHECK=y
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+CONFIG_SECURITY=y
+# CONFIG_SECURITY_NETWORK is not set
+CONFIG_SECURITY_CAPABILITIES=y
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/blackfin/configs/CM-BF537E_defconfig b/arch/blackfin/configs/CM-BF537E_defconfig
new file mode 100644 (file)
index 0000000..9f66d2d
--- /dev/null
@@ -0,0 +1,940 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.22.16
+#
+# CONFIG_MMU is not set
+# CONFIG_FPU is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_BLACKFIN=y
+CONFIG_ZONE_DMA=y
+CONFIG_SEMAPHORE_SLEEPERS=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_FORCE_MAX_ZONEORDER=14
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT 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_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+# CONFIG_UID16 is not set
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_EVENTFD=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3
+# CONFIG_NP2 is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_RT_MUTEXES=y
+CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+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
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+
+#
+# Blackfin Processor Options
+#
+
+#
+# Processor and Board Settings
+#
+# CONFIG_BF522 is not set
+# CONFIG_BF523 is not set
+# CONFIG_BF524 is not set
+# CONFIG_BF525 is not set
+# CONFIG_BF526 is not set
+# CONFIG_BF527 is not set
+# CONFIG_BF531 is not set
+# CONFIG_BF532 is not set
+# CONFIG_BF533 is not set
+# CONFIG_BF534 is not set
+# CONFIG_BF536 is not set
+CONFIG_BF537=y
+# CONFIG_BF542 is not set
+# CONFIG_BF544 is not set
+# CONFIG_BF547 is not set
+# CONFIG_BF548 is not set
+# CONFIG_BF549 is not set
+# CONFIG_BF561 is not set
+# CONFIG_BF_REV_0_0 is not set
+# CONFIG_BF_REV_0_1 is not set
+CONFIG_BF_REV_0_2=y
+# CONFIG_BF_REV_0_3 is not set
+# CONFIG_BF_REV_0_4 is not set
+# CONFIG_BF_REV_0_5 is not set
+# CONFIG_BF_REV_ANY is not set
+# CONFIG_BF_REV_NONE is not set
+CONFIG_BF53x=y
+CONFIG_BFIN_SINGLE_CORE=y
+CONFIG_MEM_MT48LC16M16A2TG_75=y
+CONFIG_IRQ_PLL_WAKEUP=7
+CONFIG_IRQ_RTC=8
+CONFIG_IRQ_PPI=8
+CONFIG_IRQ_SPORT0_RX=9
+CONFIG_IRQ_SPORT0_TX=9
+CONFIG_IRQ_SPORT1_RX=9
+CONFIG_IRQ_SPORT1_TX=9
+CONFIG_IRQ_TWI=10
+CONFIG_IRQ_SPI=10
+CONFIG_IRQ_UART0_RX=10
+CONFIG_IRQ_UART0_TX=10
+CONFIG_IRQ_UART1_RX=10
+CONFIG_IRQ_UART1_TX=10
+CONFIG_IRQ_MAC_RX=11
+CONFIG_IRQ_MAC_TX=11
+CONFIG_IRQ_TMR0=12
+CONFIG_IRQ_TMR1=12
+CONFIG_IRQ_TMR2=12
+CONFIG_IRQ_TMR3=12
+CONFIG_IRQ_TMR4=12
+CONFIG_IRQ_TMR5=12
+CONFIG_IRQ_TMR6=12
+CONFIG_IRQ_TMR7=12
+CONFIG_IRQ_PORTG_INTB=12
+CONFIG_IRQ_MEM_DMA0=13
+CONFIG_IRQ_MEM_DMA1=13
+CONFIG_IRQ_WATCH=13
+# CONFIG_BFIN537_STAMP is not set
+CONFIG_BFIN537_BLUETECHNIX_CM=y
+# CONFIG_PNAV10 is not set
+# CONFIG_CAMSIG_MINOTAUR is not set
+# CONFIG_GENERIC_BF537_BOARD is not set
+
+#
+# BF537 Specific Configuration
+#
+
+#
+# Interrupt Priority Assignment
+#
+
+#
+# Priority
+#
+CONFIG_IRQ_DMA_ERROR=7
+CONFIG_IRQ_ERROR=7
+CONFIG_IRQ_CAN_RX=11
+CONFIG_IRQ_CAN_TX=11
+CONFIG_IRQ_PROG_INTA=12
+
+#
+# Board customizations
+#
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Clock/PLL Setup
+#
+CONFIG_CLKIN_HZ=25000000
+# CONFIG_BFIN_KERNEL_CLOCK is not set
+CONFIG_MAX_VCO_HZ=600000000
+CONFIG_MIN_VCO_HZ=50000000
+CONFIG_MAX_SCLK_HZ=133333333
+CONFIG_MIN_SCLK_HZ=27000000
+
+#
+# Kernel Timer/Scheduler
+#
+# 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
+
+#
+# Memory Setup
+#
+CONFIG_MAX_MEM_SIZE=32
+CONFIG_MEM_ADD_WIDTH=9
+CONFIG_BOOT_LOAD=0x1000
+CONFIG_BFIN_SCRATCH_REG_RETN=y
+# CONFIG_BFIN_SCRATCH_REG_RETE is not set
+# CONFIG_BFIN_SCRATCH_REG_CYCLES is not set
+
+#
+# Blackfin Kernel Optimizations
+#
+
+#
+# Memory Optimizations
+#
+CONFIG_I_ENTRY_L1=y
+CONFIG_EXCPT_IRQ_SYSC_L1=y
+CONFIG_DO_IRQ_L1=y
+CONFIG_CORE_TIMER_IRQ_L1=y
+CONFIG_IDLE_L1=y
+CONFIG_SCHEDULE_L1=y
+CONFIG_ARITHMETIC_OPS_L1=y
+CONFIG_ACCESS_OK_L1=y
+CONFIG_MEMSET_L1=y
+CONFIG_MEMCPY_L1=y
+CONFIG_SYS_BFIN_SPINLOCK_L1=y
+CONFIG_IP_CHECKSUM_L1=y
+CONFIG_CACHELINE_ALIGNED_L1=y
+CONFIG_SYSCALL_TAB_L1=y
+CONFIG_CPLB_SWITCH_TAB_L1=y
+CONFIG_RAMKERNEL=y
+# CONFIG_ROMKERNEL is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_LARGE_ALLOCS=y
+# CONFIG_BFIN_GPTIMERS is not set
+CONFIG_BFIN_DMA_5XX=y
+# CONFIG_DMA_UNCACHED_2M is not set
+CONFIG_DMA_UNCACHED_1M=y
+# CONFIG_DMA_UNCACHED_NONE is not set
+
+#
+# Cache Support
+#
+CONFIG_BFIN_ICACHE=y
+CONFIG_BFIN_DCACHE=y
+# CONFIG_BFIN_DCACHE_BANKA is not set
+# CONFIG_BFIN_ICACHE_LOCK is not set
+CONFIG_BFIN_WB=y
+# CONFIG_BFIN_WT is not set
+CONFIG_L1_MAX_PIECE=16
+# CONFIG_MPU is not set
+
+#
+# Asynchonous Memory Configuration
+#
+
+#
+# EBIU_AMGCTL Global Control
+#
+CONFIG_C_AMCKEN=y
+CONFIG_C_CDPRIO=y
+# CONFIG_C_AMBEN is not set
+# CONFIG_C_AMBEN_B0 is not set
+# CONFIG_C_AMBEN_B0_B1 is not set
+# CONFIG_C_AMBEN_B0_B1_B2 is not set
+CONFIG_C_AMBEN_ALL=y
+
+#
+# EBIU_AMBCTL Control
+#
+CONFIG_BANK_0=0x7BB0
+CONFIG_BANK_1=0x7BB0
+CONFIG_BANK_2=0x7BB0
+CONFIG_BANK_3=0xFFC3
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF_FDPIC=y
+CONFIG_BINFMT_FLAT=y
+CONFIG_BINFMT_ZFLAT=y
+CONFIG_BINFMT_SHARED_FLAT=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+# CONFIG_PM_WAKEUP_BY_GPIO is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Networking
+#
+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_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# 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_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETLABEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE 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
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO 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_RFKILL is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_RAM=y
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_UCLINUX=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI 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_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# Misc devices
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY 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_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_SMC91X is not set
+CONFIG_BFIN_MAC=y
+CONFIG_BFIN_MAC_USE_L1=y
+CONFIG_BFIN_TX_DESC_NUM=10
+CONFIG_BFIN_RX_DESC_NUM=20
+# CONFIG_BFIN_MAC_RMII is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_DM9000 is not set
+CONFIG_NETDEV_1000=y
+# CONFIG_AX88180 is not set
+CONFIG_NETDEV_10000=y
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 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
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_AD9960 is not set
+# CONFIG_SPI_ADC_BF533 is not set
+# CONFIG_BF5xx_PFLAGS is not set
+# CONFIG_BF5xx_PPIFCD is not set
+# CONFIG_BFIN_SIMPLE_TIMER is not set
+# CONFIG_BF5xx_PPI is not set
+CONFIG_BFIN_SPORT=y
+# CONFIG_BFIN_TIMER_LATENCY is not set
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_BFIN=y
+CONFIG_SERIAL_BFIN_CONSOLE=y
+CONFIG_SERIAL_BFIN_DMA=y
+# CONFIG_SERIAL_BFIN_PIO is not set
+CONFIG_SERIAL_BFIN_UART0=y
+# CONFIG_BFIN_UART0_CTSRTS is not set
+CONFIG_SERIAL_BFIN_UART1=y
+# CONFIG_BFIN_UART1_CTSRTS is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_BFIN_SPORT is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# CAN, the car bus and industrial fieldbus
+#
+# CONFIG_CAN4LINUX is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
+
+#
+# Graphics support
+#
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+# CONFIG_USB is not set
+
+#
+# Enable Host or Gadget support to see Inventra options
+#
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# PBX support
+#
+# CONFIG_PBX is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+# CONFIG_EXT2_FS_POSIX_ACL is not set
+# CONFIG_EXT2_FS_SECURITY is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+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
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# 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_YAFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+# CONFIG_NFS_FS is not set
+# CONFIG_NFSD 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
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+# 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_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_MMRS is not set
+# CONFIG_DEBUG_HUNT_FOR_ZERO is not set
+CONFIG_DEBUG_BFIN_HWTRACE_ON=y
+CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
+# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE is not set
+# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_TWO is not set
+CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0
+# CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set
+# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
+# CONFIG_EARLY_PRINTK is not set
+CONFIG_CPLB_INFO=y
+CONFIG_ACCESS_CHECK=y
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+CONFIG_SECURITY=y
+# CONFIG_SECURITY_NETWORK is not set
+CONFIG_SECURITY_CAPABILITIES=y
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/blackfin/configs/CM-BF537U_defconfig b/arch/blackfin/configs/CM-BF537U_defconfig
new file mode 100644 (file)
index 0000000..2694d06
--- /dev/null
@@ -0,0 +1,940 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.22.16
+#
+# CONFIG_MMU is not set
+# CONFIG_FPU is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_BLACKFIN=y
+CONFIG_ZONE_DMA=y
+CONFIG_SEMAPHORE_SLEEPERS=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_FORCE_MAX_ZONEORDER=14
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT 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_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+# CONFIG_UID16 is not set
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_EVENTFD=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3
+# CONFIG_NP2 is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_RT_MUTEXES=y
+CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+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
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+
+#
+# Blackfin Processor Options
+#
+
+#
+# Processor and Board Settings
+#
+# CONFIG_BF522 is not set
+# CONFIG_BF523 is not set
+# CONFIG_BF524 is not set
+# CONFIG_BF525 is not set
+# CONFIG_BF526 is not set
+# CONFIG_BF527 is not set
+# CONFIG_BF531 is not set
+# CONFIG_BF532 is not set
+# CONFIG_BF533 is not set
+# CONFIG_BF534 is not set
+# CONFIG_BF536 is not set
+CONFIG_BF537=y
+# CONFIG_BF542 is not set
+# CONFIG_BF544 is not set
+# CONFIG_BF547 is not set
+# CONFIG_BF548 is not set
+# CONFIG_BF549 is not set
+# CONFIG_BF561 is not set
+# CONFIG_BF_REV_0_0 is not set
+# CONFIG_BF_REV_0_1 is not set
+CONFIG_BF_REV_0_2=y
+# CONFIG_BF_REV_0_3 is not set
+# CONFIG_BF_REV_0_4 is not set
+# CONFIG_BF_REV_0_5 is not set
+# CONFIG_BF_REV_ANY is not set
+# CONFIG_BF_REV_NONE is not set
+CONFIG_BF53x=y
+CONFIG_BFIN_SINGLE_CORE=y
+CONFIG_MEM_MT48LC16M16A2TG_75=y
+CONFIG_IRQ_PLL_WAKEUP=7
+CONFIG_IRQ_RTC=8
+CONFIG_IRQ_PPI=8
+CONFIG_IRQ_SPORT0_RX=9
+CONFIG_IRQ_SPORT0_TX=9
+CONFIG_IRQ_SPORT1_RX=9
+CONFIG_IRQ_SPORT1_TX=9
+CONFIG_IRQ_TWI=10
+CONFIG_IRQ_SPI=10
+CONFIG_IRQ_UART0_RX=10
+CONFIG_IRQ_UART0_TX=10
+CONFIG_IRQ_UART1_RX=10
+CONFIG_IRQ_UART1_TX=10
+CONFIG_IRQ_MAC_RX=11
+CONFIG_IRQ_MAC_TX=11
+CONFIG_IRQ_TMR0=12
+CONFIG_IRQ_TMR1=12
+CONFIG_IRQ_TMR2=12
+CONFIG_IRQ_TMR3=12
+CONFIG_IRQ_TMR4=12
+CONFIG_IRQ_TMR5=12
+CONFIG_IRQ_TMR6=12
+CONFIG_IRQ_TMR7=12
+CONFIG_IRQ_PORTG_INTB=12
+CONFIG_IRQ_MEM_DMA0=13
+CONFIG_IRQ_MEM_DMA1=13
+CONFIG_IRQ_WATCH=13
+# CONFIG_BFIN537_STAMP is not set
+CONFIG_BFIN537_BLUETECHNIX_CM=y
+# CONFIG_PNAV10 is not set
+# CONFIG_CAMSIG_MINOTAUR is not set
+# CONFIG_GENERIC_BF537_BOARD is not set
+
+#
+# BF537 Specific Configuration
+#
+
+#
+# Interrupt Priority Assignment
+#
+
+#
+# Priority
+#
+CONFIG_IRQ_DMA_ERROR=7
+CONFIG_IRQ_ERROR=7
+CONFIG_IRQ_CAN_RX=11
+CONFIG_IRQ_CAN_TX=11
+CONFIG_IRQ_PROG_INTA=12
+
+#
+# Board customizations
+#
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Clock/PLL Setup
+#
+CONFIG_CLKIN_HZ=30000000
+# CONFIG_BFIN_KERNEL_CLOCK is not set
+CONFIG_MAX_VCO_HZ=600000000
+CONFIG_MIN_VCO_HZ=50000000
+CONFIG_MAX_SCLK_HZ=133333333
+CONFIG_MIN_SCLK_HZ=27000000
+
+#
+# Kernel Timer/Scheduler
+#
+# 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
+
+#
+# Memory Setup
+#
+CONFIG_MAX_MEM_SIZE=32
+CONFIG_MEM_ADD_WIDTH=9
+CONFIG_BOOT_LOAD=0x1000
+CONFIG_BFIN_SCRATCH_REG_RETN=y
+# CONFIG_BFIN_SCRATCH_REG_RETE is not set
+# CONFIG_BFIN_SCRATCH_REG_CYCLES is not set
+
+#
+# Blackfin Kernel Optimizations
+#
+
+#
+# Memory Optimizations
+#
+CONFIG_I_ENTRY_L1=y
+CONFIG_EXCPT_IRQ_SYSC_L1=y
+CONFIG_DO_IRQ_L1=y
+CONFIG_CORE_TIMER_IRQ_L1=y
+CONFIG_IDLE_L1=y
+CONFIG_SCHEDULE_L1=y
+CONFIG_ARITHMETIC_OPS_L1=y
+CONFIG_ACCESS_OK_L1=y
+CONFIG_MEMSET_L1=y
+CONFIG_MEMCPY_L1=y
+CONFIG_SYS_BFIN_SPINLOCK_L1=y
+CONFIG_IP_CHECKSUM_L1=y
+CONFIG_CACHELINE_ALIGNED_L1=y
+CONFIG_SYSCALL_TAB_L1=y
+CONFIG_CPLB_SWITCH_TAB_L1=y
+CONFIG_RAMKERNEL=y
+# CONFIG_ROMKERNEL is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_LARGE_ALLOCS=y
+# CONFIG_BFIN_GPTIMERS is not set
+CONFIG_BFIN_DMA_5XX=y
+# CONFIG_DMA_UNCACHED_2M is not set
+CONFIG_DMA_UNCACHED_1M=y
+# CONFIG_DMA_UNCACHED_NONE is not set
+
+#
+# Cache Support
+#
+CONFIG_BFIN_ICACHE=y
+CONFIG_BFIN_DCACHE=y
+# CONFIG_BFIN_DCACHE_BANKA is not set
+# CONFIG_BFIN_ICACHE_LOCK is not set
+CONFIG_BFIN_WB=y
+# CONFIG_BFIN_WT is not set
+CONFIG_L1_MAX_PIECE=16
+# CONFIG_MPU is not set
+
+#
+# Asynchonous Memory Configuration
+#
+
+#
+# EBIU_AMGCTL Global Control
+#
+CONFIG_C_AMCKEN=y
+CONFIG_C_CDPRIO=y
+# CONFIG_C_AMBEN is not set
+# CONFIG_C_AMBEN_B0 is not set
+# CONFIG_C_AMBEN_B0_B1 is not set
+# CONFIG_C_AMBEN_B0_B1_B2 is not set
+CONFIG_C_AMBEN_ALL=y
+
+#
+# EBIU_AMBCTL Control
+#
+CONFIG_BANK_0=0x7BB0
+CONFIG_BANK_1=0x7BB0
+CONFIG_BANK_2=0xFFC3
+CONFIG_BANK_3=0xFFC3
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF_FDPIC=y
+CONFIG_BINFMT_FLAT=y
+CONFIG_BINFMT_ZFLAT=y
+CONFIG_BINFMT_SHARED_FLAT=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+# CONFIG_PM_WAKEUP_BY_GPIO is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Networking
+#
+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_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# 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_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETLABEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE 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
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO 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_RFKILL is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_RAM=y
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_UCLINUX=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI 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_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# Misc devices
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_SMC91X=y
+# CONFIG_BFIN_MAC is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_DM9000 is not set
+CONFIG_NETDEV_1000=y
+# CONFIG_AX88180 is not set
+CONFIG_NETDEV_10000=y
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 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
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_AD9960 is not set
+# CONFIG_SPI_ADC_BF533 is not set
+# CONFIG_BF5xx_PFLAGS is not set
+# CONFIG_BF5xx_PPIFCD is not set
+# CONFIG_BFIN_SIMPLE_TIMER is not set
+# CONFIG_BF5xx_PPI is not set
+CONFIG_BFIN_SPORT=y
+# CONFIG_BFIN_TIMER_LATENCY is not set
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_BFIN=y
+CONFIG_SERIAL_BFIN_CONSOLE=y
+CONFIG_SERIAL_BFIN_DMA=y
+# CONFIG_SERIAL_BFIN_PIO is not set
+CONFIG_SERIAL_BFIN_UART0=y
+# CONFIG_BFIN_UART0_CTSRTS is not set
+CONFIG_SERIAL_BFIN_UART1=y
+# CONFIG_BFIN_UART1_CTSRTS is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_BFIN_SPORT is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# CAN, the car bus and industrial fieldbus
+#
+# CONFIG_CAN4LINUX is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
+
+#
+# Graphics support
+#
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+# CONFIG_USB 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'
+#
+
+#
+# USB Gadget Support
+#
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+CONFIG_USB_GADGET_NET2272=y
+CONFIG_USB_NET2272=y
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_PXA2XX 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_AT91 is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+# CONFIG_USB_ZERO is not set
+# CONFIG_USB_ETH is not set
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FILE_STORAGE is not set
+# CONFIG_USB_G_SERIAL is not set
+# CONFIG_USB_MIDI_GADGET is not set
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# PBX support
+#
+# CONFIG_PBX is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+# CONFIG_EXT2_FS_POSIX_ACL is not set
+# CONFIG_EXT2_FS_SECURITY is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+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
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# 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_YAFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+# CONFIG_NFS_FS is not set
+# CONFIG_NFSD 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
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+# 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_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_MMRS is not set
+# CONFIG_DEBUG_HUNT_FOR_ZERO is not set
+CONFIG_DEBUG_BFIN_HWTRACE_ON=y
+CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
+# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE is not set
+# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_TWO is not set
+CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0
+# CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set
+# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
+# CONFIG_EARLY_PRINTK is not set
+CONFIG_CPLB_INFO=y
+CONFIG_ACCESS_CHECK=y
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+CONFIG_SECURITY=y
+# CONFIG_SECURITY_NETWORK is not set
+CONFIG_SECURITY_CAPABILITIES=y
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/blackfin/configs/CM-BF548_defconfig b/arch/blackfin/configs/CM-BF548_defconfig
new file mode 100644 (file)
index 0000000..9020725
--- /dev/null
@@ -0,0 +1,1373 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.24.4
+#
+# CONFIG_MMU is not set
+# CONFIG_FPU is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_BLACKFIN=y
+CONFIG_ZONE_DMA=y
+CONFIG_SEMAPHORE_SLEEPERS=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_FORCE_MAX_ZONEORDER=14
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SYSVIPC=y
+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=y
+CONFIG_IKCONFIG_PROC=y
+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_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_EVENTFD=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3
+# CONFIG_NP2 is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+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_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+
+#
+# Blackfin Processor Options
+#
+
+#
+# Processor and Board Settings
+#
+# CONFIG_BF522 is not set
+# CONFIG_BF523 is not set
+# CONFIG_BF524 is not set
+# CONFIG_BF525 is not set
+# CONFIG_BF526 is not set
+# CONFIG_BF527 is not set
+# CONFIG_BF531 is not set
+# CONFIG_BF532 is not set
+# CONFIG_BF533 is not set
+# CONFIG_BF534 is not set
+# CONFIG_BF536 is not set
+# CONFIG_BF537 is not set
+# CONFIG_BF542 is not set
+# CONFIG_BF544 is not set
+# CONFIG_BF547 is not set
+CONFIG_BF548=y
+# CONFIG_BF549 is not set
+# CONFIG_BF561 is not set
+CONFIG_BF_REV_0_0=y
+# CONFIG_BF_REV_0_1 is not set
+# CONFIG_BF_REV_0_2 is not set
+# CONFIG_BF_REV_0_3 is not set
+# CONFIG_BF_REV_0_4 is not set
+# CONFIG_BF_REV_0_5 is not set
+# CONFIG_BF_REV_ANY is not set
+# CONFIG_BF_REV_NONE is not set
+CONFIG_BF54x=y
+CONFIG_IRQ_PLL_WAKEUP=7
+CONFIG_IRQ_RTC=8
+CONFIG_IRQ_SPORT0_RX=9
+CONFIG_IRQ_SPORT0_TX=9
+CONFIG_IRQ_SPORT1_RX=9
+CONFIG_IRQ_SPORT1_TX=9
+CONFIG_IRQ_UART0_RX=10
+CONFIG_IRQ_UART0_TX=10
+CONFIG_IRQ_UART1_RX=10
+CONFIG_IRQ_UART1_TX=10
+CONFIG_IRQ_CNT=8
+CONFIG_IRQ_USB_INT0=11
+CONFIG_IRQ_USB_INT1=11
+CONFIG_IRQ_USB_INT2=11
+CONFIG_IRQ_USB_DMA=11
+CONFIG_IRQ_TIMER0=11
+CONFIG_IRQ_TIMER1=11
+CONFIG_IRQ_TIMER2=11
+CONFIG_IRQ_TIMER3=11
+CONFIG_IRQ_TIMER4=11
+CONFIG_IRQ_TIMER5=11
+CONFIG_IRQ_TIMER6=11
+CONFIG_IRQ_TIMER7=11
+CONFIG_IRQ_TIMER8=11
+CONFIG_IRQ_TIMER9=11
+CONFIG_IRQ_TIMER10=11
+# CONFIG_BFIN548_EZKIT is not set
+CONFIG_BFIN548_BLUETECHNIX_CM=y
+
+#
+# BF548 Specific Configuration
+#
+# CONFIG_DEB_DMA_URGENT is not set
+
+#
+# Interrupt Priority Assignment
+#
+
+#
+# Priority
+#
+CONFIG_IRQ_DMAC0_ERR=7
+CONFIG_IRQ_EPPI0_ERR=7
+CONFIG_IRQ_SPORT0_ERR=7
+CONFIG_IRQ_SPORT1_ERR=7
+CONFIG_IRQ_SPI0_ERR=7
+CONFIG_IRQ_UART0_ERR=7
+CONFIG_IRQ_EPPI0=8
+CONFIG_IRQ_SPI0=10
+CONFIG_IRQ_PINT0=12
+CONFIG_IRQ_PINT1=12
+CONFIG_IRQ_MDMAS0=13
+CONFIG_IRQ_MDMAS1=13
+CONFIG_IRQ_WATCHDOG=13
+CONFIG_IRQ_DMAC1_ERR=7
+CONFIG_IRQ_SPORT2_ERR=7
+CONFIG_IRQ_SPORT3_ERR=7
+CONFIG_IRQ_MXVR_DATA=7
+CONFIG_IRQ_SPI1_ERR=7
+CONFIG_IRQ_SPI2_ERR=7
+CONFIG_IRQ_UART1_ERR=7
+CONFIG_IRQ_UART2_ERR=7
+CONFIG_IRQ_CAN0_ERR=7
+CONFIG_IRQ_SPORT2_RX=9
+CONFIG_IRQ_SPORT2_TX=9
+CONFIG_IRQ_SPORT3_RX=9
+CONFIG_IRQ_SPORT3_TX=9
+CONFIG_IRQ_EPPI1=9
+CONFIG_IRQ_EPPI2=9
+CONFIG_IRQ_SPI1=10
+CONFIG_IRQ_SPI2=10
+CONFIG_IRQ_ATAPI_RX=10
+CONFIG_IRQ_ATAPI_TX=10
+CONFIG_IRQ_TWI0=11
+CONFIG_IRQ_TWI1=11
+CONFIG_IRQ_CAN0_RX=11
+CONFIG_IRQ_CAN0_TX=11
+CONFIG_IRQ_MDMAS2=13
+CONFIG_IRQ_MDMAS3=13
+CONFIG_IRQ_MXVR_ERR=11
+CONFIG_IRQ_MXVR_MSG=11
+CONFIG_IRQ_MXVR_PKT=11
+CONFIG_IRQ_EPPI1_ERR=7
+CONFIG_IRQ_EPPI2_ERR=7
+CONFIG_IRQ_UART3_ERR=7
+CONFIG_IRQ_HOST_ERR=7
+CONFIG_IRQ_PIXC_ERR=7
+CONFIG_IRQ_NFC_ERR=7
+CONFIG_IRQ_ATAPI_ERR=7
+CONFIG_IRQ_CAN1_ERR=7
+CONFIG_IRQ_HS_DMA_ERR=7
+CONFIG_IRQ_PIXC_IN0=8
+CONFIG_IRQ_PIXC_IN1=8
+CONFIG_IRQ_PIXC_OUT=8
+CONFIG_IRQ_SDH=8
+CONFIG_IRQ_KEY=8
+CONFIG_IRQ_CAN1_RX=11
+CONFIG_IRQ_CAN1_TX=11
+CONFIG_IRQ_SDH_MASK0=11
+CONFIG_IRQ_SDH_MASK1=11
+CONFIG_IRQ_OTPSEC=11
+CONFIG_IRQ_PINT2=11
+CONFIG_IRQ_PINT3=11
+
+#
+# Pin Interrupt to Port Assignment
+#
+
+#
+# Assignment
+#
+CONFIG_PINTx_REASSIGN=y
+CONFIG_PINT0_ASSIGN=0x00000101
+CONFIG_PINT1_ASSIGN=0x01010000
+CONFIG_PINT2_ASSIGN=0x07000101
+CONFIG_PINT3_ASSIGN=0x02020303
+
+#
+# Board customizations
+#
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Clock/PLL Setup
+#
+CONFIG_CLKIN_HZ=25000000
+# CONFIG_BFIN_KERNEL_CLOCK is not set
+CONFIG_MAX_VCO_HZ=600000000
+CONFIG_MIN_VCO_HZ=50000000
+CONFIG_MAX_SCLK_HZ=133333333
+CONFIG_MIN_SCLK_HZ=27000000
+
+#
+# Kernel Timer/Scheduler
+#
+# 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_GENERIC_TIME is not set
+# CONFIG_TICK_ONESHOT is not set
+
+#
+# Memory Setup
+#
+CONFIG_MAX_MEM_SIZE=64
+# CONFIG_MEM_MT46V32M16_6T is not set
+CONFIG_MEM_MT46V32M16_5B=y
+CONFIG_BOOT_LOAD=0x1000
+CONFIG_BFIN_SCRATCH_REG_RETN=y
+# CONFIG_BFIN_SCRATCH_REG_RETE is not set
+# CONFIG_BFIN_SCRATCH_REG_CYCLES is not set
+
+#
+# Blackfin Kernel Optimizations
+#
+
+#
+# Memory Optimizations
+#
+CONFIG_I_ENTRY_L1=y
+CONFIG_EXCPT_IRQ_SYSC_L1=y
+CONFIG_DO_IRQ_L1=y
+CONFIG_CORE_TIMER_IRQ_L1=y
+CONFIG_IDLE_L1=y
+# CONFIG_SCHEDULE_L1 is not set
+CONFIG_ARITHMETIC_OPS_L1=y
+CONFIG_ACCESS_OK_L1=y
+# CONFIG_MEMSET_L1 is not set
+# CONFIG_MEMCPY_L1 is not set
+# CONFIG_SYS_BFIN_SPINLOCK_L1 is not set
+# CONFIG_IP_CHECKSUM_L1 is not set
+CONFIG_CACHELINE_ALIGNED_L1=y
+# CONFIG_SYSCALL_TAB_L1 is not set
+# CONFIG_CPLB_SWITCH_TAB_L1 is not set
+CONFIG_RAMKERNEL=y
+# CONFIG_ROMKERNEL is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_BFIN_GPTIMERS is not set
+CONFIG_BFIN_DMA_5XX=y
+# CONFIG_DMA_UNCACHED_2M is not set
+CONFIG_DMA_UNCACHED_1M=y
+# CONFIG_DMA_UNCACHED_NONE is not set
+
+#
+# Cache Support
+#
+CONFIG_BFIN_ICACHE=y
+CONFIG_BFIN_DCACHE=y
+# CONFIG_BFIN_DCACHE_BANKA is not set
+# CONFIG_BFIN_ICACHE_LOCK is not set
+# CONFIG_BFIN_WB is not set
+CONFIG_BFIN_WT=y
+CONFIG_L1_MAX_PIECE=16
+# CONFIG_MPU is not set
+
+#
+# Asynchonous Memory Configuration
+#
+
+#
+# EBIU_AMGCTL Global Control
+#
+CONFIG_C_AMCKEN=y
+# CONFIG_C_CDPRIO is not set
+# CONFIG_C_AMBEN is not set
+# CONFIG_C_AMBEN_B0 is not set
+# CONFIG_C_AMBEN_B0_B1 is not set
+# CONFIG_C_AMBEN_B0_B1_B2 is not set
+CONFIG_C_AMBEN_ALL=y
+
+#
+# EBIU_AMBCTL Control
+#
+CONFIG_BANK_0=0x7BB0
+CONFIG_BANK_1=0x5554
+CONFIG_BANK_2=0x7BB0
+CONFIG_BANK_3=0x99B3
+CONFIG_EBIU_MBSCTLVAL=0x0
+CONFIG_EBIU_MODEVAL=0x1
+CONFIG_EBIU_FCTLVAL=0x6
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF_FDPIC=y
+CONFIG_BINFMT_FLAT=y
+CONFIG_BINFMT_ZFLAT=y
+# CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+CONFIG_SUSPEND_UP_POSSIBLE=y
+# CONFIG_PM_WAKEUP_BY_GPIO is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Networking
+#
+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_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# 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_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# 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_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 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETLABEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE 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_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_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 is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# 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
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+CONFIG_MTD_RAM=y
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0x20000000
+CONFIG_MTD_PHYSMAP_LEN=0x800000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# CONFIG_MTD_UCLINUX is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_IDE 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
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_ATA is not set
+# CONFIG_MD 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_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_SMC91X is not set
+CONFIG_SMSC911X=y
+# 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_B44 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_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
+# 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 is not set
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=m
+CONFIG_INPUT_EVBUG=m
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# 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_KEYBOARD_BFIN is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_AD9960 is not set
+# CONFIG_SPI_ADC_BF533 is not set
+# CONFIG_BF5xx_PPIFCD is not set
+# CONFIG_BFIN_SIMPLE_TIMER is not set
+# CONFIG_BF5xx_PPI is not set
+CONFIG_BFIN_OTP=y
+# CONFIG_BFIN_OTP_WRITE_ENABLE is not set
+# CONFIG_BFIN_SPORT is not set
+# CONFIG_BFIN_TIMER_LATENCY is not set
+# CONFIG_TWI_LCD is not set
+# CONFIG_SIMPLE_GPIO is not set
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_BFIN=y
+CONFIG_SERIAL_BFIN_CONSOLE=y
+# CONFIG_SERIAL_BFIN_DMA is not set
+CONFIG_SERIAL_BFIN_PIO=y
+# CONFIG_SERIAL_BFIN_UART0 is not set
+CONFIG_SERIAL_BFIN_UART1=y
+# CONFIG_BFIN_UART1_CTSRTS is not set
+# CONFIG_SERIAL_BFIN_UART2 is not set
+# CONFIG_SERIAL_BFIN_UART3 is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_BFIN_SPORT is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# CAN, the car bus and industrial fieldbus
+#
+# CONFIG_CAN4LINUX is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_GEN_RTC is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+CONFIG_I2C_BLACKFIN_TWI=y
+CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=50
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_TINY_USB 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_SENSORS_AD5252 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8575 is not set
+# CONFIG_SENSORS_PCA9543 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=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BFIN=y
+# CONFIG_SPI_BITBANG is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_AT25 is not set
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 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_AD7418 is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_BFIN_WDT=y
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
+# CONFIG_USB_DABUSB 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
+
+#
+# Sound
+#
+# 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_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+CONFIG_USB_MUSB_HDRC=y
+CONFIG_USB_MUSB_SOC=y
+
+#
+# Blackfin BF54x, BF525 and BF527 high speed USB support
+#
+CONFIG_USB_MUSB_HOST=y
+# CONFIG_USB_MUSB_PERIPHERAL is not set
+# CONFIG_USB_MUSB_OTG is not set
+CONFIG_USB_MUSB_HDRC_HCD=y
+# CONFIG_MUSB_PIO_ONLY is not set
+# CONFIG_USB_INVENTRA_DMA is not set
+# CONFIG_USB_TI_CPPI_DMA is not set
+CONFIG_USB_MUSB_LOGLEVEL=0
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# 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_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# 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
+
+#
+# USB Miscellaneous drivers
+#
+# 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_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+
+#
+# MMC/SD Host Controller Drivers
+#
+CONFIG_SDH_BFIN=y
+# CONFIG_MMC_SPI is not set
+# CONFIG_SPI_MMC is not set
+# CONFIG_NEW_LEDS is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# 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
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_BFIN=y
+
+#
+# Userspace I/O
+#
+# CONFIG_UIO is not set
+
+#
+# PBX support
+#
+# CONFIG_PBX is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+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
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+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=m
+# CONFIG_NTFS_DEBUG is not set
+CONFIG_NTFS_RW=y
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS 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_YAFFS_FS=m
+CONFIG_YAFFS_YAFFS1=y
+# CONFIG_YAFFS_DOES_ECC is not set
+CONFIG_YAFFS_YAFFS2=y
+CONFIG_YAFFS_AUTO_YAFFS2=y
+# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
+CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS=10
+# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
+# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
+CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
+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 is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=m
+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=m
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+# CONFIG_NFSD_V4 is not set
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_SMB_NLS_REMOTE="cp437"
+CONFIG_CIFS=y
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_WEAK_PW_HASH 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
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_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 is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION 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
+CONFIG_INSTRUMENTATION=y
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_SAMPLES is not set
+# CONFIG_DEBUG_MMRS is not set
+CONFIG_DEBUG_HUNT_FOR_ZERO=y
+CONFIG_DEBUG_BFIN_HWTRACE_ON=y
+CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
+# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE is not set
+# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_TWO is not set
+CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0
+# CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set
+# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
+# CONFIG_EARLY_PRINTK is not set
+CONFIG_CPLB_INFO=y
+CONFIG_ACCESS_CHECK=y
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+CONFIG_SECURITY=y
+# CONFIG_SECURITY_NETWORK is not set
+# CONFIG_SECURITY_CAPABILITIES is not set
+# CONFIG_SECURITY_ROOTPLUG is not set
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 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_ZLIB_DEFLATE=m
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/blackfin/configs/CM-BF561_defconfig b/arch/blackfin/configs/CM-BF561_defconfig
new file mode 100644 (file)
index 0000000..daf0090
--- /dev/null
@@ -0,0 +1,876 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.24.4
+# Tue Apr  1 10:50:11 2008
+#
+# CONFIG_MMU is not set
+# CONFIG_FPU is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_BLACKFIN=y
+CONFIG_ZONE_DMA=y
+CONFIG_SEMAPHORE_SLEEPERS=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_FORCE_MAX_ZONEORDER=14
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SYSVIPC=y
+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_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+# CONFIG_UID16 is not set
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_EVENTFD=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3
+# CONFIG_NP2 is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+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_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+
+#
+# Blackfin Processor Options
+#
+
+#
+# Processor and Board Settings
+#
+# CONFIG_BF522 is not set
+# CONFIG_BF523 is not set
+# CONFIG_BF524 is not set
+# CONFIG_BF525 is not set
+# CONFIG_BF526 is not set
+# CONFIG_BF527 is not set
+# CONFIG_BF531 is not set
+# CONFIG_BF532 is not set
+# CONFIG_BF533 is not set
+# CONFIG_BF534 is not set
+# CONFIG_BF536 is not set
+# CONFIG_BF537 is not set
+# CONFIG_BF542 is not set
+# CONFIG_BF544 is not set
+# CONFIG_BF547 is not set
+# CONFIG_BF548 is not set
+# CONFIG_BF549 is not set
+CONFIG_BF561=y
+# CONFIG_BF_REV_0_0 is not set
+# CONFIG_BF_REV_0_1 is not set
+# CONFIG_BF_REV_0_2 is not set
+CONFIG_BF_REV_0_3=y
+# CONFIG_BF_REV_0_4 is not set
+# CONFIG_BF_REV_0_5 is not set
+# CONFIG_BF_REV_ANY is not set
+# CONFIG_BF_REV_NONE is not set
+CONFIG_BFIN_DUAL_CORE=y
+CONFIG_MEM_MT48LC8M32B2B5_7=y
+CONFIG_IRQ_PLL_WAKEUP=7
+CONFIG_IRQ_SPORT0_ERROR=7
+CONFIG_IRQ_SPORT1_ERROR=7
+CONFIG_IRQ_SPI_ERROR=7
+# CONFIG_BFIN561_EZKIT is not set
+# CONFIG_BFIN561_TEPLA is not set
+CONFIG_BFIN561_BLUETECHNIX_CM=y
+# CONFIG_GENERIC_BF561_BOARD is not set
+
+#
+# BF561 Specific Configuration
+#
+
+#
+# Core B Support
+#
+
+#
+# Core B Support
+#
+CONFIG_BF561_COREB=y
+# CONFIG_BF561_COREB_RESET is not set
+
+#
+# Interrupt Priority Assignment
+#
+
+#
+# Priority
+#
+CONFIG_IRQ_DMA1_ERROR=7
+CONFIG_IRQ_DMA2_ERROR=7
+CONFIG_IRQ_IMDMA_ERROR=7
+CONFIG_IRQ_PPI0_ERROR=7
+CONFIG_IRQ_PPI1_ERROR=7
+CONFIG_IRQ_UART_ERROR=7
+CONFIG_IRQ_RESERVED_ERROR=7
+CONFIG_IRQ_DMA1_0=8
+CONFIG_IRQ_DMA1_1=8
+CONFIG_IRQ_DMA1_2=8
+CONFIG_IRQ_DMA1_3=8
+CONFIG_IRQ_DMA1_4=8
+CONFIG_IRQ_DMA1_5=8
+CONFIG_IRQ_DMA1_6=8
+CONFIG_IRQ_DMA1_7=8
+CONFIG_IRQ_DMA1_8=8
+CONFIG_IRQ_DMA1_9=8
+CONFIG_IRQ_DMA1_10=8
+CONFIG_IRQ_DMA1_11=8
+CONFIG_IRQ_DMA2_0=9
+CONFIG_IRQ_DMA2_1=9
+CONFIG_IRQ_DMA2_2=9
+CONFIG_IRQ_DMA2_3=9
+CONFIG_IRQ_DMA2_4=9
+CONFIG_IRQ_DMA2_5=9
+CONFIG_IRQ_DMA2_6=9
+CONFIG_IRQ_DMA2_7=9
+CONFIG_IRQ_DMA2_8=9
+CONFIG_IRQ_DMA2_9=9
+CONFIG_IRQ_DMA2_10=9
+CONFIG_IRQ_DMA2_11=9
+CONFIG_IRQ_TIMER0=10
+CONFIG_IRQ_TIMER1=10
+CONFIG_IRQ_TIMER2=10
+CONFIG_IRQ_TIMER3=10
+CONFIG_IRQ_TIMER4=10
+CONFIG_IRQ_TIMER5=10
+CONFIG_IRQ_TIMER6=10
+CONFIG_IRQ_TIMER7=10
+CONFIG_IRQ_TIMER8=10
+CONFIG_IRQ_TIMER9=10
+CONFIG_IRQ_TIMER10=10
+CONFIG_IRQ_TIMER11=10
+CONFIG_IRQ_PROG0_INTA=11
+CONFIG_IRQ_PROG0_INTB=11
+CONFIG_IRQ_PROG1_INTA=11
+CONFIG_IRQ_PROG1_INTB=11
+CONFIG_IRQ_PROG2_INTA=11
+CONFIG_IRQ_PROG2_INTB=11
+CONFIG_IRQ_DMA1_WRRD0=8
+CONFIG_IRQ_DMA1_WRRD1=8
+CONFIG_IRQ_DMA2_WRRD0=9
+CONFIG_IRQ_DMA2_WRRD1=9
+CONFIG_IRQ_IMDMA_WRRD0=12
+CONFIG_IRQ_IMDMA_WRRD1=12
+CONFIG_IRQ_WDTIMER=13
+
+#
+# Board customizations
+#
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Clock/PLL Setup
+#
+CONFIG_CLKIN_HZ=25000000
+# CONFIG_BFIN_KERNEL_CLOCK is not set
+CONFIG_MAX_VCO_HZ=600000000
+CONFIG_MIN_VCO_HZ=50000000
+CONFIG_MAX_SCLK_HZ=133333333
+CONFIG_MIN_SCLK_HZ=27000000
+
+#
+# Kernel Timer/Scheduler
+#
+# 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_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_CYCLES_CLOCKSOURCE 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
+
+#
+# Memory Setup
+#
+CONFIG_MAX_MEM_SIZE=32
+CONFIG_BOOT_LOAD=0x1000
+CONFIG_BFIN_SCRATCH_REG_RETN=y
+# CONFIG_BFIN_SCRATCH_REG_RETE is not set
+# CONFIG_BFIN_SCRATCH_REG_CYCLES is not set
+
+#
+# Blackfin Kernel Optimizations
+#
+
+#
+# Memory Optimizations
+#
+CONFIG_I_ENTRY_L1=y
+CONFIG_EXCPT_IRQ_SYSC_L1=y
+CONFIG_DO_IRQ_L1=y
+CONFIG_CORE_TIMER_IRQ_L1=y
+CONFIG_IDLE_L1=y
+CONFIG_SCHEDULE_L1=y
+CONFIG_ARITHMETIC_OPS_L1=y
+CONFIG_ACCESS_OK_L1=y
+CONFIG_MEMSET_L1=y
+CONFIG_MEMCPY_L1=y
+CONFIG_SYS_BFIN_SPINLOCK_L1=y
+CONFIG_IP_CHECKSUM_L1=y
+CONFIG_CACHELINE_ALIGNED_L1=y
+CONFIG_SYSCALL_TAB_L1=y
+CONFIG_CPLB_SWITCH_TAB_L1=y
+CONFIG_RAMKERNEL=y
+# CONFIG_ROMKERNEL is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_VIRT_TO_BUS=y
+CONFIG_LARGE_ALLOCS=y
+# CONFIG_BFIN_GPTIMERS is not set
+CONFIG_BFIN_DMA_5XX=y
+# CONFIG_DMA_UNCACHED_2M is not set
+CONFIG_DMA_UNCACHED_1M=y
+# CONFIG_DMA_UNCACHED_NONE is not set
+
+#
+# Cache Support
+#
+CONFIG_BFIN_ICACHE=y
+CONFIG_BFIN_DCACHE=y
+# CONFIG_BFIN_DCACHE_BANKA is not set
+# CONFIG_BFIN_ICACHE_LOCK is not set
+CONFIG_BFIN_WB=y
+# CONFIG_BFIN_WT is not set
+CONFIG_L1_MAX_PIECE=16
+# CONFIG_MPU is not set
+
+#
+# Asynchonous Memory Configuration
+#
+
+#
+# EBIU_AMGCTL Global Control
+#
+CONFIG_C_AMCKEN=y
+CONFIG_C_CDPRIO=y
+CONFIG_C_B0PEN=y
+CONFIG_C_B1PEN=y
+CONFIG_C_B2PEN=y
+# CONFIG_C_B3PEN is not set
+# CONFIG_C_AMBEN is not set
+# CONFIG_C_AMBEN_B0 is not set
+# CONFIG_C_AMBEN_B0_B1 is not set
+# CONFIG_C_AMBEN_B0_B1_B2 is not set
+CONFIG_C_AMBEN_ALL=y
+
+#
+# EBIU_AMBCTL Control
+#
+CONFIG_BANK_0=0x7BB0
+CONFIG_BANK_1=0x7BB0
+CONFIG_BANK_2=0x7BB0
+CONFIG_BANK_3=0xFFC3
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF_FDPIC=y
+CONFIG_BINFMT_FLAT=y
+CONFIG_BINFMT_ZFLAT=y
+CONFIG_BINFMT_SHARED_FLAT=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+CONFIG_SUSPEND_UP_POSSIBLE=y
+# CONFIG_PM_WAKEUP_BY_GPIO is not set
+
+#
+# Networking
+#
+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_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# 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_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 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETLABEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE 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_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_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# 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
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_RAM=y
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_UCLINUX=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_IDE is not set
+# CONFIG_BFIN_IDE_ADDRESS_MAPPING_MODE0 is not set
+# CONFIG_BFIN_IDE_ADDRESS_MAPPING_MODE1 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_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_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_SMC91X=y
+# CONFIG_SMSC911X is not set
+# 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_B44 is not set
+CONFIG_NETDEV_1000=y
+# CONFIG_AX88180 is not set
+CONFIG_NETDEV_10000=y
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 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
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_AD9960 is not set
+# CONFIG_SPI_ADC_BF533 is not set
+# CONFIG_BF5xx_PPIFCD is not set
+# CONFIG_BFIN_SIMPLE_TIMER is not set
+# CONFIG_BF5xx_PPI is not set
+# CONFIG_BFIN_SPORT is not set
+# CONFIG_BFIN_TIMER_LATENCY is not set
+# CONFIG_SIMPLE_GPIO is not set
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_BFIN=y
+CONFIG_SERIAL_BFIN_CONSOLE=y
+CONFIG_SERIAL_BFIN_DMA=y
+# CONFIG_SERIAL_BFIN_PIO is not set
+CONFIG_SERIAL_BFIN_UART0=y
+# CONFIG_BFIN_UART0_CTSRTS is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_BFIN_SPORT is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# CAN, the car bus and industrial fieldbus
+#
+# CONFIG_CAN4LINUX is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# 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=y
+# CONFIG_HWMON_VID 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_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_WATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
+
+#
+# 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
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+# CONFIG_USB is not set
+
+#
+# Enable Host or Gadget support to see Inventra options
+#
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+# CONFIG_MMC is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_RTC_CLASS is not set
+
+#
+# Userspace I/O
+#
+# CONFIG_UIO is not set
+
+#
+# PBX support
+#
+# CONFIG_PBX is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+# CONFIG_EXT2_FS_POSIX_ACL is not set
+# CONFIG_EXT2_FS_SECURITY is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+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
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS 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_YAFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+# CONFIG_NFS_FS is not set
+# CONFIG_NFSD 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 is not set
+# CONFIG_DLM is not set
+CONFIG_INSTRUMENTATION=y
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+# 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_DEBUG_BUGVERBOSE is not set
+# CONFIG_SAMPLES is not set
+# CONFIG_DEBUG_MMRS is not set
+CONFIG_DEBUG_HUNT_FOR_ZERO=y
+CONFIG_DEBUG_BFIN_HWTRACE_ON=y
+CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
+# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE is not set
+# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_TWO is not set
+CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0
+# CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set
+# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
+# CONFIG_EARLY_PRINTK is not set
+# CONFIG_DUAL_CORE_TEST_MODULE is not set
+CONFIG_CPLB_INFO=y
+CONFIG_ACCESS_CHECK=y
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+CONFIG_SECURITY=y
+# CONFIG_SECURITY_NETWORK is not set
+CONFIG_SECURITY_CAPABILITIES=y
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 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
index 18cbb8c3c373072f23c6d1e09e2236610bdd812c..679c7483ea714361c67c2589e5c6ebcaf9506c1f 100644 (file)
@@ -13,7 +13,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
-# CONFIG_GENERIC_TIME is not set
+CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_GPIO=y
 CONFIG_FORCE_MAX_ZONEORDER=14
 CONFIG_GENERIC_CALIBRATE_DELAY=y
@@ -207,7 +207,7 @@ CONFIG_HZ=250
 #
 # Memory Setup
 #
-CONFIG_MEM_SIZE=32
+CONFIG_MAX_MEM_SIZE=32
 CONFIG_MEM_ADD_WIDTH=9
 CONFIG_BOOT_LOAD=0x1000
 CONFIG_BFIN_SCRATCH_REG_RETN=y
diff --git a/arch/blackfin/configs/IP0X_defconfig b/arch/blackfin/configs/IP0X_defconfig
new file mode 100644 (file)
index 0000000..5f6ff04
--- /dev/null
@@ -0,0 +1,1252 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.22.18
+#
+# CONFIG_MMU is not set
+# CONFIG_FPU is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_BLACKFIN=y
+CONFIG_ZONE_DMA=y
+CONFIG_SEMAPHORE_SLEEPERS=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+# CONFIG_GENERIC_TIME is not set
+CONFIG_GENERIC_GPIO=y
+CONFIG_FORCE_MAX_ZONEORDER=14
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT 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_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_EVENTFD=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3
+# CONFIG_NP2 is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_RT_MUTEXES=y
+CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+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
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+
+#
+# Blackfin Processor Options
+#
+
+#
+# Processor and Board Settings
+#
+# CONFIG_BF522 is not set
+# CONFIG_BF523 is not set
+# CONFIG_BF524 is not set
+# CONFIG_BF525 is not set
+# CONFIG_BF526 is not set
+# CONFIG_BF527 is not set
+# CONFIG_BF531 is not set
+CONFIG_BF532=y
+# CONFIG_BF533 is not set
+# CONFIG_BF534 is not set
+# CONFIG_BF536 is not set
+# CONFIG_BF537 is not set
+# CONFIG_BF542 is not set
+# CONFIG_BF544 is not set
+# CONFIG_BF547 is not set
+# CONFIG_BF548 is not set
+# CONFIG_BF549 is not set
+# CONFIG_BF561 is not set
+# CONFIG_BF_REV_0_0 is not set
+# CONFIG_BF_REV_0_1 is not set
+# CONFIG_BF_REV_0_2 is not set
+# CONFIG_BF_REV_0_3 is not set
+# CONFIG_BF_REV_0_4 is not set
+CONFIG_BF_REV_0_5=y
+# CONFIG_BF_REV_ANY is not set
+# CONFIG_BF_REV_NONE is not set
+CONFIG_BF53x=y
+CONFIG_BFIN_SINGLE_CORE=y
+CONFIG_MEM_MT48LC32M16A2TG_75=y
+# CONFIG_BFIN533_EZKIT is not set
+# CONFIG_BFIN533_STAMP is not set
+# CONFIG_BFIN533_BLUETECHNIX_CM is not set
+# CONFIG_H8606_HVSISTEMAS is not set
+CONFIG_BFIN532_IP0X=y
+# CONFIG_GENERIC_BF533_BOARD is not set
+
+#
+# BF533/2/1 Specific Configuration
+#
+
+#
+# Interrupt Priority Assignment
+#
+
+#
+# Priority
+#
+CONFIG_UART_ERROR=7
+CONFIG_SPORT0_ERROR=7
+CONFIG_SPI_ERROR=7
+CONFIG_SPORT1_ERROR=7
+CONFIG_PPI_ERROR=7
+CONFIG_DMA_ERROR=7
+CONFIG_PLLWAKE_ERROR=7
+CONFIG_RTC_ERROR=8
+CONFIG_DMA0_PPI=8
+CONFIG_DMA1_SPORT0RX=9
+CONFIG_DMA2_SPORT0TX=9
+CONFIG_DMA3_SPORT1RX=9
+CONFIG_DMA4_SPORT1TX=9
+CONFIG_DMA5_SPI=10
+CONFIG_DMA6_UARTRX=10
+CONFIG_DMA7_UARTTX=10
+CONFIG_TIMER0=11
+CONFIG_TIMER1=11
+CONFIG_TIMER2=11
+CONFIG_PFA=12
+CONFIG_PFB=12
+CONFIG_MEMDMA0=13
+CONFIG_MEMDMA1=13
+CONFIG_WDTIMER=13
+
+#
+# Board customizations
+#
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Clock/PLL Setup
+#
+CONFIG_CLKIN_HZ=10000000
+# CONFIG_BFIN_KERNEL_CLOCK is not set
+CONFIG_MAX_VCO_HZ=400000000
+CONFIG_MIN_VCO_HZ=50000000
+CONFIG_MAX_SCLK_HZ=133333333
+CONFIG_MIN_SCLK_HZ=27000000
+
+#
+# Kernel Timer/Scheduler
+#
+# 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
+
+#
+# Memory Setup
+#
+CONFIG_MEM_SIZE=64
+CONFIG_MEM_ADD_WIDTH=10
+
+#
+# Hardware addresses
+#
+CONFIG_IP0X_NET1=0x20100000
+CONFIG_IP0X_NET2=0x20200000
+CONFIG_IP0X_USB=0x20300000
+CONFIG_BOOT_LOAD=0x1000
+CONFIG_BFIN_SCRATCH_REG_RETN=y
+# CONFIG_BFIN_SCRATCH_REG_RETE is not set
+# CONFIG_BFIN_SCRATCH_REG_CYCLES is not set
+
+#
+# Blackfin Kernel Optimizations
+#
+
+#
+# Memory Optimizations
+#
+CONFIG_I_ENTRY_L1=y
+CONFIG_EXCPT_IRQ_SYSC_L1=y
+CONFIG_DO_IRQ_L1=y
+CONFIG_CORE_TIMER_IRQ_L1=y
+CONFIG_IDLE_L1=y
+CONFIG_SCHEDULE_L1=y
+CONFIG_ARITHMETIC_OPS_L1=y
+CONFIG_ACCESS_OK_L1=y
+CONFIG_MEMSET_L1=y
+CONFIG_MEMCPY_L1=y
+CONFIG_SYS_BFIN_SPINLOCK_L1=y
+# CONFIG_IP_CHECKSUM_L1 is not set
+CONFIG_CACHELINE_ALIGNED_L1=y
+# CONFIG_SYSCALL_TAB_L1 is not set
+# CONFIG_CPLB_SWITCH_TAB_L1 is not set
+CONFIG_RAMKERNEL=y
+# CONFIG_ROMKERNEL is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_LARGE_ALLOCS=y
+# CONFIG_BFIN_GPTIMERS is not set
+CONFIG_BFIN_DMA_5XX=y
+# CONFIG_DMA_UNCACHED_2M is not set
+CONFIG_DMA_UNCACHED_1M=y
+# CONFIG_DMA_UNCACHED_NONE is not set
+
+#
+# Cache Support
+#
+# CONFIG_BFIN_ICACHE is not set
+# CONFIG_BFIN_DCACHE is not set
+# CONFIG_BFIN_ICACHE_LOCK is not set
+CONFIG_L1_MAX_PIECE=16
+# CONFIG_MPU is not set
+
+#
+# Asynchonous Memory Configuration
+#
+
+#
+# EBIU_AMGCTL Global Control
+#
+CONFIG_C_AMCKEN=y
+CONFIG_C_CDPRIO=y
+# CONFIG_C_AMBEN is not set
+# CONFIG_C_AMBEN_B0 is not set
+# CONFIG_C_AMBEN_B0_B1 is not set
+# CONFIG_C_AMBEN_B0_B1_B2 is not set
+CONFIG_C_AMBEN_ALL=y
+
+#
+# EBIU_AMBCTL Control
+#
+CONFIG_BANK_0=0xffc2
+CONFIG_BANK_1=0xffc2
+CONFIG_BANK_2=0xffc2
+CONFIG_BANK_3=0xffc2
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF_FDPIC=y
+CONFIG_BINFMT_FLAT=y
+CONFIG_BINFMT_ZFLAT=y
+# CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# 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
+CONFIG_PM_BFIN_SLEEP_DEEPER=y
+# CONFIG_PM_BFIN_SLEEP is not set
+# CONFIG_PM_WAKEUP_BY_GPIO is not set
+
+#
+# Networking
+#
+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_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# 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_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# 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_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+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_IP_VS is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETLABEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NF_CONNTRACK_ENABLED is not set
+# CONFIG_NF_CONNTRACK is not set
+CONFIG_NETFILTER_XTABLES=y
+# 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_TCPMSS 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_LENGTH is not set
+# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM 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_HASHLIMIT is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_QUEUE is not set
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_IPRANGE=y
+CONFIG_IP_NF_MATCH_TOS=y
+# CONFIG_IP_NF_MATCH_RECENT is not set
+# CONFIG_IP_NF_MATCH_ECN is not set
+# CONFIG_IP_NF_MATCH_AH is not set
+# CONFIG_IP_NF_MATCH_TTL is not set
+# CONFIG_IP_NF_MATCH_OWNER is not set
+# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+# CONFIG_IP_NF_TARGET_LOG is not set
+# CONFIG_IP_NF_TARGET_ULOG is not set
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_TARGET_TOS=y
+# 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
+# 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_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
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO 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_RFKILL is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+CONFIG_MTD_RAM=y
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_UCLINUX=y
+CONFIG_MTD_PLATRAM=y
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+CONFIG_MTD_NAND_BFIN=y
+CONFIG_BFIN_NAND_BASE=0x20000000
+CONFIG_BFIN_NAND_SIZE=0x10000000
+CONFIG_BFIN_NAND_CLE=2
+CONFIG_BFIN_NAND_ALE=1
+CONFIG_BFIN_NAND_READY=10
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI 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_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# Misc devices
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
+# 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 is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# 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_SCSI_DEBUG is not set
+# CONFIG_ATA is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_SMC91X is not set
+# CONFIG_SMSC911X is not set
+CONFIG_DM9000=y
+CONFIG_NETDEV_1000=y
+# CONFIG_AX88180 is not set
+CONFIG_NETDEV_10000=y
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
+# CONFIG_USB_USBNET 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
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_AD9960 is not set
+# CONFIG_SPI_ADC_BF533 is not set
+# CONFIG_BF5xx_PFLAGS is not set
+# CONFIG_BF5xx_PPIFCD is not set
+# CONFIG_BFIN_SIMPLE_TIMER is not set
+# CONFIG_BF5xx_PPI is not set
+CONFIG_BFIN_SPORT=y
+# CONFIG_BFIN_TIMER_LATENCY is not set
+# CONFIG_AD5304 is not set
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_BFIN=y
+CONFIG_SERIAL_BFIN_CONSOLE=y
+CONFIG_SERIAL_BFIN_DMA=y
+# CONFIG_SERIAL_BFIN_PIO is not set
+CONFIG_SERIAL_BFIN_UART0=y
+# CONFIG_BFIN_UART0_CTSRTS is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_BFIN_SPORT is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# CAN, the car bus and industrial fieldbus
+#
+# CONFIG_CAN4LINUX is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_BFIN_WDT is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_GEN_RTC is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BFIN=y
+# CONFIG_SPI_BITBANG is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_AT25 is not set
+# CONFIG_SPI_SPIDEV is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+# CONFIG_HWMON is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+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_OTG_WHITELIST=y
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_ISP1362_HCD=y
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_SL811_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
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# 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
+
+#
+# USB Miscellaneous drivers
+#
+# 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_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+CONFIG_MMC=m
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD Card Drivers
+#
+CONFIG_MMC_BLOCK=m
+
+#
+# MMC/SD Host Controller Drivers
+#
+CONFIG_SPI_MMC=m
+CONFIG_SPI_MMC_FRAMEWORK_DRIVER=y
+# CONFIG_SPI_MMC_BFIN_PIO_SPI is not set
+CONFIG_SPI_MMC_CS_CHAN=5
+CONFIG_SPI_MMC_MAX_HZ=20000000
+# CONFIG_SPI_MMC_CARD_DETECT is not set
+# CONFIG_SPI_MMC_DEBUG_MODE is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_BFIN=y
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# PBX support
+#
+# CONFIG_PBX is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+# CONFIG_EXT2_FS_POSIX_ACL is not set
+# CONFIG_EXT2_FS_SECURITY is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+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
+
+#
+# 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_SYSCTL=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# 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_YAFFS_FS=y
+CONFIG_YAFFS_YAFFS1=y
+# CONFIG_YAFFS_DOES_ECC is not set
+CONFIG_YAFFS_YAFFS2=y
+CONFIG_YAFFS_AUTO_YAFFS2=y
+# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
+CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS=10
+# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
+# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
+CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
+# CONFIG_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+# CONFIG_NFS_FS is not set
+# CONFIG_NFSD 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
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+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 is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+# 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_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_MMRS is not set
+CONFIG_DEBUG_HUNT_FOR_ZERO=y
+CONFIG_DEBUG_BFIN_HWTRACE_ON=y
+CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
+# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE is not set
+# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_TWO is not set
+CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0
+# CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set
+# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
+# CONFIG_EARLY_PRINTK is not set
+CONFIG_CPLB_INFO=y
+CONFIG_ACCESS_CHECK=y
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+CONFIG_SECURITY=y
+# CONFIG_SECURITY_NETWORK is not set
+CONFIG_SECURITY_CAPABILITIES=m
+# CONFIG_SECURITY_ROOTPLUG is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO 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_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
index 25709f504d8f6f4f7874c5ccef392e90748c1b6a..87622ad9df479e545bb7b8d9c9dc834b7e122494 100644 (file)
@@ -13,7 +13,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
-# CONFIG_GENERIC_TIME is not set
+CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_GPIO=y
 CONFIG_FORCE_MAX_ZONEORDER=14
 CONFIG_GENERIC_CALIBRATE_DELAY=y
@@ -214,7 +214,7 @@ CONFIG_HZ=250
 #
 # Memory Setup
 #
-CONFIG_MEM_SIZE=64
+CONFIG_MAX_MEM_SIZE=64
 CONFIG_MEM_ADD_WIDTH=10
 CONFIG_BOOT_LOAD=0x1000
 CONFIG_BFIN_SCRATCH_REG_RETN=y
diff --git a/arch/blackfin/configs/SRV1_defconfig b/arch/blackfin/configs/SRV1_defconfig
new file mode 100644 (file)
index 0000000..951ea04
--- /dev/null
@@ -0,0 +1,1290 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.22.10
+# Fri Nov  2 20:50:23 2007
+#
+# CONFIG_MMU is not set
+# CONFIG_FPU is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_BLACKFIN=y
+CONFIG_ZONE_DMA=y
+CONFIG_BFIN=y
+CONFIG_SEMAPHORE_SLEEPERS=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+# CONFIG_GENERIC_TIME is not set
+CONFIG_GENERIC_GPIO=y
+CONFIG_FORCE_MAX_ZONEORDER=14
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_IRQCHIP_DEMUX_GPIO=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT 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_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_EVENTFD=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3
+# CONFIG_NP2 is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_RT_MUTEXES=y
+CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+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
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+
+#
+# Blackfin Processor Options
+#
+
+#
+# Processor and Board Settings
+#
+# CONFIG_BF522 is not set
+# CONFIG_BF525 is not set
+# CONFIG_BF527 is not set
+# CONFIG_BF531 is not set
+# CONFIG_BF532 is not set
+# CONFIG_BF533 is not set
+# CONFIG_BF534 is not set
+# CONFIG_BF536 is not set
+CONFIG_BF537=y
+# CONFIG_BF542 is not set
+# CONFIG_BF544 is not set
+# CONFIG_BF548 is not set
+# CONFIG_BF549 is not set
+# CONFIG_BF561 is not set
+# CONFIG_BF_REV_0_0 is not set
+# CONFIG_BF_REV_0_1 is not set
+CONFIG_BF_REV_0_2=y
+# CONFIG_BF_REV_0_3 is not set
+# CONFIG_BF_REV_0_4 is not set
+# CONFIG_BF_REV_0_5 is not set
+# CONFIG_BF_REV_ANY is not set
+# CONFIG_BF_REV_NONE is not set
+CONFIG_BF53x=y
+CONFIG_BFIN_SINGLE_CORE=y
+# CONFIG_BFIN527_EZKIT is not set
+# CONFIG_BFIN533_EZKIT is not set
+# CONFIG_BFIN533_STAMP is not set
+# CONFIG_BFIN537_STAMP is not set
+# CONFIG_CAMSIG_MINOTAUR is not set
+# CONFIG_BFIN533_BLUETECHNIX_CM is not set
+# CONFIG_BFIN537_BLUETECHNIX_CM is not set
+# CONFIG_BFIN548_EZKIT is not set
+# CONFIG_BFIN561_BLUETECHNIX_CM is not set
+# CONFIG_BFIN561_EZKIT is not set
+# CONFIG_BFIN561_TEPLA is not set
+# CONFIG_PNAV10 is not set
+# CONFIG_VISTASCAN is not set
+# CONFIG_BFIN533_SR3K is not set
+CONFIG_GENERIC_BOARD=y
+CONFIG_MEM_GENERIC_BOARD=y
+CONFIG_IRQ_PLL_WAKEUP=7
+CONFIG_IRQ_RTC=8
+CONFIG_IRQ_PPI=8
+CONFIG_IRQ_SPORT0_RX=9
+CONFIG_IRQ_SPORT0_TX=9
+CONFIG_IRQ_SPORT1_RX=9
+CONFIG_IRQ_SPORT1_TX=9
+CONFIG_IRQ_TWI=10
+CONFIG_IRQ_SPI=10
+CONFIG_IRQ_UART0_RX=10
+CONFIG_IRQ_UART0_TX=10
+CONFIG_IRQ_UART1_RX=10
+CONFIG_IRQ_UART1_TX=10
+CONFIG_IRQ_MAC_RX=11
+CONFIG_IRQ_MAC_TX=11
+CONFIG_IRQ_TMR0=12
+CONFIG_IRQ_TMR1=12
+CONFIG_IRQ_TMR2=12
+CONFIG_IRQ_TMR3=12
+CONFIG_IRQ_TMR4=12
+CONFIG_IRQ_TMR5=12
+CONFIG_IRQ_TMR6=12
+CONFIG_IRQ_TMR7=12
+CONFIG_IRQ_PORTG_INTB=12
+CONFIG_IRQ_MEM_DMA0=13
+CONFIG_IRQ_MEM_DMA1=13
+CONFIG_IRQ_WATCH=13
+
+#
+# BF537 Specific Configuration
+#
+
+#
+# Interrupt Priority Assignment
+#
+
+#
+# Priority
+#
+CONFIG_IRQ_DMA_ERROR=7
+CONFIG_IRQ_ERROR=7
+CONFIG_IRQ_CAN_RX=11
+CONFIG_IRQ_CAN_TX=11
+CONFIG_IRQ_PROG_INTA=12
+
+#
+# Board customizations
+#
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Clock/PLL Setup
+#
+CONFIG_CLKIN_HZ=22118400
+# CONFIG_BFIN_KERNEL_CLOCK is not set
+CONFIG_MAX_VCO_HZ=600000000
+CONFIG_MIN_VCO_HZ=50000000
+CONFIG_MAX_SCLK_HZ=133000000
+CONFIG_MIN_SCLK_HZ=27000000
+
+#
+# Kernel Timer/Scheduler
+#
+# 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
+
+#
+# Memory Setup
+#
+CONFIG_MAX_MEM_SIZE=32
+CONFIG_MEM_ADD_WIDTH=9
+CONFIG_BOOT_LOAD=0x400000
+CONFIG_BFIN_SCRATCH_REG_RETN=y
+# CONFIG_BFIN_SCRATCH_REG_RETE is not set
+# CONFIG_BFIN_SCRATCH_REG_CYCLES is not set
+
+#
+# Blackfin Kernel Optimizations
+#
+
+#
+# Memory Optimizations
+#
+CONFIG_I_ENTRY_L1=y
+CONFIG_EXCPT_IRQ_SYSC_L1=y
+CONFIG_DO_IRQ_L1=y
+CONFIG_CORE_TIMER_IRQ_L1=y
+CONFIG_IDLE_L1=y
+CONFIG_SCHEDULE_L1=y
+CONFIG_ARITHMETIC_OPS_L1=y
+CONFIG_ACCESS_OK_L1=y
+CONFIG_MEMSET_L1=y
+CONFIG_MEMCPY_L1=y
+CONFIG_SYS_BFIN_SPINLOCK_L1=y
+# CONFIG_IP_CHECKSUM_L1 is not set
+CONFIG_CACHELINE_ALIGNED_L1=y
+# CONFIG_SYSCALL_TAB_L1 is not set
+# CONFIG_CPLB_SWITCH_TAB_L1 is not set
+CONFIG_RAMKERNEL=y
+# CONFIG_ROMKERNEL is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_LARGE_ALLOCS=y
+CONFIG_BFIN_DMA_5XX=y
+CONFIG_DMA_UNCACHED_2M=y
+# CONFIG_DMA_UNCACHED_1M is not set
+# CONFIG_DMA_UNCACHED_NONE is not set
+
+#
+# Cache Support
+#
+CONFIG_BFIN_ICACHE=y
+CONFIG_BFIN_DCACHE=y
+# CONFIG_BFIN_DCACHE_BANKA is not set
+# CONFIG_BFIN_ICACHE_LOCK is not set
+# CONFIG_BFIN_WB is not set
+CONFIG_BFIN_WT=y
+CONFIG_L1_MAX_PIECE=16
+
+#
+# Asynchonous Memory Configuration
+#
+
+#
+# EBIU_AMGCTL Global Control
+#
+CONFIG_C_AMCKEN=y
+CONFIG_C_CDPRIO=y
+# CONFIG_C_AMBEN is not set
+# CONFIG_C_AMBEN_B0 is not set
+# CONFIG_C_AMBEN_B0_B1 is not set
+# CONFIG_C_AMBEN_B0_B1_B2 is not set
+CONFIG_C_AMBEN_ALL=y
+
+#
+# EBIU_AMBCTL Control
+#
+CONFIG_BANK_0=0x7BB0
+CONFIG_BANK_1=0x7BB0
+CONFIG_BANK_2=0x7BB0
+CONFIG_BANK_3=0x99B3
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF_FDPIC=y
+CONFIG_BINFMT_FLAT=y
+CONFIG_BINFMT_ZFLAT=y
+# CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# 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
+CONFIG_PM_WAKEUP_GPIO_BY_SIC_IWR=y
+# CONFIG_PM_WAKEUP_BY_GPIO is not set
+# CONFIG_PM_WAKEUP_GPIO_API is not set
+CONFIG_PM_WAKEUP_SIC_IWR=0x80000000
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Networking
+#
+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_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# 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_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# 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_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETLABEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE 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
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+# CONFIG_IRDA_FAST_RR is not set
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+# CONFIG_DONGLE is not set
+
+#
+# Old SIR device drivers
+#
+# CONFIG_IRPORT_SIR is not set
+
+#
+# Old Serial dongle support
+#
+
+#
+# FIR device drivers
+#
+# 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_RFKILL is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+CONFIG_MTD_JEDECPROBE=m
+CONFIG_MTD_GEN_PROBE=m
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_MW320D=m
+CONFIG_MTD_RAM=y
+CONFIG_MTD_ROM=m
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_BF5xx=m
+CONFIG_BFIN_FLASH_SIZE=0x400000
+CONFIG_EBIU_FLASH_BASE=0x20000000
+CONFIG_MTD_UCLINUX=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=m
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+CONFIG_MTD_NAND_BFIN=m
+CONFIG_BFIN_NAND_BASE=0x20212000
+CONFIG_BFIN_NAND_CLE=2
+CONFIG_BFIN_NAND_ALE=1
+CONFIG_BFIN_NAND_READY=3
+CONFIG_MTD_NAND_IDS=m
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI 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_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# Misc devices
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+# CONFIG_NET_ETHERNET is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 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
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# 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 is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV 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_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+CONFIG_INPUT_UINPUT=y
+# CONFIG_BF53X_PFBUTTONS is not set
+# CONFIG_TWI_KEYPAD is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_AD9960 is not set
+# CONFIG_SPI_ADC_BF533 is not set
+CONFIG_BF5xx_PFLAGS=y
+# CONFIG_BF5xx_PFLAGS_PROC is not set
+# CONFIG_BF5xx_PPIFCD is not set
+# CONFIG_BF5xx_TIMERS is not set
+# CONFIG_BF5xx_PPI is not set
+# CONFIG_BFIN_SPORT is not set
+# CONFIG_BFIN_TIMER_LATENCY is not set
+# CONFIG_TWI_LCD is not set
+# CONFIG_AD5304 is not set
+# CONFIG_BF5xx_TEA5764 is not set
+# CONFIG_BF5xx_FBDMA is not set
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_BFIN=y
+CONFIG_SERIAL_BFIN_CONSOLE=y
+CONFIG_SERIAL_BFIN_DMA=y
+# CONFIG_SERIAL_BFIN_PIO is not set
+CONFIG_SERIAL_BFIN_UART0=y
+# CONFIG_BFIN_UART0_CTSRTS is not set
+# CONFIG_SERIAL_BFIN_UART1 is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_BFIN_SPORT is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# CAN, the car bus and industrial fieldbus
+#
+# CONFIG_CAN4LINUX is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_BFIN_WDT=y
+CONFIG_HW_RANDOM=m
+# CONFIG_GEN_RTC is not set
+CONFIG_BLACKFIN_DPMC=y
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_BLACKFIN_GPIO is not set
+CONFIG_I2C_BLACKFIN_TWI=y
+CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=50
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_SIMTEC 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_SENSORS_AD5252 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8575 is not set
+# CONFIG_SENSORS_PCA9543 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 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=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BFIN=y
+# CONFIG_SPI_BITBANG is not set
+
+#
+# SPI Protocol Masters
+#
+CONFIG_SPI_AT25=m
+# CONFIG_SPI_SPIDEV is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+CONFIG_HWMON=m
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=y
+# CONFIG_VIDEO_V4L1 is not set
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2=y
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set
+
+#
+# Encoders/decoders and other helper chips
+#
+
+#
+# Audio decoders
+#
+# CONFIG_VIDEO_TDA9840 is not set
+# CONFIG_VIDEO_TEA6415C is not set
+# CONFIG_VIDEO_TEA6420 is not set
+# CONFIG_VIDEO_MSP3400 is not set
+# CONFIG_VIDEO_CS53L32A is not set
+# CONFIG_VIDEO_TLV320AIC23B is not set
+# CONFIG_VIDEO_WM8775 is not set
+# CONFIG_VIDEO_WM8739 is not set
+
+#
+# Video decoders
+#
+# CONFIG_VIDEO_OV7670 is not set
+# CONFIG_VIDEO_SAA711X is not set
+# CONFIG_VIDEO_TVP5150 is not set
+
+#
+# Video and audio decoders
+#
+# CONFIG_VIDEO_CX25840 is not set
+
+#
+# MPEG video encoders
+#
+# CONFIG_VIDEO_CX2341X is not set
+
+#
+# Video encoders
+#
+# CONFIG_VIDEO_SAA7127 is not set
+
+#
+# Video improvement chips
+#
+# CONFIG_VIDEO_UPD64031A is not set
+# CONFIG_VIDEO_UPD64083 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_VIDEO_PPI_GENERIC is not set
+CONFIG_VIDEO_BLACKFIN_CAM=m
+# CONFIG_VIDEO_BLACKFIN_MT9M001 is not set
+
+#
+# CMOS Camera Sensor Selection
+#
+# CONFIG_MT9V022 is not set
+# CONFIG_MT9M001 is not set
+# CONFIG_VS6524 is not set
+# CONFIG_VS6624 is not set
+CONFIG_OV9655=y
+# CONFIG_RADIO_ADAPTERS is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# HID Devices
+#
+# CONFIG_HID is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+# CONFIG_USB is not set
+
+#
+# Enable Host or Gadget support to see Inventra options
+#
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# PBX support
+#
+# CONFIG_PBX is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+# CONFIG_EXT2_FS_POSIX_ACL is not set
+# CONFIG_EXT2_FS_SECURITY is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+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
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# 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_YAFFS_FS=m
+CONFIG_YAFFS_YAFFS1=y
+# CONFIG_YAFFS_DOES_ECC is not set
+CONFIG_YAFFS_YAFFS2=y
+CONFIG_YAFFS_AUTO_YAFFS2=y
+# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
+CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS=10
+# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
+# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
+CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+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_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT 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
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# 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 is not set
+# 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 is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+# 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_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS 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 is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_FRAME_POINTER is not set
+# CONFIG_FORCED_INLINING is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_DEBUG_MMRS is not set
+# CONFIG_DEBUG_HWERR is not set
+CONFIG_DEBUG_HUNT_FOR_ZERO=y
+CONFIG_DEBUG_BFIN_HWTRACE_ON=y
+CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
+# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE is not set
+# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_TWO is not set
+CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0
+# CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set
+# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
+# CONFIG_EARLY_PRINTK is not set
+CONFIG_CPLB_INFO=y
+CONFIG_ACCESS_CHECK=y
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+CONFIG_SECURITY=y
+# CONFIG_SECURITY_NETWORK is not set
+CONFIG_SECURITY_CAPABILITIES=y
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
index 318b9b692a48a94aa1fd2044c9c25b978b91f4c0..6140cd69c782455e225b66eec7d4494366ebd819 100644 (file)
@@ -6,9 +6,15 @@ extra-y := init_task.o vmlinux.lds
 
 obj-y := \
        entry.o process.o bfin_ksyms.o ptrace.o setup.o signal.o \
-       sys_bfin.o time.o traps.o irqchip.o dma-mapping.o flat.o \
+       sys_bfin.o traps.o irqchip.o dma-mapping.o flat.o \
        fixed_code.o reboot.o bfin_gpio.o
 
+ifeq ($(CONFIG_GENERIC_CLOCKEVENTS),y)
+    obj-y += time-ts.o
+else
+    obj-y += time.o
+endif
+
 obj-$(CONFIG_BFIN_GPTIMERS)          += gptimers.o
 obj-$(CONFIG_MODULES)                += module.o
 obj-$(CONFIG_BFIN_DMA_5XX)           += bfin_dma_5xx.o
index 8fd5d22cec34d124dfedb031bcad84a4149a4b33..fd5448d6107cdf7564b53b6470731dccbd2e7ba9 100644 (file)
@@ -67,7 +67,7 @@ static int __init blackfin_dma_init(void)
 
        for (i = 0; i < MAX_BLACKFIN_DMA_CHANNEL; i++) {
                dma_ch[i].chan_status = DMA_CHANNEL_FREE;
-               dma_ch[i].regs = base_addr[i];
+               dma_ch[i].regs = dma_io_base_addr[i];
                mutex_init(&(dma_ch[i].dmalock));
        }
        /* Mark MEMDMA Channel 0 as requested since we're using it internally */
@@ -106,12 +106,15 @@ int request_dma(unsigned int channel, char *device_id)
 
 #ifdef CONFIG_BF54x
        if (channel >= CH_UART2_RX && channel <= CH_UART3_TX) {
-               if (strncmp(device_id, "BFIN_UART", 9) == 0)
+               if (strncmp(device_id, "BFIN_UART", 9) == 0) {
+                       dma_ch[channel].regs->peripheral_map &= 0x0FFF;
                        dma_ch[channel].regs->peripheral_map |=
-                               (channel - CH_UART2_RX + 0xC);
-               else
+                               ((channel - CH_UART2_RX + 0xC)<<12);
+               } else {
+                       dma_ch[channel].regs->peripheral_map &= 0x0FFF;
                        dma_ch[channel].regs->peripheral_map |=
-                               (channel - CH_UART2_RX + 0x6);
+                               ((channel - CH_UART2_RX + 0x6)<<12);
+               }
        }
 #endif
 
index 08788f7bbfbab2a39ed27b710c43ba43f074cabf..7e8eaf4a31bbc64ffbe17602c5b8ec1bbd8e8c45 100644 (file)
@@ -95,14 +95,14 @@ enum {
        AWA_data_clear = SYSCR,
        AWA_data_set = SYSCR,
        AWA_toggle = SYSCR,
-       AWA_maska = UART_SCR,
-       AWA_maska_clear = UART_SCR,
-       AWA_maska_set = UART_SCR,
-       AWA_maska_toggle = UART_SCR,
-       AWA_maskb = UART_GCTL,
-       AWA_maskb_clear = UART_GCTL,
-       AWA_maskb_set = UART_GCTL,
-       AWA_maskb_toggle = UART_GCTL,
+       AWA_maska = BFIN_UART_SCR,
+       AWA_maska_clear = BFIN_UART_SCR,
+       AWA_maska_set = BFIN_UART_SCR,
+       AWA_maska_toggle = BFIN_UART_SCR,
+       AWA_maskb = BFIN_UART_GCTL,
+       AWA_maskb_clear = BFIN_UART_GCTL,
+       AWA_maskb_set = BFIN_UART_GCTL,
+       AWA_maskb_toggle = BFIN_UART_GCTL,
        AWA_dir = SPORT1_STAT,
        AWA_polar = SPORT1_STAT,
        AWA_edge = SPORT1_STAT,
@@ -348,11 +348,10 @@ static void portmux_setup(unsigned short per, unsigned short function)
                        offset = port_mux_lut[y].offset;
                        muxreg = bfin_read_PORT_MUX();
 
-                       if (offset != 1) {
+                       if (offset != 1)
                                muxreg &= ~(1 << offset);
-                       } else {
+                       else
                                muxreg &= ~(3 << 1);
-                       }
 
                        muxreg |= (function << offset);
                        bfin_write_PORT_MUX(muxreg);
@@ -396,39 +395,11 @@ inline void portmux_setup(unsigned short portno, unsigned short function)
 # define portmux_setup(...)  do { } while (0)
 #endif
 
-#ifndef BF548_FAMILY
-static void default_gpio(unsigned gpio)
-{
-       unsigned short bank, bitmask;
-       unsigned long flags;
-
-       bank = gpio_bank(gpio);
-       bitmask = gpio_bit(gpio);
-
-       local_irq_save(flags);
-
-       gpio_bankb[bank]->maska_clear = bitmask;
-       gpio_bankb[bank]->maskb_clear = bitmask;
-       SSYNC();
-       gpio_bankb[bank]->inen &= ~bitmask;
-       gpio_bankb[bank]->dir &= ~bitmask;
-       gpio_bankb[bank]->polar &= ~bitmask;
-       gpio_bankb[bank]->both &= ~bitmask;
-       gpio_bankb[bank]->edge &= ~bitmask;
-       AWA_DUMMY_READ(edge);
-       local_irq_restore(flags);
-}
-#else
-# define default_gpio(...)  do { } while (0)
-#endif
-
 static int __init bfin_gpio_init(void)
 {
-
        printk(KERN_INFO "Blackfin GPIO Controller\n");
 
        return 0;
-
 }
 arch_initcall(bfin_gpio_init);
 
@@ -821,10 +792,10 @@ int peripheral_request(unsigned short per, const char *label)
        local_irq_save(flags);
 
        if (unlikely(reserved_gpio_map[gpio_bank(ident)] & gpio_bit(ident))) {
+               dump_stack();
                printk(KERN_ERR
                    "%s: Peripheral %d is already reserved as GPIO by %s !\n",
-                      __FUNCTION__, ident, get_label(ident));
-               dump_stack();
+                      __func__, ident, get_label(ident));
                local_irq_restore(flags);
                return -EBUSY;
        }
@@ -833,31 +804,31 @@ int peripheral_request(unsigned short per, const char *label)
 
                u16 funct = get_portmux(ident);
 
-       /*
-        * Pin functions like AMC address strobes my
-        * be requested and used by several drivers
-        */
+               /*
+                * Pin functions like AMC address strobes my
+                * be requested and used by several drivers
+                */
 
                if (!((per & P_MAYSHARE) && (funct == P_FUNCT2MUX(per)))) {
 
-               /*
-                * Allow that the identical pin function can
-                * be requested from the same driver twice
-                */
+                       /*
+                        * Allow that the identical pin function can
+                        * be requested from the same driver twice
+                        */
 
-               if (cmp_label(ident, label) == 0)
-                       goto anyway;
+                       if (cmp_label(ident, label) == 0)
+                               goto anyway;
 
+                       dump_stack();
                        printk(KERN_ERR
                               "%s: Peripheral %d function %d is already reserved by %s !\n",
-                              __FUNCTION__, ident, P_FUNCT2MUX(per), get_label(ident));
-                       dump_stack();
+                              __func__, ident, P_FUNCT2MUX(per), get_label(ident));
                        local_irq_restore(flags);
                        return -EBUSY;
                }
        }
 
-anyway:
+ anyway:
        reserved_peri_map[gpio_bank(ident)] |= gpio_bit(ident);
 
        portmux_setup(ident, P_FUNCT2MUX(per));
@@ -890,47 +861,47 @@ int peripheral_request(unsigned short per, const char *label)
 
        if (!check_gpio(ident)) {
 
-       if (unlikely(reserved_gpio_map[gpio_bank(ident)] & gpio_bit(ident))) {
-               printk(KERN_ERR
-                      "%s: Peripheral %d is already reserved as GPIO by %s !\n",
-                      __FUNCTION__, ident, get_label(ident));
-               dump_stack();
-               local_irq_restore(flags);
-               return -EBUSY;
-       }
+               if (unlikely(reserved_gpio_map[gpio_bank(ident)] & gpio_bit(ident))) {
+                       dump_stack();
+                       printk(KERN_ERR
+                              "%s: Peripheral %d is already reserved as GPIO by %s !\n",
+                              __func__, ident, get_label(ident));
+                       local_irq_restore(flags);
+                       return -EBUSY;
+               }
 
        }
 
        if (unlikely(reserved_peri_map[gpio_bank(ident)] & gpio_bit(ident))) {
 
-       /*
-        * Pin functions like AMC address strobes my
-        * be requested and used by several drivers
-        */
+               /*
+                * Pin functions like AMC address strobes my
+                * be requested and used by several drivers
+                */
 
-       if (!(per & P_MAYSHARE)) {
+               if (!(per & P_MAYSHARE)) {
 
-       /*
-        * Allow that the identical pin function can
-        * be requested from the same driver twice
-        */
+                       /*
+                        * Allow that the identical pin function can
+                        * be requested from the same driver twice
+                        */
 
-               if (cmp_label(ident, label) == 0)
-                       goto anyway;
+                       if (cmp_label(ident, label) == 0)
+                               goto anyway;
 
+                       dump_stack();
                        printk(KERN_ERR
                               "%s: Peripheral %d function %d is already"
                               " reserved by %s !\n",
-                              __FUNCTION__, ident, P_FUNCT2MUX(per),
+                              __func__, ident, P_FUNCT2MUX(per),
                                get_label(ident));
-                       dump_stack();
                        local_irq_restore(flags);
                        return -EBUSY;
                }
 
        }
 
-anyway:
+ anyway:
        portmux_setup(per, P_FUNCT2MUX(per));
 
        port_setup(ident, PERIPHERAL_USAGE);
@@ -944,7 +915,7 @@ anyway:
 EXPORT_SYMBOL(peripheral_request);
 #endif
 
-int peripheral_request_list(unsigned short per[], const char *label)
+int peripheral_request_list(const unsigned short per[], const char *label)
 {
        u16 cnt;
        int ret;
@@ -954,10 +925,10 @@ int peripheral_request_list(unsigned short per[], const char *label)
                ret = peripheral_request(per[cnt], label);
 
                if (ret < 0) {
-                       for ( ; cnt > 0; cnt--) {
+                       for ( ; cnt > 0; cnt--)
                                peripheral_free(per[cnt - 1]);
-                       }
-               return ret;
+
+                       return ret;
                }
        }
 
@@ -981,15 +952,13 @@ void peripheral_free(unsigned short per)
 
        local_irq_save(flags);
 
-       if (unlikely(!(reserved_peri_map[gpio_bank(ident)]
-                        & gpio_bit(ident)))) {
+       if (unlikely(!(reserved_peri_map[gpio_bank(ident)] & gpio_bit(ident)))) {
                local_irq_restore(flags);
                return;
        }
 
-       if (!(per & P_MAYSHARE)) {
+       if (!(per & P_MAYSHARE))
                port_setup(ident, GPIO_USAGE);
-       }
 
        reserved_peri_map[gpio_bank(ident)] &= ~gpio_bit(ident);
 
@@ -999,14 +968,11 @@ void peripheral_free(unsigned short per)
 }
 EXPORT_SYMBOL(peripheral_free);
 
-void peripheral_free_list(unsigned short per[])
+void peripheral_free_list(const unsigned short per[])
 {
        u16 cnt;
-
-       for (cnt = 0; per[cnt] != 0; cnt++) {
+       for (cnt = 0; per[cnt] != 0; cnt++)
                peripheral_free(per[cnt]);
-       }
-
 }
 EXPORT_SYMBOL(peripheral_free_list);
 
@@ -1046,17 +1012,17 @@ int gpio_request(unsigned gpio, const char *label)
        }
 
        if (unlikely(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
+               dump_stack();
                printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved by %s !\n",
                         gpio, get_label(gpio));
-               dump_stack();
                local_irq_restore(flags);
                return -EBUSY;
        }
        if (unlikely(reserved_peri_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
+               dump_stack();
                printk(KERN_ERR
                       "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",
                       gpio, get_label(gpio));
-               dump_stack();
                local_irq_restore(flags);
                return -EBUSY;
        }
@@ -1082,14 +1048,12 @@ void gpio_free(unsigned gpio)
        local_irq_save(flags);
 
        if (unlikely(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)))) {
-               gpio_error(gpio);
                dump_stack();
+               gpio_error(gpio);
                local_irq_restore(flags);
                return;
        }
 
-       default_gpio(gpio);
-
        reserved_gpio_map[gpio_bank(gpio)] &= ~gpio_bit(gpio);
 
        set_label(gpio, "free");
@@ -1152,6 +1116,18 @@ int gpio_get_value(unsigned gpio)
 }
 EXPORT_SYMBOL(gpio_get_value);
 
+void bfin_gpio_irq_prepare(unsigned gpio)
+{
+       unsigned long flags;
+
+       port_setup(gpio, GPIO_USAGE);
+
+       local_irq_save(flags);
+       gpio_array[gpio_bank(gpio)]->port_dir_clear = gpio_bit(gpio);
+       gpio_array[gpio_bank(gpio)]->port_inen |= gpio_bit(gpio);
+       local_irq_restore(flags);
+}
+
 #else
 
 int gpio_direction_input(unsigned gpio)
@@ -1218,6 +1194,11 @@ void bfin_gpio_reset_spi0_ssel1(void)
        udelay(1);
 }
 
+void bfin_gpio_irq_prepare(unsigned gpio)
+{
+       port_setup(gpio, GPIO_USAGE);
+}
+
 #endif /*BF548_FAMILY */
 
 #if defined(CONFIG_PROC_FS)
index bd072299f7f24519144f052577682fae283bcad3..822beefa3a4b2bdc44b049f71890423d56472eda 100644 (file)
 #include <asm/cplbinit.h>
 #include <asm/blackfin.h>
 
-#define CPLB_I 1
-#define CPLB_D 2
-
-#define SYNC_SYS    SSYNC()
-#define SYNC_CORE   CSYNC()
-
-#define CPLB_BIT_PAGESIZE 0x30000
-
 static char page_size_string_table[][4] = { "1K", "4K", "1M", "4M" };
 
 static char *cplb_print_entry(char *buf, struct cplb_entry *tbl, int switched)
index dc6e8a7a8bda30ef21c08e5d50b73f5bbab13c54..48060105346adab6481be7119b534a717f475fe2 100644 (file)
@@ -43,13 +43,15 @@ void __init generate_cpl_tables(void)
        unsigned long d_data, i_data;
        unsigned long d_cache = 0, i_cache = 0;
 
+       printk(KERN_INFO "MPU: setting up cplb tables with memory protection\n");
+
 #ifdef CONFIG_BFIN_ICACHE
        i_cache = CPLB_L1_CHBL | ANOMALY_05000158_WORKAROUND;
 #endif
 
 #ifdef CONFIG_BFIN_DCACHE
        d_cache = CPLB_L1_CHBL;
-#ifdef CONFIG_BLKFIN_WT
+#ifdef CONFIG_BFIN_WT
        d_cache |= CPLB_L1_AOW | CPLB_WT;
 #endif
 #endif
index c426a22f99073e0669e26d280a4b5f93ecf385d1..99f2831e2964949a052fc3d5f1e788b69a9c6f8f 100644 (file)
@@ -24,8 +24,6 @@
 #include <asm/cplbinit.h>
 #include <asm/mmu_context.h>
 
-#ifdef CONFIG_BFIN_ICACHE
-
 #define FAULT_RW       (1 << 16)
 #define FAULT_USERSUPV (1 << 17)
 
@@ -143,30 +141,48 @@ static noinline int dcplb_miss(void)
        unsigned long d_data;
 
        nr_dcplb_miss++;
-       if (addr >= _ramend)
-               return CPLB_PROT_VIOL;
 
        d_data = CPLB_SUPV_WR | CPLB_VALID | CPLB_DIRTY | PAGE_SIZE_4KB;
 #ifdef CONFIG_BFIN_DCACHE
-       d_data |= CPLB_L1_CHBL | ANOMALY_05000158_WORKAROUND;
-#ifdef CONFIG_BLKFIN_WT
-       d_data |= CPLB_L1_AOW | CPLB_WT;
-#endif
+       if (addr < _ramend - DMA_UNCACHED_REGION ||
+           (reserved_mem_dcache_on && addr >= _ramend &&
+            addr < physical_mem_end)) {
+               d_data |= CPLB_L1_CHBL | ANOMALY_05000158_WORKAROUND;
+#ifdef CONFIG_BFIN_WT
+               d_data |= CPLB_L1_AOW | CPLB_WT;
 #endif
-       mask = current_rwx_mask;
-       if (mask) {
-               int page = addr >> PAGE_SHIFT;
-               int offs = page >> 5;
-               int bit = 1 << (page & 31);
-
-               if (mask[offs] & bit)
-                       d_data |= CPLB_USER_RD;
-
-               mask += page_mask_nelts;
-               if (mask[offs] & bit)
-                       d_data |= CPLB_USER_WR;
        }
+#endif
+       if (addr >= physical_mem_end) {
+               if (addr >= ASYNC_BANK0_BASE && addr < ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE
+                   && (status & FAULT_USERSUPV)) {
+                       addr &= ~0x3fffff;
+                       d_data &= ~PAGE_SIZE_4KB;
+                       d_data |= PAGE_SIZE_4MB;
+               } else if (addr >= BOOT_ROM_START && addr < BOOT_ROM_START + BOOT_ROM_LENGTH
+                   && (status & (FAULT_RW | FAULT_USERSUPV)) == FAULT_USERSUPV) {
+                       addr &= ~(1 * 1024 * 1024 - 1);
+                       d_data &= ~PAGE_SIZE_4KB;
+                       d_data |= PAGE_SIZE_1MB;
+               } else
+                       return CPLB_PROT_VIOL;
+       } else if (addr >= _ramend) {
+           d_data |= CPLB_USER_RD | CPLB_USER_WR;
+       } else {
+               mask = current_rwx_mask;
+               if (mask) {
+                       int page = addr >> PAGE_SHIFT;
+                       int offs = page >> 5;
+                       int bit = 1 << (page & 31);
+
+                       if (mask[offs] & bit)
+                               d_data |= CPLB_USER_RD;
 
+                       mask += page_mask_nelts;
+                       if (mask[offs] & bit)
+                               d_data |= CPLB_USER_WR;
+               }
+       }
        idx = evict_one_dcplb();
 
        addr &= PAGE_MASK;
@@ -189,12 +205,14 @@ static noinline int icplb_miss(void)
        unsigned long i_data;
 
        nr_icplb_miss++;
-       if (status & FAULT_USERSUPV)
-               nr_icplb_supv_miss++;
 
-       if (addr >= _ramend)
+       /* If inside the uncached DMA region, fault.  */
+       if (addr >= _ramend - DMA_UNCACHED_REGION && addr < _ramend)
                return CPLB_PROT_VIOL;
 
+       if (status & FAULT_USERSUPV)
+               nr_icplb_supv_miss++;
+
        /*
         * First, try to find a CPLB that matches this address.  If we
         * find one, then the fact that we're in the miss handler means
@@ -211,30 +229,48 @@ static noinline int icplb_miss(void)
        }
 
        i_data = CPLB_VALID | CPLB_PORTPRIO | PAGE_SIZE_4KB;
-#ifdef CONFIG_BFIN_ICACHE
-       i_data |= CPLB_L1_CHBL | ANOMALY_05000158_WORKAROUND;
-#endif
 
+#ifdef CONFIG_BFIN_ICACHE
        /*
-        * Two cases to distinguish - a supervisor access must necessarily
-        * be for a module page; we grant it unconditionally (could do better
-        * here in the future).  Otherwise, check the x bitmap of the current
-        * process.
+        * Normal RAM, and possibly the reserved memory area, are
+        * cacheable.
         */
-       if (!(status & FAULT_USERSUPV)) {
-               unsigned long *mask = current_rwx_mask;
-
-               if (mask) {
-                       int page = addr >> PAGE_SHIFT;
-                       int offs = page >> 5;
-                       int bit = 1 << (page & 31);
+       if (addr < _ramend ||
+           (addr < physical_mem_end && reserved_mem_icache_on))
+               i_data |= CPLB_L1_CHBL | ANOMALY_05000158_WORKAROUND;
+#endif
 
-                       mask += 2 * page_mask_nelts;
-                       if (mask[offs] & bit)
-                               i_data |= CPLB_USER_RD;
+       if (addr >= physical_mem_end) {
+               if (addr >= BOOT_ROM_START && addr < BOOT_ROM_START + BOOT_ROM_LENGTH
+                   && (status & FAULT_USERSUPV)) {
+                       addr &= ~(1 * 1024 * 1024 - 1);
+                       i_data &= ~PAGE_SIZE_4KB;
+                       i_data |= PAGE_SIZE_1MB;
+               } else
+                   return CPLB_PROT_VIOL;
+       } else if (addr >= _ramend) {
+               i_data |= CPLB_USER_RD;
+       } else {
+               /*
+                * Two cases to distinguish - a supervisor access must
+                * necessarily be for a module page; we grant it
+                * unconditionally (could do better here in the future).
+                * Otherwise, check the x bitmap of the current process.
+                */
+               if (!(status & FAULT_USERSUPV)) {
+                       unsigned long *mask = current_rwx_mask;
+
+                       if (mask) {
+                               int page = addr >> PAGE_SHIFT;
+                               int offs = page >> 5;
+                               int bit = 1 << (page & 31);
+
+                               mask += 2 * page_mask_nelts;
+                               if (mask[offs] & bit)
+                                       i_data |= CPLB_USER_RD;
+                       }
                }
        }
-
        idx = evict_one_icplb();
        addr &= PAGE_MASK;
        icplb_tbl[idx].addr = addr;
@@ -250,7 +286,6 @@ static noinline int icplb_miss(void)
 
 static noinline int dcplb_protection_fault(void)
 {
-       unsigned long addr = bfin_read_DCPLB_FAULT_ADDR();
        int status = bfin_read_DCPLB_STATUS();
 
        nr_dcplb_prot++;
@@ -280,8 +315,7 @@ int cplb_hdr(int seqstat, struct pt_regs *regs)
        case 0x26:
                return dcplb_miss();
        default:
-           return 1;
-               panic_cplb_error(seqstat, regs);
+               return 1;
        }
 }
 
@@ -299,7 +333,7 @@ void flush_switched_cplbs(void)
        enable_icplb();
 
        disable_dcplb();
-       for (i = first_mask_dcplb; i < MAX_CPLBS; i++) {
+       for (i = first_switched_dcplb; i < MAX_CPLBS; i++) {
                dcplb_tbl[i].data = 0;
                bfin_write32(DCPLB_DATA0 + i * 4, 0);
        }
@@ -319,7 +353,7 @@ void set_mask_dcplbs(unsigned long *masks)
        d_data = CPLB_SUPV_WR | CPLB_VALID | CPLB_DIRTY | PAGE_SIZE_4KB;
 #ifdef CONFIG_BFIN_DCACHE
        d_data |= CPLB_L1_CHBL;
-#ifdef CONFIG_BLKFIN_WT
+#ifdef CONFIG_BFIN_WT
        d_data |= CPLB_L1_AOW | CPLB_WT;
 #endif
 #endif
@@ -334,5 +368,3 @@ void set_mask_dcplbs(unsigned long *masks)
        }
        enable_dcplb();
 }
-
-#endif
index a4f0b428a34da88f1bcd0543973f46f3bf5dbb34..1e74f0b97996075f3823466cc369b6a063ba6baa 100644 (file)
@@ -33,9 +33,7 @@
 #include <linux/proc_fs.h>
 #include <linux/uaccess.h>
 
-#include <asm/current.h>
-#include <asm/system.h>
-#include <asm/cplb.h>
+#include <asm/cplbinit.h>
 #include <asm/blackfin.h>
 
 #define CPLB_I 1
@@ -174,16 +172,6 @@ static int cplbinfo_read_proc(char *page, char **start, off_t off,
        return len;
 }
 
-static int cplbinfo_write_proc(struct file *file, const char __user *buffer,
-                              unsigned long count, void *data)
-{
-       printk(KERN_INFO "Reset the CPLB swap in/out counts.\n");
-       memset(ipdt_swapcount_table, 0, MAX_SWITCH_I_CPLBS * sizeof(unsigned long));
-       memset(dpdt_swapcount_table, 0, MAX_SWITCH_D_CPLBS * sizeof(unsigned long));
-
-       return count;
-}
-
 static int __init cplbinfo_init(void)
 {
        struct proc_dir_entry *entry;
@@ -193,7 +181,6 @@ static int __init cplbinfo_init(void)
                return -ENOMEM;
 
        entry->read_proc = cplbinfo_read_proc;
-       entry->write_proc = cplbinfo_write_proc;
        entry->data = NULL;
 
        return 0;
index 6320bc45fbba6b6d55c1e803bde124732646700a..917325bfbd849723899d6bfaa26e21c39d566ed8 100644 (file)
 #include <asm/cplb.h>
 #include <asm/cplbinit.h>
 
+#ifdef CONFIG_MAX_MEM_SIZE
+# define CPLB_MEM CONFIG_MAX_MEM_SIZE
+#else
+# define CPLB_MEM CONFIG_MEM_SIZE
+#endif
+
+/*
+* Number of required data CPLB switchtable entries
+* MEMSIZE / 4 (we mostly install 4M page size CPLBs
+* approx 16 for smaller 1MB page size CPLBs for allignment purposes
+* 1 for L1 Data Memory
+* possibly 1 for L2 Data Memory
+* 1 for CONFIG_DEBUG_HUNT_FOR_ZERO
+* 1 for ASYNC Memory
+*/
+#define MAX_SWITCH_D_CPLBS (((CPLB_MEM / 4) + 16 + 1 + 1 + 1 \
+                                + ASYNC_MEMORY_CPLB_COVERAGE) * 2)
+
+/*
+* Number of required instruction CPLB switchtable entries
+* MEMSIZE / 4 (we mostly install 4M page size CPLBs
+* approx 12 for smaller 1MB page size CPLBs for allignment purposes
+* 1 for L1 Instruction Memory
+* possibly 1 for L2 Instruction Memory
+* 1 for CONFIG_DEBUG_HUNT_FOR_ZERO
+*/
+#define MAX_SWITCH_I_CPLBS (((CPLB_MEM / 4) + 12 + 1 + 1 + 1) * 2)
+
+
 u_long icplb_table[MAX_CPLBS + 1];
 u_long dcplb_table[MAX_CPLBS + 1];
 
@@ -295,6 +324,8 @@ void __init generate_cpl_tables(void)
        struct cplb_tab *t_d = NULL;
        struct s_cplb cplb;
 
+       printk(KERN_INFO "NOMPU: setting up cplb tables for global access\n");
+
        cplb.init_i.size = MAX_CPLBS;
        cplb.init_d.size = MAX_CPLBS;
        cplb.switch_i.size = MAX_SWITCH_I_CPLBS;
index d6b61d56b656798db1b2fa2bee1d9df7c04872ac..2f62a9f4058acbf9eea9bc75142f8990967d0c0e 100644 (file)
@@ -59,7 +59,7 @@ void dma_alloc_init(unsigned long start, unsigned long end)
        memset((void *)dma_base, 0, DMA_UNCACHED_REGION);
        dma_initialized = 1;
 
-       printk(KERN_INFO "%s: dma_page @ 0x%p - %d pages at 0x%08lx\n", __FUNCTION__,
+       printk(KERN_INFO "%s: dma_page @ 0x%p - %d pages at 0x%08lx\n", __func__,
               dma_page, dma_pages, dma_base);
 }
 
@@ -100,7 +100,7 @@ static void __free_dma_pages(unsigned long addr, unsigned int pages)
        int i;
 
        if ((page + pages) > dma_pages) {
-               printk(KERN_ERR "%s: freeing outside range.\n", __FUNCTION__);
+               printk(KERN_ERR "%s: freeing outside range.\n", __func__);
                BUG();
        }
 
index 1904d8b53328fad9440b33a4cfdb391e7d2f0473..e698554895a7b54a236eecaad8ebbcfc28703e73 100644 (file)
@@ -52,12 +52,14 @@ static volatile GPTIMER_timer_regs *const timer_regs[MAX_BLACKFIN_GPTIMERS] =
        (GPTIMER_timer_regs *)TIMER5_CONFIG,
        (GPTIMER_timer_regs *)TIMER6_CONFIG,
        (GPTIMER_timer_regs *)TIMER7_CONFIG,
-#endif
-#if (MAX_BLACKFIN_GPTIMERS > 8)
+# if (MAX_BLACKFIN_GPTIMERS > 8)
        (GPTIMER_timer_regs *)TIMER8_CONFIG,
        (GPTIMER_timer_regs *)TIMER9_CONFIG,
        (GPTIMER_timer_regs *)TIMER10_CONFIG,
+#  if (MAX_BLACKFIN_GPTIMERS > 11)
        (GPTIMER_timer_regs *)TIMER11_CONFIG,
+#  endif
+# endif
 #endif
 };
 
@@ -80,12 +82,14 @@ static uint32_t const trun_mask[MAX_BLACKFIN_GPTIMERS] =
        TIMER_STATUS_TRUN5,
        TIMER_STATUS_TRUN6,
        TIMER_STATUS_TRUN7,
-#endif
-#if (MAX_BLACKFIN_GPTIMERS > 8)
+# if (MAX_BLACKFIN_GPTIMERS > 8)
        TIMER_STATUS_TRUN8,
        TIMER_STATUS_TRUN9,
        TIMER_STATUS_TRUN10,
+#  if (MAX_BLACKFIN_GPTIMERS > 11)
        TIMER_STATUS_TRUN11,
+#  endif
+# endif
 #endif
 };
 
@@ -100,12 +104,14 @@ static uint32_t const tovf_mask[MAX_BLACKFIN_GPTIMERS] =
        TIMER_STATUS_TOVF5,
        TIMER_STATUS_TOVF6,
        TIMER_STATUS_TOVF7,
-#endif
-#if (MAX_BLACKFIN_GPTIMERS > 8)
+# if (MAX_BLACKFIN_GPTIMERS > 8)
        TIMER_STATUS_TOVF8,
        TIMER_STATUS_TOVF9,
        TIMER_STATUS_TOVF10,
+#  if (MAX_BLACKFIN_GPTIMERS > 11)
        TIMER_STATUS_TOVF11,
+#  endif
+# endif
 #endif
 };
 
@@ -120,12 +126,14 @@ static uint32_t const timil_mask[MAX_BLACKFIN_GPTIMERS] =
        TIMER_STATUS_TIMIL5,
        TIMER_STATUS_TIMIL6,
        TIMER_STATUS_TIMIL7,
-#endif
-#if (MAX_BLACKFIN_GPTIMERS > 8)
+# if (MAX_BLACKFIN_GPTIMERS > 8)
        TIMER_STATUS_TIMIL8,
        TIMER_STATUS_TIMIL9,
        TIMER_STATUS_TIMIL10,
+#  if (MAX_BLACKFIN_GPTIMERS > 11)
        TIMER_STATUS_TIMIL11,
+#  endif
+# endif
 #endif
 };
 
index 6b8459c661631b1ce9364bb50a6da36c3103766a..be9fdd00d7cb2c55ef0dcd1d83a9c0bb9beb6c85 100644 (file)
@@ -32,6 +32,8 @@
 #include <linux/unistd.h>
 #include <linux/user.h>
 #include <linux/uaccess.h>
+#include <linux/sched.h>
+#include <linux/tick.h>
 #include <linux/fs.h>
 #include <linux/err.h>
 
@@ -69,33 +71,44 @@ EXPORT_SYMBOL(pm_power_off);
  * The idle loop on BFIN
  */
 #ifdef CONFIG_IDLE_L1
-void default_idle(void)__attribute__((l1_text));
+static void default_idle(void)__attribute__((l1_text));
 void cpu_idle(void)__attribute__((l1_text));
 #endif
 
-void default_idle(void)
+/*
+ * This is our default idle handler.  We need to disable
+ * interrupts here to ensure we don't miss a wakeup call.
+ */
+static void default_idle(void)
 {
-       while (!need_resched()) {
-               local_irq_disable();
-               if (likely(!need_resched()))
-                       idle_with_irq_disabled();
-               local_irq_enable();
-       }
-}
+       local_irq_disable();
+       if (!need_resched())
+               idle_with_irq_disabled();
 
-void (*idle)(void) = default_idle;
+       local_irq_enable();
+}
 
 /*
- * The idle thread. There's no useful work to be
- * done, so just try to conserve power and have a
- * low exit latency (ie sit in a loop waiting for
- * somebody to say that they'd like to reschedule)
+ * The idle thread.  We try to conserve power, while trying to keep
+ * overall latency low.  The architecture specific idle is passed
+ * a value to indicate the level of "idleness" of the system.
  */
 void cpu_idle(void)
 {
        /* endless idle loop with no priority at all */
        while (1) {
-               idle();
+               void (*idle)(void) = pm_idle;
+
+#ifdef CONFIG_HOTPLUG_CPU
+               if (cpu_is_offline(smp_processor_id()))
+                       cpu_die();
+#endif
+               if (!idle)
+                       idle = default_idle;
+               tick_nohz_stop_sched_tick();
+               while (!need_resched())
+                       idle();
+               tick_nohz_restart_sched_tick();
                preempt_enable_no_resched();
                schedule();
                preempt_disable();
@@ -189,7 +202,7 @@ copy_thread(int nr, unsigned long clone_flags,
  * sys_execve() executes a new program.
  */
 
-asmlinkage int sys_execve(char *name, char **argv, char **envp)
+asmlinkage int sys_execve(char __user *name, char __user * __user *argv, char __user * __user *envp)
 {
        int error;
        char *filename;
@@ -232,23 +245,25 @@ unsigned long get_wchan(struct task_struct *p)
 
 void finish_atomic_sections (struct pt_regs *regs)
 {
+       int __user *up0 = (int __user *)&regs->p0;
+
        if (regs->pc < ATOMIC_SEQS_START || regs->pc >= ATOMIC_SEQS_END)
                return;
 
        switch (regs->pc) {
        case ATOMIC_XCHG32 + 2:
-               put_user(regs->r1, (int *)regs->p0);
+               put_user(regs->r1, up0);
                regs->pc += 2;
                break;
 
        case ATOMIC_CAS32 + 2:
        case ATOMIC_CAS32 + 4:
                if (regs->r0 == regs->r1)
-                       put_user(regs->r2, (int *)regs->p0);
+                       put_user(regs->r2, up0);
                regs->pc = ATOMIC_CAS32 + 8;
                break;
        case ATOMIC_CAS32 + 6:
-               put_user(regs->r2, (int *)regs->p0);
+               put_user(regs->r2, up0);
                regs->pc += 2;
                break;
 
@@ -256,7 +271,7 @@ void finish_atomic_sections (struct pt_regs *regs)
                regs->r0 = regs->r1 + regs->r0;
                /* fall through */
        case ATOMIC_ADD32 + 4:
-               put_user(regs->r0, (int *)regs->p0);
+               put_user(regs->r0, up0);
                regs->pc = ATOMIC_ADD32 + 6;
                break;
 
@@ -264,7 +279,7 @@ void finish_atomic_sections (struct pt_regs *regs)
                regs->r0 = regs->r1 - regs->r0;
                /* fall through */
        case ATOMIC_SUB32 + 4:
-               put_user(regs->r0, (int *)regs->p0);
+               put_user(regs->r0, up0);
                regs->pc = ATOMIC_SUB32 + 6;
                break;
 
@@ -272,7 +287,7 @@ void finish_atomic_sections (struct pt_regs *regs)
                regs->r0 = regs->r1 | regs->r0;
                /* fall through */
        case ATOMIC_IOR32 + 4:
-               put_user(regs->r0, (int *)regs->p0);
+               put_user(regs->r0, up0);
                regs->pc = ATOMIC_IOR32 + 6;
                break;
 
@@ -280,7 +295,7 @@ void finish_atomic_sections (struct pt_regs *regs)
                regs->r0 = regs->r1 & regs->r0;
                /* fall through */
        case ATOMIC_AND32 + 4:
-               put_user(regs->r0, (int *)regs->p0);
+               put_user(regs->r0, up0);
                regs->pc = ATOMIC_AND32 + 6;
                break;
 
@@ -288,7 +303,7 @@ void finish_atomic_sections (struct pt_regs *regs)
                regs->r0 = regs->r1 ^ regs->r0;
                /* fall through */
        case ATOMIC_XOR32 + 4:
-               put_user(regs->r0, (int *)regs->p0);
+               put_user(regs->r0, up0);
                regs->pc = ATOMIC_XOR32 + 6;
                break;
        }
@@ -309,6 +324,12 @@ int _access_ok(unsigned long addr, unsigned long size)
                return 1;
        if (addr >= memory_mtd_end && (addr + size) <= physical_mem_end)
                return 1;
+
+#ifdef CONFIG_ROMFS_MTD_FS
+       /* For XIP, allow user space to use pointers within the ROMFS.  */
+       if (addr >= memory_mtd_start && (addr + size) <= memory_mtd_end)
+               return 1;
+#endif
 #else
        if (addr >= memory_start && (addr + size) <= physical_mem_end)
                return 1;
index 85caf9b711a16ff59eb069a42ee9fb29491a589b..b4f062c172c69042e192b73352c21805ef4a7abe 100644 (file)
@@ -193,6 +193,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 {
        int ret;
        int add = 0;
+       unsigned long __user *datap = (unsigned long __user *)data;
 
        switch (request) {
                /* when I and D space are separate, these will need to be fixed. */
@@ -229,7 +230,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
                        pr_debug("ptrace: copied size %d [0x%08lx]\n", copied, tmp);
                        if (copied != sizeof(tmp))
                                break;
-                       ret = put_user(tmp, (unsigned long *)data);
+                       ret = put_user(tmp, datap);
                        break;
                }
 
@@ -263,7 +264,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
                        } else {
                                tmp = get_reg(child, addr);
                        }
-                       ret = put_user(tmp, (unsigned long *)data);
+                       ret = put_user(tmp, datap);
                        break;
                }
 
@@ -389,7 +390,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
                {
 
                        /* Get all gp regs from the child. */
-                       ret = ptrace_getregs(child, (void __user *)data);
+                       ret = ptrace_getregs(child, datap);
                        break;
                }
 
index 483f93dfc1b590a7ea6cdc582a40eadd3d17982e..367e2dc0988195a9ed6d41e5acda35a00cc088f4 100644 (file)
 #include <asm/reboot.h>
 #include <asm/system.h>
 
-#if defined(BF537_FAMILY) || defined(BF533_FAMILY) || defined(BF527_FAMILY)
-#define SYSCR_VAL      0x0
-#elif defined(BF561_FAMILY)
-#define SYSCR_VAL      0x20
-#elif defined(BF548_FAMILY)
-#define SYSCR_VAL      0x10
-#endif
-
-/*
- * Delay min 5 SCLK cycles using worst case CCLK/SCLK ratio (15)
- */
-#define SWRST_DELAY    (5 * 15)
-
-/* A system soft reset makes external memory unusable
- * so force this function into L1.
+/* A system soft reset makes external memory unusable so force
+ * this function into L1.  We use the compiler ssync here rather
+ * than SSYNC() because it's safe (no interrupts and such) and
+ * we save some L1.  We do not need to force sanity in the SYSCR
+ * register as the BMODE selection bit is cleared by the soft
+ * reset while the Core B bit (on dual core parts) is cleared by
+ * the core reset.
  */
 __attribute__((l1_text))
 void bfin_reset(void)
 {
-       /* force BMODE and disable Core B (as needed) */
-       bfin_write_SYSCR(SYSCR_VAL);
-
-       /* we use asm ssync here because it's save and we save some L1 */
-       asm("ssync;");
+       /* Wait for completion of "system" events such as cache line
+        * line fills so that we avoid infinite stalls later on as
+        * much as possible.  This code is in L1, so it won't trigger
+        * any such event after this point in time.
+        */
+       __builtin_bfin_ssync();
 
        while (1) {
-               /* initiate system soft reset with magic 0x7 */
+               /* Initiate System software reset. */
                bfin_write_SWRST(0x7);
 
-               /* Wait for System reset to actually reset, needs to be 5 SCLKs, */
-               /* Assume CCLK / SCLK ratio is worst case (15), and use 5*15     */
-
-               asm("LSETUP(.Lfoo,.Lfoo) LC0 = %0\n .Lfoo: NOP;\n"
-                : : "a" (SWRST_DELAY) : "LC0", "LT0", "LB0");
+               /* Due to the way reset is handled in the hardware, we need
+                * to delay for 7 SCLKS.  The only reliable way to do this is
+                * to calculate the CCLK/SCLK ratio and multiply 7.  For now,
+                * we'll assume worse case which is a 1:15 ratio.
+                */
+               asm(
+                       "LSETUP (1f, 1f) LC0 = %0\n"
+                       "1: nop;"
+                       :
+                       : "a" (15 * 7)
+                       : "LC0", "LB0", "LT0"
+               );
 
-               /* clear system soft reset */
+               /* Clear System software reset */
                bfin_write_SWRST(0);
-               asm("ssync;");
-               /* issue core reset */
+
+               /* Wait for the SWRST write to complete.  Cannot rely on SSYNC
+                * though as the System state is all reset now.
+                */
+               asm(
+                       "LSETUP (1f, 1f) LC1 = %0\n"
+                       "1: nop;"
+                       :
+                       : "a" (15 * 1)
+                       : "LC1", "LB1", "LT1"
+               );
+
+               /* Issue core reset */
                asm("raise 1");
        }
 }
index 2255c289a714db37938d0b96345de10335dbc7ae..8efea004aecb46cdcd01c5899cf3aa52d97f9613 100644 (file)
@@ -35,6 +35,7 @@ u16 _bfin_swrst;
 EXPORT_SYMBOL(_bfin_swrst);
 
 unsigned long memory_start, memory_end, physical_mem_end;
+unsigned long _rambase, _ramstart, _ramend;
 unsigned long reserved_mem_dcache_on;
 unsigned long reserved_mem_icache_on;
 EXPORT_SYMBOL(memory_start);
@@ -106,7 +107,7 @@ void __init bf53x_relocate_l1_mem(void)
 
        l1_code_length = _etext_l1 - _stext_l1;
        if (l1_code_length > L1_CODE_LENGTH)
-               l1_code_length = L1_CODE_LENGTH;
+               panic("L1 Instruction SRAM Overflow\n");
        /* cannot complain as printk is not available as yet.
         * But we can continue booting and complain later!
         */
@@ -116,19 +117,18 @@ void __init bf53x_relocate_l1_mem(void)
 
        l1_data_a_length = _ebss_l1 - _sdata_l1;
        if (l1_data_a_length > L1_DATA_A_LENGTH)
-               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 */
        dma_memcpy(_sdata_l1, _l1_lma_start + l1_code_length, l1_data_a_length);
 
        l1_data_b_length = _ebss_b_l1 - _sdata_b_l1;
        if (l1_data_b_length > L1_DATA_B_LENGTH)
-               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 */
        dma_memcpy(_sdata_b_l1, _l1_lma_start + l1_code_length +
                        l1_data_a_length, l1_data_b_length);
-
 }
 
 /* add_memory_region to memmap */
@@ -547,11 +547,38 @@ static __init void  memory_setup(void)
                );
 }
 
+/*
+ * Find the lowest, highest page frame number we have available
+ */
+void __init find_min_max_pfn(void)
+{
+       int i;
+
+       max_pfn = 0;
+       min_low_pfn = memory_end;
+
+       for (i = 0; i < bfin_memmap.nr_map; i++) {
+               unsigned long start, end;
+               /* RAM? */
+               if (bfin_memmap.map[i].type != BFIN_MEMMAP_RAM)
+                       continue;
+               start = PFN_UP(bfin_memmap.map[i].addr);
+               end = PFN_DOWN(bfin_memmap.map[i].addr +
+                               bfin_memmap.map[i].size);
+               if (start >= end)
+                       continue;
+               if (end > max_pfn)
+                       max_pfn = end;
+               if (start < min_low_pfn)
+                       min_low_pfn = start;
+       }
+}
+
 static __init void setup_bootmem_allocator(void)
 {
        int bootmap_size;
        int i;
-       unsigned long min_pfn, max_pfn;
+       unsigned long start_pfn, end_pfn;
        unsigned long curr_pfn, last_pfn, size;
 
        /* mark memory between memory_start and memory_end usable */
@@ -561,8 +588,19 @@ static __init void setup_bootmem_allocator(void)
        sanitize_memmap(bfin_memmap.map, &bfin_memmap.nr_map);
        print_memory_map("boot memmap");
 
-       min_pfn = PAGE_OFFSET >> PAGE_SHIFT;
-       max_pfn = memory_end >> PAGE_SHIFT;
+       /* intialize globals in linux/bootmem.h */
+       find_min_max_pfn();
+       /* pfn of the last usable page frame */
+       if (max_pfn > memory_end >> PAGE_SHIFT)
+               max_pfn = memory_end >> PAGE_SHIFT;
+       /* pfn of last page frame directly mapped by kernel */
+       max_low_pfn = max_pfn;
+       /* pfn of the first usable page frame after kernel image*/
+       if (min_low_pfn < memory_start >> PAGE_SHIFT)
+               min_low_pfn = memory_start >> PAGE_SHIFT;
+
+       start_pfn = PAGE_OFFSET >> PAGE_SHIFT;
+       end_pfn = memory_end >> PAGE_SHIFT;
 
        /*
         * give all the memory to the bootmap allocator,  tell it to put the
@@ -570,7 +608,7 @@ static __init void setup_bootmem_allocator(void)
         */
        bootmap_size = init_bootmem_node(NODE_DATA(0),
                        memory_start >> PAGE_SHIFT,     /* map goes here */
-                       min_pfn, max_pfn);
+                       start_pfn, end_pfn);
 
        /* register the memmap regions with the bootmem allocator */
        for (i = 0; i < bfin_memmap.nr_map; i++) {
@@ -583,7 +621,7 @@ static __init void setup_bootmem_allocator(void)
                 * We are rounding up the start address of usable memory:
                 */
                curr_pfn = PFN_UP(bfin_memmap.map[i].addr);
-               if (curr_pfn >= max_pfn)
+               if (curr_pfn >= end_pfn)
                        continue;
                /*
                 * ... and at the end of the usable range downwards:
@@ -591,8 +629,8 @@ static __init void setup_bootmem_allocator(void)
                last_pfn = PFN_DOWN(bfin_memmap.map[i].addr +
                                         bfin_memmap.map[i].size);
 
-               if (last_pfn > max_pfn)
-                       last_pfn = max_pfn;
+               if (last_pfn > end_pfn)
+                       last_pfn = end_pfn;
 
                /*
                 * .. finally, did all the rounding and playing
@@ -611,9 +649,59 @@ static __init void setup_bootmem_allocator(void)
                BOOTMEM_DEFAULT);
 }
 
+#define EBSZ_TO_MEG(ebsz) \
+({ \
+       int meg = 0; \
+       switch (ebsz & 0xf) { \
+               case 0x1: meg =  16; break; \
+               case 0x3: meg =  32; break; \
+               case 0x5: meg =  64; break; \
+               case 0x7: meg = 128; break; \
+               case 0x9: meg = 256; break; \
+               case 0xb: meg = 512; break; \
+       } \
+       meg; \
+})
+static inline int __init get_mem_size(void)
+{
+#ifdef CONFIG_MEM_SIZE
+       return CONFIG_MEM_SIZE;
+#else
+# if defined(EBIU_SDBCTL)
+#  if defined(BF561_FAMILY)
+       int ret = 0;
+       u32 sdbctl = bfin_read_EBIU_SDBCTL();
+       ret += EBSZ_TO_MEG(sdbctl >>  0);
+       ret += EBSZ_TO_MEG(sdbctl >>  8);
+       ret += EBSZ_TO_MEG(sdbctl >> 16);
+       ret += EBSZ_TO_MEG(sdbctl >> 24);
+       return ret;
+#  else
+       return EBSZ_TO_MEG(bfin_read_EBIU_SDBCTL());
+#  endif
+# elif defined(EBIU_DDRCTL1)
+       u32 ddrctl = bfin_read_EBIU_DDRCTL1();
+       int ret = 0;
+       switch (ddrctl & 0xc0000) {
+               case DEVSZ_64:  ret = 64 / 8;
+               case DEVSZ_128: ret = 128 / 8;
+               case DEVSZ_256: ret = 256 / 8;
+               case DEVSZ_512: ret = 512 / 8;
+       }
+       switch (ddrctl & 0x30000) {
+               case DEVWD_4:  ret *= 2;
+               case DEVWD_8:  ret *= 2;
+               case DEVWD_16: break;
+       }
+       return ret;
+# endif
+#endif
+       BUG();
+}
+
 void __init setup_arch(char **cmdline_p)
 {
-       unsigned long l1_length, sclk, cclk;
+       unsigned long sclk, cclk;
 
 #ifdef CONFIG_DUMMY_CONSOLE
        conswitchp = &dummy_con;
@@ -631,7 +719,7 @@ void __init setup_arch(char **cmdline_p)
 
        /* setup memory defaults from the user config */
        physical_mem_end = 0;
-       _ramend = CONFIG_MEM_SIZE * 1024 * 1024;
+       _ramend = get_mem_size() * 1024 * 1024;
 
        memset(&bfin_memmap, 0, sizeof(bfin_memmap));
 
@@ -712,15 +800,6 @@ void __init setup_arch(char **cmdline_p)
 
        paging_init();
 
-       /* check the size of the l1 area */
-       l1_length = _etext_l1 - _stext_l1;
-       if (l1_length > L1_CODE_LENGTH)
-               panic("L1 code memory overflow\n");
-
-       l1_length = _ebss_l1 - _sdata_l1;
-       if (l1_length > L1_DATA_A_LENGTH)
-               panic("L1 data memory overflow\n");
-
        /* Copy atomic sequences to their fixed location, and sanity check that
           these locations are the ones that we advertise to userspace.  */
        memcpy((void *)FIXED_CODE_START, &fixed_code_start,
@@ -859,12 +938,17 @@ static int show_cpuinfo(struct seq_file *m, void *v)
        seq_printf(m, "processor\t: %d\n"
                "vendor_id\t: %s\n"
                "cpu family\t: 0x%x\n"
-               "model name\t: ADSP-%s %lu(MHz CCLK) %lu(MHz SCLK)\n"
+               "model name\t: ADSP-%s %lu(MHz CCLK) %lu(MHz SCLK) (%s)\n"
                "stepping\t: %d\n",
                0,
                vendor,
                (bfin_read_CHIPID() & CHIPID_FAMILY),
                cpu, cclk/1000000, sclk/1000000,
+#ifdef CONFIG_MPU
+               "mpu on",
+#else
+               "mpu off",
+#endif
                revid);
 
        seq_printf(m, "cpu MHz\t\t: %lu.%03lu/%lu.%03lu\n",
@@ -973,7 +1057,6 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                seq_printf(m, "No Ways are locked\n");
        }
 #endif
-
        seq_printf(m, "board name\t: %s\n", bfin_board_name);
        seq_printf(m, "board memory\t: %ld kB (0x%p -> 0x%p)\n",
                 physical_mem_end >> 10, (void *)0, (void *)physical_mem_end);
index 5564c9588aa807bd3c0384c9b5256e205b1cd7bd..d1fa24401dc6995d92410efb3948989049682e52 100644 (file)
@@ -38,6 +38,7 @@
 
 #include <asm/cacheflush.h>
 #include <asm/ucontext.h>
+#include <asm/fixed_code.h>
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
@@ -50,18 +51,20 @@ struct rt_sigframe {
        int sig;
        struct siginfo *pinfo;
        void *puc;
+       /* This is no longer needed by the kernel, but unfortunately userspace
+        * code expects it to be there.  */
        char retcode[8];
        struct siginfo info;
        struct ucontext uc;
 };
 
-asmlinkage int sys_sigaltstack(const stack_t * uss, stack_t * uoss)
+asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
 {
        return do_sigaltstack(uss, uoss, rdusp());
 }
 
 static inline int
-rt_restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc, int *pr0)
+rt_restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *pr0)
 {
        unsigned long usp = 0;
        int err = 0;
@@ -159,11 +162,6 @@ static inline int rt_setup_sigcontext(struct sigcontext *sc, struct pt_regs *reg
        return err;
 }
 
-static inline void push_cache(unsigned long vaddr, unsigned int len)
-{
-       flush_icache_range(vaddr, vaddr + len);
-}
-
 static inline void *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
                                 size_t frame_size)
 {
@@ -209,19 +207,9 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info,
        err |= rt_setup_sigcontext(&frame->uc.uc_mcontext, regs);
        err |= copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
 
-       /* Set up to return from userspace.  */
-       err |= __put_user(0x28, &(frame->retcode[0]));
-       err |= __put_user(0xe1, &(frame->retcode[1]));
-       err |= __put_user(0xad, &(frame->retcode[2]));
-       err |= __put_user(0x00, &(frame->retcode[3]));
-       err |= __put_user(0xa0, &(frame->retcode[4]));
-       err |= __put_user(0x00, &(frame->retcode[5]));
-
        if (err)
                goto give_sigsegv;
 
-       push_cache((unsigned long)&frame->retcode, sizeof(frame->retcode));
-
        /* Set up registers for signal handler */
        wrusp((unsigned long)frame);
        if (get_personality & FDPIC_FUNCPTRS) {
@@ -231,7 +219,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info,
                __get_user(regs->p3, &funcptr->GOT);
        } else
                regs->pc = (unsigned long)ka->sa.sa_handler;
-       regs->rets = (unsigned long)(frame->retcode);
+       regs->rets = SIGRETURN_STUB;
 
        regs->r0 = frame->sig;
        regs->r1 = (unsigned long)(&frame->info);
index abcd14817d0e4f1291f115e9bf12df16982397a9..efb7b25a2633be0c0c79971ec89ab3c9101153ed 100644 (file)
@@ -49,7 +49,7 @@
  * sys_pipe() is the normal C calling standard for creating
  * a pipe. It's not the way unix traditionally does this, though.
  */
-asmlinkage int sys_pipe(unsigned long *fildes)
+asmlinkage int sys_pipe(unsigned long __user *fildes)
 {
        int fd[2];
        int error;
diff --git a/arch/blackfin/kernel/time-ts.c b/arch/blackfin/kernel/time-ts.c
new file mode 100644 (file)
index 0000000..4482c47
--- /dev/null
@@ -0,0 +1,219 @@
+/*
+ * linux/arch/kernel/time-ts.c
+ *
+ * Based on arm clockevents implementation and old bfin time tick.
+ *
+ * Copyright(C) 2008, GeoTechnologies, Vitja Makarov
+ *
+ * This code is licenced under the GPL version 2. For details see
+ * kernel-base/COPYING.
+ */
+#include <linux/module.h>
+#include <linux/profile.h>
+#include <linux/interrupt.h>
+#include <linux/time.h>
+#include <linux/timex.h>
+#include <linux/irq.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/cpufreq.h>
+
+#include <asm/blackfin.h>
+#include <asm/time.h>
+
+#ifdef CONFIG_CYCLES_CLOCKSOURCE
+
+/* Accelerators for sched_clock()
+ * convert from cycles(64bits) => nanoseconds (64bits)
+ *  basic equation:
+ *             ns = cycles / (freq / ns_per_sec)
+ *             ns = cycles * (ns_per_sec / freq)
+ *             ns = cycles * (10^9 / (cpu_khz * 10^3))
+ *             ns = cycles * (10^6 / cpu_khz)
+ *
+ *     Then we use scaling math (suggested by george@mvista.com) to get:
+ *             ns = cycles * (10^6 * SC / cpu_khz) / SC
+ *             ns = cycles * cyc2ns_scale / SC
+ *
+ *     And since SC is a constant power of two, we can convert the div
+ *  into a shift.
+ *
+ *  We can use khz divisor instead of mhz to keep a better precision, since
+ *  cyc2ns_scale is limited to 10^6 * 2^10, which fits in 32 bits.
+ *  (mathieu.desnoyers@polymtl.ca)
+ *
+ *                     -johnstul@us.ibm.com "math is hard, lets go shopping!"
+ */
+
+static unsigned long cyc2ns_scale;
+#define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */
+
+static inline void set_cyc2ns_scale(unsigned long cpu_khz)
+{
+       cyc2ns_scale = (1000000 << CYC2NS_SCALE_FACTOR) / cpu_khz;
+}
+
+static inline unsigned long long cycles_2_ns(cycle_t cyc)
+{
+       return (cyc * cyc2ns_scale) >> CYC2NS_SCALE_FACTOR;
+}
+
+static cycle_t read_cycles(void)
+{
+       return get_cycles();
+}
+
+unsigned long long sched_clock(void)
+{
+       return cycles_2_ns(read_cycles());
+}
+
+static struct clocksource clocksource_bfin = {
+       .name           = "bfin_cycles",
+       .rating         = 350,
+       .read           = read_cycles,
+       .mask           = CLOCKSOURCE_MASK(64),
+       .shift          = 22,
+       .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static int __init bfin_clocksource_init(void)
+{
+       set_cyc2ns_scale(get_cclk() / 1000);
+
+       clocksource_bfin.mult = clocksource_hz2mult(get_cclk(), clocksource_bfin.shift);
+
+       if (clocksource_register(&clocksource_bfin))
+               panic("failed to register clocksource");
+
+       return 0;
+}
+
+#else
+# define bfin_clocksource_init()
+#endif
+
+static int bfin_timer_set_next_event(unsigned long cycles,
+                                     struct clock_event_device *evt)
+{
+       bfin_write_TCOUNT(cycles);
+       CSYNC();
+       return 0;
+}
+
+static void bfin_timer_set_mode(enum clock_event_mode mode,
+                                struct clock_event_device *evt)
+{
+       switch (mode) {
+       case CLOCK_EVT_MODE_PERIODIC: {
+               unsigned long tcount = ((get_cclk() / (HZ * TIME_SCALE)) - 1);
+               bfin_write_TCNTL(TMPWR);
+               bfin_write_TSCALE(TIME_SCALE - 1);
+               CSYNC();
+               bfin_write_TPERIOD(tcount);
+               bfin_write_TCOUNT(tcount);
+               bfin_write_TCNTL(TMPWR | TMREN | TAUTORLD);
+               CSYNC();
+               break;
+       }
+       case CLOCK_EVT_MODE_ONESHOT:
+               bfin_write_TSCALE(0);
+               bfin_write_TCOUNT(0);
+               bfin_write_TCNTL(TMPWR | TMREN);
+               CSYNC();
+               break;
+       case CLOCK_EVT_MODE_UNUSED:
+       case CLOCK_EVT_MODE_SHUTDOWN:
+               bfin_write_TCNTL(0);
+               CSYNC();
+               break;
+       case CLOCK_EVT_MODE_RESUME:
+               break;
+       }
+}
+
+static void __init bfin_timer_init(void)
+{
+       /* power up the timer, but don't enable it just yet */
+       bfin_write_TCNTL(TMPWR);
+       CSYNC();
+
+       /*
+        * the TSCALE prescaler counter.
+        */
+       bfin_write_TSCALE(TIME_SCALE - 1);
+       bfin_write_TPERIOD(0);
+       bfin_write_TCOUNT(0);
+
+       /* now enable the timer */
+       CSYNC();
+}
+
+/*
+ * timer_interrupt() needs to keep up the real-time clock,
+ * as well as call the "do_timer()" routine every clocktick
+ */
+#ifdef CONFIG_CORE_TIMER_IRQ_L1
+__attribute__((l1_text))
+#endif
+irqreturn_t timer_interrupt(int irq, void *dev_id);
+
+static struct clock_event_device clockevent_bfin = {
+       .name           = "bfin_core_timer",
+       .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+       .shift          = 32,
+       .cpumask        = CPU_MASK_CPU0,
+       .set_next_event = bfin_timer_set_next_event,
+       .set_mode       = bfin_timer_set_mode,
+};
+
+static struct irqaction bfin_timer_irq = {
+       .name           = "Blackfin Core Timer",
+       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+       .handler        = timer_interrupt,
+       .dev_id         = &clockevent_bfin,
+};
+
+irqreturn_t timer_interrupt(int irq, void *dev_id)
+{
+       struct clock_event_device *evt = dev_id;
+       evt->event_handler(evt);
+       return IRQ_HANDLED;
+}
+
+static int __init bfin_clockevent_init(void)
+{
+       setup_irq(IRQ_CORETMR, &bfin_timer_irq);
+       bfin_timer_init();
+
+       clockevent_bfin.mult = div_sc(get_cclk(), NSEC_PER_SEC, clockevent_bfin.shift);
+       clockevent_bfin.max_delta_ns = clockevent_delta2ns(-1, &clockevent_bfin);
+       clockevent_bfin.min_delta_ns = clockevent_delta2ns(100, &clockevent_bfin);
+       clockevents_register_device(&clockevent_bfin);
+
+       return 0;
+}
+
+void __init time_init(void)
+{
+       time_t secs_since_1970 = (365 * 37 + 9) * 24 * 60 * 60; /* 1 Jan 2007 */
+
+#ifdef CONFIG_RTC_DRV_BFIN
+       /* [#2663] hack to filter junk RTC values that would cause
+        * userspace to have to deal with time values greater than
+        * 2^31 seconds (which uClibc cannot cope with yet)
+        */
+       if ((bfin_read_RTC_STAT() & 0xC0000000) == 0xC0000000) {
+               printk(KERN_NOTICE "bfin-rtc: invalid date; resetting\n");
+               bfin_write_RTC_STAT(0);
+       }
+#endif
+
+       /* Initialize xtime. From now on, xtime is updated with timer interrupts */
+       xtime.tv_sec = secs_since_1970;
+       xtime.tv_nsec = 0;
+       set_normalized_timespec(&wall_to_monotonic, -xtime.tv_sec, -xtime.tv_nsec);
+
+       bfin_clocksource_init();
+       bfin_clockevent_init();
+}
index 715b3945e4c7119b4af88c4f986b38cf91d63700..eb23523204547194c1de575478554510a7665356 100644 (file)
@@ -6,9 +6,10 @@
  * Created:
  * Description:  This file contains the bfin-specific time handling details.
  *               Most of the stuff is located in the machine specific files.
+ *              FIXME: (This file is subject for removal)
  *
  * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
+ *               Copyright 2004-2008 Analog Devices Inc.
  *
  * Bugs:         Enter bugs at http://blackfin.uclinux.org/
  *
@@ -35,6 +36,7 @@
 #include <linux/irq.h>
 
 #include <asm/blackfin.h>
+#include <asm/time.h>
 
 /* This is an NTP setting */
 #define        TICK_SIZE (tick_nsec / 1000)
@@ -47,21 +49,6 @@ static struct irqaction bfin_timer_irq = {
        .flags = IRQF_DISABLED
 };
 
-/*
- * The way that the Blackfin core timer works is:
- *  - CCLK is divided by a programmable 8-bit pre-scaler (TSCALE)
- *  - Every time TSCALE ticks, a 32bit is counted down (TCOUNT)
- *
- * If you take the fastest clock (1ns, or 1GHz to make the math work easier)
- *    10ms is 10,000,000 clock ticks, which fits easy into a 32-bit counter
- *    (32 bit counter is 4,294,967,296ns or 4.2 seconds) so, we don't need
- *    to use TSCALE, and program it to zero (which is pass CCLK through).
- *    If you feel like using it, try to keep HZ * TIMESCALE to some
- *    value that divides easy (like power of 2).
- */
-
-#define TIME_SCALE 1
-
 static void
 time_sched_init(irq_handler_t timer_routine)
 {
index 56a67ab698c7a6a69cee1a04d20b72b1e1d7cd6d..5b847070dae509f293827e327e32204d4be8e133 100644 (file)
@@ -67,6 +67,8 @@ void __init trap_init(void)
        CSYNC();
 }
 
+void *saved_icplb_fault_addr, *saved_dcplb_fault_addr;
+
 int kstack_depth_to_print = 48;
 
 static void decode_address(char *buf, unsigned long address)
@@ -75,7 +77,7 @@ static void decode_address(char *buf, unsigned long address)
        struct task_struct *p;
        struct mm_struct *mm;
        unsigned long flags, offset;
-       unsigned int in_exception = bfin_read_IPEND() & 0x10;
+       unsigned char in_atomic = (bfin_read_IPEND() & 0x10) || in_atomic();
 
 #ifdef CONFIG_KALLSYMS
        unsigned long symsize;
@@ -117,7 +119,7 @@ static void decode_address(char *buf, unsigned long address)
         */
        write_lock_irqsave(&tasklist_lock, flags);
        for_each_process(p) {
-               mm = (in_exception ? p->mm : get_task_mm(p));
+               mm = (in_atomic ? p->mm : get_task_mm(p));
                if (!mm)
                        continue;
 
@@ -137,23 +139,36 @@ static void decode_address(char *buf, unsigned long address)
                                /* FLAT does not have its text aligned to the start of
                                 * the map while FDPIC ELF does ...
                                 */
-                               if (current->mm &&
-                                   (address > current->mm->start_code) &&
-                                   (address < current->mm->end_code))
-                                       offset = address - current->mm->start_code;
-                               else
-                                       offset = (address - vma->vm_start) + (vma->vm_pgoff << PAGE_SHIFT);
-
-                               sprintf(buf, "<0x%p> [ %s + 0x%lx ]",
-                                       (void *)address, name, offset);
-                               if (!in_exception)
+
+                               /* before we can check flat/fdpic, we need to
+                                * make sure current is valid
+                                */
+                               if ((unsigned long)current >= FIXED_CODE_START &&
+                                   !((unsigned long)current & 0x3)) {
+                                       if (current->mm &&
+                                           (address > current->mm->start_code) &&
+                                           (address < current->mm->end_code))
+                                               offset = address - current->mm->start_code;
+                                       else
+                                               offset = (address - vma->vm_start) +
+                                                        (vma->vm_pgoff << PAGE_SHIFT);
+
+                                       sprintf(buf, "<0x%p> [ %s + 0x%lx ]",
+                                               (void *)address, name, offset);
+                               } else
+                                       sprintf(buf, "<0x%p> [ %s vma:0x%lx-0x%lx]",
+                                               (void *)address, name,
+                                               vma->vm_start, vma->vm_end);
+
+                               if (!in_atomic)
                                        mmput(mm);
+
                                goto done;
                        }
 
                        vml = vml->next;
                }
-               if (!in_exception)
+               if (!in_atomic)
                        mmput(mm);
        }
 
@@ -506,7 +521,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
 
        info.si_signo = sig;
        info.si_errno = 0;
-       info.si_addr = (void *)fp->pc;
+       info.si_addr = (void __user *)fp->pc;
        force_sig_info(sig, &info, current);
 
        trace_buffer_restore(j);
@@ -655,21 +670,31 @@ void dump_bfin_process(struct pt_regs *fp)
        else if (context & 0x8000)
                printk(KERN_NOTICE "Kernel process context\n");
 
-       if (current->pid && current->mm) {
+       /* Because we are crashing, and pointers could be bad, we check things
+        * pretty closely before we use them
+        */
+       if ((unsigned long)current >= FIXED_CODE_START &&
+           !((unsigned long)current & 0x3) && current->pid) {
                printk(KERN_NOTICE "CURRENT PROCESS:\n");
-               printk(KERN_NOTICE "COMM=%s PID=%d\n",
-                       current->comm, current->pid);
-
-               printk(KERN_NOTICE "TEXT = 0x%p-0x%p  DATA = 0x%p-0x%p\n"
-                       KERN_NOTICE "BSS = 0x%p-0x%p   USER-STACK = 0x%p\n"
-                       KERN_NOTICE "\n",
-                       (void *)current->mm->start_code,
-                       (void *)current->mm->end_code,
-                       (void *)current->mm->start_data,
-                       (void *)current->mm->end_data,
-                       (void *)current->mm->end_data,
-                       (void *)current->mm->brk,
-                       (void *)current->mm->start_stack);
+               if (current->comm >= (char *)FIXED_CODE_START)
+                       printk(KERN_NOTICE "COMM=%s PID=%d\n",
+                               current->comm, current->pid);
+               else
+                       printk(KERN_NOTICE "COMM= invalid\n");
+
+               if (!((unsigned long)current->mm & 0x3) && (unsigned long)current->mm >= FIXED_CODE_START)
+                       printk(KERN_NOTICE  "TEXT = 0x%p-0x%p        DATA = 0x%p-0x%p\n"
+                               KERN_NOTICE " BSS = 0x%p-0x%p  USER-STACK = 0x%p\n"
+                               KERN_NOTICE "\n",
+                               (void *)current->mm->start_code,
+                               (void *)current->mm->end_code,
+                               (void *)current->mm->start_data,
+                               (void *)current->mm->end_data,
+                               (void *)current->mm->end_data,
+                               (void *)current->mm->brk,
+                               (void *)current->mm->start_stack);
+               else
+                       printk(KERN_NOTICE "invalid mm\n");
        } else
                printk(KERN_NOTICE "\n" KERN_NOTICE
                     "No Valid process in current context\n");
@@ -680,10 +705,7 @@ void dump_bfin_mem(struct pt_regs *fp)
        unsigned short *addr, *erraddr, val = 0, err = 0;
        char sti = 0, buf[6];
 
-       if (unlikely((fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR))
-               erraddr = (void *)fp->pc;
-       else
-               erraddr = (void *)fp->retx;
+       erraddr = (void *)fp->pc;
 
        printk(KERN_NOTICE "return address: [0x%p]; contents of:", erraddr);
 
@@ -807,9 +829,9 @@ unlock:
 
        if (((long)fp->seqstat &  SEQSTAT_EXCAUSE) &&
            (((long)fp->seqstat & SEQSTAT_EXCAUSE) != VEC_HWERR)) {
-               decode_address(buf, bfin_read_DCPLB_FAULT_ADDR());
+               decode_address(buf, saved_dcplb_fault_addr);
                printk(KERN_NOTICE "DCPLB_FAULT_ADDR: %s\n", buf);
-               decode_address(buf, bfin_read_ICPLB_FAULT_ADDR());
+               decode_address(buf, saved_icplb_fault_addr);
                printk(KERN_NOTICE "ICPLB_FAULT_ADDR: %s\n", buf);
        }
 
@@ -917,8 +939,8 @@ void panic_cplb_error(int cplb_panic, struct pt_regs *fp)
 
        oops_in_progress = 1;
 
-       printk(KERN_EMERG "DCPLB_FAULT_ADDR=%p\n", (void *)bfin_read_DCPLB_FAULT_ADDR());
-       printk(KERN_EMERG "ICPLB_FAULT_ADDR=%p\n", (void *)bfin_read_ICPLB_FAULT_ADDR());
+       printk(KERN_EMERG "DCPLB_FAULT_ADDR=%p\n", saved_dcplb_fault_addr);
+       printk(KERN_EMERG "ICPLB_FAULT_ADDR=%p\n", saved_icplb_fault_addr);
        dump_bfin_process(fp);
        dump_bfin_mem(fp);
        show_regs(fp);
index cb01a9de26802aad098eef036a434cdaf8d6b0d7..3ecc64cab3be03231484f907ddfc20fd784be6df 100644 (file)
@@ -56,6 +56,10 @@ SECTIONS
                *(.text.*)
                *(.fixup)
 
+#if !L1_CODE_LENGTH
+               *(.l1.text)
+#endif
+
                . = ALIGN(16);
                ___start___ex_table = .;
                *(__ex_table)
@@ -73,6 +77,12 @@ SECTIONS
                ___bss_start = .;
                *(.bss .bss.*)
                *(COMMON)
+#if !L1_DATA_A_LENGTH
+               *(.l1.bss)
+#endif
+#if !L1_DATA_B_LENGTH
+               *(.l1.bss.B)
+#endif
                ___bss_stop = .;
        }
 
@@ -83,6 +93,15 @@ SECTIONS
                . = ALIGN(32);
                *(.data.cacheline_aligned)
 
+#if !L1_DATA_A_LENGTH
+               . = ALIGN(32);
+               *(.data_l1.cacheline_aligned)
+               *(.l1.data)
+#endif
+#if !L1_DATA_B_LENGTH
+               *(.l1.data.B)
+#endif
+
                DATA_DATA
                *(.data.*)
                CONSTRUCTORS
@@ -147,64 +166,43 @@ SECTIONS
 
        __l1_lma_start = .;
 
-#if L1_CODE_LENGTH
-# define LDS_L1_CODE *(.l1.text)
-#else
-# define LDS_L1_CODE
-#endif
        .text_l1 L1_CODE_START : AT(LOADADDR(.init.ramfs) + SIZEOF(.init.ramfs))
        {
                . = ALIGN(4);
                __stext_l1 = .;
-               LDS_L1_CODE
+               *(.l1.text)
                . = ALIGN(4);
                __etext_l1 = .;
        }
 
-#if L1_DATA_A_LENGTH
-# define LDS_L1_A_DATA  *(.l1.data)
-# define LDS_L1_A_BSS   *(.l1.bss)
-# define LDS_L1_A_CACHE *(.data_l1.cacheline_aligned)
-#else
-# define LDS_L1_A_DATA
-# define LDS_L1_A_BSS
-# define LDS_L1_A_CACHE
-#endif
        .data_l1 L1_DATA_A_START : AT(LOADADDR(.text_l1) + SIZEOF(.text_l1))
        {
                . = ALIGN(4);
                __sdata_l1 = .;
-               LDS_L1_A_DATA
+               *(.l1.data)
                __edata_l1 = .;
 
                . = ALIGN(4);
                __sbss_l1 = .;
-               LDS_L1_A_BSS
+               *(.l1.bss)
 
                . = ALIGN(32);
-               LDS_L1_A_CACHE
+               *(.data_l1.cacheline_aligned)
 
                . = ALIGN(4);
                __ebss_l1 = .;
        }
 
-#if L1_DATA_B_LENGTH
-# define LDS_L1_B_DATA  *(.l1.data.B)
-# define LDS_L1_B_BSS   *(.l1.bss.B)
-#else
-# define LDS_L1_B_DATA
-# define LDS_L1_B_BSS
-#endif
        .data_b_l1 L1_DATA_B_START : AT(LOADADDR(.data_l1) + SIZEOF(.data_l1))
        {
                . = ALIGN(4);
                __sdata_b_l1 = .;
-               LDS_L1_B_DATA
+               *(.l1.data.B)
                __edata_b_l1 = .;
 
                . = ALIGN(4);
                __sbss_b_l1 = .;
-               LDS_L1_B_BSS
+               *(.l1.bss.B)
 
                . = ALIGN(4);
                __ebss_b_l1 = .;
@@ -223,8 +221,6 @@ SECTIONS
 
        DWARF_DEBUG
 
-       NOTES
-
        /DISCARD/ :
        {
                EXIT_TEXT
index 9f99f5d0bcd1cbfedbe4c37622f30599bf6465c7..4eddb580319cc68c1ec44b99059f9e00539b975e 100644 (file)
@@ -5,5 +5,3 @@
 extra-y := head.o
 
 obj-y := ints-priority.o dma.o
-
-obj-$(CONFIG_CPU_FREQ)   += cpu.o
index cf4bc0d8335521737422e2d3c3796278e4962fee..583d53811f0364fb4ae28c3654c5736489e853dd 100644 (file)
@@ -94,7 +94,7 @@ int __init bfin_isp1761_init(void)
 {
        unsigned int num_devices = ARRAY_SIZE(bfin_isp1761_devices);
 
-       printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
+       printk(KERN_INFO "%s(): registering device resources\n", __func__);
        set_irq_type(ISP1761_IRQ, IRQF_TRIGGER_FALLING);
 
        return platform_add_devices(bfin_isp1761_devices, num_devices);
@@ -416,7 +416,7 @@ static struct platform_device net2272_bfin_device = {
 static struct mtd_partition bfin_spi_flash_partitions[] = {
        {
                .name = "bootloader",
-               .size = 0x00020000,
+               .size = 0x00040000,
                .offset = 0,
                .mask_flags = MTD_CAP_ROM
        }, {
@@ -707,6 +707,32 @@ static struct platform_device bfin_uart_device = {
 };
 #endif
 
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+static struct resource bfin_sir_resources[] = {
+#ifdef CONFIG_BFIN_SIR0
+       {
+               .start = 0xFFC00400,
+               .end = 0xFFC004FF,
+               .flags = IORESOURCE_MEM,
+       },
+#endif
+#ifdef CONFIG_BFIN_SIR1
+       {
+               .start = 0xFFC02000,
+               .end = 0xFFC020FF,
+               .flags = IORESOURCE_MEM,
+       },
+#endif
+};
+
+static struct platform_device bfin_sir_device = {
+       .name = "bfin_sir",
+       .id = 0,
+       .num_resources = ARRAY_SIZE(bfin_sir_resources),
+       .resource = bfin_sir_resources,
+};
+#endif
+
 #if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
 static struct resource bfin_twi0_resource[] = {
        [0] = {
@@ -874,6 +900,10 @@ static struct platform_device *stamp_devices[] __initdata = {
        &bfin_uart_device,
 #endif
 
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+       &bfin_sir_device,
+#endif
+
 #if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
        &i2c_bfin_twi_device,
 #endif
@@ -896,7 +926,7 @@ static struct platform_device *stamp_devices[] __initdata = {
 
 static int __init stamp_init(void)
 {
-       printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
+       printk(KERN_INFO "%s(): registering device resources\n", __func__);
        platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
 #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
        spi_register_board_info(bfin_spi_board_info,
diff --git a/arch/blackfin/mach-bf527/cpu.c b/arch/blackfin/mach-bf527/cpu.c
deleted file mode 100644 (file)
index 1975402..0000000
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * File:         arch/blackfin/mach-bf527/cpu.c
- * Based on:   arch/blackfin/mach-bf537/cpu.c
- * Author:       michael.kang@analog.com
- *
- * Created:
- * Description:  clock scaling for the bf527
- *
- * Modified:
- *               Copyright 2004-2007 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/cpufreq.h>
-#include <asm/dpmc.h>
-#include <linux/fs.h>
-#include <asm/bfin-global.h>
-
-/* CONFIG_CLKIN_HZ=11059200 */
-#define VCO5 (CONFIG_CLKIN_HZ*45)      /*497664000 */
-#define VCO4 (CONFIG_CLKIN_HZ*36)      /*398131200 */
-#define VCO3 (CONFIG_CLKIN_HZ*27)      /*298598400 */
-#define VCO2 (CONFIG_CLKIN_HZ*18)      /*199065600 */
-#define VCO1 (CONFIG_CLKIN_HZ*9)       /*99532800 */
-#define VCO(x) VCO##x
-
-#define MFREQ(x) {VCO(x), VCO(x)/4}, {VCO(x), VCO(x)/2}, {VCO(x), VCO(x)}
-/* frequency */
-static struct cpufreq_frequency_table bf527_freq_table[] = {
-       MFREQ(1),
-       MFREQ(3),
-       {VCO4, VCO4 / 2}, {VCO4, VCO4},
-       MFREQ(5),
-       {0, CPUFREQ_TABLE_END},
-};
-
-/*
- * dpmc_fops->ioctl()
- * static int dpmc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
- */
-static int bf527_getfreq(unsigned int cpu)
-{
-       unsigned long cclk_mhz;
-
-       /* The driver only support single cpu */
-       if (cpu == 0)
-               dpmc_fops.ioctl(NULL, NULL, IOCTL_GET_CORECLOCK, &cclk_mhz);
-       else
-               cclk_mhz = -1;
-
-       return cclk_mhz;
-}
-
-static int bf527_target(struct cpufreq_policy *policy,
-                       unsigned int target_freq, unsigned int relation)
-{
-       unsigned long cclk_mhz;
-       unsigned long vco_mhz;
-       unsigned long flags;
-       unsigned int index;
-       struct cpufreq_freqs freqs;
-
-       if (cpufreq_frequency_table_target
-           (policy, bf527_freq_table, target_freq, relation, &index))
-               return -EINVAL;
-
-       cclk_mhz = bf527_freq_table[index].frequency;
-       vco_mhz = bf527_freq_table[index].index;
-
-       dpmc_fops.ioctl(NULL, NULL, IOCTL_CHANGE_FREQUENCY, &vco_mhz);
-       freqs.old = bf527_getfreq(0);
-       freqs.new = cclk_mhz;
-       freqs.cpu = 0;
-
-       pr_debug
-           ("cclk begin change to cclk %d,vco=%d,index=%d,target=%d,oldfreq=%d\n",
-            cclk_mhz, vco_mhz, index, target_freq, freqs.old);
-
-       cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-       local_irq_save(flags);
-       dpmc_fops.ioctl(NULL, NULL, IOCTL_SET_CCLK, &cclk_mhz);
-       local_irq_restore(flags);
-       cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-
-       vco_mhz = get_vco();
-       cclk_mhz = get_cclk();
-       return 0;
-}
-
-/* make sure that only the "userspace" governor is run -- anything else wouldn't make sense on
- * this platform, anyway.
- */
-static int bf527_verify_speed(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, &bf527_freq_table);
-}
-
-static int __init __bf527_cpu_init(struct cpufreq_policy *policy)
-{
-       if (policy->cpu != 0)
-               return -EINVAL;
-
-       policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
-
-       policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
-       /*Now ,only support one cpu */
-       policy->cur = bf527_getfreq(0);
-       cpufreq_frequency_table_get_attr(bf527_freq_table, policy->cpu);
-       return cpufreq_frequency_table_cpuinfo(policy, bf527_freq_table);
-}
-
-static struct freq_attr *bf527_freq_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
-static struct cpufreq_driver bf527_driver = {
-       .verify = bf527_verify_speed,
-       .target = bf527_target,
-       .get = bf527_getfreq,
-       .init = __bf527_cpu_init,
-       .name = "bf527",
-       .owner = THIS_MODULE,
-       .attr = bf527_freq_attr,
-};
-
-static int __init bf527_cpu_init(void)
-{
-       return cpufreq_register_driver(&bf527_driver);
-}
-
-static void __exit bf527_cpu_exit(void)
-{
-       cpufreq_unregister_driver(&bf527_driver);
-}
-
-MODULE_AUTHOR("Mickael Kang");
-MODULE_DESCRIPTION("cpufreq driver for bf527 CPU");
-MODULE_LICENSE("GPL");
-
-module_init(bf527_cpu_init);
-module_exit(bf527_cpu_exit);
index 522de24cc39413a53e68b35d5cc6cbf369bffbd1..dfd080cda787cbbc33ad0e13d68027f908471817 100644 (file)
  * to the Free Software Foundation, Inc.,
  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
+#include <linux/module.h>
+
 #include <asm/blackfin.h>
 #include <asm/dma.h>
 
-struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
+struct dma_register *dma_io_base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
        (struct dma_register *) DMA0_NEXT_DESC_PTR,
        (struct dma_register *) DMA1_NEXT_DESC_PTR,
        (struct dma_register *) DMA2_NEXT_DESC_PTR,
@@ -47,6 +49,7 @@ struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
        (struct dma_register *) MDMA_D1_NEXT_DESC_PTR,
        (struct dma_register *) MDMA_S1_NEXT_DESC_PTR,
 };
+EXPORT_SYMBOL(dma_io_base_addr);
 
 int channel2irq(unsigned int channel)
 {
index cdb00a084965c19fc77d4fd8b9a91e436206bcb2..57bdb3ba2fede26bf63b3ad4ee9cab714d87f1fe 100644 (file)
@@ -37,9 +37,6 @@
 #include <asm/mach/mem_init.h>
 #endif
 
-.global __rambase
-.global __ramstart
-.global __ramend
 .extern ___bss_stop
 .extern ___bss_start
 .extern _bf53x_relocate_l1_mem
@@ -439,18 +436,3 @@ ENTRY(_start_dma_code)
        RTS;
 ENDPROC(_start_dma_code)
 #endif /* CONFIG_BFIN_KERNEL_CLOCK */
-
-.data
-
-/*
- * Set up the usable of RAM stuff. Size of RAM is determined then
- * an initial stack set up at the end.
- */
-
-.align 4
-__rambase:
-.long   0
-__ramstart:
-.long   0
-__ramend:
-.long   0
index 8cce1736360d3b8904df3acc9be3fa8a709588e2..aa9f2647ee0c209eafa6087c0073b629a469a10f 100644 (file)
@@ -5,5 +5,3 @@
 extra-y := head.o
 
 obj-y := ints-priority.o dma.o
-
-obj-$(CONFIG_CPU_FREQ)   += cpu.o
index 97378b0a975308047004fb89eb2768038968597f..7cc4864f6aafa0e32aa5bdf595b2cf7c198d0b10 100644 (file)
@@ -304,6 +304,25 @@ static struct platform_device bfin_uart_device = {
 };
 #endif
 
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+static struct resource bfin_sir_resources[] = {
+#ifdef CONFIG_BFIN_SIR0
+       {
+               .start = 0xFFC00400,
+               .end = 0xFFC004FF,
+               .flags = IORESOURCE_MEM,
+       },
+#endif
+};
+
+static struct platform_device bfin_sir_device = {
+       .name = "bfin_sir",
+       .id = 0,
+       .num_resources = ARRAY_SIZE(bfin_sir_resources),
+       .resource = bfin_sir_resources,
+};
+#endif
+
 #if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
 
 #include <linux/serial_8250.h>
@@ -403,6 +422,10 @@ static struct platform_device *h8606_devices[] __initdata = {
        &serial8250_device,
 #endif
 
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+       &bfin_sir_device,
+#endif
+
 #if defined(CONFIG_KEYBOARD_OPENCORES) || defined(CONFIG_KEYBOARD_OPENCORES_MODULE)
        &opencores_kbd_device,
 #endif
@@ -411,7 +434,7 @@ static struct platform_device *h8606_devices[] __initdata = {
 static int __init H8606_init(void)
 {
        printk(KERN_INFO "HV Sistemas H8606 board support by http://www.hvsistemas.com\n");
-       printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
+       printk(KERN_INFO "%s(): registering device resources\n", __func__);
        platform_add_devices(h8606_devices, ARRAY_SIZE(h8606_devices));
 #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
        spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
index 751de5110afc480d3d137f514bd817a1ecaad7d2..840059241fbecc58b2c4bdc9dbedfc400ff54ae1 100644 (file)
@@ -26,6 +26,12 @@ config H8606_HVSISTEMAS
        help
          HV Sistemas H8606 board support.
 
+config BFIN532_IP0X
+       bool "IP04/IP08 IP-PBX"
+       depends on (BF532)
+       help
+         Core support for IP04/IP04 open hardware IP-PBX.
+
 config GENERIC_BF533_BOARD
        bool "Generic"
        help
index 54f57fb9791e0c501256d30a5a99897c46170d67..b7a1a1d79bdad4ff8e2463a9d6f6b757f5f598a5 100644 (file)
@@ -4,6 +4,7 @@
 
 obj-$(CONFIG_GENERIC_BF533_BOARD)      += generic_board.o
 obj-$(CONFIG_BFIN533_STAMP)            += stamp.o
+obj-$(CONFIG_BFIN532_IP0X)             += ip0x.o
 obj-$(CONFIG_BFIN533_EZKIT)            += ezkit.o
 obj-$(CONFIG_BFIN533_BLUETECHNIX_CM)   += cm_bf533.o
 obj-$(CONFIG_H8606_HVSISTEMAS)         += H8606.o
index 886f260d9359f35b9e754ecab4eccccbd35ceb94..a03149c72681adb2fdf9e2f2c29c3ed005c59fc2 100644 (file)
@@ -234,6 +234,25 @@ static struct platform_device bfin_uart_device = {
 };
 #endif
 
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+static struct resource bfin_sir_resources[] = {
+#ifdef CONFIG_BFIN_SIR0
+       {
+               .start = 0xFFC00400,
+               .end = 0xFFC004FF,
+               .flags = IORESOURCE_MEM,
+       },
+#endif
+};
+
+static struct platform_device bfin_sir_device = {
+       .name = "bfin_sir",
+       .id = 0,
+       .num_resources = ARRAY_SIZE(bfin_sir_resources),
+       .resource = bfin_sir_resources,
+};
+#endif
+
 #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
 static struct platform_device bfin_sport0_uart_device = {
        .name = "bfin-sport-uart",
@@ -327,6 +346,10 @@ static struct platform_device *cm_bf533_devices[] __initdata = {
        &bfin_uart_device,
 #endif
 
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+       &bfin_sir_device,
+#endif
+
 #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
        &bfin_sport0_uart_device,
        &bfin_sport1_uart_device,
@@ -355,7 +378,7 @@ static struct platform_device *cm_bf533_devices[] __initdata = {
 
 static int __init cm_bf533_init(void)
 {
-       printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
+       printk(KERN_INFO "%s(): registering device resources\n", __func__);
        platform_add_devices(cm_bf533_devices, ARRAY_SIZE(cm_bf533_devices));
 #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
        spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
index 241b5a20a36a78003e1128ce79f9af98e7ae89cd..08a7943949aef477b5fb2820c6d70d059ded82b3 100644 (file)
@@ -237,6 +237,25 @@ static struct platform_device bfin_uart_device = {
 };
 #endif
 
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+static struct resource bfin_sir_resources[] = {
+#ifdef CONFIG_BFIN_SIR0
+       {
+               .start = 0xFFC00400,
+               .end = 0xFFC004FF,
+               .flags = IORESOURCE_MEM,
+       },
+#endif
+};
+
+static struct platform_device bfin_sir_device = {
+       .name = "bfin_sir",
+       .id = 0,
+       .num_resources = ARRAY_SIZE(bfin_sir_resources),
+       .resource = bfin_sir_resources,
+};
+#endif
+
 #if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
 #define PATA_INT       55
 
@@ -352,6 +371,10 @@ static struct platform_device *ezkit_devices[] __initdata = {
        &bfin_uart_device,
 #endif
 
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+       &bfin_sir_device,
+#endif
+
 #if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
        &bfin_pata_device,
 #endif
@@ -369,7 +392,7 @@ static struct platform_device *ezkit_devices[] __initdata = {
 
 static int __init ezkit_init(void)
 {
-       printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
+       printk(KERN_INFO "%s(): registering device resources\n", __func__);
        platform_add_devices(ezkit_devices, ARRAY_SIZE(ezkit_devices));
 #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
        spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
index e359a0d6467fd846c66c68e9fce44c480b877582..82b1f6a60e3f7dc07859cc082b1e4fca75da5096 100644 (file)
@@ -84,7 +84,7 @@ static struct platform_device *generic_board_devices[] __initdata = {
 
 static int __init generic_board_init(void)
 {
-       printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
+       printk(KERN_INFO "%s(): registering device resources\n", __func__);
        return platform_add_devices(generic_board_devices, ARRAY_SIZE(generic_board_devices));
 }
 
diff --git a/arch/blackfin/mach-bf533/boards/ip0x.c b/arch/blackfin/mach-bf533/boards/ip0x.c
new file mode 100644 (file)
index 0000000..5864892
--- /dev/null
@@ -0,0 +1,303 @@
+/*
+ * File:         arch/blackfin/mach-bf533/ip0x.c
+ * Based on:     arch/blackfin/mach-bf533/bf1.c
+ * Based on:     arch/blackfin/mach-bf533/stamp.c
+ * Author:       Ivan Danov <idanov@gmail.com>
+ *               Modified for IP0X David Rowe
+ *
+ * Created:      2007
+ * Description:  Board info file for the IP04/IP08 boards, which
+ *               are derived from the BlackfinOne V2.0 boards.
+ *
+ * Modified:
+ *               COpyright 2007 David Rowe
+ *               Copyright 2006 Intratrade Ltd.
+ *               Copyright 2005 National ICT Australia (NICTA)
+ *               Copyright 2004-2006 Analog Devices 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
+#include <linux/usb/isp1362.h>
+#endif
+#include <asm/irq.h>
+#include <asm/bfin5xx_spi.h>
+
+/*
+ * Name the Board for the /proc/cpuinfo
+ */
+const char bfin_board_name[] = "IP04/IP08";
+
+/*
+ *  Driver needs to know address, irq and flag pin.
+ */
+#if defined(CONFIG_BFIN532_IP0X)
+#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
+
+#include <linux/dm9000.h>
+
+static struct resource dm9000_resource1[] = {
+       {
+               .start = 0x20100000,
+               .end   = 0x20100000 + 1,
+               .flags = IORESOURCE_MEM
+       },{
+               .start = 0x20100000 + 2,
+               .end   = 0x20100000 + 3,
+               .flags = IORESOURCE_MEM
+       },{
+               .start = IRQ_PF15,
+               .end   = IRQ_PF15,
+               .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE
+       }
+};
+
+static struct resource dm9000_resource2[] = {
+       {
+               .start = 0x20200000,
+               .end   = 0x20200000 + 1,
+               .flags = IORESOURCE_MEM
+       },{
+               .start = 0x20200000 + 2,
+               .end   = 0x20200000 + 3,
+               .flags = IORESOURCE_MEM
+       },{
+               .start = IRQ_PF14,
+               .end   = IRQ_PF14,
+               .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE
+       }
+};
+
+/*
+* for the moment we limit ourselves to 16bit IO until some
+* better IO routines can be written and tested
+*/
+static struct dm9000_plat_data dm9000_platdata1 = {
+       .flags          = DM9000_PLATF_16BITONLY,
+};
+
+static struct platform_device dm9000_device1 = {
+       .name           = "dm9000",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(dm9000_resource1),
+       .resource       = dm9000_resource1,
+       .dev            = {
+               .platform_data = &dm9000_platdata1,
+       }
+};
+
+static struct dm9000_plat_data dm9000_platdata2 = {
+       .flags          = DM9000_PLATF_16BITONLY,
+};
+
+static struct platform_device dm9000_device2 = {
+       .name           = "dm9000",
+       .id             = 1,
+       .num_resources  = ARRAY_SIZE(dm9000_resource2),
+       .resource       = dm9000_resource2,
+       .dev            = {
+               .platform_data = &dm9000_platdata2,
+       }
+};
+
+#endif
+#endif
+
+
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+/* all SPI peripherals info goes here */
+
+#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
+static struct bfin5xx_spi_chip spi_mmc_chip_info = {
+/*
+ * CPOL (Clock Polarity)
+ *  0 - Active high SCK
+ *  1 - Active low SCK
+ *  CPHA (Clock Phase) Selects transfer format and operation mode
+ *  0 - SCLK toggles from middle of the first data bit, slave select
+ *      pins controlled by hardware.
+ *  1 - SCLK toggles from beginning of first data bit, slave select
+ *      pins controller by user software.
+ *     .ctl_reg = 0x1c00,               *  CPOL=1,CPHA=1,Sandisk 1G work
+ * NO NO       .ctl_reg = 0x1800,               *  CPOL=1,CPHA=0
+ * NO NO       .ctl_reg = 0x1400,               *  CPOL=0,CPHA=1
+ */
+       .ctl_reg = 0x1000,              /* CPOL=0,CPHA=0,Sandisk 1G work */
+       .enable_dma = 0,                /* if 1 - block!!! */
+       .bits_per_word = 8,
+       .cs_change_per_word = 0,
+};
+#endif
+
+/* Notice: for blackfin, the speed_hz is the value of register
+ * SPI_BAUD, not the real baudrate */
+static struct spi_board_info bfin_spi_board_info[] __initdata = {
+#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
+       {
+               .modalias = "spi_mmc",
+               .max_speed_hz = 2,
+               .bus_num = 1,
+               .chip_select = CONFIG_SPI_MMC_CS_CHAN,
+               .platform_data = NULL,
+               .controller_data = &spi_mmc_chip_info,
+       },
+#endif
+};
+
+/* SPI controller data */
+static struct bfin5xx_spi_master spi_bfin_master_info = {
+       .num_chipselect = 8,
+       .enable_dma = 1,  /* master has the ability to do dma transfer */
+};
+
+static struct platform_device spi_bfin_master_device = {
+       .name = "bfin-spi-master",
+       .id = 1, /* Bus number */
+       .dev = {
+               .platform_data = &spi_bfin_master_info, /* Passed to driver */
+       },
+};
+#endif  /* spi master and devices */
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+static struct resource bfin_uart_resources[] = {
+       {
+               .start = 0xFFC00400,
+               .end = 0xFFC004FF,
+               .flags = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device bfin_uart_device = {
+       .name = "bfin-uart",
+       .id = 1,
+       .num_resources = ARRAY_SIZE(bfin_uart_resources),
+       .resource = bfin_uart_resources,
+};
+#endif
+
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+static struct resource bfin_sir_resources[] = {
+#ifdef CONFIG_BFIN_SIR0
+       {
+               .start = 0xFFC00400,
+               .end = 0xFFC004FF,
+               .flags = IORESOURCE_MEM,
+       },
+#endif
+};
+
+static struct platform_device bfin_sir_device = {
+       .name = "bfin_sir",
+       .id = 0,
+       .num_resources = ARRAY_SIZE(bfin_sir_resources),
+       .resource = bfin_sir_resources,
+};
+#endif
+
+#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
+static struct resource isp1362_hcd_resources[] = {
+       {
+               .start = 0x20300000,
+               .end   = 0x20300000 + 1,
+               .flags = IORESOURCE_MEM,
+       },{
+               .start = 0x20300000 + 2,
+               .end   = 0x20300000 + 3,
+               .flags = IORESOURCE_MEM,
+       },{
+               .start = IRQ_PF11,
+               .end   = IRQ_PF11,
+               .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+       },
+};
+
+static struct isp1362_platform_data isp1362_priv = {
+       .sel15Kres = 1,
+       .clknotstop = 0,
+       .oc_enable = 0,         /* external OC */
+       .int_act_high = 0,
+       .int_edge_triggered = 0,
+       .remote_wakeup_connected = 0,
+       .no_power_switching = 1,
+       .power_switching_mode = 0,
+};
+
+static struct platform_device isp1362_hcd_device = {
+       .name = "isp1362-hcd",
+       .id = 0,
+       .dev = {
+               .platform_data = &isp1362_priv,
+       },
+       .num_resources = ARRAY_SIZE(isp1362_hcd_resources),
+       .resource = isp1362_hcd_resources,
+};
+#endif
+
+
+static struct platform_device *ip0x_devices[] __initdata = {
+#if defined(CONFIG_BFIN532_IP0X)
+#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
+       &dm9000_device1,
+       &dm9000_device2,
+#endif
+#endif
+
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+       &spi_bfin_master_device,
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+       &bfin_uart_device,
+#endif
+
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+       &bfin_sir_device,
+#endif
+
+#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
+       &isp1362_hcd_device,
+#endif
+};
+
+static int __init ip0x_init(void)
+{
+       int i;
+
+       printk(KERN_INFO "%s(): registering device resources\n", __func__);
+       platform_add_devices(ip0x_devices, ARRAY_SIZE(ip0x_devices));
+
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+       for (i = 0; i < ARRAY_SIZE(bfin_spi_board_info); ++i) {
+               int j = 1 << bfin_spi_board_info[i].chip_select;
+               /* set spi cs to 1 */
+               bfin_write_FIO_DIR(bfin_read_FIO_DIR() | j);
+               bfin_write_FIO_FLAG_S(j);
+       }
+       spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
+#endif
+
+       return 0;
+}
+
+arch_initcall(ip0x_init);
index b2ac4816ae62d585633de456c74e5a07dedee751..fddce32901a2249e31af17a17bacb3afa768667d 100644 (file)
@@ -40,6 +40,7 @@
 #endif
 #include <linux/ata_platform.h>
 #include <linux/irq.h>
+#include <linux/i2c.h>
 #include <asm/dma.h>
 #include <asm/bfin5xx_spi.h>
 #include <asm/reboot.h>
@@ -109,6 +110,7 @@ static struct platform_device net2272_bfin_device = {
 };
 #endif
 
+#if defined(CONFIG_MTD_BF5xx) || defined(CONFIG_MTD_BF5xx_MODULE)
 static struct mtd_partition stamp_partitions[] = {
        {
                .name   = "Bootloader",
@@ -152,6 +154,7 @@ static struct platform_device stamp_flash_device = {
        .num_resources = ARRAY_SIZE(stamp_flash_resource),
        .resource      = stamp_flash_resource,
 };
+#endif
 
 #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
 /* all SPI peripherals info goes here */
@@ -367,6 +370,25 @@ static struct platform_device bfin_uart_device = {
 };
 #endif
 
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+static struct resource bfin_sir_resources[] = {
+#ifdef CONFIG_BFIN_SIR0
+       {
+               .start = 0xFFC00400,
+               .end = 0xFFC004FF,
+               .flags = IORESOURCE_MEM,
+       },
+#endif
+};
+
+static struct platform_device bfin_sir_device = {
+       .name = "bfin_sir",
+       .id = 0,
+       .num_resources = ARRAY_SIZE(bfin_sir_resources),
+       .resource = bfin_sir_resources,
+};
+#endif
+
 #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
 static struct platform_device bfin_sport0_uart_device = {
        .name = "bfin-sport-uart",
@@ -472,6 +494,31 @@ static struct platform_device i2c_gpio_device = {
 };
 #endif
 
+#ifdef CONFIG_I2C_BOARDINFO
+static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
+#if defined(CONFIG_JOYSTICK_AD7142) || defined(CONFIG_JOYSTICK_AD7142_MODULE)
+       {
+               I2C_BOARD_INFO("ad7142_joystick", 0x2C),
+               .type = "ad7142_joystick",
+               .irq = 39,
+       },
+#endif
+#if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
+       {
+               I2C_BOARD_INFO("pcf8574_lcd", 0x22),
+               .type = "pcf8574_lcd",
+       },
+#endif
+#if defined(CONFIG_TWI_KEYPAD) || defined(CONFIG_TWI_KEYPAD_MODULE)
+       {
+               I2C_BOARD_INFO("pcf8574_keypad", 0x27),
+               .type = "pcf8574_keypad",
+               .irq = 39,
+       },
+#endif
+};
+#endif
+
 static struct platform_device *stamp_devices[] __initdata = {
 #if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
        &rtc_device,
@@ -497,6 +544,10 @@ static struct platform_device *stamp_devices[] __initdata = {
        &bfin_uart_device,
 #endif
 
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+       &bfin_sir_device,
+#endif
+
 #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
        &bfin_sport0_uart_device,
        &bfin_sport1_uart_device,
@@ -515,14 +566,23 @@ static struct platform_device *stamp_devices[] __initdata = {
 #endif
 
        &bfin_gpios_device,
+
+#if defined(CONFIG_MTD_BF5xx) || defined(CONFIG_MTD_BF5xx_MODULE)
        &stamp_flash_device,
+#endif
 };
 
 static int __init stamp_init(void)
 {
        int ret;
 
-       printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
+       printk(KERN_INFO "%s(): registering device resources\n", __func__);
+
+#ifdef CONFIG_I2C_BOARDINFO
+       i2c_register_board_info(0, bfin_i2c_board_info,
+                               ARRAY_SIZE(bfin_i2c_board_info));
+#endif
+
        ret = platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
        if (ret < 0)
                return ret;
diff --git a/arch/blackfin/mach-bf533/cpu.c b/arch/blackfin/mach-bf533/cpu.c
deleted file mode 100644 (file)
index b7a0e0f..0000000
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * File:         arch/blackfin/mach-bf533/cpu.c
- * Based on:
- * Author:       michael.kang@analog.com
- *
- * Created:
- * Description:  clock scaling for the bf533
- *
- * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/cpufreq.h>
-#include <asm/dpmc.h>
-#include <linux/fs.h>
-#include <asm/bfin-global.h>
-
-/* CONFIG_CLKIN_HZ=11059200 */
-#define VCO5 (CONFIG_CLKIN_HZ*45)      /*497664000 */
-#define VCO4 (CONFIG_CLKIN_HZ*36)      /*398131200 */
-#define VCO3 (CONFIG_CLKIN_HZ*27)      /*298598400 */
-#define VCO2 (CONFIG_CLKIN_HZ*18)      /*199065600 */
-#define VCO1 (CONFIG_CLKIN_HZ*9)       /*99532800 */
-#define VCO(x) VCO##x
-
-#define FREQ(x) {VCO(x),VCO(x)/4},{VCO(x),VCO(x)/2},{VCO(x),VCO(x)}
-/* frequency */
-static struct cpufreq_frequency_table bf533_freq_table[] = {
-       FREQ(1),
-       FREQ(3),
-       {VCO4, VCO4 / 2}, {VCO4, VCO4},
-       FREQ(5),
-       {0, CPUFREQ_TABLE_END},
-};
-
-/*
- * dpmc_fops->ioctl()
- * static int dpmc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
- */
-static int bf533_getfreq(unsigned int cpu)
-{
-       unsigned long cclk_mhz, vco_mhz;
-
-       /* The driver only support single cpu */
-       if (cpu == 0)
-               dpmc_fops.ioctl(NULL, NULL, IOCTL_GET_CORECLOCK, &cclk_mhz);
-       else
-               cclk_mhz = -1;
-       return cclk_mhz;
-}
-
-static int bf533_target(struct cpufreq_policy *policy,
-                           unsigned int target_freq, unsigned int relation)
-{
-       unsigned long cclk_mhz;
-       unsigned long vco_mhz;
-       unsigned long flags;
-       unsigned int index, vco_index;
-       int i;
-
-       struct cpufreq_freqs freqs;
-       if (cpufreq_frequency_table_target(policy, bf533_freq_table, target_freq, relation, &index))
-               return -EINVAL;
-       cclk_mhz = bf533_freq_table[index].frequency;
-       vco_mhz = bf533_freq_table[index].index;
-
-       dpmc_fops.ioctl(NULL, NULL, IOCTL_CHANGE_FREQUENCY, &vco_mhz);
-       freqs.old = bf533_getfreq(0);
-       freqs.new = cclk_mhz;
-       freqs.cpu = 0;
-
-       pr_debug("cclk begin change to cclk %d,vco=%d,index=%d,target=%d,oldfreq=%d\n",
-                cclk_mhz, vco_mhz, index, target_freq, freqs.old);
-
-       cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-       local_irq_save(flags);
-       dpmc_fops.ioctl(NULL, NULL, IOCTL_SET_CCLK, &cclk_mhz);
-       local_irq_restore(flags);
-       cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-
-       vco_mhz = get_vco();
-       cclk_mhz = get_cclk();
-       return 0;
-}
-
-/* make sure that only the "userspace" governor is run -- anything else wouldn't make sense on
- * this platform, anyway.
- */
-static int bf533_verify_speed(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, &bf533_freq_table);
-}
-
-static int __init __bf533_cpu_init(struct cpufreq_policy *policy)
-{
-       int result;
-
-       if (policy->cpu != 0)
-               return -EINVAL;
-
-       policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
-       /*Now ,only support one cpu */
-       policy->cur = bf533_getfreq(0);
-       cpufreq_frequency_table_get_attr(bf533_freq_table, policy->cpu);
-       return cpufreq_frequency_table_cpuinfo(policy, bf533_freq_table);
-}
-
-static struct freq_attr *bf533_freq_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
-static struct cpufreq_driver bf533_driver = {
-       .verify = bf533_verify_speed,
-       .target = bf533_target,
-       .get = bf533_getfreq,
-       .init = __bf533_cpu_init,
-       .name = "bf533",
-       .owner = THIS_MODULE,
-       .attr = bf533_freq_attr,
-};
-
-static int __init bf533_cpu_init(void)
-{
-       return cpufreq_register_driver(&bf533_driver);
-}
-
-static void __exit bf533_cpu_exit(void)
-{
-       cpufreq_unregister_driver(&bf533_driver);
-}
-
-MODULE_AUTHOR("Mickael Kang");
-MODULE_DESCRIPTION("cpufreq driver for BF533 CPU");
-MODULE_LICENSE("GPL");
-
-module_init(bf533_cpu_init);
-module_exit(bf533_cpu_exit);
index 6c909cf4f7bf41901a905be26051b1cda657f416..28655c1cb7dc52ecdbc24bca24f34f58ce63e243 100644 (file)
  * to the Free Software Foundation, Inc.,
  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
+#include <linux/module.h>
+
 #include <asm/blackfin.h>
 #include <asm/dma.h>
 
-struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
+struct dma_register *dma_io_base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
        (struct dma_register *) DMA0_NEXT_DESC_PTR,
        (struct dma_register *) DMA1_NEXT_DESC_PTR,
        (struct dma_register *) DMA2_NEXT_DESC_PTR,
@@ -43,6 +45,7 @@ struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
        (struct dma_register *) MDMA_D1_NEXT_DESC_PTR,
        (struct dma_register *) MDMA_S1_NEXT_DESC_PTR,
 };
+EXPORT_SYMBOL(dma_io_base_addr);
 
 int channel2irq(unsigned int channel)
 {
index 1ded945a6fa0212973a122b24d022bd79751cd2c..1295deac00a48379c0bdd2bfb951c56cde463f69 100644 (file)
@@ -36,9 +36,6 @@
 #include <asm/mach/mem_init.h>
 #endif
 
-.global __rambase
-.global __ramstart
-.global __ramend
 .extern ___bss_stop
 .extern ___bss_start
 .extern _bf53x_relocate_l1_mem
@@ -151,26 +148,26 @@ ENTRY(__start)
 
        /* Initialise UART - when booting from u-boot, the UART is not disabled
         * so if we dont initalize here, our serial console gets hosed */
-       p0.h = hi(UART_LCR);
-       p0.l = lo(UART_LCR);
+       p0.h = hi(BFIN_UART_LCR);
+       p0.l = lo(BFIN_UART_LCR);
        r0 = 0x0(Z);
        w[p0] = r0.L;   /* To enable DLL writes */
        ssync;
 
-       p0.h = hi(UART_DLL);
-       p0.l = lo(UART_DLL);
+       p0.h = hi(BFIN_UART_DLL);
+       p0.l = lo(BFIN_UART_DLL);
        r0 = 0x0(Z);
        w[p0] = r0.L;
        ssync;
 
-       p0.h = hi(UART_DLH);
-       p0.l = lo(UART_DLH);
+       p0.h = hi(BFIN_UART_DLH);
+       p0.l = lo(BFIN_UART_DLH);
        r0 = 0x00(Z);
        w[p0] = r0.L;
        ssync;
 
-       p0.h = hi(UART_GCTL);
-       p0.l = lo(UART_GCTL);
+       p0.h = hi(BFIN_UART_GCTL);
+       p0.l = lo(BFIN_UART_GCTL);
        r0 = 0x0(Z);
        w[p0] = r0.L;   /* To enable UART clock */
        ssync;
@@ -431,18 +428,3 @@ ENTRY(_start_dma_code)
        RTS;
 ENDPROC(_start_dma_code)
 #endif /* CONFIG_BFIN_KERNEL_CLOCK */
-
-.data
-
-/*
- * Set up the usable of RAM stuff. Size of RAM is determined then
- * an initial stack set up at the end.
- */
-
-.align 4
-__rambase:
-.long   0
-__ramstart:
-.long   0
-__ramend:
-.long   0
index 7e7c9c8ac5b263ac02f3aaa58ff349ed3060ee55..68e5478e95a9789bc2d5e0398b0f78a16f4da9de 100644 (file)
@@ -5,5 +5,3 @@
 extra-y := head.o
 
 obj-y := ints-priority.o dma.o
-
-obj-$(CONFIG_CPU_FREQ)   += cpu.o
index f7c1f964f13b1a42d38bd14e81dfe5f4c70ca12c..d8a23cd9b9ed9f860ae22ccfba85ff1d2c4b175f 100644 (file)
@@ -325,6 +325,54 @@ static struct platform_device bfin_uart_device = {
 };
 #endif
 
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+static struct resource bfin_sir_resources[] = {
+#ifdef CONFIG_BFIN_SIR0
+       {
+               .start = 0xFFC00400,
+               .end = 0xFFC004FF,
+               .flags = IORESOURCE_MEM,
+       },
+#endif
+#ifdef CONFIG_BFIN_SIR1
+       {
+               .start = 0xFFC02000,
+               .end = 0xFFC020FF,
+               .flags = IORESOURCE_MEM,
+       },
+#endif
+};
+
+static struct platform_device bfin_sir_device = {
+       .name = "bfin_sir",
+       .id = 0,
+       .num_resources = ARRAY_SIZE(bfin_sir_resources),
+       .resource = bfin_sir_resources,
+};
+#endif
+
+#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+static struct resource bfin_twi0_resource[] = {
+       [0] = {
+               .start = TWI0_REGBASE,
+               .end   = TWI0_REGBASE,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = IRQ_TWI,
+               .end   = IRQ_TWI,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device i2c_bfin_twi_device = {
+       .name = "i2c-bfin-twi",
+       .id = 0,
+       .num_resources = ARRAY_SIZE(bfin_twi0_resource),
+       .resource = bfin_twi0_resource,
+};
+#endif
+
 #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
 static struct platform_device bfin_sport0_uart_device = {
        .name = "bfin-sport-uart",
@@ -393,6 +441,14 @@ static struct platform_device *cm_bf537_devices[] __initdata = {
        &bfin_uart_device,
 #endif
 
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+       &bfin_sir_device,
+#endif
+
+#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+       &i2c_bfin_twi_device,
+#endif
+
 #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
        &bfin_sport0_uart_device,
        &bfin_sport1_uart_device,
@@ -425,7 +481,7 @@ static struct platform_device *cm_bf537_devices[] __initdata = {
 
 static int __init cm_bf537_init(void)
 {
-       printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
+       printk(KERN_INFO "%s(): registering device resources\n", __func__);
        platform_add_devices(cm_bf537_devices, ARRAY_SIZE(cm_bf537_devices));
 #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
        spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
index c95395ba7bfa97c09b948fe9475709ef3da1c317..7d250828dad82b7ae8b15bda211d1740fd5b586c 100644 (file)
@@ -90,7 +90,7 @@ int __init bfin_isp1761_init(void)
 {
        unsigned int num_devices = ARRAY_SIZE(bfin_isp1761_devices);
 
-       printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
+       printk(KERN_INFO "%s(): registering device resources\n", __func__);
        set_irq_type(ISP1761_IRQ, IRQF_TRIGGER_FALLING);
 
        return platform_add_devices(bfin_isp1761_devices, num_devices);
@@ -554,6 +554,32 @@ static struct platform_device bfin_uart_device = {
 };
 #endif
 
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+static struct resource bfin_sir_resources[] = {
+#ifdef CONFIG_BFIN_SIR0
+       {
+               .start = 0xFFC00400,
+               .end = 0xFFC004FF,
+               .flags = IORESOURCE_MEM,
+       },
+#endif
+#ifdef CONFIG_BFIN_SIR1
+       {
+               .start = 0xFFC02000,
+               .end = 0xFFC020FF,
+               .flags = IORESOURCE_MEM,
+       },
+#endif
+};
+
+static struct platform_device bfin_sir_device = {
+       .name = "bfin_sir",
+       .id = 0,
+       .num_resources = ARRAY_SIZE(bfin_sir_resources),
+       .resource = bfin_sir_resources,
+};
+#endif
+
 #if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
 static struct resource bfin_twi0_resource[] = {
        [0] = {
@@ -674,6 +700,10 @@ static struct platform_device *stamp_devices[] __initdata = {
        &bfin_uart_device,
 #endif
 
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+       &bfin_sir_device,
+#endif
+
 #if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
        &i2c_bfin_twi_device,
 #endif
@@ -690,7 +720,7 @@ static struct platform_device *stamp_devices[] __initdata = {
 
 static int __init stamp_init(void)
 {
-       printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
+       printk(KERN_INFO "%s(): registering device resources\n", __func__);
        platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
 #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
        spi_register_board_info(bfin_spi_board_info,
index d71e0be339212c752a14aeea214ee7d1b72f654f..18ddf7a520052ea7a57e506ffd0fcde9d98d1c64 100644 (file)
@@ -8,12 +8,12 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/flash.h>
 #if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
-#include <linux/usb_isp1362.h>
+#include <linux/usb/isp1362.h>
 #endif
 #include <linux/ata_platform.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
-#include <linux/usb_sl811.h>
+#include <linux/usb/sl811.h>
 #include <asm/dma.h>
 #include <asm/bfin5xx_spi.h>
 #include <asm/reboot.h>
@@ -225,6 +225,32 @@ static struct platform_device bfin_uart_device = {
 };
 #endif
 
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+static struct resource bfin_sir_resources[] = {
+#ifdef CONFIG_BFIN_SIR0
+       {
+               .start = 0xFFC00400,
+               .end = 0xFFC004FF,
+               .flags = IORESOURCE_MEM,
+       },
+#endif
+#ifdef CONFIG_BFIN_SIR1
+       {
+               .start = 0xFFC02000,
+               .end = 0xFFC020FF,
+               .flags = IORESOURCE_MEM,
+       },
+#endif
+};
+
+static struct platform_device bfin_sir_device = {
+       .name = "bfin_sir",
+       .id = 0,
+       .num_resources = ARRAY_SIZE(bfin_sir_resources),
+       .resource = bfin_sir_resources,
+};
+#endif
+
 #if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
 static struct resource bfin_twi0_resource[] = {
        [0] = {
@@ -284,6 +310,10 @@ static struct platform_device *minotaur_devices[] __initdata = {
        &bfin_uart_device,
 #endif
 
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+       &bfin_sir_device,
+#endif
+
 #if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
        &i2c_bfin_twi_device,
 #endif
@@ -297,7 +327,7 @@ static struct platform_device *minotaur_devices[] __initdata = {
 
 static int __init minotaur_init(void)
 {
-       printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
+       printk(KERN_INFO "%s(): registering device resources\n", __func__);
        platform_add_devices(minotaur_devices, ARRAY_SIZE(minotaur_devices));
 #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
        spi_register_board_info(bfin_spi_board_info,
index 509a8a236fd05cafe1e29b9b8ad25db5ca11788d..51c3bab14a69facc7336835375699d55e6eedc20 100644 (file)
@@ -452,6 +452,31 @@ static struct platform_device bfin_uart_device = {
 };
 #endif
 
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+static struct resource bfin_sir_resources[] = {
+#ifdef CONFIG_BFIN_SIR0
+       {
+               .start = 0xFFC00400,
+               .end = 0xFFC004FF,
+               .flags = IORESOURCE_MEM,
+       },
+#endif
+#ifdef CONFIG_BFIN_SIR1
+       {
+               .start = 0xFFC02000,
+               .end = 0xFFC020FF,
+               .flags = IORESOURCE_MEM,
+       },
+#endif
+};
+
+static struct platform_device bfin_sir_device = {
+       .name = "bfin_sir",
+       .id = 0,
+       .num_resources = ARRAY_SIZE(bfin_sir_resources),
+       .resource = bfin_sir_resources,
+};
+#endif
 
 static struct platform_device *stamp_devices[] __initdata = {
 #if defined(CONFIG_BFIN_CFPCMCIA) || defined(CONFIG_BFIN_CFPCMCIA_MODULE)
@@ -493,11 +518,15 @@ static struct platform_device *stamp_devices[] __initdata = {
 #if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
        &bfin_uart_device,
 #endif
+
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+       &bfin_sir_device,
+#endif
 };
 
 static int __init stamp_init(void)
 {
-       printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
+       printk(KERN_INFO "%s(): registering device resources\n", __func__);
        platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
 #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
        spi_register_board_info(bfin_spi_board_info,
index ea83148993da1f4dd8266d0d04e2e2744b984b56..0cec14b1ef5c0ee45345dcdcd05303e30857e9ea 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/ata_platform.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
+#include <linux/i2c.h>
 #include <linux/usb/sl811.h>
 #include <asm/dma.h>
 #include <asm/bfin5xx_spi.h>
@@ -90,7 +91,7 @@ int __init bfin_isp1761_init(void)
 {
        unsigned int num_devices = ARRAY_SIZE(bfin_isp1761_devices);
 
-       printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
+       printk(KERN_INFO "%s(): registering device resources\n", __func__);
        set_irq_type(ISP1761_IRQ, IRQF_TRIGGER_FALLING);
 
        return platform_add_devices(bfin_isp1761_devices, num_devices);
@@ -353,6 +354,7 @@ static struct platform_device net2272_bfin_device = {
 };
 #endif
 
+#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
 static struct mtd_partition stamp_partitions[] = {
        {
                .name       = "Bootloader",
@@ -395,6 +397,7 @@ static struct platform_device stamp_flash_device = {
        .num_resources = 1,
        .resource      = &stamp_flash_resource,
 };
+#endif
 
 #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
 /* all SPI peripherals info goes here */
@@ -500,6 +503,15 @@ static struct bfin5xx_spi_chip spidev_chip_info = {
 };
 #endif
 
+#if defined(CONFIG_MTD_DATAFLASH) \
+       || defined(CONFIG_MTD_DATAFLASH_MODULE)
+/* DataFlash chip */
+static struct bfin5xx_spi_chip data_flash_chip_info = {
+       .enable_dma = 0,         /* use dma transfer with this chip*/
+       .bits_per_word = 8,
+};
+#endif
+
 static struct spi_board_info bfin_spi_board_info[] __initdata = {
 #if defined(CONFIG_MTD_M25P80) \
        || defined(CONFIG_MTD_M25P80_MODULE)
@@ -514,7 +526,17 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
                .mode = SPI_MODE_3,
        },
 #endif
-
+#if defined(CONFIG_MTD_DATAFLASH) \
+       || defined(CONFIG_MTD_DATAFLASH_MODULE)
+       {       /* DataFlash chip */
+               .modalias = "mtd_dataflash",
+               .max_speed_hz = 25000000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 0, /* Framework bus number */
+               .chip_select = 1, /* Framework chip select. On STAMP537 it is SPISSEL1*/
+               .controller_data = &data_flash_chip_info,
+               .mode = SPI_MODE_3,
+       },
+#endif
 #if defined(CONFIG_SPI_ADC_BF533) \
        || defined(CONFIG_SPI_ADC_BF533_MODULE)
        {
@@ -676,6 +698,32 @@ static struct platform_device bfin_uart_device = {
 };
 #endif
 
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+static struct resource bfin_sir_resources[] = {
+#ifdef CONFIG_BFIN_SIR0
+       {
+               .start = 0xFFC00400,
+               .end = 0xFFC004FF,
+               .flags = IORESOURCE_MEM,
+       },
+#endif
+#ifdef CONFIG_BFIN_SIR1
+       {
+               .start = 0xFFC02000,
+               .end = 0xFFC020FF,
+               .flags = IORESOURCE_MEM,
+       },
+#endif
+};
+
+static struct platform_device bfin_sir_device = {
+       .name = "bfin_sir",
+       .id = 0,
+       .num_resources = ARRAY_SIZE(bfin_sir_resources),
+       .resource = bfin_sir_resources,
+};
+#endif
+
 #if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
 static struct resource bfin_twi0_resource[] = {
        [0] = {
@@ -698,6 +746,31 @@ static struct platform_device i2c_bfin_twi_device = {
 };
 #endif
 
+#ifdef CONFIG_I2C_BOARDINFO
+static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
+#if defined(CONFIG_JOYSTICK_AD7142) || defined(CONFIG_JOYSTICK_AD7142_MODULE)
+       {
+               I2C_BOARD_INFO("ad7142_joystick", 0x2C),
+               .type = "ad7142_joystick",
+               .irq = 55,
+       },
+#endif
+#if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
+       {
+               I2C_BOARD_INFO("pcf8574_lcd", 0x22),
+               .type = "pcf8574_lcd",
+       },
+#endif
+#if defined(CONFIG_TWI_KEYPAD) || defined(CONFIG_TWI_KEYPAD_MODULE)
+       {
+               I2C_BOARD_INFO("pcf8574_keypad", 0x27),
+               .type = "pcf8574_keypad",
+               .irq = 72,
+       },
+#endif
+};
+#endif
+
 #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
 static struct platform_device bfin_sport0_uart_device = {
        .name = "bfin-sport-uart",
@@ -800,6 +873,10 @@ static struct platform_device *stamp_devices[] __initdata = {
        &bfin_uart_device,
 #endif
 
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+       &bfin_sir_device,
+#endif
+
 #if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
        &i2c_bfin_twi_device,
 #endif
@@ -818,12 +895,21 @@ static struct platform_device *stamp_devices[] __initdata = {
 #endif
 
        &bfin_gpios_device,
+
+#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
        &stamp_flash_device,
+#endif
 };
 
 static int __init stamp_init(void)
 {
-       printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
+       printk(KERN_INFO "%s(): registering device resources\n", __func__);
+
+#ifdef CONFIG_I2C_BOARDINFO
+       i2c_register_board_info(0, bfin_i2c_board_info,
+                               ARRAY_SIZE(bfin_i2c_board_info));
+#endif
+
        platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
 #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
        spi_register_board_info(bfin_spi_board_info,
@@ -833,6 +919,7 @@ static int __init stamp_init(void)
 #if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
        irq_desc[PATA_INT].status |= IRQ_NOAUTOEN;
 #endif
+
        return 0;
 }
 
diff --git a/arch/blackfin/mach-bf537/cpu.c b/arch/blackfin/mach-bf537/cpu.c
deleted file mode 100644 (file)
index 0442c4c..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * File:         arch/blackfin/mach-bf537/cpu.c
- * Based on:
- * Author:       michael.kang@analog.com
- *
- * Created:
- * Description:  clock scaling for the bf537
- *
- * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/cpufreq.h>
-#include <asm/dpmc.h>
-#include <linux/fs.h>
-#include <asm/bfin-global.h>
-
-/* CONFIG_CLKIN_HZ=11059200 */
-#define VCO5 (CONFIG_CLKIN_HZ*45)      /*497664000 */
-#define VCO4 (CONFIG_CLKIN_HZ*36)      /*398131200 */
-#define VCO3 (CONFIG_CLKIN_HZ*27)      /*298598400 */
-#define VCO2 (CONFIG_CLKIN_HZ*18)      /*199065600 */
-#define VCO1 (CONFIG_CLKIN_HZ*9)       /*99532800 */
-#define VCO(x) VCO##x
-
-#define MFREQ(x) {VCO(x),VCO(x)/4},{VCO(x),VCO(x)/2},{VCO(x),VCO(x)}
-/* frequency */
-static struct cpufreq_frequency_table bf537_freq_table[] = {
-       MFREQ(1),
-       MFREQ(3),
-       {VCO4, VCO4 / 2}, {VCO4, VCO4},
-       MFREQ(5),
-       {0, CPUFREQ_TABLE_END},
-};
-
-/*
- * dpmc_fops->ioctl()
- * static int dpmc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
- */
-static int bf537_getfreq(unsigned int cpu)
-{
-       unsigned long cclk_mhz;
-
-       /* The driver only support single cpu */
-       if (cpu == 0)
-               dpmc_fops.ioctl(NULL, NULL, IOCTL_GET_CORECLOCK, &cclk_mhz);
-       else
-               cclk_mhz = -1;
-
-       return cclk_mhz;
-}
-
-static int bf537_target(struct cpufreq_policy *policy,
-                           unsigned int target_freq, unsigned int relation)
-{
-       unsigned long cclk_mhz;
-       unsigned long vco_mhz;
-       unsigned long flags;
-       unsigned int index;
-       struct cpufreq_freqs freqs;
-
-       if (cpufreq_frequency_table_target(policy, bf537_freq_table, target_freq, relation, &index))
-               return -EINVAL;
-
-       cclk_mhz = bf537_freq_table[index].frequency;
-       vco_mhz = bf537_freq_table[index].index;
-
-       dpmc_fops.ioctl(NULL, NULL, IOCTL_CHANGE_FREQUENCY, &vco_mhz);
-       freqs.old = bf537_getfreq(0);
-       freqs.new = cclk_mhz;
-       freqs.cpu = 0;
-
-       pr_debug("cclk begin change to cclk %d,vco=%d,index=%d,target=%d,oldfreq=%d\n",
-                cclk_mhz, vco_mhz, index, target_freq, freqs.old);
-
-       cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-       local_irq_save(flags);
-       dpmc_fops.ioctl(NULL, NULL, IOCTL_SET_CCLK, &cclk_mhz);
-       local_irq_restore(flags);
-       cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-
-       vco_mhz = get_vco();
-       cclk_mhz = get_cclk();
-       return 0;
-}
-
-/* make sure that only the "userspace" governor is run -- anything else wouldn't make sense on
- * this platform, anyway.
- */
-static int bf537_verify_speed(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, &bf537_freq_table);
-}
-
-static int __init __bf537_cpu_init(struct cpufreq_policy *policy)
-{
-       if (policy->cpu != 0)
-               return -EINVAL;
-
-       policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
-
-       policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
-       /*Now ,only support one cpu */
-       policy->cur = bf537_getfreq(0);
-       cpufreq_frequency_table_get_attr(bf537_freq_table, policy->cpu);
-       return cpufreq_frequency_table_cpuinfo(policy, bf537_freq_table);
-}
-
-static struct freq_attr *bf537_freq_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
-static struct cpufreq_driver bf537_driver = {
-       .verify = bf537_verify_speed,
-       .target = bf537_target,
-       .get = bf537_getfreq,
-       .init = __bf537_cpu_init,
-       .name = "bf537",
-       .owner = THIS_MODULE,
-       .attr = bf537_freq_attr,
-};
-
-static int __init bf537_cpu_init(void)
-{
-       return cpufreq_register_driver(&bf537_driver);
-}
-
-static void __exit bf537_cpu_exit(void)
-{
-       cpufreq_unregister_driver(&bf537_driver);
-}
-
-MODULE_AUTHOR("Mickael Kang");
-MODULE_DESCRIPTION("cpufreq driver for BF537 CPU");
-MODULE_LICENSE("GPL");
-
-module_init(bf537_cpu_init);
-module_exit(bf537_cpu_exit);
index 706cb97b0265bb93d8645de795becff99b2c914a..4edb363ff99c041884501d6ae225abcb3397bd8d 100644 (file)
  * to the Free Software Foundation, Inc.,
  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
+#include <linux/module.h>
+
 #include <asm/blackfin.h>
 #include <asm/dma.h>
 
-struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
+struct dma_register *dma_io_base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
        (struct dma_register *) DMA0_NEXT_DESC_PTR,
        (struct dma_register *) DMA1_NEXT_DESC_PTR,
        (struct dma_register *) DMA2_NEXT_DESC_PTR,
@@ -47,6 +49,7 @@ struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
        (struct dma_register *) MDMA_D1_NEXT_DESC_PTR,
        (struct dma_register *) MDMA_S1_NEXT_DESC_PTR,
 };
+EXPORT_SYMBOL(dma_io_base_addr);
 
 int channel2irq(unsigned int channel)
 {
index 3014fe8dd1556bf717421422873e1f7ead28ab04..48cd58a410a0b75e8a55b02e0a87b2566701bdc8 100644 (file)
@@ -37,9 +37,6 @@
 #include <asm/mach/mem_init.h>
 #endif
 
-.global __rambase
-.global __ramstart
-.global __ramend
 .extern ___bss_stop
 .extern ___bss_start
 .extern _bf53x_relocate_l1_mem
@@ -180,40 +177,28 @@ ENTRY(__start)
        SSYNC;
 #endif
 
-#ifdef CONFIG_BF537_PORT_H
-       p0.h = hi(PORTH_FER);
-       p0.l = lo(PORTH_FER);
-       R0.L = W[P0]; /* Read */
-       SSYNC;
-       R0 = 0x0000;
-       W[P0] = R0.L; /* Write */
-       SSYNC;
-       W[P0] = R0.L; /* Disable peripheral function of PORTH */
-       SSYNC;
-#endif
-
        /* Initialise UART - when booting from u-boot, the UART is not disabled
         * so if we dont initalize here, our serial console gets hosed */
-       p0.h = hi(UART_LCR);
-       p0.l = lo(UART_LCR);
+       p0.h = hi(BFIN_UART_LCR);
+       p0.l = lo(BFIN_UART_LCR);
        r0 = 0x0(Z);
        w[p0] = r0.L;   /* To enable DLL writes */
        ssync;
 
-       p0.h = hi(UART_DLL);
-       p0.l = lo(UART_DLL);
+       p0.h = hi(BFIN_UART_DLL);
+       p0.l = lo(BFIN_UART_DLL);
        r0 = 0x0(Z);
        w[p0] = r0.L;
        ssync;
 
-       p0.h = hi(UART_DLH);
-       p0.l = lo(UART_DLH);
+       p0.h = hi(BFIN_UART_DLH);
+       p0.l = lo(BFIN_UART_DLH);
        r0 = 0x00(Z);
        w[p0] = r0.L;
        ssync;
 
-       p0.h = hi(UART_GCTL);
-       p0.l = lo(UART_GCTL);
+       p0.h = hi(BFIN_UART_GCTL);
+       p0.l = lo(BFIN_UART_GCTL);
        r0 = 0x0(Z);
        w[p0] = r0.L;   /* To enable UART clock */
        ssync;
@@ -483,18 +468,3 @@ ENTRY(_start_dma_code)
        RTS;
 ENDPROC(_start_dma_code)
 #endif /* CONFIG_BFIN_KERNEL_CLOCK */
-
-.data
-
-/*
- * Set up the usable of RAM stuff. Size of RAM is determined then
- * an initial stack set up at the end.
- */
-
-.align 4
-__rambase:
-.long   0
-__ramstart:
-.long   0
-__ramend:
-.long   0
index 7e7c9c8ac5b263ac02f3aaa58ff349ed3060ee55..68e5478e95a9789bc2d5e0398b0f78a16f4da9de 100644 (file)
@@ -5,5 +5,3 @@
 extra-y := head.o
 
 obj-y := ints-priority.o dma.o
-
-obj-$(CONFIG_CPU_FREQ)   += cpu.o
index 057129064037f741692f41f93a09cd0d7443c455..d38e52671853634a201d743f3f845a899effcc2e 100644 (file)
@@ -8,5 +8,11 @@ config BFIN548_EZKIT
        bool "BF548-EZKIT"
        help
          BFIN548-EZKIT board support.
+         
+config BFIN548_BLUETECHNIX_CM
+       bool "Bluetechnix CM-BF548"
+       depends on (BF548)
+       help
+         CM-BF548 support for DEV-Board.         
 
 endchoice
index a444cc739578bc8f286a4b06ee7fb74a79ae4d59..eed161dd7845de6c4462f958f43e2ac409aacb12 100644 (file)
@@ -3,3 +3,4 @@
 #
 
 obj-$(CONFIG_BFIN548_EZKIT)            += ezkit.o led.o
+obj-$(CONFIG_BFIN548_BLUETECHNIX_CM)   += cm_bf548.o
diff --git a/arch/blackfin/mach-bf548/boards/cm_bf548.c b/arch/blackfin/mach-bf548/boards/cm_bf548.c
new file mode 100644 (file)
index 0000000..e3e8479
--- /dev/null
@@ -0,0 +1,664 @@
+/*
+ * File:         arch/blackfin/mach-bf548/boards/cm_bf548.c
+ * Based on:     arch/blackfin/mach-bf537/boards/ezkit.c
+ * Author:       Aidan Williams <aidan@nicta.com.au>
+ *
+ * Created:
+ * Description:
+ *
+ * Modified:
+ *               Copyright 2005 National ICT Australia (NICTA)
+ *               Copyright 2004-2008 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/usb/musb.h>
+#include <asm/bfin5xx_spi.h>
+#include <asm/cplb.h>
+#include <asm/dma.h>
+#include <asm/gpio.h>
+#include <asm/nand.h>
+#include <asm/portmux.h>
+#include <asm/mach/bf54x_keys.h>
+#include <linux/input.h>
+#include <linux/spi/ad7877.h>
+
+/*
+ * Name the Board for the /proc/cpuinfo
+ */
+const char bfin_board_name[] = "Bluetechnix CM-BF548";
+
+/*
+ *  Driver needs to know address, irq and flag pin.
+ */
+
+#if defined(CONFIG_FB_BF54X_LQ043) || defined(CONFIG_FB_BF54X_LQ043_MODULE)
+
+#include <asm/mach/bf54x-lq043.h>
+
+static struct bfin_bf54xfb_mach_info bf54x_lq043_data = {
+       .width =        480,
+       .height =       272,
+       .xres =         {480, 480, 480},
+       .yres =         {272, 272, 272},
+       .bpp =          {24, 24, 24},
+       .disp =         GPIO_PE3,
+};
+
+static struct resource bf54x_lq043_resources[] = {
+       {
+               .start = IRQ_EPPI0_ERR,
+               .end = IRQ_EPPI0_ERR,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device bf54x_lq043_device = {
+       .name           = "bf54x-lq043",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(bf54x_lq043_resources),
+       .resource       = bf54x_lq043_resources,
+       .dev            = {
+               .platform_data = &bf54x_lq043_data,
+       },
+};
+#endif
+
+#if defined(CONFIG_KEYBOARD_BFIN) || defined(CONFIG_KEYBOARD_BFIN_MODULE)
+static unsigned int bf548_keymap[] = {
+       KEYVAL(0, 0, KEY_ENTER),
+       KEYVAL(0, 1, KEY_HELP),
+       KEYVAL(0, 2, KEY_0),
+       KEYVAL(0, 3, KEY_BACKSPACE),
+       KEYVAL(1, 0, KEY_TAB),
+       KEYVAL(1, 1, KEY_9),
+       KEYVAL(1, 2, KEY_8),
+       KEYVAL(1, 3, KEY_7),
+       KEYVAL(2, 0, KEY_DOWN),
+       KEYVAL(2, 1, KEY_6),
+       KEYVAL(2, 2, KEY_5),
+       KEYVAL(2, 3, KEY_4),
+       KEYVAL(3, 0, KEY_UP),
+       KEYVAL(3, 1, KEY_3),
+       KEYVAL(3, 2, KEY_2),
+       KEYVAL(3, 3, KEY_1),
+};
+
+static struct bfin_kpad_platform_data bf54x_kpad_data = {
+       .rows                   = 4,
+       .cols                   = 4,
+       .keymap                 = bf548_keymap,
+       .keymapsize             = ARRAY_SIZE(bf548_keymap),
+       .repeat                 = 0,
+       .debounce_time          = 5000, /* ns (5ms) */
+       .coldrive_time          = 1000, /* ns (1ms) */
+       .keyup_test_interval    = 50, /* ms (50ms) */
+};
+
+static struct resource bf54x_kpad_resources[] = {
+       {
+               .start = IRQ_KEY,
+               .end = IRQ_KEY,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device bf54x_kpad_device = {
+       .name           = "bf54x-keys",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(bf54x_kpad_resources),
+       .resource       = bf54x_kpad_resources,
+       .dev            = {
+               .platform_data = &bf54x_kpad_data,
+       },
+};
+#endif
+
+#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
+static struct platform_device rtc_device = {
+       .name = "rtc-bfin",
+       .id   = -1,
+};
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+static struct resource bfin_uart_resources[] = {
+#ifdef CONFIG_SERIAL_BFIN_UART0
+       {
+               .start = 0xFFC00400,
+               .end = 0xFFC004FF,
+               .flags = IORESOURCE_MEM,
+       },
+#endif
+#ifdef CONFIG_SERIAL_BFIN_UART1
+       {
+               .start = 0xFFC02000,
+               .end = 0xFFC020FF,
+               .flags = IORESOURCE_MEM,
+       },
+#endif
+#ifdef CONFIG_SERIAL_BFIN_UART2
+       {
+               .start = 0xFFC02100,
+               .end = 0xFFC021FF,
+               .flags = IORESOURCE_MEM,
+       },
+#endif
+#ifdef CONFIG_SERIAL_BFIN_UART3
+       {
+               .start = 0xFFC03100,
+               .end = 0xFFC031FF,
+       },
+#endif
+};
+
+static struct platform_device bfin_uart_device = {
+       .name = "bfin-uart",
+       .id = 1,
+       .num_resources = ARRAY_SIZE(bfin_uart_resources),
+       .resource = bfin_uart_resources,
+};
+#endif
+
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+static struct resource bfin_sir_resources[] = {
+#ifdef CONFIG_BFIN_SIR0
+       {
+               .start = 0xFFC00400,
+               .end = 0xFFC004FF,
+               .flags = IORESOURCE_MEM,
+       },
+#endif
+#ifdef CONFIG_BFIN_SIR1
+       {
+               .start = 0xFFC02000,
+               .end = 0xFFC020FF,
+               .flags = IORESOURCE_MEM,
+       },
+#endif
+#ifdef CONFIG_BFIN_SIR2
+       {
+               .start = 0xFFC02100,
+               .end = 0xFFC021FF,
+               .flags = IORESOURCE_MEM,
+       },
+#endif
+#ifdef CONFIG_BFIN_SIR3
+       {
+               .start = 0xFFC03100,
+               .end = 0xFFC031FF,
+               .flags = IORESOURCE_MEM,
+       },
+#endif
+};
+
+static struct platform_device bfin_sir_device = {
+       .name = "bfin_sir",
+       .id = 0,
+       .num_resources = ARRAY_SIZE(bfin_sir_resources),
+       .resource = bfin_sir_resources,
+};
+#endif
+
+#if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
+static struct resource smsc911x_resources[] = {
+       {
+               .name = "smsc911x-memory",
+               .start = 0x24000000,
+               .end = 0x24000000 + 0xFF,
+               .flags = IORESOURCE_MEM,
+       },
+       {
+               .start = IRQ_PE6,
+               .end = IRQ_PE6,
+               .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
+       },
+};
+static struct platform_device smsc911x_device = {
+       .name = "smsc911x",
+       .id = 0,
+       .num_resources = ARRAY_SIZE(smsc911x_resources),
+       .resource = smsc911x_resources,
+};
+#endif
+
+#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE)
+static struct resource musb_resources[] = {
+       [0] = {
+               .start  = 0xFFC03C00,
+               .end    = 0xFFC040FF,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = { /* general IRQ */
+               .start  = IRQ_USB_INT0,
+               .end    = IRQ_USB_INT0,
+               .flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+       },
+       [2] = { /* DMA IRQ */
+               .start  = IRQ_USB_DMA,
+               .end    = IRQ_USB_DMA,
+               .flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+       },
+};
+
+static struct musb_hdrc_platform_data musb_plat = {
+#if defined(CONFIG_USB_MUSB_OTG)
+       .mode           = MUSB_OTG,
+#elif defined(CONFIG_USB_MUSB_HDRC_HCD)
+       .mode           = MUSB_HOST,
+#elif defined(CONFIG_USB_GADGET_MUSB_HDRC)
+       .mode           = MUSB_PERIPHERAL,
+#endif
+       .multipoint     = 0,
+};
+
+static u64 musb_dmamask = ~(u32)0;
+
+static struct platform_device musb_device = {
+       .name           = "musb_hdrc",
+       .id             = 0,
+       .dev = {
+               .dma_mask               = &musb_dmamask,
+               .coherent_dma_mask      = 0xffffffff,
+               .platform_data          = &musb_plat,
+       },
+       .num_resources  = ARRAY_SIZE(musb_resources),
+       .resource       = musb_resources,
+};
+#endif
+
+#if defined(CONFIG_PATA_BF54X) || defined(CONFIG_PATA_BF54X_MODULE)
+static struct resource bfin_atapi_resources[] = {
+       {
+               .start = 0xFFC03800,
+               .end = 0xFFC0386F,
+               .flags = IORESOURCE_MEM,
+       },
+       {
+               .start = IRQ_ATAPI_ERR,
+               .end = IRQ_ATAPI_ERR,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device bfin_atapi_device = {
+       .name = "pata-bf54x",
+       .id = -1,
+       .num_resources = ARRAY_SIZE(bfin_atapi_resources),
+       .resource = bfin_atapi_resources,
+};
+#endif
+
+#if defined(CONFIG_MTD_NAND_BF5XX) || defined(CONFIG_MTD_NAND_BF5XX_MODULE)
+static struct mtd_partition partition_info[] = {
+       {
+               .name = "Linux Kernel",
+               .offset = 0,
+               .size = 4 * SIZE_1M,
+       },
+       {
+               .name = "File System",
+               .offset = 4 * SIZE_1M,
+               .size = (256 - 4) * SIZE_1M,
+       },
+};
+
+static struct bf5xx_nand_platform bf5xx_nand_platform = {
+       .page_size = NFC_PG_SIZE_256,
+       .data_width = NFC_NWIDTH_8,
+       .partitions = partition_info,
+       .nr_partitions = ARRAY_SIZE(partition_info),
+       .rd_dly = 3,
+       .wr_dly = 3,
+};
+
+static struct resource bf5xx_nand_resources[] = {
+       {
+               .start = 0xFFC03B00,
+               .end = 0xFFC03B4F,
+               .flags = IORESOURCE_MEM,
+       },
+       {
+               .start = CH_NFC,
+               .end = CH_NFC,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device bf5xx_nand_device = {
+       .name = "bf5xx-nand",
+       .id = 0,
+       .num_resources = ARRAY_SIZE(bf5xx_nand_resources),
+       .resource = bf5xx_nand_resources,
+       .dev = {
+               .platform_data = &bf5xx_nand_platform,
+       },
+};
+#endif
+
+#if defined(CONFIG_SDH_BFIN) || defined(CONFIG_SDH_BFIN_MODULE)
+static struct platform_device bf54x_sdh_device = {
+       .name = "bfin-sdh",
+       .id = 0,
+};
+#endif
+
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+/* all SPI peripherals info goes here */
+#if defined(CONFIG_MTD_M25P80) \
+       || defined(CONFIG_MTD_M25P80_MODULE)
+/* SPI flash chip (m25p16) */
+static struct mtd_partition bfin_spi_flash_partitions[] = {
+       {
+               .name = "bootloader",
+               .size = 0x00040000,
+               .offset = 0,
+               .mask_flags = MTD_CAP_ROM
+       }, {
+               .name = "linux kernel",
+               .size = 0x1c0000,
+               .offset = 0x40000
+       }
+};
+
+static struct flash_platform_data bfin_spi_flash_data = {
+       .name = "m25p80",
+       .parts = bfin_spi_flash_partitions,
+       .nr_parts = ARRAY_SIZE(bfin_spi_flash_partitions),
+       .type = "m25p16",
+};
+
+static struct bfin5xx_spi_chip spi_flash_chip_info = {
+       .enable_dma = 0,         /* use dma transfer with this chip*/
+       .bits_per_word = 8,
+       .cs_change_per_word = 0,
+};
+#endif
+
+#if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
+static struct bfin5xx_spi_chip spi_ad7877_chip_info = {
+       .cs_change_per_word = 0,
+       .enable_dma = 0,
+       .bits_per_word = 16,
+};
+
+static const struct ad7877_platform_data bfin_ad7877_ts_info = {
+       .model                  = 7877,
+       .vref_delay_usecs       = 50,   /* internal, no capacitor */
+       .x_plate_ohms           = 419,
+       .y_plate_ohms           = 486,
+       .pressure_max           = 1000,
+       .pressure_min           = 0,
+       .stopacq_polarity       = 1,
+       .first_conversion_delay = 3,
+       .acquisition_time       = 1,
+       .averaging              = 1,
+       .pen_down_acc_interval  = 1,
+};
+#endif
+
+#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
+static struct bfin5xx_spi_chip spidev_chip_info = {
+       .enable_dma = 0,
+       .bits_per_word = 8,
+};
+#endif
+
+static struct spi_board_info bf54x_spi_board_info[] __initdata = {
+#if defined(CONFIG_MTD_M25P80) \
+       || defined(CONFIG_MTD_M25P80_MODULE)
+       {
+               /* the modalias must be the same as spi device driver name */
+               .modalias = "m25p80", /* Name of spi_driver for this device */
+               .max_speed_hz = 25000000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 0, /* Framework bus number */
+               .chip_select = 1, /* SPI_SSEL1*/
+               .platform_data = &bfin_spi_flash_data,
+               .controller_data = &spi_flash_chip_info,
+               .mode = SPI_MODE_3,
+       },
+#endif
+#if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
+{
+       .modalias               = "ad7877",
+       .platform_data          = &bfin_ad7877_ts_info,
+       .irq                    = IRQ_PJ11,
+       .max_speed_hz           = 12500000,     /* max spi clock (SCK) speed in HZ */
+       .bus_num                = 0,
+       .chip_select            = 2,
+       .controller_data = &spi_ad7877_chip_info,
+},
+#endif
+#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
+       {
+               .modalias = "spidev",
+               .max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 0,
+               .chip_select = 1,
+               .controller_data = &spidev_chip_info,
+       },
+#endif
+};
+
+/* SPI (0) */
+static struct resource bfin_spi0_resource[] = {
+       [0] = {
+               .start = SPI0_REGBASE,
+               .end   = SPI0_REGBASE + 0xFF,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = CH_SPI0,
+               .end   = CH_SPI0,
+               .flags = IORESOURCE_IRQ,
+       }
+};
+
+/* SPI (1) */
+static struct resource bfin_spi1_resource[] = {
+       [0] = {
+               .start = SPI1_REGBASE,
+               .end   = SPI1_REGBASE + 0xFF,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = CH_SPI1,
+               .end   = CH_SPI1,
+               .flags = IORESOURCE_IRQ,
+       }
+};
+
+/* SPI controller data */
+static struct bfin5xx_spi_master bf54x_spi_master_info0 = {
+       .num_chipselect = 8,
+       .enable_dma = 1,  /* master has the ability to do dma transfer */
+       .pin_req = {P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0},
+};
+
+static struct platform_device bf54x_spi_master0 = {
+       .name = "bfin-spi",
+       .id = 0, /* Bus number */
+       .num_resources = ARRAY_SIZE(bfin_spi0_resource),
+       .resource = bfin_spi0_resource,
+       .dev = {
+               .platform_data = &bf54x_spi_master_info0, /* Passed to driver */
+               },
+};
+
+static struct bfin5xx_spi_master bf54x_spi_master_info1 = {
+       .num_chipselect = 8,
+       .enable_dma = 1,  /* master has the ability to do dma transfer */
+       .pin_req = {P_SPI1_SCK, P_SPI1_MISO, P_SPI1_MOSI, 0},
+};
+
+static struct platform_device bf54x_spi_master1 = {
+       .name = "bfin-spi",
+       .id = 1, /* Bus number */
+       .num_resources = ARRAY_SIZE(bfin_spi1_resource),
+       .resource = bfin_spi1_resource,
+       .dev = {
+               .platform_data = &bf54x_spi_master_info1, /* Passed to driver */
+               },
+};
+#endif  /* spi master and devices */
+
+#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+static struct resource bfin_twi0_resource[] = {
+       [0] = {
+               .start = TWI0_REGBASE,
+               .end   = TWI0_REGBASE + 0xFF,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = IRQ_TWI0,
+               .end   = IRQ_TWI0,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device i2c_bfin_twi0_device = {
+       .name = "i2c-bfin-twi",
+       .id = 0,
+       .num_resources = ARRAY_SIZE(bfin_twi0_resource),
+       .resource = bfin_twi0_resource,
+};
+
+#if !defined(CONFIG_BF542)     /* The BF542 only has 1 TWI */
+static struct resource bfin_twi1_resource[] = {
+       [0] = {
+               .start = TWI1_REGBASE,
+               .end   = TWI1_REGBASE + 0xFF,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = IRQ_TWI1,
+               .end   = IRQ_TWI1,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device i2c_bfin_twi1_device = {
+       .name = "i2c-bfin-twi",
+       .id = 1,
+       .num_resources = ARRAY_SIZE(bfin_twi1_resource),
+       .resource = bfin_twi1_resource,
+};
+#endif
+#endif
+
+#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
+#include <linux/gpio_keys.h>
+
+static struct gpio_keys_button bfin_gpio_keys_table[] = {
+       {BTN_0, GPIO_PH7, 1, "gpio-keys: BTN0"},
+};
+
+static struct gpio_keys_platform_data bfin_gpio_keys_data = {
+       .buttons        = bfin_gpio_keys_table,
+       .nbuttons       = ARRAY_SIZE(bfin_gpio_keys_table),
+};
+
+static struct platform_device bfin_device_gpiokeys = {
+       .name      = "gpio-keys",
+       .dev = {
+               .platform_data = &bfin_gpio_keys_data,
+       },
+};
+#endif
+
+static struct platform_device *cm_bf548_devices[] __initdata = {
+#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
+       &rtc_device,
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+       &bfin_uart_device,
+#endif
+
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+       &bfin_sir_device,
+#endif
+
+#if defined(CONFIG_FB_BF54X_LQ043) || defined(CONFIG_FB_BF54X_LQ043_MODULE)
+       &bf54x_lq043_device,
+#endif
+
+#if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
+       &smsc911x_device,
+#endif
+
+#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE)
+       &musb_device,
+#endif
+
+#if defined(CONFIG_PATA_BF54X) || defined(CONFIG_PATA_BF54X_MODULE)
+       &bfin_atapi_device,
+#endif
+
+#if defined(CONFIG_MTD_NAND_BF5XX) || defined(CONFIG_MTD_NAND_BF5XX_MODULE)
+       &bf5xx_nand_device,
+#endif
+
+#if defined(CONFIG_SDH_BFIN) || defined(CONFIG_SDH_BFIN_MODULE)
+       &bf54x_sdh_device,
+#endif
+
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+       &bf54x_spi_master0,
+       &bf54x_spi_master1,
+#endif
+
+#if defined(CONFIG_KEYBOARD_BFIN) || defined(CONFIG_KEYBOARD_BFIN_MODULE)
+       &bf54x_kpad_device,
+#endif
+
+#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+/*     &i2c_bfin_twi0_device, */
+#if !defined(CONFIG_BF542)
+       &i2c_bfin_twi1_device,
+#endif
+#endif
+
+#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
+       &bfin_device_gpiokeys,
+#endif
+};
+
+static int __init cm_bf548_init(void)
+{
+       printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
+       platform_add_devices(cm_bf548_devices, ARRAY_SIZE(cm_bf548_devices));
+
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+       spi_register_board_info(bf54x_spi_board_info,
+                       ARRAY_SIZE(bf54x_spi_board_info));
+#endif
+
+       return 0;
+}
+
+arch_initcall(cm_bf548_init);
index 40846aa034c4a7d6bb659c47b92dc3d19d3590f1..231dfbd3bc1ffcefc1a9c11b94ad885ab1d376d3 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/flash.h>
 #include <linux/irq.h>
+#include <linux/i2c.h>
 #include <linux/interrupt.h>
 #if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE)
 #include <linux/usb/musb.h>
@@ -187,6 +188,46 @@ static struct platform_device bfin_uart_device = {
 };
 #endif
 
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+static struct resource bfin_sir_resources[] = {
+#ifdef CONFIG_BFIN_SIR0
+       {
+               .start = 0xFFC00400,
+               .end = 0xFFC004FF,
+               .flags = IORESOURCE_MEM,
+       },
+#endif
+#ifdef CONFIG_BFIN_SIR1
+       {
+               .start = 0xFFC02000,
+               .end = 0xFFC020FF,
+               .flags = IORESOURCE_MEM,
+       },
+#endif
+#ifdef CONFIG_BFIN_SIR2
+       {
+               .start = 0xFFC02100,
+               .end = 0xFFC021FF,
+               .flags = IORESOURCE_MEM,
+       },
+#endif
+#ifdef CONFIG_BFIN_SIR3
+       {
+               .start = 0xFFC03100,
+               .end = 0xFFC031FF,
+               .flags = IORESOURCE_MEM,
+       },
+#endif
+};
+
+static struct platform_device bfin_sir_device = {
+       .name = "bfin_sir",
+       .id = 0,
+       .num_resources = ARRAY_SIZE(bfin_sir_resources),
+       .resource = bfin_sir_resources,
+};
+#endif
+
 #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
 static struct resource smsc911x_resources[] = {
        {
@@ -330,6 +371,7 @@ static struct platform_device bf54x_sdh_device = {
 };
 #endif
 
+#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
 static struct mtd_partition ezkit_partitions[] = {
        {
                .name       = "Bootloader",
@@ -337,7 +379,7 @@ static struct mtd_partition ezkit_partitions[] = {
                .offset     = 0,
        }, {
                .name       = "Kernel",
-               .size       = 0xE0000,
+               .size       = 0x1C0000,
                .offset     = MTDPART_OFS_APPEND,
        }, {
                .name       = "RootFS",
@@ -367,6 +409,7 @@ static struct platform_device ezkit_flash_device = {
        .num_resources = 1,
        .resource      = &ezkit_flash_resource,
 };
+#endif
 
 #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
 /* all SPI peripherals info goes here */
@@ -400,6 +443,14 @@ static struct bfin5xx_spi_chip spi_flash_chip_info = {
 };
 #endif
 
+#if defined(CONFIG_SND_BLACKFIN_AD1836) \
+       || defined(CONFIG_SND_BLACKFIN_AD1836_MODULE)
+static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
+       .enable_dma = 0,
+       .bits_per_word = 16,
+};
+#endif
+
 #if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
 static struct bfin5xx_spi_chip spi_ad7877_chip_info = {
        .cs_change_per_word = 0,
@@ -443,6 +494,16 @@ static struct spi_board_info bf54x_spi_board_info[] __initdata = {
                .mode = SPI_MODE_3,
        },
 #endif
+#if defined(CONFIG_SND_BLACKFIN_AD1836) \
+       || defined(CONFIG_SND_BLACKFIN_AD1836_MODULE)
+       {
+               .modalias = "ad1836-spi",
+               .max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 1,
+               .chip_select = CONFIG_SND_BLACKFIN_SPI_PFBIT,
+               .controller_data = &ad1836_spi_chip_info,
+       },
+#endif
 #if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
 {
        .modalias               = "ad7877",
@@ -571,6 +632,29 @@ static struct platform_device i2c_bfin_twi1_device = {
 #endif
 #endif
 
+#ifdef CONFIG_I2C_BOARDINFO
+static struct i2c_board_info __initdata bfin_i2c_board_info0[] = {
+};
+
+#if !defined(CONFIG_BF542)     /* The BF542 only has 1 TWI */
+static struct i2c_board_info __initdata bfin_i2c_board_info1[] = {
+#if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
+       {
+               I2C_BOARD_INFO("pcf8574_lcd", 0x22),
+               .type = "pcf8574_lcd",
+       },
+#endif
+#if defined(CONFIG_TWI_KEYPAD) || defined(CONFIG_TWI_KEYPAD_MODULE)
+       {
+               I2C_BOARD_INFO("pcf8574_keypad", 0x27),
+               .type = "pcf8574_keypad",
+               .irq = 212,
+       },
+#endif
+};
+#endif
+#endif
+
 #if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
 #include <linux/gpio_keys.h>
 
@@ -616,6 +700,10 @@ static struct platform_device *ezkit_devices[] __initdata = {
        &bfin_uart_device,
 #endif
 
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+       &bfin_sir_device,
+#endif
+
 #if defined(CONFIG_FB_BF54X_LQ043) || defined(CONFIG_FB_BF54X_LQ043_MODULE)
        &bf54x_lq043_device,
 #endif
@@ -661,12 +749,25 @@ static struct platform_device *ezkit_devices[] __initdata = {
 #endif
 
        &bfin_gpios_device,
+
+#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
        &ezkit_flash_device,
+#endif
 };
 
 static int __init ezkit_init(void)
 {
-       printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
+       printk(KERN_INFO "%s(): registering device resources\n", __func__);
+
+#ifdef CONFIG_I2C_BOARDINFO
+       i2c_register_board_info(0, bfin_i2c_board_info0,
+                               ARRAY_SIZE(bfin_i2c_board_info0));
+#if !defined(CONFIG_BF542)     /* The BF542 only has 1 TWI */
+       i2c_register_board_info(1, bfin_i2c_board_info1,
+                               ARRAY_SIZE(bfin_i2c_board_info1));
+#endif
+#endif
+
        platform_add_devices(ezkit_devices, ARRAY_SIZE(ezkit_devices));
 
 #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
diff --git a/arch/blackfin/mach-bf548/cpu.c b/arch/blackfin/mach-bf548/cpu.c
deleted file mode 100644 (file)
index 4298a3c..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * File:         arch/blackfin/mach-bf548/cpu.c
- * Based on:
- * Author:
- *
- * Created:
- * Description:  clock scaling for the bf54x
- *
- * Modified:
- *               Copyright 2004-2007 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/cpufreq.h>
-#include <asm/dpmc.h>
-#include <linux/fs.h>
-#include <asm/bfin-global.h>
-
-/* CONFIG_CLKIN_HZ=25000000 */
-#define VCO5 (CONFIG_CLKIN_HZ*45)
-#define VCO4 (CONFIG_CLKIN_HZ*36)
-#define VCO3 (CONFIG_CLKIN_HZ*27)
-#define VCO2 (CONFIG_CLKIN_HZ*18)
-#define VCO1 (CONFIG_CLKIN_HZ*9)
-#define VCO(x) VCO##x
-
-#define MFREQ(x) {VCO(x),VCO(x)/4},{VCO(x),VCO(x)/2},{VCO(x),VCO(x)}
-/* frequency */
-static struct cpufreq_frequency_table bf548_freq_table[] = {
-       MFREQ(1),
-       MFREQ(3),
-       {VCO4, VCO4 / 2}, {VCO4, VCO4},
-       MFREQ(5),
-       {0, CPUFREQ_TABLE_END},
-};
-
-/*
- * dpmc_fops->ioctl()
- * static int dpmc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
- */
-static int bf548_getfreq(unsigned int cpu)
-{
-       unsigned long cclk_mhz;
-
-       /* The driver only support single cpu */
-       if (cpu == 0)
-               dpmc_fops.ioctl(NULL, NULL, IOCTL_GET_CORECLOCK, &cclk_mhz);
-       else
-               cclk_mhz = -1;
-
-       return cclk_mhz;
-}
-
-static int bf548_target(struct cpufreq_policy *policy,
-                           unsigned int target_freq, unsigned int relation)
-{
-       unsigned long cclk_mhz;
-       unsigned long vco_mhz;
-       unsigned long flags;
-       unsigned int index;
-       struct cpufreq_freqs freqs;
-
-       if (cpufreq_frequency_table_target(policy, bf548_freq_table, target_freq, relation, &index))
-               return -EINVAL;
-
-       cclk_mhz = bf548_freq_table[index].frequency;
-       vco_mhz = bf548_freq_table[index].index;
-
-       dpmc_fops.ioctl(NULL, NULL, IOCTL_CHANGE_FREQUENCY, &vco_mhz);
-       freqs.old = bf548_getfreq(0);
-       freqs.new = cclk_mhz;
-       freqs.cpu = 0;
-
-       pr_debug("cclk begin change to cclk %d,vco=%d,index=%d,target=%d,oldfreq=%d\n",
-                cclk_mhz, vco_mhz, index, target_freq, freqs.old);
-
-       cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-       local_irq_save(flags);
-       dpmc_fops.ioctl(NULL, NULL, IOCTL_SET_CCLK, &cclk_mhz);
-       local_irq_restore(flags);
-       cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-
-       vco_mhz = get_vco();
-       cclk_mhz = get_cclk();
-       return 0;
-}
-
-/* make sure that only the "userspace" governor is run -- anything else wouldn't make sense on
- * this platform, anyway.
- */
-static int bf548_verify_speed(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, &bf548_freq_table);
-}
-
-static int __init __bf548_cpu_init(struct cpufreq_policy *policy)
-{
-       if (policy->cpu != 0)
-               return -EINVAL;
-
-       policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
-
-       policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
-       /*Now ,only support one cpu */
-       policy->cur = bf548_getfreq(0);
-       cpufreq_frequency_table_get_attr(bf548_freq_table, policy->cpu);
-       return cpufreq_frequency_table_cpuinfo(policy, bf548_freq_table);
-}
-
-static struct freq_attr *bf548_freq_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
-static struct cpufreq_driver bf548_driver = {
-       .verify = bf548_verify_speed,
-       .target = bf548_target,
-       .get = bf548_getfreq,
-       .init = __bf548_cpu_init,
-       .name = "bf548",
-       .owner = THIS_MODULE,
-       .attr = bf548_freq_attr,
-};
-
-static int __init bf548_cpu_init(void)
-{
-       return cpufreq_register_driver(&bf548_driver);
-}
-
-static void __exit bf548_cpu_exit(void)
-{
-       cpufreq_unregister_driver(&bf548_driver);
-}
-
-MODULE_AUTHOR("Mickael Kang");
-MODULE_DESCRIPTION("cpufreq driver for BF548 CPU");
-MODULE_LICENSE("GPL");
-
-module_init(bf548_cpu_init);
-module_exit(bf548_cpu_exit);
index f5479298bb7913fd55baee1538ed310d090f8cec..74730eb8ae1bf41208d3da8b67b15fde18246f0c 100644 (file)
@@ -32,7 +32,7 @@
 #include <asm/blackfin.h>
 #include <asm/dma.h>
 
- struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
+struct dma_register *dma_io_base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
        (struct dma_register *) DMA0_NEXT_DESC_PTR,
        (struct dma_register *) DMA1_NEXT_DESC_PTR,
        (struct dma_register *) DMA2_NEXT_DESC_PTR,
@@ -66,7 +66,7 @@
        (struct dma_register *) MDMA_D3_NEXT_DESC_PTR,
        (struct dma_register *) MDMA_S3_NEXT_DESC_PTR,
 };
-EXPORT_SYMBOL(base_addr);
+EXPORT_SYMBOL(dma_io_base_addr);
 
 int channel2irq(unsigned int channel)
 {
index 46222a75321a5d7f8fa21e103b4ce9ae666967cd..f7191141a3ce104fafe7a312703ce51b28171175 100644 (file)
@@ -36,9 +36,6 @@
 #include <asm/mach/mem_init.h>
 #endif
 
-.global __rambase
-.global __ramstart
-.global __ramend
 .extern ___bss_stop
 .extern ___bss_start
 .extern _bf53x_relocate_l1_mem
@@ -456,18 +453,3 @@ ENTRY(_start_dma_code)
        RTS;
 ENDPROC(_start_dma_code)
 #endif /* CONFIG_BFIN_KERNEL_CLOCK */
-
-.data
-
-/*
- * Set up the usable of RAM stuff. Size of RAM is determined then
- * an initial stack set up at the end.
- */
-
-.align 4
-__rambase:
-.long   0
-__ramstart:
-.long   0
-__ramend:
-.long   0
index bf9e738a7c6451938a3254039e324c68cc71ff85..9fd580952fd891cc0a64808f22fdf43fb154473b 100644 (file)
@@ -283,6 +283,25 @@ static struct platform_device bfin_uart_device = {
 };
 #endif
 
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+static struct resource bfin_sir_resources[] = {
+#ifdef CONFIG_BFIN_SIR0
+       {
+               .start = 0xFFC00400,
+               .end = 0xFFC004FF,
+               .flags = IORESOURCE_MEM,
+       },
+#endif
+};
+
+static struct platform_device bfin_sir_device = {
+       .name = "bfin_sir",
+       .id = 0,
+       .num_resources = ARRAY_SIZE(bfin_sir_resources),
+       .resource = bfin_sir_resources,
+};
+#endif
+
 #if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
 #define PATA_INT       119
 
@@ -330,6 +349,10 @@ static struct platform_device *cm_bf561_devices[] __initdata = {
        &bfin_uart_device,
 #endif
 
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+       &bfin_sir_device,
+#endif
+
 #if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
        &isp1362_hcd_device,
 #endif
@@ -349,7 +372,7 @@ static struct platform_device *cm_bf561_devices[] __initdata = {
 
 static int __init cm_bf561_init(void)
 {
-       printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
+       printk(KERN_INFO "%s(): registering device resources\n", __func__);
        platform_add_devices(cm_bf561_devices, ARRAY_SIZE(cm_bf561_devices));
 #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
        spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
index d357f648d963295f630b5db160607804a3bb9ba5..0d74b7d99209e7460c5af87f9926d9ea1c32c32e 100644 (file)
@@ -78,7 +78,7 @@ int __init bfin_isp1761_init(void)
 {
        unsigned int num_devices = ARRAY_SIZE(bfin_isp1761_devices);
 
-       printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
+       printk(KERN_INFO "%s(): registering device resources\n", __func__);
        set_irq_type(ISP1761_IRQ, IRQF_TRIGGER_FALLING);
 
        return platform_add_devices(bfin_isp1761_devices, num_devices);
@@ -220,6 +220,26 @@ static struct platform_device bfin_uart_device = {
 };
 #endif
 
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+static struct resource bfin_sir_resources[] = {
+#ifdef CONFIG_BFIN_SIR0
+       {
+               .start = 0xFFC00400,
+               .end = 0xFFC004FF,
+               .flags = IORESOURCE_MEM,
+       },
+#endif
+};
+
+static struct platform_device bfin_sir_device = {
+       .name = "bfin_sir",
+       .id = 0,
+       .num_resources = ARRAY_SIZE(bfin_sir_resources),
+       .resource = bfin_sir_resources,
+};
+#endif
+
+#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
 static struct mtd_partition ezkit_partitions[] = {
        {
                .name       = "Bootloader",
@@ -227,7 +247,7 @@ static struct mtd_partition ezkit_partitions[] = {
                .offset     = 0,
        }, {
                .name       = "Kernel",
-               .size       = 0xE0000,
+               .size       = 0x1C0000,
                .offset     = MTDPART_OFS_APPEND,
        }, {
                .name       = "RootFS",
@@ -257,6 +277,7 @@ static struct platform_device ezkit_flash_device = {
        .num_resources = 1,
        .resource      = &ezkit_flash_resource,
 };
+#endif
 
 #ifdef CONFIG_SPI_BFIN
 #if defined(CONFIG_SND_BLACKFIN_AD1836) \
@@ -443,6 +464,10 @@ static struct platform_device *ezkit_devices[] __initdata = {
        &bfin_uart_device,
 #endif
 
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+       &bfin_sir_device,
+#endif
+
 #if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
        &bfin_pata_device,
 #endif
@@ -460,7 +485,10 @@ static struct platform_device *ezkit_devices[] __initdata = {
 #endif
 
        &bfin_gpios_device,
+
+#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
        &ezkit_flash_device,
+#endif
 };
 
 static int __init ezkit_init(void)
index fc80c5d059f8b28cbd29471f37c152f7d21e9322..2faa0072d614532cd38aa9c45da18806a4f162f8 100644 (file)
@@ -70,7 +70,7 @@ static struct platform_device *generic_board_devices[] __initdata = {
 
 static int __init generic_board_init(void)
 {
-       printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
+       printk(KERN_INFO "%s(): registering device resources\n", __func__);
        return platform_add_devices(generic_board_devices,
                                    ARRAY_SIZE(generic_board_devices));
 }
index ec6a2207c202491f347cd3ab2f45721fb33ec634..c9174b39f98dcdf08278f6b37bc1853354170df6 100644 (file)
@@ -50,7 +50,7 @@ static struct platform_device *tepla_devices[] __initdata = {
 
 static int __init tepla_init(void)
 {
-       printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
+       printk(KERN_INFO "%s(): registering device resources\n", __func__);
        return platform_add_devices(tepla_devices, ARRAY_SIZE(tepla_devices));
 }
 
index 89c65bb0bed38fb988c87ab62984467f48c05bf8..24415eb82698dd4961b1fddb3ac9c738aac141d0 100644 (file)
  * to the Free Software Foundation, Inc.,
  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
+#include <linux/module.h>
+
 #include <asm/blackfin.h>
 #include <asm/dma.h>
 
-struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
+struct dma_register *dma_io_base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
        (struct dma_register *) DMA1_0_NEXT_DESC_PTR,
        (struct dma_register *) DMA1_1_NEXT_DESC_PTR,
        (struct dma_register *) DMA1_2_NEXT_DESC_PTR,
@@ -67,6 +69,7 @@ struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
        (struct dma_register *) IMDMA_D1_NEXT_DESC_PTR,
        (struct dma_register *) IMDMA_S1_NEXT_DESC_PTR,
 };
+EXPORT_SYMBOL(dma_io_base_addr);
 
 int channel2irq(unsigned int channel)
 {
index 96a3d456fb6d8a678e614cc37741cbf824263490..5b8bd40851dd5cdd596a62040a1d51a5adea78bc 100644 (file)
@@ -37,9 +37,6 @@
 #include <asm/mach/mem_init.h>
 #endif
 
-.global __rambase
-.global __ramstart
-.global __ramend
 .extern ___bss_stop
 .extern ___bss_start
 .extern _bf53x_relocate_l1_mem
@@ -139,26 +136,26 @@ ENTRY(__start)
 
        /* Initialise UART - when booting from u-boot, the UART is not disabled
         * so if we dont initalize here, our serial console gets hosed */
-       p0.h = hi(UART_LCR);
-       p0.l = lo(UART_LCR);
+       p0.h = hi(BFIN_UART_LCR);
+       p0.l = lo(BFIN_UART_LCR);
        r0 = 0x0(Z);
        w[p0] = r0.L;   /* To enable DLL writes */
        ssync;
 
-       p0.h = hi(UART_DLL);
-       p0.l = lo(UART_DLL);
+       p0.h = hi(BFIN_UART_DLL);
+       p0.l = lo(BFIN_UART_DLL);
        r0 = 0x0(Z);
        w[p0] = r0.L;
        ssync;
 
-       p0.h = hi(UART_DLH);
-       p0.l = lo(UART_DLH);
+       p0.h = hi(BFIN_UART_DLH);
+       p0.l = lo(BFIN_UART_DLH);
        r0 = 0x00(Z);
        w[p0] = r0.L;
        ssync;
 
-       p0.h = hi(UART_GCTL);
-       p0.l = lo(UART_GCTL);
+       p0.h = hi(BFIN_UART_GCTL);
+       p0.l = lo(BFIN_UART_GCTL);
        r0 = 0x0(Z);
        w[p0] = r0.L;   /* To enable UART clock */
        ssync;
@@ -411,18 +408,3 @@ ENTRY(_start_dma_code)
        RTS;
 ENDPROC(_start_dma_code)
 #endif /* CONFIG_BFIN_KERNEL_CLOCK */
-
-.data
-
-/*
- * Set up the usable of RAM stuff. Size of RAM is determined then
- * an initial stack set up at the end.
- */
-
-.align 4
-__rambase:
-.long   0
-__ramstart:
-.long   0
-__ramend:
-.long   0
index 15e33ca1ce805205667d9014516da41657dbcae4..393081e9b6804316b4d61c6d4f25ef9fbe13bb3d 100644 (file)
@@ -6,4 +6,5 @@ obj-y := \
        cache.o cacheinit.o entry.o \
        interrupt.o lock.o irqpanic.o arch_checks.o ints-priority.o
 
-obj-$(CONFIG_PM)                 += pm.o dpmc.o
+obj-$(CONFIG_PM)         += pm.o dpmc.o
+obj-$(CONFIG_CPU_FREQ)   += cpufreq.o
index 2f6ce397780fd2ac8735f01f1a93164a8f1c79c6..caaab49e9cfa18800c52d08a44b13fd820daaca2 100644 (file)
@@ -54,7 +54,8 @@
 
 #endif /* CONFIG_BFIN_KERNEL_CLOCK */
 
+#ifdef CONFIG_MEM_SIZE
 #if (CONFIG_MEM_SIZE % 4)
 #error "SDRAM mem size must be multible of 4MB"
 #endif
-
+#endif
diff --git a/arch/blackfin/mach-common/cpufreq.c b/arch/blackfin/mach-common/cpufreq.c
new file mode 100644 (file)
index 0000000..ed81e00
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ * File:        arch/blackfin/mach-common/cpufreq.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:         Blackfin core clock scaling
+ *
+ * Modified:
+ *              Copyright 2004-2008 Analog Devices Inc.
+ *
+ * Bugs:        Enter bugs at http://blackfin.uclinux.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA     02110-1301      USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/cpufreq.h>
+#include <linux/fs.h>
+#include <asm/blackfin.h>
+#include <asm/time.h>
+
+
+/* this is the table of CCLK frequencies, in Hz */
+/* .index is the entry in the auxillary dpm_state_table[] */
+static struct cpufreq_frequency_table bfin_freq_table[] = {
+       {
+               .frequency = CPUFREQ_TABLE_END,
+               .index = 0,
+       },
+       {
+               .frequency = CPUFREQ_TABLE_END,
+               .index = 1,
+       },
+       {
+               .frequency = CPUFREQ_TABLE_END,
+               .index = 2,
+       },
+       {
+               .frequency = CPUFREQ_TABLE_END,
+               .index = 0,
+       },
+};
+
+static struct bfin_dpm_state {
+       unsigned int csel; /* system clock divider */
+       unsigned int tscale; /* change the divider on the core timer interrupt */
+} dpm_state_table[3];
+
+/**************************************************************************/
+
+static unsigned int bfin_getfreq(unsigned int cpu)
+{
+       /* The driver only support single cpu */
+       if (cpu != 0)
+               return -1;
+
+       return get_cclk();
+}
+
+
+static int bfin_target(struct cpufreq_policy *policy,
+                       unsigned int target_freq, unsigned int relation)
+{
+       unsigned int index, plldiv, tscale;
+       unsigned long flags, cclk_hz;
+       struct cpufreq_freqs freqs;
+
+       if (cpufreq_frequency_table_target(policy, bfin_freq_table,
+                target_freq, relation, &index))
+               return -EINVAL;
+
+       cclk_hz = bfin_freq_table[index].frequency;
+
+       freqs.old = bfin_getfreq(0);
+       freqs.new = cclk_hz;
+       freqs.cpu = 0;
+
+       pr_debug("cpufreq: changing cclk to %lu; target = %u, oldfreq = %u\n",
+                cclk_hz, target_freq, freqs.old);
+
+       cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+       local_irq_save(flags);
+               plldiv = (bfin_read_PLL_DIV() & SSEL) | dpm_state_table[index].csel;
+               tscale = dpm_state_table[index].tscale;
+               bfin_write_PLL_DIV(plldiv);
+               /* we have to adjust the core timer, because it is using cclk */
+               bfin_write_TSCALE(tscale);
+               SSYNC();
+       local_irq_restore(flags);
+       cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+       return 0;
+}
+
+static int bfin_verify_speed(struct cpufreq_policy *policy)
+{
+       return cpufreq_frequency_table_verify(policy, bfin_freq_table);
+}
+
+static int __init __bfin_cpu_init(struct cpufreq_policy *policy)
+{
+
+       unsigned long cclk, sclk, csel, min_cclk;
+       int index;
+
+#ifdef CONFIG_CYCLES_CLOCKSOURCE
+/*
+ * Clocksource CYCLES is still CONTINUOUS but not longer MONOTONIC in case we enable
+ * CPU frequency scaling, since CYCLES runs off Core Clock.
+ */
+       printk(KERN_WARNING "CPU frequency scaling not supported: Clocksource not suitable\n"
+               return -ENODEV;
+#endif
+
+       if (policy->cpu != 0)
+               return -EINVAL;
+
+       cclk = get_cclk();
+       sclk = get_sclk();
+
+#if ANOMALY_05000273
+       min_cclk = sclk * 2;
+#else
+       min_cclk = sclk;
+#endif
+       csel = ((bfin_read_PLL_DIV() & CSEL) >> 4);
+
+       for (index = 0;  (cclk >> index) >= min_cclk && csel <= 3; index++, csel++) {
+               bfin_freq_table[index].frequency = cclk >> index;
+               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",
+                                                bfin_freq_table[index].frequency,
+                                                dpm_state_table[index].csel,
+                                                dpm_state_table[index].tscale);
+       }
+
+       policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
+
+       policy->cpuinfo.transition_latency = (bfin_read_PLL_LOCKCNT() / (sclk / 1000000)) * 1000;
+       /*Now ,only support one cpu */
+       policy->cur = cclk;
+       cpufreq_frequency_table_get_attr(bfin_freq_table, policy->cpu);
+       return cpufreq_frequency_table_cpuinfo(policy, bfin_freq_table);
+}
+
+static struct freq_attr *bfin_freq_attr[] = {
+       &cpufreq_freq_attr_scaling_available_freqs,
+       NULL,
+};
+
+static struct cpufreq_driver bfin_driver = {
+       .verify = bfin_verify_speed,
+       .target = bfin_target,
+       .get = bfin_getfreq,
+       .init = __bfin_cpu_init,
+       .name = "bfin cpufreq",
+       .owner = THIS_MODULE,
+       .attr = bfin_freq_attr,
+};
+
+static int __init bfin_cpu_init(void)
+{
+       return cpufreq_register_driver(&bfin_driver);
+}
+
+static void __exit bfin_cpu_exit(void)
+{
+       cpufreq_unregister_driver(&bfin_driver);
+}
+
+MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
+MODULE_DESCRIPTION("cpufreq driver for Blackfin");
+MODULE_LICENSE("GPL");
+
+module_init(bfin_cpu_init);
+module_exit(bfin_cpu_exit);
index cee54cebbc6592505e0ff2046a7cc94d2b792c15..f2fb87e9a46e29edfb5f04f2190ff337717e35da 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/unistd.h>
 #include <asm/blackfin.h>
 #include <asm/errno.h>
+#include <asm/fixed_code.h>
 #include <asm/thread_info.h>  /* TIF_NEED_RESCHED */
 #include <asm/asm-offsets.h>
 #include <asm/trace.h>
 # define EX_SCRATCH_REG CYCLES
 #endif
 
-#if ANOMALY_05000281
-ENTRY(_safe_speculative_execution)
-       NOP;
-       NOP;
-       NOP;
-       jump _safe_speculative_execution;
-ENDPROC(_safe_speculative_execution)
-#endif
-
 #ifdef CONFIG_EXCPT_IRQ_SYSC_L1
 .section .l1.text
 #else
@@ -121,10 +113,14 @@ ENTRY(_ex_icplb_miss)
        (R7:6,P5:4) = [sp++];
        ASTAT = [sp++];
        SAVE_ALL_SYS
-       DEBUG_HWTRACE_SAVE(p5, r7)
 #ifdef CONFIG_MPU
+       /* We must load R1 here, _before_ DEBUG_HWTRACE_SAVE, since that
+        * will change the stack pointer.  */
        R0 = SEQSTAT;
        R1 = SP;
+#endif
+       DEBUG_HWTRACE_SAVE(p5, r7)
+#ifdef CONFIG_MPU
        sp += -12;
        call _cplb_hdr;
        sp += 12;
@@ -191,6 +187,7 @@ ENTRY(_bfin_return_from_exception)
 ENDPROC(_bfin_return_from_exception)
 
 ENTRY(_handle_bad_cplb)
+       DEBUG_HWTRACE_RESTORE(p5, r7)
        /* To get here, we just tried and failed to change a CPLB
         * so, handle things in trap_c (C code), by lowering to
         * IRQ5, just like we normally do. Since this is not a
@@ -225,6 +222,26 @@ ENTRY(_ex_trap_c)
        [p4] = p5;
        csync;
 
+       p4.l = lo(DCPLB_FAULT_ADDR);
+       p4.h = hi(DCPLB_FAULT_ADDR);
+       r7 = [p4];
+       p5.h = _saved_dcplb_fault_addr;
+       p5.l = _saved_dcplb_fault_addr;
+       [p5] = r7;
+
+       r7 = [p4 + (ICPLB_FAULT_ADDR - DCPLB_FAULT_ADDR)];
+       p5.h = _saved_icplb_fault_addr;
+       p5.l = _saved_icplb_fault_addr;
+       [p5] = r7;
+
+       p4.l = __retx;
+       p4.h = __retx;
+       r6 = retx;
+       [p4] = r6;
+       p4.l = lo(SAFE_USER_INSTRUCTION);
+       p4.h = hi(SAFE_USER_INSTRUCTION);
+       retx = p4;
+
        /* Disable all interrupts, but make sure level 5 is enabled so
         * we can switch to that level.  Save the old mask.  */
        cli r6;
@@ -234,23 +251,6 @@ ENTRY(_ex_trap_c)
        r6 = 0x3f;
        sti r6;
 
-       /* Save the excause into a circular buffer, in case the instruction
-        * which caused this excecptions causes others.
-        */
-       P5.l = _in_ptr_excause;
-       P5.h = _in_ptr_excause;
-       R7 = [P5];
-       R7 += 4;
-       R6 = 0xF;
-       R7 = R7 & R6;
-       [P5] = R7;
-       R6.l = _excause_circ_buf;
-       R6.h = _excause_circ_buf;
-       R7 = R7 + R6;
-       p5 = R7;
-       R6 = SEQSTAT;
-       [P5] = R6;
-
        (R7:6,P5:4) = [sp++];
        ASTAT = [sp++];
        SP = EX_SCRATCH_REG;
@@ -307,6 +307,11 @@ ENDPROC(_double_fault)
 ENTRY(_exception_to_level5)
        SAVE_ALL_SYS
 
+       p4.l = __retx;
+       p4.h = __retx;
+       r6 = [p4];
+       [sp + PT_PC] = r6;
+
        /* Restore interrupt mask.  We haven't pushed RETI, so this
         * doesn't enable interrupts until we return from this handler.  */
        p4.l = _excpt_saved_imask;
@@ -328,42 +333,11 @@ ENTRY(_exception_to_level5)
        r0 = [p2];              /* Read current IPEND */
        [sp + PT_IPEND] = r0;   /* Store IPEND */
 
-       /* Pop the excause from the circular buffer and push it on the stack
-        * (in the right place - if you change the location of SEQSTAT, you
-        * must change this offset.
-        */
-.L_excep_to_5_again:
-       P5.l = _out_ptr_excause;
-       P5.h = _out_ptr_excause;
-       R7 = [P5];
-       R7 += 4;
-       R6 = 0xF;
-       R7 = R7 & R6;
-       [P5] = R7;
-       R6.l = _excause_circ_buf;
-       R6.h = _excause_circ_buf;
-       R7 = R7 + R6;
-       P5 = R7;
-       R1 = [P5];
-       [SP + PT_SEQSTAT] = r1;
-
        r0 = sp;        /* stack frame pt_regs pointer argument ==> r0 */
        SP += -12;
        call _trap_c;
        SP += 12;
 
-       /* See if anything else is in the exception buffer
-        * if there is, process it
-        */
-       P5.l = _out_ptr_excause;
-       P5.h = _out_ptr_excause;
-       P4.l = _in_ptr_excause;
-       P4.h = _in_ptr_excause;
-       R6 = [P5];
-       R7 = [P4];
-       CC = R6 == R7;
-       if ! CC JUMP .L_excep_to_5_again
-
        call _ret_from_exception;
        RESTORE_ALL_SYS
        rti;
@@ -727,8 +701,8 @@ ENTRY(_return_from_int)
        [p0] = p1;
        csync;
 #if ANOMALY_05000281
-       r0.l = _safe_speculative_execution;
-       r0.h = _safe_speculative_execution;
+       r0.l = lo(SAFE_USER_INSTRUCTION);
+       r0.h = hi(SAFE_USER_INSTRUCTION);
        reti = r0;
 #endif
        r0 = 0x801f (z);
@@ -741,8 +715,8 @@ ENDPROC(_return_from_int)
 
 ENTRY(_lower_to_irq14)
 #if ANOMALY_05000281
-       r0.l = _safe_speculative_execution;
-       r0.h = _safe_speculative_execution;
+       r0.l = lo(SAFE_USER_INSTRUCTION);
+       r0.h = hi(SAFE_USER_INSTRUCTION);
        reti = r0;
 #endif
        r0 = 0x401f;
@@ -809,20 +783,6 @@ _schedule_and_signal:
        rti;
 ENDPROC(_lower_to_irq14)
 
-/* Make sure when we start, that the circular buffer is initialized properly
- * R0 and P0 are call clobbered, so we can use them here.
- */
-ENTRY(_init_exception_buff)
-       r0 = 0;
-       p0.h = _in_ptr_excause;
-       p0.l = _in_ptr_excause;
-       [p0] = r0;
-       p0.h = _out_ptr_excause;
-       p0.l = _out_ptr_excause;
-       [p0] = r0;
-       rts;
-ENDPROC(_init_exception_buff)
-
 /* We handle this 100% in exception space - to reduce overhead
  * Only potiential problem is if the software buffer gets swapped out of the
  * CPLB table - then double fault. - so we don't let this happen in other places
@@ -1398,17 +1358,7 @@ _exception_stack_top:
 _last_cplb_fault_retx:
        .long 0;
 #endif
-/*
- * Single instructions can have multiple faults, which need to be
- * handled by traps.c, in irq5. We store the exception cause to ensure
- * we don't miss a double fault condition
- */
-ENTRY(_in_ptr_excause)
+       /* Used to save the real RETX when temporarily storing a safe
+        * return address.  */
+__retx:
        .long 0;
-ENTRY(_out_ptr_excause)
-       .long 0;
-ALIGN
-ENTRY(_excause_circ_buf)
-       .rept 4
-       .long 0
-       .endr
index 225ef14af75eade0ef629575cc5ab646db063796..f5fd768022eaeb13cab7d7be9dd24b8e86c6d5e7 100644 (file)
@@ -316,7 +316,7 @@ static void bfin_demux_error_irq(unsigned int int_err_irq,
                printk(KERN_ERR
                       "%s : %s : LINE %d :\nIRQ ?: PERIPHERAL ERROR"
                       " INTERRUPT ASSERTED BUT NO SOURCE FOUND\n",
-                      __FUNCTION__, __FILE__, __LINE__);
+                      __func__, __FILE__, __LINE__);
 
 }
 #endif                         /* BF537_GENERIC_ERROR_INT_DEMUX */
@@ -326,6 +326,7 @@ static void bfin_demux_error_irq(unsigned int int_err_irq,
 static unsigned short gpio_enabled[gpio_bank(MAX_BLACKFIN_GPIOS)];
 static unsigned short gpio_edge_triggered[gpio_bank(MAX_BLACKFIN_GPIOS)];
 
+extern void bfin_gpio_irq_prepare(unsigned gpio);
 
 static void bfin_gpio_ack_irq(unsigned int irq)
 {
@@ -364,35 +365,25 @@ static void bfin_gpio_unmask_irq(unsigned int irq)
 
 static unsigned int bfin_gpio_irq_startup(unsigned int irq)
 {
-       unsigned int ret;
        u16 gpionr = irq - IRQ_PF0;
-       char buf[8];
 
-       if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) {
-               snprintf(buf, sizeof buf, "IRQ %d", irq);
-               ret = gpio_request(gpionr, buf);
-               if (ret)
-                       return ret;
-       }
+       if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr)))
+               bfin_gpio_irq_prepare(gpionr);
 
        gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr);
        bfin_gpio_unmask_irq(irq);
 
-       return ret;
+       return 0;
 }
 
 static void bfin_gpio_irq_shutdown(unsigned int irq)
 {
        bfin_gpio_mask_irq(irq);
-       gpio_free(irq - IRQ_PF0);
        gpio_enabled[gpio_bank(irq - IRQ_PF0)] &= ~gpio_bit(irq - IRQ_PF0);
 }
 
 static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
 {
-
-       unsigned int ret;
-       char buf[8];
        u16 gpionr = irq - IRQ_PF0;
 
        if (type == IRQ_TYPE_PROBE) {
@@ -404,12 +395,8 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
 
        if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING |
                    IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
-               if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) {
-                       snprintf(buf, sizeof buf, "IRQ %d", irq);
-                       ret = gpio_request(gpionr, buf);
-                       if (ret)
-                               return ret;
-               }
+               if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr)))
+                       bfin_gpio_irq_prepare(gpionr);
 
                gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr);
        } else {
@@ -595,6 +582,8 @@ static struct pin_int_t *pint[NR_PINT_SYS_IRQS] = {
        (struct pin_int_t *)PINT3_MASK_SET,
 };
 
+extern void bfin_gpio_irq_prepare(unsigned gpio);
+
 inline unsigned short get_irq_base(u8 bank, u8 bmap)
 {
 
@@ -697,8 +686,6 @@ static void bfin_gpio_unmask_irq(unsigned int irq)
 
 static unsigned int bfin_gpio_irq_startup(unsigned int irq)
 {
-       unsigned int ret;
-       char buf[8];
        u16 gpionr = irq_to_gpio(irq);
        u8 pint_val = irq2pint_lut[irq - SYS_IRQS];
 
@@ -709,17 +696,13 @@ static unsigned int bfin_gpio_irq_startup(unsigned int irq)
                return -ENODEV;
        }
 
-       if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) {
-               snprintf(buf, sizeof buf, "IRQ %d", irq);
-               ret = gpio_request(gpionr, buf);
-               if (ret)
-                       return ret;
-       }
+       if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr)))
+               bfin_gpio_irq_prepare(gpionr);
 
        gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr);
        bfin_gpio_unmask_irq(irq);
 
-       return ret;
+       return 0;
 }
 
 static void bfin_gpio_irq_shutdown(unsigned int irq)
@@ -727,15 +710,12 @@ static void bfin_gpio_irq_shutdown(unsigned int irq)
        u16 gpionr = irq_to_gpio(irq);
 
        bfin_gpio_mask_irq(irq);
-       gpio_free(gpionr);
        gpio_enabled[gpio_bank(gpionr)] &= ~gpio_bit(gpionr);
 }
 
 static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
 {
 
-       unsigned int ret;
-       char buf[8];
        u16 gpionr = irq_to_gpio(irq);
        u8 pint_val = irq2pint_lut[irq - SYS_IRQS];
        u32 pintbit = PINT_BIT(pint_val);
@@ -753,12 +733,8 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
 
        if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING |
                    IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
-               if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) {
-                       snprintf(buf, sizeof buf, "IRQ %d", irq);
-                       ret = gpio_request(gpionr, buf);
-                       if (ret)
-                               return ret;
-               }
+               if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr)))
+                       bfin_gpio_irq_prepare(gpionr);
 
                gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr);
        } else {
@@ -766,8 +742,6 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
                return 0;
        }
 
-       gpio_direction_input(gpionr);
-
        if ((type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW)))
                pint[bank]->invert_set = pintbit;       /* low or falling edge denoted by one */
        else
@@ -965,8 +939,6 @@ int __init init_arch_irq(void)
 
        local_irq_disable();
 
-       init_exception_buff();
-
 #ifdef CONFIG_BF54x
 # ifdef CONFIG_PINTx_REASSIGN
        pint[0]->assign = CONFIG_PINT0_ASSIGN;
index 28b87fe9ce3c6f610ef610f134a4c29858629234..30b887e67dd6776def5ef53238ebe3fead7a6bbd 100644 (file)
@@ -174,7 +174,7 @@ ENTRY(_cache_lock)
        CLI R3;
 
        R7 = [P1];
-       R2 = 0xFFFFFF87 (X);
+       R2 = ~(0x78) (X);       /* mask out ILOC */
        R7 = R7 & R2;
        R0 = R0 << 3;
        R7 = R0 | R7;
index e41f0e8ecacbd33d463295897aa1454d7b1e6023..3246f91c7baa40bc87fc30436b9ec7022092b356 100644 (file)
@@ -401,7 +401,7 @@ EXPORT_SYMBOL(l1_data_sram_free);
 
 void *l1_inst_sram_alloc(size_t size)
 {
-#if L1_DATA_A_LENGTH != 0
+#if L1_CODE_LENGTH != 0
        unsigned flags;
        void *addr;
 
index cb8b8d5af34fa450f1c58273d10acf71428eff2b..0f6d303a88913f3a3d20b0f8aaea8f42f5004429 100644 (file)
@@ -75,7 +75,7 @@ static int op_bfin_start(void)
 {
        int ret = -EBUSY;
 
-       printk(KERN_INFO "KSDBG:in %s\n", __FUNCTION__);
+       printk(KERN_INFO "KSDBG:in %s\n", __func__);
        mutex_lock(&pfmon_lock);
        if (!pfmon_enabled) {
                ret = model->start(ctr);
index 872dffe3362360f6eb1e46e4d9d53961d04c359e..d1c698bb9ee5f037e0db9e0bbcadc97717b513a4 100644 (file)
@@ -125,7 +125,7 @@ int pm_overflow_handler(int irq, struct pt_regs *regs)
        unsigned int pc, pfctl;
        unsigned int count[2];
 
-       pr_debug("get interrupt in %s\n", __FUNCTION__);
+       pr_debug("get interrupt in %s\n", __func__);
        if (oprofile_running == 0) {
                pr_debug("error: entering interrupt when oprofile is stopped.\n\r");
                return -1;
index 135644f8add772c785f1afb84b4d5f5e86e83b33..484c83d23eef3e478f9e1ada60af29932cdb82d6 100644 (file)
@@ -1409,7 +1409,6 @@ syscall_is_too_hard:
 
        st      %o0, [%sp + STACKFRAME_SZ + PT_I0]
 
-       .globl  ret_sys_call
 ret_sys_call:
        ld      [%curptr + TI_FLAGS], %l6
        cmp     %o0, -ERESTART_RESTARTBLOCK
index 1f730619a24ad048ed341845fc2c5d3128d4b8a2..3e849e8e34803778a1e6d9032fa807a41b0e1912 100644 (file)
@@ -105,11 +105,6 @@ static int _sigpause_common(old_sigset_t set)
        return -ERESTARTNOHAND;
 }
 
-asmlinkage int sys_sigpause(unsigned int set)
-{
-       return _sigpause_common(set);
-}
-
 asmlinkage int sys_sigsuspend(old_sigset_t set)
 {
        return _sigpause_common(set);
index df3eacb5ca15dcaf1f716148d1dcdcc1e7c33195..8acc5cc386212c4cba07ff12b93cd2fabf0a57b6 100644 (file)
@@ -250,6 +250,26 @@ endchoice
 
 endmenu
 
+config NUMA
+       bool "NUMA support"
+
+config NODES_SHIFT
+       int
+       default "4"
+       depends on NEED_MULTIPLE_NODES
+
+# Some NUMA nodes have memory ranges that span
+# other nodes.  Even though a pfn is valid and
+# between a node's start and end pfns, it may not
+# reside on that node.  See memmap_init_zone()
+# for details.
+config NODES_SPAN_OTHER_NODES
+       def_bool y
+       depends on NEED_MULTIPLE_NODES
+
+config ARCH_POPULATES_NODE_MAP
+       def_bool y
+
 config ARCH_SELECT_MEMORY_MODEL
        def_bool y
 
index e1835868ad36f5e30b383a31c5d0f26193dc1785..92f79680f70d92da247c2e80130db38af86363ad 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.25
-# Sun Apr 20 01:33:21 2008
+# Linux kernel version: 2.6.25-numa
+# Wed Apr 23 04:49:08 2008
 #
 CONFIG_SPARC=y
 CONFIG_SPARC64=y
@@ -152,6 +152,8 @@ CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_HUGETLB_PAGE_SIZE_4MB=y
 # CONFIG_HUGETLB_PAGE_SIZE_512K is not set
 # CONFIG_HUGETLB_PAGE_SIZE_64K is not set
+# CONFIG_NUMA is not set
+CONFIG_ARCH_POPULATES_NODE_MAP=y
 CONFIG_ARCH_SELECT_MEMORY_MODEL=y
 CONFIG_ARCH_SPARSEMEM_ENABLE=y
 CONFIG_ARCH_SPARSEMEM_DEFAULT=y
@@ -787,7 +789,6 @@ CONFIG_I2C_ALGOBIT=y
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_TPS65010 is not set
 # CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
@@ -869,6 +870,7 @@ CONFIG_SSB_POSSIBLE=y
 # Multifunction device drivers
 #
 # CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
 
 #
 # Multimedia devices
@@ -1219,10 +1221,6 @@ CONFIG_USB_STORAGE=m
 # CONFIG_NEW_LEDS is not set
 # CONFIG_INFINIBAND is not set
 # CONFIG_RTC_CLASS is not set
-
-#
-# Userspace I/O
-#
 # CONFIG_UIO is not set
 
 #
@@ -1399,6 +1397,7 @@ CONFIG_SCHEDSTATS=y
 CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_INFO is not set
 # CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_BOOT_PRINTK_DELAY is not set
@@ -1425,53 +1424,82 @@ CONFIG_ASYNC_CORE=m
 CONFIG_ASYNC_MEMCPY=m
 CONFIG_ASYNC_XOR=m
 CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
 CONFIG_CRYPTO_ALGAPI=y
 CONFIG_CRYPTO_AEAD=y
 CONFIG_CRYPTO_BLKCIPHER=y
-# CONFIG_CRYPTO_SEQIV is not set
 CONFIG_CRYPTO_HASH=y
 CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+# CONFIG_CRYPTO_CRYPTD is not set
+CONFIG_CRYPTO_AUTHENC=y
+CONFIG_CRYPTO_TEST=m
+
+#
+# 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=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+
+#
+# Hash modes
+#
 CONFIG_CRYPTO_HMAC=y
 CONFIG_CRYPTO_XCBC=y
-CONFIG_CRYPTO_NULL=m
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=m
 CONFIG_CRYPTO_MD4=y
 CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_SHA1=y
 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=y
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_LRW=m
-CONFIG_CRYPTO_XTS=m
-# CONFIG_CRYPTO_CTR is not set
-# CONFIG_CRYPTO_GCM is not set
-# CONFIG_CRYPTO_CCM is not set
-# CONFIG_CRYPTO_CRYPTD is not set
-CONFIG_CRYPTO_DES=y
-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=y
+CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_SEED=m
 # CONFIG_CRYPTO_SALSA20 is not set
+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=y
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_CRC32C=m
-CONFIG_CRYPTO_CAMELLIA=m
-CONFIG_CRYPTO_TEST=m
-CONFIG_CRYPTO_AUTHENC=y
 # CONFIG_CRYPTO_LZO is not set
 CONFIG_CRYPTO_HW=y
 # CONFIG_CRYPTO_DEV_HIFN_795X is not set
@@ -1492,3 +1520,4 @@ CONFIG_PLIST=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
+CONFIG_HAVE_LMB=y
index 04ab81cb4f483f24e78c6d74c40e044d29383203..bc26322748406ece4159e3b754e0697bec000f85 100644 (file)
@@ -396,6 +396,7 @@ static void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_de
        sd->op = &dev->ofdev;
        sd->iommu = dev->bus->ofdev.dev.parent->archdata.iommu;
        sd->stc = dev->bus->ofdev.dev.parent->archdata.stc;
+       sd->numa_node = dev->bus->ofdev.dev.parent->archdata.numa_node;
 
        dev->ofdev.node = dp;
        dev->ofdev.dev.parent = &dev->bus->ofdev.dev;
index fb43c76bdc261b5be56428305d8192f8e1a03504..fd06e937ae1e5ed741c58ea62c48d91d9a2b91e3 100644 (file)
@@ -47,7 +47,7 @@ do_fpdis:
        ba,pt           %xcc, etrap
 109:    or             %g7, %lo(109b), %g7
        add             %g0, %g0, %g0
-       ba,a,pt         %xcc, rtrap_clr_l6
+       ba,a,pt         %xcc, rtrap
 
 1:     TRAP_LOAD_THREAD_REG(%g6, %g1)
        ldub            [%g6 + TI_FPSAVED], %g5
@@ -226,7 +226,7 @@ fp_other_bounce:
        call            do_fpother
         add            %sp, PTREGS_OFF, %o0
        ba,pt           %xcc, rtrap
-        clr            %l6
+        nop
 
        .globl          do_fpother_check_fitos
        .align          32
@@ -489,7 +489,7 @@ utrap_trap:         /* %g3=handler,%g4=level */
         call           bad_trap
         add            %sp, PTREGS_OFF, %o0
        ba,pt           %xcc, rtrap
-        clr            %l6
+        nop
 
 invoke_utrap:
        sllx            %g3, 3, %g3
@@ -607,7 +607,7 @@ __spitfire_cee_trap_continue:
        call            spitfire_access_error
         add            %sp, PTREGS_OFF, %o0
        ba,pt           %xcc, rtrap
-        clr            %l6
+        nop
 
        /* This is the trap handler entry point for ECC correctable
         * errors.  They are corrected, but we listen for the trap
@@ -686,7 +686,7 @@ __spitfire_data_access_exception_tl1:
        call            spitfire_data_access_exception_tl1
         add            %sp, PTREGS_OFF, %o0
        ba,pt           %xcc, rtrap
-        clr            %l6
+        nop
 
 __spitfire_data_access_exception:
        rdpr            %pstate, %g4
@@ -705,7 +705,7 @@ __spitfire_data_access_exception:
        call            spitfire_data_access_exception
         add            %sp, PTREGS_OFF, %o0
        ba,pt           %xcc, rtrap
-        clr            %l6
+        nop
 
        .globl          __spitfire_insn_access_exception
        .globl          __spitfire_insn_access_exception_tl1
@@ -725,7 +725,7 @@ __spitfire_insn_access_exception_tl1:
        call            spitfire_insn_access_exception_tl1
         add            %sp, PTREGS_OFF, %o0
        ba,pt           %xcc, rtrap
-        clr            %l6
+        nop
 
 __spitfire_insn_access_exception:
        rdpr            %pstate, %g4
@@ -743,7 +743,7 @@ __spitfire_insn_access_exception:
        call            spitfire_insn_access_exception
         add            %sp, PTREGS_OFF, %o0
        ba,pt           %xcc, rtrap
-        clr            %l6
+        nop
 
        /* These get patched into the trap table at boot time
         * once we know we have a cheetah processor.
@@ -937,7 +937,7 @@ do_dcpe_tl1_fatal:
        call            cheetah_plus_parity_error
         add            %sp, PTREGS_OFF, %o1
        ba,pt           %xcc, rtrap
-        clr            %l6
+        nop
 
 do_icpe_tl1:
        rdpr            %tl, %g1                ! Save original trap level
@@ -979,7 +979,7 @@ do_icpe_tl1_fatal:
        call            cheetah_plus_parity_error
         add            %sp, PTREGS_OFF, %o1
        ba,pt           %xcc, rtrap
-        clr            %l6
+        nop
        
 dcpe_icpe_tl1_common:
        /* Flush D-cache, re-enable D/I caches in DCU and finally
@@ -1281,7 +1281,7 @@ __do_privact:
        call            do_privact
         add            %sp, PTREGS_OFF, %o0
        ba,pt           %xcc, rtrap
-        clr            %l6
+        nop
 
        .globl          do_mna
 do_mna:
@@ -1308,7 +1308,7 @@ do_mna:
        call            mem_address_unaligned
         add            %sp, PTREGS_OFF, %o0
        ba,pt           %xcc, rtrap
-        clr            %l6
+        nop
 
        .globl          do_lddfmna
 do_lddfmna:
@@ -1326,7 +1326,7 @@ do_lddfmna:
        call            handle_lddfmna
         add            %sp, PTREGS_OFF, %o0
        ba,pt           %xcc, rtrap
-        clr            %l6
+        nop
 
        .globl          do_stdfmna
 do_stdfmna:
@@ -1344,7 +1344,7 @@ do_stdfmna:
        call            handle_stdfmna
         add            %sp, PTREGS_OFF, %o0
        ba,pt           %xcc, rtrap
-        clr            %l6
+        nop
 
        .globl  breakpoint_trap
 breakpoint_trap:
@@ -1424,13 +1424,13 @@ sys32_rt_sigreturn:
 1:             ldx             [%curptr + TI_FLAGS], %l5
                andcc           %l5, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %g0
                be,pt           %icc, rtrap
-                clr            %l6
+                nop
                add             %sp, PTREGS_OFF, %o0
                call            syscall_trace
                 mov            1, %o1
 
                ba,pt           %xcc, rtrap
-                clr            %l6
+                nop
 
        /* This is how fork() was meant to be done, 8 instruction entry.
         *
@@ -1559,7 +1559,7 @@ linux_sparc_syscall32:
 
        /* Linux native system calls enter here... */
        .align  32
-       .globl  linux_sparc_syscall, ret_sys_call
+       .globl  linux_sparc_syscall
 linux_sparc_syscall:
        /* Direct access to user regs, much faster. */
        cmp             %g1, NR_SYSCALLS                        ! IEU1  Group
@@ -1605,7 +1605,7 @@ ret_sys_call:
        bne,pn          %icc, linux_syscall_trace2
         add            %l1, 0x4, %l2                   ! npc = npc+4
        stx             %l1, [%sp + PTREGS_OFF + PT_V9_TPC]
-       ba,pt           %xcc, rtrap_clr_l6
+       ba,pt           %xcc, rtrap
         stx            %l2, [%sp + PTREGS_OFF + PT_V9_TNPC]
 
 1:
@@ -1616,7 +1616,6 @@ ret_sys_call:
        sub             %g0, %o0, %o0
        or              %g3, %g2, %g3
        stx             %o0, [%sp + PTREGS_OFF + PT_V9_I0]
-       mov             1, %l6
        stx             %g3, [%sp + PTREGS_OFF + PT_V9_TSTATE]
        bne,pn          %icc, linux_syscall_trace2
         add            %l1, 0x4, %l2                   ! npc = npc+4
index 4a91e9c6d31b755ba087c7a1ec4a3693b45b2d25..32fbab620852063dbe525bf3e9e32720af8b2323 100644 (file)
@@ -20,7 +20,6 @@ extern void timer_interrupt(int irq, struct pt_regs *regs);
 
 extern void do_notify_resume(struct pt_regs *regs,
                             unsigned long orig_i0,
-                            int restart_syscall,
                             unsigned long thread_info_flags);
 
 extern asmlinkage void syscall_trace(struct pt_regs *regs,
index 4b2bf9eb447a1f5eaa7c93b27627c0c217a9937b..b49d3b60bc0ca267cb79a61dc293c29d7faae83b 100644 (file)
@@ -53,7 +53,11 @@ etrap_irq:
                stx     %g3, [%g2 + STACKFRAME_SZ + PT_V9_TPC]
                rd      %y, %g3
                stx     %g1, [%g2 + STACKFRAME_SZ + PT_V9_TNPC]
+               rdpr    %tt, %g1
                st      %g3, [%g2 + STACKFRAME_SZ + PT_V9_Y]
+               sethi   %hi(PT_REGS_MAGIC), %g3
+               or      %g3, %g1, %g1
+               st      %g1, [%g2 + STACKFRAME_SZ + PT_V9_MAGIC]
 
                rdpr    %cansave, %g1
                brnz,pt %g1, etrap_save
index 756fa24eeefa18ae72da4a4825e8ba7f143cf682..2a37a6ca2a16d46e5dd5ea5680230b56e11bedb3 100644 (file)
@@ -173,9 +173,11 @@ void iommu_range_free(struct iommu *iommu, dma_addr_t dma_addr, unsigned long np
 }
 
 int iommu_table_init(struct iommu *iommu, int tsbsize,
-                    u32 dma_offset, u32 dma_addr_mask)
+                    u32 dma_offset, u32 dma_addr_mask,
+                    int numa_node)
 {
-       unsigned long i, tsbbase, order, sz, num_tsb_entries;
+       unsigned long i, order, sz, num_tsb_entries;
+       struct page *page;
 
        num_tsb_entries = tsbsize / sizeof(iopte_t);
 
@@ -188,11 +190,12 @@ int iommu_table_init(struct iommu *iommu, int tsbsize,
        /* Allocate and initialize the free area map.  */
        sz = num_tsb_entries / 8;
        sz = (sz + 7UL) & ~7UL;
-       iommu->arena.map = kzalloc(sz, GFP_KERNEL);
+       iommu->arena.map = kmalloc_node(sz, GFP_KERNEL, numa_node);
        if (!iommu->arena.map) {
                printk(KERN_ERR "IOMMU: Error, kmalloc(arena.map) failed.\n");
                return -ENOMEM;
        }
+       memset(iommu->arena.map, 0, sz);
        iommu->arena.limit = num_tsb_entries;
 
        if (tlb_type != hypervisor)
@@ -201,21 +204,23 @@ int iommu_table_init(struct iommu *iommu, int tsbsize,
        /* Allocate and initialize the dummy page which we
         * set inactive IO PTEs to point to.
         */
-       iommu->dummy_page = get_zeroed_page(GFP_KERNEL);
-       if (!iommu->dummy_page) {
+       page = alloc_pages_node(numa_node, GFP_KERNEL, 0);
+       if (!page) {
                printk(KERN_ERR "IOMMU: Error, gfp(dummy_page) failed.\n");
                goto out_free_map;
        }
+       iommu->dummy_page = (unsigned long) page_address(page);
+       memset((void *)iommu->dummy_page, 0, PAGE_SIZE);
        iommu->dummy_page_pa = (unsigned long) __pa(iommu->dummy_page);
 
        /* Now allocate and setup the IOMMU page table itself.  */
        order = get_order(tsbsize);
-       tsbbase = __get_free_pages(GFP_KERNEL, order);
-       if (!tsbbase) {
+       page = alloc_pages_node(numa_node, GFP_KERNEL, order);
+       if (!page) {
                printk(KERN_ERR "IOMMU: Error, gfp(tsb) failed.\n");
                goto out_free_dummy_page;
        }
-       iommu->page_table = (iopte_t *)tsbbase;
+       iommu->page_table = (iopte_t *)page_address(page);
 
        for (i = 0; i < num_tsb_entries; i++)
                iopte_make_dummy(iommu, &iommu->page_table[i]);
@@ -276,20 +281,24 @@ static inline void iommu_free_ctx(struct iommu *iommu, int ctx)
 static void *dma_4u_alloc_coherent(struct device *dev, size_t size,
                                   dma_addr_t *dma_addrp, gfp_t gfp)
 {
+       unsigned long flags, order, first_page;
        struct iommu *iommu;
+       struct page *page;
+       int npages, nid;
        iopte_t *iopte;
-       unsigned long flags, order, first_page;
        void *ret;
-       int npages;
 
        size = IO_PAGE_ALIGN(size);
        order = get_order(size);
        if (order >= 10)
                return NULL;
 
-       first_page = __get_free_pages(gfp, order);
-       if (first_page == 0UL)
+       nid = dev->archdata.numa_node;
+       page = alloc_pages_node(nid, gfp, order);
+       if (unlikely(!page))
                return NULL;
+
+       first_page = (unsigned long) page_address(page);
        memset((char *)first_page, 0, PAGE_SIZE << order);
 
        iommu = dev->archdata.iommu;
index b5f7b354084f6d91d1da68e2374d7d409f1c5416..a2af5ed784c99bd12def0527f8dccecbbc120725 100644 (file)
@@ -92,6 +92,7 @@ static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br)
                sd->op = &isa_dev->ofdev;
                sd->iommu = isa_br->ofdev.dev.parent->archdata.iommu;
                sd->stc = isa_br->ofdev.dev.parent->archdata.stc;
+               sd->numa_node = isa_br->ofdev.dev.parent->archdata.numa_node;
 
                isa_dev->ofdev.node = dp;
                isa_dev->ofdev.dev.parent = &isa_br->ofdev.dev;
index 9100835895691e1c8f93f6ac38b8bfcf42db7132..dde52bcf5c64e11daa1cd22558238ebd45eb46b9 100644 (file)
@@ -1,10 +1,10 @@
 /* mdesc.c: Sun4V machine description handling.
  *
- * Copyright (C) 2007 David S. Miller <davem@davemloft.net>
+ * Copyright (C) 2007, 2008 David S. Miller <davem@davemloft.net>
  */
 #include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/bootmem.h>
+#include <linux/lmb.h>
 #include <linux/log2.h>
 #include <linux/list.h>
 #include <linux/slab.h>
@@ -84,24 +84,28 @@ static void mdesc_handle_init(struct mdesc_handle *hp,
        hp->handle_size = handle_size;
 }
 
-static struct mdesc_handle * __init mdesc_bootmem_alloc(unsigned int mdesc_size)
+static struct mdesc_handle * __init mdesc_lmb_alloc(unsigned int mdesc_size)
 {
-       struct mdesc_handle *hp;
        unsigned int handle_size, alloc_size;
+       struct mdesc_handle *hp;
+       unsigned long paddr;
 
        handle_size = (sizeof(struct mdesc_handle) -
                       sizeof(struct mdesc_hdr) +
                       mdesc_size);
        alloc_size = PAGE_ALIGN(handle_size);
 
-       hp = __alloc_bootmem(alloc_size, PAGE_SIZE, 0UL);
-       if (hp)
-               mdesc_handle_init(hp, handle_size, hp);
+       paddr = lmb_alloc(alloc_size, PAGE_SIZE);
 
+       hp = NULL;
+       if (paddr) {
+               hp = __va(paddr);
+               mdesc_handle_init(hp, handle_size, hp);
+       }
        return hp;
 }
 
-static void mdesc_bootmem_free(struct mdesc_handle *hp)
+static void mdesc_lmb_free(struct mdesc_handle *hp)
 {
        unsigned int alloc_size, handle_size = hp->handle_size;
        unsigned long start, end;
@@ -124,9 +128,9 @@ static void mdesc_bootmem_free(struct mdesc_handle *hp)
        }
 }
 
-static struct mdesc_mem_ops bootmem_mdesc_ops = {
-       .alloc = mdesc_bootmem_alloc,
-       .free  = mdesc_bootmem_free,
+static struct mdesc_mem_ops lmb_mdesc_ops = {
+       .alloc = mdesc_lmb_alloc,
+       .free  = mdesc_lmb_free,
 };
 
 static struct mdesc_handle *mdesc_kmalloc(unsigned int mdesc_size)
@@ -888,7 +892,7 @@ void __init sun4v_mdesc_init(void)
 
        printk("MDESC: Size is %lu bytes.\n", len);
 
-       hp = mdesc_alloc(len, &bootmem_mdesc_ops);
+       hp = mdesc_alloc(len, &lmb_mdesc_ops);
        if (hp == NULL) {
                prom_printf("MDESC: alloc of %lu bytes failed.\n", len);
                prom_halt();
index 0fd9db95b896415773e0208f390457b4c263b19d..9e58e8cba1c38655fdd7138526d9dc29e60ca5c1 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/mod_devicetable.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
+#include <linux/irq.h>
 #include <linux/of_device.h>
 #include <linux/of_platform.h>
 
@@ -660,6 +661,7 @@ static unsigned int __init build_one_device_irq(struct of_device *op,
        struct device_node *dp = op->node;
        struct device_node *pp, *ip;
        unsigned int orig_irq = irq;
+       int nid;
 
        if (irq == 0xffffffff)
                return irq;
@@ -672,7 +674,7 @@ static unsigned int __init build_one_device_irq(struct of_device *op,
                        printk("%s: direct translate %x --> %x\n",
                               dp->full_name, orig_irq, irq);
 
-               return irq;
+               goto out;
        }
 
        /* Something more complicated.  Walk up to the root, applying
@@ -744,6 +746,14 @@ static unsigned int __init build_one_device_irq(struct of_device *op,
                printk("%s: Apply IRQ trans [%s] %x --> %x\n",
                       op->node->full_name, ip->full_name, orig_irq, irq);
 
+out:
+       nid = of_node_to_nid(dp);
+       if (nid != -1) {
+               cpumask_t numa_mask = node_to_cpumask(nid);
+
+               irq_set_affinity(irq, numa_mask);
+       }
+
        return irq;
 }
 
index 545356b00e2e14c956841ba8dc751041782d5ef3..49f912766519c493ebf51db93e4c2ced79a81db8 100644 (file)
@@ -369,10 +369,12 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
        sd->host_controller = pbm;
        sd->prom_node = node;
        sd->op = of_find_device_by_node(node);
+       sd->numa_node = pbm->numa_node;
 
        sd = &sd->op->dev.archdata;
        sd->iommu = pbm->iommu;
        sd->stc = &pbm->stc;
+       sd->numa_node = pbm->numa_node;
 
        type = of_get_property(node, "device_type", NULL);
        if (type == NULL)
@@ -1159,6 +1161,16 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
        return 0;
 }
 
+#ifdef CONFIG_NUMA
+int pcibus_to_node(struct pci_bus *pbus)
+{
+       struct pci_pbm_info *pbm = pbus->sysdata;
+
+       return pbm->numa_node;
+}
+EXPORT_SYMBOL(pcibus_to_node);
+#endif
+
 /* Return the domain nuber for this pci bus */
 
 int pci_domain_nr(struct pci_bus *pbus)
index 7571ed563147295623c41fce6f9def73d0dc8993..d23bb6f53cdac8e09225f7a8b95c01f6d40a38be 100644 (file)
@@ -71,7 +71,8 @@ static int pci_fire_pbm_iommu_init(struct pci_pbm_info *pbm)
         */
        fire_write(iommu->iommu_flushinv, ~(u64)0);
 
-       err = iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask);
+       err = iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask,
+                              pbm->numa_node);
        if (err)
                return err;
 
@@ -449,6 +450,8 @@ static int __init pci_fire_pbm_init(struct pci_controller_info *p,
        pbm->next = pci_pbm_root;
        pci_pbm_root = pbm;
 
+       pbm->numa_node = -1;
+
        pbm->scan_bus = pci_fire_scan_bus;
        pbm->pci_ops = &sun4u_pci_ops;
        pbm->config_space_reg_bits = 12;
index 4a50da13ce4899d7641cceb667e13652a2d46c32..218bac4ff79bdaf18fae0acb0d54e64e8ceae703 100644 (file)
@@ -148,6 +148,8 @@ struct pci_pbm_info {
        struct pci_bus                  *pci_bus;
        void (*scan_bus)(struct pci_pbm_info *);
        struct pci_ops                  *pci_ops;
+
+       int                             numa_node;
 };
 
 struct pci_controller_info {
@@ -161,8 +163,6 @@ extern struct pci_pbm_info *pci_pbm_root;
 extern int pci_num_pbms;
 
 /* PCI bus scanning and fixup support. */
-extern void pci_iommu_table_init(struct iommu *iommu, int tsbsize,
-                                u32 dma_offset, u32 dma_addr_mask);
 extern void pci_get_pbm_props(struct pci_pbm_info *pbm);
 extern struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm);
 extern void pci_determine_mem_io_space(struct pci_pbm_info *pbm);
index d6d64b44af63da31e2512475f4e6167203758ea3..db5e8fd8f6742281bea1a643f46eefb317551ae5 100644 (file)
@@ -279,11 +279,17 @@ static int bringup_one_msi_queue(struct pci_pbm_info *pbm,
                                 unsigned long devino)
 {
        int irq = ops->msiq_build_irq(pbm, msiqid, devino);
-       int err;
+       int err, nid;
 
        if (irq < 0)
                return irq;
 
+       nid = pbm->numa_node;
+       if (nid != -1) {
+               cpumask_t numa_mask = node_to_cpumask(nid);
+
+               irq_set_affinity(irq, numa_mask);
+       }
        err = request_irq(irq, sparc64_msiq_interrupt, 0,
                          "MSIQ",
                          &pbm->msiq_irq_cookies[msiqid - pbm->msiq_first]);
index 0bad96e5d184a3d6d983e31d90f743e43275111d..994dbe0603da037c8a76ee7a7f0e27c5eabc2f42 100644 (file)
@@ -848,7 +848,8 @@ static int psycho_iommu_init(struct pci_pbm_info *pbm)
        /* Leave diag mode enabled for full-flushing done
         * in pci_iommu.c
         */
-       err = iommu_table_init(iommu, IO_TSB_SIZE, 0xc0000000, 0xffffffff);
+       err = iommu_table_init(iommu, IO_TSB_SIZE, 0xc0000000, 0xffffffff,
+                              pbm->numa_node);
        if (err)
                return err;
 
@@ -979,6 +980,8 @@ static void __init psycho_pbm_init(struct pci_controller_info *p,
        pbm->next = pci_pbm_root;
        pci_pbm_root = pbm;
 
+       pbm->numa_node = -1;
+
        pbm->scan_bus = psycho_scan_bus;
        pbm->pci_ops = &sun4u_pci_ops;
        pbm->config_space_reg_bits = 8;
index 1c5f5fa2339f30de8504ced049d6f393020b030b..4c34195baf37f5e675dabb35986edb61e4a590da 100644 (file)
@@ -704,7 +704,7 @@ static int sabre_iommu_init(struct pci_pbm_info *pbm,
         * in pci_iommu.c
         */
        err = iommu_table_init(iommu, tsbsize * 1024 * 8,
-                              dvma_offset, dma_mask);
+                              dvma_offset, dma_mask, pbm->numa_node);
        if (err)
                return err;
 
@@ -737,6 +737,8 @@ static void __init sabre_pbm_init(struct pci_controller_info *p,
        pbm->name = dp->full_name;
        printk("%s: SABRE PCI Bus Module\n", pbm->name);
 
+       pbm->numa_node = -1;
+
        pbm->scan_bus = sabre_scan_bus;
        pbm->pci_ops = &sun4u_pci_ops;
        pbm->config_space_reg_bits = 8;
index e306093623222a645900c559ad3286f5e90071df..615edd9c8e2af2c883363b9a337079f24a5a3d22 100644 (file)
@@ -1220,7 +1220,8 @@ static int schizo_pbm_iommu_init(struct pci_pbm_info *pbm)
        /* Leave diag mode enabled for full-flushing done
         * in pci_iommu.c
         */
-       err = iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask);
+       err = iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask,
+                              pbm->numa_node);
        if (err)
                return err;
 
@@ -1379,6 +1380,8 @@ static int __init schizo_pbm_init(struct pci_controller_info *p,
        pbm->next = pci_pbm_root;
        pci_pbm_root = pbm;
 
+       pbm->numa_node = -1;
+
        pbm->scan_bus = schizo_scan_bus;
        pbm->pci_ops = &sun4u_pci_ops;
        pbm->config_space_reg_bits = 8;
index 01839706bd520b17c73a548d5225e3b1cc238720..e2bb9790039c5b47f9e6b85a8bd35f387665d7ce 100644 (file)
@@ -127,10 +127,12 @@ static inline long iommu_batch_end(void)
 static void *dma_4v_alloc_coherent(struct device *dev, size_t size,
                                   dma_addr_t *dma_addrp, gfp_t gfp)
 {
-       struct iommu *iommu;
        unsigned long flags, order, first_page, npages, n;
+       struct iommu *iommu;
+       struct page *page;
        void *ret;
        long entry;
+       int nid;
 
        size = IO_PAGE_ALIGN(size);
        order = get_order(size);
@@ -139,10 +141,12 @@ static void *dma_4v_alloc_coherent(struct device *dev, size_t size,
 
        npages = size >> IO_PAGE_SHIFT;
 
-       first_page = __get_free_pages(gfp, order);
-       if (unlikely(first_page == 0UL))
+       nid = dev->archdata.numa_node;
+       page = alloc_pages_node(nid, gfp, order);
+       if (unlikely(!page))
                return NULL;
 
+       first_page = (unsigned long) page_address(page);
        memset((char *)first_page, 0, PAGE_SIZE << order);
 
        iommu = dev->archdata.iommu;
@@ -899,6 +903,8 @@ static void __init pci_sun4v_pbm_init(struct pci_controller_info *p,
        pbm->next = pci_pbm_root;
        pci_pbm_root = pbm;
 
+       pbm->numa_node = of_node_to_nid(dp);
+
        pbm->scan_bus = pci_sun4v_scan_bus;
        pbm->pci_ops = &sun4v_pci_ops;
        pbm->config_space_reg_bits = 12;
@@ -913,6 +919,7 @@ static void __init pci_sun4v_pbm_init(struct pci_controller_info *p,
        pbm->name = dp->full_name;
 
        printk("%s: SUN4V PCI Bus Module\n", pbm->name);
+       printk("%s: On NUMA node %d\n", pbm->name, pbm->numa_node);
 
        pci_determine_mem_io_space(pbm);
 
index 68964ddcde1e53bd5ce77207815cfe0bbc2068f3..ed03a18d3b36da1b48148109595b0443733492b0 100644 (file)
@@ -19,8 +19,8 @@
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/mm.h>
-#include <linux/bootmem.h>
 #include <linux/module.h>
+#include <linux/lmb.h>
 
 #include <asm/prom.h>
 #include <asm/of_device.h>
@@ -122,16 +122,20 @@ int of_find_in_proplist(const char *list, const char *match, int len)
 }
 EXPORT_SYMBOL(of_find_in_proplist);
 
-static unsigned int prom_early_allocated;
+static unsigned int prom_early_allocated __initdata;
 
 static void * __init prom_early_alloc(unsigned long size)
 {
+       unsigned long paddr = lmb_alloc(size, SMP_CACHE_BYTES);
        void *ret;
 
-       ret = __alloc_bootmem(size, SMP_CACHE_BYTES, 0UL);
-       if (ret != NULL)
-               memset(ret, 0, size);
+       if (!paddr) {
+               prom_printf("prom_early_alloc(%lu) failed\n");
+               prom_halt();
+       }
 
+       ret = __va(paddr);
+       memset(ret, 0, size);
        prom_early_allocated += size;
 
        return ret;
index 079d18a11d247fcb3ee668e06438004bb500db74..ecf6753b204a07d2da8b5a9c1bad0bbc35995218 100644 (file)
 #define                RTRAP_PSTATE_IRQOFF     (PSTATE_RMO|PSTATE_PEF|PSTATE_PRIV)
 #define                RTRAP_PSTATE_AG_IRQOFF  (PSTATE_RMO|PSTATE_PEF|PSTATE_PRIV|PSTATE_AG)
 
-               /* Register %l6 keeps track of whether we are returning
-                * from a system call or not.  It is cleared if we call
-                * do_notify_resume, and it must not be otherwise modified
-                * until we fully commit to returning to userspace.
-                */
-
                .text
                .align                  32
 __handle_softirq:
@@ -56,14 +50,12 @@ __handle_user_windows:
                be,pt                   %xcc, __handle_user_windows_continue
                 nop
                mov                     %l5, %o1
-               mov                     %l6, %o2
                add                     %sp, PTREGS_OFF, %o0
-               mov                     %l0, %o3
+               mov                     %l0, %o2
 
                call                    do_notify_resume
                 wrpr                   %g0, RTRAP_PSTATE, %pstate
                wrpr                    %g0, RTRAP_PSTATE_IRQOFF, %pstate
-               clr                     %l6
                /* Signal delivery can modify pt_regs tstate, so we must
                 * reload it.
                 */
@@ -99,14 +91,12 @@ __handle_perfctrs:
                be,pt                   %xcc, __handle_perfctrs_continue
                 sethi                  %hi(TSTATE_PEF), %o0
                mov                     %l5, %o1
-               mov                     %l6, %o2
                add                     %sp, PTREGS_OFF, %o0
-               mov                     %l0, %o3
+               mov                     %l0, %o2
                call                    do_notify_resume
 
                 wrpr                   %g0, RTRAP_PSTATE, %pstate
                wrpr                    %g0, RTRAP_PSTATE_IRQOFF, %pstate
-               clr                     %l6
                /* Signal delivery can modify pt_regs tstate, so we must
                 * reload it.
                 */
@@ -127,13 +117,11 @@ __handle_userfpu:
 
 __handle_signal:
                mov                     %l5, %o1
-               mov                     %l6, %o2
                add                     %sp, PTREGS_OFF, %o0
-               mov                     %l0, %o3
+               mov                     %l0, %o2
                call                    do_notify_resume
                 wrpr                   %g0, RTRAP_PSTATE, %pstate
                wrpr                    %g0, RTRAP_PSTATE_IRQOFF, %pstate
-               clr                     %l6
 
                /* Signal delivery can modify pt_regs tstate, so we must
                 * reload it.
@@ -145,9 +133,8 @@ __handle_signal:
                 andn                   %l1, %l4, %l1
 
                .align                  64
-               .globl                  rtrap_irq, rtrap_clr_l6, rtrap, irqsz_patchme, rtrap_xcall
+               .globl                  rtrap_irq, rtrap, irqsz_patchme, rtrap_xcall
 rtrap_irq:
-rtrap_clr_l6:  clr                     %l6
 rtrap:
 #ifndef CONFIG_SMP
                sethi                   %hi(per_cpu____cpu_data), %l0
index d1fb13ba02b59e75d56a9259e9f188e0784f3d38..fa2827c4a3adb267109f1634b3a5e982ca78399c 100644 (file)
@@ -544,6 +544,7 @@ static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus)
 
        sbus->ofdev.dev.archdata.iommu = iommu;
        sbus->ofdev.dev.archdata.stc = strbuf;
+       sbus->ofdev.dev.archdata.numa_node = -1;
 
        reg_base = regs + SYSIO_IOMMUREG_BASE;
        iommu->iommu_control = reg_base + IOMMU_CONTROL;
@@ -575,7 +576,7 @@ static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus)
               sbus->portid, regs);
 
        /* Setup for TSB_SIZE=7, TBW_SIZE=0, MMU_DE=1, MMU_EN=1 */
-       if (iommu_table_init(iommu, IO_TSB_SIZE, MAP_BASE, 0xffffffff))
+       if (iommu_table_init(iommu, IO_TSB_SIZE, MAP_BASE, 0xffffffff, -1))
                goto fatal_memory_error;
 
        control = upa_readq(iommu->iommu_control);
index 6acb4c51cfe4944e3d8c8dae77417515e64514cc..da5e6ee0c6617b29cbfb8a180e1d82241a2b884a 100644 (file)
@@ -82,7 +82,7 @@ unsigned long cmdline_memory_size = 0;
 static struct console prom_early_console = {
        .name =         "earlyprom",
        .write =        prom_console_write,
-       .flags =        CON_PRINTBUFFER | CON_BOOT,
+       .flags =        CON_PRINTBUFFER | CON_BOOT | CON_ANYTIME,
        .index =        -1,
 };
 
@@ -281,6 +281,7 @@ void __init setup_arch(char **cmdline_p)
        /* Initialize PROM console and command line. */
        *cmdline_p = prom_getbootargs();
        strcpy(boot_command_line, *cmdline_p);
+       parse_early_param();
 
        boot_flags_init(*cmdline_p);
        register_console(&prom_early_console);
index 1c47009eb5ec09068e7417d4c158c97c841c230d..77a3e8592cbcfb25a6475ff0070339dd468c6710 100644 (file)
@@ -510,15 +510,20 @@ static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
  * want to handle. Thus you cannot kill init even with a SIGKILL even by
  * mistake.
  */
-static void do_signal(struct pt_regs *regs, unsigned long orig_i0, int restart_syscall)
+static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
 {
-       siginfo_t info;
        struct signal_deliver_cookie cookie;
        struct k_sigaction ka;
-       int signr;
        sigset_t *oldset;
+       siginfo_t info;
+       int signr, tt;
        
-       cookie.restart_syscall = restart_syscall;
+       tt = regs->magic & 0x1ff;
+       if (tt == 0x110 || tt == 0x111 || tt == 0x16d) {
+               regs->magic &= ~0x1ff;
+               cookie.restart_syscall = 1;
+       } else
+               cookie.restart_syscall = 0;
        cookie.orig_i0 = orig_i0;
 
        if (test_thread_flag(TIF_RESTORE_SIGMASK))
@@ -529,9 +534,8 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0, int restart_s
 #ifdef CONFIG_SPARC32_COMPAT
        if (test_thread_flag(TIF_32BIT)) {
                extern void do_signal32(sigset_t *, struct pt_regs *,
-                                       unsigned long, int);
-               do_signal32(oldset, regs, orig_i0,
-                           cookie.restart_syscall);
+                                       struct signal_deliver_cookie *);
+               do_signal32(oldset, regs, &cookie);
                return;
        }
 #endif 
@@ -539,7 +543,7 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0, int restart_s
        signr = get_signal_to_deliver(&info, &ka, regs, &cookie);
        if (signr > 0) {
                if (cookie.restart_syscall)
-                       syscall_restart(orig_i0, regs, &ka.sa);
+                       syscall_restart(cookie.orig_i0, regs, &ka.sa);
                handle_signal(signr, &ka, &info, oldset, regs);
 
                /* a signal was successfully delivered; the saved
@@ -576,11 +580,10 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0, int restart_s
        }
 }
 
-void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, int restart_syscall,
-                     unsigned long thread_info_flags)
+void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, unsigned long thread_info_flags)
 {
        if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
-               do_signal(regs, orig_i0, restart_syscall);
+               do_signal(regs, orig_i0);
 }
 
 void ptrace_signal_deliver(struct pt_regs *regs, void *cookie)
index 74e0512f135c9380d35f06f98aed5a5949406b98..43cdec64d9c9014c9b53380cc69632702e0639ca 100644 (file)
@@ -982,20 +982,16 @@ static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs
  * mistake.
  */
 void do_signal32(sigset_t *oldset, struct pt_regs * regs,
-                unsigned long orig_i0, int restart_syscall)
+                struct signal_deliver_cookie *cookie)
 {
-       siginfo_t info;
-       struct signal_deliver_cookie cookie;
        struct k_sigaction ka;
+       siginfo_t info;
        int signr;
        
-       cookie.restart_syscall = restart_syscall;
-       cookie.orig_i0 = orig_i0;
-
-       signr = get_signal_to_deliver(&info, &ka, regs, &cookie);
+       signr = get_signal_to_deliver(&info, &ka, regs, cookie);
        if (signr > 0) {
-               if (cookie.restart_syscall)
-                       syscall_restart32(orig_i0, regs, &ka.sa);
+               if (cookie->restart_syscall)
+                       syscall_restart32(cookie->orig_i0, regs, &ka.sa);
                handle_signal32(signr, &ka, &info, oldset, regs);
 
                /* a signal was successfully delivered; the saved
@@ -1007,16 +1003,16 @@ void do_signal32(sigset_t *oldset, struct pt_regs * regs,
                        clear_thread_flag(TIF_RESTORE_SIGMASK);
                return;
        }
-       if (cookie.restart_syscall &&
+       if (cookie->restart_syscall &&
            (regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
             regs->u_regs[UREG_I0] == ERESTARTSYS ||
             regs->u_regs[UREG_I0] == ERESTARTNOINTR)) {
                /* replay the system call when we are done */
-               regs->u_regs[UREG_I0] = cookie.orig_i0;
+               regs->u_regs[UREG_I0] = cookie->orig_i0;
                regs->tpc -= 4;
                regs->tnpc -= 4;
        }
-       if (cookie.restart_syscall &&
+       if (cookie->restart_syscall &&
            regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) {
                regs->u_regs[UREG_G1] = __NR_restart_syscall;
                regs->tpc -= 4;
index 59f020d69d4c246c82c2a434eeb15b0d310a8c08..524b88920947d268233825aefec54b549d0ba21f 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/cache.h>
 #include <linux/jiffies.h>
 #include <linux/profile.h>
-#include <linux/bootmem.h>
+#include <linux/lmb.h>
 
 #include <asm/head.h>
 #include <asm/ptrace.h>
@@ -1431,7 +1431,7 @@ EXPORT_SYMBOL(__per_cpu_shift);
 
 void __init real_setup_per_cpu_areas(void)
 {
-       unsigned long goal, size, i;
+       unsigned long paddr, goal, size, i;
        char *ptr;
 
        /* Copy section for each CPU (we discard the original) */
@@ -1441,8 +1441,13 @@ void __init real_setup_per_cpu_areas(void)
        for (size = PAGE_SIZE; size < goal; size <<= 1UL)
                __per_cpu_shift++;
 
-       ptr = alloc_bootmem_pages(size * NR_CPUS);
+       paddr = lmb_alloc(size * NR_CPUS, PAGE_SIZE);
+       if (!paddr) {
+               prom_printf("Cannot allocate per-cpu memory.\n");
+               prom_halt();
+       }
 
+       ptr = __va(paddr);
        __per_cpu_base = ptr - __per_cpu_start;
 
        for (i = 0; i < NR_CPUS; i++, ptr += size)
index 38736460b8dbc86a76c7af4be6220fbe6d64e760..66336590e83087c1698c9e4b25f4bbde14cf688f 100644 (file)
@@ -68,8 +68,6 @@ extern void *__memscan_zero(void *, size_t);
 extern void *__memscan_generic(void *, int, size_t);
 extern int __memcmp(const void *, const void *, __kernel_size_t);
 extern __kernel_size_t strlen(const char *);
-extern void linux_sparc_syscall(void);
-extern void rtrap(void);
 extern void show_regs(struct pt_regs *);
 extern void syscall_trace(struct pt_regs *, int);
 extern void sys_sigsuspend(void);
index 84d39e873e880655d32b4b1ceb05ea32ddc9cf79..01b52f561af49f86a0bb5e0f1513af60fe9aaef4 100644 (file)
@@ -20,6 +20,8 @@ void save_stack_trace(struct stack_trace *trace)
        thread_base = (unsigned long) tp;
        do {
                struct reg_window *rw;
+               struct pt_regs *regs;
+               unsigned long pc;
 
                /* Bogus frame pointer? */
                if (fp < (thread_base + sizeof(struct thread_info)) ||
@@ -27,11 +29,19 @@ void save_stack_trace(struct stack_trace *trace)
                        break;
 
                rw = (struct reg_window *) fp;
+               regs = (struct pt_regs *) (rw + 1);
+
+               if ((regs->magic & ~0x1ff) == PT_REGS_MAGIC) {
+                       pc = regs->tpc;
+                       fp = regs->u_regs[UREG_I6] + STACK_BIAS;
+               } else {
+                       pc = rw->ins[7];
+                       fp = rw->ins[6] + STACK_BIAS;
+               }
+
                if (trace->skip > 0)
                        trace->skip--;
                else
-                       trace->entries[trace->nr_entries++] = rw->ins[7];
-
-               fp = rw->ins[6] + STACK_BIAS;
+                       trace->entries[trace->nr_entries++] = pc;
        } while (trace->nr_entries < trace->max_entries);
 }
index fd9430562e0be4c20f558fd9a903db6e2f212013..e1fbf8c75787ce02ee840177d4556c4eeaf7d4c8 100644 (file)
@@ -262,7 +262,7 @@ sun4v_iacc:
        mov     %l5, %o2
        call    sun4v_insn_access_exception
         add    %sp, PTREGS_OFF, %o0
-       ba,a,pt %xcc, rtrap_clr_l6
+       ba,a,pt %xcc, rtrap
 
        /* Instruction Access Exception, tl1. */
 sun4v_iacc_tl1:
@@ -278,7 +278,7 @@ sun4v_iacc_tl1:
        mov     %l5, %o2
        call    sun4v_insn_access_exception_tl1
         add    %sp, PTREGS_OFF, %o0
-       ba,a,pt %xcc, rtrap_clr_l6
+       ba,a,pt %xcc, rtrap
 
        /* Data Access Exception, tl0. */
 sun4v_dacc:
@@ -294,7 +294,7 @@ sun4v_dacc:
        mov     %l5, %o2
        call    sun4v_data_access_exception
         add    %sp, PTREGS_OFF, %o0
-       ba,a,pt %xcc, rtrap_clr_l6
+       ba,a,pt %xcc, rtrap
 
        /* Data Access Exception, tl1. */
 sun4v_dacc_tl1:
@@ -310,7 +310,7 @@ sun4v_dacc_tl1:
        mov     %l5, %o2
        call    sun4v_data_access_exception_tl1
         add    %sp, PTREGS_OFF, %o0
-       ba,a,pt %xcc, rtrap_clr_l6
+       ba,a,pt %xcc, rtrap
 
        /* Memory Address Unaligned.  */
 sun4v_mna:
@@ -344,7 +344,7 @@ sun4v_mna:
        mov     %l5, %o2
        call    sun4v_do_mna
         add    %sp, PTREGS_OFF, %o0
-       ba,a,pt %xcc, rtrap_clr_l6
+       ba,a,pt %xcc, rtrap
 
        /* Privileged Action.  */
 sun4v_privact:
@@ -352,7 +352,7 @@ sun4v_privact:
         rd     %pc, %g7
        call    do_privact
         add    %sp, PTREGS_OFF, %o0
-       ba,a,pt %xcc, rtrap_clr_l6
+       ba,a,pt %xcc, rtrap
 
        /* Unaligned ldd float, tl0. */
 sun4v_lddfmna:
@@ -368,7 +368,7 @@ sun4v_lddfmna:
        mov     %l5, %o2
        call    handle_lddfmna
         add    %sp, PTREGS_OFF, %o0
-       ba,a,pt %xcc, rtrap_clr_l6
+       ba,a,pt %xcc, rtrap
 
        /* Unaligned std float, tl0. */
 sun4v_stdfmna:
@@ -384,7 +384,7 @@ sun4v_stdfmna:
        mov     %l5, %o2
        call    handle_stdfmna
         add    %sp, PTREGS_OFF, %o0
-       ba,a,pt %xcc, rtrap_clr_l6
+       ba,a,pt %xcc, rtrap
 
 #define BRANCH_ALWAYS  0x10680000
 #define NOP            0x01000000
index 52816c7be0b96f8015c997c268dd5a866269979e..e885034a6b73a865c049fa5ca62ca5dab3a88fc1 100644 (file)
@@ -273,10 +273,22 @@ static void __init check_mmu_stats(void)
                mmu_stats_supported = 1;
 }
 
+static void register_nodes(void)
+{
+#ifdef CONFIG_NUMA
+       int i;
+
+       for (i = 0; i < MAX_NUMNODES; i++)
+               register_one_node(i);
+#endif
+}
+
 static int __init topology_init(void)
 {
        int cpu;
 
+       register_nodes();
+
        check_mmu_stats();
 
        register_cpu_notifier(&sysfs_cpu_nb);
index 96da847023f3c956cecdec5a04fda1fe518be05d..d9b8d46707d15db413ca8f23410e728a2c4add06 100644 (file)
@@ -2091,9 +2091,8 @@ static void user_instruction_dump(unsigned int __user *pc)
 
 void show_stack(struct task_struct *tsk, unsigned long *_ksp)
 {
-       unsigned long pc, fp, thread_base, ksp;
+       unsigned long fp, thread_base, ksp;
        struct thread_info *tp;
-       struct reg_window *rw;
        int count = 0;
 
        ksp = (unsigned long) _ksp;
@@ -2117,15 +2116,27 @@ void show_stack(struct task_struct *tsk, unsigned long *_ksp)
        printk("\n");
 #endif
        do {
+               struct reg_window *rw;
+               struct pt_regs *regs;
+               unsigned long pc;
+
                /* Bogus frame pointer? */
                if (fp < (thread_base + sizeof(struct thread_info)) ||
                    fp >= (thread_base + THREAD_SIZE))
                        break;
                rw = (struct reg_window *)fp;
-               pc = rw->ins[7];
+               regs = (struct pt_regs *) (rw + 1);
+
+               if ((regs->magic & ~0x1ff) == PT_REGS_MAGIC) {
+                       pc = regs->tpc;
+                       fp = regs->u_regs[UREG_I6] + STACK_BIAS;
+               } else {
+                       pc = rw->ins[7];
+                       fp = rw->ins[6] + STACK_BIAS;
+               }
+
                printk(" [%016lx] ", pc);
                print_symbol("%s\n", pc);
-               fp = rw->ins[6] + STACK_BIAS;
        } while (++count < 16);
 #ifndef CONFIG_KALLSYMS
        printk("\n");
index 10adb2fb8ffe1f80fd67fe6bc832bf93446bbfa5..c499214b501d007414e84a7f63d3b505193bf52d 100644 (file)
@@ -275,7 +275,7 @@ sparc64_realfault_common:
        stx     %l5, [%g6 + TI_FAULT_ADDR]      ! Save fault address
        call    do_sparc64_fault                ! Call fault handler
         add    %sp, PTREGS_OFF, %o0            ! Compute pt_regs arg
-       ba,pt   %xcc, rtrap_clr_l6              ! Restore cpu state
+       ba,pt   %xcc, rtrap                     ! Restore cpu state
         nop                                    ! Delay slot (fill me)
 
 winfix_trampoline:
index c4aa110a10e5c25882896b001df4a3e5f89fd771..a6b0863c27df48e12bfa656a83783fee6ecfa05c 100644 (file)
@@ -32,7 +32,7 @@ fill_fixup:
         rd     %pc, %g7
        call    do_sparc64_fault
         add    %sp, PTREGS_OFF, %o0
-       ba,pt   %xcc, rtrap_clr_l6
+       ba,pt   %xcc, rtrap
         nop
 
        /* Be very careful about usage of the trap globals here.
@@ -100,7 +100,7 @@ spill_fixup_dax:
         rd     %pc, %g7
        call    do_sparc64_fault
         add    %sp, PTREGS_OFF, %o0
-       ba,a,pt %xcc, rtrap_clr_l6
+       ba,a,pt %xcc, rtrap
 
 winfix_mna:
        andn    %g3, 0x7f, %g3
@@ -122,12 +122,12 @@ fill_fixup_mna:
        mov     %l4, %o2
        call    sun4v_do_mna
         mov    %l5, %o1
-       ba,a,pt %xcc, rtrap_clr_l6
+       ba,a,pt %xcc, rtrap
 1:     mov     %l4, %o1
        mov     %l5, %o2
        call    mem_address_unaligned
         nop
-       ba,a,pt %xcc, rtrap_clr_l6
+       ba,a,pt %xcc, rtrap
 
 winfix_dax:
        andn    %g3, 0x7f, %g3
@@ -150,7 +150,7 @@ fill_fixup_dax:
         add    %sp, PTREGS_OFF, %o0
        call    sun4v_data_access_exception
         nop
-       ba,a,pt %xcc, rtrap_clr_l6
+       ba,a,pt %xcc, rtrap
 1:     call    spitfire_data_access_exception
         nop
-       ba,a,pt %xcc, rtrap_clr_l6
+       ba,a,pt %xcc, rtrap
index f37078d964073561cda5cbd9a71f9228dcadfc0a..177d8aaeec42e2d147b92617dd308afa9c2baec1 100644 (file)
@@ -24,6 +24,8 @@
 #include <linux/cache.h>
 #include <linux/sort.h>
 #include <linux/percpu.h>
+#include <linux/lmb.h>
+#include <linux/mmzone.h>
 
 #include <asm/head.h>
 #include <asm/system.h>
@@ -72,9 +74,7 @@ extern struct tsb swapper_4m_tsb[KERNEL_TSB4M_NENTRIES];
 #define MAX_BANKS      32
 
 static struct linux_prom64_registers pavail[MAX_BANKS] __initdata;
-static struct linux_prom64_registers pavail_rescan[MAX_BANKS] __initdata;
 static int pavail_ents __initdata;
-static int pavail_rescan_ents __initdata;
 
 static int cmp_p64(const void *a, const void *b)
 {
@@ -715,285 +715,684 @@ out:
                smp_new_mmu_context_version();
 }
 
-/* Find a free area for the bootmem map, avoiding the kernel image
- * and the initial ramdisk.
- */
-static unsigned long __init choose_bootmap_pfn(unsigned long start_pfn,
-                                              unsigned long end_pfn)
+static int numa_enabled = 1;
+static int numa_debug;
+
+static int __init early_numa(char *p)
 {
-       unsigned long avoid_start, avoid_end, bootmap_size;
-       int i;
+       if (!p)
+               return 0;
+
+       if (strstr(p, "off"))
+               numa_enabled = 0;
+
+       if (strstr(p, "debug"))
+               numa_debug = 1;
+
+       return 0;
+}
+early_param("numa", early_numa);
 
-       bootmap_size = bootmem_bootmap_pages(end_pfn - start_pfn);
-       bootmap_size <<= PAGE_SHIFT;
+#define numadbg(f, a...) \
+do {   if (numa_debug) \
+               printk(KERN_INFO f, ## a); \
+} while (0)
 
-       avoid_start = avoid_end = 0;
+static void __init find_ramdisk(unsigned long phys_base)
+{
 #ifdef CONFIG_BLK_DEV_INITRD
-       avoid_start = initrd_start;
-       avoid_end = PAGE_ALIGN(initrd_end);
+       if (sparc_ramdisk_image || sparc_ramdisk_image64) {
+               unsigned long ramdisk_image;
+
+               /* Older versions of the bootloader only supported a
+                * 32-bit physical address for the ramdisk image
+                * location, stored at sparc_ramdisk_image.  Newer
+                * SILO versions set sparc_ramdisk_image to zero and
+                * provide a full 64-bit physical address at
+                * sparc_ramdisk_image64.
+                */
+               ramdisk_image = sparc_ramdisk_image;
+               if (!ramdisk_image)
+                       ramdisk_image = sparc_ramdisk_image64;
+
+               /* Another bootloader quirk.  The bootloader normalizes
+                * the physical address to KERNBASE, so we have to
+                * factor that back out and add in the lowest valid
+                * physical page address to get the true physical address.
+                */
+               ramdisk_image -= KERNBASE;
+               ramdisk_image += phys_base;
+
+               numadbg("Found ramdisk at physical address 0x%lx, size %u\n",
+                       ramdisk_image, sparc_ramdisk_size);
+
+               initrd_start = ramdisk_image;
+               initrd_end = ramdisk_image + sparc_ramdisk_size;
+
+               lmb_reserve(initrd_start, initrd_end);
+       }
 #endif
+}
 
-       for (i = 0; i < pavail_ents; i++) {
-               unsigned long start, end;
+struct node_mem_mask {
+       unsigned long mask;
+       unsigned long val;
+       unsigned long bootmem_paddr;
+};
+static struct node_mem_mask node_masks[MAX_NUMNODES];
+static int num_node_masks;
 
-               start = pavail[i].phys_addr;
-               end = start + pavail[i].reg_size;
+int numa_cpu_lookup_table[NR_CPUS];
+cpumask_t numa_cpumask_lookup_table[MAX_NUMNODES];
 
-               while (start < end) {
-                       if (start >= kern_base &&
-                           start < PAGE_ALIGN(kern_base + kern_size)) {
-                               start = PAGE_ALIGN(kern_base + kern_size);
-                               continue;
-                       }
-                       if (start >= avoid_start && start < avoid_end) {
-                               start = avoid_end;
-                               continue;
-                       }
+#ifdef CONFIG_NEED_MULTIPLE_NODES
+static bootmem_data_t plat_node_bdata[MAX_NUMNODES];
 
-                       if ((end - start) < bootmap_size)
-                               break;
+struct mdesc_mblock {
+       u64     base;
+       u64     size;
+       u64     offset; /* RA-to-PA */
+};
+static struct mdesc_mblock *mblocks;
+static int num_mblocks;
 
-                       if (start < kern_base &&
-                           (start + bootmap_size) > kern_base) {
-                               start = PAGE_ALIGN(kern_base + kern_size);
-                               continue;
-                       }
+static unsigned long ra_to_pa(unsigned long addr)
+{
+       int i;
 
-                       if (start < avoid_start &&
-                           (start + bootmap_size) > avoid_start) {
-                               start = avoid_end;
-                               continue;
-                       }
+       for (i = 0; i < num_mblocks; i++) {
+               struct mdesc_mblock *m = &mblocks[i];
 
-                       /* OK, it doesn't overlap anything, use it.  */
-                       return start >> PAGE_SHIFT;
+               if (addr >= m->base &&
+                   addr < (m->base + m->size)) {
+                       addr += m->offset;
+                       break;
                }
        }
-
-       prom_printf("Cannot find free area for bootmap, aborting.\n");
-       prom_halt();
+       return addr;
 }
 
-static void __init trim_pavail(unsigned long *cur_size_p,
-                              unsigned long *end_of_phys_p)
+static int find_node(unsigned long addr)
 {
-       unsigned long to_trim = *cur_size_p - cmdline_memory_size;
-       unsigned long avoid_start, avoid_end;
        int i;
 
-       to_trim = PAGE_ALIGN(to_trim);
+       addr = ra_to_pa(addr);
+       for (i = 0; i < num_node_masks; i++) {
+               struct node_mem_mask *p = &node_masks[i];
 
-       avoid_start = avoid_end = 0;
-#ifdef CONFIG_BLK_DEV_INITRD
-       avoid_start = initrd_start;
-       avoid_end = PAGE_ALIGN(initrd_end);
+               if ((addr & p->mask) == p->val)
+                       return i;
+       }
+       return -1;
+}
+
+static unsigned long nid_range(unsigned long start, unsigned long end,
+                              int *nid)
+{
+       *nid = find_node(start);
+       start += PAGE_SIZE;
+       while (start < end) {
+               int n = find_node(start);
+
+               if (n != *nid)
+                       break;
+               start += PAGE_SIZE;
+       }
+
+       return start;
+}
+#else
+static unsigned long nid_range(unsigned long start, unsigned long end,
+                              int *nid)
+{
+       *nid = 0;
+       return end;
+}
 #endif
 
-       /* Trim some pavail[] entries in order to satisfy the
-        * requested "mem=xxx" kernel command line specification.
-        *
-        * We must not trim off the kernel image area nor the
-        * initial ramdisk range (if any).  Also, we must not trim
-        * any pavail[] entry down to zero in order to preserve
-        * the invariant that all pavail[] entries have a non-zero
-        * size which is assumed by all of the code in here.
-        */
-       for (i = 0; i < pavail_ents; i++) {
-               unsigned long start, end, kern_end;
-               unsigned long trim_low, trim_high, n;
+/* This must be invoked after performing all of the necessary
+ * add_active_range() calls for 'nid'.  We need to be able to get
+ * correct data from get_pfn_range_for_nid().
+ */
+static void __init allocate_node_data(int nid)
+{
+       unsigned long paddr, num_pages, start_pfn, end_pfn;
+       struct pglist_data *p;
+
+#ifdef CONFIG_NEED_MULTIPLE_NODES
+       paddr = lmb_alloc_nid(sizeof(struct pglist_data),
+                             SMP_CACHE_BYTES, nid, nid_range);
+       if (!paddr) {
+               prom_printf("Cannot allocate pglist_data for nid[%d]\n", nid);
+               prom_halt();
+       }
+       NODE_DATA(nid) = __va(paddr);
+       memset(NODE_DATA(nid), 0, sizeof(struct pglist_data));
 
-               kern_end = PAGE_ALIGN(kern_base + kern_size);
+       NODE_DATA(nid)->bdata = &plat_node_bdata[nid];
+#endif
 
-               trim_low = start = pavail[i].phys_addr;
-               trim_high = end = start + pavail[i].reg_size;
+       p = NODE_DATA(nid);
 
-               if (kern_base >= start &&
-                   kern_base < end) {
-                       trim_low = kern_base;
-                       if (kern_end >= end)
-                               continue;
-               }
-               if (kern_end >= start &&
-                   kern_end < end) {
-                       trim_high = kern_end;
-               }
-               if (avoid_start &&
-                   avoid_start >= start &&
-                   avoid_start < end) {
-                       if (trim_low > avoid_start)
-                               trim_low = avoid_start;
-                       if (avoid_end >= end)
-                               continue;
-               }
-               if (avoid_end &&
-                   avoid_end >= start &&
-                   avoid_end < end) {
-                       if (trim_high < avoid_end)
-                               trim_high = avoid_end;
+       get_pfn_range_for_nid(nid, &start_pfn, &end_pfn);
+       p->node_start_pfn = start_pfn;
+       p->node_spanned_pages = end_pfn - start_pfn;
+
+       if (p->node_spanned_pages) {
+               num_pages = bootmem_bootmap_pages(p->node_spanned_pages);
+
+               paddr = lmb_alloc_nid(num_pages << PAGE_SHIFT, PAGE_SIZE, nid,
+                                     nid_range);
+               if (!paddr) {
+                       prom_printf("Cannot allocate bootmap for nid[%d]\n",
+                                 nid);
+                       prom_halt();
                }
+               node_masks[nid].bootmem_paddr = paddr;
+       }
+}
+
+static void init_node_masks_nonnuma(void)
+{
+       int i;
+
+       numadbg("Initializing tables for non-numa.\n");
+
+       node_masks[0].mask = node_masks[0].val = 0;
+       num_node_masks = 1;
+
+       for (i = 0; i < NR_CPUS; i++)
+               numa_cpu_lookup_table[i] = 0;
+
+       numa_cpumask_lookup_table[0] = CPU_MASK_ALL;
+}
+
+#ifdef CONFIG_NEED_MULTIPLE_NODES
+struct pglist_data *node_data[MAX_NUMNODES];
+
+EXPORT_SYMBOL(numa_cpu_lookup_table);
+EXPORT_SYMBOL(numa_cpumask_lookup_table);
+EXPORT_SYMBOL(node_data);
+
+struct mdesc_mlgroup {
+       u64     node;
+       u64     latency;
+       u64     match;
+       u64     mask;
+};
+static struct mdesc_mlgroup *mlgroups;
+static int num_mlgroups;
+
+static int scan_pio_for_cfg_handle(struct mdesc_handle *md, u64 pio,
+                                  u32 cfg_handle)
+{
+       u64 arc;
 
-               if (trim_high <= trim_low)
+       mdesc_for_each_arc(arc, md, pio, MDESC_ARC_TYPE_FWD) {
+               u64 target = mdesc_arc_target(md, arc);
+               const u64 *val;
+
+               val = mdesc_get_property(md, target,
+                                        "cfg-handle", NULL);
+               if (val && *val == cfg_handle)
+                       return 0;
+       }
+       return -ENODEV;
+}
+
+static int scan_arcs_for_cfg_handle(struct mdesc_handle *md, u64 grp,
+                                   u32 cfg_handle)
+{
+       u64 arc, candidate, best_latency = ~(u64)0;
+
+       candidate = MDESC_NODE_NULL;
+       mdesc_for_each_arc(arc, md, grp, MDESC_ARC_TYPE_FWD) {
+               u64 target = mdesc_arc_target(md, arc);
+               const char *name = mdesc_node_name(md, target);
+               const u64 *val;
+
+               if (strcmp(name, "pio-latency-group"))
                        continue;
 
-               if (trim_low == start && trim_high == end) {
-                       /* Whole chunk is available for trimming.
-                        * Trim all except one page, in order to keep
-                        * entry non-empty.
-                        */
-                       n = (end - start) - PAGE_SIZE;
-                       if (n > to_trim)
-                               n = to_trim;
-
-                       if (n) {
-                               pavail[i].phys_addr += n;
-                               pavail[i].reg_size -= n;
-                               to_trim -= n;
-                       }
-               } else {
-                       n = (trim_low - start);
-                       if (n > to_trim)
-                               n = to_trim;
-
-                       if (n) {
-                               pavail[i].phys_addr += n;
-                               pavail[i].reg_size -= n;
-                               to_trim -= n;
-                       }
-                       if (to_trim) {
-                               n = end - trim_high;
-                               if (n > to_trim)
-                                       n = to_trim;
-                               if (n) {
-                                       pavail[i].reg_size -= n;
-                                       to_trim -= n;
-                               }
-                       }
+               val = mdesc_get_property(md, target, "latency", NULL);
+               if (!val)
+                       continue;
+
+               if (*val < best_latency) {
+                       candidate = target;
+                       best_latency = *val;
                }
+       }
+
+       if (candidate == MDESC_NODE_NULL)
+               return -ENODEV;
+
+       return scan_pio_for_cfg_handle(md, candidate, cfg_handle);
+}
+
+int of_node_to_nid(struct device_node *dp)
+{
+       const struct linux_prom64_registers *regs;
+       struct mdesc_handle *md;
+       u32 cfg_handle;
+       int count, nid;
+       u64 grp;
 
-               if (!to_trim)
+       if (!mlgroups)
+               return -1;
+
+       regs = of_get_property(dp, "reg", NULL);
+       if (!regs)
+               return -1;
+
+       cfg_handle = (regs->phys_addr >> 32UL) & 0x0fffffff;
+
+       md = mdesc_grab();
+
+       count = 0;
+       nid = -1;
+       mdesc_for_each_node_by_name(md, grp, "group") {
+               if (!scan_arcs_for_cfg_handle(md, grp, cfg_handle)) {
+                       nid = count;
                        break;
+               }
+               count++;
        }
 
-       /* Recalculate.  */
-       *cur_size_p = 0UL;
-       for (i = 0; i < pavail_ents; i++) {
-               *end_of_phys_p = pavail[i].phys_addr +
-                       pavail[i].reg_size;
-               *cur_size_p += pavail[i].reg_size;
-       }
+       mdesc_release(md);
+
+       return nid;
 }
 
-/* About pages_avail, this is the value we will use to calculate
- * the zholes_size[] argument given to free_area_init_node().  The
- * page allocator uses this to calculate nr_kernel_pages,
- * nr_all_pages and zone->present_pages.  On NUMA it is used
- * to calculate zone->min_unmapped_pages and zone->min_slab_pages.
- *
- * So this number should really be set to what the page allocator
- * actually ends up with.  This means:
- * 1) It should include bootmem map pages, we'll release those.
- * 2) It should not include the kernel image, except for the
- *    __init sections which we will also release.
- * 3) It should include the initrd image, since we'll release
- *    that too.
- */
-static unsigned long __init bootmem_init(unsigned long *pages_avail,
-                                        unsigned long phys_base)
+static void add_node_ranges(void)
 {
-       unsigned long bootmap_size, end_pfn;
-       unsigned long end_of_phys_memory = 0UL;
-       unsigned long bootmap_pfn, bytes_avail, size;
        int i;
 
-       bytes_avail = 0UL;
-       for (i = 0; i < pavail_ents; i++) {
-               end_of_phys_memory = pavail[i].phys_addr +
-                       pavail[i].reg_size;
-               bytes_avail += pavail[i].reg_size;
+       for (i = 0; i < lmb.memory.cnt; i++) {
+               unsigned long size = lmb_size_bytes(&lmb.memory, i);
+               unsigned long start, end;
+
+               start = lmb.memory.region[i].base;
+               end = start + size;
+               while (start < end) {
+                       unsigned long this_end;
+                       int nid;
+
+                       this_end = nid_range(start, end, &nid);
+
+                       numadbg("Adding active range nid[%d] "
+                               "start[%lx] end[%lx]\n",
+                               nid, start, this_end);
+
+                       add_active_range(nid,
+                                        start >> PAGE_SHIFT,
+                                        this_end >> PAGE_SHIFT);
+
+                       start = this_end;
+               }
        }
+}
 
-       /* Determine the location of the initial ramdisk before trying
-        * to honor the "mem=xxx" command line argument.  We must know
-        * where the kernel image and the ramdisk image are so that we
-        * do not trim those two areas from the physical memory map.
-        */
+static int __init grab_mlgroups(struct mdesc_handle *md)
+{
+       unsigned long paddr;
+       int count = 0;
+       u64 node;
+
+       mdesc_for_each_node_by_name(md, node, "memory-latency-group")
+               count++;
+       if (!count)
+               return -ENOENT;
+
+       paddr = lmb_alloc(count * sizeof(struct mdesc_mlgroup),
+                         SMP_CACHE_BYTES);
+       if (!paddr)
+               return -ENOMEM;
+
+       mlgroups = __va(paddr);
+       num_mlgroups = count;
+
+       count = 0;
+       mdesc_for_each_node_by_name(md, node, "memory-latency-group") {
+               struct mdesc_mlgroup *m = &mlgroups[count++];
+               const u64 *val;
+
+               m->node = node;
+
+               val = mdesc_get_property(md, node, "latency", NULL);
+               m->latency = *val;
+               val = mdesc_get_property(md, node, "address-match", NULL);
+               m->match = *val;
+               val = mdesc_get_property(md, node, "address-mask", NULL);
+               m->mask = *val;
+
+               numadbg("MLGROUP[%d]: node[%lx] latency[%lx] "
+                       "match[%lx] mask[%lx]\n",
+                       count - 1, m->node, m->latency, m->match, m->mask);
+       }
 
-#ifdef CONFIG_BLK_DEV_INITRD
-       /* Now have to check initial ramdisk, so that bootmap does not overwrite it */
-       if (sparc_ramdisk_image || sparc_ramdisk_image64) {
-               unsigned long ramdisk_image = sparc_ramdisk_image ?
-                       sparc_ramdisk_image : sparc_ramdisk_image64;
-               ramdisk_image -= KERNBASE;
-               initrd_start = ramdisk_image + phys_base;
-               initrd_end = initrd_start + sparc_ramdisk_size;
-               if (initrd_end > end_of_phys_memory) {
-                       printk(KERN_CRIT "initrd extends beyond end of memory "
-                                        "(0x%016lx > 0x%016lx)\ndisabling initrd\n",
-                              initrd_end, end_of_phys_memory);
-                       initrd_start = 0;
-                       initrd_end = 0;
+       return 0;
+}
+
+static int __init grab_mblocks(struct mdesc_handle *md)
+{
+       unsigned long paddr;
+       int count = 0;
+       u64 node;
+
+       mdesc_for_each_node_by_name(md, node, "mblock")
+               count++;
+       if (!count)
+               return -ENOENT;
+
+       paddr = lmb_alloc(count * sizeof(struct mdesc_mblock),
+                         SMP_CACHE_BYTES);
+       if (!paddr)
+               return -ENOMEM;
+
+       mblocks = __va(paddr);
+       num_mblocks = count;
+
+       count = 0;
+       mdesc_for_each_node_by_name(md, node, "mblock") {
+               struct mdesc_mblock *m = &mblocks[count++];
+               const u64 *val;
+
+               val = mdesc_get_property(md, node, "base", NULL);
+               m->base = *val;
+               val = mdesc_get_property(md, node, "size", NULL);
+               m->size = *val;
+               val = mdesc_get_property(md, node,
+                                        "address-congruence-offset", NULL);
+               m->offset = *val;
+
+               numadbg("MBLOCK[%d]: base[%lx] size[%lx] offset[%lx]\n",
+                       count - 1, m->base, m->size, m->offset);
+       }
+
+       return 0;
+}
+
+static void __init numa_parse_mdesc_group_cpus(struct mdesc_handle *md,
+                                              u64 grp, cpumask_t *mask)
+{
+       u64 arc;
+
+       cpus_clear(*mask);
+
+       mdesc_for_each_arc(arc, md, grp, MDESC_ARC_TYPE_BACK) {
+               u64 target = mdesc_arc_target(md, arc);
+               const char *name = mdesc_node_name(md, target);
+               const u64 *id;
+
+               if (strcmp(name, "cpu"))
+                       continue;
+               id = mdesc_get_property(md, target, "id", NULL);
+               if (*id < NR_CPUS)
+                       cpu_set(*id, *mask);
+       }
+}
+
+static struct mdesc_mlgroup * __init find_mlgroup(u64 node)
+{
+       int i;
+
+       for (i = 0; i < num_mlgroups; i++) {
+               struct mdesc_mlgroup *m = &mlgroups[i];
+               if (m->node == node)
+                       return m;
+       }
+       return NULL;
+}
+
+static int __init numa_attach_mlgroup(struct mdesc_handle *md, u64 grp,
+                                     int index)
+{
+       struct mdesc_mlgroup *candidate = NULL;
+       u64 arc, best_latency = ~(u64)0;
+       struct node_mem_mask *n;
+
+       mdesc_for_each_arc(arc, md, grp, MDESC_ARC_TYPE_FWD) {
+               u64 target = mdesc_arc_target(md, arc);
+               struct mdesc_mlgroup *m = find_mlgroup(target);
+               if (!m)
+                       continue;
+               if (m->latency < best_latency) {
+                       candidate = m;
+                       best_latency = m->latency;
                }
        }
-#endif 
+       if (!candidate)
+               return -ENOENT;
+
+       if (num_node_masks != index) {
+               printk(KERN_ERR "Inconsistent NUMA state, "
+                      "index[%d] != num_node_masks[%d]\n",
+                      index, num_node_masks);
+               return -EINVAL;
+       }
 
-       if (cmdline_memory_size &&
-           bytes_avail > cmdline_memory_size)
-               trim_pavail(&bytes_avail,
-                           &end_of_phys_memory);
+       n = &node_masks[num_node_masks++];
 
-       *pages_avail = bytes_avail >> PAGE_SHIFT;
+       n->mask = candidate->mask;
+       n->val = candidate->match;
 
-       end_pfn = end_of_phys_memory >> PAGE_SHIFT;
+       numadbg("NUMA NODE[%d]: mask[%lx] val[%lx] (latency[%lx])\n",
+               index, n->mask, n->val, candidate->latency);
 
-       /* Initialize the boot-time allocator. */
-       max_pfn = max_low_pfn = end_pfn;
-       min_low_pfn = (phys_base >> PAGE_SHIFT);
+       return 0;
+}
+
+static int __init numa_parse_mdesc_group(struct mdesc_handle *md, u64 grp,
+                                        int index)
+{
+       cpumask_t mask;
+       int cpu;
 
-       bootmap_pfn = choose_bootmap_pfn(min_low_pfn, end_pfn);
+       numa_parse_mdesc_group_cpus(md, grp, &mask);
 
-       bootmap_size = init_bootmem_node(NODE_DATA(0), bootmap_pfn,
-                                        min_low_pfn, end_pfn);
+       for_each_cpu_mask(cpu, mask)
+               numa_cpu_lookup_table[cpu] = index;
+       numa_cpumask_lookup_table[index] = mask;
 
-       /* Now register the available physical memory with the
-        * allocator.
-        */
-       for (i = 0; i < pavail_ents; i++)
-               free_bootmem(pavail[i].phys_addr, pavail[i].reg_size);
+       if (numa_debug) {
+               printk(KERN_INFO "NUMA GROUP[%d]: cpus [ ", index);
+               for_each_cpu_mask(cpu, mask)
+                       printk("%d ", cpu);
+               printk("]\n");
+       }
 
-#ifdef CONFIG_BLK_DEV_INITRD
-       if (initrd_start) {
-               size = initrd_end - initrd_start;
+       return numa_attach_mlgroup(md, grp, index);
+}
+
+static int __init numa_parse_mdesc(void)
+{
+       struct mdesc_handle *md = mdesc_grab();
+       int i, err, count;
+       u64 node;
+
+       node = mdesc_node_by_name(md, MDESC_NODE_NULL, "latency-groups");
+       if (node == MDESC_NODE_NULL) {
+               mdesc_release(md);
+               return -ENOENT;
+       }
+
+       err = grab_mblocks(md);
+       if (err < 0)
+               goto out;
+
+       err = grab_mlgroups(md);
+       if (err < 0)
+               goto out;
+
+       count = 0;
+       mdesc_for_each_node_by_name(md, node, "group") {
+               err = numa_parse_mdesc_group(md, node, count);
+               if (err < 0)
+                       break;
+               count++;
+       }
+
+       add_node_ranges();
+
+       for (i = 0; i < num_node_masks; i++) {
+               allocate_node_data(i);
+               node_set_online(i);
+       }
+
+       err = 0;
+out:
+       mdesc_release(md);
+       return err;
+}
+
+static int __init numa_parse_sun4u(void)
+{
+       return -1;
+}
 
-               /* Reserve the initrd image area. */
-               reserve_bootmem(initrd_start, size, BOOTMEM_DEFAULT);
+static int __init bootmem_init_numa(void)
+{
+       int err = -1;
 
-               initrd_start += PAGE_OFFSET;
-               initrd_end += PAGE_OFFSET;
+       numadbg("bootmem_init_numa()\n");
+
+       if (numa_enabled) {
+               if (tlb_type == hypervisor)
+                       err = numa_parse_mdesc();
+               else
+                       err = numa_parse_sun4u();
        }
+       return err;
+}
+
+#else
+
+static int bootmem_init_numa(void)
+{
+       return -1;
+}
+
 #endif
-       /* Reserve the kernel text/data/bss. */
-       reserve_bootmem(kern_base, kern_size, BOOTMEM_DEFAULT);
-       *pages_avail -= PAGE_ALIGN(kern_size) >> PAGE_SHIFT;
-
-       /* Add back in the initmem pages. */
-       size = ((unsigned long)(__init_end) & PAGE_MASK) -
-               PAGE_ALIGN((unsigned long)__init_begin);
-       *pages_avail += size >> PAGE_SHIFT;
-
-       /* Reserve the bootmem map.   We do not account for it
-        * in pages_avail because we will release that memory
-        * in free_all_bootmem.
-        */
-       size = bootmap_size;
-       reserve_bootmem((bootmap_pfn << PAGE_SHIFT), size, BOOTMEM_DEFAULT);
 
-       for (i = 0; i < pavail_ents; i++) {
+static void __init bootmem_init_nonnuma(void)
+{
+       unsigned long top_of_ram = lmb_end_of_DRAM();
+       unsigned long total_ram = lmb_phys_mem_size();
+       unsigned int i;
+
+       numadbg("bootmem_init_nonnuma()\n");
+
+       printk(KERN_INFO "Top of RAM: 0x%lx, Total RAM: 0x%lx\n",
+              top_of_ram, total_ram);
+       printk(KERN_INFO "Memory hole size: %ldMB\n",
+              (top_of_ram - total_ram) >> 20);
+
+       init_node_masks_nonnuma();
+
+       for (i = 0; i < lmb.memory.cnt; i++) {
+               unsigned long size = lmb_size_bytes(&lmb.memory, i);
                unsigned long start_pfn, end_pfn;
 
-               start_pfn = pavail[i].phys_addr >> PAGE_SHIFT;
-               end_pfn = (start_pfn + (pavail[i].reg_size >> PAGE_SHIFT));
-               memory_present(0, start_pfn, end_pfn);
+               if (!size)
+                       continue;
+
+               start_pfn = lmb.memory.region[i].base >> PAGE_SHIFT;
+               end_pfn = start_pfn + lmb_size_pages(&lmb.memory, i);
+               add_active_range(0, start_pfn, end_pfn);
+       }
+
+       allocate_node_data(0);
+
+       node_set_online(0);
+}
+
+static void __init reserve_range_in_node(int nid, unsigned long start,
+                                        unsigned long end)
+{
+       numadbg("    reserve_range_in_node(nid[%d],start[%lx],end[%lx]\n",
+               nid, start, end);
+       while (start < end) {
+               unsigned long this_end;
+               int n;
+
+               this_end = nid_range(start, end, &n);
+               if (n == nid) {
+                       numadbg("      MATCH reserving range [%lx:%lx]\n",
+                               start, this_end);
+                       reserve_bootmem_node(NODE_DATA(nid), start,
+                                            (this_end - start), BOOTMEM_DEFAULT);
+               } else
+                       numadbg("      NO MATCH, advancing start to %lx\n",
+                               this_end);
+
+               start = this_end;
+       }
+}
+
+static void __init trim_reserved_in_node(int nid)
+{
+       int i;
+
+       numadbg("  trim_reserved_in_node(%d)\n", nid);
+
+       for (i = 0; i < lmb.reserved.cnt; i++) {
+               unsigned long start = lmb.reserved.region[i].base;
+               unsigned long size = lmb_size_bytes(&lmb.reserved, i);
+               unsigned long end = start + size;
+
+               reserve_range_in_node(nid, start, end);
+       }
+}
+
+static void __init bootmem_init_one_node(int nid)
+{
+       struct pglist_data *p;
+
+       numadbg("bootmem_init_one_node(%d)\n", nid);
+
+       p = NODE_DATA(nid);
+
+       if (p->node_spanned_pages) {
+               unsigned long paddr = node_masks[nid].bootmem_paddr;
+               unsigned long end_pfn;
+
+               end_pfn = p->node_start_pfn + p->node_spanned_pages;
+
+               numadbg("  init_bootmem_node(%d, %lx, %lx, %lx)\n",
+                       nid, paddr >> PAGE_SHIFT, p->node_start_pfn, end_pfn);
+
+               init_bootmem_node(p, paddr >> PAGE_SHIFT,
+                                 p->node_start_pfn, end_pfn);
+
+               numadbg("  free_bootmem_with_active_regions(%d, %lx)\n",
+                       nid, end_pfn);
+               free_bootmem_with_active_regions(nid, end_pfn);
+
+               trim_reserved_in_node(nid);
+
+               numadbg("  sparse_memory_present_with_active_regions(%d)\n",
+                       nid);
+               sparse_memory_present_with_active_regions(nid);
        }
+}
+
+static unsigned long __init bootmem_init(unsigned long phys_base)
+{
+       unsigned long end_pfn;
+       int nid;
+
+       end_pfn = lmb_end_of_DRAM() >> PAGE_SHIFT;
+       max_pfn = max_low_pfn = end_pfn;
+       min_low_pfn = (phys_base >> PAGE_SHIFT);
+
+       if (bootmem_init_numa() < 0)
+               bootmem_init_nonnuma();
+
+       /* XXX cpu notifier XXX */
+
+       for_each_online_node(nid)
+               bootmem_init_one_node(nid);
 
        sparse_init();
 
@@ -1289,7 +1688,7 @@ void __init setup_per_cpu_areas(void)
 
 void __init paging_init(void)
 {
-       unsigned long end_pfn, pages_avail, shift, phys_base;
+       unsigned long end_pfn, shift, phys_base;
        unsigned long real_end, i;
 
        /* These build time checkes make sure that the dcache_dirty_cpu()
@@ -1330,12 +1729,26 @@ void __init paging_init(void)
                sun4v_ktsb_init();
        }
 
+       lmb_init();
+
        /* Find available physical memory... */
        read_obp_memory("available", &pavail[0], &pavail_ents);
 
        phys_base = 0xffffffffffffffffUL;
-       for (i = 0; i < pavail_ents; i++)
+       for (i = 0; i < pavail_ents; i++) {
                phys_base = min(phys_base, pavail[i].phys_addr);
+               lmb_add(pavail[i].phys_addr, pavail[i].reg_size);
+       }
+
+       lmb_reserve(kern_base, kern_size);
+
+       find_ramdisk(phys_base);
+
+       if (cmdline_memory_size)
+               lmb_enforce_memory_limit(phys_base + cmdline_memory_size);
+
+       lmb_analyze();
+       lmb_dump_all();
 
        set_bit(0, mmu_context_bmap);
 
@@ -1371,14 +1784,10 @@ void __init paging_init(void)
        if (tlb_type == hypervisor)
                sun4v_ktsb_register();
 
-       /* Setup bootmem... */
-       pages_avail = 0;
-       last_valid_pfn = end_pfn = bootmem_init(&pages_avail, phys_base);
-
-       max_mapnr = last_valid_pfn;
-
-       kernel_physical_mapping_init();
-
+       /* We must setup the per-cpu areas before we pull in the
+        * PROM and the MDESC.  The code there fills in cpu and
+        * other information into per-cpu data structures.
+        */
        real_setup_per_cpu_areas();
 
        prom_build_devicetree();
@@ -1386,20 +1795,22 @@ void __init paging_init(void)
        if (tlb_type == hypervisor)
                sun4v_mdesc_init();
 
+       /* Setup bootmem... */
+       last_valid_pfn = end_pfn = bootmem_init(phys_base);
+
+#ifndef CONFIG_NEED_MULTIPLE_NODES
+       max_mapnr = last_valid_pfn;
+#endif
+       kernel_physical_mapping_init();
+
        {
-               unsigned long zones_size[MAX_NR_ZONES];
-               unsigned long zholes_size[MAX_NR_ZONES];
-               int znum;
+               unsigned long max_zone_pfns[MAX_NR_ZONES];
 
-               for (znum = 0; znum < MAX_NR_ZONES; znum++)
-                       zones_size[znum] = zholes_size[znum] = 0;
+               memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
 
-               zones_size[ZONE_NORMAL] = end_pfn;
-               zholes_size[ZONE_NORMAL] = end_pfn - pages_avail;
+               max_zone_pfns[ZONE_NORMAL] = end_pfn;
 
-               free_area_init_node(0, &contig_page_data, zones_size,
-                                   __pa(PAGE_OFFSET) >> PAGE_SHIFT,
-                                   zholes_size);
+               free_area_init_nodes(max_zone_pfns);
        }
 
        printk("Booting Linux...\n");
@@ -1408,21 +1819,52 @@ void __init paging_init(void)
        cpu_probe();
 }
 
-static void __init taint_real_pages(void)
+int __init page_in_phys_avail(unsigned long paddr)
+{
+       int i;
+
+       paddr &= PAGE_MASK;
+
+       for (i = 0; i < pavail_ents; i++) {
+               unsigned long start, end;
+
+               start = pavail[i].phys_addr;
+               end = start + pavail[i].reg_size;
+
+               if (paddr >= start && paddr < end)
+                       return 1;
+       }
+       if (paddr >= kern_base && paddr < (kern_base + kern_size))
+               return 1;
+#ifdef CONFIG_BLK_DEV_INITRD
+       if (paddr >= __pa(initrd_start) &&
+           paddr < __pa(PAGE_ALIGN(initrd_end)))
+               return 1;
+#endif
+
+       return 0;
+}
+
+static struct linux_prom64_registers pavail_rescan[MAX_BANKS] __initdata;
+static int pavail_rescan_ents __initdata;
+
+/* Certain OBP calls, such as fetching "available" properties, can
+ * claim physical memory.  So, along with initializing the valid
+ * address bitmap, what we do here is refetch the physical available
+ * memory list again, and make sure it provides at least as much
+ * memory as 'pavail' does.
+ */
+static void setup_valid_addr_bitmap_from_pavail(void)
 {
        int i;
 
        read_obp_memory("available", &pavail_rescan[0], &pavail_rescan_ents);
 
-       /* Find changes discovered in the physmem available rescan and
-        * reserve the lost portions in the bootmem maps.
-        */
        for (i = 0; i < pavail_ents; i++) {
                unsigned long old_start, old_end;
 
                old_start = pavail[i].phys_addr;
-               old_end = old_start +
-                       pavail[i].reg_size;
+               old_end = old_start + pavail[i].reg_size;
                while (old_start < old_end) {
                        int n;
 
@@ -1440,7 +1882,16 @@ static void __init taint_real_pages(void)
                                        goto do_next_page;
                                }
                        }
-                       reserve_bootmem(old_start, PAGE_SIZE, BOOTMEM_DEFAULT);
+
+                       prom_printf("mem_init: Lost memory in pavail\n");
+                       prom_printf("mem_init: OLD start[%lx] size[%lx]\n",
+                                   pavail[i].phys_addr,
+                                   pavail[i].reg_size);
+                       prom_printf("mem_init: NEW start[%lx] size[%lx]\n",
+                                   pavail_rescan[i].phys_addr,
+                                   pavail_rescan[i].reg_size);
+                       prom_printf("mem_init: Cannot continue, aborting.\n");
+                       prom_halt();
 
                do_next_page:
                        old_start += PAGE_SIZE;
@@ -1448,32 +1899,6 @@ static void __init taint_real_pages(void)
        }
 }
 
-int __init page_in_phys_avail(unsigned long paddr)
-{
-       int i;
-
-       paddr &= PAGE_MASK;
-
-       for (i = 0; i < pavail_rescan_ents; i++) {
-               unsigned long start, end;
-
-               start = pavail_rescan[i].phys_addr;
-               end = start + pavail_rescan[i].reg_size;
-
-               if (paddr >= start && paddr < end)
-                       return 1;
-       }
-       if (paddr >= kern_base && paddr < (kern_base + kern_size))
-               return 1;
-#ifdef CONFIG_BLK_DEV_INITRD
-       if (paddr >= __pa(initrd_start) &&
-           paddr < __pa(PAGE_ALIGN(initrd_end)))
-               return 1;
-#endif
-
-       return 0;
-}
-
 void __init mem_init(void)
 {
        unsigned long codepages, datapages, initpages;
@@ -1496,14 +1921,26 @@ void __init mem_init(void)
                addr += PAGE_SIZE;
        }
 
-       taint_real_pages();
+       setup_valid_addr_bitmap_from_pavail();
 
        high_memory = __va(last_valid_pfn << PAGE_SHIFT);
 
+#ifdef CONFIG_NEED_MULTIPLE_NODES
+       for_each_online_node(i) {
+               if (NODE_DATA(i)->node_spanned_pages != 0) {
+                       totalram_pages +=
+                               free_all_bootmem_node(NODE_DATA(i));
+               }
+       }
+#else
+       totalram_pages = free_all_bootmem();
+#endif
+
        /* We subtract one to account for the mem_map_zero page
         * allocated below.
         */
-       totalram_pages = num_physpages = free_all_bootmem() - 1;
+       totalram_pages -= 1;
+       num_physpages = totalram_pages;
 
        /*
         * Set up the zero page, mark it reserved, so that page count
index a3e6e4b635b3cc174aa91a33cb0a352b5261578a..fe70c8a557b58ae1c96cb4312878797b8d881d49 100644 (file)
@@ -321,7 +321,8 @@ retry_tsb_alloc:
        if (new_size > (PAGE_SIZE * 2))
                gfp_flags = __GFP_NOWARN | __GFP_NORETRY;
 
-       new_tsb = kmem_cache_alloc(tsb_caches[new_cache_index], gfp_flags);
+       new_tsb = kmem_cache_alloc_node(tsb_caches[new_cache_index],
+                                       gfp_flags, numa_node_id());
        if (unlikely(!new_tsb)) {
                /* Not being able to fork due to a high-order TSB
                 * allocation failure is very bad behavior.  Just back
index 2865c105b6a43927d84e00080ca61e8f571f1c3e..e686a67561af081aacc6e22fb8c4768508d4f096 100644 (file)
@@ -476,7 +476,6 @@ xcall_sync_tick:
 #endif
        call            smp_synchronize_tick_client
         nop
-       clr             %l6
        b               rtrap_xcall
         ldx            [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
 
@@ -511,7 +510,6 @@ xcall_report_regs:
 #endif
        call            __show_regs
         add            %sp, PTREGS_OFF, %o0
-       clr             %l6
        /* Has to be a non-v9 branch due to the large distance. */
        b               rtrap_xcall
         ldx            [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
@@ -576,7 +574,7 @@ __hypervisor_tlb_xcall_error:
        mov     %l4, %o0
        call    hypervisor_tlbop_error_xcall
         mov    %l5, %o1
-       ba,a,pt %xcc, rtrap_clr_l6
+       ba,a,pt %xcc, rtrap
 
        .globl          __hypervisor_xcall_flush_tlb_mm
 __hypervisor_xcall_flush_tlb_mm: /* 21 insns */
index 87a693cf2bb79f6cebbd82368bb2da35e3b45cf9..4d350b5cbc71fdaf7f8c8ed0d6a84d4aa96b9de4 100644 (file)
@@ -23,7 +23,7 @@ config X86
        select HAVE_KPROBES
        select HAVE_KRETPROBES
        select HAVE_KVM if ((X86_32 && !X86_VOYAGER && !X86_VISWS && !X86_NUMAQ) || X86_64)
-       select HAVE_ARCH_KGDB
+       select HAVE_ARCH_KGDB if !X86_VOYAGER
 
 
 config GENERIC_LOCKBREAK
index 687208190b065d0b0b17650b5335f1f931fffe50..8317401170b86845d3346251c3d44ef150830c05 100644 (file)
@@ -902,7 +902,7 @@ void __init init_bsp_APIC(void)
        apic_write_around(APIC_LVT1, value);
 }
 
-void __cpuinit lapic_setup_esr(void)
+static void __cpuinit lapic_setup_esr(void)
 {
        unsigned long oldvalue, value, maxlvt;
        if (lapic_is_integrated() && !esr_disable) {
index 9e8e5c050c55f7fa9418c0621c17030f9fea3b54..bf83157337e428bb84619478420d540e01fce466 100644 (file)
@@ -429,7 +429,7 @@ void __init setup_boot_APIC_clock(void)
  * set the DUMMY flag again and force the broadcast mode in the
  * clockevents layer.
  */
-void __cpuinit check_boot_apic_timer_broadcast(void)
+static void __cpuinit check_boot_apic_timer_broadcast(void)
 {
        if (!disable_apic_timer ||
            (lapic_clockevent.features & CLOCK_EVT_FEAT_DUMMY))
@@ -834,7 +834,7 @@ void __cpuinit setup_local_APIC(void)
        preempt_enable();
 }
 
-void __cpuinit lapic_setup_esr(void)
+static void __cpuinit lapic_setup_esr(void)
 {
        unsigned maxlvt = lapic_get_maxlvt();
 
index 7adad088e373fbf4bf5523dcf70f22665331b105..77de848bd1fbbca9d498a07f4c0fbc65cf05c43b 100644 (file)
@@ -550,7 +550,7 @@ static void hard_enable_TSC(void)
        write_cr4(read_cr4() & ~X86_CR4_TSD);
 }
 
-void enable_TSC(void)
+static void enable_TSC(void)
 {
        preempt_disable();
        if (test_and_clear_thread_flag(TIF_NOTSC))
index 891af1a1b48a5cbf0ef303d9f1b5c5601b485869..131c2ee7ac5618e9fc92f576f4db19676bd235af 100644 (file)
@@ -562,7 +562,7 @@ static void hard_enable_TSC(void)
        write_cr4(read_cr4() & ~X86_CR4_TSD);
 }
 
-void enable_TSC(void)
+static void enable_TSC(void)
 {
        preempt_disable();
        if (test_and_clear_thread_flag(TIF_NOTSC))
index 0d1f44ae6eea83b3ab32d17fe04a817227dd2acf..c0c68c18a788dff30e0103b144cb0b76a09ec775 100644 (file)
@@ -18,8 +18,6 @@ unsigned disabled_cpus __cpuinitdata;
 unsigned int boot_cpu_physical_apicid = -1U;
 EXPORT_SYMBOL(boot_cpu_physical_apicid);
 
-physid_mask_t phys_cpu_present_map;
-
 DEFINE_PER_CPU(u16, x86_cpu_to_apicid) = BAD_APICID;
 EXPORT_PER_CPU_SYMBOL(x86_cpu_to_apicid);
 
index 78828b0f604fb387f1e847ae16f35272d51cb44a..455d3c80960bf93e63d0914c56a170f88482ab70 100644 (file)
@@ -442,7 +442,7 @@ static void __init reserve_ebda_region(void)
 }
 
 #ifndef CONFIG_NEED_MULTIPLE_NODES
-void __init setup_bootmem_allocator(void);
+static void __init setup_bootmem_allocator(void);
 static unsigned long __init setup_memory(void)
 {
        /*
@@ -477,7 +477,7 @@ static unsigned long __init setup_memory(void)
        return max_low_pfn;
 }
 
-void __init zone_sizes_init(void)
+static void __init zone_sizes_init(void)
 {
        unsigned long max_zone_pfns[MAX_NR_ZONES];
        memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
index 6a925394bc7e646e70cd17a54fd6da0710a11e80..ade371f9663a9efa6ca0b37636b139cf3297e338 100644 (file)
@@ -184,7 +184,7 @@ static void unmap_cpu_to_node(int cpu)
 u8 cpu_2_logical_apicid[NR_CPUS] __read_mostly =
                                        { [0 ... NR_CPUS-1] = BAD_APICID };
 
-void map_cpu_to_logical_apicid(void)
+static void map_cpu_to_logical_apicid(void)
 {
        int cpu = smp_processor_id();
        int apicid = logical_smp_processor_id();
@@ -197,7 +197,7 @@ void map_cpu_to_logical_apicid(void)
        map_cpu_to_node(cpu, node);
 }
 
-void unmap_cpu_to_logical_apicid(int cpu)
+static void unmap_cpu_to_logical_apicid(int cpu)
 {
        cpu_2_logical_apicid[cpu] = BAD_APICID;
        unmap_cpu_to_node(cpu);
@@ -211,7 +211,7 @@ void unmap_cpu_to_logical_apicid(int cpu)
  * Report back to the Boot Processor.
  * Running on AP.
  */
-void __cpuinit smp_callin(void)
+static void __cpuinit smp_callin(void)
 {
        int cpuid, phys_id;
        unsigned long timeout;
@@ -436,7 +436,7 @@ valid_k7:
 #endif
 }
 
-void __cpuinit smp_checks(void)
+static void __cpuinit smp_checks(void)
 {
        if (smp_b_stepping)
                printk(KERN_WARNING "WARNING: SMP operation may be unreliable"
@@ -565,7 +565,7 @@ void __init smp_alloc_memory(void)
 }
 #endif
 
-void impress_friends(void)
+static void impress_friends(void)
 {
        int cpu;
        unsigned long bogosum = 0;
@@ -1287,7 +1287,7 @@ void cpu_exit_clear(void)
 }
 #  endif /* CONFIG_X86_32 */
 
-void remove_siblinginfo(int cpu)
+static void remove_siblinginfo(int cpu)
 {
        int sibling;
        struct cpuinfo_x86 *c = &cpu_data(cpu);
index 1558e513757e4516fac196729a182657977a95f3..df224a8774cb461e1e542686c17fdfe46dceec8f 100644 (file)
@@ -191,7 +191,7 @@ void native_flush_tlb_others(const cpumask_t *cpumaskp, struct mm_struct *mm,
        spin_unlock(&f->tlbstate_lock);
 }
 
-int __cpuinit init_smp_flush(void)
+static int __cpuinit init_smp_flush(void)
 {
        int i;
 
index edff4c9854854429fda22ce2d35f7f08fa64c593..61efa2f7d5645c804bba44bf524661133bc15374 100644 (file)
@@ -216,7 +216,7 @@ vgetcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *tcache)
        return 0;
 }
 
-long __vsyscall(3) venosys_1(void)
+static long __vsyscall(3) venosys_1(void)
 {
        return -ENOSYS;
 }
index 2a8456a1f44fc5896fe7de8ed25aa106d8bead68..57484e91ab904c35b327464d80bd16766556f3eb 100644 (file)
 /* Have we found an MP table */
 int smp_found_config;
 
-/*
- * Various Linux-internal data structures created from the
- * MP-table.
- */
-int apic_version [MAX_APICS];
-
 int pic_mode;
-unsigned long mp_lapic_addr;
-
-/* Processor that is doing the boot up */
-unsigned int boot_cpu_physical_apicid = -1U;
-
-/* Bitmask of physically existing CPUs */
-physid_mask_t phys_cpu_present_map;
 
-unsigned int __initdata maxcpus = NR_CPUS;
+extern unsigned int __cpuinitdata maxcpus;
 
 /*
  * The Visual Workstation is Intel MP compliant in the hardware
index 96f60c7cd124a141e7f4825bbbe555e8893d9ef3..d05722121d2412b76bb6aea832935c5f16aee773 100644 (file)
@@ -206,11 +206,6 @@ static struct irq_chip vic_chip = {
 /* used to count up as CPUs are brought on line (starts at 0) */
 static int cpucount = 0;
 
-/* steal a page from the bottom of memory for the trampoline and
- * squirrel its address away here.  This will be in kernel virtual
- * space */
-unsigned char *trampoline_base;
-
 /* The per cpu profile stuff - used in smp_local_timer_interrupt */
 static DEFINE_PER_CPU(int, prof_multiplier) = 1;
 static DEFINE_PER_CPU(int, prof_old_multiplier) = 1;
@@ -427,18 +422,6 @@ void __init smp_store_cpu_info(int id)
        identify_secondary_cpu(c);
 }
 
-/* set up the trampoline and return the physical address of the code */
-unsigned long __init setup_trampoline(void)
-{
-       /* these two are global symbols in trampoline.S */
-       extern const __u8 trampoline_end[];
-       extern const __u8 trampoline_data[];
-
-       memcpy(trampoline_base, trampoline_data,
-              trampoline_end - trampoline_data);
-       return virt_to_phys(trampoline_base);
-}
-
 /* Routine initially called when a non-boot CPU is brought online */
 static void __init start_secondary(void *unused)
 {
index 6791b8334bc6809ebd7d35bc69c29f1e23e2ff64..2c24bea92c669457d50c77b7752c1954e6654f11 100644 (file)
@@ -324,7 +324,7 @@ static const struct file_operations ptdump_fops = {
        .release        = single_release,
 };
 
-int pt_dump_init(void)
+static int pt_dump_init(void)
 {
        struct dentry *pe;
 
index f7823a17286838d016985c3c3bb9885c08982c95..c29ebd037254fb3252b75944e9649cdac1b3059a 100644 (file)
@@ -993,7 +993,7 @@ static const struct file_operations dpa_fops = {
        .release        = single_release,
 };
 
-int __init debug_pagealloc_proc_init(void)
+static int __init debug_pagealloc_proc_init(void)
 {
        struct dentry *de;
 
index fb43d89f46f3c92b51e5eedc85be49340eabd765..3890234e5b2629f54f1449224510ba612d58ba68 100644 (file)
@@ -163,7 +163,7 @@ acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa)
               pxm, apic_id, node);
 }
 
-int update_end_of_memory(unsigned long end) {return -1;}
+static int update_end_of_memory(unsigned long end) {return -1;}
 static int hotadd_enough_memory(struct bootnode *nd) {return 1;}
 #ifdef CONFIG_MEMORY_HOTPLUG_SPARSE
 static inline int save_add_info(void) {return 1;}
index a87b89db08e99dd10cb30b9b2e0f7d72421b6edf..2906ee7bd298f5e87f2cfea5ea10e113d0abfb08 100644 (file)
@@ -481,6 +481,34 @@ config BRIQ_PANEL
 
          It's safe to say N here.
 
+config BFIN_OTP
+       tristate "Blackfin On-Chip OTP Memory Support"
+       depends on BLACKFIN && (BF52x || BF54x)
+       default y
+       help
+         If you say Y here, you will get support for a character device
+         interface into the One Time Programmable memory pages that are
+         stored on the Blackfin processor.  This will not get you access
+         to the secure memory pages however.  You will need to write your
+         own secure code and reader for that.
+
+         To compile this driver as a module, choose M here: the module
+         will be called bfin-otp.
+
+         If unsure, it is safe to say Y.
+
+config BFIN_OTP_WRITE_ENABLE
+       bool "Enable writing support of OTP pages"
+       depends on BFIN_OTP
+       default n
+       help
+         If you say Y here, you will enable support for writing of the
+         OTP pages.  This is dangerous by nature as you can only program
+         the pages once, so only enable this option when you actually
+         need it so as to not inadvertently clobber data.
+
+         If unsure, say N.
+
 config PRINTER
        tristate "Parallel printer support"
        depends on PARPORT
index 5407b7615614b8864c6c81c259b04283598eedc1..4c1c584e9eb678d366e575a3cd983b287d4419e0 100644 (file)
@@ -59,6 +59,7 @@ obj-$(CONFIG_VIOTAPE)         += viotape.o
 obj-$(CONFIG_HVCS)             += hvcs.o
 obj-$(CONFIG_SGI_MBCS)         += mbcs.o
 obj-$(CONFIG_BRIQ_PANEL)       += briq_panel.o
+obj-$(CONFIG_BFIN_OTP)         += bfin-otp.o
 
 obj-$(CONFIG_PRINTER)          += lp.o
 obj-$(CONFIG_TIPAR)            += tipar.o
diff --git a/drivers/char/bfin-otp.c b/drivers/char/bfin-otp.c
new file mode 100644 (file)
index 0000000..0a01329
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ * Blackfin On-Chip OTP Memory Interface
+ *  Supports BF52x/BF54x
+ *
+ * Copyright 2007-2008 Analog Devices Inc.
+ *
+ * Enter bugs at http://blackfin.uclinux.org/
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/types.h>
+
+#include <asm/blackfin.h>
+#include <asm/uaccess.h>
+
+#define stamp(fmt, args...) pr_debug("%s:%i: " fmt "\n", __func__, __LINE__, ## args)
+#define stampit() stamp("here i am")
+#define pr_init(fmt, args...) ({ static const __initconst char __fmt[] = fmt; printk(__fmt, ## args); })
+
+#define DRIVER_NAME "bfin-otp"
+#define PFX DRIVER_NAME ": "
+
+static DEFINE_MUTEX(bfin_otp_lock);
+
+/* OTP Boot ROM functions */
+#define _BOOTROM_OTP_COMMAND           0xEF000018
+#define _BOOTROM_OTP_READ              0xEF00001A
+#define _BOOTROM_OTP_WRITE             0xEF00001C
+
+static u32 (* const otp_command)(u32 command, u32 value) = (void *)_BOOTROM_OTP_COMMAND;
+static u32 (* const otp_read)(u32 page, u32 flags, u64 *page_content) = (void *)_BOOTROM_OTP_READ;
+static u32 (* const otp_write)(u32 page, u32 flags, u64 *page_content) = (void *)_BOOTROM_OTP_WRITE;
+
+/* otp_command(): defines for "command" */
+#define OTP_INIT             0x00000001
+#define OTP_CLOSE            0x00000002
+
+/* otp_{read,write}(): defines for "flags" */
+#define OTP_LOWER_HALF       0x00000000 /* select upper/lower 64-bit half (bit 0) */
+#define OTP_UPPER_HALF       0x00000001
+#define OTP_NO_ECC           0x00000010 /* do not use ECC */
+#define OTP_LOCK             0x00000020 /* sets page protection bit for page */
+#define OTP_ACCESS_READ      0x00001000
+#define OTP_ACCESS_READWRITE 0x00002000
+
+/* Return values for all functions */
+#define OTP_SUCCESS          0x00000000
+#define OTP_MASTER_ERROR     0x001
+#define OTP_WRITE_ERROR      0x003
+#define OTP_READ_ERROR       0x005
+#define OTP_ACC_VIO_ERROR    0x009
+#define OTP_DATA_MULT_ERROR  0x011
+#define OTP_ECC_MULT_ERROR   0x021
+#define OTP_PREV_WR_ERROR    0x041
+#define OTP_DATA_SB_WARN     0x100
+#define OTP_ECC_SB_WARN      0x200
+
+/**
+ *     bfin_otp_read - Read OTP pages
+ *
+ *     All reads must be in half page chunks (half page == 64 bits).
+ */
+static ssize_t bfin_otp_read(struct file *file, char __user *buff, size_t count, loff_t *pos)
+{
+       ssize_t bytes_done;
+       u32 page, flags, ret;
+       u64 content;
+
+       stampit();
+
+       if (count % sizeof(u64))
+               return -EMSGSIZE;
+
+       if (mutex_lock_interruptible(&bfin_otp_lock))
+               return -ERESTARTSYS;
+
+       bytes_done = 0;
+       page = *pos / (sizeof(u64) * 2);
+       while (bytes_done < count) {
+               flags = (*pos % (sizeof(u64) * 2) ? OTP_UPPER_HALF : OTP_LOWER_HALF);
+               stamp("processing page %i (%s)", page, (flags == OTP_UPPER_HALF ? "upper" : "lower"));
+               ret = otp_read(page, flags, &content);
+               if (ret & OTP_MASTER_ERROR) {
+                       bytes_done = -EIO;
+                       break;
+               }
+               if (copy_to_user(buff + bytes_done, &content, sizeof(content))) {
+                       bytes_done = -EFAULT;
+                       break;
+               }
+               if (flags == OTP_UPPER_HALF)
+                       ++page;
+               bytes_done += sizeof(content);
+               *pos += sizeof(content);
+       }
+
+       mutex_unlock(&bfin_otp_lock);
+
+       return bytes_done;
+}
+
+#ifdef CONFIG_BFIN_OTP_WRITE_ENABLE
+/**
+ *     bfin_otp_write - Write OTP pages
+ *
+ *     All writes must be in half page chunks (half page == 64 bits).
+ */
+static ssize_t bfin_otp_write(struct file *filp, const char __user *buff, size_t count, loff_t *pos)
+{
+       stampit();
+
+       if (count % sizeof(u64))
+               return -EMSGSIZE;
+
+       if (mutex_lock_interruptible(&bfin_otp_lock))
+               return -ERESTARTSYS;
+
+       /* need otp_init() documentation before this can be implemented */
+
+       mutex_unlock(&bfin_otp_lock);
+
+       return -EINVAL;
+}
+#else
+# define bfin_otp_write NULL
+#endif
+
+static struct file_operations bfin_otp_fops = {
+       .owner    = THIS_MODULE,
+       .read     = bfin_otp_read,
+       .write    = bfin_otp_write,
+};
+
+static struct miscdevice bfin_otp_misc_device = {
+       .minor    = MISC_DYNAMIC_MINOR,
+       .name     = DRIVER_NAME,
+       .fops     = &bfin_otp_fops,
+};
+
+/**
+ *     bfin_otp_init - Initialize module
+ *
+ *     Registers the device and notifier handler. Actual device
+ *     initialization is handled by bfin_otp_open().
+ */
+static int __init bfin_otp_init(void)
+{
+       int ret;
+
+       stampit();
+
+       ret = misc_register(&bfin_otp_misc_device);
+       if (ret) {
+               pr_init(KERN_ERR PFX "unable to register a misc device\n");
+               return ret;
+       }
+
+       pr_init(KERN_INFO PFX "initialized\n");
+
+       return 0;
+}
+
+/**
+ *     bfin_otp_exit - Deinitialize module
+ *
+ *     Unregisters the device and notifier handler. Actual device
+ *     deinitialization is handled by bfin_otp_close().
+ */
+static void __exit bfin_otp_exit(void)
+{
+       stampit();
+
+       misc_deregister(&bfin_otp_misc_device);
+}
+
+module_init(bfin_otp_init);
+module_exit(bfin_otp_exit);
+
+MODULE_AUTHOR("Mike Frysinger <vapier@gentoo.org>");
+MODULE_DESCRIPTION("Blackfin OTP Memory Interface");
+MODULE_LICENSE("GPL");
index 37fe80df0b91bdbeecee5072ac3f6b129ca62481..f282976daaacfe8e6da245071757c9d552f0fbad 100644 (file)
@@ -97,24 +97,20 @@ static void EnableSRAM(THINKPAD_BD_DATA * pBDData)
 
 static irqreturn_t UartInterrupt(int irq, void *dev_id)
 {
-       int irqno = (int)(unsigned long) dev_id;
-
        PRINTK_3(TRACE_TP3780I,
-               "tp3780i::UartInterrupt entry irq %x dev_id %p\n", irqno, dev_id);
+               "tp3780i::UartInterrupt entry irq %x dev_id %p\n", irq, dev_id);
        return IRQ_HANDLED;
 }
 
 static irqreturn_t DspInterrupt(int irq, void *dev_id)
 {
-       int irqno = (int)(unsigned long) dev_id;
-
        pMWAVE_DEVICE_DATA pDrvData = &mwave_s_mdd;
        DSP_3780I_CONFIG_SETTINGS *pSettings = &pDrvData->rBDData.rDspSettings;
        unsigned short usDspBaseIO = pSettings->usDspBaseIO;
        unsigned short usIPCSource = 0, usIsolationMask, usPCNum;
 
        PRINTK_3(TRACE_TP3780I,
-               "tp3780i::DspInterrupt entry irq %x dev_id %p\n", irqno, dev_id);
+               "tp3780i::DspInterrupt entry irq %x dev_id %p\n", irq, dev_id);
 
        if (dsp3780I_GetIPCSource(usDspBaseIO, &usIPCSource) == 0) {
                PRINTK_2(TRACE_TP3780I,
@@ -365,16 +361,14 @@ int tp3780I_EnableDSP(THINKPAD_BD_DATA * pBDData)
        pSettings->bPllBypass = TP_CFG_PllBypass;
        pSettings->usChipletEnable = TP_CFG_ChipletEnable;
 
-       if (request_irq(pSettings->usUartIrq, &UartInterrupt, 0, "mwave_uart",
-                       (void *)(unsigned long) pSettings->usUartIrq)) {
+       if (request_irq(pSettings->usUartIrq, &UartInterrupt, 0, "mwave_uart", NULL)) {
                PRINTK_ERROR(KERN_ERR_MWAVE "tp3780i::tp3780I_EnableDSP: Error: Could not get UART IRQ %x\n", pSettings->usUartIrq);
                goto exit_cleanup;
        } else {                /* no conflict just release */
                free_irq(pSettings->usUartIrq, NULL);
        }
 
-       if (request_irq(pSettings->usDspIrq, &DspInterrupt, 0, "mwave_3780i",
-                       (void *)(unsigned long) pSettings->usDspIrq)) {
+       if (request_irq(pSettings->usDspIrq, &DspInterrupt, 0, "mwave_3780i", NULL)) {
                PRINTK_ERROR("tp3780i::tp3780I_EnableDSP: Error: Could not get 3780i IRQ %x\n", pSettings->usDspIrq);
                goto exit_cleanup;
        } else {
index c5263d63aca3a2cc56914f7651f44d56bf8c8a32..92b683411d5ab293cf27d34c0a9c07e1fafa2cf5 100644 (file)
@@ -15,6 +15,7 @@ if INPUT_MISC
 config INPUT_PCSPKR
        tristate "PC Speaker support"
        depends on ALPHA || X86 || MIPS || PPC_PREP || PPC_CHRP || PPC_PSERIES
+       depends on SND_PCSP=n
        help
          Say Y here if you want the standard PC Speaker to be used for
          bells and whistles.
index 11950698a2e7529611080fcd83c475b1ccf9511e..128bb9cd5755f57f7a8cab9895149edcb39680aa 100644 (file)
@@ -30,7 +30,7 @@ config VIDEO_V4L2_COMMON
        depends on (I2C || I2C=n) && VIDEO_DEV
        default (I2C || I2C=n) && VIDEO_DEV
 
-config VIDEO_V4L1
+config VIDEO_ALLOW_V4L1
        bool "Enable Video For Linux API 1 (DEPRECATED)"
        depends on VIDEO_DEV && VIDEO_V4L2_COMMON
        default VIDEO_DEV && VIDEO_V4L2_COMMON
@@ -59,10 +59,15 @@ config VIDEO_V4L1_COMPAT
          If you are unsure as to whether this is required, answer Y.
 
 config VIDEO_V4L2
-       bool
+       tristate
        depends on VIDEO_DEV && VIDEO_V4L2_COMMON
        default VIDEO_DEV && VIDEO_V4L2_COMMON
 
+config VIDEO_V4L1
+       tristate
+       depends on VIDEO_DEV && VIDEO_V4L2_COMMON && VIDEO_ALLOW_V4L1
+       default VIDEO_DEV && VIDEO_V4L2_COMMON && VIDEO_ALLOW_V4L1
+
 source "drivers/media/video/Kconfig"
 
 source "drivers/media/radio/Kconfig"
@@ -155,7 +160,7 @@ config VIDEOBUF_GEN
        tristate
 
 config VIDEOBUF_DMA_SG
-       depends on PCI
+       depends on HAS_DMA
        select VIDEOBUF_GEN
        tristate
 
index bb2a027b94837d40740503ad50a94dbb71dc2b74..2665052079258c6d015cc42f7109bfd1d11f6b8c 100644 (file)
@@ -34,7 +34,7 @@ static int repeat = 1;
 module_param(repeat, int, 0444);
 MODULE_PARM_DESC(repeat,"auto-repeat for IR keys (default: on)");
 
-static int debug = 0;    /* debug level (0,1,2) */
+static int debug;    /* debug level (0,1,2) */
 module_param(debug, int, 0644);
 
 #define dprintk(level, fmt, arg...)    if (debug >= level) \
index 2ab5a120470d98569a6f922afd08a463c446566a..a3485817e46c9e06b765bda262fdd9f8215b7168 100644 (file)
@@ -212,6 +212,51 @@ IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = {
 
 EXPORT_SYMBOL_GPL(ir_codes_pixelview);
 
+/*
+   Mauro Carvalho Chehab <mchehab@infradead.org>
+   present on PV MPEG 8000GT
+ */
+IR_KEYTAB_TYPE ir_codes_pixelview_new[IR_KEYTAB_SIZE] = {
+       [0x3c] = KEY_PAUSE,             /* Timeshift */
+       [0x12] = KEY_POWER,
+
+       [0x3d] = KEY_1,
+       [0x38] = KEY_2,
+       [0x18] = KEY_3,
+       [0x35] = KEY_4,
+       [0x39] = KEY_5,
+       [0x15] = KEY_6,
+       [0x36] = KEY_7,
+       [0x3a] = KEY_8,
+       [0x1e] = KEY_9,
+       [0x3e] = KEY_0,
+
+       [0x1c] = KEY_AGAIN,             /* LOOP */
+       [0x3f] = KEY_MEDIA,             /* Source */
+       [0x1f] = KEY_LAST,              /* +100 */
+       [0x1b] = KEY_MUTE,
+
+       [0x17] = KEY_CHANNELDOWN,
+       [0x16] = KEY_CHANNELUP,
+       [0x10] = KEY_VOLUMEUP,
+       [0x14] = KEY_VOLUMEDOWN,
+       [0x13] = KEY_ZOOM,
+
+       [0x19] = KEY_SHUFFLE,           /* SNAPSHOT */
+       [0x1a] = KEY_SEARCH,            /* scan */
+
+       [0x37] = KEY_REWIND,            /* << */
+       [0x32] = KEY_RECORD,            /* o (red) */
+       [0x33] = KEY_FORWARD,           /* >> */
+       [0x11] = KEY_STOP,              /* square */
+       [0x3b] = KEY_PLAY,              /* > */
+       [0x30] = KEY_PLAYPAUSE,         /* || */
+
+       [0x31] = KEY_TV,
+       [0x34] = KEY_RADIO,
+};
+EXPORT_SYMBOL_GPL(ir_codes_pixelview_new);
+
 IR_KEYTAB_TYPE ir_codes_nebula[IR_KEYTAB_SIZE] = {
        [ 0x00 ] = KEY_0,
        [ 0x01 ] = KEY_1,
@@ -726,7 +771,11 @@ IR_KEYTAB_TYPE ir_codes_flyvideo[IR_KEYTAB_SIZE] = {
        [ 0x12 ] = KEY_CHANNELUP,    // Channel +
        [ 0x13 ] = KEY_CHANNELDOWN,  // Channel -
        [ 0x06 ] = KEY_AGAIN,        // Recall
-       [ 0x10 ] = KEY_ENTER,      // Enter
+       [ 0x10 ] = KEY_ENTER,        // Enter
+
+       [ 0x19 ] = KEY_BACK,         // Rewind  ( <<< )
+       [ 0x1f ] = KEY_FORWARD,      // Forward ( >>> )
+       [ 0x0a ] = KEY_ANGLE,        // (no label, may be used as the PAUSE button)
 };
 
 EXPORT_SYMBOL_GPL(ir_codes_flyvideo);
@@ -1157,7 +1206,8 @@ EXPORT_SYMBOL_GPL(ir_codes_purpletv);
 
 /* Mapping for the 28 key remote control as seen at
    http://www.sednacomputer.com/photo/cardbus-tv.jpg
-   Pavel Mihaylov <bin@bash.info> */
+   Pavel Mihaylov <bin@bash.info>
+   Also for the remote bundled with Kozumi KTV-01C card */
 IR_KEYTAB_TYPE ir_codes_pctv_sedna[IR_KEYTAB_SIZE] = {
        [ 0x00 ] = KEY_0,
        [ 0x01 ] = KEY_1,
@@ -1188,6 +1238,11 @@ IR_KEYTAB_TYPE ir_codes_pctv_sedna[IR_KEYTAB_SIZE] = {
        [ 0x1c ] = KEY_RADIO,          /* FM Radio */
        [ 0x1d ] = KEY_RECORD,
        [ 0x1e ] = KEY_PAUSE,
+       /* additional codes for Kozumi's remote */
+       [0x14] = KEY_INFO,        /* OSD */
+       [0x16] = KEY_OK,          /* OK */
+       [0x17] = KEY_DIGITS,      /* Plus */
+       [0x1f] = KEY_PLAY,        /* Play */
 };
 
 EXPORT_SYMBOL_GPL(ir_codes_pctv_sedna);
@@ -1988,6 +2043,76 @@ IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE] = {
 
 EXPORT_SYMBOL_GPL(ir_codes_behold);
 
+/* Beholder Intl. Ltd. 2008
+ * Dmitry Belimov d.belimov@google.com
+ * Keytable is used by BeholdTV Columbus
+ * The "ascii-art picture" below (in comments, first row
+ * is the keycode in hex, and subsequent row(s) shows
+ * the button labels (several variants when appropriate)
+ * helps to descide which keycodes to assign to the buttons.
+ */
+IR_KEYTAB_TYPE ir_codes_behold_columbus[IR_KEYTAB_SIZE] = {
+
+       /*  0x13   0x11   0x1C   0x12  *
+        *  Mute  Source  TV/FM  Power *
+        *                             */
+
+       [0x13] = KEY_MUTE,
+       [0x11] = KEY_PROPS,
+       [0x1C] = KEY_TUNER,     /* KEY_TV/KEY_RADIO */
+       [0x12] = KEY_POWER,
+
+       /*  0x01    0x02    0x03  0x0D    *
+        *   1       2       3   Stereo   *
+        *                                *
+        *  0x04    0x05    0x06  0x19    *
+        *   4       5       6   Snapshot *
+        *                                *
+        *  0x07    0x08    0x09  0x10    *
+        *   7       8       9    Zoom    *
+        *                                */
+       [0x01] = KEY_1,
+       [0x02] = KEY_2,
+       [0x03] = KEY_3,
+       [0x0D] = KEY_SETUP,       /* Setup key */
+       [0x04] = KEY_4,
+       [0x05] = KEY_5,
+       [0x06] = KEY_6,
+       [0x19] = KEY_BOOKMARKS, /* Snapshot key */
+       [0x07] = KEY_7,
+       [0x08] = KEY_8,
+       [0x09] = KEY_9,
+       [0x10] = KEY_ZOOM,
+
+       /*  0x0A    0x00    0x0B       0x0C   *
+        * RECALL    0    ChannelUp  VolumeUp *
+        *                                    */
+       [0x0A] = KEY_AGAIN,
+       [0x00] = KEY_0,
+       [0x0B] = KEY_CHANNELUP,
+       [0x0C] = KEY_VOLUMEUP,
+
+       /*   0x1B      0x1D      0x15        0x18     *
+        * Timeshift  Record  ChannelDown  VolumeDown *
+        *                                            */
+
+       [0x1B] = KEY_REWIND,
+       [0x1D] = KEY_RECORD,
+       [0x15] = KEY_CHANNELDOWN,
+       [0x18] = KEY_VOLUMEDOWN,
+
+       /*   0x0E   0x1E     0x0F     0x1A  *
+        *   Stop   Pause  Previouse  Next  *
+        *                                  */
+
+       [0x0E] = KEY_STOP,
+       [0x1E] = KEY_PAUSE,
+       [0x0F] = KEY_PREVIOUS,
+       [0x1A] = KEY_NEXT,
+
+};
+EXPORT_SYMBOL_GPL(ir_codes_behold_columbus);
+
 /*
  * Remote control for the Genius TVGO A11MCE
  * Adrian Pardini <pardo.bsso@gmail.com>
@@ -2033,3 +2158,46 @@ IR_KEYTAB_TYPE ir_codes_genius_tvgo_a11mce[IR_KEYTAB_SIZE] = {
        [0x50] = KEY_BLUE,
 };
 EXPORT_SYMBOL_GPL(ir_codes_genius_tvgo_a11mce);
+
+/*
+ * Remote control for Powercolor Real Angel 330
+ * Daniel Fraga <fragabr@gmail.com>
+ */
+IR_KEYTAB_TYPE ir_codes_powercolor_real_angel[IR_KEYTAB_SIZE] = {
+       [0x38] = KEY_SWITCHVIDEOMODE,   /* switch inputs */
+       [0x0c] = KEY_MEDIA,             /* Turn ON/OFF App */
+       [0x00] = KEY_0,
+       [0x01] = KEY_1,
+       [0x02] = KEY_2,
+       [0x03] = KEY_3,
+       [0x04] = KEY_4,
+       [0x05] = KEY_5,
+       [0x06] = KEY_6,
+       [0x07] = KEY_7,
+       [0x08] = KEY_8,
+       [0x09] = KEY_9,
+       [0x0a] = KEY_DIGITS,            /* single, double, tripple digit */
+       [0x29] = KEY_PREVIOUS,          /* previous channel */
+       [0x12] = KEY_BRIGHTNESSUP,
+       [0x13] = KEY_BRIGHTNESSDOWN,
+       [0x2b] = KEY_MODE,              /* stereo/mono */
+       [0x2c] = KEY_TEXT,              /* teletext */
+       [0x20] = KEY_UP,                /* channel up */
+       [0x21] = KEY_DOWN,              /* channel down */
+       [0x10] = KEY_RIGHT,             /* volume up */
+       [0x11] = KEY_LEFT,              /* volume down */
+       [0x0d] = KEY_MUTE,
+       [0x1f] = KEY_RECORD,
+       [0x17] = KEY_PLAY,
+       [0x16] = KEY_PAUSE,
+       [0x0b] = KEY_STOP,
+       [0x27] = KEY_FASTFORWARD,
+       [0x26] = KEY_REWIND,
+       [0x1e] = KEY_SEARCH,            /* autoscan */
+       [0x0e] = KEY_SHUFFLE,           /* snapshot */
+       [0x2d] = KEY_SETUP,
+       [0x0f] = KEY_SCREEN,            /* full screen */
+       [0x14] = KEY_RADIO,             /* FM radio */
+       [0x25] = KEY_POWER,             /* power */
+};
+EXPORT_SYMBOL_GPL(ir_codes_powercolor_real_angel);
index 7707b8c7394b17308c067b2813f6809e105c5072..89c7660b85d66cf4dc84c6da4baa9ba14461bd0e 100644 (file)
@@ -74,7 +74,7 @@ static inline int saa7146_wait_for_debi_done_sleep(struct saa7146_dev *dev,
                if (err) {
                        printk(KERN_ERR "%s: %s timed out while waiting for "
                                        "registers getting programmed\n",
-                                       dev->name, __FUNCTION__);
+                                       dev->name, __func__);
                        return -ETIMEDOUT;
                }
                msleep(1);
@@ -89,7 +89,7 @@ static inline int saa7146_wait_for_debi_done_sleep(struct saa7146_dev *dev,
                saa7146_read(dev, MC2);
                if (err) {
                        DEB_S(("%s: %s timed out while waiting for transfer "
-                               "completion\n", dev->name, __FUNCTION__));
+                               "completion\n", dev->name, __func__));
                        return -ETIMEDOUT;
                }
                msleep(1);
@@ -111,7 +111,7 @@ static inline int saa7146_wait_for_debi_done_busyloop(struct saa7146_dev *dev,
                if (!loops--) {
                        printk(KERN_ERR "%s: %s timed out while waiting for "
                                        "registers getting programmed\n",
-                                       dev->name, __FUNCTION__);
+                                       dev->name, __func__);
                        return -ETIMEDOUT;
                }
                udelay(1);
@@ -125,7 +125,7 @@ static inline int saa7146_wait_for_debi_done_busyloop(struct saa7146_dev *dev,
                saa7146_read(dev, MC2);
                if (!loops--) {
                        DEB_S(("%s: %s timed out while waiting for transfer "
-                               "completion\n", dev->name, __FUNCTION__));
+                               "completion\n", dev->name, __func__));
                        return -ETIMEDOUT;
                }
                udelay(5);
index 7e7689afae629c0a012979dc56a2dc6f30ade7d3..35b01ec40a5139d6e48b675338bd057360a0a79c 100644 (file)
@@ -203,7 +203,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
                                return -ERESTARTSYS;
 
                        printk(KERN_WARNING "%s %s [irq]: timed out waiting for end of xfer\n",
-                               dev->name, __FUNCTION__);
+                               dev->name, __func__);
                        return -EIO;
                }
                status = saa7146_read(dev, I2C_STATUS);
@@ -221,7 +221,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
                        }
                        if (time_after(jiffies,timeout)) {
                                printk(KERN_WARNING "%s %s: timed out waiting for MC2\n",
-                                       dev->name, __FUNCTION__);
+                                       dev->name, __func__);
                                return -EIO;
                        }
                }
@@ -238,7 +238,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
                                 * (no answer from nonexisistant device...)
                                 */
                                printk(KERN_WARNING "%s %s [poll]: timed out waiting for end of xfer\n",
-                                       dev->name, __FUNCTION__);
+                                       dev->name, __func__);
                                return -EIO;
                        }
                        if (++trial < 50 && short_delay)
index bfbd5a841ebf9f621642b60d1ca0324a650c6b84..74e2b56ecb5bb09b13135640872efb32445165b3 100644 (file)
@@ -407,8 +407,8 @@ static int vbi_open(struct saa7146_dev *dev, struct file *file)
        fh->vbi_fmt.start[1] = 312;
        fh->vbi_fmt.count[1] = 16;
 
-       videobuf_queue_pci_init(&fh->vbi_q, &vbi_qops,
-                           dev->pci, &dev->slock,
+       videobuf_queue_sg_init(&fh->vbi_q, &vbi_qops,
+                           &dev->pci->dev, &dev->slock,
                            V4L2_BUF_TYPE_VBI_CAPTURE,
                            V4L2_FIELD_SEQ_TB, // FIXME: does this really work?
                            sizeof(struct saa7146_buf),
index 66fdbd0e6a6ddfe5ad7f5a6a72045e574db95d56..3cbc6ebbe64939b5d7239dd40caa4b6ab38c58f0 100644 (file)
@@ -1410,8 +1410,8 @@ static int video_open(struct saa7146_dev *dev, struct file *file)
        sfmt = format_by_fourcc(dev,fh->video_fmt.pixelformat);
        fh->video_fmt.sizeimage = (fh->video_fmt.width * fh->video_fmt.height * sfmt->depth)/8;
 
-       videobuf_queue_pci_init(&fh->video_q, &video_qops,
-                           dev->pci, &dev->slock,
+       videobuf_queue_sg_init(&fh->video_q, &video_qops,
+                           &dev->pci->dev, &dev->slock,
                            V4L2_BUF_TYPE_VIDEO_CAPTURE,
                            V4L2_FIELD_INTERLACED,
                            sizeof(struct saa7146_buf),
index 3197aeb61d1f88181261e3db244b8531e64f9706..6ec5afba1ca7ee061779067f22b36ad352d43b96 100644 (file)
@@ -9,6 +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 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
        help
          Support for the digital TV receiver chip made by B2C2 Inc. included in
          Technisats PCI cards and USB boxes.
index e97ff60a1eff820c1c8df35d8d593c5d24240dfe..870e2848c2962418b343ef2ae4ae5fcc561c0a5d 100644 (file)
@@ -2,6 +2,7 @@ b2c2-flexcop-objs = flexcop.o flexcop-fe-tuner.o flexcop-i2c.o \
        flexcop-sram.o flexcop-eeprom.o flexcop-misc.o flexcop-hw-filter.o
 obj-$(CONFIG_DVB_B2C2_FLEXCOP) += b2c2-flexcop.o
 
+
 ifneq ($(CONFIG_DVB_B2C2_FLEXCOP_PCI),)
 b2c2-flexcop-objs += flexcop-dma.o
 endif
@@ -13,3 +14,4 @@ b2c2-flexcop-usb-objs = flexcop-usb.o
 obj-$(CONFIG_DVB_B2C2_FLEXCOP_USB) += b2c2-flexcop-usb.o
 
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
+EXTRA_CFLAGS += -Idrivers/media/video/
index 5a6c4fe249e7b5bd190c1a062e4f28320c022534..8ce06336e76f88372b83bc0297915b5c048238ca 100644 (file)
@@ -44,6 +44,14 @@ struct flexcop_dma {
        u32 size; /* size of each address in bytes */
 };
 
+struct flexcop_i2c_adapter {
+       struct flexcop_device *fc;
+       struct i2c_adapter i2c_adap;
+
+       u8 no_base_addr;
+       flexcop_i2c_port_t port;
+};
+
 /* Control structure for data definitions that are common to
  * the B2C2-based PCI and USB devices.
  */
@@ -72,7 +80,7 @@ struct flexcop_device {
        struct dmx_frontend mem_frontend;
        int (*fe_sleep) (struct dvb_frontend *);
 
-       struct i2c_adapter i2c_adap;
+       struct flexcop_i2c_adapter fc_i2c_adap[3];
        struct mutex i2c_mutex;
        struct module *owner;
 
@@ -87,7 +95,8 @@ struct flexcop_device {
        int               (*write_ibi_reg) (struct flexcop_device *, flexcop_ibi_register, flexcop_ibi_value);
 
 
-       int (*i2c_request) (struct flexcop_device*, flexcop_access_op_t, flexcop_i2c_port_t, u8 chipaddr, u8 addr, u8 *buf, u16 len);
+       int (*i2c_request) (struct flexcop_i2c_adapter*,
+               flexcop_access_op_t, u8 chipaddr, u8 addr, u8 *buf, u16 len);
        int (*stream_control) (struct flexcop_device*, int);
 
        int (*get_mac_addr) (struct flexcop_device *fc, int extended);
@@ -128,8 +137,8 @@ int flexcop_eeprom_check_mac_addr(struct flexcop_device *fc, int extended);
  * one. We have it in flexcop-i2c.c, because it is going via the actual
  * I2C-channel of the flexcop.
  */
-int flexcop_i2c_request(struct flexcop_device*, flexcop_access_op_t,
-                       flexcop_i2c_port_t, u8 chipaddr, u8 addr, u8 *buf, u16 len);
+int flexcop_i2c_request(struct flexcop_i2c_adapter*, flexcop_access_op_t,
+       u8 chipaddr, u8 addr, u8 *buf, u16 len);
 
 /* from flexcop-sram.c */
 int flexcop_sram_set_dest(struct flexcop_device *fc, flexcop_sram_dest_t dest, flexcop_sram_dest_target_t target);
index 6f592bc32d22ee136eb12fd0e4150af076370701..a91ed28f03a41d815f9edc2f32b7805535cf8ce1 100644 (file)
@@ -112,7 +112,7 @@ static int flexcop_dma_remap(struct flexcop_device *fc,
 {
        flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_00c : dma2_01c;
        flexcop_ibi_value v = fc->read_ibi_reg(fc,r);
-       deb_info("%s\n",__FUNCTION__);
+       deb_info("%s\n",__func__);
        v.dma_0xc.remap_enable = onoff;
        fc->write_ibi_reg(fc,r,v);
        return 0;
@@ -162,7 +162,7 @@ int flexcop_dma_config_timer(struct flexcop_device *fc,
 
        flexcop_dma_remap(fc,dma_idx,0);
 
-       deb_info("%s\n",__FUNCTION__);
+       deb_info("%s\n",__func__);
        v.dma_0x4_write.dmatimer = cycles;
        fc->write_ibi_reg(fc,r,v);
        return 0;
index bbcf070a178ddd95ef0e33f8024c6a80958010ee..8a8ae8a3e6ba6954717739ef59487d8804698297 100644 (file)
@@ -114,15 +114,18 @@ static int flexcop_eeprom_request(struct flexcop_device *fc, flexcop_access_op_t
 {
        int i,ret = 0;
        u8 chipaddr =  0x50 | ((addr >> 8) & 3);
-       for (i = 0; i < retries; i++)
-               if ((ret = fc->i2c_request(fc,op,FC_I2C_PORT_EEPROM,chipaddr,addr & 0xff,buf,len)) == 0)
+       for (i = 0; i < retries; i++) {
+               ret = fc->i2c_request(&fc->fc_i2c_adap[1], op, chipaddr,
+                       addr & 0xff, buf, len);
+               if (ret == 0)
                        break;
+       }
        return ret;
 }
 
 static int flexcop_eeprom_lrc_read(struct flexcop_device *fc, u16 addr, u8 *buf, u16 len, int retries)
 {
-       int ret = flexcop_eeprom_request(fc,FC_READ,addr,buf,len,retries);
+       int ret = flexcop_eeprom_request(fc, FC_READ, addr, buf, len, retries);
        if (ret == 0)
                if (calc_lrc(buf, len - 1) != buf[len - 1])
                        ret = -EINVAL;
index 0378fd64659141ec73933149637552d71aacc0f8..7b0ea3bdfafbf9c1b00080a0e3a97a3478bce212 100644 (file)
@@ -5,6 +5,8 @@
  *
  * see flexcop.c for copyright information.
  */
+#include <media/tuner.h>
+
 #include "flexcop.h"
 
 #include "stv0299.h"
 #include "mt312.h"
 #include "lgdt330x.h"
 #include "dvb-pll.h"
+#include "tuner-simple.h"
+
+#include "s5h1420.h"
+#include "itd1000.h"
+
+#include "cx24123.h"
+#include "cx24113.h"
+
+#include "isl6421.h"
 
 /* lnb control */
 
@@ -180,13 +191,13 @@ static int samsung_tbmu24112_tuner_set_params(struct dvb_frontend* fe, struct dv
        buf[2] = 0x84;  /* 0xC4 */
        buf[3] = 0x08;
 
-       if (params->frequency < 1500000) buf[3] |= 0x10;
+       if (params->frequency < 1500000)
+               buf[3] |= 0x10;
 
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 1);
-       if (i2c_transfer(&fc->i2c_adap, &msg, 1) != 1) {
+       if (i2c_transfer(&fc->fc_i2c_adap[0].i2c_adap, &msg, 1) != 1)
                return -EIO;
-       }
        return 0;
 }
 
@@ -241,7 +252,7 @@ static struct stv0299_config samsung_tbmu24112_config = {
        .mclk = 88000000UL,
        .invert = 0,
        .skip_reinit = 0,
-       .lock_output = STV0229_LOCKOUTPUT_LK,
+       .lock_output = STV0299_LOCKOUTPUT_LK,
        .volt13_op0_op1 = STV0299_VOLT13_OP1,
        .min_delay_ms = 100,
        .set_symbol_rate = samsung_tbmu24112_set_symbol_rate,
@@ -337,7 +348,7 @@ static int skystar23_samsung_tbdu18132_tuner_set_params(struct dvb_frontend* fe,
 
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 1);
-       if (i2c_transfer(&fc->i2c_adap, &msg, 1) != 1)
+       if (i2c_transfer(&fc->fc_i2c_adap[0].i2c_adap, &msg, 1) != 1)
                return -EIO;
        return 0;
 }
@@ -386,10 +397,11 @@ static int alps_tdee4_stv0297_tuner_set_params(struct dvb_frontend* fe,
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 0);
        deb_tuner("tuner buffer for %d Hz: %x %x %x %x\n",fep->frequency, buf[0],buf[1],buf[2],buf[3]);
-       ret = fc->i2c_request(fc, FC_WRITE, FC_I2C_PORT_TUNER, 0x61, buf[0], &buf[1], 3);
+       ret = fc->i2c_request(&fc->fc_i2c_adap[2],
+               FC_WRITE, 0x61, buf[0], &buf[1], 3);
        deb_tuner("tuner write returned: %d\n",ret);
 
-       return 0;
+       return ret;
 }
 
 static u8 alps_tdee4_stv0297_inittab[] = {
@@ -472,56 +484,159 @@ static struct stv0297_config alps_tdee4_stv0297_config = {
 //     .pll_set = alps_tdee4_stv0297_pll_set,
 };
 
+
+/* SkyStar2 rev2.7 (a/u) */
+static struct s5h1420_config skystar2_rev2_7_s5h1420_config = {
+       .demod_address = 0x53,
+       .invert = 1,
+       .repeated_start_workaround = 1,
+};
+
+static struct itd1000_config skystar2_rev2_7_itd1000_config = {
+       .i2c_address = 0x61,
+};
+
+/* SkyStar2 rev2.8 */
+static struct cx24123_config skystar2_rev2_8_cx24123_config = {
+       .demod_address = 0x55,
+       .dont_use_pll = 1,
+       .agc_callback = cx24113_agc_callback,
+};
+
+static const struct cx24113_config skystar2_rev2_8_cx24113_config = {
+       .i2c_addr = 0x54,
+       .xtal_khz = 10111,
+};
+
 /* try to figure out the frontend, each card/box can have on of the following list */
 int flexcop_frontend_init(struct flexcop_device *fc)
 {
        struct dvb_frontend_ops *ops;
+       struct i2c_adapter *i2c = &fc->fc_i2c_adap[0].i2c_adap;
+       struct i2c_adapter *i2c_tuner;
+
+       /* enable no_base_addr - no repeated start when reading */
+       fc->fc_i2c_adap[0].no_base_addr = 1;
+       fc->fe = dvb_attach(s5h1420_attach, &skystar2_rev2_7_s5h1420_config, i2c);
+       if (fc->fe != NULL) {
+               flexcop_ibi_value r108;
+               i2c_tuner = s5h1420_get_tuner_i2c_adapter(fc->fe);
+               ops = &fc->fe->ops;
+
+               fc->fe_sleep = ops->sleep;
+               ops->sleep   = flexcop_sleep;
+
+               fc->dev_type = FC_SKY_REV27;
+
+               /* enable no_base_addr - no repeated start when reading */
+               fc->fc_i2c_adap[2].no_base_addr = 1;
+               if (dvb_attach(isl6421_attach, fc->fe, &fc->fc_i2c_adap[2].i2c_adap, 0x08, 1, 1) == NULL)
+                       err("ISL6421 could NOT be attached");
+               else
+                       info("ISL6421 successfully attached");
+
+               /* the ITD1000 requires a lower i2c clock - it slows down the stuff for everyone - but is it a problem ? */
+               r108.raw = 0x00000506;
+               fc->write_ibi_reg(fc, tw_sm_c_108, r108);
+               if (i2c_tuner) {
+                       if (dvb_attach(itd1000_attach, fc->fe, i2c_tuner, &skystar2_rev2_7_itd1000_config) == NULL)
+                               err("ITD1000 could NOT be attached");
+                       else
+                               info("ITD1000 successfully attached");
+               }
+               goto fe_found;
+       }
+       fc->fc_i2c_adap[0].no_base_addr = 0; /* for the next devices we need it again */
+
+       /* try the sky v2.8 (cx24123, isl6421) */
+       fc->fe = dvb_attach(cx24123_attach,
+               &skystar2_rev2_8_cx24123_config, i2c);
+       if (fc->fe != NULL) {
+               i2c_tuner = cx24123_get_tuner_i2c_adapter(fc->fe);
+               if (i2c_tuner != NULL) {
+                       if (dvb_attach(cx24113_attach, fc->fe,
+                                       &skystar2_rev2_8_cx24113_config,
+                                       i2c_tuner) == NULL)
+                               err("CX24113 could NOT be attached");
+                       else
+                               info("CX24113 successfully attached");
+               }
+
+               fc->dev_type = FC_SKY_REV28;
+
+               fc->fc_i2c_adap[2].no_base_addr = 1;
+               if (dvb_attach(isl6421_attach, fc->fe,
+                      &fc->fc_i2c_adap[2].i2c_adap, 0x08, 0, 0) == NULL)
+                       err("ISL6421 could NOT be attached");
+               else
+                       info("ISL6421 successfully attached");
+
+               /* TODO on i2c_adap[1] addr 0x11 (EEPROM) there seems to be an
+                * IR-receiver (PIC16F818) - but the card has no input for
+                * that ??? */
+
+               goto fe_found;
+    }
 
        /* try the sky v2.6 (stv0299/Samsung tbmu24112(sl1935)) */
-       if ((fc->fe = dvb_attach(stv0299_attach, &samsung_tbmu24112_config, &fc->i2c_adap)) != NULL) {
+       fc->fe = dvb_attach(stv0299_attach, &samsung_tbmu24112_config, i2c);
+       if (fc->fe != NULL) {
                ops = &fc->fe->ops;
 
                ops->tuner_ops.set_params = samsung_tbmu24112_tuner_set_params;
 
                ops->set_voltage = flexcop_set_voltage;
 
-               fc->fe_sleep             = ops->sleep;
-               ops->sleep               = flexcop_sleep;
+               fc->fe_sleep = ops->sleep;
+               ops->sleep = flexcop_sleep;
+
+               fc->dev_type = FC_SKY;
+               goto fe_found;
+       }
 
-               fc->dev_type          = FC_SKY;
-               info("found the stv0299 at i2c address: 0x%02x",samsung_tbmu24112_config.demod_address);
-       } else
        /* try the air dvb-t (mt352/Samsung tdtc9251dh0(??)) */
-       if ((fc->fe = dvb_attach(mt352_attach, &samsung_tdtc9251dh0_config, &fc->i2c_adap)) != NULL ) {
-               fc->dev_type          = FC_AIR_DVB;
+       fc->fe = dvb_attach(mt352_attach, &samsung_tdtc9251dh0_config, i2c);
+       if (fc->fe != NULL) {
+               fc->dev_type = FC_AIR_DVB;
                fc->fe->ops.tuner_ops.calc_regs = samsung_tdtc9251dh0_calc_regs;
-               info("found the mt352 at i2c address: 0x%02x",samsung_tdtc9251dh0_config.demod_address);
-       } else
+               goto fe_found;
+       }
+
        /* try the air atsc 2nd generation (nxt2002) */
-       if ((fc->fe = dvb_attach(nxt200x_attach, &samsung_tbmv_config, &fc->i2c_adap)) != NULL) {
-               fc->dev_type          = FC_AIR_ATSC2;
+       fc->fe = dvb_attach(nxt200x_attach, &samsung_tbmv_config, i2c);
+       if (fc->fe != NULL) {
+               fc->dev_type = FC_AIR_ATSC2;
                dvb_attach(dvb_pll_attach, fc->fe, 0x61, NULL, DVB_PLL_SAMSUNG_TBMV);
-               info("found the nxt2002 at i2c address: 0x%02x",samsung_tbmv_config.demod_address);
-       } else
-       /* try the air atsc 3nd generation (lgdt3303) */
-       if ((fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, &fc->i2c_adap)) != NULL) {
-               fc->dev_type          = FC_AIR_ATSC3;
-               dvb_attach(dvb_pll_attach, fc->fe, 0x61, &fc->i2c_adap, DVB_PLL_LG_TDVS_H06XF);
-               info("found the lgdt3303 at i2c address: 0x%02x",air2pc_atsc_hd5000_config.demod_address);
-       } else
+               goto fe_found;
+       }
+
+       fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, i2c);
+       if (fc->fe != NULL) {
+               fc->dev_type = FC_AIR_ATSC3;
+               dvb_attach(simple_tuner_attach, fc->fe, i2c, 0x61,
+                               TUNER_LG_TDVS_H06XF);
+               goto fe_found;
+       }
+
        /* try the air atsc 1nd generation (bcm3510)/panasonic ct10s */
-       if ((fc->fe = dvb_attach(bcm3510_attach, &air2pc_atsc_first_gen_config, &fc->i2c_adap)) != NULL) {
-               fc->dev_type          = FC_AIR_ATSC1;
-               info("found the bcm3510 at i2c address: 0x%02x",air2pc_atsc_first_gen_config.demod_address);
-       } else
+       fc->fe = dvb_attach(bcm3510_attach, &air2pc_atsc_first_gen_config, i2c);
+       if (fc->fe != NULL) {
+               fc->dev_type = FC_AIR_ATSC1;
+               goto fe_found;
+       }
+
        /* try the cable dvb (stv0297) */
-       if ((fc->fe = dvb_attach(stv0297_attach, &alps_tdee4_stv0297_config, &fc->i2c_adap)) != NULL) {
-               fc->dev_type                        = FC_CABLE;
+       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;
-               info("found the stv0297 at i2c address: 0x%02x",alps_tdee4_stv0297_config.demod_address);
-       } else
+               goto fe_found;
+       }
+
        /* try the sky v2.3 (vp310/Samsung tbdu18132(tsa5059)) */
-       if ((fc->fe = dvb_attach(vp310_mt312_attach, &skystar23_samsung_tbdu18132_config, &fc->i2c_adap)) != NULL) {
+       fc->fe = dvb_attach(vp310_mt312_attach,
+               &skystar23_samsung_tbdu18132_config, i2c);
+       if (fc->fe != NULL) {
                ops = &fc->fe->ops;
 
                ops->tuner_ops.set_params = skystar23_samsung_tbdu18132_tuner_set_params;
@@ -535,19 +650,21 @@ int flexcop_frontend_init(struct flexcop_device *fc)
                ops->sleep                  = flexcop_sleep;
 
                fc->dev_type                = FC_SKY_OLD;
-               info("found the vp310 (aka mt312) at i2c address: 0x%02x",skystar23_samsung_tbdu18132_config.demod_address);
+               goto fe_found;
        }
 
-       if (fc->fe == NULL) {
-               err("no frontend driver found for this B2C2/FlexCop adapter");
-               return -ENODEV;
-       } else {
-               if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) {
-                       err("frontend registration failed!");
-                       dvb_frontend_detach(fc->fe);
-                       fc->fe = NULL;
-                       return -EINVAL;
-               }
+       err("no frontend driver found for this B2C2/FlexCop adapter");
+       return -ENODEV;
+
+fe_found:
+       info("found '%s' .", fc->fe->ops.info.name);
+       if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) {
+               err("frontend registration failed!");
+               ops = &fc->fe->ops;
+               if (ops->release != NULL)
+                       ops->release(fc->fe);
+               fc->fe = NULL;
+               return -EINVAL;
        }
        fc->init_state |= FC_STATE_FE_INIT;
        return 0;
index 6bf858a436c98048653f1a6a0ef9eb9305709584..55973eaf371180d90534bced637142582e5373bc 100644 (file)
@@ -9,6 +9,8 @@
 
 #define FC_MAX_I2C_RETRIES 100000
 
+/* #define DUMP_I2C_MESSAGES */
+
 static int flexcop_i2c_operation(struct flexcop_device *fc, flexcop_ibi_value *r100)
 {
        int i;
@@ -38,30 +40,25 @@ static int flexcop_i2c_operation(struct flexcop_device *fc, flexcop_ibi_value *r
        return -EREMOTEIO;
 }
 
-static int flexcop_i2c_read4(struct flexcop_device *fc, flexcop_ibi_value r100, u8 *buf)
+static int flexcop_i2c_read4(struct flexcop_i2c_adapter *i2c,
+       flexcop_ibi_value r100, u8 *buf)
 {
        flexcop_ibi_value r104;
        int len = r100.tw_sm_c_100.total_bytes, /* remember total_bytes is buflen-1 */
                ret;
 
-       if ((ret = flexcop_i2c_operation(fc,&r100)) != 0) {
-               /* The Cablestar needs a different kind of i2c-transfer (does not
-                * support "Repeat Start"):
-                * wait for the ACK failure,
-                * and do a subsequent read with the Bit 30 enabled
-                */
-               r100.tw_sm_c_100.no_base_addr_ack_error = 1;
-               if ((ret = flexcop_i2c_operation(fc,&r100)) != 0) {
-                       deb_i2c("no_base_addr read failed. %d\n",ret);
-                       return 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("read failed. %d\n", ret);
+               return ret;
        }
 
        buf[0] = r100.tw_sm_c_100.data1_reg;
 
        if (len > 0) {
-               r104 = fc->read_ibi_reg(fc,tw_sm_c_104);
-               deb_i2c("read: r100: %08x, r104: %08x\n",r100.raw,r104.raw);
+               r104 = i2c->fc->read_ibi_reg(i2c->fc, tw_sm_c_104);
+               deb_i2c("read: r100: %08x, r104: %08x\n", r100.raw, r104.raw);
 
                /* there is at least one more byte, otherwise we wouldn't be here */
                buf[1] = r104.tw_sm_c_104.data2_reg;
@@ -85,17 +82,22 @@ static int flexcop_i2c_write4(struct flexcop_device *fc, flexcop_ibi_value r100,
        r104.tw_sm_c_104.data3_reg = len > 1 ? buf[2] : 0;
        r104.tw_sm_c_104.data4_reg = len > 2 ? buf[3] : 0;
 
-       deb_i2c("write: r100: %08x, r104: %08x\n",r100.raw,r104.raw);
+       deb_i2c("write: r100: %08x, r104: %08x\n", r100.raw, r104.raw);
 
        /* write the additional i2c data before doing the actual i2c operation */
-       fc->write_ibi_reg(fc,tw_sm_c_104,r104);
-       return flexcop_i2c_operation(fc,&r100);
+       fc->write_ibi_reg(fc, tw_sm_c_104, r104);
+       return flexcop_i2c_operation(fc, &r100);
 }
 
-int flexcop_i2c_request(struct flexcop_device *fc, flexcop_access_op_t op,
-               flexcop_i2c_port_t port, u8 chipaddr, u8 addr, u8 *buf, u16 len)
+int flexcop_i2c_request(struct flexcop_i2c_adapter *i2c,
+       flexcop_access_op_t op, u8 chipaddr, u8 addr, u8 *buf, u16 len)
 {
        int ret;
+
+#ifdef DUMP_I2C_MESSAGES
+       int i;
+#endif
+
        u16 bytes_to_transfer;
        flexcop_ibi_value r100;
 
@@ -103,7 +105,25 @@ int flexcop_i2c_request(struct flexcop_device *fc, flexcop_access_op_t op,
        r100.raw = 0;
        r100.tw_sm_c_100.chipaddr = chipaddr;
        r100.tw_sm_c_100.twoWS_rw = op;
-       r100.tw_sm_c_100.twoWS_port_reg = port;
+       r100.tw_sm_c_100.twoWS_port_reg = i2c->port;
+
+#ifdef DUMP_I2C_MESSAGES
+       printk(KERN_DEBUG "%d ", i2c->port);
+       if (op == FC_READ)
+               printk("rd(");
+       else
+               printk("wr(");
+
+       printk("%02x): %02x ", chipaddr, addr);
+#endif
+
+       /* in that case addr is the only value ->
+        * we write it twice as baseaddr and val0
+        * BBTI is doing it like that for ISL6421 at least */
+       if (i2c->no_base_addr && len == 0 && op == FC_WRITE) {
+               buf = &addr;
+               len = 1;
+       }
 
        while (len != 0) {
                bytes_to_transfer = len > 4 ? 4 : len;
@@ -112,9 +132,14 @@ int flexcop_i2c_request(struct flexcop_device *fc, flexcop_access_op_t op,
                r100.tw_sm_c_100.baseaddr = addr;
 
                if (op == FC_READ)
-                       ret = flexcop_i2c_read4(fc, r100, buf);
+                       ret = flexcop_i2c_read4(i2c, r100, buf);
                else
-                       ret = flexcop_i2c_write4(fc,r100, buf);
+                       ret = flexcop_i2c_write4(i2c->fc, r100, buf);
+
+#ifdef DUMP_I2C_MESSAGES
+               for (i = 0; i < bytes_to_transfer; i++)
+                       printk("%02x ", buf[i]);
+#endif
 
                if (ret < 0)
                        return ret;
@@ -122,7 +147,11 @@ int flexcop_i2c_request(struct flexcop_device *fc, flexcop_access_op_t op,
                buf  += bytes_to_transfer;
                addr += bytes_to_transfer;
                len  -= bytes_to_transfer;
-       };
+       }
+
+#ifdef DUMP_I2C_MESSAGES
+       printk("\n");
+#endif
 
        return 0;
 }
@@ -132,7 +161,7 @@ EXPORT_SYMBOL(flexcop_i2c_request);
 /* master xfer callback for demodulator */
 static int flexcop_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num)
 {
-       struct flexcop_device *fc = i2c_get_adapdata(i2c_adap);
+       struct flexcop_i2c_adapter *i2c = i2c_get_adapdata(i2c_adap);
        int i, ret = 0;
 
        /* Some drivers use 1 byte or 0 byte reads as probes, which this
@@ -142,34 +171,29 @@ static int flexcop_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs
        if (num == 1 && msgs[0].flags == I2C_M_RD && msgs[0].len <= 1)
                return 1;
 
-       if (mutex_lock_interruptible(&fc->i2c_mutex))
+       if (mutex_lock_interruptible(&i2c->fc->i2c_mutex))
                return -ERESTARTSYS;
 
-       /* reading */
-       if (num == 2 &&
-               msgs[0].flags == 0 &&
-               msgs[1].flags == I2C_M_RD &&
-               msgs[0].buf != NULL &&
-               msgs[1].buf != NULL) {
-
-               ret = fc->i2c_request(fc, FC_READ, FC_I2C_PORT_DEMOD, msgs[0].addr, msgs[0].buf[0], msgs[1].buf, msgs[1].len);
-
-       } else for (i = 0; i < num; i++) { /* writing command */
-               if (msgs[i].flags != 0 || msgs[i].buf == NULL || msgs[i].len < 2) {
-                       ret = -EINVAL;
+       for (i = 0; i < num; i++) {
+               /* reading */
+               if (i+1 < num && (msgs[i+1].flags == I2C_M_RD)) {
+                       ret = i2c->fc->i2c_request(i2c, FC_READ, msgs[i].addr,
+                               msgs[i].buf[0], msgs[i+1].buf, msgs[i+1].len);
+                       i++; /* skip the following message */
+               } else /* writing */
+                       ret = i2c->fc->i2c_request(i2c, FC_WRITE, msgs[i].addr,
+                               msgs[i].buf[0], &msgs[i].buf[1],
+                               msgs[i].len - 1);
+               if (ret < 0) {
+                       err("i2c master_xfer failed");
                        break;
                }
-
-               ret = fc->i2c_request(fc, FC_WRITE, FC_I2C_PORT_DEMOD, msgs[i].addr, msgs[i].buf[0], &msgs[i].buf[1], msgs[i].len - 1);
        }
 
-       if (ret < 0)
-               err("i2c master_xfer failed");
-       else
-               ret = num;
-
-       mutex_unlock(&fc->i2c_mutex);
+       mutex_unlock(&i2c->fc->i2c_mutex);
 
+       if (ret == 0)
+               ret = num;
        return ret;
 }
 
@@ -189,28 +213,68 @@ int flexcop_i2c_init(struct flexcop_device *fc)
 
        mutex_init(&fc->i2c_mutex);
 
-       memset(&fc->i2c_adap, 0, sizeof(struct i2c_adapter));
-       strncpy(fc->i2c_adap.name, "B2C2 FlexCop device",
-               sizeof(fc->i2c_adap.name));
-
-       i2c_set_adapdata(&fc->i2c_adap,fc);
+       fc->fc_i2c_adap[0].fc = fc;
+       fc->fc_i2c_adap[1].fc = fc;
+       fc->fc_i2c_adap[2].fc = fc;
+
+       fc->fc_i2c_adap[0].port = FC_I2C_PORT_DEMOD;
+       fc->fc_i2c_adap[1].port = FC_I2C_PORT_EEPROM;
+       fc->fc_i2c_adap[2].port = FC_I2C_PORT_TUNER;
+
+       strncpy(fc->fc_i2c_adap[0].i2c_adap.name,
+               "B2C2 FlexCop I2C to demod", I2C_NAME_SIZE);
+       strncpy(fc->fc_i2c_adap[1].i2c_adap.name,
+               "B2C2 FlexCop I2C to eeprom", I2C_NAME_SIZE);
+       strncpy(fc->fc_i2c_adap[2].i2c_adap.name,
+               "B2C2 FlexCop I2C to tuner", I2C_NAME_SIZE);
+
+       i2c_set_adapdata(&fc->fc_i2c_adap[0].i2c_adap, &fc->fc_i2c_adap[0]);
+       i2c_set_adapdata(&fc->fc_i2c_adap[1].i2c_adap, &fc->fc_i2c_adap[1]);
+       i2c_set_adapdata(&fc->fc_i2c_adap[2].i2c_adap, &fc->fc_i2c_adap[2]);
+
+       fc->fc_i2c_adap[0].i2c_adap.class =
+               fc->fc_i2c_adap[1].i2c_adap.class =
+               fc->fc_i2c_adap[2].i2c_adap.class = I2C_CLASS_TV_DIGITAL;
+       fc->fc_i2c_adap[0].i2c_adap.algo =
+               fc->fc_i2c_adap[1].i2c_adap.algo =
+               fc->fc_i2c_adap[2].i2c_adap.algo = &flexcop_algo;
+       fc->fc_i2c_adap[0].i2c_adap.algo_data =
+               fc->fc_i2c_adap[1].i2c_adap.algo_data =
+               fc->fc_i2c_adap[2].i2c_adap.algo_data = NULL;
+       fc->fc_i2c_adap[0].i2c_adap.dev.parent =
+               fc->fc_i2c_adap[1].i2c_adap.dev.parent =
+               fc->fc_i2c_adap[2].i2c_adap.dev.parent = fc->dev;
+
+       ret = i2c_add_adapter(&fc->fc_i2c_adap[0].i2c_adap);
+       if (ret < 0)
+               return ret;
 
-       fc->i2c_adap.class          = I2C_CLASS_TV_DIGITAL;
-       fc->i2c_adap.algo       = &flexcop_algo;
-       fc->i2c_adap.algo_data  = NULL;
-       fc->i2c_adap.dev.parent = fc->dev;
+       ret = i2c_add_adapter(&fc->fc_i2c_adap[1].i2c_adap);
+       if (ret < 0)
+               goto adap_1_failed;
 
-       if ((ret = i2c_add_adapter(&fc->i2c_adap)) < 0)
-               return ret;
+       ret = i2c_add_adapter(&fc->fc_i2c_adap[2].i2c_adap);
+       if (ret < 0)
+               goto adap_2_failed;
 
        fc->init_state |= FC_STATE_I2C_INIT;
        return 0;
+
+adap_2_failed:
+       i2c_del_adapter(&fc->fc_i2c_adap[1].i2c_adap);
+adap_1_failed:
+       i2c_del_adapter(&fc->fc_i2c_adap[0].i2c_adap);
+
+       return ret;
 }
 
 void flexcop_i2c_exit(struct flexcop_device *fc)
 {
-       if (fc->init_state & FC_STATE_I2C_INIT)
-               i2c_del_adapter(&fc->i2c_adap);
+       if (fc->init_state & FC_STATE_I2C_INIT) {
+               i2c_del_adapter(&fc->fc_i2c_adap[2].i2c_adap);
+               i2c_del_adapter(&fc->fc_i2c_adap[1].i2c_adap);
+               i2c_del_adapter(&fc->fc_i2c_adap[0].i2c_adap);
+       }
 
        fc->init_state &= ~FC_STATE_I2C_INIT;
 }
index 167583bf0621879b1f9deefd1c443646ccbd4771..93d20e56f909e17c243c8348e81e01047937e213 100644 (file)
@@ -52,6 +52,8 @@ static const char *flexcop_device_names[] = {
        "Sky2PC/SkyStar 2 DVB-S (old version)",
        "Cable2PC/CableStar 2 DVB-C",
        "Air2PC/AirStar 2 ATSC 3rd generation (HD5000)",
+       "Sky2PC/SkyStar 2 DVB-S rev 2.7a/u",
+       "Sky2PC/SkyStar 2 DVB-S rev 2.8",
 };
 
 static const char *flexcop_bus_names[] = {
index 01af4d237eb13b585ba6f8136494c07a3a17f27c..5b30dfc7846b2fbbe870efb38901e311c3bc2375 100644 (file)
@@ -32,7 +32,7 @@ MODULE_PARM_DESC(irq_chk_intv, "set the interval for IRQ watchdog (currently jus
 #define deb_irq(args...)   dprintk(0x08,args)
 #define deb_chk(args...)   dprintk(0x10,args)
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "set debug level (1=info,2=regs,4=TS,8=irqdma (|-able))." DEBSTATUS);
 
index 491f9bd6e1951be8d23463667da4fb5c72972b81..7599fccc1a5b80a438e9cbfd2c8d387c9b526f6c 100644 (file)
@@ -25,6 +25,8 @@ typedef enum {
        FC_SKY_OLD,
        FC_CABLE,
        FC_AIR_ATSC3,
+       FC_SKY_REV27,
+       FC_SKY_REV28,
 } flexcop_device_type_t;
 
 typedef enum {
index 01570ec80962ea7628596cb9fef36d615807b3e3..cda69528548ac9d0d9757f47786cbf732491a37f 100644 (file)
@@ -90,7 +90,7 @@ static void flexcop_sram_write(struct adapter *adapter, u32 bank, u32 addr, u8 *
                };
 
                if (retries == 0)
-                       printk("%s: SRAM timeout\n", __FUNCTION__);
+                       printk("%s: SRAM timeout\n", __func__);
 
                write_reg_dw(adapter, 0x700, command);
 
@@ -115,7 +115,7 @@ static void flex_sram_read(struct adapter *adapter, u32 bank, u32 addr, u8 *buf,
                };
 
                if (retries == 0)
-                       printk("%s: SRAM timeout\n", __FUNCTION__);
+                       printk("%s: SRAM timeout\n", __func__);
 
                write_reg_dw(adapter, 0x700, command);
 
@@ -127,7 +127,7 @@ static void flex_sram_read(struct adapter *adapter, u32 bank, u32 addr, u8 *buf,
                };
 
                if (retries == 0)
-                       printk("%s: SRAM timeout\n", __FUNCTION__);
+                       printk("%s: SRAM timeout\n", __func__);
 
                value = read_reg_dw(adapter, 0x700) >> 0x10;
 
@@ -240,13 +240,13 @@ static void sram_init(struct adapter *adapter)
 
                adapter->dw_sram_type = tmp & 0x30000;
 
-               ddprintk("%s: dw_sram_type = %x\n", __FUNCTION__, adapter->dw_sram_type);
+               ddprintk("%s: dw_sram_type = %x\n", __func__, adapter->dw_sram_type);
 
        } else {
 
                adapter->dw_sram_type = 0x10000;
 
-               ddprintk("%s: dw_sram_type = %x\n", __FUNCTION__, adapter->dw_sram_type);
+               ddprintk("%s: dw_sram_type = %x\n", __func__, adapter->dw_sram_type);
        }
 
        /* return value is never used? */
@@ -257,7 +257,7 @@ static int sram_test_location(struct adapter *adapter, u32 mask, u32 addr)
 {
        u8 tmp1, tmp2;
 
-       dprintk("%s: mask = %x, addr = %x\n", __FUNCTION__, mask, addr);
+       dprintk("%s: mask = %x, addr = %x\n", __func__, mask, addr);
 
        sram_set_size(adapter, mask);
        sram_init(adapter);
@@ -275,7 +275,7 @@ static int sram_test_location(struct adapter *adapter, u32 mask, u32 addr)
        sram_read(adapter, addr, &tmp2, 1);
        sram_read(adapter, addr, &tmp2, 1);
 
-       dprintk("%s: wrote 0xa5, read 0x%2x\n", __FUNCTION__, tmp2);
+       dprintk("%s: wrote 0xa5, read 0x%2x\n", __func__, tmp2);
 
        if (tmp2 != 0xa5)
                return 0;
@@ -293,7 +293,7 @@ static int sram_test_location(struct adapter *adapter, u32 mask, u32 addr)
        sram_read(adapter, addr, &tmp2, 1);
        sram_read(adapter, addr, &tmp2, 1);
 
-       dprintk("%s: wrote 0x5a, read 0x%2x\n", __FUNCTION__, tmp2);
+       dprintk("%s: wrote 0x5a, read 0x%2x\n", __func__, tmp2);
 
        if (tmp2 != 0x5a)
                return 0;
@@ -340,7 +340,7 @@ static int flexcop_sram_detect(struct flexcop_device *fc)
 
        tmp3 = read_reg_dw(adapter, 0x71c);
 
-       dprintk("%s: tmp3 = %x\n", __FUNCTION__, tmp3);
+       dprintk("%s: tmp3 = %x\n", __func__, tmp3);
 
        write_reg_dw(adapter, 0x71c, tmp2);
 
@@ -351,7 +351,7 @@ static int flexcop_sram_detect(struct flexcop_device *fc)
                sram_init(adapter);
                write_reg_dw(adapter, 0x208, tmp);
 
-               dprintk("%s: sram size = 32K\n", __FUNCTION__);
+               dprintk("%s: sram size = 32K\n", __func__);
 
                return 32;
        }
@@ -361,7 +361,7 @@ static int flexcop_sram_detect(struct flexcop_device *fc)
                sram_init(adapter);
                write_reg_dw(adapter, 0x208, tmp);
 
-               dprintk("%s: sram size = 128K\n", __FUNCTION__);
+               dprintk("%s: sram size = 128K\n", __func__);
 
                return 128;
        }
@@ -371,7 +371,7 @@ static int flexcop_sram_detect(struct flexcop_device *fc)
                sram_init(adapter);
                write_reg_dw(adapter, 0x208, tmp);
 
-               dprintk("%s: sram size = 64K\n", __FUNCTION__);
+               dprintk("%s: sram size = 64K\n", __func__);
 
                return 64;
        }
@@ -381,7 +381,7 @@ static int flexcop_sram_detect(struct flexcop_device *fc)
                sram_init(adapter);
                write_reg_dw(adapter, 0x208, tmp);
 
-               dprintk("%s: sram size = 32K\n", __FUNCTION__);
+               dprintk("%s: sram size = 32K\n", __func__);
 
                return 32;
        }
@@ -390,7 +390,7 @@ static int flexcop_sram_detect(struct flexcop_device *fc)
        sram_init(adapter);
        write_reg_dw(adapter, 0x208, tmp);
 
-       dprintk("%s: SRAM detection failed. Set to 32K \n", __FUNCTION__);
+       dprintk("%s: SRAM detection failed. Set to 32K \n", __func__);
 
        return 0;
 }
index 87fb75f0d1cf0b88eb6e16706d8dfe3ffc3b7ebc..449fb5c3d0b1ed31f078ff9b8eb2c244ae4c10bf 100644 (file)
@@ -211,10 +211,11 @@ static int flexcop_usb_utility_req(struct flexcop_usb *fc_usb, int set,
 #endif
 
 /* usb i2c stuff */
-static int flexcop_usb_i2c_req(struct flexcop_usb *fc_usb,
+static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c,
                flexcop_usb_request_t req, flexcop_usb_i2c_function_t func,
-               flexcop_i2c_port_t port, u8 chipaddr, u8 addr, u8 *buf, u8 buflen)
+               u8 chipaddr, u8 addr, u8 *buf, u8 buflen)
 {
+       struct flexcop_usb *fc_usb = i2c->fc->bus_specific;
        u16 wValue, wIndex;
        int nWaitTime,pipe,len;
 //     u8 dwRequestType;
@@ -242,7 +243,7 @@ static int flexcop_usb_i2c_req(struct flexcop_usb *fc_usb,
                        deb_info("unsupported function for i2c_req %x\n",func);
                        return -EINVAL;
        }
-       wValue = (func << 8 ) | (port << 4);
+       wValue = (func << 8) | (i2c->port << 4);
        wIndex = (chipaddr << 8 ) | addr;
 
        deb_i2c("i2c %2d: %02x %02x %02x %02x %02x %02x\n",func,request_type,req,
@@ -274,13 +275,15 @@ static int flexcop_usb_write_ibi_reg(struct flexcop_device *fc, flexcop_ibi_regi
        return flexcop_usb_readwrite_dw(fc,reg, &val.raw, 0);
 }
 
-static int flexcop_usb_i2c_request(struct flexcop_device *fc, flexcop_access_op_t op,
-               flexcop_i2c_port_t port, u8 chipaddr, u8 addr, u8 *buf, u16 len)
+static int flexcop_usb_i2c_request(struct flexcop_i2c_adapter *i2c,
+       flexcop_access_op_t op, u8 chipaddr, u8 addr, u8 *buf, u16 len)
 {
        if (op == FC_READ)
-               return flexcop_usb_i2c_req(fc->bus_specific,B2C2_USB_I2C_REQUEST,USB_FUNC_I2C_READ,port,chipaddr,addr,buf,len);
+               return flexcop_usb_i2c_req(i2c, B2C2_USB_I2C_REQUEST,
+                       USB_FUNC_I2C_READ, chipaddr, addr, buf, len);
        else
-               return flexcop_usb_i2c_req(fc->bus_specific,B2C2_USB_I2C_REQUEST,USB_FUNC_I2C_WRITE,port,chipaddr,addr,buf,len);
+               return flexcop_usb_i2c_req(i2c, B2C2_USB_I2C_REQUEST,
+                       USB_FUNC_I2C_WRITE, chipaddr, addr, buf, len);
 }
 
 static void flexcop_usb_process_frame(struct flexcop_usb *fc_usb, u8 *buffer, int buffer_length)
index 2ddafd071c9776ddf02946f6ce018f86504e1fa0..5f79c8dc383651aa9349e3445f854d24947aab9a 100644 (file)
@@ -49,6 +49,8 @@ module_param_named(debug, b2c2_flexcop_debug,  int, 0644);
 MODULE_PARM_DESC(debug, "set debug level (1=info,2=tuner,4=i2c,8=ts,16=sram,32=reg (|-able))." DEBSTATUS);
 #undef DEBSTATUS
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 /* global zero for ibi values */
 flexcop_ibi_value ibi_zero;
 
@@ -66,8 +68,10 @@ static int flexcop_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
 
 static int flexcop_dvb_init(struct flexcop_device *fc)
 {
-       int ret;
-       if ((ret = dvb_register_adapter(&fc->dvb_adapter,"FlexCop Digital TV device",fc->owner,fc->dev)) < 0) {
+       int ret = dvb_register_adapter(&fc->dvb_adapter,
+                                      "FlexCop Digital TV device", fc->owner,
+                                      fc->dev, adapter_nr);
+       if (ret < 0) {
                err("error registering DVB adapter");
                return ret;
        }
@@ -257,6 +261,12 @@ int flexcop_device_initialize(struct flexcop_device *fc)
        if ((ret = flexcop_dvb_init(fc)))
                goto error;
 
+       /* i2c has to be done before doing EEProm stuff -
+        * because the EEProm is accessed via i2c */
+       ret = flexcop_i2c_init(fc);
+       if (ret)
+               goto error;
+
        /* do the MAC address reading after initializing the dvb_adapter */
        if (fc->get_mac_addr(fc, 0) == 0) {
                u8 *b = fc->dvb_adapter.proposed_mac;
@@ -266,10 +276,6 @@ int flexcop_device_initialize(struct flexcop_device *fc)
        } else
                warn("reading of MAC address failed.\n");
 
-
-       if ((ret = flexcop_i2c_init(fc)))
-               goto error;
-
        if ((ret = flexcop_frontend_init(fc)))
                goto error;
 
index ea666174e98874a8d9bb5a3de78aac660e03bf4f..902c762e0b7fb8867bc1d62ea65f2e2a4ee5e9a3 100644 (file)
@@ -7,8 +7,8 @@ config DVB_BT8XX
        select DVB_CX24110 if !DVB_FE_CUSTOMISE
        select DVB_OR51211 if !DVB_FE_CUSTOMISE
        select DVB_LGDT330X if !DVB_FE_CUSTOMISE
-       select DVB_PLL if !DVB_FE_CUSTOMISE
        select DVB_ZL10353 if !DVB_FE_CUSTOMISE
+       select TUNER_SIMPLE if !DVB_FE_CUSTOMISE
        select FW_LOADER
        help
          Support for PCI cards based on the Bt8xx PCI bridge. Examples are
index 84cf70504d17855ff8821aa0d6e6700c5ecded76..9d3e68b5d6ebc22e9b8fb4adfdbf42aa50784d20 100644 (file)
@@ -1,3 +1,6 @@
 obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o dst.o dst_ca.o
 
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/video/bt8xx -Idrivers/media/dvb/frontends
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
+EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+EXTRA_CFLAGS += -Idrivers/media/video/bt8xx
+EXTRA_CFLAGS += -Idrivers/media/video
index 307ff35bdf13a6226e6413c104ae7279d176f50d..75711bde23ad3675fe82f89bf6f4edf68d7db644 100644 (file)
@@ -1290,7 +1290,7 @@ static int dst_get_signal(struct dst_state *state)
 {
        int retval;
        u8 get_signal[] = { 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb };
-       //dprintk("%s: Getting Signal strength and other parameters\n", __FUNCTION__);
+       //dprintk("%s: Getting Signal strength and other parameters\n", __func__);
        if ((state->diseq_flags & ATTEMPT_TUNE) == 0) {
                state->decode_lock = state->decode_strength = state->decode_snr = 0;
                return 0;
index 50bc32a8bd5533921a9af2923cf618728a18db8b..0258451423ad876b53e3e2a9b94044cf1b7025c9 100644 (file)
 #define dprintk(x, y, z, format, arg...) do {                                          \
        if (z) {                                                                        \
                if      ((x > DST_CA_ERROR) && (x > y))                                 \
-                       printk(KERN_ERR "%s: " format "\n", __FUNCTION__ , ##arg);      \
+                       printk(KERN_ERR "%s: " format "\n", __func__ , ##arg);  \
                else if ((x > DST_CA_NOTICE) && (x > y))                                \
-                       printk(KERN_NOTICE "%s: " format "\n", __FUNCTION__ , ##arg);   \
+                       printk(KERN_NOTICE "%s: " format "\n", __func__ , ##arg);       \
                else if ((x > DST_CA_INFO) && (x > y))                                  \
-                       printk(KERN_INFO "%s: " format "\n", __FUNCTION__ , ##arg);     \
+                       printk(KERN_INFO "%s: " format "\n", __func__ , ##arg); \
                else if ((x > DST_CA_DEBUG) && (x > y))                                 \
-                       printk(KERN_DEBUG "%s: " format "\n", __FUNCTION__ , ##arg);    \
+                       printk(KERN_DEBUG "%s: " format "\n", __func__ , ##arg);        \
        } else {                                                                        \
                if (x > y)                                                              \
                        printk(format, ## arg);                                         \
@@ -162,7 +162,7 @@ static int ca_get_app_info(struct dst_state *state)
        dprintk(verbose, DST_CA_INFO, 1, " ================================ CI Module Application Info ======================================");
        dprintk(verbose, DST_CA_INFO, 1, " Application Type=[%d], Application Vendor=[%d], Vendor Code=[%d]\n%s: Application info=[%s]",
                state->messages[7], (state->messages[8] << 8) | state->messages[9],
-               (state->messages[10] << 8) | state->messages[11], __FUNCTION__, (char *)(&state->messages[12]));
+               (state->messages[10] << 8) | state->messages[11], __func__, (char *)(&state->messages[12]));
        dprintk(verbose, DST_CA_INFO, 1, " ==================================================================================================");
 
        // Transform dst message to correct application_info message
index dedd30a8356bbaad2f78ef936a8352413f4acf41..6afbfbbef0ce304885826365df8a40735c9a5ee7 100644 (file)
@@ -40,10 +40,12 @@ static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 #define dprintk( args... ) \
-       do \
+       do \
                if (debug) printk(KERN_DEBUG args); \
-       while (0)
+       while (0)
 
 #define IF_FREQUENCYx6 217    /* 6 * 36.16666666667MHz */
 
@@ -609,8 +611,9 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
                lgdt330x_reset(card);
                card->fe = dvb_attach(lgdt330x_attach, &tdvs_tua6034_config, card->i2c_adapter);
                if (card->fe != NULL) {
-                       dvb_attach(dvb_pll_attach, card->fe, 0x61,
-                                  card->i2c_adapter, DVB_PLL_LG_TDVS_H06XF);
+                       dvb_attach(simple_tuner_attach, card->fe,
+                                  card->i2c_adapter, 0x61,
+                                  TUNER_LG_TDVS_H06XF);
                        dprintk ("dvb_bt8xx: lgdt330x detected\n");
                }
                break;
@@ -670,7 +673,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
                state->dst_ca = NULL;
                /*      DST is not a frontend, attaching the ASIC       */
                if (dvb_attach(dst_attach, state, &card->dvb_adapter) == NULL) {
-                       printk("%s: Could not find a Twinhan DST.\n", __FUNCTION__);
+                       printk("%s: Could not find a Twinhan DST.\n", __func__);
                        break;
                }
                /*      Attach other DST peripherals if any             */
@@ -692,8 +695,9 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
        case BTTV_BOARD_PC_HDTV:
                card->fe = dvb_attach(or51211_attach, &or51211_config, card->i2c_adapter);
                if (card->fe != NULL)
-                       dvb_attach(dvb_pll_attach, card->fe, 0x61,
-                                  card->i2c_adapter, DVB_PLL_FCV1236D);
+                       dvb_attach(simple_tuner_attach, card->fe,
+                                  card->i2c_adapter, 0x61,
+                                  TUNER_PHILIPS_FCV1236D);
                break;
        }
 
@@ -715,7 +719,10 @@ static int __devinit dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type)
 {
        int result;
 
-       if ((result = dvb_register_adapter(&card->dvb_adapter, card->card_name, THIS_MODULE, &card->bt->dev->dev)) < 0) {
+       result = dvb_register_adapter(&card->dvb_adapter, card->card_name,
+                                     THIS_MODULE, &card->bt->dev->dev,
+                                     adapter_nr);
+       if (result < 0) {
                printk("dvb_bt8xx: dvb_register_adapter failed (errno = %d)\n", result);
                return result;
        }
index 436880e68672fe752859135dbff42790fefd93f3..4499ed2ac0ed7339384663dc1b2a5f8f77d82224 100644 (file)
@@ -38,7 +38,7 @@
 #include "or51211.h"
 #include "lgdt330x.h"
 #include "zl10353.h"
-#include "dvb-pll.h"
+#include "tuner-simple.h"
 
 struct dvb_bt8xx_card {
        struct mutex lock;
index db08b0a8888afc5763e935a53e712844f8a217aa..f5010e8671b8476109b44df80e90a47079305302 100644 (file)
@@ -58,11 +58,13 @@ static int debug;
 module_param_named(debug, debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 #define dprintk(level, args...)                                                \
 do {                                                                   \
        if ((debug & level)) {                                          \
                printk("%s: %s(): ", KBUILD_MODNAME,                    \
-                      __FUNCTION__);                                   \
+                      __func__);                                       \
                printk(args); }                                         \
 } while (0)
 
@@ -938,7 +940,10 @@ static int cinergyt2_probe (struct usb_interface *intf,
                return -ENOMEM;
        }
 
-       if ((err = dvb_register_adapter(&cinergyt2->adapter, DRIVER_NAME, THIS_MODULE, &cinergyt2->udev->dev)) < 0) {
+       err = dvb_register_adapter(&cinergyt2->adapter, DRIVER_NAME,
+                                  THIS_MODULE, &cinergyt2->udev->dev,
+                                  adapter_nr);
+       if (err < 0) {
                kfree(cinergyt2);
                return err;
        }
index 0c1d87c5227ab0bf3e903d95e3cc92ce982b6d98..b0d347daae47a889ba54f89b938ecd8dd3ee46a5 100644 (file)
@@ -80,6 +80,8 @@ enum dmx_success {
 #define        TS_PAYLOAD_ONLY 2   /* in case TS_PACKET is set, only send the TS
                               payload (<=184 bytes per packet) to callback */
 #define TS_DECODER      4   /* send stream to built-in decoder (if present) */
+#define TS_DEMUX        8   /* in case TS_PACKET is set, send the TS to
+                              the demux device, not to the dvr device */
 
 /* PES type for filters which write to built-in decoder */
 /* these should be kept identical to the types in dmx.h */
index f94bc31e3b3334d020b7e5dc95759f25a3e70ca8..df5bef6a2517821c013c1aedbcae843ff7b278fa 100644 (file)
@@ -126,7 +126,7 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
        struct dmxdev *dmxdev = dvbdev->priv;
        struct dmx_frontend *front;
 
-       dprintk("function : %s\n", __FUNCTION__);
+       dprintk("function : %s\n", __func__);
 
        if (mutex_lock_interruptible(&dmxdev->mutex))
                return -ERESTARTSYS;
@@ -259,6 +259,39 @@ static ssize_t dvb_dvr_read(struct file *file, char __user *buf, size_t count,
        return ret;
 }
 
+static int dvb_dvr_set_buffer_size(struct dmxdev *dmxdev,
+                                     unsigned long size)
+{
+       struct dvb_ringbuffer *buf = &dmxdev->dvr_buffer;
+       void *newmem;
+       void *oldmem;
+
+       dprintk("function : %s\n", __func__);
+
+       if (buf->size == size)
+               return 0;
+       if (!size)
+               return -EINVAL;
+
+       newmem = vmalloc(size);
+       if (!newmem)
+               return -ENOMEM;
+
+       oldmem = buf->data;
+
+       spin_lock_irq(&dmxdev->lock);
+       buf->data = newmem;
+       buf->size = size;
+
+       /* reset and not flush in case the buffer shrinks */
+       dvb_ringbuffer_reset(buf);
+       spin_unlock_irq(&dmxdev->lock);
+
+       vfree(oldmem);
+
+       return 0;
+}
+
 static inline void dvb_dmxdev_filter_state_set(struct dmxdev_filter
                                               *dmxdevfilter, int state)
 {
@@ -271,28 +304,32 @@ static int dvb_dmxdev_set_buffer_size(struct dmxdev_filter *dmxdevfilter,
                                      unsigned long size)
 {
        struct dvb_ringbuffer *buf = &dmxdevfilter->buffer;
-       void *mem;
+       void *newmem;
+       void *oldmem;
 
        if (buf->size == size)
                return 0;
+       if (!size)
+               return -EINVAL;
        if (dmxdevfilter->state >= DMXDEV_STATE_GO)
                return -EBUSY;
+
+       newmem = vmalloc(size);
+       if (!newmem)
+               return -ENOMEM;
+
+       oldmem = buf->data;
+
        spin_lock_irq(&dmxdevfilter->dev->lock);
-       mem = buf->data;
-       buf->data = NULL;
+       buf->data = newmem;
        buf->size = size;
-       dvb_ringbuffer_flush(buf);
+
+       /* reset and not flush in case the buffer shrinks */
+       dvb_ringbuffer_reset(buf);
        spin_unlock_irq(&dmxdevfilter->dev->lock);
-       vfree(mem);
 
-       if (buf->size) {
-               mem = vmalloc(dmxdevfilter->buffer.size);
-               if (!mem)
-                       return -ENOMEM;
-               spin_lock_irq(&dmxdevfilter->dev->lock);
-               buf->data = mem;
-               spin_unlock_irq(&dmxdevfilter->dev->lock);
-       }
+       vfree(oldmem);
+
        return 0;
 }
 
@@ -374,7 +411,8 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
                return 0;
        }
 
-       if (dmxdevfilter->params.pes.output == DMX_OUT_TAP)
+       if (dmxdevfilter->params.pes.output == DMX_OUT_TAP
+           || dmxdevfilter->params.pes.output == DMX_OUT_TSDEMUX_TAP)
                buffer = &dmxdevfilter->buffer;
        else
                buffer = &dmxdevfilter->dev->dvr_buffer;
@@ -550,7 +588,7 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
                                                                   dvb_dmxdev_section_callback);
                        if (ret < 0) {
                                printk("DVB (%s): could not alloc feed\n",
-                                      __FUNCTION__);
+                                      __func__);
                                return ret;
                        }
 
@@ -558,7 +596,7 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
                                              (para->flags & DMX_CHECK_CRC) ? 1 : 0);
                        if (ret < 0) {
                                printk("DVB (%s): could not set feed\n",
-                                      __FUNCTION__);
+                                      __func__);
                                dvb_dmxdev_feed_restart(filter);
                                return ret;
                        }
@@ -620,9 +658,10 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
 
                if (otype == DMX_OUT_TS_TAP)
                        ts_type |= TS_PACKET;
-
-               if (otype == DMX_OUT_TAP)
-                       ts_type |= TS_PAYLOAD_ONLY | TS_PACKET;
+               else if (otype == DMX_OUT_TSDEMUX_TAP)
+                       ts_type |= TS_PACKET | TS_DEMUX;
+               else if (otype == DMX_OUT_TAP)
+                       ts_type |= TS_PACKET | TS_DEMUX | TS_PAYLOAD_ONLY;
 
                ret = dmxdev->demux->allocate_ts_feed(dmxdev->demux,
                                                      tsfeed,
@@ -732,7 +771,7 @@ static int dvb_dmxdev_filter_set(struct dmxdev *dmxdev,
                                 struct dmxdev_filter *dmxdevfilter,
                                 struct dmx_sct_filter_params *params)
 {
-       dprintk("function : %s\n", __FUNCTION__);
+       dprintk("function : %s\n", __func__);
 
        dvb_dmxdev_filter_stop(dmxdevfilter);
 
@@ -1007,6 +1046,7 @@ static int dvb_dvr_do_ioctl(struct inode *inode, struct file *file,
 {
        struct dvb_device *dvbdev = file->private_data;
        struct dmxdev *dmxdev = dvbdev->priv;
+       unsigned long arg = (unsigned long)parg;
        int ret;
 
        if (mutex_lock_interruptible(&dmxdev->mutex))
@@ -1014,8 +1054,7 @@ static int dvb_dvr_do_ioctl(struct inode *inode, struct file *file,
 
        switch (cmd) {
        case DMX_SET_BUFFER_SIZE:
-               // FIXME: implement
-               ret = 0;
+               ret = dvb_dvr_set_buffer_size(dmxdev, arg);
                break;
 
        default:
@@ -1038,7 +1077,7 @@ static unsigned int dvb_dvr_poll(struct file *file, poll_table *wait)
        struct dmxdev *dmxdev = dvbdev->priv;
        unsigned int mask = 0;
 
-       dprintk("function : %s\n", __FUNCTION__);
+       dprintk("function : %s\n", __func__);
 
        poll_wait(file, &dmxdev->dvr_buffer.queue, wait);
 
index 89437fdab8befcd393578c57f8c44d9434787612..8cbdb0ec67e2e4d2cc8f8119a7bfeaddd0c8f9ab 100644 (file)
@@ -250,7 +250,7 @@ static int dvb_ca_en50221_wait_if_status(struct dvb_ca_private *ca, int slot,
        unsigned long timeout;
        unsigned long start;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        /* loop until timeout elapsed */
        start = jiffies;
@@ -263,7 +263,7 @@ static int dvb_ca_en50221_wait_if_status(struct dvb_ca_private *ca, int slot,
 
                /* if we got the flags, it was successful! */
                if (res & waitfor) {
-                       dprintk("%s succeeded timeout:%lu\n", __FUNCTION__, jiffies - start);
+                       dprintk("%s succeeded timeout:%lu\n", __func__, jiffies - start);
                        return 0;
                }
 
@@ -276,7 +276,7 @@ static int dvb_ca_en50221_wait_if_status(struct dvb_ca_private *ca, int slot,
                msleep(1);
        }
 
-       dprintk("%s failed timeout:%lu\n", __FUNCTION__, jiffies - start);
+       dprintk("%s failed timeout:%lu\n", __func__, jiffies - start);
 
        /* if we get here, we've timed out */
        return -ETIMEDOUT;
@@ -297,7 +297,7 @@ static int dvb_ca_en50221_link_init(struct dvb_ca_private *ca, int slot)
        int buf_size;
        u8 buf[2];
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        /* we'll be determining these during this function */
        ca->slot_info[slot].da_irq_supported = 0;
@@ -549,7 +549,7 @@ static int dvb_ca_en50221_set_configoption(struct dvb_ca_private *ca, int slot)
 {
        int configoption;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        /* set the config option */
        ca->pub->write_attribute_mem(ca->pub, slot,
@@ -587,7 +587,7 @@ static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot, u8 * eb
        u8 buf[HOST_LINK_BUF_SIZE];
        int i;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        /* check if we have space for a link buf in the rx_buffer */
        if (ebuf == NULL) {
@@ -708,7 +708,7 @@ static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot, u8 * b
        int status;
        int i;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
 
        // sanity check
@@ -785,7 +785,7 @@ EXPORT_SYMBOL(dvb_ca_en50221_camchange_irq);
  */
 static int dvb_ca_en50221_slot_shutdown(struct dvb_ca_private *ca, int slot)
 {
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        ca->pub->slot_shutdown(ca->pub, slot);
        ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE;
@@ -892,7 +892,7 @@ void dvb_ca_en50221_frda_irq(struct dvb_ca_en50221 *pubca, int slot)
 static void dvb_ca_en50221_thread_wakeup(struct dvb_ca_private *ca)
 {
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        ca->wakeup = 1;
        mb();
@@ -964,7 +964,7 @@ static int dvb_ca_en50221_thread(void *data)
        int pktcount;
        void *rxbuf;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        /* choose the correct initial delay */
        dvb_ca_en50221_thread_update_delay(ca);
@@ -1172,7 +1172,7 @@ static int dvb_ca_en50221_io_do_ioctl(struct inode *inode, struct file *file,
        int err = 0;
        int slot;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        switch (cmd) {
        case CA_RESET:
@@ -1266,7 +1266,7 @@ static ssize_t dvb_ca_en50221_io_write(struct file *file,
        unsigned long timeout;
        int written;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        /* Incoming packet has a 2 byte header. hdr[0] = slot_id, hdr[1] = connection_id */
        if (count < 2)
@@ -1401,7 +1401,7 @@ static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user * buf,
        int pktlen;
        int dispose = 0;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        /* Outgoing packet has a 2 byte header. hdr[0] = slot_id, hdr[1] = connection_id */
        if (count < 2)
@@ -1490,7 +1490,7 @@ static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file)
        int err;
        int i;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        if (!try_module_get(ca->pub->owner))
                return -EIO;
@@ -1534,7 +1534,7 @@ static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file)
        struct dvb_ca_private *ca = dvbdev->priv;
        int err;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        /* mark the CA device as closed */
        ca->open = 0;
@@ -1564,7 +1564,7 @@ static unsigned int dvb_ca_en50221_io_poll(struct file *file, poll_table * wait)
        int slot;
        int result = 0;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        if (dvb_ca_en50221_io_read_condition(ca, &result, &slot) == 1) {
                mask |= POLLIN;
@@ -1626,7 +1626,7 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter,
        struct dvb_ca_private *ca = NULL;
        int i;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        if (slot_count < 1)
                return -EINVAL;
@@ -1704,7 +1704,7 @@ void dvb_ca_en50221_release(struct dvb_ca_en50221 *pubca)
        struct dvb_ca_private *ca = pubca->private;
        int i;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        /* shutdown the thread if there was one */
        kthread_stop(ca->thread);
index 7959020f9317d2ee5f1f0824370ab730542f09c3..934e15fffc565f4660dfc5954a49d1346748d315 100644 (file)
@@ -368,7 +368,7 @@ static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed,
 #define DVR_FEED(f)                                                    \
        (((f)->type == DMX_TYPE_TS) &&                                  \
        ((f)->feed.ts.is_filtering) &&                                  \
-       (((f)->ts_type & (TS_PACKET|TS_PAYLOAD_ONLY)) == TS_PACKET))
+       (((f)->ts_type & (TS_PACKET | TS_DEMUX)) == TS_PACKET))
 
 static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
 {
@@ -553,7 +553,7 @@ static void dvb_demux_feed_add(struct dvb_demux_feed *feed)
        spin_lock_irq(&feed->demux->lock);
        if (dvb_demux_feed_find(feed)) {
                printk(KERN_ERR "%s: feed already in list (type=%x state=%x pid=%x)\n",
-                      __FUNCTION__, feed->type, feed->state, feed->pid);
+                      __func__, feed->type, feed->state, feed->pid);
                goto out;
        }
 
@@ -567,7 +567,7 @@ static void dvb_demux_feed_del(struct dvb_demux_feed *feed)
        spin_lock_irq(&feed->demux->lock);
        if (!(dvb_demux_feed_find(feed))) {
                printk(KERN_ERR "%s: feed not in list (type=%x state=%x pid=%x)\n",
-                      __FUNCTION__, feed->type, feed->state, feed->pid);
+                      __func__, feed->type, feed->state, feed->pid);
                goto out;
        }
 
index 925cfa6221ad09d73e2831a6cadb2435a3747290..2dddd08c5445383cfe1b94352c94bda403147130 100644 (file)
@@ -135,7 +135,7 @@ static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status)
        struct dvb_frontend_event *e;
        int wp;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        if (mutex_lock_interruptible (&events->mtx))
                return;
@@ -171,7 +171,7 @@ static int dvb_frontend_get_event(struct dvb_frontend *fe,
        struct dvb_frontend_private *fepriv = fe->frontend_priv;
        struct dvb_fe_events *events = &fepriv->events;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        if (events->overflow) {
                events->overflow = 0;
@@ -237,7 +237,7 @@ static void dvb_frontend_swzigzag_update_delay(struct dvb_frontend_private *fepr
 {
        int q2;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        if (locked)
                (fepriv->quality) = (fepriv->quality * 220 + 36*256) / 256;
@@ -329,7 +329,7 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra
 
        dprintk("%s: drift:%i inversion:%i auto_step:%i "
                "auto_sub_step:%i started_auto_step:%i\n",
-               __FUNCTION__, fepriv->lnb_drift, fepriv->inversion,
+               __func__, fepriv->lnb_drift, fepriv->inversion,
                fepriv->auto_step, fepriv->auto_sub_step, fepriv->started_auto_step);
 
        /* set the frontend itself */
@@ -511,7 +511,7 @@ static int dvb_frontend_thread(void *data)
        fe_status_t s;
        struct dvb_frontend_parameters *params;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        fepriv->check_wrapped = 0;
        fepriv->quality = 0;
@@ -597,7 +597,7 @@ static void dvb_frontend_stop(struct dvb_frontend *fe)
 {
        struct dvb_frontend_private *fepriv = fe->frontend_priv;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        fepriv->exit = 1;
        mb();
@@ -665,7 +665,7 @@ static int dvb_frontend_start(struct dvb_frontend *fe)
        struct dvb_frontend_private *fepriv = fe->frontend_priv;
        struct task_struct *fe_thread;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        if (fepriv->thread) {
                if (!fepriv->exit)
@@ -763,7 +763,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
        struct dvb_frontend_private *fepriv = fe->frontend_priv;
        int err = -EOPNOTSUPP;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        if (fepriv->exit)
                return -ENODEV;
@@ -895,7 +895,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
                        int i;
                        u8 last = 1;
                        if (dvb_frontend_debug)
-                               printk("%s switch command: 0x%04lx\n", __FUNCTION__, cmd);
+                               printk("%s switch command: 0x%04lx\n", __func__, cmd);
                        do_gettimeofday(&nexttime);
                        if (dvb_frontend_debug)
                                memcpy(&tv[0], &nexttime, sizeof(struct timeval));
@@ -919,7 +919,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
                        }
                        if (dvb_frontend_debug) {
                                printk("%s(%d): switch delay (should be 32k followed by all 8k\n",
-                                       __FUNCTION__, fe->dvb->num);
+                                       __func__, fe->dvb->num);
                                for (i = 1; i < 10; i++)
                                        printk("%d: %d\n", i, timeval_usec_diff(tv[i-1] , tv[i]));
                        }
@@ -1037,7 +1037,7 @@ static unsigned int dvb_frontend_poll(struct file *file, struct poll_table_struc
        struct dvb_frontend *fe = dvbdev->priv;
        struct dvb_frontend_private *fepriv = fe->frontend_priv;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        poll_wait (file, &fepriv->events.wait_queue, wait);
 
@@ -1054,7 +1054,7 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
        struct dvb_frontend_private *fepriv = fe->frontend_priv;
        int ret;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl) {
                if ((ret = fe->ops.ts_bus_ctrl(fe, 1)) < 0)
@@ -1095,7 +1095,7 @@ static int dvb_frontend_release(struct inode *inode, struct file *file)
        struct dvb_frontend_private *fepriv = fe->frontend_priv;
        int ret;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        if ((file->f_flags & O_ACCMODE) != O_RDONLY)
                fepriv->release_jiffies = jiffies;
@@ -1135,7 +1135,7 @@ int dvb_register_frontend(struct dvb_adapter* dvb,
                .kernel_ioctl = dvb_frontend_ioctl
        };
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        if (mutex_lock_interruptible(&frontend_mutex))
                return -ERESTARTSYS;
@@ -1169,7 +1169,7 @@ EXPORT_SYMBOL(dvb_register_frontend);
 int dvb_unregister_frontend(struct dvb_frontend* fe)
 {
        struct dvb_frontend_private *fepriv = fe->frontend_priv;
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        mutex_lock(&frontend_mutex);
        dvb_frontend_stop (fe);
index 4c8b62e2c035246095e5fc6e750a3127e7a188b3..56d871cfd7fc23bf6406fca9f3f0482830c6b881 100644 (file)
@@ -354,7 +354,7 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
 #ifdef ULE_DEBUG
        /* The code inside ULE_DEBUG keeps a history of the last 100 TS cells processed. */
        static unsigned char ule_hist[100*TS_SZ];
-       static unsigned char *ule_where = ule_hist, ule_dump = 0;
+       static unsigned char *ule_where = ule_hist, ule_dump;
 #endif
 
        /* For all TS cells in current buffer.
@@ -965,17 +965,17 @@ static int dvb_net_feed_start(struct net_device *dev)
        struct dmx_demux *demux = priv->demux;
        unsigned char *mac = (unsigned char *) dev->dev_addr;
 
-       dprintk("%s: rx_mode %i\n", __FUNCTION__, priv->rx_mode);
+       dprintk("%s: rx_mode %i\n", __func__, priv->rx_mode);
        mutex_lock(&priv->mutex);
        if (priv->tsfeed || priv->secfeed || priv->secfilter || priv->multi_secfilter[0])
-               printk("%s: BUG %d\n", __FUNCTION__, __LINE__);
+               printk("%s: BUG %d\n", __func__, __LINE__);
 
        priv->secfeed=NULL;
        priv->secfilter=NULL;
        priv->tsfeed = NULL;
 
        if (priv->feedtype == DVB_NET_FEEDTYPE_MPE) {
-               dprintk("%s: alloc secfeed\n", __FUNCTION__);
+               dprintk("%s: alloc secfeed\n", __func__);
                ret=demux->allocate_section_feed(demux, &priv->secfeed,
                                         dvb_net_sec_callback);
                if (ret<0) {
@@ -993,38 +993,38 @@ static int dvb_net_feed_start(struct net_device *dev)
                }
 
                if (priv->rx_mode != RX_MODE_PROMISC) {
-                       dprintk("%s: set secfilter\n", __FUNCTION__);
+                       dprintk("%s: set secfilter\n", __func__);
                        dvb_net_filter_sec_set(dev, &priv->secfilter, mac, mask_normal);
                }
 
                switch (priv->rx_mode) {
                case RX_MODE_MULTI:
                        for (i = 0; i < priv->multi_num; i++) {
-                               dprintk("%s: set multi_secfilter[%d]\n", __FUNCTION__, i);
+                               dprintk("%s: set multi_secfilter[%d]\n", __func__, i);
                                dvb_net_filter_sec_set(dev, &priv->multi_secfilter[i],
                                                       priv->multi_macs[i], mask_normal);
                        }
                        break;
                case RX_MODE_ALL_MULTI:
                        priv->multi_num=1;
-                       dprintk("%s: set multi_secfilter[0]\n", __FUNCTION__);
+                       dprintk("%s: set multi_secfilter[0]\n", __func__);
                        dvb_net_filter_sec_set(dev, &priv->multi_secfilter[0],
                                               mac_allmulti, mask_allmulti);
                        break;
                case RX_MODE_PROMISC:
                        priv->multi_num=0;
-                       dprintk("%s: set secfilter\n", __FUNCTION__);
+                       dprintk("%s: set secfilter\n", __func__);
                        dvb_net_filter_sec_set(dev, &priv->secfilter, mac, mask_promisc);
                        break;
                }
 
-               dprintk("%s: start filtering\n", __FUNCTION__);
+               dprintk("%s: start filtering\n", __func__);
                priv->secfeed->start_filtering(priv->secfeed);
        } else if (priv->feedtype == DVB_NET_FEEDTYPE_ULE) {
                struct timespec timeout = { 0, 10000000 }; // 10 msec
 
                /* we have payloads encapsulated in TS */
-               dprintk("%s: alloc tsfeed\n", __FUNCTION__);
+               dprintk("%s: alloc tsfeed\n", __func__);
                ret = demux->allocate_ts_feed(demux, &priv->tsfeed, dvb_net_ts_callback);
                if (ret < 0) {
                        printk("%s: could not allocate ts feed\n", dev->name);
@@ -1048,7 +1048,7 @@ static int dvb_net_feed_start(struct net_device *dev)
                        goto error;
                }
 
-               dprintk("%s: start filtering\n", __FUNCTION__);
+               dprintk("%s: start filtering\n", __func__);
                priv->tsfeed->start_filtering(priv->tsfeed);
        } else
                ret = -EINVAL;
@@ -1063,17 +1063,17 @@ static int dvb_net_feed_stop(struct net_device *dev)
        struct dvb_net_priv *priv = dev->priv;
        int i, ret = 0;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
        mutex_lock(&priv->mutex);
        if (priv->feedtype == DVB_NET_FEEDTYPE_MPE) {
                if (priv->secfeed) {
                        if (priv->secfeed->is_filtering) {
-                               dprintk("%s: stop secfeed\n", __FUNCTION__);
+                               dprintk("%s: stop secfeed\n", __func__);
                                priv->secfeed->stop_filtering(priv->secfeed);
                        }
 
                        if (priv->secfilter) {
-                               dprintk("%s: release secfilter\n", __FUNCTION__);
+                               dprintk("%s: release secfilter\n", __func__);
                                priv->secfeed->release_filter(priv->secfeed,
                                                              priv->secfilter);
                                priv->secfilter=NULL;
@@ -1082,7 +1082,7 @@ static int dvb_net_feed_stop(struct net_device *dev)
                        for (i=0; i<priv->multi_num; i++) {
                                if (priv->multi_secfilter[i]) {
                                        dprintk("%s: release multi_filter[%d]\n",
-                                               __FUNCTION__, i);
+                                               __func__, i);
                                        priv->secfeed->release_filter(priv->secfeed,
                                                                      priv->multi_secfilter[i]);
                                        priv->multi_secfilter[i] = NULL;
@@ -1096,7 +1096,7 @@ static int dvb_net_feed_stop(struct net_device *dev)
        } else if (priv->feedtype == DVB_NET_FEEDTYPE_ULE) {
                if (priv->tsfeed) {
                        if (priv->tsfeed->is_filtering) {
-                               dprintk("%s: stop tsfeed\n", __FUNCTION__);
+                               dprintk("%s: stop tsfeed\n", __func__);
                                priv->tsfeed->stop_filtering(priv->tsfeed);
                        }
                        priv->demux->release_ts_feed(priv->demux, priv->tsfeed);
index ac9d93cf83c6c898d48a6dd17622ce40e6d42094..872985b7912d3db12036abd78380a012012033e1 100644 (file)
@@ -90,7 +90,11 @@ void dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf)
        rbuf->error = 0;
 }
 
-
+void dvb_ringbuffer_reset(struct dvb_ringbuffer *rbuf)
+{
+       rbuf->pread = rbuf->pwrite = 0;
+       rbuf->error = 0;
+}
 
 void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf)
 {
index d97714e757362b6ee62204de6444b68337faaede..890826262966c16c709815d83e1e08ac68c08058 100644 (file)
@@ -69,6 +69,7 @@ struct dvb_ringbuffer {
 **     to lock read or write operations.
 **     Two or more readers must be locked against each other.
 **     Flushing the buffer counts as a read operation.
+**     Resetting the buffer counts as a read and write operation.
 **     Two or more writers must be locked against each other.
 */
 
@@ -85,6 +86,13 @@ extern ssize_t dvb_ringbuffer_free(struct dvb_ringbuffer *rbuf);
 extern ssize_t dvb_ringbuffer_avail(struct dvb_ringbuffer *rbuf);
 
 
+/*
+** Reset the read and write pointers to zero and flush the buffer
+** This counts as a read and write operation
+*/
+extern void dvb_ringbuffer_reset(struct dvb_ringbuffer *rbuf);
+
+
 /* read routines & macros */
 /* ---------------------- */
 /* flush buffer */
index 18738faecbbc51adc7f9311c066779cafdee0b88..8b56d929f7fd52c63f1fbda3165bcce33d0aa11d 100644 (file)
@@ -49,7 +49,6 @@ static const char * const dnames[] = {
        "net", "osd"
 };
 
-#define DVB_MAX_ADAPTERS       8
 #define DVB_MAX_IDS            4
 #define nums2minor(num,type,id)        ((num << 6) | (id << 4) | type)
 #define MAX_DVB_MINORS         (DVB_MAX_ADAPTERS*64)
@@ -97,7 +96,7 @@ static int dvb_device_open(struct inode *inode, struct file *file)
 }
 
 
-static struct file_operations dvb_device_fops =
+static const struct file_operations dvb_device_fops =
 {
        .owner =        THIS_MODULE,
        .open =         dvb_device_open,
@@ -196,7 +195,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
        if ((id = dvbdev_get_free_id (adap, type)) < 0){
                mutex_unlock(&dvbdev_register_lock);
                *pdvbdev = NULL;
-               printk(KERN_ERR "%s: couldn't find free device id\n", __FUNCTION__);
+               printk(KERN_ERR "%s: couldn't find free device id\n", __func__);
                return -ENFILE;
        }
 
@@ -235,7 +234,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
                               "dvb%d.%s%d", adap->num, dnames[type], id);
        if (IS_ERR(clsdev)) {
                printk(KERN_ERR "%s: failed to create device dvb%d.%s%d (%ld)\n",
-                      __FUNCTION__, adap->num, dnames[type], id, PTR_ERR(clsdev));
+                      __func__, adap->num, dnames[type], id, PTR_ERR(clsdev));
                return PTR_ERR(clsdev);
        }
 
@@ -262,18 +261,25 @@ void dvb_unregister_device(struct dvb_device *dvbdev)
 }
 EXPORT_SYMBOL(dvb_unregister_device);
 
+static int dvbdev_check_free_adapter_num(int num)
+{
+       struct list_head *entry;
+       list_for_each(entry, &dvb_adapter_list) {
+               struct dvb_adapter *adap;
+               adap = list_entry(entry, struct dvb_adapter, list_head);
+               if (adap->num == num)
+                       return 0;
+       }
+       return 1;
+}
 
 static int dvbdev_get_free_adapter_num (void)
 {
        int num = 0;
 
        while (num < DVB_MAX_ADAPTERS) {
-               struct dvb_adapter *adap;
-               list_for_each_entry(adap, &dvb_adapter_list, list_head)
-                       if (adap->num == num)
-                               goto skip;
-               return num;
-skip:
+               if (dvbdev_check_free_adapter_num(num))
+                       return num;
                num++;
        }
 
@@ -281,13 +287,28 @@ skip:
 }
 
 
-int dvb_register_adapter(struct dvb_adapter *adap, const char *name, struct module *module, struct device *device)
+int dvb_register_adapter(struct dvb_adapter *adap, const char *name,
+                        struct module *module, struct device *device,
+                        short *adapter_nums)
 {
-       int num;
+       int i, num;
 
        mutex_lock(&dvbdev_register_lock);
 
-       if ((num = dvbdev_get_free_adapter_num ()) < 0) {
+       for (i = 0; i < DVB_MAX_ADAPTERS; ++i) {
+               num = adapter_nums[i];
+               if (num >= 0  &&  num < DVB_MAX_ADAPTERS) {
+               /* use the one the driver asked for */
+                       if (dvbdev_check_free_adapter_num(num))
+                               break;
+               } else {
+                       num = dvbdev_get_free_adapter_num();
+                       break;
+               }
+               num = -1;
+       }
+
+       if (num < 0) {
                mutex_unlock(&dvbdev_register_lock);
                return -ENFILE;
        }
index 6dff10ebf47052a1f92872e7a95541f56e845646..5f9a737c6de194065d3e5f7e4de06e0407d8c322 100644 (file)
 
 #define DVB_MAJOR 212
 
+#define DVB_MAX_ADAPTERS 8
+
+#define DVB_UNSET (-1)
+
 #define DVB_DEVICE_VIDEO      0
 #define DVB_DEVICE_AUDIO      1
 #define DVB_DEVICE_SEC        2
 #define DVB_DEVICE_NET        7
 #define DVB_DEVICE_OSD        8
 
+#define DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr) \
+       static short adapter_nr[] = \
+               {[0 ... (DVB_MAX_ADAPTERS - 1)] = DVB_UNSET }; \
+       module_param_array(adapter_nr, short, NULL, 0444); \
+       MODULE_PARM_DESC(adapter_nr, "DVB adapter numbers")
 
 struct dvb_adapter {
        int num;
@@ -78,7 +87,9 @@ struct dvb_device {
 };
 
 
-extern int dvb_register_adapter (struct dvb_adapter *adap, const char *name, struct module *module, struct device *device);
+extern int dvb_register_adapter(struct dvb_adapter *adap, const char *name,
+                               struct module *module, struct device *device,
+                               short *adapter_nums);
 extern int dvb_unregister_adapter (struct dvb_adapter *adap);
 
 extern int dvb_register_device (struct dvb_adapter *adap,
index d73934dd4c573790790c9cd885db3ef7063f02f7..3c8493d2026dd329a9e20c1c6faaf2d9581b94b3 100644 (file)
@@ -105,6 +105,7 @@ 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 TUNER_SIMPLE if !DVB_FE_CUSTOMISE
        help
          Say Y here to support the Conexant USB2.0 hybrid reference design.
          Currently, only DVB and ATSC modes are supported, analog mode
index a6c5f19f680d6dd38452a0f5356885bfa082994b..dc8c8784caa8a8c46e36886acdcbff6e8f3eeb1e 100644 (file)
@@ -18,6 +18,9 @@
 static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "set debugging level (rc=1 (or-able))." DVB_USB_DEBUG_STATUS);
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 #define deb_rc(args...)   dprintk(debug,0x01,args)
 
 static int a800_power_ctrl(struct dvb_usb_device *d, int onoff)
@@ -94,7 +97,8 @@ static struct dvb_usb_device_properties a800_properties;
 static int a800_probe(struct usb_interface *intf,
                const struct usb_device_id *id)
 {
-       return dvb_usb_device_init(intf,&a800_properties,THIS_MODULE,NULL);
+       return dvb_usb_device_init(intf, &a800_properties,
+                                  THIS_MODULE, NULL, adapter_nr);
 }
 
 /* do not change the order of the ID table */
index e7f76f515b4f6bbe293832596daf20c78dc0d0b4..cfe71feefcad27a8e64598316a366bda99ae8985 100644 (file)
@@ -39,6 +39,8 @@ int dvb_usb_af9005_dump_eeprom = 0;
 module_param_named(dump_eeprom, dvb_usb_af9005_dump_eeprom, int, 0);
 MODULE_PARM_DESC(dump_eeprom, "dump contents of the eeprom.");
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 /* remote control decoder */
 int (*rc_decode) (struct dvb_usb_device * d, u8 * data, int len, u32 * event,
                  int *state);
@@ -1020,7 +1022,8 @@ static struct dvb_usb_device_properties af9005_properties;
 static int af9005_usb_probe(struct usb_interface *intf,
                            const struct usb_device_id *id)
 {
-       return dvb_usb_device_init(intf, &af9005_properties, THIS_MODULE, NULL);
+       return dvb_usb_device_init(intf, &af9005_properties,
+                                  THIS_MODULE, NULL, adapter_nr);
 }
 
 static struct usb_device_id af9005_usb_table[] = {
index f3ff8131469607422e2599b88492521bac9e3f78..2ccb90fa60c85917cd9604443cb13e5169e61f5f 100644 (file)
@@ -19,6 +19,8 @@ static int dvb_usb_au6610_debug;
 module_param_named(debug, dvb_usb_au6610_debug, int, 0644);
 MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 static int au6610_usb_msg(struct dvb_usb_device *d, u8 operation, u8 addr,
                          u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
 {
@@ -163,7 +165,9 @@ static int au6610_probe(struct usb_interface *intf,
        if (intf->num_altsetting < AU6610_ALTSETTING_COUNT)
                return -ENODEV;
 
-       if ((ret = dvb_usb_device_init(intf, &au6610_properties, THIS_MODULE, &d)) == 0) {
+       ret = dvb_usb_device_init(intf, &au6610_properties, THIS_MODULE, &d,
+                                 adapter_nr);
+       if (ret == 0) {
                alt = usb_altnum_to_altsetting(intf, AU6610_ALTSETTING);
 
                if (alt == NULL) {
index c58365005ac1cb32e0f7739918f6e3b3f8a37a97..720fcd1c3c1d75caad387932f9bc56329c42ff47 100644 (file)
@@ -23,6 +23,8 @@
  *
  * see Documentation/dvb/README.dvb-usb for more information
  */
+#include <media/tuner.h>
+
 #include "cxusb.h"
 
 #include "cx22702.h"
 #include "mt352_priv.h"
 #include "zl10353.h"
 #include "tuner-xc2028.h"
-#include "tuner-xc2028-types.h"
+#include "tuner-simple.h"
 
 /* debug */
 static int dvb_usb_cxusb_debug;
 module_param_named(debug, dvb_usb_cxusb_debug, int, 0644);
 MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 #define deb_info(args...)   dprintk(dvb_usb_cxusb_debug,0x01,args)
 #define deb_i2c(args...)    if (d->udev->descriptor.idVendor == USB_VID_MEDION) \
                                dprintk(dvb_usb_cxusb_debug,0x01,args)
@@ -450,8 +455,9 @@ static struct mt352_config cxusb_mt352_xc3028_config = {
 /* Callbacks for DVB USB */
 static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap)
 {
-       dvb_attach(dvb_pll_attach, adap->fe, 0x61, &adap->dev->i2c_adap,
-                  DVB_PLL_FMD1216ME);
+       dvb_attach(simple_tuner_attach, adap->fe,
+                  &adap->dev->i2c_adap, 0x61,
+                  TUNER_PHILIPS_FMD1216ME_MK3);
        return 0;
 }
 
@@ -477,8 +483,8 @@ static int cxusb_dtt7579_tuner_attach(struct dvb_usb_adapter *adap)
 
 static int cxusb_lgh064f_tuner_attach(struct dvb_usb_adapter *adap)
 {
-       dvb_attach(dvb_pll_attach, adap->fe, 0x61, &adap->dev->i2c_adap,
-                  DVB_PLL_LG_TDVS_H06XF);
+       dvb_attach(simple_tuner_attach, adap->fe,
+                  &adap->dev->i2c_adap, 0x61, TUNER_LG_TDVS_H06XF);
        return 0;
 }
 
@@ -488,14 +494,14 @@ static int dvico_bluebird_xc2028_callback(void *ptr, int command, int arg)
 
        switch (command) {
        case XC2028_TUNER_RESET:
-               deb_info("%s: XC2028_TUNER_RESET %d\n", __FUNCTION__, arg);
+               deb_info("%s: XC2028_TUNER_RESET %d\n", __func__, arg);
                cxusb_bluebird_gpio_pulse(d, 0x01, 1);
                break;
        case XC2028_RESET_CLK:
-               deb_info("%s: XC2028_RESET_CLK %d\n", __FUNCTION__, arg);
+               deb_info("%s: XC2028_RESET_CLK %d\n", __func__, arg);
                break;
        default:
-               deb_info("%s: unknown command %d, arg %d\n", __FUNCTION__,
+               deb_info("%s: unknown command %d, arg %d\n", __func__,
                         command, arg);
                return -EINVAL;
        }
@@ -509,13 +515,12 @@ static int cxusb_dvico_xc3028_tuner_attach(struct dvb_usb_adapter *adap)
        struct xc2028_config      cfg = {
                .i2c_adap  = &adap->dev->i2c_adap,
                .i2c_addr  = 0x61,
-               .video_dev = adap->dev,
                .callback  = dvico_bluebird_xc2028_callback,
        };
        static struct xc2028_ctrl ctl = {
                .fname       = "xc3028-dvico-au-01.fw",
                .max_len     = 64,
-               .scode_table = ZARLINK456,
+               .scode_table = XC3028_FE_ZARLINK456,
        };
 
        fe = dvb_attach(xc2028_attach, adap->fe, &cfg);
@@ -720,16 +725,24 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_prope
 static int cxusb_probe(struct usb_interface *intf,
                       const struct usb_device_id *id)
 {
-       if (dvb_usb_device_init(intf,&cxusb_medion_properties,THIS_MODULE,NULL) == 0 ||
-               dvb_usb_device_init(intf,&cxusb_bluebird_lgh064f_properties,THIS_MODULE,NULL) == 0 ||
-               dvb_usb_device_init(intf,&cxusb_bluebird_dee1601_properties,THIS_MODULE,NULL) == 0 ||
-               dvb_usb_device_init(intf,&cxusb_bluebird_lgz201_properties,THIS_MODULE,NULL) == 0 ||
-               dvb_usb_device_init(intf,&cxusb_bluebird_dtt7579_properties,THIS_MODULE,NULL) == 0 ||
-               dvb_usb_device_init(intf,&cxusb_bluebird_dualdig4_properties,THIS_MODULE,NULL) == 0 ||
-               dvb_usb_device_init(intf,&cxusb_bluebird_nano2_properties,THIS_MODULE,NULL) == 0 ||
-               dvb_usb_device_init(intf,&cxusb_bluebird_nano2_needsfirmware_properties,THIS_MODULE,NULL) == 0) {
+       if (0 == dvb_usb_device_init(intf, &cxusb_medion_properties,
+                                    THIS_MODULE, NULL, adapter_nr) ||
+           0 == dvb_usb_device_init(intf, &cxusb_bluebird_lgh064f_properties,
+                                    THIS_MODULE, NULL, adapter_nr) ||
+           0 == dvb_usb_device_init(intf, &cxusb_bluebird_dee1601_properties,
+                                    THIS_MODULE, NULL, adapter_nr) ||
+           0 == dvb_usb_device_init(intf, &cxusb_bluebird_lgz201_properties,
+                                    THIS_MODULE, NULL, adapter_nr) ||
+           0 == dvb_usb_device_init(intf, &cxusb_bluebird_dtt7579_properties,
+                                    THIS_MODULE, NULL, adapter_nr) ||
+           0 == dvb_usb_device_init(intf, &cxusb_bluebird_dualdig4_properties,
+                                    THIS_MODULE, NULL, adapter_nr) ||
+           0 == dvb_usb_device_init(intf, &cxusb_bluebird_nano2_properties,
+                                    THIS_MODULE, NULL, adapter_nr) ||
+           0 == dvb_usb_device_init(intf,
+                               &cxusb_bluebird_nano2_needsfirmware_properties,
+                                    THIS_MODULE, NULL, adapter_nr))
                return 0;
-       }
 
        return -EINVAL;
 }
index 4a903ea958965d5bc7cbadbd96f2282e89dedf34..66d4dc6ba46fe8a78a9d597f3d45bdb6e6c5cf01 100644 (file)
@@ -37,6 +37,7 @@ struct dib0700_state {
        u8 channel_state;
        u16 mt2060_if1[2];
        u8 rc_toggle;
+       u8 rc_counter;
        u8 is_dib7000pc;
 };
 
@@ -44,12 +45,15 @@ extern int dib0700_set_gpio(struct dvb_usb_device *, enum dib07x0_gpios gpio, u8
 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);
 extern int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw);
+extern int dib0700_rc_setup(struct dvb_usb_device *d);
 extern int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff);
 extern struct i2c_algorithm dib0700_i2c_algo;
 extern int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props,
                        struct dvb_usb_device_description **desc, int *cold);
 
 extern int dib0700_device_count;
+extern int dvb_usb_dib0700_ir_proto;
 extern struct dvb_usb_device_properties dib0700_devices[];
 extern struct usb_device_id dib0700_usb_id_table[];
+
 #endif
index c9857d5c69829e68bbc9e82af68026ebc4d4288c..595a04696c87af2590588bf87013a44b8e44aa7c 100644 (file)
@@ -13,10 +13,12 @@ int dvb_usb_dib0700_debug;
 module_param_named(debug,dvb_usb_dib0700_debug, int, 0644);
 MODULE_PARM_DESC(debug, "set debugging level (1=info,2=fw,4=fwdata,8=data (or-able))." DVB_USB_DEBUG_STATUS);
 
-static int dvb_usb_dib0700_ir_proto = 1;
+int dvb_usb_dib0700_ir_proto = 1;
 module_param(dvb_usb_dib0700_ir_proto, int, 0644);
 MODULE_PARM_DESC(dvb_usb_dib0700_ir_proto, "set ir protocol (0=NEC, 1=RC5 (default), 2=RC6).");
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 /* expecting rx buffer: request data[0] data[1] ... data[2] */
 static int dib0700_ctrl_wr(struct dvb_usb_device *d, u8 *tx, u8 txlen)
 {
@@ -261,7 +263,7 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
        return dib0700_ctrl_wr(adap->dev, b, 4);
 }
 
-static int dib0700_rc_setup(struct dvb_usb_device *d)
+int dib0700_rc_setup(struct dvb_usb_device *d)
 {
        u8 rc_setup[3] = {REQUEST_SET_RC, dvb_usb_dib0700_ir_proto, 0};
        int i = dib0700_ctrl_wr(d, rc_setup, 3);
@@ -279,7 +281,8 @@ static int dib0700_probe(struct usb_interface *intf,
        struct dvb_usb_device *dev;
 
        for (i = 0; i < dib0700_device_count; i++)
-               if (dvb_usb_device_init(intf, &dib0700_devices[i], THIS_MODULE, &dev) == 0)
+               if (dvb_usb_device_init(intf, &dib0700_devices[i], THIS_MODULE,
+                                       &dev, adapter_nr) == 0)
                {
                        dib0700_rc_setup(dev);
                        return 0;
index e7093826e975896f31153621f08edf7aef219bf7..6477fc66cc2381da08ff3637673e04042388470b 100644 (file)
@@ -13,6 +13,7 @@
 #include "dib7000p.h"
 #include "mt2060.h"
 #include "mt2266.h"
+#include "tuner-xc2028.h"
 #include "dib0070.h"
 
 static int force_lna_activation;
@@ -297,10 +298,156 @@ static int stk7700d_tuner_attach(struct dvb_usb_adapter *adap)
                &stk7700d_mt2266_config[adap->id]) == NULL ? -ENODEV : 0;;
 }
 
+/* STK7700-PH: Digital/Analog Hybrid Tuner, e.h. Cinergy HT USB HE */
+struct dibx000_agc_config xc3028_agc_config = {
+       BAND_VHF | BAND_UHF,       /* band_caps */
+
+       /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=0,
+        * P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0,
+        * P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */
+       (0 << 15) | (0 << 14) | (0 << 11) | (0 << 10) | (0 << 9) | (0 << 8) |
+       (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), /* setup */
+
+       712,    /* inv_gain */
+       21,     /* time_stabiliz */
+
+       0,      /* alpha_level */
+       118,    /* thlock */
+
+       0,      /* wbd_inv */
+       2867,   /* wbd_ref */
+       0,      /* wbd_sel */
+       2,      /* wbd_alpha */
+
+       0,      /* agc1_max */
+       0,      /* agc1_min */
+       39718,  /* agc2_max */
+       9930,   /* agc2_min */
+       0,      /* agc1_pt1 */
+       0,      /* agc1_pt2 */
+       0,      /* agc1_pt3 */
+       0,      /* agc1_slope1 */
+       0,      /* agc1_slope2 */
+       0,      /* agc2_pt1 */
+       128,    /* agc2_pt2 */
+       29,     /* agc2_slope1 */
+       29,     /* agc2_slope2 */
+
+       17,     /* alpha_mant */
+       27,     /* alpha_exp */
+       23,     /* beta_mant */
+       51,     /* beta_exp */
+
+       1,      /* perform_agc_softsplit */
+};
+
+/* PLL Configuration for COFDM BW_MHz = 8.00 with external clock = 30.00 */
+struct dibx000_bandwidth_config xc3028_bw_config = {
+       60000, 30000, /* internal, sampling */
+       1, 8, 3, 1, 0, /* pll_cfg: prediv, ratio, range, reset, bypass */
+       0, 0, 1, 1, 0, /* misc: refdiv, bypclk_div, IO_CLK_en_core, ADClkSrc,
+                         modulo */
+       (3 << 14) | (1 << 12) | (524 << 0), /* sad_cfg: refsel, sel, freq_15k */
+       (1 << 25) | 5816102, /* ifreq = 5.200000 MHz */
+       20452225, /* timf */
+       30000000, /* xtal_hz */
+};
+
+static struct dib7000p_config stk7700ph_dib7700_xc3028_config = {
+       .output_mpeg2_in_188_bytes = 1,
+       .tuner_is_baseband = 1,
+
+       .agc_config_count = 1,
+       .agc = &xc3028_agc_config,
+       .bw  = &xc3028_bw_config,
+
+       .gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS,
+       .gpio_val = DIB7000P_GPIO_DEFAULT_VALUES,
+       .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
+};
+
+static int stk7700ph_xc3028_callback(void *ptr, int command, int arg)
+{
+       struct dvb_usb_adapter *adap = ptr;
+
+       switch (command) {
+       case XC2028_TUNER_RESET:
+               /* Send the tuner in then out of reset */
+               dib7000p_set_gpio(adap->fe, 8, 0, 0); msleep(10);
+               dib7000p_set_gpio(adap->fe, 8, 0, 1);
+               break;
+       case XC2028_RESET_CLK:
+               break;
+       default:
+               err("%s: unknown command %d, arg %d\n", __func__,
+                       command, arg);
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static struct xc2028_ctrl stk7700ph_xc3028_ctrl = {
+       .fname = XC2028_DEFAULT_FIRMWARE,
+       .max_len = 64,
+       .demod = XC3028_FE_DIBCOM52,
+};
+
+static struct xc2028_config stk7700ph_xc3028_config = {
+       .i2c_addr = 0x61,
+       .callback = stk7700ph_xc3028_callback,
+       .ctrl = &stk7700ph_xc3028_ctrl,
+};
+
+static int stk7700ph_frontend_attach(struct dvb_usb_adapter *adap)
+{
+       struct usb_device_descriptor *desc = &adap->dev->udev->descriptor;
+
+       if (desc->idVendor  == USB_VID_PINNACLE &&
+           desc->idProduct == USB_PID_PINNACLE_EXPRESSCARD_320CX)
+       dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
+       else
+       dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
+       msleep(20);
+       dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
+       dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
+       dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
+       dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
+       msleep(10);
+       dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
+       msleep(20);
+       dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
+       msleep(10);
+
+       dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
+               &stk7700ph_dib7700_xc3028_config);
+
+       adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
+               &stk7700ph_dib7700_xc3028_config);
+
+       return adap->fe == NULL ? -ENODEV : 0;
+}
+
+static int stk7700ph_tuner_attach(struct dvb_usb_adapter *adap)
+{
+       struct i2c_adapter *tun_i2c;
+
+       tun_i2c = dib7000p_get_i2c_master(adap->fe,
+               DIBX000_I2C_INTERFACE_TUNER, 1);
+
+       stk7700ph_xc3028_config.i2c_adap = tun_i2c;
+       stk7700ph_xc3028_config.video_dev = adap;
+
+       return dvb_attach(xc2028_attach, adap->fe, &stk7700ph_xc3028_config)
+               == NULL ? -ENODEV : 0;
+}
+
 #define DEFAULT_RC_INTERVAL 150
 
 static u8 rc_request[] = { REQUEST_POLL_RC, 0 };
 
+/* Number of keypresses to ignore before start repeating */
+#define RC_REPEAT_DELAY 2
+
 static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 {
        u8 key[4];
@@ -314,18 +461,67 @@ static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
                err("RC Query Failed");
                return -1;
        }
+
+       /* losing half of KEY_0 events from Philipps rc5 remotes.. */
        if (key[0]==0 && key[1]==0 && key[2]==0 && key[3]==0) return 0;
-       if (key[3-1]!=st->rc_toggle) {
+
+       /* info("%d: %2X %2X %2X %2X",dvb_usb_dib0700_ir_proto,(int)key[3-2],(int)key[3-3],(int)key[3-1],(int)key[3]);  */
+
+       dib0700_rc_setup(d); /* reset ir sensor data to prevent false events */
+
+       switch (dvb_usb_dib0700_ir_proto) {
+       case 0: {
+               /* NEC protocol sends repeat code as 0 0 0 FF */
+               if ((key[3-2] == 0x00) && (key[3-3] == 0x00) &&
+                   (key[3] == 0xFF)) {
+                       st->rc_counter++;
+                       if (st->rc_counter > RC_REPEAT_DELAY) {
+                               *event = d->last_event;
+                               *state = REMOTE_KEY_PRESSED;
+                               st->rc_counter = RC_REPEAT_DELAY;
+                       }
+                       return 0;
+               }
                for (i=0;i<d->props.rc_key_map_size; i++) {
                        if (keymap[i].custom == key[3-2] && keymap[i].data == key[3-3]) {
+                               st->rc_counter = 0;
+                               *event = keymap[i].event;
+                               *state = REMOTE_KEY_PRESSED;
+                               d->last_event = keymap[i].event;
+                               return 0;
+                       }
+               }
+               break;
+       }
+       default: {
+               /* RC-5 protocol changes toggle bit on new keypress */
+               for (i = 0; i < d->props.rc_key_map_size; i++) {
+                       if (keymap[i].custom == key[3-2] && keymap[i].data == key[3-3]) {
+                               if (d->last_event == keymap[i].event &&
+                                       key[3-1] == st->rc_toggle) {
+                                       st->rc_counter++;
+                                       /* prevents unwanted double hits */
+                                       if (st->rc_counter > RC_REPEAT_DELAY) {
+                                               *event = d->last_event;
+                                               *state = REMOTE_KEY_PRESSED;
+                                               st->rc_counter = RC_REPEAT_DELAY;
+                                       }
+
+                                       return 0;
+                               }
+                               st->rc_counter = 0;
                                *event = keymap[i].event;
                                *state = REMOTE_KEY_PRESSED;
-                               st->rc_toggle=key[3-1];
+                               st->rc_toggle = key[3-1];
+                               d->last_event = keymap[i].event;
                                return 0;
                        }
                }
-               err("Unknown remote controller key : %2X %2X",(int)key[3-2],(int)key[3-3]);
+               break;
        }
+       }
+       err("Unknown remote controller key: %2X %2X %2X %2X", (int) key[3-2], (int) key[3-3], (int) key[3-1], (int) key[3]);
+       d->last_event = 0;
        return 0;
 }
 
@@ -794,6 +990,10 @@ static struct dib7000p_config dib7070p_dib7000p_config = {
 /* STK7070P */
 static int stk7070p_frontend_attach(struct dvb_usb_adapter *adap)
 {
+       if (adap->dev->udev->descriptor.idVendor  == USB_VID_PINNACLE &&
+       adap->dev->udev->descriptor.idProduct == USB_PID_PINNACLE_PCTV72E)
+       dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
+       else
        dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
        msleep(10);
        dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
@@ -808,9 +1008,11 @@ static int stk7070p_frontend_attach(struct dvb_usb_adapter *adap)
        msleep(10);
        dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
 
-       dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, &dib7070p_dib7000p_config);
+       dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
+               &dib7070p_dib7000p_config);
 
-       adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, &dib7070p_dib7000p_config);
+       adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
+               &dib7070p_dib7000p_config);
        return adap->fe == NULL ? -ENODEV : 0;
 }
 
@@ -878,34 +1080,43 @@ static int stk7070pd_frontend_attach1(struct dvb_usb_adapter *adap)
 /* DVB-USB and USB stuff follows */
 struct usb_device_id dib0700_usb_id_table[] = {
 /* 0 */        { USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK7700P) },
-               { USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK7700P_PC) },
-
-               { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500) },
-               { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_2) },
-               { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK) },
+       { USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK7700P_PC) },
+       { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500) },
+       { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_2) },
+       { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK) },
 /* 5 */        { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR) },
-               { USB_DEVICE(USB_VID_COMPRO,    USB_PID_COMPRO_VIDEOMATE_U500) },
-               { USB_DEVICE(USB_VID_UNIWILL,   USB_PID_UNIWILL_STK7700P) },
-               { USB_DEVICE(USB_VID_LEADTEK,   USB_PID_WINFAST_DTV_DONGLE_STK7700P) },
-               { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK_2) },
+       { USB_DEVICE(USB_VID_COMPRO,    USB_PID_COMPRO_VIDEOMATE_U500) },
+       { USB_DEVICE(USB_VID_UNIWILL,   USB_PID_UNIWILL_STK7700P) },
+       { USB_DEVICE(USB_VID_LEADTEK,   USB_PID_WINFAST_DTV_DONGLE_STK7700P) },
+       { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK_2) },
 /* 10 */{ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_2) },
-               { USB_DEVICE(USB_VID_PINNACLE,  USB_PID_PINNACLE_PCTV2000E) },
-               { USB_DEVICE(USB_VID_TERRATEC,  USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY) },
-               { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_TD_STICK) },
-               { USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK7700D) },
+       { USB_DEVICE(USB_VID_PINNACLE,  USB_PID_PINNACLE_PCTV2000E) },
+       { USB_DEVICE(USB_VID_TERRATEC,
+                       USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY) },
+       { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_TD_STICK) },
+       { USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK7700D) },
 /* 15 */{ USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK7070P) },
-               { USB_DEVICE(USB_VID_PINNACLE,  USB_PID_PINNACLE_PCTV_DVB_T_FLASH) },
-               { USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK7070PD) },
-               { USB_DEVICE(USB_VID_PINNACLE,  USB_PID_PINNACLE_PCTV_DUAL_DIVERSITY_DVB_T) },
-               { USB_DEVICE(USB_VID_COMPRO,    USB_PID_COMPRO_VIDEOMATE_U500_PC) },
+       { USB_DEVICE(USB_VID_PINNACLE,  USB_PID_PINNACLE_PCTV_DVB_T_FLASH) },
+       { USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK7070PD) },
+       { USB_DEVICE(USB_VID_PINNACLE,
+                       USB_PID_PINNACLE_PCTV_DUAL_DIVERSITY_DVB_T) },
+       { USB_DEVICE(USB_VID_COMPRO,    USB_PID_COMPRO_VIDEOMATE_U500_PC) },
 /* 20 */{ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_EXPRESS) },
-               { USB_DEVICE(USB_VID_GIGABYTE,  USB_PID_GIGABYTE_U7000) },
-               { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ARTEC_T14BR) },
-               { USB_DEVICE(USB_VID_ASUS,      USB_PID_ASUS_U3000) },
-               { USB_DEVICE(USB_VID_ASUS,      USB_PID_ASUS_U3100) },
-/* 25 */       { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK_3) },
-               { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_MYTV_T) },
-               { 0 }           /* Terminating entry */
+       { USB_DEVICE(USB_VID_GIGABYTE,  USB_PID_GIGABYTE_U7000) },
+       { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ARTEC_T14BR) },
+       { USB_DEVICE(USB_VID_ASUS,      USB_PID_ASUS_U3000) },
+       { USB_DEVICE(USB_VID_ASUS,      USB_PID_ASUS_U3100) },
+/* 25 */{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK_3) },
+       { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_MYTV_T) },
+       { USB_DEVICE(USB_VID_TERRATEC,  USB_PID_TERRATEC_CINERGY_HT_USB_XE) },
+       { USB_DEVICE(USB_VID_PINNACLE,  USB_PID_PINNACLE_EXPRESSCARD_320CX) },
+       { USB_DEVICE(USB_VID_PINNACLE,  USB_PID_PINNACLE_PCTV72E) },
+/* 30 */{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV73E) },
+       { USB_DEVICE(USB_VID_YUAN,      USB_PID_YUAN_EC372S) },
+       { USB_DEVICE(USB_VID_TERRATEC,  USB_PID_TERRATEC_CINERGY_HT_EXPRESS) },
+       { USB_DEVICE(USB_VID_TERRATEC,  USB_PID_TERRATEC_CINERGY_T_XXS) },
+       { USB_DEVICE(USB_VID_LEADTEK,   USB_PID_WINFAST_DTV_DONGLE_STK7700P_2) },
+       { 0 }           /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
 
@@ -969,7 +1180,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                                { NULL },
                        },
                        {   "Leadtek Winfast DTV Dongle (STK7700P based)",
-                               { &dib0700_usb_id_table[8], NULL },
+                               { &dib0700_usb_id_table[8], &dib0700_usb_id_table[34] },
                                { NULL },
                        },
                        {   "AVerMedia AVerTV DVB-T Express",
@@ -1069,12 +1280,16 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                        },
                },
 
-               .num_device_descs = 1,
+               .num_device_descs = 2,
                .devices = {
                        {   "ASUS My Cinema U3000 Mini DVBT Tuner",
                                { &dib0700_usb_id_table[23], NULL },
                                { NULL },
                        },
+                       {   "Yuan EC372S",
+                               { &dib0700_usb_id_table[31], NULL },
+                               { NULL },
+                       }
                }
        }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
 
@@ -1090,7 +1305,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                        },
                },
 
-               .num_device_descs = 6,
+               .num_device_descs = 9,
                .devices = {
                        {   "DiBcom STK7070P reference design",
                                { &dib0700_usb_id_table[15], NULL },
@@ -1116,6 +1331,18 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                                { &dib0700_usb_id_table[26], NULL },
                                { NULL },
                        },
+                       {   "Pinnacle PCTV 72e",
+                               { &dib0700_usb_id_table[29], NULL },
+                               { NULL },
+                       },
+                       {   "Pinnacle PCTV 73e",
+                               { &dib0700_usb_id_table[30], NULL },
+                               { NULL },
+                       },
+                       {   "Terratec Cinergy T USB XXS",
+                               { &dib0700_usb_id_table[33], NULL },
+                               { NULL },
+                       },
                },
 
                .rc_interval      = DEFAULT_RC_INTERVAL,
@@ -1155,6 +1382,40 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                                { NULL },
                        }
                }
+       }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
+
+               .num_adapters = 1,
+               .adapter = {
+                       {
+                               .frontend_attach  = stk7700ph_frontend_attach,
+                               .tuner_attach     = stk7700ph_tuner_attach,
+
+                               DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
+
+                               .size_of_priv = sizeof(struct
+                                               dib0700_adapter_state),
+                       },
+               },
+
+               .num_device_descs = 3,
+               .devices = {
+                       {   "Terratec Cinergy HT USB XE",
+                               { &dib0700_usb_id_table[27], NULL },
+                               { NULL },
+                       },
+                       {   "Pinnacle Expresscard 320cx",
+                               { &dib0700_usb_id_table[28], NULL },
+                               { NULL },
+                       },
+                       {   "Terratec Cinergy HT Express",
+                               { &dib0700_usb_id_table[32], NULL },
+                               { NULL },
+                       },
+               },
+               .rc_interval      = DEFAULT_RC_INTERVAL,
+               .rc_key_map       = dib0700_rc_keys,
+               .rc_key_map_size  = ARRAY_SIZE(dib0700_rc_keys),
+               .rc_query         = dib0700_rc_query
        },
 };
 
index 043cadae08594f62ed1dead95e77439e728a3a2d..eeef50bff4f9b39c41e984ffd52a76ccb2720ddf 100644 (file)
@@ -14,6 +14,8 @@
  */
 #include "dibusb.h"
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 static int dib3000mb_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
 {
        struct dvb_usb_adapter *adap = fe->dvb->priv;
@@ -107,10 +109,14 @@ static struct dvb_usb_device_properties artec_t1_usb2_properties;
 static int dibusb_probe(struct usb_interface *intf,
                const struct usb_device_id *id)
 {
-       if (dvb_usb_device_init(intf,&dibusb1_1_properties,THIS_MODULE,NULL) == 0 ||
-               dvb_usb_device_init(intf,&dibusb1_1_an2235_properties,THIS_MODULE,NULL) == 0 ||
-               dvb_usb_device_init(intf,&dibusb2_0b_properties,THIS_MODULE,NULL) == 0 ||
-               dvb_usb_device_init(intf,&artec_t1_usb2_properties,THIS_MODULE,NULL) == 0)
+       if (0 == dvb_usb_device_init(intf, &dibusb1_1_properties,
+                                    THIS_MODULE, NULL, adapter_nr) ||
+           0 == dvb_usb_device_init(intf, &dibusb1_1_an2235_properties,
+                                    THIS_MODULE, NULL, adapter_nr) ||
+           0 == dvb_usb_device_init(intf, &dibusb2_0b_properties,
+                                    THIS_MODULE, NULL, adapter_nr) ||
+           0 == dvb_usb_device_init(intf, &artec_t1_usb2_properties,
+                                    THIS_MODULE, NULL, adapter_nr))
                return 0;
 
        return -EINVAL;
index e7ea3e753d6da2eb287af30cb9b245214352b20b..059cec95531826aa8128bc3bcdc6e57e371ee6e7 100644 (file)
  */
 #include "dibusb.h"
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 /* USB Driver stuff */
 static struct dvb_usb_device_properties dibusb_mc_properties;
 
 static int dibusb_mc_probe(struct usb_interface *intf,
                const struct usb_device_id *id)
 {
-       return dvb_usb_device_init(intf,&dibusb_mc_properties,THIS_MODULE,NULL);
+       return dvb_usb_device_init(intf, &dibusb_mc_properties, THIS_MODULE,
+                                  NULL, adapter_nr);
 }
 
 /* do not change the order of the ID table */
index 3acbda4aa27e1e550cb548e4f2972c050c8d4ada..b545cf3eab2e5c0a63ac1f48ca67fca3cf8eae21 100644 (file)
@@ -20,6 +20,9 @@
 static int dvb_usb_digitv_debug;
 module_param_named(debug,dvb_usb_digitv_debug, int, 0644);
 MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 #define deb_rc(args...)   dprintk(dvb_usb_digitv_debug,0x01,args)
 
 static int digitv_ctrl_msg(struct dvb_usb_device *d,
@@ -256,8 +259,9 @@ static int digitv_probe(struct usb_interface *intf,
                const struct usb_device_id *id)
 {
        struct dvb_usb_device *d;
-       int ret;
-       if ((ret = dvb_usb_device_init(intf,&digitv_properties,THIS_MODULE,&d)) == 0) {
+       int ret = dvb_usb_device_init(intf, &digitv_properties, THIS_MODULE, &d,
+                                     adapter_nr);
+       if (ret == 0) {
                u8 b[4] = { 0 };
 
                if (d != NULL) { /* do that only when the firmware is loaded */
index d86cf9bee91c23fdd8ec0b528994b51b95cd6f7b..81a6cbf601603a6e8b2313921291350b131bd1ae 100644 (file)
@@ -18,6 +18,8 @@ int dvb_usb_dtt200u_debug;
 module_param_named(debug,dvb_usb_dtt200u_debug, int, 0644);
 MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2 (or-able))." DVB_USB_DEBUG_STATUS);
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 static int dtt200u_power_ctrl(struct dvb_usb_device *d, int onoff)
 {
        u8 b = SET_INIT;
@@ -101,11 +103,16 @@ static struct dvb_usb_device_properties wt220u_miglia_properties;
 static int dtt200u_usb_probe(struct usb_interface *intf,
                const struct usb_device_id *id)
 {
-       if (dvb_usb_device_init(intf,&dtt200u_properties,THIS_MODULE,NULL) == 0 ||
-               dvb_usb_device_init(intf,&wt220u_properties,THIS_MODULE,NULL) == 0 ||
-               dvb_usb_device_init(intf,&wt220u_fc_properties,THIS_MODULE,NULL) == 0 ||
-               dvb_usb_device_init(intf,&wt220u_zl0353_properties,THIS_MODULE,NULL) == 0 ||
-               dvb_usb_device_init(intf,&wt220u_miglia_properties,THIS_MODULE,NULL) == 0)
+       if (0 == dvb_usb_device_init(intf, &dtt200u_properties,
+                                    THIS_MODULE, NULL, adapter_nr) ||
+           0 == dvb_usb_device_init(intf, &wt220u_properties,
+                                    THIS_MODULE, NULL, adapter_nr) ||
+           0 == dvb_usb_device_init(intf, &wt220u_fc_properties,
+                                    THIS_MODULE, NULL, adapter_nr) ||
+           0 == dvb_usb_device_init(intf, &wt220u_zl0353_properties,
+                                    THIS_MODULE, NULL, adapter_nr) ||
+           0 == dvb_usb_device_init(intf, &wt220u_miglia_properties,
+                                    THIS_MODULE, NULL, adapter_nr))
                return 0;
 
        return -ENODEV;
index 35ab68f6dcf6346e5748e775c95a722c478295e5..6b7b2a89242e797d9bbe0c959ddef57515a25a8f 100644 (file)
@@ -40,7 +40,8 @@ extern int dvb_usb_adapter_stream_exit(struct dvb_usb_adapter *adap);
 extern int dvb_usb_i2c_init(struct dvb_usb_device *);
 extern int dvb_usb_i2c_exit(struct dvb_usb_device *);
 
-extern int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap);
+extern int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap,
+                                   short *adapter_nums);
 extern int dvb_usb_adapter_dvb_exit(struct dvb_usb_adapter *adap);
 extern int dvb_usb_adapter_frontend_init(struct dvb_usb_adapter *adap);
 extern int dvb_usb_adapter_frontend_exit(struct dvb_usb_adapter *adap);
index 4561a672da924c70ab9ba121c056b4591b1f55e4..ce8cd0c5d83120b173ad5fa4950d1f43a8c0a585 100644 (file)
@@ -77,12 +77,13 @@ static int dvb_usb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
        return dvb_usb_ctrl_feed(dvbdmxfeed,0);
 }
 
-int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap)
+int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap, short *adapter_nums)
 {
-       int ret;
+       int ret = dvb_register_adapter(&adap->dvb_adap, adap->dev->desc->name,
+                                      adap->dev->owner, &adap->dev->udev->dev,
+                                      adapter_nums);
 
-       if ((ret = dvb_register_adapter(&adap->dvb_adap, adap->dev->desc->name,
-                       adap->dev->owner, &adap->dev->udev->dev)) < 0) {
+       if (ret < 0) {
                deb_info("dvb_register_adapter failed: error %d", ret);
                goto err;
        }
index aa4844ef875e02798c6f761423a0f33d9aeffd79..34245d1b7dd92a151233de0e266466e1df4b06ae 100644 (file)
 #define USB_VID_MSI                            0x0db0
 #define USB_VID_OPERA1                         0x695c
 #define USB_VID_PINNACLE                       0x2304
+#define USB_VID_TECHNOTREND                    0x0b48
 #define USB_VID_TERRATEC                       0x0ccd
 #define USB_VID_VISIONPLUS                     0x13d3
 #define USB_VID_TWINHAN                                0x1822
 #define USB_VID_ULTIMA_ELECTRONIC              0x05d8
 #define USB_VID_UNIWILL                                0x1584
 #define USB_VID_WIDEVIEW                       0x14aa
-/* dom : pour gigabyte u7000 */
 #define USB_VID_GIGABYTE                       0x1044
+#define USB_VID_YUAN                           0x1164
 
 
 /* Product IDs */
 #define USB_PID_AVERMEDIA_EXPRESS                      0xb568
 #define USB_PID_AVERMEDIA_VOLAR                                0xa807
 #define USB_PID_AVERMEDIA_VOLAR_2                      0xb808
+#define USB_PID_TECHNOTREND_CONNECT_S2400               0x3006
 #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY       0x005a
+#define USB_PID_TERRATEC_CINERGY_HT_USB_XE             0x0058
+#define USB_PID_TERRATEC_CINERGY_HT_EXPRESS            0x0060
+#define USB_PID_TERRATEC_CINERGY_T_XXS                 0x0078
+#define USB_PID_PINNACLE_EXPRESSCARD_320CX             0x022e
 #define USB_PID_PINNACLE_PCTV2000E                     0x022c
 #define USB_PID_PINNACLE_PCTV_DVB_T_FLASH              0x0228
 #define USB_PID_PINNACLE_PCTV_DUAL_DIVERSITY_DVB_T     0x0229
+#define USB_PID_PINNACLE_PCTV72E                       0x0236
+#define USB_PID_PINNACLE_PCTV73E                       0x0237
 #define USB_PID_PCTV_200E                              0x020e
 #define USB_PID_PCTV_400E                              0x020f
 #define USB_PID_PCTV_450E                              0x0222
 #define USB_PID_WINFAST_DTV_DONGLE_COLD                        0x6025
 #define USB_PID_WINFAST_DTV_DONGLE_WARM                        0x6026
 #define USB_PID_WINFAST_DTV_DONGLE_STK7700P            0x6f00
+#define USB_PID_WINFAST_DTV_DONGLE_STK7700P_2          0x6f01
 #define USB_PID_GENPIX_8PSK_REV_1_COLD                 0x0200
 #define USB_PID_GENPIX_8PSK_REV_1_WARM                 0x0201
 #define USB_PID_GENPIX_8PSK_REV_2                      0x0202
 #define USB_PID_OPERA1_WARM                            0x3829
 #define USB_PID_LIFEVIEW_TV_WALKER_TWIN_COLD           0x0514
 #define USB_PID_LIFEVIEW_TV_WALKER_TWIN_WARM           0x0513
-/* dom pour gigabyte u7000 */
 #define USB_PID_GIGABYTE_U7000                         0x7001
 #define USB_PID_ASUS_U3000                             0x171f
 #define USB_PID_ASUS_U3100                             0x173f
+#define USB_PID_YUAN_EC372S                            0x1edc
 
 #endif
index cdd717c3fe45ac79c099a49397d529cf0ffdda5c..e331db8c77b210125c72f4cb475e4c71c9ca8798 100644 (file)
@@ -26,7 +26,7 @@ static int dvb_usb_force_pid_filter_usage;
 module_param_named(force_pid_filter_usage, dvb_usb_force_pid_filter_usage, int, 0444);
 MODULE_PARM_DESC(force_pid_filter_usage, "force all dvb-usb-devices to use a PID filter, if any (default: 0).");
 
-static int dvb_usb_adapter_init(struct dvb_usb_device *d)
+static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs)
 {
        struct dvb_usb_adapter *adap;
        int ret,n;
@@ -72,7 +72,7 @@ static int dvb_usb_adapter_init(struct dvb_usb_device *d)
                }
 
                if ((ret = dvb_usb_adapter_stream_init(adap)) ||
-                       (ret = dvb_usb_adapter_dvb_init(adap)) ||
+                       (ret = dvb_usb_adapter_dvb_init(adap, adapter_nrs)) ||
                        (ret = dvb_usb_adapter_frontend_init(adap))) {
                        return ret;
                }
@@ -122,7 +122,7 @@ static int dvb_usb_exit(struct dvb_usb_device *d)
        return 0;
 }
 
-static int dvb_usb_init(struct dvb_usb_device *d)
+static int dvb_usb_init(struct dvb_usb_device *d, short *adapter_nums)
 {
        int ret = 0;
 
@@ -143,7 +143,7 @@ static int dvb_usb_init(struct dvb_usb_device *d)
        dvb_usb_device_power_ctrl(d, 1);
 
        if ((ret = dvb_usb_i2c_init(d)) ||
-               (ret = dvb_usb_adapter_init(d))) {
+               (ret = dvb_usb_adapter_init(d, adapter_nums))) {
                dvb_usb_exit(d);
                return ret;
        }
@@ -213,8 +213,10 @@ int dvb_usb_device_power_ctrl(struct dvb_usb_device *d, int onoff)
 /*
  * USB
  */
-int dvb_usb_device_init(struct usb_interface *intf, struct dvb_usb_device_properties
-               *props, struct module *owner,struct dvb_usb_device **du)
+int dvb_usb_device_init(struct usb_interface *intf,
+                       struct dvb_usb_device_properties *props,
+                       struct module *owner, struct dvb_usb_device **du,
+                       short *adapter_nums)
 {
        struct usb_device *udev = interface_to_usbdev(intf);
        struct dvb_usb_device *d = NULL;
@@ -254,7 +256,7 @@ int dvb_usb_device_init(struct usb_interface *intf, struct dvb_usb_device_proper
        if (du != NULL)
                *du = d;
 
-       ret = dvb_usb_init(d);
+       ret = dvb_usb_init(d, adapter_nums);
 
        if (ret == 0)
                info("%s successfully initialized and connected.",desc->name);
index d1b3c7b81fffebad0da13a96406903d276db1d01..b1de0f7e26e8dce984c41bf6388ed6d2e932bd5d 100644 (file)
@@ -372,7 +372,10 @@ struct dvb_usb_device {
        void *priv;
 };
 
-extern int dvb_usb_device_init(struct usb_interface *, struct dvb_usb_device_properties *, struct module *, struct dvb_usb_device **);
+extern int dvb_usb_device_init(struct usb_interface *,
+                              struct dvb_usb_device_properties *,
+                              struct module *, struct dvb_usb_device **,
+                              short *adapter_nums);
 extern void dvb_usb_device_exit(struct usb_interface *);
 
 /* the generic read/write method for device control */
index 6b99d9f4d5b35846892f023998d903aafdc8caa5..0a8ac64a4e33a6a345cd6eea538b7397a33c6536 100644 (file)
@@ -16,6 +16,8 @@ static int dvb_usb_gl861_debug;
 module_param_named(debug,dvb_usb_gl861_debug, int, 0644);
 MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 static int gl861_i2c_msg(struct dvb_usb_device *d, u8 addr,
                         u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
 {
@@ -140,7 +142,9 @@ static int gl861_probe(struct usb_interface *intf,
        if (intf->num_altsetting < 2)
                return -ENODEV;
 
-       if ((ret = dvb_usb_device_init(intf, &gl861_properties, THIS_MODULE, &d)) == 0) {
+       ret = dvb_usb_device_init(intf, &gl861_properties, THIS_MODULE, &d,
+                                 adapter_nr);
+       if (ret == 0) {
                alt = usb_altnum_to_altsetting(intf, 0);
 
                if (alt == NULL) {
index e37142d9271a83aa0f1b3e3575e21dc3c5a8a6f3..262a858c30684e28e0798034e776ed9138f3f255 100644 (file)
@@ -152,7 +152,7 @@ static int gp8psk_fe_send_diseqc_msg (struct dvb_frontend* fe,
 {
        struct gp8psk_fe_state *st = fe->demodulator_priv;
 
-       deb_fe("%s\n",__FUNCTION__);
+       deb_fe("%s\n",__func__);
 
        if (gp8psk_usb_out_op(st->d,SEND_DISEQC_COMMAND, m->msg[0], 0,
                        m->msg, m->msg_len)) {
@@ -167,7 +167,7 @@ static int gp8psk_fe_send_diseqc_burst (struct dvb_frontend* fe,
        struct gp8psk_fe_state *st = fe->demodulator_priv;
        u8 cmd;
 
-       deb_fe("%s\n",__FUNCTION__);
+       deb_fe("%s\n",__func__);
 
        /* These commands are certainly wrong */
        cmd = (burst == SEC_MINI_A) ? 0x00 : 0x01;
index 83e8535014c6d092fc08f5c91e0963f31408dca2..9a942afaf0af8d1a3c16cf9e5681656d3c1eca72 100644 (file)
@@ -22,6 +22,8 @@ int dvb_usb_gp8psk_debug;
 module_param_named(debug,dvb_usb_gp8psk_debug, int, 0644);
 MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS);
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen)
 {
        int ret = 0,try = 0;
@@ -190,7 +192,8 @@ static int gp8psk_usb_probe(struct usb_interface *intf,
 {
        int ret;
        struct usb_device *udev = interface_to_usbdev(intf);
-       ret =  dvb_usb_device_init(intf,&gp8psk_properties,THIS_MODULE,NULL);
+       ret = dvb_usb_device_init(intf, &gp8psk_properties,
+                                 THIS_MODULE, NULL, adapter_nr);
        if (ret == 0) {
                info("found Genpix USB device pID = %x (hex)",
                        le16_to_cpu(udev->descriptor.idProduct));
index a956bc503a4c7aa6480e06c21a6900c6328cee60..a12e6f784fdae92aade0f2b08040f93948206155 100644 (file)
@@ -22,6 +22,8 @@ static int dvb_usb_m920x_debug;
 module_param_named(debug,dvb_usb_m920x_debug, int, 0644);
 MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 static int m920x_set_filter(struct dvb_usb_device *d, int type, int idx, int pid);
 
 static inline int m920x_read(struct usb_device *udev, u8 request, u16 value,
@@ -477,7 +479,7 @@ static struct qt1010_config m920x_qt1010_config = {
 /* Callbacks for DVB USB */
 static int m920x_mt352_frontend_attach(struct dvb_usb_adapter *adap)
 {
-       deb("%s\n",__FUNCTION__);
+       deb("%s\n",__func__);
 
        if ((adap->fe = dvb_attach(mt352_attach,
                                   &m920x_mt352_config,
@@ -489,7 +491,7 @@ static int m920x_mt352_frontend_attach(struct dvb_usb_adapter *adap)
 
 static int m920x_tda10046_08_frontend_attach(struct dvb_usb_adapter *adap)
 {
-       deb("%s\n",__FUNCTION__);
+       deb("%s\n",__func__);
 
        if ((adap->fe = dvb_attach(tda10046_attach,
                                   &m920x_tda10046_08_config,
@@ -501,7 +503,7 @@ static int m920x_tda10046_08_frontend_attach(struct dvb_usb_adapter *adap)
 
 static int m920x_tda10046_0b_frontend_attach(struct dvb_usb_adapter *adap)
 {
-       deb("%s\n",__FUNCTION__);
+       deb("%s\n",__func__);
 
        if ((adap->fe = dvb_attach(tda10046_attach,
                                   &m920x_tda10046_0b_config,
@@ -513,7 +515,7 @@ static int m920x_tda10046_0b_frontend_attach(struct dvb_usb_adapter *adap)
 
 static int m920x_qt1010_tuner_attach(struct dvb_usb_adapter *adap)
 {
-       deb("%s\n",__FUNCTION__);
+       deb("%s\n",__func__);
 
        if (dvb_attach(qt1010_attach, adap->fe, &adap->dev->i2c_adap, &m920x_qt1010_config) == NULL)
                return -ENODEV;
@@ -523,7 +525,7 @@ static int m920x_qt1010_tuner_attach(struct dvb_usb_adapter *adap)
 
 static int m920x_tda8275_60_tuner_attach(struct dvb_usb_adapter *adap)
 {
-       deb("%s\n",__FUNCTION__);
+       deb("%s\n",__func__);
 
        if (dvb_attach(tda827x_attach, adap->fe, 0x60, &adap->dev->i2c_adap, NULL) == NULL)
                return -ENODEV;
@@ -533,7 +535,7 @@ static int m920x_tda8275_60_tuner_attach(struct dvb_usb_adapter *adap)
 
 static int m920x_tda8275_61_tuner_attach(struct dvb_usb_adapter *adap)
 {
-       deb("%s\n",__FUNCTION__);
+       deb("%s\n",__func__);
 
        if (dvb_attach(tda827x_attach, adap->fe, 0x61, &adap->dev->i2c_adap, NULL) == NULL)
                return -ENODEV;
@@ -618,27 +620,31 @@ static int m920x_probe(struct usb_interface *intf,
                 * multi-tuner device
                 */
 
-               if ((ret = dvb_usb_device_init(intf, &megasky_properties,
-                                              THIS_MODULE, &d)) == 0) {
+               ret = dvb_usb_device_init(intf, &megasky_properties,
+                                         THIS_MODULE, &d, adapter_nr);
+               if (ret == 0) {
                        rc_init_seq = megasky_rc_init;
                        goto found;
                }
 
-               if ((ret = dvb_usb_device_init(intf, &digivox_mini_ii_properties,
-                                              THIS_MODULE, &d)) == 0) {
+               ret = dvb_usb_device_init(intf, &digivox_mini_ii_properties,
+                                         THIS_MODULE, &d, adapter_nr);
+               if (ret == 0) {
                        /* No remote control, so no rc_init_seq */
                        goto found;
                }
 
                /* This configures both tuners on the TV Walker Twin */
-               if ((ret = dvb_usb_device_init(intf, &tvwalkertwin_properties,
-                                              THIS_MODULE, &d)) == 0) {
+               ret = dvb_usb_device_init(intf, &tvwalkertwin_properties,
+                                         THIS_MODULE, &d, adapter_nr);
+               if (ret == 0) {
                        rc_init_seq = tvwalkertwin_rc_init;
                        goto found;
                }
 
-               if ((ret = dvb_usb_device_init(intf, &dposh_properties,
-                                              THIS_MODULE, &d)) == 0) {
+               ret = dvb_usb_device_init(intf, &dposh_properties,
+                                         THIS_MODULE, &d, adapter_nr);
+               if (ret == 0) {
                        /* Remote controller not supported yet. */
                        goto found;
                }
index badc468170ea615aff5a0eaa2332cd6559db4f09..07fb843c7c2b22d35b4a977dd405e2b6d5e97ab7 100644 (file)
@@ -15,6 +15,8 @@ static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "set debugging level (1=rc,2=eeprom (|-able))." DVB_USB_DEBUG_STATUS);
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 #define deb_rc(args...) dprintk(debug,0x01,args)
 #define deb_ee(args...) dprintk(debug,0x02,args)
 
@@ -142,7 +144,8 @@ static struct dvb_usb_device_properties nova_t_properties;
 static int nova_t_probe(struct usb_interface *intf,
                const struct usb_device_id *id)
 {
-       return dvb_usb_device_init(intf,&nova_t_properties,THIS_MODULE,NULL);
+       return dvb_usb_device_init(intf, &nova_t_properties,
+                                  THIS_MODULE, NULL, adapter_nr);
 }
 
 /* do not change the order of the ID table */
index 302cc67407c397e17091bc729c078e9d63f54031..7e32d11f32b0fd6e4ddc41714d7dd3242bacc819 100644 (file)
@@ -46,6 +46,9 @@ MODULE_PARM_DESC(debug,
                 "set debugging level (1=info,xfer=2,pll=4,ts=8,err=16,rc=32,fw=64 (or-able))."
                 DVB_USB_DEBUG_STATUS);
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+
 static int opera1_xilinx_rw(struct usb_device *dev, u8 request, u16 value,
                            u8 * data, u16 len, int flags)
 {
@@ -243,7 +246,7 @@ static struct stv0299_config opera1_stv0299_config = {
        .mclk = 88000000UL,
        .invert = 1,
        .skip_reinit = 0,
-       .lock_output = STV0229_LOCKOUTPUT_0,
+       .lock_output = STV0299_LOCKOUTPUT_0,
        .volt13_op0_op1 = STV0299_VOLT13_OP0,
        .inittab = opera1_inittab,
        .set_symbol_rate = opera1_stv0299_set_symbol_rate,
@@ -548,7 +551,8 @@ static int opera1_probe(struct usb_interface *intf,
                return -EINVAL;
        }
 
-       if (dvb_usb_device_init(intf, &opera1_properties, THIS_MODULE, NULL) != 0)
+       if (0 != dvb_usb_device_init(intf, &opera1_properties,
+                                    THIS_MODULE, NULL, adapter_nr))
                return -EINVAL;
        return 0;
 }
index 3b9da9c25c6e8d15dc48925b8cd399533453fc6e..20ca9d9ee99b23aedb60d3ecf3e892c5d9ae71a5 100644 (file)
@@ -37,6 +37,8 @@ static int dvb_usb_ttusb2_debug;
 module_param_named(debug,dvb_usb_ttusb2_debug, int, 0644);
 MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))." DVB_USB_DEBUG_STATUS);
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 struct ttusb2_state {
        u8 id;
 };
@@ -145,6 +147,7 @@ static struct tda10086_config tda10086_config = {
        .demod_address = 0x0e,
        .invert = 0,
        .diseqc_tone = 1,
+       .xtal_freq = TDA10086_XTAL_16M,
 };
 
 static int ttusb2_frontend_attach(struct dvb_usb_adapter *adap)
@@ -176,17 +179,25 @@ static int ttusb2_tuner_attach(struct dvb_usb_adapter *adap)
 
 /* DVB USB Driver stuff */
 static struct dvb_usb_device_properties ttusb2_properties;
+static struct dvb_usb_device_properties ttusb2_properties_s2400;
 
 static int ttusb2_probe(struct usb_interface *intf,
                const struct usb_device_id *id)
 {
-       return dvb_usb_device_init(intf,&ttusb2_properties,THIS_MODULE,NULL);
+       if (0 == dvb_usb_device_init(intf, &ttusb2_properties,
+                                    THIS_MODULE, NULL, adapter_nr) ||
+           0 == dvb_usb_device_init(intf, &ttusb2_properties_s2400,
+                                    THIS_MODULE, NULL, adapter_nr))
+               return 0;
+       return -ENODEV;
 }
 
 static struct usb_device_id ttusb2_table [] = {
-               { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_400E) },
-               { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_450E) },
-               {}              /* Terminating entry */
+       { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_400E) },
+       { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_450E) },
+       { USB_DEVICE(USB_VID_TECHNOTREND,
+               USB_PID_TECHNOTREND_CONNECT_S2400) },
+       {}              /* Terminating entry */
 };
 MODULE_DEVICE_TABLE (usb, ttusb2_table);
 
@@ -242,6 +253,54 @@ static struct dvb_usb_device_properties ttusb2_properties = {
        }
 };
 
+static struct dvb_usb_device_properties ttusb2_properties_s2400 = {
+       .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+       .usb_ctrl = CYPRESS_FX2,
+       .firmware = "dvb-usb-tt-s2400-01.fw",
+
+       .size_of_priv = sizeof(struct ttusb2_state),
+
+       .num_adapters = 1,
+       .adapter = {
+               {
+                       .streaming_ctrl   = NULL,
+
+                       .frontend_attach  = ttusb2_frontend_attach,
+                       .tuner_attach     = ttusb2_tuner_attach,
+
+                       /* parameter for the MPEG2-data transfer */
+                       .stream = {
+                               .type = USB_ISOC,
+                               .count = 5,
+                               .endpoint = 0x02,
+                               .u = {
+                                       .isoc = {
+                                               .framesperurb = 4,
+                                               .framesize = 940,
+                                               .interval = 1,
+                                       }
+                               }
+                       }
+               }
+       },
+
+       .power_ctrl       = ttusb2_power_ctrl,
+       .identify_state   = ttusb2_identify_state,
+
+       .i2c_algo         = &ttusb2_i2c_algo,
+
+       .generic_bulk_ctrl_endpoint = 0x01,
+
+       .num_device_descs = 1,
+       .devices = {
+               {   "Technotrend TT-connect S-2400",
+                       { &ttusb2_table[2], NULL },
+                       { NULL },
+               },
+       }
+};
+
 static struct usb_driver ttusb2_driver = {
        .name           = "dvb_usb_ttusb2",
        .probe          = ttusb2_probe,
index 0dcab3d4e2362bcfd5f1862a236aa56f4b94b920..9e7653bb3b660bc4c44985db551cf94e0f65ee5e 100644 (file)
@@ -13,6 +13,8 @@
 
 #include "mt352.h"
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 static int umt_mt352_demod_init(struct dvb_frontend *fe)
 {
        static u8 mt352_clock_config[] = { 0x89, 0xb8, 0x2d };
@@ -75,7 +77,8 @@ static struct dvb_usb_device_properties umt_properties;
 static int umt_probe(struct usb_interface *intf,
                const struct usb_device_id *id)
 {
-       if (dvb_usb_device_init(intf,&umt_properties,THIS_MODULE,NULL) == 0)
+       if (0 == dvb_usb_device_init(intf, &umt_properties,
+                                    THIS_MODULE, NULL, adapter_nr))
                return 0;
        return -EINVAL;
 }
index c3fdc7cd094e33f41c4e2c34f4ec7b565233d2e6..ccc7e445266450dc41efd1313396b53c762db46d 100644 (file)
@@ -67,7 +67,7 @@ static int vp702x_fe_read_status(struct dvb_frontend* fe, fe_status_t *status)
 {
        struct vp702x_fe_state *st = fe->demodulator_priv;
        vp702x_fe_refresh_state(st);
-       deb_fe("%s\n",__FUNCTION__);
+       deb_fe("%s\n",__func__);
 
        if (st->lock == 0)
                *status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_SIGNAL | FE_HAS_CARRIER;
@@ -121,7 +121,7 @@ static int vp702x_fe_read_snr(struct dvb_frontend* fe, u16 *snr)
 
 static int vp702x_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
 {
-       deb_fe("%s\n",__FUNCTION__);
+       deb_fe("%s\n",__func__);
        tune->min_delay_ms = 2000;
        return 0;
 }
@@ -183,21 +183,21 @@ static int vp702x_fe_set_frontend(struct dvb_frontend* fe,
 static int vp702x_fe_init(struct dvb_frontend *fe)
 {
        struct vp702x_fe_state *st = fe->demodulator_priv;
-       deb_fe("%s\n",__FUNCTION__);
+       deb_fe("%s\n",__func__);
        vp702x_usb_in_op(st->d, RESET_TUNER, 0, 0, NULL, 0);
        return 0;
 }
 
 static int vp702x_fe_sleep(struct dvb_frontend *fe)
 {
-       deb_fe("%s\n",__FUNCTION__);
+       deb_fe("%s\n",__func__);
        return 0;
 }
 
 static int vp702x_fe_get_frontend(struct dvb_frontend* fe,
                                  struct dvb_frontend_parameters *fep)
 {
-       deb_fe("%s\n",__FUNCTION__);
+       deb_fe("%s\n",__func__);
        return 0;
 }
 
@@ -208,7 +208,7 @@ static int vp702x_fe_send_diseqc_msg (struct dvb_frontend* fe,
        u8 cmd[8],ibuf[10];
        memset(cmd,0,8);
 
-       deb_fe("%s\n",__FUNCTION__);
+       deb_fe("%s\n",__func__);
 
        if (m->msg_len > 4)
                return -EINVAL;
@@ -230,7 +230,7 @@ static int vp702x_fe_send_diseqc_msg (struct dvb_frontend* fe,
 
 static int vp702x_fe_send_diseqc_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
 {
-       deb_fe("%s\n",__FUNCTION__);
+       deb_fe("%s\n",__func__);
        return 0;
 }
 
@@ -238,7 +238,7 @@ static int vp702x_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
 {
        struct vp702x_fe_state *st = fe->demodulator_priv;
        u8 ibuf[10];
-       deb_fe("%s\n",__FUNCTION__);
+       deb_fe("%s\n",__func__);
 
        st->tone_mode = tone;
 
@@ -263,7 +263,7 @@ static int vp702x_fe_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t
 {
        struct vp702x_fe_state *st = fe->demodulator_priv;
        u8 ibuf[10];
-       deb_fe("%s\n",__FUNCTION__);
+       deb_fe("%s\n",__func__);
 
        st->voltage = voltage;
 
index e553c139ac44947abbc4ad010564ec4ec8bdcb6d..986fff9a5ba81580c6a40bcbfb2bd13100b0dddb 100644 (file)
@@ -21,6 +21,8 @@ int dvb_usb_vp702x_debug;
 module_param_named(debug,dvb_usb_vp702x_debug, int, 0644);
 MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS);
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 struct vp702x_state {
        int pid_filter_count;
        int pid_filter_can_bypass;
@@ -238,7 +240,8 @@ static struct dvb_usb_device_properties vp702x_properties;
 static int vp702x_usb_probe(struct usb_interface *intf,
                const struct usb_device_id *id)
 {
-       return dvb_usb_device_init(intf,&vp702x_properties,THIS_MODULE,NULL);
+       return dvb_usb_device_init(intf, &vp702x_properties,
+                                  THIS_MODULE, NULL, adapter_nr);
 }
 
 static struct usb_device_id vp702x_usb_table [] = {
index c172babf59bbf5d850c41dcb2eacd083887ce4ce..acb345504e0da0cbd8d3c2d3541a1a5a092a6def 100644 (file)
@@ -18,6 +18,9 @@
 static int dvb_usb_vp7045_debug;
 module_param_named(debug,dvb_usb_vp7045_debug, int, 0644);
 MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS);
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 #define deb_info(args...) dprintk(dvb_usb_vp7045_debug,0x01,args)
 #define deb_xfer(args...) dprintk(dvb_usb_vp7045_debug,0x02,args)
 #define deb_rc(args...)   dprintk(dvb_usb_vp7045_debug,0x04,args)
@@ -219,7 +222,8 @@ static struct dvb_usb_device_properties vp7045_properties;
 static int vp7045_usb_probe(struct usb_interface *intf,
                const struct usb_device_id *id)
 {
-       return dvb_usb_device_init(intf,&vp7045_properties,THIS_MODULE,NULL);
+       return dvb_usb_device_init(intf, &vp7045_properties,
+                                  THIS_MODULE, NULL, adapter_nr);
 }
 
 static struct usb_device_id vp7045_usb_table [] = {
index 9ad86ce4a4e5b783e0d8627e2b30b0f816ef8245..68fab616f55dfa483d62f3d69cb3ad4c6f4ac5ad 100644 (file)
@@ -188,6 +188,14 @@ config DVB_DIB7000P
          A DVB-T tuner module. Designed for mobile usage. Say Y when you want
          to support this frontend.
 
+config DVB_TDA10048
+       tristate "Philips TDA10048HN based"
+       depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
+       select FW_LOADER
+       help
+         A DVB-T tuner module. Say Y when you want to support this frontend.
+
 comment "DVB-C (cable) frontends"
        depends on DVB_CORE
 
@@ -291,6 +299,14 @@ config DVB_S5H1409
          An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
          to support this frontend.
 
+config DVB_AU8522
+       tristate "Auvitek AU8522 based"
+       depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
+       help
+         An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
+         to support this frontend.
+
 comment "Tuners/PLL support"
        depends on DVB_CORE
 
@@ -369,6 +385,11 @@ config DVB_TUNER_XC5000
          This device is only used inside a SiP called togther with a
          demodulator for now.
 
+config DVB_TUNER_ITD1000
+       tristate "Integrant ITD1000 Zero IF tuner for DVB-S/DSS"
+       depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
+
 comment "Miscellaneous devices"
        depends on DVB_CORE
 
@@ -379,6 +400,13 @@ config DVB_LNBP21
        help
          An SEC control chip.
 
+config DVB_ISL6405
+       tristate "ISL6405 SEC controller"
+       depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
+       help
+         An SEC control chip.
+
 config DVB_ISL6421
        tristate "ISL6421 SEC controller"
        depends on DVB_CORE && I2C
index 16bd107ebd32d83a2c64da419a367f0351e37820..2f873fc0f6498e2aa52dfdcee0cb7b1f44d9c2c1 100644 (file)
@@ -38,6 +38,7 @@ obj-$(CONFIG_DVB_S5H1420) += s5h1420.o
 obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o
 obj-$(CONFIG_DVB_CX24123) += cx24123.o
 obj-$(CONFIG_DVB_LNBP21) += lnbp21.o
+obj-$(CONFIG_DVB_ISL6405) += isl6405.o
 obj-$(CONFIG_DVB_ISL6421) += isl6421.o
 obj-$(CONFIG_DVB_TDA10086) += tda10086.o
 obj-$(CONFIG_DVB_TDA826X) += tda826x.o
@@ -51,3 +52,6 @@ obj-$(CONFIG_DVB_TUA6100) += tua6100.o
 obj-$(CONFIG_DVB_TUNER_MT2131) += mt2131.o
 obj-$(CONFIG_DVB_S5H1409) += s5h1409.o
 obj-$(CONFIG_DVB_TUNER_XC5000) += xc5000.o
+obj-$(CONFIG_DVB_TUNER_ITD1000) += itd1000.o
+obj-$(CONFIG_DVB_AU8522) += au8522.o
+obj-$(CONFIG_DVB_TDA10048) += tda10048.o
diff --git a/drivers/media/dvb/frontends/au8522.c b/drivers/media/dvb/frontends/au8522.c
new file mode 100644 (file)
index 0000000..084a280
--- /dev/null
@@ -0,0 +1,692 @@
+/*
+    Auvitek AU8522 QAM/8VSB demodulator driver
+
+    Copyright (C) 2008 Steven Toth <stoth@hauppauge.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include "dvb_frontend.h"
+#include "dvb-pll.h"
+#include "au8522.h"
+
+struct au8522_state {
+
+       struct i2c_adapter *i2c;
+
+       /* configuration settings */
+       const struct au8522_config *config;
+
+       struct dvb_frontend frontend;
+
+       u32 current_frequency;
+       fe_modulation_t current_modulation;
+
+};
+
+static int debug;
+
+#define dprintk(arg...) do {           \
+       if (debug)                      \
+                printk(arg);           \
+       } while (0)
+
+/* 16 bit registers, 8 bit values */
+static int au8522_writereg(struct au8522_state *state, u16 reg, u8 data)
+{
+       int ret;
+       u8 buf [] = { reg >> 8, reg & 0xff, data };
+
+       struct i2c_msg msg = { .addr = state->config->demod_address,
+                              .flags = 0, .buf = buf, .len = 3 };
+
+       ret = i2c_transfer(state->i2c, &msg, 1);
+
+       if (ret != 1)
+               printk("%s: writereg error (reg == 0x%02x, val == 0x%04x, "
+                      "ret == %i)\n", __func__, reg, data, ret);
+
+       return (ret != 1) ? -1 : 0;
+}
+
+static u8 au8522_readreg(struct au8522_state *state, u16 reg)
+{
+       int ret;
+       u8 b0 [] = { reg >> 8, reg & 0xff };
+       u8 b1 [] = { 0 };
+
+       struct i2c_msg msg [] = {
+               { .addr = state->config->demod_address, .flags = 0,
+                 .buf = b0, .len = 2 },
+               { .addr = state->config->demod_address, .flags = I2C_M_RD,
+                 .buf = b1, .len = 1 } };
+
+       ret = i2c_transfer(state->i2c, msg, 2);
+
+       if (ret != 2)
+               printk(KERN_ERR "%s: readreg error (ret == %i)\n",
+                      __func__, ret);
+       return b1[0];
+}
+
+static int au8522_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+       struct au8522_state *state = fe->demodulator_priv;
+
+       dprintk("%s(%d)\n", __func__, enable);
+
+       if (enable)
+               return au8522_writereg(state, 0x106, 1);
+       else
+               return au8522_writereg(state, 0x106, 0);
+}
+
+struct mse2snr_tab {
+       u16 val;
+       u16 data;
+};
+
+/* VSB SNR lookup table */
+static struct mse2snr_tab vsb_mse2snr_tab[] = {
+       {   0, 270 },
+       {   2, 250 },
+       {   3, 240 },
+       {   5, 230 },
+       {   7, 220 },
+       {   9, 210 },
+       {  12, 200 },
+       {  13, 195 },
+       {  15, 190 },
+       {  17, 185 },
+       {  19, 180 },
+       {  21, 175 },
+       {  24, 170 },
+       {  27, 165 },
+       {  31, 160 },
+       {  32, 158 },
+       {  33, 156 },
+       {  36, 152 },
+       {  37, 150 },
+       {  39, 148 },
+       {  40, 146 },
+       {  41, 144 },
+       {  43, 142 },
+       {  44, 140 },
+       {  48, 135 },
+       {  50, 130 },
+       {  43, 142 },
+       {  53, 125 },
+       {  56, 120 },
+       { 256, 115 },
+};
+
+/* QAM64 SNR lookup table */
+static struct mse2snr_tab qam64_mse2snr_tab[] = {
+       {  15,   0 },
+       {  16, 290 },
+       {  17, 288 },
+       {  18, 286 },
+       {  19, 284 },
+       {  20, 282 },
+       {  21, 281 },
+       {  22, 279 },
+       {  23, 277 },
+       {  24, 275 },
+       {  25, 273 },
+       {  26, 271 },
+       {  27, 269 },
+       {  28, 268 },
+       {  29, 266 },
+       {  30, 264 },
+       {  31, 262 },
+       {  32, 260 },
+       {  33, 259 },
+       {  34, 258 },
+       {  35, 256 },
+       {  36, 255 },
+       {  37, 254 },
+       {  38, 252 },
+       {  39, 251 },
+       {  40, 250 },
+       {  41, 249 },
+       {  42, 248 },
+       {  43, 246 },
+       {  44, 245 },
+       {  45, 244 },
+       {  46, 242 },
+       {  47, 241 },
+       {  48, 240 },
+       {  50, 239 },
+       {  51, 238 },
+       {  53, 237 },
+       {  54, 236 },
+       {  56, 235 },
+       {  57, 234 },
+       {  59, 233 },
+       {  60, 232 },
+       {  62, 231 },
+       {  63, 230 },
+       {  65, 229 },
+       {  67, 228 },
+       {  68, 227 },
+       {  70, 226 },
+       {  71, 225 },
+       {  73, 224 },
+       {  74, 223 },
+       {  76, 222 },
+       {  78, 221 },
+       {  80, 220 },
+       {  82, 219 },
+       {  85, 218 },
+       {  88, 217 },
+       {  90, 216 },
+       {  92, 215 },
+       {  93, 214 },
+       {  94, 212 },
+       {  95, 211 },
+       {  97, 210 },
+       {  99, 209 },
+       { 101, 208 },
+       { 102, 207 },
+       { 104, 206 },
+       { 107, 205 },
+       { 111, 204 },
+       { 114, 203 },
+       { 118, 202 },
+       { 122, 201 },
+       { 125, 200 },
+       { 128, 199 },
+       { 130, 198 },
+       { 132, 197 },
+       { 256, 190 },
+};
+
+/* QAM256 SNR lookup table */
+static struct mse2snr_tab qam256_mse2snr_tab[] = {
+       {  16,   0 },
+       {  17, 400 },
+       {  18, 398 },
+       {  19, 396 },
+       {  20, 394 },
+       {  21, 392 },
+       {  22, 390 },
+       {  23, 388 },
+       {  24, 386 },
+       {  25, 384 },
+       {  26, 382 },
+       {  27, 380 },
+       {  28, 379 },
+       {  29, 378 },
+       {  30, 377 },
+       {  31, 376 },
+       {  32, 375 },
+       {  33, 374 },
+       {  34, 373 },
+       {  35, 372 },
+       {  36, 371 },
+       {  37, 370 },
+       {  38, 362 },
+       {  39, 354 },
+       {  40, 346 },
+       {  41, 338 },
+       {  42, 330 },
+       {  43, 328 },
+       {  44, 326 },
+       {  45, 324 },
+       {  46, 322 },
+       {  47, 320 },
+       {  48, 319 },
+       {  49, 318 },
+       {  50, 317 },
+       {  51, 316 },
+       {  52, 315 },
+       {  53, 314 },
+       {  54, 313 },
+       {  55, 312 },
+       {  56, 311 },
+       {  57, 310 },
+       {  58, 308 },
+       {  59, 306 },
+       {  60, 304 },
+       {  61, 302 },
+       {  62, 300 },
+       {  63, 298 },
+       {  65, 295 },
+       {  68, 294 },
+       {  70, 293 },
+       {  73, 292 },
+       {  76, 291 },
+       {  78, 290 },
+       {  79, 289 },
+       {  81, 288 },
+       {  82, 287 },
+       {  83, 286 },
+       {  84, 285 },
+       {  85, 284 },
+       {  86, 283 },
+       {  88, 282 },
+       {  89, 281 },
+       { 256, 280 },
+};
+
+static int au8522_mse2snr_lookup(struct mse2snr_tab *tab, int sz, int mse,
+                                u16 *snr)
+{
+       int i, ret = -EINVAL;
+       dprintk("%s()\n", __func__);
+
+       for (i = 0; i < sz; i++) {
+               if (mse < tab[i].val) {
+                       *snr = tab[i].data;
+                       ret = 0;
+                       break;
+               }
+       }
+       dprintk("%s() snr=%d\n", __func__, *snr);
+       return ret;
+}
+
+/* VSB Modulation table */
+static struct {
+       u16 reg;
+       u16 data;
+} VSB_mod_tab[] = {
+       { 0x8090, 0x84 },
+       { 0x4092, 0x11 },
+       { 0x2005, 0x00 },
+       { 0x8091, 0x80 },
+       { 0x80a3, 0x0c },
+       { 0x80a4, 0xe8 },
+       { 0x8081, 0xc4 },
+       { 0x80a5, 0x40 },
+       { 0x80a7, 0x40 },
+       { 0x80a6, 0x67 },
+       { 0x8262, 0x20 },
+       { 0x821c, 0x30 },
+       { 0x80d8, 0x1a },
+       { 0x8227, 0xa0 },
+       { 0x8121, 0xff },
+       { 0x80a8, 0xf0 },
+       { 0x80a9, 0x05 },
+       { 0x80aa, 0x77 },
+       { 0x80ab, 0xf0 },
+       { 0x80ac, 0x05 },
+       { 0x80ad, 0x77 },
+       { 0x80ae, 0x41 },
+       { 0x80af, 0x66 },
+       { 0x821b, 0xcc },
+       { 0x821d, 0x80 },
+       { 0x80b5, 0xfb },
+       { 0x80b6, 0x8e },
+       { 0x80b7, 0x39 },
+       { 0x80a4, 0xe8 },
+       { 0x8231, 0x13 },
+};
+
+/* QAM Modulation table */
+static struct {
+       u16 reg;
+       u16 data;
+} QAM_mod_tab[] = {
+       { 0x80a3, 0x09 },
+       { 0x80a4, 0x00 },
+       { 0x8081, 0xc4 },
+       { 0x80a5, 0x40 },
+       { 0x80b5, 0xfb },
+       { 0x80b6, 0x8e },
+       { 0x80b7, 0x39 },
+       { 0x80aa, 0x77 },
+       { 0x80ad, 0x77 },
+       { 0x80a6, 0x67 },
+       { 0x8262, 0x20 },
+       { 0x821c, 0x30 },
+       { 0x80b8, 0x3e },
+       { 0x80b9, 0xf0 },
+       { 0x80ba, 0x01 },
+       { 0x80bb, 0x18 },
+       { 0x80bc, 0x50 },
+       { 0x80bd, 0x00 },
+       { 0x80be, 0xea },
+       { 0x80bf, 0xef },
+       { 0x80c0, 0xfc },
+       { 0x80c1, 0xbd },
+       { 0x80c2, 0x1f },
+       { 0x80c3, 0xfc },
+       { 0x80c4, 0xdd },
+       { 0x80c5, 0xaf },
+       { 0x80c6, 0x00 },
+       { 0x80c7, 0x38 },
+       { 0x80c8, 0x30 },
+       { 0x80c9, 0x05 },
+       { 0x80ca, 0x4a },
+       { 0x80cb, 0xd0 },
+       { 0x80cc, 0x01 },
+       { 0x80cd, 0xd9 },
+       { 0x80ce, 0x6f },
+       { 0x80cf, 0xf9 },
+       { 0x80d0, 0x70 },
+       { 0x80d1, 0xdf },
+       { 0x80d2, 0xf7 },
+       { 0x80d3, 0xc2 },
+       { 0x80d4, 0xdf },
+       { 0x80d5, 0x02 },
+       { 0x80d6, 0x9a },
+       { 0x80d7, 0xd0 },
+       { 0x8250, 0x0d },
+       { 0x8251, 0xcd },
+       { 0x8252, 0xe0 },
+       { 0x8253, 0x05 },
+       { 0x8254, 0xa7 },
+       { 0x8255, 0xff },
+       { 0x8256, 0xed },
+       { 0x8257, 0x5b },
+       { 0x8258, 0xae },
+       { 0x8259, 0xe6 },
+       { 0x825a, 0x3d },
+       { 0x825b, 0x0f },
+       { 0x825c, 0x0d },
+       { 0x825d, 0xea },
+       { 0x825e, 0xf2 },
+       { 0x825f, 0x51 },
+       { 0x8260, 0xf5 },
+       { 0x8261, 0x06 },
+       { 0x821a, 0x00 },
+       { 0x8546, 0x40 },
+       { 0x8210, 0x26 },
+       { 0x8211, 0xf6 },
+       { 0x8212, 0x84 },
+       { 0x8213, 0x02 },
+       { 0x8502, 0x01 },
+       { 0x8121, 0x04 },
+       { 0x8122, 0x04 },
+       { 0x852e, 0x10 },
+       { 0x80a4, 0xca },
+       { 0x80a7, 0x40 },
+       { 0x8526, 0x01 },
+};
+
+static int au8522_enable_modulation(struct dvb_frontend *fe,
+                                   fe_modulation_t m)
+{
+       struct au8522_state *state = fe->demodulator_priv;
+       int i;
+
+       dprintk("%s(0x%08x)\n", __func__, m);
+
+       switch (m) {
+       case VSB_8:
+               dprintk("%s() VSB_8\n", __func__);
+               for (i = 0; i < ARRAY_SIZE(VSB_mod_tab); i++)
+                       au8522_writereg(state,
+                               VSB_mod_tab[i].reg,
+                               VSB_mod_tab[i].data);
+               break;
+       case QAM_64:
+       case QAM_256:
+               dprintk("%s() QAM 64/256\n", __func__);
+               for (i = 0; i < ARRAY_SIZE(QAM_mod_tab); i++)
+                       au8522_writereg(state,
+                               QAM_mod_tab[i].reg,
+                               QAM_mod_tab[i].data);
+               break;
+       default:
+               dprintk("%s() Invalid modulation\n", __func__);
+               return -EINVAL;
+       }
+
+       state->current_modulation = m;
+
+       return 0;
+}
+
+/* Talk to the demod, set the FEC, GUARD, QAM settings etc */
+static int au8522_set_frontend(struct dvb_frontend *fe,
+                              struct dvb_frontend_parameters *p)
+{
+       struct au8522_state *state = fe->demodulator_priv;
+
+       dprintk("%s(frequency=%d)\n", __func__, p->frequency);
+
+       state->current_frequency = p->frequency;
+
+       au8522_enable_modulation(fe, p->u.vsb.modulation);
+
+       /* Allow the demod to settle */
+       msleep(100);
+
+       if (fe->ops.tuner_ops.set_params) {
+               if (fe->ops.i2c_gate_ctrl)
+                       fe->ops.i2c_gate_ctrl(fe, 1);
+               fe->ops.tuner_ops.set_params(fe, p);
+               if (fe->ops.i2c_gate_ctrl)
+                       fe->ops.i2c_gate_ctrl(fe, 0);
+       }
+
+       return 0;
+}
+
+/* Reset the demod hardware and reset all of the configuration registers
+   to a default state. */
+static int au8522_init(struct dvb_frontend *fe)
+{
+       struct au8522_state *state = fe->demodulator_priv;
+       dprintk("%s()\n", __func__);
+
+       au8522_writereg(state, 0xa4, 1 << 5);
+
+       au8522_i2c_gate_ctrl(fe, 1);
+
+       return 0;
+}
+
+static int au8522_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+       struct au8522_state *state = fe->demodulator_priv;
+       u8 reg;
+       u32 tuner_status = 0;
+
+       *status = 0;
+
+       if (state->current_modulation == VSB_8) {
+               dprintk("%s() Checking VSB_8\n", __func__);
+               reg = au8522_readreg(state, 0x4088);
+               if (reg & 0x01)
+                       *status |= FE_HAS_VITERBI;
+               if (reg & 0x02)
+                       *status |= FE_HAS_LOCK | FE_HAS_SYNC;
+       } else {
+               dprintk("%s() Checking QAM\n", __func__);
+               reg = au8522_readreg(state, 0x4541);
+               if (reg & 0x80)
+                       *status |= FE_HAS_VITERBI;
+               if (reg & 0x20)
+                       *status |= FE_HAS_LOCK | FE_HAS_SYNC;
+       }
+
+       switch (state->config->status_mode) {
+       case AU8522_DEMODLOCKING:
+               dprintk("%s() DEMODLOCKING\n", __func__);
+               if (*status & FE_HAS_VITERBI)
+                       *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
+               break;
+       case AU8522_TUNERLOCKING:
+               /* Get the tuner status */
+               dprintk("%s() TUNERLOCKING\n", __func__);
+               if (fe->ops.tuner_ops.get_status) {
+                       if (fe->ops.i2c_gate_ctrl)
+                               fe->ops.i2c_gate_ctrl(fe, 1);
+
+                       fe->ops.tuner_ops.get_status(fe, &tuner_status);
+
+                       if (fe->ops.i2c_gate_ctrl)
+                               fe->ops.i2c_gate_ctrl(fe, 0);
+               }
+               if (tuner_status)
+                       *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
+               break;
+       }
+
+       dprintk("%s() status 0x%08x\n", __func__, *status);
+
+       return 0;
+}
+
+static int au8522_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+       struct au8522_state *state = fe->demodulator_priv;
+       int ret = -EINVAL;
+
+       dprintk("%s()\n", __func__);
+
+       if (state->current_modulation == QAM_256)
+               ret = au8522_mse2snr_lookup(qam256_mse2snr_tab,
+                                           ARRAY_SIZE(qam256_mse2snr_tab),
+                                           au8522_readreg(state, 0x4522),
+                                           snr);
+       else if (state->current_modulation == QAM_64)
+               ret = au8522_mse2snr_lookup(qam64_mse2snr_tab,
+                                           ARRAY_SIZE(qam64_mse2snr_tab),
+                                           au8522_readreg(state, 0x4522),
+                                           snr);
+       else /* VSB_8 */
+               ret = au8522_mse2snr_lookup(vsb_mse2snr_tab,
+                                           ARRAY_SIZE(vsb_mse2snr_tab),
+                                           au8522_readreg(state, 0x4311),
+                                           snr);
+
+       return ret;
+}
+
+static int au8522_read_signal_strength(struct dvb_frontend *fe,
+                                      u16 *signal_strength)
+{
+       return au8522_read_snr(fe, signal_strength);
+}
+
+static int au8522_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+       struct au8522_state *state = fe->demodulator_priv;
+
+       if (state->current_modulation == VSB_8)
+               *ucblocks = au8522_readreg(state, 0x4087);
+       else
+               *ucblocks = au8522_readreg(state, 0x4543);
+
+       return 0;
+}
+
+static int au8522_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+       return au8522_read_ucblocks(fe, ber);
+}
+
+static int au8522_get_frontend(struct dvb_frontend *fe,
+                               struct dvb_frontend_parameters *p)
+{
+       struct au8522_state *state = fe->demodulator_priv;
+
+       p->frequency = state->current_frequency;
+       p->u.vsb.modulation = state->current_modulation;
+
+       return 0;
+}
+
+static int au8522_get_tune_settings(struct dvb_frontend *fe,
+                                   struct dvb_frontend_tune_settings *tune)
+{
+       tune->min_delay_ms = 1000;
+       return 0;
+}
+
+static void au8522_release(struct dvb_frontend *fe)
+{
+       struct au8522_state *state = fe->demodulator_priv;
+       kfree(state);
+}
+
+static struct dvb_frontend_ops au8522_ops;
+
+struct dvb_frontend *au8522_attach(const struct au8522_config *config,
+                                  struct i2c_adapter *i2c)
+{
+       struct au8522_state *state = NULL;
+
+       /* allocate memory for the internal state */
+       state = kmalloc(sizeof(struct au8522_state), GFP_KERNEL);
+       if (state == NULL)
+               goto error;
+
+       /* setup the state */
+       state->config = config;
+       state->i2c = i2c;
+       /* create dvb_frontend */
+       memcpy(&state->frontend.ops, &au8522_ops,
+              sizeof(struct dvb_frontend_ops));
+       state->frontend.demodulator_priv = state;
+
+       if (au8522_init(&state->frontend) != 0) {
+               printk(KERN_ERR "%s: Failed to initialize correctly\n",
+                       __func__);
+               goto error;
+       }
+
+       /* Note: Leaving the I2C gate open here. */
+       au8522_i2c_gate_ctrl(&state->frontend, 1);
+
+       return &state->frontend;
+
+error:
+       kfree(state);
+       return NULL;
+}
+EXPORT_SYMBOL(au8522_attach);
+
+static struct dvb_frontend_ops au8522_ops = {
+
+       .info = {
+               .name                   = "Auvitek AU8522 QAM/8VSB Frontend",
+               .type                   = FE_ATSC,
+               .frequency_min          = 54000000,
+               .frequency_max          = 858000000,
+               .frequency_stepsize     = 62500,
+               .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
+       },
+
+       .init                 = au8522_init,
+       .i2c_gate_ctrl        = au8522_i2c_gate_ctrl,
+       .set_frontend         = au8522_set_frontend,
+       .get_frontend         = au8522_get_frontend,
+       .get_tune_settings    = au8522_get_tune_settings,
+       .read_status          = au8522_read_status,
+       .read_ber             = au8522_read_ber,
+       .read_signal_strength = au8522_read_signal_strength,
+       .read_snr             = au8522_read_snr,
+       .read_ucblocks        = au8522_read_ucblocks,
+       .release              = au8522_release,
+};
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Enable verbose debug messages");
+
+MODULE_DESCRIPTION("Auvitek AU8522 QAM-B/ATSC Demodulator driver");
+MODULE_AUTHOR("Steven Toth");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/au8522.h b/drivers/media/dvb/frontends/au8522.h
new file mode 100644 (file)
index 0000000..d7affa3
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+    Auvitek AU8522 QAM/8VSB demodulator driver
+
+    Copyright (C) 2008 Steven Toth <stoth@hauppauge.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef __AU8522_H__
+#define __AU8522_H__
+
+#include <linux/dvb/frontend.h>
+
+struct au8522_config {
+       /* the demodulator's i2c address */
+       u8 demod_address;
+
+       /* Return lock status based on tuner lock, or demod lock */
+#define AU8522_TUNERLOCKING 0
+#define AU8522_DEMODLOCKING 1
+       u8 status_mode;
+};
+
+#if defined(CONFIG_DVB_AU8522) ||                              \
+           (defined(CONFIG_DVB_AU8522_MODULE) && defined(MODULE))
+extern struct dvb_frontend *au8522_attach(const struct au8522_config *config,
+                                         struct i2c_adapter *i2c);
+#else
+static inline
+struct dvb_frontend *au8522_attach(const struct au8522_config *config,
+                                  struct i2c_adapter *i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return NULL;
+}
+#endif /* CONFIG_DVB_AU8522 */
+
+#endif /* __AU8522_H__ */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ */
index a913f49c062b98a46d4fdbf75b38b62b1590083f..d268e65e777d69acdc513e55f705a1064b0e05b8 100644 (file)
@@ -91,7 +91,7 @@ static int bcm3510_writebytes (struct bcm3510_state *state, u8 reg, u8 *buf, u8
        if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
 
                deb_info("%s: i2c write error (addr %02x, reg %02x, err == %i)\n",
-                       __FUNCTION__, state->config->demod_address, reg,  err);
+                       __func__, state->config->demod_address, reg,  err);
                return -EREMOTEIO;
        }
 
@@ -110,7 +110,7 @@ static int bcm3510_readbytes (struct bcm3510_state *state, u8 reg, u8 *buf, u8 l
 
        if ((err = i2c_transfer (state->i2c, msg, 2)) != 2) {
                deb_info("%s: i2c read error (addr %02x, reg %02x, err == %i)\n",
-                       __FUNCTION__, state->config->demod_address, reg,  err);
+                       __func__, state->config->demod_address, reg,  err);
                return -EREMOTEIO;
        }
        deb_i2c("i2c rd %02x: ",reg);
index 7e4f95e1734b4cf512731ca67b76f616c4a37f38..f4575c0cc446252c7a6413c1f45598a618a0113c 100644 (file)
@@ -41,7 +41,7 @@ extern struct dvb_frontend* bcm3510_attach(const struct bcm3510_config* config,
 static inline struct dvb_frontend* bcm3510_attach(const struct bcm3510_config* config,
                                                  struct i2c_adapter* i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_BCM3510
index d8f65738e5d2520e05d2f6508c317fcaadfb4e1f..5e431ebd089b44d997490af145a567608905732e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * bsbe1.h - ALPS BSBE1 tuner support (moved from av7110.c)
+ * bsbe1.h - ALPS BSBE1 tuner support
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
 #define BSBE1_H
 
 static u8 alps_bsbe1_inittab[] = {
-       0x01, 0x15,
-       0x02, 0x30,
-       0x03, 0x00,
+       0x01, 0x15,   /* XTAL = 4MHz, VCO = 352 MHz */
+       0x02, 0x30,   /* MCLK = 88 MHz */
+       0x03, 0x00,   /* ACR output 0 */
        0x04, 0x7d,   /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
-       0x05, 0x35,   /* I2CT = 0, SCLT = 1, SDAT = 1 */
-       0x06, 0x40,   /* DAC not used, set to high impendance mode */
-       0x07, 0x00,   /* DAC LSB */
+       0x05, 0x05,   /* I2CT = 0, SCLT = 1, SDAT = 1 */
+       0x06, 0x00,   /* DAC output 0 */
        0x08, 0x40,   /* DiSEqC off, LNB power on OP2/LOCK pin on */
        0x09, 0x00,   /* FIFO */
-       0x0c, 0x51,   /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
-       0x0d, 0x82,   /* DC offset compensation = ON, beta_agc1 = 2 */
-       0x0e, 0x23,   /* alpha_tmg = 2, beta_tmg = 3 */
-       0x10, 0x3f,   // AGC2  0x3d
-       0x11, 0x84,
-       0x12, 0xb9,
-       0x15, 0xc9,   // lock detector threshold
-       0x16, 0x00,
-       0x17, 0x00,
-       0x18, 0x00,
-       0x19, 0x00,
-       0x1a, 0x00,
-       0x1f, 0x50,
-       0x20, 0x00,
-       0x21, 0x00,
-       0x22, 0x00,
-       0x23, 0x00,
-       0x28, 0x00,  // out imp: normal  out type: parallel FEC mode:0
-       0x29, 0x1e,  // 1/2 threshold
-       0x2a, 0x14,  // 2/3 threshold
-       0x2b, 0x0f,  // 3/4 threshold
-       0x2c, 0x09,  // 5/6 threshold
-       0x2d, 0x05,  // 7/8 threshold
-       0x2e, 0x01,
-       0x31, 0x1f,  // test all FECs
-       0x32, 0x19,  // viterbi and synchro search
-       0x33, 0xfc,  // rs control
-       0x34, 0x93,  // error control
-       0x0f, 0x92,
+       0x0c, 0x51,   /* OP1/OP0 normal, val = 1 (LNB power on) */
+       0x0d, 0x82,   /* DC offset compensation = on, beta_agc1 = 2 */
+       0x0f, 0x92,   /* AGC1R */
+       0x10, 0x34,   /* AGC2O */
+       0x11, 0x84,   /* TLSR */
+       0x12, 0xb9,   /* CFD */
+       0x15, 0xc9,   /* lock detector threshold */
+       0x28, 0x00,   /* out imp: normal, type: parallel, FEC mode: QPSK */
+       0x33, 0xfc,   /* RS control */
+       0x34, 0x93,   /* count viterbi bit errors per 2E18 bytes */
        0xff, 0xff
 };
 
@@ -100,11 +80,11 @@ static int alps_bsbe1_tuner_set_params(struct dvb_frontend* fe, struct dvb_front
        if ((params->frequency < 950000) || (params->frequency > 2150000))
                return -EINVAL;
 
-       div = (params->frequency + (125 - 1)) / 125; // round correctly
+       div = params->frequency / 1000;
        data[0] = (div >> 8) & 0x7f;
        data[1] = div & 0xff;
-       data[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
-       data[3] = (params->frequency > 1530000) ? 0xE0 : 0xE4;
+       data[2] = 0x80 | ((div & 0x18000) >> 10) | 0x1;
+       data[3] = 0xe0;
 
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 1);
index e231cd84b3a16a49f4744b1c4b86e9962bcc11a5..45a6dfd8ebb596ea97195a8730cb93abd7a58aff 100644 (file)
@@ -133,7 +133,7 @@ static struct stv0299_config alps_bsru6_config = {
        .mclk = 88000000UL,
        .invert = 1,
        .skip_reinit = 0,
-       .lock_output = STV0229_LOCKOUTPUT_1,
+       .lock_output = STV0299_LOCKOUTPUT_1,
        .volt13_op0_op1 = STV0299_VOLT13_OP1,
        .min_delay_ms = 100,
        .set_symbol_rate = alps_bsru6_set_symbol_rate,
index 11a4968f18cb301be6b5df5676ac2d769ae50631..ace5cb17165daddf0e78c82a08aeaf215b5dec4d 100644 (file)
@@ -73,13 +73,13 @@ static int cx22700_writereg (struct cx22700_state* state, u8 reg, u8 data)
        u8 buf [] = { reg, data };
        struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        ret = i2c_transfer (state->i2c, &msg, 1);
 
        if (ret != 1)
                printk("%s: writereg error (reg == 0x%02x, val == 0x%02x, ret == %i)\n",
-                       __FUNCTION__, reg, data, ret);
+                       __func__, reg, data, ret);
 
        return (ret != 1) ? -1 : 0;
 }
@@ -92,7 +92,7 @@ static int cx22700_readreg (struct cx22700_state* state, u8 reg)
        struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 },
                           { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        ret = i2c_transfer (state->i2c, msg, 2);
 
@@ -105,7 +105,7 @@ static int cx22700_set_inversion (struct cx22700_state* state, int inversion)
 {
        u8 val;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        switch (inversion) {
        case INVERSION_AUTO:
@@ -127,7 +127,7 @@ static int cx22700_set_tps (struct cx22700_state *state, struct dvb_ofdm_paramet
        static const u8 fec_tab [6] = { 0, 1, 2, 0, 3, 4 };
        u8 val;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        if (p->code_rate_HP < FEC_1_2 || p->code_rate_HP > FEC_7_8)
                return -EINVAL;
@@ -191,7 +191,7 @@ static int cx22700_get_tps (struct cx22700_state* state, struct dvb_ofdm_paramet
                                                    FEC_5_6, FEC_7_8 };
        u8 val;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        if (!(cx22700_readreg(state, 0x07) & 0x20))  /*  tps valid? */
                return -EAGAIN;
index 7ac33690cdcc1144ba268e656f5f528fb3ca52d9..4757a930ca0515426130562ed94c0a7019abb854 100644 (file)
@@ -38,7 +38,7 @@ extern struct dvb_frontend* cx22700_attach(const struct cx22700_config* config,
 static inline struct dvb_frontend* cx22700_attach(const struct cx22700_config* config,
                                           struct i2c_adapter* i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_CX22700
index 1dc164d5488cd277b3059a19828f98655a7fa86a..cc1db4e371c360c6365ea3ae1b49b91f85d6ab48 100644 (file)
@@ -48,7 +48,7 @@ struct cx22702_state {
        u8 prevUCBlocks;
 };
 
-static int debug = 0;
+static int debug;
 #define dprintk        if (debug) printk
 
 /* Register values to initialise the demod */
@@ -90,7 +90,7 @@ static int cx22702_writereg (struct cx22702_state* state, u8 reg, u8 data)
 
        if (ret != 1)
                printk("%s: writereg error (reg == 0x%02x, val == 0x%02x, ret == %i)\n",
-                       __FUNCTION__, reg, data, ret);
+                       __func__, reg, data, ret);
 
        return (ret != 1) ? -1 : 0;
 }
@@ -108,7 +108,7 @@ static u8 cx22702_readreg (struct cx22702_state* state, u8 reg)
        ret = i2c_transfer(state->i2c, msg, 2);
 
        if (ret != 2)
-               printk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
+               printk("%s: readreg error (ret == %i)\n", __func__, ret);
 
        return b1[0];
 }
@@ -195,7 +195,7 @@ static int cx22702_get_tps (struct cx22702_state *state, struct dvb_ofdm_paramet
 static int cx22702_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
 {
        struct cx22702_state* state = fe->demodulator_priv;
-       dprintk ("%s(%d)\n", __FUNCTION__, enable);
+       dprintk ("%s(%d)\n", __func__, enable);
        if (enable)
                return cx22702_writereg (state, 0x0D, cx22702_readreg(state, 0x0D) & 0xfe);
        else
@@ -228,7 +228,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
                cx22702_writereg(state, 0x0C, cx22702_readreg(state, 0x0C) &0xcf );
                break;
        default:
-               dprintk ("%s: invalid bandwidth\n",__FUNCTION__);
+               dprintk ("%s: invalid bandwidth\n",__func__);
                return -EINVAL;
        }
 
@@ -250,7 +250,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
                cx22702_writereg(state, 0x0B, cx22702_readreg(state, 0x0B) & 0xfc );
                cx22702_writereg(state, 0x0C, (cx22702_readreg(state, 0x0C) & 0xBF) | 0x40 );
                cx22702_writereg(state, 0x00, 0x01); /* Begin aquisition */
-               dprintk("%s: Autodetecting\n",__FUNCTION__);
+               dprintk("%s: Autodetecting\n",__func__);
                return 0;
        }
 
@@ -261,7 +261,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
                case QAM_16: val = (val&0xe7)|0x08; break;
                case QAM_64: val = (val&0xe7)|0x10; break;
                default:
-                       dprintk ("%s: invalid constellation\n",__FUNCTION__);
+                       dprintk ("%s: invalid constellation\n",__func__);
                        return -EINVAL;
        }
        switch(p->u.ofdm.hierarchy_information) {
@@ -270,7 +270,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
                case    HIERARCHY_2: val = (val&0xf8)|2; break;
                case    HIERARCHY_4: val = (val&0xf8)|3; break;
                default:
-                       dprintk ("%s: invalid hierarchy\n",__FUNCTION__);
+                       dprintk ("%s: invalid hierarchy\n",__func__);
                        return -EINVAL;
        }
        cx22702_writereg (state, 0x06, val);
@@ -284,7 +284,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
                case FEC_5_6: val = (val&0xc7)|0x18; break;
                case FEC_7_8: val = (val&0xc7)|0x20; break;
                default:
-                       dprintk ("%s: invalid code_rate_HP\n",__FUNCTION__);
+                       dprintk ("%s: invalid code_rate_HP\n",__func__);
                        return -EINVAL;
        }
        switch(p->u.ofdm.code_rate_LP) {
@@ -295,7 +295,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
                case FEC_5_6: val = (val&0xf8)|3; break;
                case FEC_7_8: val = (val&0xf8)|4; break;
                default:
-                       dprintk ("%s: invalid code_rate_LP\n",__FUNCTION__);
+                       dprintk ("%s: invalid code_rate_LP\n",__func__);
                        return -EINVAL;
        }
        cx22702_writereg (state, 0x07, val);
@@ -307,14 +307,14 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
                case  GUARD_INTERVAL_1_8: val = (val&0xf3)|0x08; break;
                case  GUARD_INTERVAL_1_4: val = (val&0xf3)|0x0c; break;
                default:
-                       dprintk ("%s: invalid guard_interval\n",__FUNCTION__);
+                       dprintk ("%s: invalid guard_interval\n",__func__);
                        return -EINVAL;
        }
        switch(p->u.ofdm.transmission_mode) {
                case TRANSMISSION_MODE_2K: val = (val&0xfc); break;
                case TRANSMISSION_MODE_8K: val = (val&0xfc)|1; break;
                default:
-                       dprintk ("%s: invalid transmission_mode\n",__FUNCTION__);
+                       dprintk ("%s: invalid transmission_mode\n",__func__);
                        return -EINVAL;
        }
        cx22702_writereg(state, 0x08, val);
@@ -360,7 +360,7 @@ static int cx22702_read_status(struct dvb_frontend* fe, fe_status_t* status)
        reg23 = cx22702_readreg (state, 0x23);
 
        dprintk ("%s: status demod=0x%02x agc=0x%02x\n"
-               ,__FUNCTION__,reg0A,reg23);
+               ,__func__,reg0A,reg23);
 
        if(reg0A & 0x10) {
                *status |= FE_HAS_LOCK;
index 9cd64da6ee40a3b72b53396911ee7e4eab7eefd7..8af766a315520b882aa7c62adb1f0507d9b6fb69 100644 (file)
@@ -48,7 +48,7 @@ extern struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
 static inline struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
                                           struct i2c_adapter* i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_CX22702
index b03d8283c37d93233dc0d4722dc1fb60a0c9989d..87ae29db024fc2aea18122996b60ac29a879b24d 100644 (file)
@@ -121,7 +121,7 @@ static int cx24110_writereg (struct cx24110_state* state, int reg, int data)
 
        if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
                dprintk ("%s: writereg error (err == %i, reg == 0x%02x,"
-                        " data == 0x%02x)\n", __FUNCTION__, err, reg, data);
+                        " data == 0x%02x)\n", __func__, err, reg, data);
                return -EREMOTEIO;
        }
 
@@ -247,7 +247,7 @@ static int cx24110_set_symbolrate (struct cx24110_state* state, u32 srate)
        static const u32 bands[]={5000000UL,15000000UL,90999000UL/2};
        int i;
 
-       dprintk("cx24110 debug: entering %s(%d)\n",__FUNCTION__,srate);
+       dprintk("cx24110 debug: entering %s(%d)\n",__func__,srate);
        if (srate>90999000UL/2)
                srate=90999000UL/2;
        if (srate<500000)
@@ -358,7 +358,7 @@ static int cx24110_initfe(struct dvb_frontend* fe)
 /* fixme (low): error handling */
        int i;
 
-       dprintk("%s: init chip\n", __FUNCTION__);
+       dprintk("%s: init chip\n", __func__);
 
        for(i = 0; i < ARRAY_SIZE(cx24110_regdata); i++) {
                cx24110_writereg(state, cx24110_regdata[i].reg, cx24110_regdata[i].data);
index 0ca3af4db5136af0108d2fb4ecd5addd89ee8a5e..1792adb23c4d527d89bbb4bd859e01ea4732e854 100644 (file)
@@ -48,7 +48,7 @@ extern struct dvb_frontend* cx24110_attach(const struct cx24110_config* config,
 static inline struct dvb_frontend* cx24110_attach(const struct cx24110_config* config,
                                                  struct i2c_adapter* i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_CX24110
diff --git a/drivers/media/dvb/frontends/cx24113.h b/drivers/media/dvb/frontends/cx24113.h
new file mode 100644 (file)
index 0000000..5ab3dd1
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ *  Driver for Conexant CX24113/CX24128 Tuner (Satelite)
+ *
+ *  Copyright (C) 2007-8 Patrick Boettcher <pb@linuxtv.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.
+ *
+ *  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., 675 Mass Ave, Cambridge, MA 02139, USA.=
+ */
+
+#ifndef CX24113_H
+#define CX24113_H
+
+struct dvb_frontend;
+
+struct cx24113_config {
+       u8 i2c_addr; /* 0x14 or 0x54 */
+
+       u32 xtal_khz;
+};
+
+/* TODO: #if defined(CONFIG_DVB_TUNER_CX24113) || \
+ * (defined(CONFIG_DVB_TUNER_CX24113_MODULE) && defined(MODULE)) */
+
+static inline struct dvb_frontend *cx24113_attach(struct dvb_frontend *fe,
+       const struct cx24113_config *config, struct i2c_adapter *i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return NULL;
+}
+
+static inline void cx24113_agc_callback(struct dvb_frontend *fe)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+}
+
+#endif /* CX24113_H */
index d74fdbd63361f77e621d1cf1e6d7f4c1b8d5f322..7f68d78c6558eb962ba2b74dbae4b8537faa1825 100644 (file)
@@ -1,24 +1,26 @@
 /*
-    Conexant cx24123/cx24109 - DVB QPSK Satellite demod/tuner driver
-
-    Copyright (C) 2005 Steven Toth <stoth@hauppauge.com>
-
-    Support for KWorld DVB-S 100 by Vadim Catana <skystar@moldova.cc>
-
-    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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
+ *   Conexant cx24123/cx24109 - DVB QPSK Satellite demod/tuner driver
+ *
+ *   Copyright (C) 2005 Steven Toth <stoth@hauppauge.com>
+ *
+ *   Support for KWorld DVB-S 100 by Vadim Catana <skystar@moldova.cc>
+ *
+ *   Support for CX24123/CX24113-NIM by Patrick Boettcher <pb@linuxtv.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.
+ *
+ *   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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
 
 #include <linux/slab.h>
 #include <linux/kernel.h>
 
 static int force_band;
 static int debug;
+
+#define info(args...) do { printk(KERN_INFO "CX24123: " args); } while (0)
+#define err(args...)  do { printk(KERN_ERR  "CX24123: " args); } while (0)
+
 #define dprintk(args...) \
        do { \
-               if (debug) printk (KERN_DEBUG "cx24123: " args); \
+               if (debug) { \
+                       printk(KERN_DEBUG "CX24123: %s: ", __func__); \
+                       printk(args); \
+               } \
        } while (0)
 
 struct cx24123_state
@@ -51,6 +60,10 @@ struct cx24123_state
        u32 pllarg;
        u32 FILTune;
 
+       struct i2c_adapter tuner_i2c_adapter;
+
+       u8 demod_rev;
+
        /* The Demod/Tuner can't easily provide these, we cache them */
        u32 currentfreq;
        u32 currentsymbolrate;
@@ -225,48 +238,52 @@ static struct {
        {0x67, 0x83}, /* Non-DCII symbol clock */
 };
 
-static int cx24123_writereg(struct cx24123_state* state, int reg, int data)
+static int cx24123_i2c_writereg(struct cx24123_state *state,
+       u8 i2c_addr, int reg, int data)
 {
        u8 buf[] = { reg, data };
-       struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
+       struct i2c_msg msg = {
+               .addr = i2c_addr, .flags = 0, .buf = buf, .len = 2
+       };
        int err;
 
-       if (debug>1)
-               printk("cx24123: %s:  write reg 0x%02x, value 0x%02x\n",
-                                               __FUNCTION__,reg, data);
+       /* printk(KERN_DEBUG "wr(%02x): %02x %02x\n", i2c_addr, reg, data); */
 
        if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
                printk("%s: writereg error(err == %i, reg == 0x%02x,"
-                        " data == 0x%02x)\n", __FUNCTION__, err, reg, data);
-               return -EREMOTEIO;
+                        " data == 0x%02x)\n", __func__, err, reg, data);
+               return err;
        }
 
        return 0;
 }
 
-static int cx24123_readreg(struct cx24123_state* state, u8 reg)
+static int cx24123_i2c_readreg(struct cx24123_state *state, u8 i2c_addr, u8 reg)
 {
        int ret;
-       u8 b0[] = { reg };
-       u8 b1[] = { 0 };
+       u8 b = 0;
        struct i2c_msg msg[] = {
-               { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 },
-               { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 }
+               { .addr = i2c_addr, .flags = 0, .buf = &reg, .len = 1 },
+               { .addr = i2c_addr, .flags = I2C_M_RD, .buf = &b, .len = 1 }
        };
 
        ret = i2c_transfer(state->i2c, msg, 2);
 
        if (ret != 2) {
-               printk("%s: reg=0x%x (error=%d)\n", __FUNCTION__, reg, ret);
+               err("%s: reg=0x%x (error=%d)\n", __func__, reg, ret);
                return ret;
        }
 
-       if (debug>1)
-               printk("cx24123: read reg 0x%02x, value 0x%02x\n",reg, ret);
+       /* printk(KERN_DEBUG "rd(%02x): %02x %02x\n", i2c_addr, reg, b); */
 
-       return b1[0];
+       return b;
 }
 
+#define cx24123_readreg(state, reg) \
+       cx24123_i2c_readreg(state, state->config->demod_address, reg)
+#define cx24123_writereg(state, reg, val) \
+       cx24123_i2c_writereg(state, state->config->demod_address, reg, val)
+
 static int cx24123_set_inversion(struct cx24123_state* state, fe_spectral_inversion_t inversion)
 {
        u8 nom_reg = cx24123_readreg(state, 0x0e);
@@ -274,17 +291,17 @@ static int cx24123_set_inversion(struct cx24123_state* state, fe_spectral_invers
 
        switch (inversion) {
        case INVERSION_OFF:
-               dprintk("%s:  inversion off\n",__FUNCTION__);
+               dprintk("inversion off\n");
                cx24123_writereg(state, 0x0e, nom_reg & ~0x80);
                cx24123_writereg(state, 0x10, auto_reg | 0x80);
                break;
        case INVERSION_ON:
-               dprintk("%s:  inversion on\n",__FUNCTION__);
+               dprintk("inversion on\n");
                cx24123_writereg(state, 0x0e, nom_reg | 0x80);
                cx24123_writereg(state, 0x10, auto_reg | 0x80);
                break;
        case INVERSION_AUTO:
-               dprintk("%s:  inversion auto\n",__FUNCTION__);
+               dprintk("inversion auto\n");
                cx24123_writereg(state, 0x10, auto_reg & ~0x80);
                break;
        default:
@@ -301,10 +318,10 @@ static int cx24123_get_inversion(struct cx24123_state* state, fe_spectral_invers
        val = cx24123_readreg(state, 0x1b) >> 7;
 
        if (val == 0) {
-               dprintk("%s:  read inversion off\n",__FUNCTION__);
+               dprintk("read inversion off\n");
                *inversion = INVERSION_OFF;
        } else {
-               dprintk("%s:  read inversion on\n",__FUNCTION__);
+               dprintk("read inversion on\n");
                *inversion = INVERSION_ON;
        }
 
@@ -326,42 +343,42 @@ static int cx24123_set_fec(struct cx24123_state* state, fe_code_rate_t fec)
 
        switch (fec) {
        case FEC_1_2:
-               dprintk("%s:  set FEC to 1/2\n",__FUNCTION__);
+               dprintk("set FEC to 1/2\n");
                cx24123_writereg(state, 0x0e, nom_reg | 0x01);
                cx24123_writereg(state, 0x0f, 0x02);
                break;
        case FEC_2_3:
-               dprintk("%s:  set FEC to 2/3\n",__FUNCTION__);
+               dprintk("set FEC to 2/3\n");
                cx24123_writereg(state, 0x0e, nom_reg | 0x02);
                cx24123_writereg(state, 0x0f, 0x04);
                break;
        case FEC_3_4:
-               dprintk("%s:  set FEC to 3/4\n",__FUNCTION__);
+               dprintk("set FEC to 3/4\n");
                cx24123_writereg(state, 0x0e, nom_reg | 0x03);
                cx24123_writereg(state, 0x0f, 0x08);
                break;
        case FEC_4_5:
-               dprintk("%s:  set FEC to 4/5\n",__FUNCTION__);
+               dprintk("set FEC to 4/5\n");
                cx24123_writereg(state, 0x0e, nom_reg | 0x04);
                cx24123_writereg(state, 0x0f, 0x10);
                break;
        case FEC_5_6:
-               dprintk("%s:  set FEC to 5/6\n",__FUNCTION__);
+               dprintk("set FEC to 5/6\n");
                cx24123_writereg(state, 0x0e, nom_reg | 0x05);
                cx24123_writereg(state, 0x0f, 0x20);
                break;
        case FEC_6_7:
-               dprintk("%s:  set FEC to 6/7\n",__FUNCTION__);
+               dprintk("set FEC to 6/7\n");
                cx24123_writereg(state, 0x0e, nom_reg | 0x06);
                cx24123_writereg(state, 0x0f, 0x40);
                break;
        case FEC_7_8:
-               dprintk("%s:  set FEC to 7/8\n",__FUNCTION__);
+               dprintk("set FEC to 7/8\n");
                cx24123_writereg(state, 0x0e, nom_reg | 0x07);
                cx24123_writereg(state, 0x0f, 0x80);
                break;
        case FEC_AUTO:
-               dprintk("%s:  set FEC to auto\n",__FUNCTION__);
+               dprintk("set FEC to auto\n");
                cx24123_writereg(state, 0x0f, 0xfe);
                break;
        default:
@@ -490,7 +507,8 @@ static int cx24123_set_symbolrate(struct cx24123_state* state, u32 srate)
        tmp = cx24123_readreg(state, 0x0c) & ~0xe0;
        cx24123_writereg(state, 0x0c, tmp | sample_gain << 5);
 
-       dprintk("%s: srate=%d, ratio=0x%08x, sample_rate=%i sample_gain=%d\n", __FUNCTION__, srate, ratio, sample_rate, sample_gain);
+       dprintk("srate=%d, ratio=0x%08x, sample_rate=%i sample_gain=%d\n",
+               srate, ratio, sample_rate, sample_gain);
 
        return 0;
 }
@@ -570,7 +588,7 @@ static int cx24123_pll_writereg(struct dvb_frontend* fe, struct dvb_frontend_par
        struct cx24123_state *state = fe->demodulator_priv;
        unsigned long timeout;
 
-       dprintk("%s:  pll writereg called, data=0x%08x\n",__FUNCTION__,data);
+       dprintk("pll writereg called, data=0x%08x\n", data);
 
        /* align the 21 bytes into to bit23 boundary */
        data = data << 3;
@@ -583,7 +601,8 @@ static int cx24123_pll_writereg(struct dvb_frontend* fe, struct dvb_frontend_par
        cx24123_writereg(state, 0x22, (data >> 16) & 0xff);
        while ((cx24123_readreg(state, 0x20) & 0x40) == 0) {
                if (time_after(jiffies, timeout)) {
-                       printk("%s:  demodulator is not responding, possibly hung, aborting.\n", __FUNCTION__);
+                       err("%s:  demodulator is not responding, "\
+                               "possibly hung, aborting.\n", __func__);
                        return -EREMOTEIO;
                }
                msleep(10);
@@ -594,7 +613,8 @@ static int cx24123_pll_writereg(struct dvb_frontend* fe, struct dvb_frontend_par
        cx24123_writereg(state, 0x22, (data>>8) & 0xff );
        while ((cx24123_readreg(state, 0x20) & 0x40) == 0) {
                if (time_after(jiffies, timeout)) {
-                       printk("%s:  demodulator is not responding, possibly hung, aborting.\n", __FUNCTION__);
+                       err("%s:  demodulator is not responding, "\
+                               "possibly hung, aborting.\n", __func__);
                        return -EREMOTEIO;
                }
                msleep(10);
@@ -605,7 +625,8 @@ static int cx24123_pll_writereg(struct dvb_frontend* fe, struct dvb_frontend_par
        cx24123_writereg(state, 0x22, (data) & 0xff );
        while ((cx24123_readreg(state, 0x20) & 0x80)) {
                if (time_after(jiffies, timeout)) {
-                       printk("%s:  demodulator is not responding, possibly hung, aborting.\n", __FUNCTION__);
+                       err("%s:  demodulator is not responding," \
+                               "possibly hung, aborting.\n", __func__);
                        return -EREMOTEIO;
                }
                msleep(10);
@@ -626,7 +647,7 @@ static int cx24123_pll_tune(struct dvb_frontend* fe, struct dvb_frontend_paramet
        dprintk("frequency=%i\n", p->frequency);
 
        if (cx24123_pll_calculate(fe, p) != 0) {
-               printk("%s: cx24123_pll_calcutate failed\n",__FUNCTION__);
+               err("%s: cx24123_pll_calcutate failed\n", __func__);
                return -EINVAL;
        }
 
@@ -643,18 +664,38 @@ static int cx24123_pll_tune(struct dvb_frontend* fe, struct dvb_frontend_paramet
        cx24123_writereg(state, 0x27, state->FILTune >> 2);
        cx24123_writereg(state, 0x28, val | (state->FILTune & 0x3));
 
-       dprintk("%s:  pll tune VCA=%d, band=%d, pll=%d\n",__FUNCTION__,state->VCAarg,
-                       state->bandselectarg,state->pllarg);
+       dprintk("pll tune VCA=%d, band=%d, pll=%d\n", state->VCAarg,
+                       state->bandselectarg, state->pllarg);
 
        return 0;
 }
 
+
+/*
+ * 0x23:
+ *    [7:7] = BTI enabled
+ *    [6:6] = I2C repeater enabled
+ *    [5:5] = I2C repeater start
+ *    [0:0] = BTI start
+ */
+
+/* mode == 1 -> i2c-repeater, 0 -> bti */
+static int cx24123_repeater_mode(struct cx24123_state *state, u8 mode, u8 start)
+{
+       u8 r = cx24123_readreg(state, 0x23) & 0x1e;
+       if (mode)
+               r |= (1 << 6) | (start << 5);
+       else
+               r |= (1 << 7) | (start);
+       return cx24123_writereg(state, 0x23, r);
+}
+
 static int cx24123_initfe(struct dvb_frontend* fe)
 {
        struct cx24123_state *state = fe->demodulator_priv;
        int i;
 
-       dprintk("%s:  init frontend\n",__FUNCTION__);
+       dprintk("init frontend\n");
 
        /* Configure the demod to a good set of defaults */
        for (i = 0; i < ARRAY_SIZE(cx24123_regdata); i++)
@@ -664,6 +705,9 @@ static int cx24123_initfe(struct dvb_frontend* fe)
        if(state->config->lnb_polarity)
                cx24123_writereg(state, 0x32, cx24123_readreg(state, 0x32) | 0x02);
 
+       if (state->config->dont_use_pll)
+       cx24123_repeater_mode(state, 1, 0);
+
        return 0;
 }
 
@@ -676,10 +720,10 @@ static int cx24123_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage
 
        switch (voltage) {
        case SEC_VOLTAGE_13:
-               dprintk("%s: setting voltage 13V\n", __FUNCTION__);
+               dprintk("setting voltage 13V\n");
                return cx24123_writereg(state, 0x29, val & 0x7f);
        case SEC_VOLTAGE_18:
-               dprintk("%s: setting voltage 18V\n", __FUNCTION__);
+               dprintk("setting voltage 18V\n");
                return cx24123_writereg(state, 0x29, val | 0x80);
        case SEC_VOLTAGE_OFF:
                /* already handled in cx88-dvb */
@@ -697,7 +741,8 @@ static void cx24123_wait_for_diseqc(struct cx24123_state *state)
        unsigned long timeout = jiffies + msecs_to_jiffies(200);
        while (!(cx24123_readreg(state, 0x29) & 0x40)) {
                if(time_after(jiffies, timeout)) {
-                       printk("%s: diseqc queue not ready, command may be lost.\n", __FUNCTION__);
+                       err("%s: diseqc queue not ready, " \
+                               "command may be lost.\n", __func__);
                        break;
                }
                msleep(10);
@@ -709,7 +754,7 @@ static int cx24123_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_ma
        struct cx24123_state *state = fe->demodulator_priv;
        int i, val, tone;
 
-       dprintk("%s:\n",__FUNCTION__);
+       dprintk("\n");
 
        /* stop continuous tone if enabled */
        tone = cx24123_readreg(state, 0x29);
@@ -744,7 +789,7 @@ static int cx24123_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t
        struct cx24123_state *state = fe->demodulator_priv;
        int val, tone;
 
-       dprintk("%s:\n", __FUNCTION__);
+       dprintk("\n");
 
        /* stop continuous tone if enabled */
        tone = cx24123_readreg(state, 0x29);
@@ -778,13 +823,21 @@ static int cx24123_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t
 static int cx24123_read_status(struct dvb_frontend* fe, fe_status_t* status)
 {
        struct cx24123_state *state = fe->demodulator_priv;
-
        int sync = cx24123_readreg(state, 0x14);
-       int lock = cx24123_readreg(state, 0x20);
 
        *status = 0;
-       if (lock & 0x01)
-               *status |= FE_HAS_SIGNAL;
+       if (state->config->dont_use_pll) {
+               u32 tun_status = 0;
+               if (fe->ops.tuner_ops.get_status)
+                       fe->ops.tuner_ops.get_status(fe, &tun_status);
+               if (tun_status & TUNER_STATUS_LOCKED)
+                       *status |= FE_HAS_SIGNAL;
+       } else {
+               int lock = cx24123_readreg(state, 0x20);
+               if (lock & 0x01)
+                       *status |= FE_HAS_SIGNAL;
+       }
+
        if (sync & 0x02)
                *status |= FE_HAS_CARRIER;      /* Phase locked */
        if (sync & 0x04)
@@ -803,7 +856,7 @@ static int cx24123_read_status(struct dvb_frontend* fe, fe_status_t* status)
  * Configured to return the measurement of errors in blocks, because no UCBLOCKS value
  * is available, so this value doubles up to satisfy both measurements
  */
-static int cx24123_read_ber(struct dvb_frontend* fe, u32* ber)
+static int cx24123_read_ber(struct dvb_frontend *fe, u32 *ber)
 {
        struct cx24123_state *state = fe->demodulator_priv;
 
@@ -813,23 +866,24 @@ static int cx24123_read_ber(struct dvb_frontend* fe, u32* ber)
                (cx24123_readreg(state, 0x1d) << 8 |
                 cx24123_readreg(state, 0x1e));
 
-       dprintk("%s:  BER = %d\n",__FUNCTION__,*ber);
+       dprintk("BER = %d\n", *ber);
 
        return 0;
 }
 
-static int cx24123_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength)
+static int cx24123_read_signal_strength(struct dvb_frontend *fe,
+       u16 *signal_strength)
 {
        struct cx24123_state *state = fe->demodulator_priv;
 
        *signal_strength = cx24123_readreg(state, 0x3b) << 8; /* larger = better */
 
-       dprintk("%s:  Signal strength = %d\n",__FUNCTION__,*signal_strength);
+       dprintk("Signal strength = %d\n", *signal_strength);
 
        return 0;
 }
 
-static int cx24123_read_snr(struct dvb_frontend* fe, u16* snr)
+static int cx24123_read_snr(struct dvb_frontend *fe, u16 *snr)
 {
        struct cx24123_state *state = fe->demodulator_priv;
 
@@ -838,16 +892,17 @@ static int cx24123_read_snr(struct dvb_frontend* fe, u16* snr)
        *snr = 65535 - (((u16)cx24123_readreg(state, 0x18) << 8) |
                         (u16)cx24123_readreg(state, 0x19));
 
-       dprintk("%s:  read S/N index = %d\n",__FUNCTION__,*snr);
+       dprintk("read S/N index = %d\n", *snr);
 
        return 0;
 }
 
-static int cx24123_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int cx24123_set_frontend(struct dvb_frontend *fe,
+       struct dvb_frontend_parameters *p)
 {
        struct cx24123_state *state = fe->demodulator_priv;
 
-       dprintk("%s:  set_frontend\n",__FUNCTION__);
+       dprintk("\n");
 
        if (state->config->set_ts_params)
                state->config->set_ts_params(fe, 0);
@@ -858,13 +913,22 @@ static int cx24123_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
        cx24123_set_inversion(state, p->inversion);
        cx24123_set_fec(state, p->u.qpsk.fec_inner);
        cx24123_set_symbolrate(state, p->u.qpsk.symbol_rate);
-       cx24123_pll_tune(fe, p);
+
+       if (!state->config->dont_use_pll)
+               cx24123_pll_tune(fe, p);
+       else if (fe->ops.tuner_ops.set_params)
+               fe->ops.tuner_ops.set_params(fe, p);
+       else
+               err("it seems I don't have a tuner...");
 
        /* Enable automatic aquisition and reset cycle */
        cx24123_writereg(state, 0x03, (cx24123_readreg(state, 0x03) | 0x07));
        cx24123_writereg(state, 0x00, 0x10);
        cx24123_writereg(state, 0x00, 0);
 
+       if (state->config->agc_callback)
+               state->config->agc_callback(fe);
+
        return 0;
 }
 
@@ -872,14 +936,14 @@ static int cx24123_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
 {
        struct cx24123_state *state = fe->demodulator_priv;
 
-       dprintk("%s:  get_frontend\n",__FUNCTION__);
+       dprintk("\n");
 
        if (cx24123_get_inversion(state, &p->inversion) != 0) {
-               printk("%s: Failed to get inversion status\n",__FUNCTION__);
+               err("%s: Failed to get inversion status\n", __func__);
                return -EREMOTEIO;
        }
        if (cx24123_get_fec(state, &p->u.qpsk.fec_inner) != 0) {
-               printk("%s: Failed to get fec status\n",__FUNCTION__);
+               err("%s: Failed to get fec status\n", __func__);
                return -EREMOTEIO;
        }
        p->frequency = state->currentfreq;
@@ -900,13 +964,13 @@ static int cx24123_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
 
        switch (tone) {
        case SEC_TONE_ON:
-               dprintk("%s: setting tone on\n", __FUNCTION__);
+               dprintk("setting tone on\n");
                return cx24123_writereg(state, 0x29, val | 0x10);
        case SEC_TONE_OFF:
-               dprintk("%s: setting tone off\n",__FUNCTION__);
+               dprintk("setting tone off\n");
                return cx24123_writereg(state, 0x29, val & 0xef);
        default:
-               printk("%s: CASE reached default with tone=%d\n", __FUNCTION__, tone);
+               err("CASE reached default with tone=%d\n", tone);
                return -EINVAL;
        }
 
@@ -939,47 +1003,86 @@ static int cx24123_get_algo(struct dvb_frontend *fe)
 static void cx24123_release(struct dvb_frontend* fe)
 {
        struct cx24123_state* state = fe->demodulator_priv;
-       dprintk("%s\n",__FUNCTION__);
+       dprintk("\n");
+       i2c_del_adapter(&state->tuner_i2c_adapter);
        kfree(state);
 }
 
+static int cx24123_tuner_i2c_tuner_xfer(struct i2c_adapter *i2c_adap,
+       struct i2c_msg msg[], int num)
+{
+       struct cx24123_state *state = i2c_get_adapdata(i2c_adap);
+       /* this repeater closes after the first stop */
+    cx24123_repeater_mode(state, 1, 1);
+       return i2c_transfer(state->i2c, msg, num);
+}
+
+static u32 cx24123_tuner_i2c_func(struct i2c_adapter *adapter)
+{
+       return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm cx24123_tuner_i2c_algo = {
+       .master_xfer   = cx24123_tuner_i2c_tuner_xfer,
+       .functionality = cx24123_tuner_i2c_func,
+};
+
+struct i2c_adapter *
+       cx24123_get_tuner_i2c_adapter(struct dvb_frontend *fe)
+{
+       struct cx24123_state *state = fe->demodulator_priv;
+       return &state->tuner_i2c_adapter;
+}
+EXPORT_SYMBOL(cx24123_get_tuner_i2c_adapter);
+
 static struct dvb_frontend_ops cx24123_ops;
 
 struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
                                    struct i2c_adapter* i2c)
 {
-       struct cx24123_state* state = NULL;
-       int ret;
-
-       dprintk("%s\n",__FUNCTION__);
+       struct cx24123_state *state =
+               kzalloc(sizeof(struct cx24123_state), GFP_KERNEL);
 
+       dprintk("\n");
        /* allocate memory for the internal state */
-       state = kmalloc(sizeof(struct cx24123_state), GFP_KERNEL);
        if (state == NULL) {
-               printk("Unable to kmalloc\n");
+               err("Unable to kmalloc\n");
                goto error;
        }
 
        /* setup the state */
        state->config = config;
        state->i2c = i2c;
-       state->VCAarg = 0;
-       state->VGAarg = 0;
-       state->bandselectarg = 0;
-       state->pllarg = 0;
-       state->currentfreq = 0;
-       state->currentsymbolrate = 0;
 
        /* check if the demod is there */
-       ret = cx24123_readreg(state, 0x00);
-       if ((ret != 0xd1) && (ret != 0xe1)) {
-               printk("Version != d1 or e1\n");
+       state->demod_rev = cx24123_readreg(state, 0x00);
+       switch (state->demod_rev) {
+       case 0xe1: info("detected CX24123C\n"); break;
+       case 0xd1: info("detected CX24123\n"); break;
+       default:
+               err("wrong demod revision: %x\n", state->demod_rev);
                goto error;
        }
 
        /* create dvb_frontend */
        memcpy(&state->frontend.ops, &cx24123_ops, sizeof(struct dvb_frontend_ops));
        state->frontend.demodulator_priv = state;
+
+    /* create tuner i2c adapter */
+    if (config->dont_use_pll)
+       cx24123_repeater_mode(state, 1, 0);
+
+       strncpy(state->tuner_i2c_adapter.name,
+               "CX24123 tuner I2C bus", I2C_NAME_SIZE);
+       state->tuner_i2c_adapter.class     = I2C_CLASS_TV_DIGITAL,
+       state->tuner_i2c_adapter.algo      = &cx24123_tuner_i2c_algo;
+       state->tuner_i2c_adapter.algo_data = NULL;
+       i2c_set_adapdata(&state->tuner_i2c_adapter, state);
+       if (i2c_add_adapter(&state->tuner_i2c_adapter) < 0) {
+       err("tuner i2c bus could not be initialized\n");
+               goto error;
+       }
+
        return &state->frontend;
 
 error:
@@ -1029,7 +1132,8 @@ MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
 module_param(force_band, int, 0644);
 MODULE_PARM_DESC(force_band, "Force a specific band select (1-9, default:off).");
 
-MODULE_DESCRIPTION("DVB Frontend module for Conexant cx24123/cx24109 hardware");
+MODULE_DESCRIPTION("DVB Frontend module for Conexant " \
+       "CX24123/CX24109/CX24113 hardware");
 MODULE_AUTHOR("Steven Toth");
 MODULE_LICENSE("GPL");
 
index 84f9e4f5c15e1d2750dd7fbb99d15425908060d9..81ebc3d2f19f07353278f00ee82537e48e484c48 100644 (file)
@@ -33,16 +33,27 @@ struct cx24123_config
 
        /* 0 = LNB voltage normal, 1 = LNB voltage inverted */
        int lnb_polarity;
+
+       /* this device has another tuner */
+       u8 dont_use_pll;
+       void (*agc_callback) (struct dvb_frontend *);
 };
 
 #if defined(CONFIG_DVB_CX24123) || (defined(CONFIG_DVB_CX24123_MODULE) && defined(MODULE))
-extern struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
-                                          struct i2c_adapter* i2c);
+extern struct dvb_frontend *cx24123_attach(const struct cx24123_config *config,
+                                          struct i2c_adapter *i2c);
+extern struct i2c_adapter *cx24123_get_tuner_i2c_adapter(struct dvb_frontend *);
 #else
-static inline struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
-                                                 struct i2c_adapter* i2c)
+static inline struct dvb_frontend *cx24123_attach(
+       const struct cx24123_config *config, struct i2c_adapter *i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return NULL;
+}
+static struct i2c_adapter *
+       cx24123_get_tuner_i2c_adapter(struct dvb_frontend *fe)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_CX24123
index a6d3854a67bcf6156bf57a9e72de1c5d135d4318..ba917359fa65e16fc5cb4cbd249a13f99c47438d 100644 (file)
@@ -48,7 +48,7 @@ extern struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config
 static inline struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config,
                                             struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_DIB3000MB
index 72d4757601d81797342a0842219f868177362a79..4142ed7a47d02201e1b5aa13deeeb96f0097f38d 100644 (file)
@@ -44,7 +44,7 @@ extern struct dvb_frontend * dib3000mc_attach(struct i2c_adapter *i2c_adap, u8 i
 #else
 static inline struct dvb_frontend * dib3000mc_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib3000mc_config *cfg)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_DIB3000MC
index 47c23e29753e6dc20dd32ae2d550e8d832d7204c..1a0142e0d74166a5576d11f27f4159403fcd78f0 100644 (file)
@@ -1168,7 +1168,7 @@ static int dib7000p_set_frontend(struct dvb_frontend* fe,
        ret = dib7000p_tune(fe, fep);
 
        /* make this a config parameter */
-       dib7000p_set_output_mode(state, OUTMODE_MPEG2_FIFO);
+       dib7000p_set_output_mode(state, state->cfg.output_mode);
     return ret;
 }
 
@@ -1330,6 +1330,12 @@ struct dvb_frontend * dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr,
        st->gpio_val = cfg->gpio_val;
        st->gpio_dir = cfg->gpio_dir;
 
+       /* Ensure the output mode remains at the previous default if it's
+        * not specifically set by the caller.
+        */
+       if (st->cfg.output_mode != OUTMODE_MPEG2_SERIAL)
+               st->cfg.output_mode = OUTMODE_MPEG2_FIFO;
+
        demod                   = &st->demod;
        demod->demodulator_priv = st;
        memcpy(&st->demod.ops, &dib7000p_ops, sizeof(struct dvb_frontend_ops));
index eefcac8b5244197d0cf9390960a77d8cd954afe5..081bd81f3da2ec5a2b61b797df57ca63b68d8ffe 100644 (file)
@@ -31,6 +31,8 @@ struct dib7000p_config {
        u8 spur_protect;
 
        int (*agc_control) (struct dvb_frontend *, u8 before);
+
+       u8 output_mode;
 };
 
 #define DEFAULT_DIB7000P_I2C_ADDRESS 18
index 8c8d7342d0b37254475d22a804e4680455d5be3a..a054894ff481867842ca344632b3feba1393e729 100644 (file)
@@ -44,14 +44,10 @@ struct dvb_pll_priv {
 
 static unsigned int dvb_pll_devcount;
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "enable verbose debug messages");
 
-static unsigned int input[DVB_PLL_MAX] = { [ 0 ... (DVB_PLL_MAX-1) ] = 0 };
-module_param_array(input, int, NULL, 0644);
-MODULE_PARM_DESC(input,"specify rf input choice, 0 for autoselect (default)");
-
 static unsigned int id[DVB_PLL_MAX] =
        { [ 0 ... (DVB_PLL_MAX-1) ] = DVB_PLL_UNDEFINED };
 module_param_array(id, int, NULL, 0644);
@@ -80,23 +76,6 @@ struct dvb_pll_desc {
 /* ----------------------------------------------------------- */
 /* descriptions                                                */
 
-/* Set AGC TOP value to 103 dBuV:
-       0x80 = Control Byte
-       0x40 = 250 uA charge pump (irrelevant)
-       0x18 = Aux Byte to follow
-       0x06 = 64.5 kHz divider (irrelevant)
-       0x01 = Disable Vt (aka sleep)
-
-       0x00 = AGC Time constant 2s Iagc = 300 nA (vs 0x80 = 9 nA)
-       0x50 = AGC Take over point = 103 dBuV */
-static u8 tua603x_agc103[] = { 2, 0x80|0x40|0x18|0x06|0x01, 0x00|0x50 };
-
-/*     0x04 = 166.67 kHz divider
-
-       0x80 = AGC Time constant 50ms Iagc = 9 uA
-       0x20 = AGC Take over point = 112 dBuV */
-static u8 tua603x_agc112[] = { 2, 0x80|0x40|0x18|0x04|0x01, 0x80|0x20 };
-
 static struct dvb_pll_desc dvb_pll_thomson_dtt7579 = {
        .name  = "Thomson dtt7579",
        .min   = 177000000,
@@ -112,19 +91,6 @@ static struct dvb_pll_desc dvb_pll_thomson_dtt7579 = {
        },
 };
 
-static struct dvb_pll_desc dvb_pll_thomson_dtt7610 = {
-       .name  = "Thomson dtt7610",
-       .min   =  44000000,
-       .max   = 958000000,
-       .iffreq= 44000000,
-       .count = 3,
-       .entries = {
-               { 157250000, 62500, 0x8e, 0x39 },
-               { 454000000, 62500, 0x8e, 0x3a },
-               { 999999999, 62500, 0x8e, 0x3c },
-       },
-};
-
 static void thomson_dtt759x_bw(struct dvb_frontend *fe, u8 *buf,
                               const struct dvb_frontend_parameters *params)
 {
@@ -165,34 +131,6 @@ static struct dvb_pll_desc dvb_pll_lg_z201 = {
        },
 };
 
-static struct dvb_pll_desc dvb_pll_microtune_4042 = {
-       .name  = "Microtune 4042 FI5",
-       .min   =  57000000,
-       .max   = 858000000,
-       .iffreq= 44000000,
-       .count = 3,
-       .entries = {
-               { 162000000, 62500, 0x8e, 0xa1 },
-               { 457000000, 62500, 0x8e, 0x91 },
-               { 999999999, 62500, 0x8e, 0x31 },
-       },
-};
-
-static struct dvb_pll_desc dvb_pll_thomson_dtt761x = {
-       /* DTT 7611 7611A 7612 7613 7613A 7614 7615 7615A */
-       .name  = "Thomson dtt761x",
-       .min   =  57000000,
-       .max   = 863000000,
-       .iffreq= 44000000,
-       .count = 3,
-       .initdata = tua603x_agc103,
-       .entries = {
-               { 147000000, 62500, 0x8e, 0x39 },
-               { 417000000, 62500, 0x8e, 0x3a },
-               { 999999999, 62500, 0x8e, 0x3c },
-       },
-};
-
 static struct dvb_pll_desc dvb_pll_unknown_1 = {
        .name  = "unknown 1", /* used by dntv live dvb-t */
        .min   = 174000000,
@@ -301,54 +239,6 @@ static struct dvb_pll_desc dvb_pll_tua6034 = {
        },
 };
 
-/* Infineon TUA6034
- * used in LG TDVS-H061F, LG TDVS-H062F and LG TDVS-H064F
- */
-static struct dvb_pll_desc dvb_pll_lg_tdvs_h06xf = {
-       .name  = "LG TDVS-H06xF",
-       .min   =  54000000,
-       .max   = 863000000,
-       .iffreq= 44000000,
-       .initdata = tua603x_agc103,
-       .count = 3,
-       .entries = {
-               {  165000000, 62500, 0xce, 0x01 },
-               {  450000000, 62500, 0xce, 0x02 },
-               {  999999999, 62500, 0xce, 0x04 },
-       },
-};
-
-/* Philips FMD1216ME
- * used in Medion Hybrid PCMCIA card and USB Box
- */
-static void fmd1216me_bw(struct dvb_frontend *fe, u8 *buf,
-                        const struct dvb_frontend_parameters *params)
-{
-       if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ &&
-           params->frequency >= 158870000)
-               buf[3] |= 0x08;
-}
-
-static struct dvb_pll_desc dvb_pll_fmd1216me = {
-       .name = "Philips FMD1216ME",
-       .min = 50870000,
-       .max = 858000000,
-       .iffreq= 36125000,
-       .set   = fmd1216me_bw,
-       .initdata = tua603x_agc112,
-       .sleepdata = (u8[]){ 4, 0x9c, 0x60, 0x85, 0x54 },
-       .count = 7,
-       .entries = {
-               { 143870000, 166667, 0xbc, 0x41 },
-               { 158870000, 166667, 0xf4, 0x41 },
-               { 329870000, 166667, 0xbc, 0x42 },
-               { 441870000, 166667, 0xf4, 0x42 },
-               { 625870000, 166667, 0xbc, 0x44 },
-               { 803870000, 166667, 0xf4, 0x44 },
-               { 999999999, 166667, 0xfc, 0x44 },
-       }
-};
-
 /* ALPS TDED4
  * used in Nebula-Cards and USB boxes
  */
@@ -391,55 +281,6 @@ static struct dvb_pll_desc dvb_pll_tdhu2 = {
        }
 };
 
-/* Philips TUV1236D
- * used in ATI HDTV Wonder
- */
-static void tuv1236d_rf(struct dvb_frontend *fe, u8 *buf,
-                       const struct dvb_frontend_parameters *params)
-{
-       struct dvb_pll_priv *priv = fe->tuner_priv;
-       unsigned int new_rf = input[priv->nr];
-
-       if ((new_rf == 0) || (new_rf > 2)) {
-               switch (params->u.vsb.modulation) {
-                       case QAM_64:
-                       case QAM_256:
-                               new_rf = 1;
-                               break;
-                       case VSB_8:
-                       default:
-                               new_rf = 2;
-               }
-       }
-
-       switch (new_rf) {
-               case 1:
-                       buf[3] |= 0x08;
-                       break;
-               case 2:
-                       buf[3] &= ~0x08;
-                       break;
-               default:
-                       printk(KERN_WARNING
-                              "%s: unhandled rf input selection: %d",
-                              __FUNCTION__, new_rf);
-       }
-}
-
-static struct dvb_pll_desc dvb_pll_tuv1236d = {
-       .name  = "Philips TUV1236D",
-       .min   =  54000000,
-       .max   = 864000000,
-       .iffreq= 44000000,
-       .set   = tuv1236d_rf,
-       .count = 3,
-       .entries = {
-               { 157250000, 62500, 0xc6, 0x41 },
-               { 454000000, 62500, 0xc6, 0x42 },
-               { 999999999, 62500, 0xc6, 0x44 },
-       },
-};
-
 /* Samsung TBMV30111IN / TBMV30712IN1
  * used in Air2PC ATSC - 2nd generation (nxt2002)
  */
@@ -476,64 +317,6 @@ static struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261 = {
        },
 };
 
-/*
- * Philips TD1316 Tuner.
- */
-static void td1316_bw(struct dvb_frontend *fe, u8 *buf,
-                     const struct dvb_frontend_parameters *params)
-{
-       u8 band;
-
-       /* determine band */
-       if (params->frequency < 161000000)
-               band = 1;
-       else if (params->frequency < 444000000)
-               band = 2;
-       else
-               band = 4;
-
-       buf[3] |= band;
-
-       /* setup PLL filter */
-       if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ)
-               buf[3] |= 1 << 3;
-}
-
-static struct dvb_pll_desc dvb_pll_philips_td1316 = {
-       .name  = "Philips TD1316",
-       .min   =  87000000,
-       .max   = 895000000,
-       .iffreq= 36166667,
-       .set   = td1316_bw,
-       .count = 9,
-       .entries = {
-               {  93834000, 166667, 0xca, 0x60},
-               { 123834000, 166667, 0xca, 0xa0},
-               { 163834000, 166667, 0xca, 0xc0},
-               { 253834000, 166667, 0xca, 0x60},
-               { 383834000, 166667, 0xca, 0xa0},
-               { 443834000, 166667, 0xca, 0xc0},
-               { 583834000, 166667, 0xca, 0x60},
-               { 793834000, 166667, 0xca, 0xa0},
-               { 858834000, 166667, 0xca, 0xe0},
-       },
-};
-
-/* FE6600 used on DViCO Hybrid */
-static struct dvb_pll_desc dvb_pll_thomson_fe6600 = {
-       .name = "Thomson FE6600",
-       .min =  44250000,
-       .max = 858000000,
-       .iffreq= 36125000,
-       .count = 4,
-       .entries = {
-               { 250000000, 166667, 0xb4, 0x12 },
-               { 455000000, 166667, 0xfe, 0x11 },
-               { 775500000, 166667, 0xbc, 0x18 },
-               { 999999999, 166667, 0xf4, 0x18 },
-       }
-};
-
 static void opera1_bw(struct dvb_frontend *fe, u8 *buf,
                      const struct dvb_frontend_parameters *params)
 {
@@ -560,50 +343,23 @@ static struct dvb_pll_desc dvb_pll_opera1 = {
        }
 };
 
-/* Philips FCV1236D
- */
-static struct dvb_pll_desc dvb_pll_fcv1236d = {
-/* Bit_0: RF Input select
- * Bit_1: 0=digital, 1=analog
- */
-       .name  = "Philips FCV1236D",
-       .min   =  53000000,
-       .max   = 803000000,
-       .iffreq= 44000000,
-       .count = 3,
-       .entries = {
-               { 159000000, 62500, 0x8e, 0xa0 },
-               { 453000000, 62500, 0x8e, 0x90 },
-               { 999999999, 62500, 0x8e, 0x30 },
-       },
-};
-
 /* ----------------------------------------------------------- */
 
 static struct dvb_pll_desc *pll_list[] = {
        [DVB_PLL_UNDEFINED]              = NULL,
        [DVB_PLL_THOMSON_DTT7579]        = &dvb_pll_thomson_dtt7579,
        [DVB_PLL_THOMSON_DTT759X]        = &dvb_pll_thomson_dtt759x,
-       [DVB_PLL_THOMSON_DTT7610]        = &dvb_pll_thomson_dtt7610,
        [DVB_PLL_LG_Z201]                = &dvb_pll_lg_z201,
-       [DVB_PLL_MICROTUNE_4042]         = &dvb_pll_microtune_4042,
-       [DVB_PLL_THOMSON_DTT761X]        = &dvb_pll_thomson_dtt761x,
        [DVB_PLL_UNKNOWN_1]              = &dvb_pll_unknown_1,
        [DVB_PLL_TUA6010XS]              = &dvb_pll_tua6010xs,
        [DVB_PLL_ENV57H1XD5]             = &dvb_pll_env57h1xd5,
        [DVB_PLL_TUA6034]                = &dvb_pll_tua6034,
-       [DVB_PLL_LG_TDVS_H06XF]          = &dvb_pll_lg_tdvs_h06xf,
        [DVB_PLL_TDA665X]                = &dvb_pll_tda665x,
-       [DVB_PLL_FMD1216ME]              = &dvb_pll_fmd1216me,
        [DVB_PLL_TDED4]                  = &dvb_pll_tded4,
-       [DVB_PLL_TUV1236D]               = &dvb_pll_tuv1236d,
        [DVB_PLL_TDHU2]                  = &dvb_pll_tdhu2,
        [DVB_PLL_SAMSUNG_TBMV]           = &dvb_pll_samsung_tbmv,
        [DVB_PLL_PHILIPS_SD1878_TDA8261] = &dvb_pll_philips_sd1878_tda8261,
-       [DVB_PLL_PHILIPS_TD1316]         = &dvb_pll_philips_td1316,
-       [DVB_PLL_THOMSON_FE6600]         = &dvb_pll_thomson_fe6600,
        [DVB_PLL_OPERA1]                 = &dvb_pll_opera1,
-       [DVB_PLL_FCV1236D]               = &dvb_pll_fcv1236d,
 };
 
 /* ----------------------------------------------------------- */
@@ -849,20 +605,6 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr,
                       id[priv->nr] == pll_desc_id ?
                                "insmod option" : "autodetected");
        }
-       if ((debug) || (input[priv->nr] > 0)) {
-               printk("dvb-pll[%d]", priv->nr);
-               if (i2c != NULL)
-                       printk(" %d-%04x", i2c_adapter_id(i2c), pll_addr);
-               printk(": tuner rf input will be ");
-               switch (input[priv->nr]) {
-               case 0:
-                       printk("autoselected\n");
-                       break;
-               default:
-                       printk("set to input %d (insmod option)\n",
-                              input[priv->nr]);
-               }
-       }
 
        return fe;
 }
index e93a8104052bb12b9ff5257d902798a27396aac0..872ca29e7cf37db7af523619637b24f2951c7408 100644 (file)
 #define DVB_PLL_UNDEFINED               0
 #define DVB_PLL_THOMSON_DTT7579         1
 #define DVB_PLL_THOMSON_DTT759X         2
-#define DVB_PLL_THOMSON_DTT7610         3
-#define DVB_PLL_LG_Z201                 4
-#define DVB_PLL_MICROTUNE_4042          5
-#define DVB_PLL_THOMSON_DTT761X         6
-#define DVB_PLL_UNKNOWN_1               7
-#define DVB_PLL_TUA6010XS               8
-#define DVB_PLL_ENV57H1XD5              9
-#define DVB_PLL_TUA6034                10
-#define DVB_PLL_LG_TDVS_H06XF          11
-#define DVB_PLL_TDA665X                12
-#define DVB_PLL_FMD1216ME              13
-#define DVB_PLL_TDED4                  14
-#define DVB_PLL_TUV1236D               15
-#define DVB_PLL_TDHU2                  16
-#define DVB_PLL_SAMSUNG_TBMV           17
-#define DVB_PLL_PHILIPS_SD1878_TDA8261 18
-#define DVB_PLL_PHILIPS_TD1316         19
-#define DVB_PLL_THOMSON_FE6600         20
-#define DVB_PLL_OPERA1                 21
-#define DVB_PLL_FCV1236D               22
+#define DVB_PLL_LG_Z201                 3
+#define DVB_PLL_UNKNOWN_1               4
+#define DVB_PLL_TUA6010XS               5
+#define DVB_PLL_ENV57H1XD5              6
+#define DVB_PLL_TUA6034                 7
+#define DVB_PLL_TDA665X                 8
+#define DVB_PLL_TDED4                   9
+#define DVB_PLL_TDHU2                  10
+#define DVB_PLL_SAMSUNG_TBMV           11
+#define DVB_PLL_PHILIPS_SD1878_TDA8261 12
+#define DVB_PLL_OPERA1                 13
 
 /**
  * Attach a dvb-pll to the supplied frontend structure.
@@ -52,7 +43,7 @@ static inline struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe,
                                           struct i2c_adapter *i2c,
                                           unsigned int pll_desc_id)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif
diff --git a/drivers/media/dvb/frontends/isl6405.c b/drivers/media/dvb/frontends/isl6405.c
new file mode 100644 (file)
index 0000000..33d33f4
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * isl6405.c - driver for dual lnb supply and control ic ISL6405
+ *
+ * Copyright (C) 2008 Hartmut Hackmann
+ * Copyright (C) 2006 Oliver Endriss
+ *
+ * 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.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ *
+ *
+ * the project's page is at http://www.linuxtv.org
+ */
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
+#include "dvb_frontend.h"
+#include "isl6405.h"
+
+struct isl6405 {
+       u8                      config;
+       u8                      override_or;
+       u8                      override_and;
+       struct i2c_adapter      *i2c;
+       u8                      i2c_addr;
+};
+
+static int isl6405_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+       struct isl6405 *isl6405 = (struct isl6405 *) fe->sec_priv;
+       struct i2c_msg msg = {  .addr = isl6405->i2c_addr, .flags = 0,
+                               .buf = &isl6405->config,
+                               .len = sizeof(isl6405->config) };
+
+       if (isl6405->override_or & 0x80) {
+               isl6405->config &= ~(ISL6405_VSEL2 | ISL6405_EN2);
+               switch (voltage) {
+               case SEC_VOLTAGE_OFF:
+                       break;
+               case SEC_VOLTAGE_13:
+                       isl6405->config |= ISL6405_EN2;
+                       break;
+               case SEC_VOLTAGE_18:
+                       isl6405->config |= (ISL6405_EN2 | ISL6405_VSEL2);
+                       break;
+               default:
+                       return -EINVAL;
+               }
+       } else {
+               isl6405->config &= ~(ISL6405_VSEL1 | ISL6405_EN1);
+               switch (voltage) {
+               case SEC_VOLTAGE_OFF:
+                       break;
+               case SEC_VOLTAGE_13:
+                       isl6405->config |= ISL6405_EN1;
+                       break;
+               case SEC_VOLTAGE_18:
+                       isl6405->config |= (ISL6405_EN1 | ISL6405_VSEL1);
+                       break;
+               default:
+                       return -EINVAL;
+               };
+       }
+       isl6405->config |= isl6405->override_or;
+       isl6405->config &= isl6405->override_and;
+
+       return (i2c_transfer(isl6405->i2c, &msg, 1) == 1) ? 0 : -EIO;
+}
+
+static int isl6405_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
+{
+       struct isl6405 *isl6405 = (struct isl6405 *) fe->sec_priv;
+       struct i2c_msg msg = {  .addr = isl6405->i2c_addr, .flags = 0,
+                               .buf = &isl6405->config,
+                               .len = sizeof(isl6405->config) };
+
+       if (isl6405->override_or & 0x80) {
+               if (arg)
+                       isl6405->config |= ISL6405_LLC2;
+               else
+                       isl6405->config &= ~ISL6405_LLC2;
+       } else {
+               if (arg)
+                       isl6405->config |= ISL6405_LLC1;
+               else
+                       isl6405->config &= ~ISL6405_LLC1;
+       }
+       isl6405->config |= isl6405->override_or;
+       isl6405->config &= isl6405->override_and;
+
+       return (i2c_transfer(isl6405->i2c, &msg, 1) == 1) ? 0 : -EIO;
+}
+
+static void isl6405_release(struct dvb_frontend *fe)
+{
+       /* power off */
+       isl6405_set_voltage(fe, SEC_VOLTAGE_OFF);
+
+       /* free */
+       kfree(fe->sec_priv);
+       fe->sec_priv = NULL;
+}
+
+struct dvb_frontend *isl6405_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c,
+                                   u8 i2c_addr, u8 override_set, u8 override_clear)
+{
+       struct isl6405 *isl6405 = kmalloc(sizeof(struct isl6405), GFP_KERNEL);
+       if (!isl6405)
+               return NULL;
+
+       /* default configuration */
+       if (override_set & 0x80)
+               isl6405->config = ISL6405_ISEL2;
+       else
+               isl6405->config = ISL6405_ISEL1;
+       isl6405->i2c = i2c;
+       isl6405->i2c_addr = i2c_addr;
+       fe->sec_priv = isl6405;
+
+       /* bits which should be forced to '1' */
+       isl6405->override_or = override_set;
+
+       /* bits which should be forced to '0' */
+       isl6405->override_and = ~override_clear;
+
+       /* detect if it is present or not */
+       if (isl6405_set_voltage(fe, SEC_VOLTAGE_OFF)) {
+               kfree(isl6405);
+               fe->sec_priv = NULL;
+               return NULL;
+       }
+
+       /* install release callback */
+       fe->ops.release_sec = isl6405_release;
+
+       /* override frontend ops */
+       fe->ops.set_voltage = isl6405_set_voltage;
+       fe->ops.enable_high_lnb_voltage = isl6405_enable_high_lnb_voltage;
+
+       return fe;
+}
+EXPORT_SYMBOL(isl6405_attach);
+
+MODULE_DESCRIPTION("Driver for lnb supply and control ic isl6405");
+MODULE_AUTHOR("Hartmut Hackmann & Oliver Endriss");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/isl6405.h b/drivers/media/dvb/frontends/isl6405.h
new file mode 100644 (file)
index 0000000..1c793d3
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * isl6405.h - driver for dual lnb supply and control ic ISL6405
+ *
+ * Copyright (C) 2008 Hartmut Hackmann
+ * Copyright (C) 2006 Oliver Endriss
+ *
+ * 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.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ *
+ *
+ * the project's page is at http://www.linuxtv.org
+ */
+
+#ifndef _ISL6405_H
+#define _ISL6405_H
+
+#include <linux/dvb/frontend.h>
+
+/* system register bits */
+
+/* this bit selects register (control) 1 or 2
+   note that the bit maps are different */
+
+#define ISL6405_SR     0x80
+
+/* SR = 0 */
+#define ISL6405_OLF1   0x01
+#define ISL6405_EN1    0x02
+#define ISL6405_VSEL1  0x04
+#define ISL6405_LLC1   0x08
+#define ISL6405_ENT1   0x10
+#define ISL6405_ISEL1  0x20
+#define ISL6405_DCL    0x40
+
+/* SR = 1 */
+#define ISL6405_OLF2   0x01
+#define ISL6405_OTF    0x02
+#define ISL6405_EN2    0x04
+#define ISL6405_VSEL2  0x08
+#define ISL6405_LLC2   0x10
+#define ISL6405_ENT2   0x20
+#define ISL6405_ISEL2  0x40
+
+#if defined(CONFIG_DVB_ISL6405) || (defined(CONFIG_DVB_ISL6405_MODULE) && defined(MODULE))
+/* override_set and override_clear control which system register bits (above)
+ * to always set & clear
+ */
+extern struct dvb_frontend *isl6405_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c,
+                                          u8 i2c_addr, u8 override_set, u8 override_clear);
+#else
+static inline struct dvb_frontend *isl6405_attach(struct dvb_frontend *fe,
+                                                 struct i2c_adapter *i2c, u8 i2c_addr,
+                                                 u8 override_set, u8 override_clear)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return NULL;
+}
+#endif /* CONFIG_DVB_ISL6405 */
+
+#endif
index ea7f78a7d3cd41bce664a6176d922d520c28a5ff..47e4518a042de6b688332df6ff6ca21b38c74844 100644 (file)
@@ -47,7 +47,7 @@ extern struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_a
 static inline struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
                                                  u8 override_set, u8 override_clear)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_ISL6421
diff --git a/drivers/media/dvb/frontends/itd1000.c b/drivers/media/dvb/frontends/itd1000.c
new file mode 100644 (file)
index 0000000..04c562c
--- /dev/null
@@ -0,0 +1,400 @@
+/*
+ *  Driver for the Integrant ITD1000 "Zero-IF Tuner IC for Direct Broadcast Satellite"
+ *
+ *  Copyright (c) 2007-8 Patrick Boettcher <pb@linuxtv.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.
+ *
+ *  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., 675 Mass Ave, Cambridge, MA 02139, USA.=
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/delay.h>
+#include <linux/dvb/frontend.h>
+#include <linux/i2c.h>
+
+#include "dvb_frontend.h"
+
+#include "itd1000.h"
+#include "itd1000_priv.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+
+#define deb(args...)  do { \
+       if (debug) { \
+               printk(KERN_DEBUG   "ITD1000: " args);\
+               printk("\n"); \
+       } \
+} while (0)
+
+#define warn(args...) do { \
+       printk(KERN_WARNING "ITD1000: " args); \
+       printk("\n"); \
+} while (0)
+
+#define info(args...) do { \
+       printk(KERN_INFO    "ITD1000: " args); \
+       printk("\n"); \
+} while (0)
+
+/* don't write more than one byte with flexcop behind */
+static int itd1000_write_regs(struct itd1000_state *state, u8 reg, u8 v[], u8 len)
+{
+       u8 buf[1+len];
+       struct i2c_msg msg = {
+               .addr = state->cfg->i2c_address, .flags = 0, .buf = buf, .len = len+1
+       };
+       buf[0] = reg;
+       memcpy(&buf[1], v, len);
+
+       /* deb("wr %02x: %02x", reg, v[0]); */
+
+       if (i2c_transfer(state->i2c, &msg, 1) != 1) {
+               printk(KERN_WARNING "itd1000 I2C write failed\n");
+               return -EREMOTEIO;
+       }
+       return 0;
+}
+
+static int itd1000_read_reg(struct itd1000_state *state, u8 reg)
+{
+       u8 val;
+       struct i2c_msg msg[2] = {
+               { .addr = state->cfg->i2c_address, .flags = 0,        .buf = &reg, .len = 1 },
+               { .addr = state->cfg->i2c_address, .flags = I2C_M_RD, .buf = &val, .len = 1 },
+       };
+
+       /* ugly flexcop workaround */
+       itd1000_write_regs(state, (reg - 1) & 0xff, &state->shadow[(reg - 1) & 0xff], 1);
+
+       if (i2c_transfer(state->i2c, msg, 2) != 2) {
+               warn("itd1000 I2C read failed");
+               return -EREMOTEIO;
+       }
+       return val;
+}
+
+static inline int itd1000_write_reg(struct itd1000_state *state, u8 r, u8 v)
+{
+       int ret = itd1000_write_regs(state, r, &v, 1);
+       state->shadow[r] = v;
+       return ret;
+}
+
+
+static struct {
+       u32 symbol_rate;
+       u8  pgaext  : 4; /* PLLFH */
+       u8  bbgvmin : 4; /* BBGVMIN */
+} itd1000_lpf_pga[] = {
+       {        0, 0x8, 0x3 },
+       {  5200000, 0x8, 0x3 },
+       { 12200000, 0x4, 0x3 },
+       { 15400000, 0x2, 0x3 },
+       { 19800000, 0x2, 0x3 },
+       { 21500000, 0x2, 0x3 },
+       { 24500000, 0x2, 0x3 },
+       { 28400000, 0x2, 0x3 },
+       { 33400000, 0x2, 0x3 },
+       { 34400000, 0x1, 0x4 },
+       { 34400000, 0x1, 0x4 },
+       { 38400000, 0x1, 0x4 },
+       { 38400000, 0x1, 0x4 },
+       { 40400000, 0x1, 0x4 },
+       { 45400000, 0x1, 0x4 },
+};
+
+static void itd1000_set_lpf_bw(struct itd1000_state *state, u32 symbol_rate)
+{
+       u8 i;
+       u8 con1    = itd1000_read_reg(state, CON1)    & 0xfd;
+       u8 pllfh   = itd1000_read_reg(state, PLLFH)   & 0x0f;
+       u8 bbgvmin = itd1000_read_reg(state, BBGVMIN) & 0xf0;
+       u8 bw      = itd1000_read_reg(state, BW)      & 0xf0;
+
+       deb("symbol_rate = %d", symbol_rate);
+
+       /* not sure what is that ? - starting to download the table */
+       itd1000_write_reg(state, CON1, con1 | (1 << 1));
+
+       for (i = 0; i < ARRAY_SIZE(itd1000_lpf_pga); i++)
+               if (symbol_rate < itd1000_lpf_pga[i].symbol_rate) {
+                       deb("symrate: index: %d pgaext: %x, bbgvmin: %x", i, itd1000_lpf_pga[i].pgaext, itd1000_lpf_pga[i].bbgvmin);
+                       itd1000_write_reg(state, PLLFH,   pllfh | (itd1000_lpf_pga[i].pgaext << 4));
+                       itd1000_write_reg(state, BBGVMIN, bbgvmin | (itd1000_lpf_pga[i].bbgvmin));
+                       itd1000_write_reg(state, BW,      bw | (i & 0x0f));
+                       break;
+               }
+
+       itd1000_write_reg(state, CON1, con1 | (0 << 1));
+}
+
+static struct {
+       u8 vcorg;
+       u32 fmax_rg;
+} itd1000_vcorg[] = {
+       {  1,  920000 },
+       {  2,  971000 },
+       {  3, 1031000 },
+       {  4, 1091000 },
+       {  5, 1171000 },
+       {  6, 1281000 },
+       {  7, 1381000 },
+       {  8,  500000 },        /* this is intentional. */
+       {  9, 1451000 },
+       { 10, 1531000 },
+       { 11, 1631000 },
+       { 12, 1741000 },
+       { 13, 1891000 },
+       { 14, 2071000 },
+       { 15, 2250000 },
+};
+
+static void itd1000_set_vco(struct itd1000_state *state, u32 freq_khz)
+{
+       u8 i;
+       u8 gvbb_i2c     = itd1000_read_reg(state, GVBB_I2C) & 0xbf;
+       u8 vco_chp1_i2c = itd1000_read_reg(state, VCO_CHP1_I2C) & 0x0f;
+       u8 adcout;
+
+       /* reserved bit again (reset ?) */
+       itd1000_write_reg(state, GVBB_I2C, gvbb_i2c | (1 << 6));
+
+       for (i = 0; i < ARRAY_SIZE(itd1000_vcorg); i++) {
+               if (freq_khz < itd1000_vcorg[i].fmax_rg) {
+                       itd1000_write_reg(state, VCO_CHP1_I2C, vco_chp1_i2c | (itd1000_vcorg[i].vcorg << 4));
+                       msleep(1);
+
+                       adcout = itd1000_read_reg(state, PLLLOCK) & 0x0f;
+
+                       deb("VCO: %dkHz: %d -> ADCOUT: %d %02x", freq_khz, itd1000_vcorg[i].vcorg, adcout, vco_chp1_i2c);
+
+                       if (adcout > 13) {
+                               if (!(itd1000_vcorg[i].vcorg == 7 || itd1000_vcorg[i].vcorg == 15))
+                                       itd1000_write_reg(state, VCO_CHP1_I2C, vco_chp1_i2c | ((itd1000_vcorg[i].vcorg + 1) << 4));
+                       } else if (adcout < 2) {
+                               if (!(itd1000_vcorg[i].vcorg == 1 || itd1000_vcorg[i].vcorg == 9))
+                                       itd1000_write_reg(state, VCO_CHP1_I2C, vco_chp1_i2c | ((itd1000_vcorg[i].vcorg - 1) << 4));
+                       }
+                       break;
+               }
+       }
+}
+
+struct {
+       u32 freq;
+       u8 values[10]; /* RFTR, RFST1 - RFST9 */
+} itd1000_fre_values[] = {
+       { 1075000, { 0x59, 0x1d, 0x1c, 0x17, 0x16, 0x0f, 0x0e, 0x0c, 0x0b, 0x0a } },
+       { 1250000, { 0x89, 0x1e, 0x1d, 0x17, 0x15, 0x0f, 0x0e, 0x0c, 0x0b, 0x0a } },
+       { 1450000, { 0x89, 0x1e, 0x1d, 0x17, 0x15, 0x0f, 0x0e, 0x0c, 0x0b, 0x0a } },
+       { 1650000, { 0x69, 0x1e, 0x1d, 0x17, 0x15, 0x0f, 0x0e, 0x0c, 0x0b, 0x0a } },
+       { 1750000, { 0x69, 0x1e, 0x17, 0x15, 0x14, 0x0f, 0x0e, 0x0c, 0x0b, 0x0a } },
+       { 1850000, { 0x69, 0x1d, 0x17, 0x16, 0x14, 0x0f, 0x0e, 0x0d, 0x0b, 0x0a } },
+       { 1900000, { 0x69, 0x1d, 0x17, 0x15, 0x14, 0x0f, 0x0e, 0x0d, 0x0b, 0x0a } },
+       { 1950000, { 0x69, 0x1d, 0x17, 0x16, 0x14, 0x13, 0x0e, 0x0d, 0x0b, 0x0a } },
+       { 2050000, { 0x69, 0x1e, 0x1d, 0x17, 0x16, 0x14, 0x13, 0x0e, 0x0b, 0x0a } },
+       { 2150000, { 0x69, 0x1d, 0x1c, 0x17, 0x15, 0x14, 0x13, 0x0f, 0x0e, 0x0b } }
+};
+
+
+#define FREF 16
+
+static void itd1000_set_lo(struct itd1000_state *state, u32 freq_khz)
+{
+       int i, j;
+       u32 plln, pllf;
+       u64 tmp;
+
+       plln = (freq_khz * 1000) / 2 / FREF;
+
+       /* Compute the factional part times 1000 */
+       tmp  = plln % 1000000;
+       plln /= 1000000;
+
+       tmp *= 1048576;
+       do_div(tmp, 1000000);
+       pllf = (u32) tmp;
+
+       state->frequency = ((plln * 1000) + (pllf * 1000)/1048576) * 2*FREF;
+       deb("frequency: %dkHz (wanted) %dkHz (set), PLLF = %d, PLLN = %d", freq_khz, state->frequency, pllf, plln);
+
+       itd1000_write_reg(state, PLLNH, 0x80); /* PLLNH */;
+       itd1000_write_reg(state, PLLNL, plln & 0xff);
+       itd1000_write_reg(state, PLLFH, (itd1000_read_reg(state, PLLFH) & 0xf0) | ((pllf >> 16) & 0x0f));
+       itd1000_write_reg(state, PLLFM, (pllf >> 8) & 0xff);
+       itd1000_write_reg(state, PLLFL, (pllf >> 0) & 0xff);
+
+       for (i = 0; i < ARRAY_SIZE(itd1000_fre_values); i++) {
+               if (freq_khz <= itd1000_fre_values[i].freq) {
+                       deb("fre_values: %d", i);
+                       itd1000_write_reg(state, RFTR, itd1000_fre_values[i].values[0]);
+                       for (j = 0; j < 9; j++)
+                               itd1000_write_reg(state, RFST1+j, itd1000_fre_values[i].values[j+1]);
+                       break;
+               }
+       }
+
+       itd1000_set_vco(state, freq_khz);
+}
+
+static int itd1000_set_parameters(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
+{
+       struct itd1000_state *state = fe->tuner_priv;
+       u8 pllcon1;
+
+       itd1000_set_lo(state, p->frequency);
+       itd1000_set_lpf_bw(state, p->u.qpsk.symbol_rate);
+
+       pllcon1 = itd1000_read_reg(state, PLLCON1) & 0x7f;
+       itd1000_write_reg(state, PLLCON1, pllcon1 | (1 << 7));
+       itd1000_write_reg(state, PLLCON1, pllcon1);
+
+       return 0;
+}
+
+static int itd1000_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+       struct itd1000_state *state = fe->tuner_priv;
+       *frequency = state->frequency;
+       return 0;
+}
+
+static int itd1000_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+{
+       return 0;
+}
+
+static u8 itd1000_init_tab[][2] = {
+       { PLLCON1,       0x65 }, /* Register does not change */
+       { PLLNH,         0x80 }, /* Bits [7:6] do not change */
+       { RESERVED_0X6D, 0x3b },
+       { VCO_CHP2_I2C,  0x12 },
+       { 0x72,          0xf9 }, /* No such regsister defined */
+       { RESERVED_0X73, 0xff },
+       { RESERVED_0X74, 0xb2 },
+       { RESERVED_0X75, 0xc7 },
+       { EXTGVBBRF,     0xf0 },
+       { DIVAGCCK,      0x80 },
+       { BBTR,          0xa0 },
+       { RESERVED_0X7E, 0x4f },
+       { 0x82,          0x88 }, /* No such regsister defined */
+       { 0x83,          0x80 }, /* No such regsister defined */
+       { 0x84,          0x80 }, /* No such regsister defined */
+       { RESERVED_0X85, 0x74 },
+       { RESERVED_0X86, 0xff },
+       { RESERVED_0X88, 0x02 },
+       { RESERVED_0X89, 0x16 },
+       { RFST0,         0x1f },
+       { RESERVED_0X94, 0x66 },
+       { RESERVED_0X95, 0x66 },
+       { RESERVED_0X96, 0x77 },
+       { RESERVED_0X97, 0x99 },
+       { RESERVED_0X98, 0xff },
+       { RESERVED_0X99, 0xfc },
+       { RESERVED_0X9A, 0xba },
+       { RESERVED_0X9B, 0xaa },
+};
+
+static u8 itd1000_reinit_tab[][2] = {
+       { VCO_CHP1_I2C, 0x8a },
+       { BW,           0x87 },
+       { GVBB_I2C,     0x03 },
+       { BBGVMIN,      0x03 },
+       { CON1,         0x2e },
+};
+
+
+static int itd1000_init(struct dvb_frontend *fe)
+{
+       struct itd1000_state *state = fe->tuner_priv;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(itd1000_init_tab); i++)
+               itd1000_write_reg(state, itd1000_init_tab[i][0], itd1000_init_tab[i][1]);
+
+       for (i = 0; i < ARRAY_SIZE(itd1000_reinit_tab); i++)
+               itd1000_write_reg(state, itd1000_reinit_tab[i][0], itd1000_reinit_tab[i][1]);
+
+       return 0;
+}
+
+static int itd1000_sleep(struct dvb_frontend *fe)
+{
+       return 0;
+}
+
+static int itd1000_release(struct dvb_frontend *fe)
+{
+       kfree(fe->tuner_priv);
+       fe->tuner_priv = NULL;
+       return 0;
+}
+
+static const struct dvb_tuner_ops itd1000_tuner_ops = {
+       .info = {
+               .name           = "Integrant ITD1000",
+               .frequency_min  = 950000,
+               .frequency_max  = 2150000,
+               .frequency_step = 125,     /* kHz for QPSK frontends */
+       },
+
+       .release       = itd1000_release,
+
+       .init          = itd1000_init,
+       .sleep         = itd1000_sleep,
+
+       .set_params    = itd1000_set_parameters,
+       .get_frequency = itd1000_get_frequency,
+       .get_bandwidth = itd1000_get_bandwidth
+};
+
+
+struct dvb_frontend *itd1000_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct itd1000_config *cfg)
+{
+       struct itd1000_state *state = NULL;
+       u8 i = 0;
+
+       state = kzalloc(sizeof(struct itd1000_state), GFP_KERNEL);
+       if (state == NULL)
+               return NULL;
+
+       state->cfg = cfg;
+       state->i2c = i2c;
+
+       i = itd1000_read_reg(state, 0);
+       if (i != 0) {
+               kfree(state);
+               return NULL;
+       }
+       info("successfully identified (ID: %d)", i);
+
+       memset(state->shadow, 0xff, sizeof(state->shadow));
+       for (i = 0x65; i < 0x9c; i++)
+               state->shadow[i] = itd1000_read_reg(state, i);
+
+       memcpy(&fe->ops.tuner_ops, &itd1000_tuner_ops, sizeof(struct dvb_tuner_ops));
+
+       fe->tuner_priv = state;
+
+       return fe;
+}
+EXPORT_SYMBOL(itd1000_attach);
+
+MODULE_AUTHOR("Patrick Boettcher <pb@linuxtv.org>");
+MODULE_DESCRIPTION("Integrant ITD1000 driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/itd1000.h b/drivers/media/dvb/frontends/itd1000.h
new file mode 100644 (file)
index 0000000..5e18df0
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ *  Driver for the Integrant ITD1000 "Zero-IF Tuner IC for Direct Broadcast Satellite"
+ *
+ *  Copyright (c) 2007 Patrick Boettcher <pb@linuxtv.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.
+ *
+ *  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., 675 Mass Ave, Cambridge, MA 02139, USA.=
+ */
+
+#ifndef ITD1000_H
+#define ITD1000_H
+
+struct dvb_frontend;
+struct i2c_adapter;
+
+struct itd1000_config {
+       u8 i2c_address;
+};
+
+#if defined(CONFIG_DVB_TUNER_ITD1000) || (defined(CONFIG_DVB_TUNER_ITD1000_MODULE) && defined(MODULE))
+extern struct dvb_frontend *itd1000_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct itd1000_config *cfg);
+#else
+static inline struct dvb_frontend *itd1000_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct itd1000_config *cfg)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return NULL;
+}
+#endif
+
+#endif
diff --git a/drivers/media/dvb/frontends/itd1000_priv.h b/drivers/media/dvb/frontends/itd1000_priv.h
new file mode 100644 (file)
index 0000000..8cdc54e
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ *  Driver for the Integrant ITD1000 "Zero-IF Tuner IC for Direct Broadcast Satellite"
+ *
+ *  Copyright (c) 2007 Patrick Boettcher <pb@linuxtv.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.
+ *
+ *  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., 675 Mass Ave, Cambridge, MA 02139, USA.=
+ */
+
+#ifndef ITD1000_PRIV_H
+#define ITD1000_PRIV_H
+
+struct itd1000_state {
+       struct itd1000_config *cfg;
+       struct i2c_adapter    *i2c;
+
+       u32 frequency; /* contains the value resulting from the LO-setting */
+
+       /* ugly workaround for flexcop's incapable i2c-controller
+        * FIXME, if possible
+        */
+       u8 shadow[255];
+};
+
+enum itd1000_register {
+       VCO_CHP1 = 0x65,
+       VCO_CHP2,
+       PLLCON1,
+       PLLNH,
+       PLLNL,
+       PLLFH,
+       PLLFM,
+       PLLFL,
+       RESERVED_0X6D,
+       PLLLOCK,
+       VCO_CHP2_I2C,
+       VCO_CHP1_I2C,
+       BW,
+       RESERVED_0X73 = 0x73,
+       RESERVED_0X74,
+       RESERVED_0X75,
+       GVBB,
+       GVRF,
+       GVBB_I2C,
+       EXTGVBBRF,
+       DIVAGCCK,
+       BBTR,
+       RFTR,
+       BBGVMIN,
+       RESERVED_0X7E,
+       RESERVED_0X85 = 0x85,
+       RESERVED_0X86,
+       CON1,
+       RESERVED_0X88,
+       RESERVED_0X89,
+       RFST0,
+       RFST1,
+       RFST2,
+       RFST3,
+       RFST4,
+       RFST5,
+       RFST6,
+       RFST7,
+       RFST8,
+       RFST9,
+       RESERVED_0X94,
+       RESERVED_0X95,
+       RESERVED_0X96,
+       RESERVED_0X97,
+       RESERVED_0X98,
+       RESERVED_0X99,
+       RESERVED_0X9A,
+       RESERVED_0X9B,
+};
+
+#endif
index 443d9045d4c9b8d93ec8fa2f53a18f9351166d6c..e1e70e9e0cb9ced61f4b71f96a882bff38d40965 100644 (file)
@@ -57,7 +57,7 @@ static int l64781_writereg (struct l64781_state* state, u8 reg, u8 data)
 
        if ((ret = i2c_transfer(state->i2c, &msg, 1)) != 1)
                dprintk ("%s: write_reg error (reg == %02x) = %02x!\n",
-                        __FUNCTION__, reg, ret);
+                        __func__, reg, ret);
 
        return (ret != 1) ? -1 : 0;
 }
index cd15f76ff28da22f6ae1157ec7d3871a9dfb4f21..1305a9e7fb0b543bab0c18d3e05655cd67c2c7bf 100644 (file)
@@ -38,7 +38,7 @@ extern struct dvb_frontend* l64781_attach(const struct l64781_config* config,
 static inline struct dvb_frontend* l64781_attach(const struct l64781_config* config,
                                          struct i2c_adapter* i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_L64781
index bdc9fa88b86afc93128f43de48adabfb1818bca2..f0195c8272f4486c4c67d402025f50e0bfe64d75 100644 (file)
@@ -49,7 +49,7 @@
 /* Use Equalizer Mean Squared Error instead of Phaser Tracker MSE */
 /* #define USE_EQMSE */
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug,"Turn on/off lgdt330x frontend debugging (default:off).");
 #define dprintk(args...) \
@@ -88,7 +88,7 @@ static int i2c_write_demod_bytes (struct lgdt330x_state* state,
 
        for (i=0; i<len-1; i+=2){
                if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
-                       printk(KERN_WARNING "lgdt330x: %s error (addr %02x <- %02x, err = %i)\n", __FUNCTION__, msg.buf[0], msg.buf[1], err);
+                       printk(KERN_WARNING "lgdt330x: %s error (addr %02x <- %02x, err = %i)\n", __func__, msg.buf[0], msg.buf[1], err);
                        if (err < 0)
                                return err;
                        else
@@ -117,7 +117,7 @@ static u8 i2c_read_demod_bytes (struct lgdt330x_state* state,
        int ret;
        ret = i2c_transfer(state->i2c, msg, 2);
        if (ret != 2) {
-               printk(KERN_WARNING "lgdt330x: %s: addr 0x%02x select 0x%02x error (ret == %i)\n", __FUNCTION__, state->config->demod_address, reg, ret);
+               printk(KERN_WARNING "lgdt330x: %s: addr 0x%02x select 0x%02x error (ret == %i)\n", __func__, state->config->demod_address, reg, ret);
        } else {
                ret = 0;
        }
@@ -256,7 +256,7 @@ static int lgdt330x_init(struct dvb_frontend* fe)
                printk (KERN_WARNING "Only LGDT3302 and LGDT3303 are supported chips.\n");
                err = -ENODEV;
        }
-       dprintk("%s entered as %s\n", __FUNCTION__, chip_name);
+       dprintk("%s entered as %s\n", __func__, chip_name);
        if (err < 0)
                return err;
        return lgdt330x_SwReset(state);
@@ -334,7 +334,7 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
        if (state->current_modulation != param->u.vsb.modulation) {
                switch(param->u.vsb.modulation) {
                case VSB_8:
-                       dprintk("%s: VSB_8 MODE\n", __FUNCTION__);
+                       dprintk("%s: VSB_8 MODE\n", __func__);
 
                        /* Select VSB mode */
                        top_ctrl_cfg[1] = 0x03;
@@ -350,7 +350,7 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
                        break;
 
                case QAM_64:
-                       dprintk("%s: QAM_64 MODE\n", __FUNCTION__);
+                       dprintk("%s: QAM_64 MODE\n", __func__);
 
                        /* Select QAM_64 mode */
                        top_ctrl_cfg[1] = 0x00;
@@ -366,7 +366,7 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
                        break;
 
                case QAM_256:
-                       dprintk("%s: QAM_256 MODE\n", __FUNCTION__);
+                       dprintk("%s: QAM_256 MODE\n", __func__);
 
                        /* Select QAM_256 mode */
                        top_ctrl_cfg[1] = 0x01;
@@ -381,7 +381,7 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
                        }
                        break;
                default:
-                       printk(KERN_WARNING "lgdt330x: %s: Modulation type(%d) UNSUPPORTED\n", __FUNCTION__, param->u.vsb.modulation);
+                       printk(KERN_WARNING "lgdt330x: %s: Modulation type(%d) UNSUPPORTED\n", __func__, param->u.vsb.modulation);
                        return -1;
                }
                /*
@@ -431,7 +431,7 @@ static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status)
 
        /* AGC status register */
        i2c_read_demod_bytes(state, AGC_STATUS, buf, 1);
-       dprintk("%s: AGC_STATUS = 0x%02x\n", __FUNCTION__, buf[0]);
+       dprintk("%s: AGC_STATUS = 0x%02x\n", __func__, buf[0]);
        if ((buf[0] & 0x0c) == 0x8){
                /* Test signal does not exist flag */
                /* as well as the AGC lock flag.   */
@@ -445,7 +445,7 @@ static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status)
         */
        /* signal status */
        i2c_read_demod_bytes(state, TOP_CONTROL, buf, sizeof(buf));
-       dprintk("%s: TOP_CONTROL = 0x%02x, IRO_MASK = 0x%02x, IRQ_STATUS = 0x%02x\n", __FUNCTION__, buf[0], buf[1], buf[2]);
+       dprintk("%s: TOP_CONTROL = 0x%02x, IRO_MASK = 0x%02x, IRQ_STATUS = 0x%02x\n", __func__, buf[0], buf[1], buf[2]);
 
 
        /* sync status */
@@ -461,7 +461,7 @@ static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status)
 
        /* Carrier Recovery Lock Status Register */
        i2c_read_demod_bytes(state, CARRIER_LOCK, buf, 1);
-       dprintk("%s: CARRIER_LOCK = 0x%02x\n", __FUNCTION__, buf[0]);
+       dprintk("%s: CARRIER_LOCK = 0x%02x\n", __func__, buf[0]);
        switch (state->current_modulation) {
        case QAM_256:
        case QAM_64:
@@ -474,7 +474,7 @@ static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status)
                        *status |= FE_HAS_CARRIER;
                break;
        default:
-               printk(KERN_WARNING "lgdt330x: %s: Modulation set to unsupported value\n", __FUNCTION__);
+               printk(KERN_WARNING "lgdt330x: %s: Modulation set to unsupported value\n", __func__);
        }
 
        return 0;
@@ -493,7 +493,7 @@ static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status)
        if (err < 0)
                return err;
 
-       dprintk("%s: AGC_STATUS = 0x%02x\n", __FUNCTION__, buf[0]);
+       dprintk("%s: AGC_STATUS = 0x%02x\n", __func__, buf[0]);
        if ((buf[0] & 0x21) == 0x01){
                /* Test input signal does not exist flag */
                /* as well as the AGC lock flag.   */
@@ -502,7 +502,7 @@ static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status)
 
        /* Carrier Recovery Lock Status Register */
        i2c_read_demod_bytes(state, CARRIER_LOCK, buf, 1);
-       dprintk("%s: CARRIER_LOCK = 0x%02x\n", __FUNCTION__, buf[0]);
+       dprintk("%s: CARRIER_LOCK = 0x%02x\n", __func__, buf[0]);
        switch (state->current_modulation) {
        case QAM_256:
        case QAM_64:
@@ -533,7 +533,7 @@ static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status)
                }
                break;
        default:
-               printk(KERN_WARNING "lgdt330x: %s: Modulation set to unsupported value\n", __FUNCTION__);
+               printk(KERN_WARNING "lgdt330x: %s: Modulation set to unsupported value\n", __func__);
        }
        return 0;
 }
@@ -607,14 +607,14 @@ static int lgdt3302_read_snr(struct dvb_frontend* fe, u16* snr)
                break;
        default:
                printk(KERN_ERR "lgdt330x: %s: Modulation set to unsupported value\n",
-                      __FUNCTION__);
+                      __func__);
                return -EREMOTEIO; /* return -EDRIVER_IS_GIBBERED; */
        }
 
        state->snr = calculate_snr(noise, c);
        *snr = (state->snr) >> 16; /* Convert from 8.24 fixed-point to 8.8 */
 
-       dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __FUNCTION__, noise,
+       dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __func__, noise,
                state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16);
 
        return 0;
@@ -651,14 +651,14 @@ static int lgdt3303_read_snr(struct dvb_frontend* fe, u16* snr)
                break;
        default:
                printk(KERN_ERR "lgdt330x: %s: Modulation set to unsupported value\n",
-                      __FUNCTION__);
+                      __func__);
                return -EREMOTEIO; /* return -EDRIVER_IS_GIBBERED; */
        }
 
        state->snr = calculate_snr(noise, c);
        *snr = (state->snr) >> 16; /* Convert from 8.24 fixed-point to 8.8 */
 
-       dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __FUNCTION__, noise,
+       dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __func__, noise,
                state->snr >> 24, (((state->snr >> 8) & 0xffff) * 100) >> 16);
 
        return 0;
@@ -743,7 +743,7 @@ struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
 
 error:
        kfree(state);
-       dprintk("%s: ERROR\n",__FUNCTION__);
+       dprintk("%s: ERROR\n",__func__);
        return NULL;
 }
 
index 995059004b109918a9909b2dfb607030129273c7..9012504f0f2d523523ff2e3dbc0b1cca2dcd7086 100644 (file)
@@ -59,7 +59,7 @@ extern struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config
 static inline struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
                                            struct i2c_adapter* i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_LGDT330X
index 68906acf7d63d75405ad58340d5a5752a0dd63e9..8fe094bd9689a1e793ce2d553abc5a306c9143c5 100644 (file)
@@ -45,7 +45,7 @@ extern struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe, struct i2c_ad
 #else
 static inline struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_LNBP21
index 0a86eab3a954d376d27a0ba4a9624a7692567380..acba0058f519bf00403a78b56b369de56f8c6a9c 100644 (file)
@@ -35,7 +35,7 @@ extern struct dvb_frontend * mt2060_attach(struct dvb_frontend *fe, struct i2c_a
 #else
 static inline struct dvb_frontend * mt2060_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2060_config *cfg, u16 if1)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_TUNER_MT2060
index 13cf16668171bb611b73ac143e7a77bfcf34b89e..e254bcfc2efb77df010cdae10d482eaeb884afb4 100644 (file)
@@ -110,7 +110,7 @@ static int mt2131_set_params(struct dvb_frontend *fe,
                priv->bandwidth = 0;
 
        freq = params->frequency / 1000;  // Hz -> kHz
-       dprintk(1, "%s() freq=%d\n", __FUNCTION__, freq);
+       dprintk(1, "%s() freq=%d\n", __func__, freq);
 
        f_lo1 = freq + MT2131_IF1 * 1000;
        f_lo1 = (f_lo1 / 250) * 250;
@@ -187,7 +187,7 @@ static int mt2131_set_params(struct dvb_frontend *fe,
 static int mt2131_get_frequency(struct dvb_frontend *fe, u32 *frequency)
 {
        struct mt2131_priv *priv = fe->tuner_priv;
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
        *frequency = priv->frequency;
        return 0;
 }
@@ -195,7 +195,7 @@ static int mt2131_get_frequency(struct dvb_frontend *fe, u32 *frequency)
 static int mt2131_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
 {
        struct mt2131_priv *priv = fe->tuner_priv;
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
        *bandwidth = priv->bandwidth;
        return 0;
 }
@@ -214,7 +214,7 @@ static int mt2131_get_status(struct dvb_frontend *fe, u32 *status)
 
        mt2131_readreg(priv, 0x09, &afc_status);
        dprintk(1, "%s() - LO Status = 0x%x, AFC Status = 0x%x\n",
-               __FUNCTION__, lock_status, afc_status);
+               __func__, lock_status, afc_status);
 
        return 0;
 }
@@ -223,7 +223,7 @@ static int mt2131_init(struct dvb_frontend *fe)
 {
        struct mt2131_priv *priv = fe->tuner_priv;
        int ret;
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
 
        if ((ret = mt2131_writeregs(priv, mt2131_config1,
                                    sizeof(mt2131_config1))) < 0)
@@ -243,7 +243,7 @@ static int mt2131_init(struct dvb_frontend *fe)
 
 static int mt2131_release(struct dvb_frontend *fe)
 {
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
        kfree(fe->tuner_priv);
        fe->tuner_priv = NULL;
        return 0;
@@ -273,7 +273,7 @@ struct dvb_frontend * mt2131_attach(struct dvb_frontend *fe,
        struct mt2131_priv *priv = NULL;
        u8 id = 0;
 
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
 
        priv = kzalloc(sizeof(struct mt2131_priv), GFP_KERNEL);
        if (priv == NULL)
index 1e4ffe7dc8c89ead1f5c5c1b529bf6f7b6549510..606d8576bc9885d2a7d8a9c504d41efcb860be76 100644 (file)
@@ -41,7 +41,7 @@ static inline struct dvb_frontend* mt2131_attach(struct dvb_frontend *fe,
                                                 struct mt2131_config *cfg,
                                                 u16 if1)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif /* CONFIG_DVB_TUNER_MT2131 */
index f31dd613ad37979005babdfb2c65c0c46cf6d9c1..c5113efe333c745a0e66919827a88b42073f3719 100644 (file)
@@ -29,7 +29,7 @@ extern struct dvb_frontend * mt2266_attach(struct dvb_frontend *fe, struct i2c_a
 #else
 static inline struct dvb_frontend * mt2266_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2266_config *cfg)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_TUNER_MT2266
index 1638301fbd6e71268812f48beddc1cea1b0cb127..081ca3398c76b074012f4fa99d7f41910d30e165 100644 (file)
@@ -1,7 +1,8 @@
 /*
-    Driver for Zarlink VP310/MT312 Satellite Channel Decoder
+    Driver for Zarlink VP310/MT312/ZL10313 Satellite Channel Decoder
 
     Copyright (C) 2003 Andreas Oberritter <obi@linuxtv.org>
+    Copyright (C) 2008 Matthias Schwarzott <zzam@gentoo.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
@@ -43,7 +44,8 @@ struct mt312_state {
        struct dvb_frontend frontend;
 
        u8 id;
-       u8 frequency;
+       unsigned long xtal;
+       u8 freq_mult;
 };
 
 static int debug;
@@ -53,12 +55,11 @@ static int debug;
                        printk(KERN_DEBUG "mt312: " args); \
        } while (0)
 
-#define MT312_SYS_CLK          90000000UL      /* 90 MHz */
-#define MT312_LPOWER_SYS_CLK   60000000UL      /* 60 MHz */
 #define MT312_PLL_CLK          10000000UL      /* 10 MHz */
+#define MT312_PLL_CLK_10_111   10111000UL      /* 10.111 MHz */
 
 static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg,
-                     void *buf, const size_t count)
+                     u8 *buf, const size_t count)
 {
        int ret;
        struct i2c_msg msg[2];
@@ -76,7 +77,7 @@ static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg,
        ret = i2c_transfer(state->i2c, msg, 2);
 
        if (ret != 2) {
-               printk(KERN_ERR "%s: ret == %d\n", __FUNCTION__, ret);
+               printk(KERN_ERR "%s: ret == %d\n", __func__, ret);
                return -EREMOTEIO;
        }
 
@@ -84,7 +85,7 @@ static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg,
                int i;
                dprintk("R(%d):", reg & 0x7f);
                for (i = 0; i < count; i++)
-                       printk(" %02x", ((const u8 *) buf)[i]);
+                       printk(" %02x", buf[i]);
                printk("\n");
        }
 
@@ -92,7 +93,7 @@ static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg,
 }
 
 static int mt312_write(struct mt312_state *state, const enum mt312_reg_addr reg,
-                      const void *src, const size_t count)
+                      const u8 *src, const size_t count)
 {
        int ret;
        u8 buf[count + 1];
@@ -102,7 +103,7 @@ static int mt312_write(struct mt312_state *state, const enum mt312_reg_addr reg,
                int i;
                dprintk("W(%d):", reg & 0x7f);
                for (i = 0; i < count; i++)
-                       printk(" %02x", ((const u8 *) src)[i]);
+                       printk(" %02x", src[i]);
                printk("\n");
        }
 
@@ -117,7 +118,7 @@ static int mt312_write(struct mt312_state *state, const enum mt312_reg_addr reg,
        ret = i2c_transfer(state->i2c, &msg, 1);
 
        if (ret != 1) {
-               dprintk("%s: ret == %d\n", __FUNCTION__, ret);
+               dprintk("%s: ret == %d\n", __func__, ret);
                return -EREMOTEIO;
        }
 
@@ -209,7 +210,7 @@ static int mt312_get_symbol_rate(struct mt312_state *state, u32 *sr)
                dprintk("sym_rat_op=%d dec_ratio=%d\n",
                       sym_rat_op, dec_ratio);
                dprintk("*sr(manual) = %lu\n",
-                      (((MT312_PLL_CLK * 8192) / (sym_rat_op + 8192)) *
+                      (((state->xtal * 8192) / (sym_rat_op + 8192)) *
                        2) - dec_ratio);
        }
 
@@ -242,7 +243,7 @@ static int mt312_initfe(struct dvb_frontend *fe)
 
        /* wake up */
        ret = mt312_writereg(state, CONFIG,
-                       (state->frequency == 60 ? 0x88 : 0x8c));
+                       (state->freq_mult == 6 ? 0x88 : 0x8c));
        if (ret < 0)
                return ret;
 
@@ -265,12 +266,37 @@ static int mt312_initfe(struct dvb_frontend *fe)
                        return ret;
        }
 
+       switch (state->id) {
+       case ID_ZL10313:
+               /* enable ADC */
+               ret = mt312_writereg(state, GPP_CTRL, 0x80);
+               if (ret < 0)
+                       return ret;
+
+               /* configure ZL10313 for optimal ADC performance */
+               buf[0] = 0x80;
+               buf[1] = 0xB0;
+               ret = mt312_write(state, HW_CTRL, buf, 2);
+               if (ret < 0)
+                       return ret;
+
+               /* enable MPEG output and ADCs */
+               ret = mt312_writereg(state, HW_CTRL, 0x00);
+               if (ret < 0)
+                       return ret;
+
+               ret = mt312_writereg(state, MPEG_CTRL, 0x00);
+               if (ret < 0)
+                       return ret;
+
+               break;
+       }
+
        /* SYS_CLK */
-       buf[0] = mt312_div((state->frequency == 60 ? MT312_LPOWER_SYS_CLK :
-                               MT312_SYS_CLK) * 2, 1000000);
+       buf[0] = mt312_div(state->xtal * state->freq_mult * 2, 1000000);
 
        /* DISEQC_RATIO */
-       buf[1] = mt312_div(MT312_PLL_CLK, 15000 * 4);
+       buf[1] = mt312_div(state->xtal, 22000 * 4);
 
        ret = mt312_write(state, SYS_CLK, buf, sizeof(buf));
        if (ret < 0)
@@ -280,7 +306,17 @@ static int mt312_initfe(struct dvb_frontend *fe)
        if (ret < 0)
                return ret;
 
-       ret = mt312_writereg(state, OP_CTRL, 0x53);
+       /* different MOCLK polarity */
+       switch (state->id) {
+       case ID_ZL10313:
+               buf[0] = 0x33;
+               break;
+       default:
+               buf[0] = 0x53;
+               break;
+       }
+
+       ret = mt312_writereg(state, OP_CTRL, buf[0]);
        if (ret < 0)
                return ret;
 
@@ -323,6 +359,9 @@ static int mt312_send_master_cmd(struct dvb_frontend *fe,
        if (ret < 0)
                return ret;
 
+       /* is there a better way to wait for message to be transmitted */
+       msleep(100);
+
        /* set DISEQC_MODE[2:0] to zero if a return message is expected */
        if (c->msg[0] & 0x02) {
                ret = mt312_writereg(state, DISEQC_MODE, (diseqc_mode & 0x40));
@@ -383,11 +422,16 @@ static int mt312_set_voltage(struct dvb_frontend *fe, const fe_sec_voltage_t v)
 {
        struct mt312_state *state = fe->demodulator_priv;
        const u8 volt_tab[3] = { 0x00, 0x40, 0x00 };
+       u8 val;
 
        if (v > SEC_VOLTAGE_OFF)
                return -EINVAL;
 
-       return mt312_writereg(state, DISEQC_MODE, volt_tab[v]);
+       val = volt_tab[v];
+       if (state->config->voltage_inverted)
+               val ^= 0x40;
+
+       return mt312_writereg(state, DISEQC_MODE, val);
 }
 
 static int mt312_read_status(struct dvb_frontend *fe, fe_status_t *s)
@@ -463,7 +507,7 @@ static int mt312_read_snr(struct dvb_frontend *fe, u16 *snr)
        int ret;
        u8 buf[2];
 
-       ret = mt312_read(state, M_SNR_H, &buf, sizeof(buf));
+       ret = mt312_read(state, M_SNR_H, buf, sizeof(buf));
        if (ret < 0)
                return ret;
 
@@ -478,7 +522,7 @@ static int mt312_read_ucblocks(struct dvb_frontend *fe, u32 *ubc)
        int ret;
        u8 buf[2];
 
-       ret = mt312_read(state, RS_UBC_H, &buf, sizeof(buf));
+       ret = mt312_read(state, RS_UBC_H, buf, sizeof(buf));
        if (ret < 0)
                return ret;
 
@@ -499,7 +543,7 @@ static int mt312_set_frontend(struct dvb_frontend *fe,
            { 0x00, 0x01, 0x02, 0x04, 0x3f, 0x08, 0x10, 0x20, 0x3f, 0x3f };
        const u8 inv_tab[3] = { 0x00, 0x40, 0x80 };
 
-       dprintk("%s: Freq %d\n", __FUNCTION__, p->frequency);
+       dprintk("%s: Freq %d\n", __func__, p->frequency);
 
        if ((p->frequency < fe->ops.info.frequency_min)
            || (p->frequency > fe->ops.info.frequency_max))
@@ -532,17 +576,17 @@ static int mt312_set_frontend(struct dvb_frontend *fe,
                        return ret;
                if (p->u.qpsk.symbol_rate >= 30000000) {
                        /* Note that 30MS/s should use 90MHz */
-                       if ((config_val & 0x0c) == 0x08) {
+                       if (state->freq_mult == 6) {
                                /* We are running 60MHz */
-                               state->frequency = 90;
+                               state->freq_mult = 9;
                                ret = mt312_initfe(fe);
                                if (ret < 0)
                                        return ret;
                        }
                } else {
-                       if ((config_val & 0x0c) == 0x0C) {
+                       if (state->freq_mult == 9) {
                                /* We are running 90MHz */
-                               state->frequency = 60;
+                               state->freq_mult = 6;
                                ret = mt312_initfe(fe);
                                if (ret < 0)
                                        return ret;
@@ -551,6 +595,7 @@ static int mt312_set_frontend(struct dvb_frontend *fe,
                break;
 
        case ID_MT312:
+       case ID_ZL10313:
                break;
 
        default:
@@ -616,11 +661,29 @@ static int mt312_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
 {
        struct mt312_state *state = fe->demodulator_priv;
 
-       if (enable) {
-               return mt312_writereg(state, GPP_CTRL, 0x40);
-       } else {
-               return mt312_writereg(state, GPP_CTRL, 0x00);
+       u8 val = 0x00;
+       int ret;
+
+       switch (state->id) {
+       case ID_ZL10313:
+               ret = mt312_readreg(state, GPP_CTRL, &val);
+               if (ret < 0)
+                       goto error;
+
+               /* preserve this bit to not accidently shutdown ADC */
+               val &= 0x80;
+               break;
        }
+
+       if (enable)
+               val |= 0x40;
+       else
+               val &= ~0x40;
+
+       ret = mt312_writereg(state, GPP_CTRL, val);
+
+error:
+       return ret;
 }
 
 static int mt312_sleep(struct dvb_frontend *fe)
@@ -634,6 +697,18 @@ static int mt312_sleep(struct dvb_frontend *fe)
        if (ret < 0)
                return ret;
 
+       if (state->id == ID_ZL10313) {
+               /* reset ADC */
+               ret = mt312_writereg(state, GPP_CTRL, 0x00);
+               if (ret < 0)
+                       return ret;
+
+               /* full shutdown of ADCs, mpeg bus tristated */
+               ret = mt312_writereg(state, HW_CTRL, 0x0d);
+               if (ret < 0)
+                       return ret;
+       }
+
        ret = mt312_readreg(state, CONFIG, &config);
        if (ret < 0)
                return ret;
@@ -661,6 +736,7 @@ static void mt312_release(struct dvb_frontend *fe)
        kfree(state);
 }
 
+#define MT312_SYS_CLK          90000000UL      /* 90 MHz */
 static struct dvb_frontend_ops vp310_mt312_ops = {
 
        .info = {
@@ -668,8 +744,8 @@ static struct dvb_frontend_ops vp310_mt312_ops = {
                .type = FE_QPSK,
                .frequency_min = 950000,
                .frequency_max = 2150000,
-               .frequency_stepsize = (MT312_PLL_CLK / 1000) / 128,
-               .symbol_rate_min = MT312_SYS_CLK / 128,
+               .frequency_stepsize = (MT312_PLL_CLK / 1000) / 128, /* FIXME: adjust freq to real used xtal */
+               .symbol_rate_min = MT312_SYS_CLK / 128, /* FIXME as above */
                .symbol_rate_max = MT312_SYS_CLK / 2,
                .caps =
                    FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 |
@@ -726,14 +802,21 @@ struct dvb_frontend *vp310_mt312_attach(const struct mt312_config *config,
        switch (state->id) {
        case ID_VP310:
                strcpy(state->frontend.ops.info.name, "Zarlink VP310 DVB-S");
-               state->frequency = 90;
+               state->xtal = MT312_PLL_CLK;
+               state->freq_mult = 9;
                break;
        case ID_MT312:
                strcpy(state->frontend.ops.info.name, "Zarlink MT312 DVB-S");
-               state->frequency = 60;
+               state->xtal = MT312_PLL_CLK;
+               state->freq_mult = 6;
+               break;
+       case ID_ZL10313:
+               strcpy(state->frontend.ops.info.name, "Zarlink ZL10313 DVB-S");
+               state->xtal = MT312_PLL_CLK_10_111;
+               state->freq_mult = 9;
                break;
        default:
-               printk(KERN_WARNING "Only Zarlink VP310/MT312"
+               printk(KERN_WARNING "Only Zarlink VP310/MT312/ZL10313"
                        " are supported chips.\n");
                goto error;
        }
@@ -749,7 +832,7 @@ EXPORT_SYMBOL(vp310_mt312_attach);
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
 
-MODULE_DESCRIPTION("Zarlink VP310/MT312 DVB-S Demodulator driver");
+MODULE_DESCRIPTION("Zarlink VP310/MT312/ZL10313 DVB-S Demodulator driver");
 MODULE_AUTHOR("Andreas Oberritter <obi@linuxtv.org>");
 MODULE_LICENSE("GPL");
 
index f17cb93ba9ba068e8a486cd804176b3e96a02a1d..96338f0c4dd47268d60727b9a35b251d62b469ad 100644 (file)
@@ -31,6 +31,9 @@
 struct mt312_config {
        /* the demodulator's i2c address */
        u8 demod_address;
+
+       /* inverted voltage setting */
+       int voltage_inverted:1;
 };
 
 #if defined(CONFIG_DVB_MT312) || (defined(CONFIG_DVB_MT312_MODULE) && defined(MODULE))
@@ -40,7 +43,7 @@ struct dvb_frontend *vp310_mt312_attach(const struct mt312_config *config,
 static inline struct dvb_frontend *vp310_mt312_attach(
        const struct mt312_config *config, struct i2c_adapter *i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif /* CONFIG_DVB_MT312 */
index 5e0b95b5337bc8be7d91903bbe0581131371380e..a3959f94d6398b0694d5df1d5f0edd0bedddc291 100644 (file)
@@ -110,6 +110,8 @@ enum mt312_reg_addr {
        VIT_ERRPER_H = 83,
        VIT_ERRPER_M = 84,
        VIT_ERRPER_L = 85,
+       HW_CTRL = 84,   /* ZL10313 only */
+       MPEG_CTRL = 85, /* ZL10313 only */
        VIT_SETUP = 86,
        VIT_REF0 = 87,
        VIT_REF1 = 88,
@@ -156,7 +158,8 @@ enum mt312_reg_addr {
 
 enum mt312_model_id {
        ID_VP310 = 1,
-       ID_MT312 = 3
+       ID_MT312 = 3,
+       ID_ZL10313 = 5,
 };
 
 #endif                         /* DVB_FRONTENDS_MT312_PRIV */
index 7cd190b6f01573919e7939948b8f922e8f5622b2..beba5aa0db5000e17d520ef8e473953c8720662d 100644 (file)
@@ -95,7 +95,7 @@ static int mt352_read_register(struct mt352_state* state, u8 reg)
 
        if (ret != 2) {
                printk("%s: readreg error (reg=%d, ret==%i)\n",
-                      __FUNCTION__, reg, ret);
+                      __func__, reg, ret);
                return ret;
        }
 
@@ -135,7 +135,7 @@ static void mt352_calc_nominal_rate(struct mt352_state* state,
        value = 64 * bw * (1<<16) / (7 * 8);
        value = value * 1000 / adc_clock;
        dprintk("%s: bw %d, adc_clock %d => 0x%x\n",
-               __FUNCTION__, bw, adc_clock, value);
+               __func__, bw, adc_clock, value);
        buf[0] = msb(value);
        buf[1] = lsb(value);
 }
@@ -161,7 +161,7 @@ static void mt352_calc_input_freq(struct mt352_state* state,
        }
        value = -16374 * ife / adc_clock;
        dprintk("%s: if2 %d, ife %d, adc_clock %d => %d / 0x%x\n",
-               __FUNCTION__, if2, ife, adc_clock, value, value & 0x3fff);
+               __func__, if2, ife, adc_clock, value, value & 0x3fff);
        buf[0] = msb(value);
        buf[1] = lsb(value);
 }
@@ -521,7 +521,7 @@ static int mt352_init(struct dvb_frontend* fe)
 
        static u8 mt352_reset_attach [] = { RESET, 0xC0 };
 
-       dprintk("%s: hello\n",__FUNCTION__);
+       dprintk("%s: hello\n",__func__);
 
        if ((mt352_read_register(state, CLOCK_CTL) & 0x10) == 0 ||
            (mt352_read_register(state, CONFIG) & 0x20) == 0) {
index e9964081fd8436cc48397fd6e1cde634fe764896..595092f9f0c4a7caf1a73f5b623d21234c33eca1 100644 (file)
@@ -58,7 +58,7 @@ extern struct dvb_frontend* mt352_attach(const struct mt352_config* config,
 static inline struct dvb_frontend* mt352_attach(const struct mt352_config* config,
                                         struct i2c_adapter* i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_MT352
index fcf964fe1d6bebb2ca9f62847fdcfd67ee8d05b1..23d022852543a1a3c9dfd7a0fdc2f2eb35799b5a 100644 (file)
@@ -74,7 +74,7 @@ static int i2c_writebytes (struct nxt200x_state* state, u8 addr, u8 *buf, u8 len
 
        if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
                printk (KERN_WARNING "nxt200x: %s: i2c write error (addr 0x%02x, err == %i)\n",
-                       __FUNCTION__, addr, err);
+                       __func__, addr, err);
                return -EREMOTEIO;
        }
        return 0;
@@ -87,7 +87,7 @@ static u8 i2c_readbytes (struct nxt200x_state* state, u8 addr, u8* buf, u8 len)
 
        if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
                printk (KERN_WARNING "nxt200x: %s: i2c read error (addr 0x%02x, err == %i)\n",
-                       __FUNCTION__, addr, err);
+                       __func__, addr, err);
                return -EREMOTEIO;
        }
        return 0;
@@ -104,7 +104,7 @@ static int nxt200x_writebytes (struct nxt200x_state* state, u8 reg, u8 *buf, u8
 
        if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
                printk (KERN_WARNING "nxt200x: %s: i2c write error (addr 0x%02x, err == %i)\n",
-                       __FUNCTION__, state->config->demod_address, err);
+                       __func__, state->config->demod_address, err);
                return -EREMOTEIO;
        }
        return 0;
@@ -121,7 +121,7 @@ static u8 nxt200x_readbytes (struct nxt200x_state* state, u8 reg, u8* buf, u8 le
 
        if ((err = i2c_transfer (state->i2c, msg, 2)) != 2) {
                printk (KERN_WARNING "nxt200x: %s: i2c read error (addr 0x%02x, err == %i)\n",
-                       __FUNCTION__, state->config->demod_address, err);
+                       __func__, state->config->demod_address, err);
                return -EREMOTEIO;
        }
        return 0;
@@ -146,7 +146,7 @@ static u16 nxt200x_crc(u16 crc, u8 c)
 static int nxt200x_writereg_multibyte (struct nxt200x_state* state, u8 reg, u8* data, u8 len)
 {
        u8 attr, len2, buf;
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        /* set mutli register register */
        nxt200x_writebytes(state, 0x35, &reg, 1);
@@ -207,7 +207,7 @@ static int nxt200x_readreg_multibyte (struct nxt200x_state* state, u8 reg, u8* d
 {
        int i;
        u8 buf, len2, attr;
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        /* set mutli register register */
        nxt200x_writebytes(state, 0x35, &reg, 1);
@@ -254,7 +254,7 @@ static int nxt200x_readreg_multibyte (struct nxt200x_state* state, u8 reg, u8* d
 static void nxt200x_microcontroller_stop (struct nxt200x_state* state)
 {
        u8 buf, stopval, counter = 0;
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        /* set correct stop value */
        switch (state->demod_chip) {
@@ -287,7 +287,7 @@ static void nxt200x_microcontroller_stop (struct nxt200x_state* state)
 static void nxt200x_microcontroller_start (struct nxt200x_state* state)
 {
        u8 buf;
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        buf = 0x00;
        nxt200x_writebytes(state, 0x22, &buf, 1);
@@ -297,7 +297,7 @@ static void nxt2004_microcontroller_init (struct nxt200x_state* state)
 {
        u8 buf[9];
        u8 counter = 0;
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        buf[0] = 0x00;
        nxt200x_writebytes(state, 0x2b, buf, 1);
@@ -328,7 +328,7 @@ static int nxt200x_writetuner (struct nxt200x_state* state, u8* data)
 {
        u8 buf, count = 0;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        dprintk("Tuner Bytes: %02X %02X %02X %02X\n", data[1], data[2], data[3], data[4]);
 
@@ -387,7 +387,7 @@ static int nxt200x_writetuner (struct nxt200x_state* state, u8* data)
 static void nxt200x_agc_reset(struct nxt200x_state* state)
 {
        u8 buf;
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        switch (state->demod_chip) {
                case NXT2002:
@@ -416,7 +416,7 @@ static int nxt2002_load_firmware (struct dvb_frontend* fe, const struct firmware
        u8 buf[3], written = 0, chunkpos = 0;
        u16 rambase, position, crc = 0;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
        dprintk("Firmware is %zu bytes\n", fw->size);
 
        /* Get the RAM base for this nxt2002 */
@@ -483,7 +483,7 @@ static int nxt2004_load_firmware (struct dvb_frontend* fe, const struct firmware
        u8 buf[3];
        u16 rambase, position, crc=0;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
        dprintk("Firmware is %zu bytes\n", fw->size);
 
        /* set rambase */
index bb0ef58d797277dbdc93c70bcc9c873ba4efd214..f3c84583770f80a1e5f5e3fabdacf29bdc7c400c 100644 (file)
@@ -49,7 +49,7 @@ extern struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* config,
 static inline struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* config,
                                           struct i2c_adapter* i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_NXT200X
index d313d7dcf3862c6fa67e1a0b6e0cd33a9c386277..0eef22dbf8a041ae5f82e0aecc5cc36770ab1d0a 100644 (file)
@@ -38,7 +38,7 @@ struct nxt6000_state {
        struct dvb_frontend frontend;
 };
 
-static int debug = 0;
+static int debug;
 #define dprintk if (debug) printk
 
 static int nxt6000_writereg(struct nxt6000_state* state, u8 reg, u8 data)
index 13d22518356ed1c06f8f28206e9ff1ceb5516081..878eb38a075ecbfff4c572caf5a52557f6876881 100644 (file)
@@ -40,7 +40,7 @@ extern struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config,
 static inline struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config,
                                           struct i2c_adapter* i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_NXT6000
index 8ffb8daca0313b53f54a9208e5cb467daa6c10f8..c7b5785f81f263321c83d54e93a26d51348ad333 100644 (file)
@@ -419,7 +419,7 @@ static int or51132_read_status(struct dvb_frontend* fe, fe_status_t* status)
                *status = 0;
                return -EREMOTEIO;
        }
-       dprintk("%s: read_status %04x\n", __FUNCTION__, reg);
+       dprintk("%s: read_status %04x\n", __func__, reg);
 
        if (reg & 0x0100) /* Receiver Lock */
                *status = FE_HAS_SIGNAL|FE_HAS_CARRIER|FE_HAS_VITERBI|
@@ -504,14 +504,14 @@ start:
                if (retry--) goto start;
                return -EREMOTEIO;
        }
-       dprintk("%s: modulation %02x, NTSC rej O%s\n", __FUNCTION__,
+       dprintk("%s: modulation %02x, NTSC rej O%s\n", __func__,
                reg&0xff, reg&0x1000?"n":"ff");
 
        /* Calculate SNR using noise, c, and NTSC rejection correction */
        state->snr = calculate_snr(noise, c) - usK;
        *snr = (state->snr) >> 16;
 
-       dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __FUNCTION__, noise,
+       dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __func__, noise,
                state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16);
 
        return 0;
index add24f0a743b9cbb9326b032b42582d233eceb37..1b8e04d973c8c8ec41036befdef092404c2028b0 100644 (file)
@@ -41,7 +41,7 @@ extern struct dvb_frontend* or51132_attach(const struct or51132_config* config,
 static inline struct dvb_frontend* or51132_attach(const struct or51132_config* config,
                                           struct i2c_adapter* i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_OR51132
index 6a6b0d727c6fc53ece47c2816086e8cf9025cf3f..7eaa4765593f039dc82c4983baeac5dedfeb787f 100644 (file)
@@ -307,19 +307,19 @@ static int or51211_read_snr(struct dvb_frontend* fe, u16* snr)
 
        if (i2c_writebytes(state,state->config->demod_address,snd_buf,3)) {
                printk(KERN_WARNING "%s: error writing snr reg\n",
-                      __FUNCTION__);
+                      __func__);
                return -1;
        }
        if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) {
                printk(KERN_WARNING "%s: read_status read error\n",
-                      __FUNCTION__);
+                      __func__);
                return -1;
        }
 
        state->snr = calculate_snr(rec_buf[0], 89599047);
        *snr = (state->snr) >> 16;
 
-       dprintk("%s: noise = 0x%02x, snr = %d.%02d dB\n", __FUNCTION__, rec_buf[0],
+       dprintk("%s: noise = 0x%02x, snr = %d.%02d dB\n", __func__, rec_buf[0],
                state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16);
 
        return 0;
index 8aad8402d615d45aea6de0d7edb72e818ad66143..3ce0508b898e102b1cf13ee8e18915e2b783b515 100644 (file)
@@ -44,7 +44,7 @@ extern struct dvb_frontend* or51211_attach(const struct or51211_config* config,
 static inline struct dvb_frontend* or51211_attach(const struct or51211_config* config,
                                           struct i2c_adapter* i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_OR51211
index 3ab4aa045c36891fccb7aec871dce427cf112bd8..cff6a7ca53801cce4335b41a24c8f29f7cf93a0a 100644 (file)
@@ -45,7 +45,7 @@ static inline struct dvb_frontend *qt1010_attach(struct dvb_frontend *fe,
                                                 struct i2c_adapter *i2c,
                                                 struct qt1010_config *cfg)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_TUNER_QT1010
index 1a4d8319773c73ffd8a858ca4c150c2f58df9d97..b999ec424ff7782041bc2c8fcb993a7355ec04dc 100644 (file)
@@ -48,7 +48,7 @@ struct s5h1409_state {
        u32 qam_state;
 };
 
-static int debug = 0;
+static int debug;
 #define dprintk        if (debug) printk
 
 /* Register values to initialise the demod, this will set VSB by default */
@@ -312,7 +312,7 @@ static int s5h1409_writereg(struct s5h1409_state* state, u8 reg, u16 data)
 
        if (ret != 1)
                printk("%s: writereg error (reg == 0x%02x, val == 0x%04x, "
-                      "ret == %i)\n", __FUNCTION__, reg, data, ret);
+                      "ret == %i)\n", __func__, reg, data, ret);
 
        return (ret != 1) ? -1 : 0;
 }
@@ -332,7 +332,7 @@ static u16 s5h1409_readreg(struct s5h1409_state* state, u8 reg)
        ret = i2c_transfer(state->i2c, msg, 2);
 
        if (ret != 2)
-               printk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
+               printk("%s: readreg error (ret == %i)\n", __func__, ret);
        return (b1[0] << 8) | b1[1];
 }
 
@@ -340,7 +340,7 @@ static int s5h1409_softreset(struct dvb_frontend* fe)
 {
        struct s5h1409_state* state = fe->demodulator_priv;
 
-       dprintk("%s()\n", __FUNCTION__);
+       dprintk("%s()\n", __func__);
 
        s5h1409_writereg(state, 0xf5, 0);
        s5h1409_writereg(state, 0xf5, 1);
@@ -356,7 +356,7 @@ static int s5h1409_set_if_freq(struct dvb_frontend* fe, int KHz)
 {
        struct s5h1409_state* state = fe->demodulator_priv;
 
-       dprintk("%s(%d KHz)\n", __FUNCTION__, KHz);
+       dprintk("%s(%d KHz)\n", __func__, KHz);
 
        switch (KHz) {
        case 4000:
@@ -381,7 +381,7 @@ static int s5h1409_set_spectralinversion(struct dvb_frontend* fe, int inverted)
 {
        struct s5h1409_state* state = fe->demodulator_priv;
 
-       dprintk("%s(%d)\n", __FUNCTION__, inverted);
+       dprintk("%s(%d)\n", __func__, inverted);
 
        if(inverted == 1)
                return s5h1409_writereg(state, 0x1b, 0x1101); /* Inverted */
@@ -394,25 +394,25 @@ static int s5h1409_enable_modulation(struct dvb_frontend* fe,
 {
        struct s5h1409_state* state = fe->demodulator_priv;
 
-       dprintk("%s(0x%08x)\n", __FUNCTION__, m);
+       dprintk("%s(0x%08x)\n", __func__, m);
 
        switch(m) {
        case VSB_8:
-               dprintk("%s() VSB_8\n", __FUNCTION__);
+               dprintk("%s() VSB_8\n", __func__);
                if (state->if_freq != S5H1409_VSB_IF_FREQ)
                        s5h1409_set_if_freq(fe, S5H1409_VSB_IF_FREQ);
                s5h1409_writereg(state, 0xf4, 0);
                break;
        case QAM_64:
        case QAM_256:
-               dprintk("%s() QAM_AUTO (64/256)\n", __FUNCTION__);
+               dprintk("%s() QAM_AUTO (64/256)\n", __func__);
                if (state->if_freq != S5H1409_QAM_IF_FREQ)
                        s5h1409_set_if_freq(fe, S5H1409_QAM_IF_FREQ);
                s5h1409_writereg(state, 0xf4, 1);
                s5h1409_writereg(state, 0x85, 0x110);
                break;
        default:
-               dprintk("%s() Invalid modulation\n", __FUNCTION__);
+               dprintk("%s() Invalid modulation\n", __func__);
                return -EINVAL;
        }
 
@@ -426,7 +426,7 @@ static int s5h1409_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
 {
        struct s5h1409_state* state = fe->demodulator_priv;
 
-       dprintk("%s(%d)\n", __FUNCTION__, enable);
+       dprintk("%s(%d)\n", __func__, enable);
 
        if (enable)
                return s5h1409_writereg(state, 0xf3, 1);
@@ -438,7 +438,7 @@ static int s5h1409_set_gpio(struct dvb_frontend* fe, int enable)
 {
        struct s5h1409_state* state = fe->demodulator_priv;
 
-       dprintk("%s(%d)\n", __FUNCTION__, enable);
+       dprintk("%s(%d)\n", __func__, enable);
 
        if (enable)
                return s5h1409_writereg(state, 0xe3,
@@ -452,7 +452,7 @@ static int s5h1409_sleep(struct dvb_frontend* fe, int enable)
 {
        struct s5h1409_state* state = fe->demodulator_priv;
 
-       dprintk("%s(%d)\n", __FUNCTION__, enable);
+       dprintk("%s(%d)\n", __func__, enable);
 
        return s5h1409_writereg(state, 0xf2, enable);
 }
@@ -461,7 +461,7 @@ static int s5h1409_register_reset(struct dvb_frontend* fe)
 {
        struct s5h1409_state* state = fe->demodulator_priv;
 
-       dprintk("%s()\n", __FUNCTION__);
+       dprintk("%s()\n", __func__);
 
        return s5h1409_writereg(state, 0xfa, 0);
 }
@@ -534,7 +534,7 @@ static int s5h1409_set_frontend (struct dvb_frontend* fe,
 {
        struct s5h1409_state* state = fe->demodulator_priv;
 
-       dprintk("%s(frequency=%d)\n", __FUNCTION__, p->frequency);
+       dprintk("%s(frequency=%d)\n", __func__, p->frequency);
 
        s5h1409_softreset(fe);
 
@@ -565,7 +565,7 @@ static int s5h1409_set_mpeg_timing(struct dvb_frontend *fe, int mode)
        struct s5h1409_state *state = fe->demodulator_priv;
        u16 val;
 
-       dprintk("%s(%d)\n", __FUNCTION__, mode);
+       dprintk("%s(%d)\n", __func__, mode);
 
        val = s5h1409_readreg(state, 0xac) & 0xcfff;
        switch (mode) {
@@ -573,7 +573,7 @@ static int s5h1409_set_mpeg_timing(struct dvb_frontend *fe, int mode)
                val |= 0x0000;
                break;
        case S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK:
-               dprintk("%s(%d) Mode1 or Defaulting\n", __FUNCTION__, mode);
+               dprintk("%s(%d) Mode1 or Defaulting\n", __func__, mode);
                val |= 0x1000;
                break;
        case S5H1409_MPEGTIMING_NONCONTINOUS_INVERTING_CLOCK:
@@ -597,7 +597,7 @@ static int s5h1409_init (struct dvb_frontend* fe)
        int i;
 
        struct s5h1409_state* state = fe->demodulator_priv;
-       dprintk("%s()\n", __FUNCTION__);
+       dprintk("%s()\n", __func__);
 
        s5h1409_sleep(fe, 0);
        s5h1409_register_reset(fe);
@@ -663,7 +663,7 @@ static int s5h1409_read_status(struct dvb_frontend* fe, fe_status_t* status)
                break;
        }
 
-       dprintk("%s() status 0x%08x\n", __FUNCTION__, *status);
+       dprintk("%s() status 0x%08x\n", __func__, *status);
 
        return 0;
 }
@@ -671,7 +671,7 @@ static int s5h1409_read_status(struct dvb_frontend* fe, fe_status_t* status)
 static int s5h1409_qam256_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
 {
        int i, ret = -EINVAL;
-       dprintk("%s()\n", __FUNCTION__);
+       dprintk("%s()\n", __func__);
 
        for (i=0; i < ARRAY_SIZE(qam256_snr_tab); i++) {
                if (v < qam256_snr_tab[i].val) {
@@ -686,7 +686,7 @@ static int s5h1409_qam256_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
 static int s5h1409_qam64_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
 {
        int i, ret = -EINVAL;
-       dprintk("%s()\n", __FUNCTION__);
+       dprintk("%s()\n", __func__);
 
        for (i=0; i < ARRAY_SIZE(qam64_snr_tab); i++) {
                if (v < qam64_snr_tab[i].val) {
@@ -701,7 +701,7 @@ static int s5h1409_qam64_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
 static int s5h1409_vsb_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
 {
        int i, ret = -EINVAL;
-       dprintk("%s()\n", __FUNCTION__);
+       dprintk("%s()\n", __func__);
 
        for (i=0; i < ARRAY_SIZE(vsb_snr_tab); i++) {
                if (v > vsb_snr_tab[i].val) {
@@ -710,7 +710,7 @@ static int s5h1409_vsb_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
                        break;
                }
        }
-       dprintk("%s() snr=%d\n", __FUNCTION__, *snr);
+       dprintk("%s() snr=%d\n", __func__, *snr);
        return ret;
 }
 
@@ -718,7 +718,7 @@ static int s5h1409_read_snr(struct dvb_frontend* fe, u16* snr)
 {
        struct s5h1409_state* state = fe->demodulator_priv;
        u16 reg;
-       dprintk("%s()\n", __FUNCTION__);
+       dprintk("%s()\n", __func__);
 
        switch(state->current_modulation) {
        case QAM_64:
@@ -812,7 +812,7 @@ struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config,
 
        if (s5h1409_init(&state->frontend) != 0) {
                printk(KERN_ERR "%s: Failed to initialize correctly\n",
-                       __FUNCTION__);
+                       __func__);
                goto error;
        }
 
index f0bb13fe808b99053333be93699d7eefb74c118a..59f4335964c6625a78ccba31e2db6ce24855466c 100644 (file)
@@ -67,7 +67,7 @@ extern struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config,
 static inline struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config,
                                                  struct i2c_adapter* i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif /* CONFIG_DVB_S5H1409 */
index 2c2c344c4c648a3c85c92f3c7e6f8f4a98e85594..281e1cb2edc67d516361a4114b8864a7c3c716b6 100644 (file)
@@ -1,24 +1,26 @@
 /*
-Driver for Samsung S5H1420 QPSK Demodulator
-
-Copyright (C) 2005 Andrew de Quincey <adq_dvb@lidskialf.net>
-
-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., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
+ * Driver for
+ *    Samsung S5H1420 and
+ *    PnpNetwork PN1010 QPSK Demodulator
+ *
+ * Copyright (C) 2005 Andrew de Quincey <adq_dvb@lidskialf.net>
+ * Copyright (C) 2005-8 Patrick Boettcher <pb@linuxtv.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.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
 
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -29,23 +31,35 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 #include <linux/jiffies.h>
 #include <asm/div64.h>
 
-#include "dvb_frontend.h"
-#include "s5h1420.h"
+#include <linux/i2c.h>
 
 
+#include "dvb_frontend.h"
+#include "s5h1420.h"
+#include "s5h1420_priv.h"
 
 #define TONE_FREQ 22000
 
 struct s5h1420_state {
        struct i2c_adapter* i2c;
        const struct s5h1420_config* config;
+
        struct dvb_frontend frontend;
+       struct i2c_adapter tuner_i2c_adapter;
+
+       u8 CON_1_val;
 
        u8 postlocked:1;
        u32 fclk;
        u32 tunedfreq;
        fe_code_rate_t fec_inner;
        u32 symbol_rate;
+
+       /* FIXME: ugly workaround for flexcop's incapable i2c-controller
+        * it does not support repeated-start, workaround: write addr-1
+        * and then read
+        */
+       u8 shadow[255];
 };
 
 static u32 s5h1420_getsymbolrate(struct s5h1420_state* state);
@@ -53,44 +67,66 @@ static int s5h1420_get_tune_settings(struct dvb_frontend* fe,
                                     struct dvb_frontend_tune_settings* fesettings);
 
 
-static int debug = 0;
-#define dprintk if (debug) printk
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable debugging");
+
+#define dprintk(x...) do { \
+       if (debug) \
+               printk(KERN_DEBUG "S5H1420: " x); \
+} while (0)
+
+static u8 s5h1420_readreg(struct s5h1420_state *state, u8 reg)
+{
+       int ret;
+       u8 b[2];
+       struct i2c_msg msg[] = {
+               { .addr = state->config->demod_address, .flags = 0, .buf = b, .len = 2 },
+               { .addr = state->config->demod_address, .flags = 0, .buf = &reg, .len = 1 },
+               { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b, .len = 1 },
+       };
+
+       b[0] = (reg - 1) & 0xff;
+       b[1] = state->shadow[(reg - 1) & 0xff];
+
+       if (state->config->repeated_start_workaround) {
+               ret = i2c_transfer(state->i2c, msg, 3);
+               if (ret != 3)
+                       return ret;
+       } else {
+               ret = i2c_transfer(state->i2c, &msg[1], 2);
+               if (ret != 2)
+                       return ret;
+       }
+
+       /* dprintk("rd(%02x): %02x %02x\n", state->config->demod_address, reg, b[0]); */
+
+       return b[0];
+}
 
 static int s5h1420_writereg (struct s5h1420_state* state, u8 reg, u8 data)
 {
-       u8 buf [] = { reg, data };
+       u8 buf[] = { reg, data };
        struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
        int err;
 
-       if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
-               dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __FUNCTION__, err, reg, data);
+       /* dprintk("wr(%02x): %02x %02x\n", state->config->demod_address, reg, data); */
+       err = i2c_transfer(state->i2c, &msg, 1);
+       if (err != 1) {
+               dprintk("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __func__, err, reg, data);
                return -EREMOTEIO;
        }
+       state->shadow[reg] = data;
 
        return 0;
 }
 
-static u8 s5h1420_readreg (struct s5h1420_state* state, u8 reg)
-{
-       int ret;
-       u8 b0 [] = { reg };
-       u8 b1 [] = { 0 };
-       struct i2c_msg msg1 = { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 };
-       struct i2c_msg msg2 = { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 };
-
-       if ((ret = i2c_transfer (state->i2c, &msg1, 1)) != 1)
-               return ret;
-
-       if ((ret = i2c_transfer (state->i2c, &msg2, 1)) != 1)
-               return ret;
-
-       return b1[0];
-}
-
 static int s5h1420_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltage)
 {
        struct s5h1420_state* state = fe->demodulator_priv;
 
+       dprintk("enter %s\n", __func__);
+
        switch(voltage) {
        case SEC_VOLTAGE_13:
                s5h1420_writereg(state, 0x3c,
@@ -106,6 +142,7 @@ static int s5h1420_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag
                break;
        }
 
+       dprintk("leave %s\n", __func__);
        return 0;
 }
 
@@ -113,6 +150,7 @@ static int s5h1420_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
 {
        struct s5h1420_state* state = fe->demodulator_priv;
 
+       dprintk("enter %s\n", __func__);
        switch(tone) {
        case SEC_TONE_ON:
                s5h1420_writereg(state, 0x3b,
@@ -124,6 +162,7 @@ static int s5h1420_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
                                 (s5h1420_readreg(state, 0x3b) & 0x74) | 0x01);
                break;
        }
+       dprintk("leave %s\n", __func__);
 
        return 0;
 }
@@ -137,6 +176,7 @@ static int s5h1420_send_master_cmd (struct dvb_frontend* fe,
        unsigned long timeout;
        int result = 0;
 
+       dprintk("enter %s\n", __func__);
        if (cmd->msg_len > 8)
                return -EINVAL;
 
@@ -168,6 +208,7 @@ static int s5h1420_send_master_cmd (struct dvb_frontend* fe,
        /* restore original settings */
        s5h1420_writereg(state, 0x3b, val);
        msleep(15);
+       dprintk("leave %s\n", __func__);
        return result;
 }
 
@@ -289,6 +330,8 @@ static int s5h1420_read_status(struct dvb_frontend* fe, fe_status_t* status)
        struct s5h1420_state* state = fe->demodulator_priv;
        u8 val;
 
+       dprintk("enter %s\n", __func__);
+
        if (status == NULL)
                return -EINVAL;
 
@@ -297,13 +340,13 @@ static int s5h1420_read_status(struct dvb_frontend* fe, fe_status_t* status)
 
        /* fix for FEC 5/6 inversion issue - if it doesn't quite lock, invert
        the inversion, wait a bit and check again */
-       if (*status == (FE_HAS_SIGNAL|FE_HAS_CARRIER|FE_HAS_VITERBI)) {
-               val = s5h1420_readreg(state, 0x32);
+       if (*status == (FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI)) {
+               val = s5h1420_readreg(state, Vit10);
                if ((val & 0x07) == 0x03) {
                        if (val & 0x08)
-                               s5h1420_writereg(state, 0x31, 0x13);
+                               s5h1420_writereg(state, Vit09, 0x13);
                        else
-                               s5h1420_writereg(state, 0x31, 0x1b);
+                               s5h1420_writereg(state, Vit09, 0x1b);
 
                        /* wait a bit then update lock status */
                        mdelay(200);
@@ -312,68 +355,73 @@ static int s5h1420_read_status(struct dvb_frontend* fe, fe_status_t* status)
        }
 
        /* perform post lock setup */
-       if ((*status & FE_HAS_LOCK) && (!state->postlocked)) {
+       if ((*status & FE_HAS_LOCK) && !state->postlocked) {
 
                /* calculate the data rate */
                u32 tmp = s5h1420_getsymbolrate(state);
-               switch(s5h1420_readreg(state, 0x32) & 0x07) {
-               case 0:
-                       tmp = (tmp * 2 * 1) / 2;
-                       break;
-
-               case 1:
-                       tmp = (tmp * 2 * 2) / 3;
-                       break;
-
-               case 2:
-                       tmp = (tmp * 2 * 3) / 4;
-                       break;
-
-               case 3:
-                       tmp = (tmp * 2 * 5) / 6;
-                       break;
-
-               case 4:
-                       tmp = (tmp * 2 * 6) / 7;
-                       break;
-
-               case 5:
-                       tmp = (tmp * 2 * 7) / 8;
-                       break;
+               switch (s5h1420_readreg(state, Vit10) & 0x07) {
+               case 0: tmp = (tmp * 2 * 1) / 2; break;
+               case 1: tmp = (tmp * 2 * 2) / 3; break;
+               case 2: tmp = (tmp * 2 * 3) / 4; break;
+               case 3: tmp = (tmp * 2 * 5) / 6; break;
+               case 4: tmp = (tmp * 2 * 6) / 7; break;
+               case 5: tmp = (tmp * 2 * 7) / 8; break;
                }
+
                if (tmp == 0) {
-                       printk("s5h1420: avoided division by 0\n");
+                       printk(KERN_ERR "s5h1420: avoided division by 0\n");
                        tmp = 1;
                }
                tmp = state->fclk / tmp;
 
+
                /* set the MPEG_CLK_INTL for the calculated data rate */
-               if (tmp < 4)
+               if (tmp < 2)
                        val = 0x00;
-               else if (tmp < 8)
+               else if (tmp < 5)
                        val = 0x01;
-               else if (tmp < 12)
+               else if (tmp < 9)
                        val = 0x02;
-               else if (tmp < 16)
+               else if (tmp < 13)
                        val = 0x03;
-               else if (tmp < 24)
+               else if (tmp < 17)
                        val = 0x04;
-               else if (tmp < 32)
+               else if (tmp < 25)
                        val = 0x05;
-               else
+               else if (tmp < 33)
                        val = 0x06;
-               s5h1420_writereg(state, 0x22, val);
+               else
+                       val = 0x07;
+               dprintk("for MPEG_CLK_INTL %d %x\n", tmp, val);
+
+               s5h1420_writereg(state, FEC01, 0x18);
+               s5h1420_writereg(state, FEC01, 0x10);
+               s5h1420_writereg(state, FEC01, val);
+
+               /* Enable "MPEG_Out" */
+               val = s5h1420_readreg(state, Mpeg02);
+               s5h1420_writereg(state, Mpeg02, val | (1 << 6));
 
-               /* DC freeze */
-               s5h1420_writereg(state, 0x1f, s5h1420_readreg(state, 0x1f) | 0x01);
+               /* kicker disable */
+               val = s5h1420_readreg(state, QPSK01) & 0x7f;
+               s5h1420_writereg(state, QPSK01, val);
 
-               /* kicker disable + remove DC offset */
-               s5h1420_writereg(state, 0x05, s5h1420_readreg(state, 0x05) & 0x6f);
+               /* DC freeze TODO it was never activated by default or it can stay activated */
+
+               if (s5h1420_getsymbolrate(state) >= 20000000) {
+                       s5h1420_writereg(state, Loop04, 0x8a);
+                       s5h1420_writereg(state, Loop05, 0x6a);
+               } else {
+                       s5h1420_writereg(state, Loop04, 0x58);
+                       s5h1420_writereg(state, Loop05, 0x27);
+               }
 
                /* post-lock processing has been done! */
                state->postlocked = 1;
        }
 
+       dprintk("leave %s\n", __func__);
+
        return 0;
 }
 
@@ -414,6 +462,7 @@ static int s5h1420_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
 
 static void s5h1420_reset(struct s5h1420_state* state)
 {
+       dprintk("%s\n", __func__);
        s5h1420_writereg (state, 0x01, 0x08);
        s5h1420_writereg (state, 0x01, 0x00);
        udelay(10);
@@ -422,54 +471,52 @@ static void s5h1420_reset(struct s5h1420_state* state)
 static void s5h1420_setsymbolrate(struct s5h1420_state* state,
                                  struct dvb_frontend_parameters *p)
 {
+       u8 v;
        u64 val;
 
+       dprintk("enter %s\n", __func__);
+
        val = ((u64) p->u.qpsk.symbol_rate / 1000ULL) * (1ULL<<24);
-       if (p->u.qpsk.symbol_rate <= 21000000) {
+       if (p->u.qpsk.symbol_rate < 29000000)
                val *= 2;
-       }
        do_div(val, (state->fclk / 1000));
 
-       s5h1420_writereg(state, 0x09, s5h1420_readreg(state, 0x09) & 0x7f);
-       s5h1420_writereg(state, 0x11, val >> 16);
-       s5h1420_writereg(state, 0x12, val >> 8);
-       s5h1420_writereg(state, 0x13, val & 0xff);
-       s5h1420_writereg(state, 0x09, s5h1420_readreg(state, 0x09) | 0x80);
+       dprintk("symbol rate register: %06llx\n", val);
+
+       v = s5h1420_readreg(state, Loop01);
+       s5h1420_writereg(state, Loop01, v & 0x7f);
+       s5h1420_writereg(state, Tnco01, val >> 16);
+       s5h1420_writereg(state, Tnco02, val >> 8);
+       s5h1420_writereg(state, Tnco03, val & 0xff);
+       s5h1420_writereg(state, Loop01,  v | 0x80);
+       dprintk("leave %s\n", __func__);
 }
 
 static u32 s5h1420_getsymbolrate(struct s5h1420_state* state)
 {
-       u64 val = 0;
-       int sampling = 2;
-
-       if (s5h1420_readreg(state, 0x05) & 0x2)
-               sampling = 1;
-
-       s5h1420_writereg(state, 0x06, s5h1420_readreg(state, 0x06) | 0x08);
-       val  = s5h1420_readreg(state, 0x11) << 16;
-       val |= s5h1420_readreg(state, 0x12) << 8;
-       val |= s5h1420_readreg(state, 0x13);
-       s5h1420_writereg(state, 0x06, s5h1420_readreg(state, 0x06) & 0xf7);
-
-       val *= (state->fclk / 1000ULL);
-       do_div(val, ((1<<24) * sampling));
-
-       return (u32) (val * 1000ULL);
+       return state->symbol_rate;
 }
 
 static void s5h1420_setfreqoffset(struct s5h1420_state* state, int freqoffset)
 {
        int val;
+       u8 v;
+
+       dprintk("enter %s\n", __func__);
 
        /* remember freqoffset is in kHz, but the chip wants the offset in Hz, so
         * divide fclk by 1000000 to get the correct value. */
        val = -(int) ((freqoffset * (1<<24)) / (state->fclk / 1000000));
 
-       s5h1420_writereg(state, 0x09, s5h1420_readreg(state, 0x09) & 0xbf);
-       s5h1420_writereg(state, 0x0e, val >> 16);
-       s5h1420_writereg(state, 0x0f, val >> 8);
-       s5h1420_writereg(state, 0x10, val & 0xff);
-       s5h1420_writereg(state, 0x09, s5h1420_readreg(state, 0x09) | 0x40);
+       dprintk("phase rotator/freqoffset: %d %06x\n", freqoffset, val);
+
+       v = s5h1420_readreg(state, Loop01);
+       s5h1420_writereg(state, Loop01, v & 0xbf);
+       s5h1420_writereg(state, Pnco01, val >> 16);
+       s5h1420_writereg(state, Pnco02, val >> 8);
+       s5h1420_writereg(state, Pnco03, val & 0xff);
+       s5h1420_writereg(state, Loop01, v | 0x40);
+       dprintk("leave %s\n", __func__);
 }
 
 static int s5h1420_getfreqoffset(struct s5h1420_state* state)
@@ -496,52 +543,53 @@ static void s5h1420_setfec_inversion(struct s5h1420_state* state,
                                     struct dvb_frontend_parameters *p)
 {
        u8 inversion = 0;
+       u8 vit08, vit09;
+
+       dprintk("enter %s\n", __func__);
 
-       if (p->inversion == INVERSION_OFF) {
+       if (p->inversion == INVERSION_OFF)
                inversion = state->config->invert ? 0x08 : 0;
-       } else if (p->inversion == INVERSION_ON) {
+       else if (p->inversion == INVERSION_ON)
                inversion = state->config->invert ? 0 : 0x08;
-       }
 
        if ((p->u.qpsk.fec_inner == FEC_AUTO) || (p->inversion == INVERSION_AUTO)) {
-               s5h1420_writereg(state, 0x30, 0x3f);
-               s5h1420_writereg(state, 0x31, 0x00 | inversion);
+               vit08 = 0x3f;
+               vit09 = 0;
        } else {
                switch(p->u.qpsk.fec_inner) {
                case FEC_1_2:
-                       s5h1420_writereg(state, 0x30, 0x01);
-                       s5h1420_writereg(state, 0x31, 0x10 | inversion);
+                       vit08 = 0x01; vit09 = 0x10;
                        break;
 
                case FEC_2_3:
-                       s5h1420_writereg(state, 0x30, 0x02);
-                       s5h1420_writereg(state, 0x31, 0x11 | inversion);
+                       vit08 = 0x02; vit09 = 0x11;
                        break;
 
                case FEC_3_4:
-                       s5h1420_writereg(state, 0x30, 0x04);
-                       s5h1420_writereg(state, 0x31, 0x12 | inversion);
+                       vit08 = 0x04; vit09 = 0x12;
                        break;
 
                case FEC_5_6:
-                       s5h1420_writereg(state, 0x30, 0x08);
-                       s5h1420_writereg(state, 0x31, 0x13 | inversion);
+                       vit08 = 0x08; vit09 = 0x13;
                        break;
 
                case FEC_6_7:
-                       s5h1420_writereg(state, 0x30, 0x10);
-                       s5h1420_writereg(state, 0x31, 0x14 | inversion);
+                       vit08 = 0x10; vit09 = 0x14;
                        break;
 
                case FEC_7_8:
-                       s5h1420_writereg(state, 0x30, 0x20);
-                       s5h1420_writereg(state, 0x31, 0x15 | inversion);
+                       vit08 = 0x20; vit09 = 0x15;
                        break;
 
                default:
                        return;
                }
        }
+       vit09 |= inversion;
+       dprintk("fec: %02x %02x\n", vit08, vit09);
+       s5h1420_writereg(state, Vit08, vit08);
+       s5h1420_writereg(state, Vit09, vit09);
+       dprintk("leave %s\n", __func__);
 }
 
 static fe_code_rate_t s5h1420_getfec(struct s5h1420_state* state)
@@ -583,16 +631,19 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe,
        struct s5h1420_state* state = fe->demodulator_priv;
        int frequency_delta;
        struct dvb_frontend_tune_settings fesettings;
+       uint8_t clock_settting;
+
+       dprintk("enter %s\n", __func__);
 
        /* check if we should do a fast-tune */
        memcpy(&fesettings.parameters, p, sizeof(struct dvb_frontend_parameters));
        s5h1420_get_tune_settings(fe, &fesettings);
        frequency_delta = p->frequency - state->tunedfreq;
        if ((frequency_delta > -fesettings.max_drift) &&
-           (frequency_delta < fesettings.max_drift) &&
-           (frequency_delta != 0) &&
-           (state->fec_inner == p->u.qpsk.fec_inner) &&
-           (state->symbol_rate == p->u.qpsk.symbol_rate)) {
+                       (frequency_delta < fesettings.max_drift) &&
+                       (frequency_delta != 0) &&
+                       (state->fec_inner == p->u.qpsk.fec_inner) &&
+                       (state->symbol_rate == p->u.qpsk.symbol_rate)) {
 
                if (fe->ops.tuner_ops.set_params) {
                        fe->ops.tuner_ops.set_params(fe, p);
@@ -606,54 +657,93 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe,
                } else {
                        s5h1420_setfreqoffset(state, 0);
                }
+               dprintk("simple tune\n");
                return 0;
        }
+       dprintk("tuning demod\n");
 
        /* first of all, software reset */
        s5h1420_reset(state);
 
        /* set s5h1420 fclk PLL according to desired symbol rate */
-       if (p->u.qpsk.symbol_rate > 28000000) {
-               state->fclk = 88000000;
-               s5h1420_writereg(state, 0x03, 0x50);
-               s5h1420_writereg(state, 0x04, 0x40);
-               s5h1420_writereg(state, 0x05, 0xae);
-       } else if (p->u.qpsk.symbol_rate > 21000000) {
+       if (p->u.qpsk.symbol_rate > 33000000)
+               state->fclk = 80000000;
+       else if (p->u.qpsk.symbol_rate > 28500000)
                state->fclk = 59000000;
-               s5h1420_writereg(state, 0x03, 0x33);
-               s5h1420_writereg(state, 0x04, 0x40);
-               s5h1420_writereg(state, 0x05, 0xae);
-       } else {
+       else if (p->u.qpsk.symbol_rate > 25000000)
+               state->fclk = 86000000;
+       else if (p->u.qpsk.symbol_rate > 1900000)
                state->fclk = 88000000;
-               s5h1420_writereg(state, 0x03, 0x50);
-               s5h1420_writereg(state, 0x04, 0x40);
-               s5h1420_writereg(state, 0x05, 0xac);
+       else
+               state->fclk = 44000000;
+
+       /* Clock */
+       switch (state->fclk) {
+       default:
+       case 88000000:
+               clock_settting = 80;
+               break;
+       case 86000000:
+               clock_settting = 78;
+               break;
+       case 80000000:
+               clock_settting = 72;
+               break;
+       case 59000000:
+               clock_settting = 51;
+               break;
+       case 44000000:
+               clock_settting = 36;
+               break;
        }
+       dprintk("pll01: %d, ToneFreq: %d\n", state->fclk/1000000 - 8, (state->fclk + (TONE_FREQ * 32) - 1) / (TONE_FREQ * 32));
+       s5h1420_writereg(state, PLL01, state->fclk/1000000 - 8);
+       s5h1420_writereg(state, PLL02, 0x40);
+       s5h1420_writereg(state, DiS01, (state->fclk + (TONE_FREQ * 32) - 1) / (TONE_FREQ * 32));
 
-       /* set misc registers */
-       s5h1420_writereg(state, 0x02, 0x00);
-       s5h1420_writereg(state, 0x06, 0x00);
-       s5h1420_writereg(state, 0x07, 0xb0);
-       s5h1420_writereg(state, 0x0a, 0xe7);
-       s5h1420_writereg(state, 0x0b, 0x78);
-       s5h1420_writereg(state, 0x0c, 0x48);
-       s5h1420_writereg(state, 0x0d, 0x6b);
-       s5h1420_writereg(state, 0x2e, 0x8e);
-       s5h1420_writereg(state, 0x35, 0x33);
-       s5h1420_writereg(state, 0x38, 0x01);
-       s5h1420_writereg(state, 0x39, 0x7d);
-       s5h1420_writereg(state, 0x3a, (state->fclk + (TONE_FREQ * 32) - 1) / (TONE_FREQ * 32));
-       s5h1420_writereg(state, 0x3c, 0x00);
-       s5h1420_writereg(state, 0x45, 0x61);
-       s5h1420_writereg(state, 0x46, 0x1d);
+       /* TODO DC offset removal, config parameter ? */
+       if (p->u.qpsk.symbol_rate > 29000000)
+               s5h1420_writereg(state, QPSK01, 0xae | 0x10);
+       else
+               s5h1420_writereg(state, QPSK01, 0xac | 0x10);
 
-       /* start QPSK */
-       s5h1420_writereg(state, 0x05, s5h1420_readreg(state, 0x05) | 1);
+       /* set misc registers */
+       s5h1420_writereg(state, CON_1, 0x00);
+       s5h1420_writereg(state, QPSK02, 0x00);
+       s5h1420_writereg(state, Pre01, 0xb0);
+
+       s5h1420_writereg(state, Loop01, 0xF0);
+       s5h1420_writereg(state, Loop02, 0x2a); /* e7 for s5h1420 */
+       s5h1420_writereg(state, Loop03, 0x79); /* 78 for s5h1420 */
+       if (p->u.qpsk.symbol_rate > 20000000)
+               s5h1420_writereg(state, Loop04, 0x79);
+       else
+               s5h1420_writereg(state, Loop04, 0x58);
+       s5h1420_writereg(state, Loop05, 0x6b);
+
+       if (p->u.qpsk.symbol_rate >= 8000000)
+               s5h1420_writereg(state, Post01, (0 << 6) | 0x10);
+       else if (p->u.qpsk.symbol_rate >= 4000000)
+               s5h1420_writereg(state, Post01, (1 << 6) | 0x10);
+       else
+               s5h1420_writereg(state, Post01, (3 << 6) | 0x10);
+
+       s5h1420_writereg(state, Monitor12, 0x00); /* unfreeze DC compensation */
+
+       s5h1420_writereg(state, Sync01, 0x33);
+       s5h1420_writereg(state, Mpeg01, state->config->cdclk_polarity);
+       s5h1420_writereg(state, Mpeg02, 0x3d); /* Parallel output more, disabled -> enabled later */
+       s5h1420_writereg(state, Err01, 0x03); /* 0x1d for s5h1420 */
+
+       s5h1420_writereg(state, Vit06, 0x6e); /* 0x8e for s5h1420 */
+       s5h1420_writereg(state, DiS03, 0x00);
+       s5h1420_writereg(state, Rf01, 0x61); /* Tuner i2c address - for the gate controller */
 
        /* set tuner PLL */
        if (fe->ops.tuner_ops.set_params) {
                fe->ops.tuner_ops.set_params(fe, p);
-               if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+               if (fe->ops.i2c_gate_ctrl)
+                       fe->ops.i2c_gate_ctrl(fe, 0);
                s5h1420_setfreqoffset(state, 0);
        }
 
@@ -661,10 +751,15 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe,
        s5h1420_setsymbolrate(state, p);
        s5h1420_setfec_inversion(state, p);
 
+       /* start QPSK */
+       s5h1420_writereg(state, QPSK01, s5h1420_readreg(state, QPSK01) | 1);
+
        state->fec_inner = p->u.qpsk.fec_inner;
        state->symbol_rate = p->u.qpsk.symbol_rate;
        state->postlocked = 0;
        state->tunedfreq = p->frequency;
+
+       dprintk("leave %s\n", __func__);
        return 0;
 }
 
@@ -717,11 +812,10 @@ static int s5h1420_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
 {
        struct s5h1420_state* state = fe->demodulator_priv;
 
-       if (enable) {
-               return s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) | 1);
-       } else {
-               return s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) & 0xfe);
-       }
+       if (enable)
+               return s5h1420_writereg(state, 0x02, state->CON_1_val | 1);
+       else
+               return s5h1420_writereg(state, 0x02, state->CON_1_val & 0xfe);
 }
 
 static int s5h1420_init (struct dvb_frontend* fe)
@@ -729,7 +823,8 @@ static int s5h1420_init (struct dvb_frontend* fe)
        struct s5h1420_state* state = fe->demodulator_priv;
 
        /* disable power down and do reset */
-       s5h1420_writereg(state, 0x02, 0x10);
+       state->CON_1_val = 0x10;
+       s5h1420_writereg(state, 0x02, state->CON_1_val);
        msleep(10);
        s5h1420_reset(state);
 
@@ -739,26 +834,60 @@ static int s5h1420_init (struct dvb_frontend* fe)
 static int s5h1420_sleep(struct dvb_frontend* fe)
 {
        struct s5h1420_state* state = fe->demodulator_priv;
-
-       return s5h1420_writereg(state, 0x02, 0x12);
+       state->CON_1_val = 0x12;
+       return s5h1420_writereg(state, 0x02, state->CON_1_val);
 }
 
 static void s5h1420_release(struct dvb_frontend* fe)
 {
        struct s5h1420_state* state = fe->demodulator_priv;
+       i2c_del_adapter(&state->tuner_i2c_adapter);
        kfree(state);
 }
 
-static struct dvb_frontend_ops s5h1420_ops;
+static u32 s5h1420_tuner_i2c_func(struct i2c_adapter *adapter)
+{
+       return I2C_FUNC_I2C;
+}
+
+static int s5h1420_tuner_i2c_tuner_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
+{
+       struct s5h1420_state *state = i2c_get_adapdata(i2c_adap);
+       struct i2c_msg m[1 + num];
+       u8 tx_open[2] = { CON_1, state->CON_1_val | 1 }; /* repeater stops once there was a stop condition */
+
+       memset(m, 0, sizeof(struct i2c_msg) * (1 + num));
+
+       m[0].addr = state->config->demod_address;
+       m[0].buf  = tx_open;
+       m[0].len  = 2;
 
-struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config,
-                                   struct i2c_adapter* i2c)
+       memcpy(&m[1], msg, sizeof(struct i2c_msg) * num);
+
+       return i2c_transfer(state->i2c, m, 1+num) == 1 + num ? num : -EIO;
+}
+
+static struct i2c_algorithm s5h1420_tuner_i2c_algo = {
+       .master_xfer   = s5h1420_tuner_i2c_tuner_xfer,
+       .functionality = s5h1420_tuner_i2c_func,
+};
+
+struct i2c_adapter *s5h1420_get_tuner_i2c_adapter(struct dvb_frontend *fe)
 {
-       struct s5h1420_state* state = NULL;
-       u8 identity;
+       struct s5h1420_state *state = fe->demodulator_priv;
+       return &state->tuner_i2c_adapter;
+}
+EXPORT_SYMBOL(s5h1420_get_tuner_i2c_adapter);
+
+static struct dvb_frontend_ops s5h1420_ops;
 
+struct dvb_frontend *s5h1420_attach(const struct s5h1420_config *config,
+                                   struct i2c_adapter *i2c)
+{
        /* allocate memory for the internal state */
-       state = kmalloc(sizeof(struct s5h1420_state), GFP_KERNEL);
+       struct s5h1420_state *state = kzalloc(sizeof(struct s5h1420_state), GFP_KERNEL);
+       u8 i;
+
        if (state == NULL)
                goto error;
 
@@ -772,24 +901,42 @@ struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config,
        state->symbol_rate = 0;
 
        /* check if the demod is there + identify it */
-       identity = s5h1420_readreg(state, 0x00);
-       if (identity != 0x03)
+       i = s5h1420_readreg(state, ID01);
+       if (i != 0x03)
                goto error;
 
+       memset(state->shadow, 0xff, sizeof(state->shadow));
+
+       for (i = 0; i < 0x50; i++)
+               state->shadow[i] = s5h1420_readreg(state, i);
+
        /* create dvb_frontend */
        memcpy(&state->frontend.ops, &s5h1420_ops, sizeof(struct dvb_frontend_ops));
        state->frontend.demodulator_priv = state;
+
+       /* create tuner i2c adapter */
+       strncpy(state->tuner_i2c_adapter.name, "S5H1420-PN1010 tuner I2C bus", I2C_NAME_SIZE);
+       state->tuner_i2c_adapter.class     = I2C_CLASS_TV_DIGITAL,
+       state->tuner_i2c_adapter.algo      = &s5h1420_tuner_i2c_algo;
+       state->tuner_i2c_adapter.algo_data = NULL;
+       i2c_set_adapdata(&state->tuner_i2c_adapter, state);
+       if (i2c_add_adapter(&state->tuner_i2c_adapter) < 0) {
+               printk(KERN_ERR "S5H1420/PN1010: tuner i2c bus could not be initialized\n");
+               goto error;
+       }
+
        return &state->frontend;
 
 error:
        kfree(state);
        return NULL;
 }
+EXPORT_SYMBOL(s5h1420_attach);
 
 static struct dvb_frontend_ops s5h1420_ops = {
 
        .info = {
-               .name     = "Samsung S5H1420 DVB-S",
+               .name     = "Samsung S5H1420/PnpNetwork PN1010 DVB-S",
                .type     = FE_QPSK,
                .frequency_min    = 950000,
                .frequency_max    = 2150000,
@@ -826,10 +973,6 @@ static struct dvb_frontend_ops s5h1420_ops = {
        .set_voltage = s5h1420_set_voltage,
 };
 
-module_param(debug, int, 0644);
-
-MODULE_DESCRIPTION("Samsung S5H1420 DVB-S Demodulator driver");
-MODULE_AUTHOR("Andrew de Quincey");
+MODULE_DESCRIPTION("Samsung S5H1420/PnpNetwork PN1010 DVB-S Demodulator driver");
+MODULE_AUTHOR("Andrew de Quincey, Patrick Boettcher");
 MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(s5h1420_attach);
index 1555870f7226b604ba6e9b2ef9e8eafdd82f26de..4c913f142bc4258a307fd38e63c1d488e97f72fb 100644 (file)
@@ -1,25 +1,26 @@
 /*
-    Driver for S5H1420 QPSK Demodulators
-
-    Copyright (C) 2005 Andrew de Quincey <adq_dvb@lidskialf.net>
-
-    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., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
+ * Driver for
+ *    Samsung S5H1420 and
+ *    PnpNetwork PN1010 QPSK Demodulator
+ *
+ * Copyright (C) 2005 Andrew de Quincey <adq_dvb@lidskialf.net>
+ * Copyright (C) 2005-8 Patrick Boettcher <pb@linuxtv.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.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
 #ifndef S5H1420_H
 #define S5H1420_H
 
@@ -31,17 +32,26 @@ struct s5h1420_config
        u8 demod_address;
 
        /* does the inversion require inversion? */
-       u8 invert:1;
+       u8 invert : 1;
+
+       u8 repeated_start_workaround : 1;
+       u8 cdclk_polarity : 1; /* 1 == falling edge, 0 == raising edge */
 };
 
 #if defined(CONFIG_DVB_S5H1420) || (defined(CONFIG_DVB_S5H1420_MODULE) && defined(MODULE))
-extern struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config,
-            struct i2c_adapter* i2c);
+extern struct dvb_frontend *s5h1420_attach(const struct s5h1420_config *config,
+            struct i2c_adapter *i2c);
+extern struct i2c_adapter *s5h1420_get_tuner_i2c_adapter(struct dvb_frontend *fe);
 #else
-static inline struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config,
-                                          struct i2c_adapter* i2c)
+static inline struct dvb_frontend *s5h1420_attach(const struct s5h1420_config *config,
+                                          struct i2c_adapter *i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return NULL;
+}
+
+static inline struct i2c_adapter *s5h1420_get_tuner_i2c_adapter(struct dvb_frontend *fe)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
        return NULL;
 }
 #endif // CONFIG_DVB_S5H1420
diff --git a/drivers/media/dvb/frontends/s5h1420_priv.h b/drivers/media/dvb/frontends/s5h1420_priv.h
new file mode 100644 (file)
index 0000000..d9c58d2
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Driver for
+ *    Samsung S5H1420 and
+ *    PnpNetwork PN1010 QPSK Demodulator
+ *
+ * Copyright (C) 2005 Andrew de Quincey <adq_dvb@lidskialf.net>
+ * Copyright (C) 2005 Patrick Boettcher <pb@linuxtv.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.
+ *
+ * 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., 675 Mass
+ * Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef S5H1420_PRIV
+#define S5H1420_PRIV
+
+#include <asm/types.h>
+
+enum s5h1420_register {
+       ID01      = 0x00,
+       CON_0     = 0x01,
+       CON_1     = 0x02,
+       PLL01     = 0x03,
+       PLL02     = 0x04,
+       QPSK01    = 0x05,
+       QPSK02    = 0x06,
+       Pre01     = 0x07,
+       Post01    = 0x08,
+       Loop01    = 0x09,
+       Loop02    = 0x0a,
+       Loop03    = 0x0b,
+       Loop04    = 0x0c,
+       Loop05    = 0x0d,
+       Pnco01    = 0x0e,
+       Pnco02    = 0x0f,
+       Pnco03    = 0x10,
+       Tnco01    = 0x11,
+       Tnco02    = 0x12,
+       Tnco03    = 0x13,
+       Monitor01 = 0x14,
+       Monitor02 = 0x15,
+       Monitor03 = 0x16,
+       Monitor04 = 0x17,
+       Monitor05 = 0x18,
+       Monitor06 = 0x19,
+       Monitor07 = 0x1a,
+       Monitor12 = 0x1f,
+
+       FEC01     = 0x22,
+       Soft01    = 0x23,
+       Soft02    = 0x24,
+       Soft03    = 0x25,
+       Soft04    = 0x26,
+       Soft05    = 0x27,
+       Soft06    = 0x28,
+       Vit01     = 0x29,
+       Vit02     = 0x2a,
+       Vit03     = 0x2b,
+       Vit04     = 0x2c,
+       Vit05     = 0x2d,
+       Vit06     = 0x2e,
+       Vit07     = 0x2f,
+       Vit08     = 0x30,
+       Vit09     = 0x31,
+       Vit10     = 0x32,
+       Vit11     = 0x33,
+       Vit12     = 0x34,
+       Sync01    = 0x35,
+       Sync02    = 0x36,
+       Rs01      = 0x37,
+       Mpeg01    = 0x38,
+       Mpeg02    = 0x39,
+       DiS01     = 0x3a,
+       DiS02     = 0x3b,
+       DiS03     = 0x3c,
+       DiS04     = 0x3d,
+       DiS05     = 0x3e,
+       DiS06     = 0x3f,
+       DiS07     = 0x40,
+       DiS08     = 0x41,
+       DiS09     = 0x42,
+       DiS10     = 0x43,
+       DiS11     = 0x44,
+       Rf01      = 0x45,
+       Err01     = 0x46,
+       Err02     = 0x47,
+       Err03     = 0x48,
+       Err04     = 0x49,
+};
+
+
+#endif
index da876f7bfe32b045595a568297c77c3f79aed534..aa78aa14aad927564108b19afa05a74efdabd646 100644 (file)
@@ -70,7 +70,7 @@ static int sp8870_writereg (struct sp8870_state* state, u16 reg, u16 data)
        int err;
 
        if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
-               dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __FUNCTION__, err, reg, data);
+               dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __func__, err, reg, data);
                return -EREMOTEIO;
        }
 
@@ -88,7 +88,7 @@ static int sp8870_readreg (struct sp8870_state* state, u16 reg)
        ret = i2c_transfer (state->i2c, msg, 2);
 
        if (ret != 2) {
-               dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
+               dprintk("%s: readreg error (ret == %i)\n", __func__, ret);
                return -1;
        }
 
@@ -104,7 +104,7 @@ static int sp8870_firmware_upload (struct sp8870_state* state, const struct firm
        int tx_len;
        int err = 0;
 
-       dprintk ("%s: ...\n", __FUNCTION__);
+       dprintk ("%s: ...\n", __func__);
 
        if (fw->size < SP8870_FIRMWARE_SIZE + SP8870_FIRMWARE_OFFSET)
                return -EINVAL;
@@ -131,14 +131,14 @@ static int sp8870_firmware_upload (struct sp8870_state* state, const struct firm
                msg.buf = tx_buf;
                msg.len = tx_len + 2;
                if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
-                       printk("%s: firmware upload failed!\n", __FUNCTION__);
-                       printk ("%s: i2c error (err == %i)\n", __FUNCTION__, err);
+                       printk("%s: firmware upload failed!\n", __func__);
+                       printk ("%s: i2c error (err == %i)\n", __func__, err);
                        return err;
                }
                fw_pos += tx_len;
        }
 
-       dprintk ("%s: done!\n", __FUNCTION__);
+       dprintk ("%s: done!\n", __func__);
        return 0;
 };
 
@@ -310,7 +310,7 @@ static int sp8870_init (struct dvb_frontend* fe)
        if (state->initialised) return 0;
        state->initialised = 1;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
 
        /* request the firmware, this will block until someone uploads it */
@@ -449,15 +449,15 @@ static int sp8870_read_uncorrected_blocks (struct dvb_frontend* fe, u32* ublocks
        return 0;
 }
 
-// number of trials to recover from lockup
+/* number of trials to recover from lockup */
 #define MAXTRIALS 5
-// maximum checks for data valid signal
+/* maximum checks for data valid signal */
 #define MAXCHECKS 100
 
-// only for debugging: counter for detected lockups
-static int lockups = 0;
-// only for debugging: counter for channel switches
-static int switches = 0;
+/* only for debugging: counter for detected lockups */
+static int lockups;
+/* only for debugging: counter for channel switches */
+static int switches;
 
 static int sp8870_set_frontend (struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
 {
@@ -475,7 +475,7 @@ static int sp8870_set_frontend (struct dvb_frontend* fe, struct dvb_frontend_par
        int trials = 0;
        int check_count = 0;
 
-       dprintk("%s: frequency = %i\n", __FUNCTION__, p->frequency);
+       dprintk("%s: frequency = %i\n", __func__, p->frequency);
 
        for (trials = 1; trials <= MAXTRIALS; trials++) {
 
@@ -487,7 +487,7 @@ static int sp8870_set_frontend (struct dvb_frontend* fe, struct dvb_frontend_par
                        valid = sp8870_read_data_valid_signal(state);
                        if (valid) {
                                dprintk("%s: delay = %i usec\n",
-                                       __FUNCTION__, check_count * 10);
+                                       __func__, check_count * 10);
                                break;
                        }
                        udelay(10);
@@ -497,20 +497,20 @@ static int sp8870_set_frontend (struct dvb_frontend* fe, struct dvb_frontend_par
        }
 
        if (!valid) {
-               printk("%s: firmware crash!!!!!!\n", __FUNCTION__);
+               printk("%s: firmware crash!!!!!!\n", __func__);
                return -EIO;
        }
 
        if (debug) {
                if (valid) {
                        if (trials > 1) {
-                               printk("%s: firmware lockup!!!\n", __FUNCTION__);
-                               printk("%s: recovered after %i trial(s))\n",  __FUNCTION__, trials - 1);
+                               printk("%s: firmware lockup!!!\n", __func__);
+                               printk("%s: recovered after %i trial(s))\n",  __func__, trials - 1);
                                lockups++;
                        }
                }
                switches++;
-               printk("%s: switches = %i lockups = %i\n", __FUNCTION__, switches, lockups);
+               printk("%s: switches = %i lockups = %i\n", __func__, switches, lockups);
        }
 
        return 0;
index 909cefe7139e2b623633caaa8e97cd51579eb602..a764a793c7d8204250e7ab80ec693ee9143e9a0e 100644 (file)
@@ -42,7 +42,7 @@ extern struct dvb_frontend* sp8870_attach(const struct sp8870_config* config,
 static inline struct dvb_frontend* sp8870_attach(const struct sp8870_config* config,
                                          struct i2c_adapter* i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_SP8870
index 1aa2539f5099b7528afb1cde568d48c97c0d1d9f..49f55877f51366f66e1b5225caf1e4fc756ad595 100644 (file)
@@ -43,7 +43,7 @@ static int i2c_writebytes (struct sp887x_state* state, u8 *buf, u8 len)
 
        if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
                printk ("%s: i2c write error (addr %02x, err == %i)\n",
-                       __FUNCTION__, state->config->demod_address, err);
+                       __func__, state->config->demod_address, err);
                return -EREMOTEIO;
        }
 
@@ -65,7 +65,7 @@ static int sp887x_writereg (struct sp887x_state* state, u16 reg, u16 data)
                {
                        printk("%s: writereg error "
                               "(reg %03x, data %03x, ret == %i)\n",
-                              __FUNCTION__, reg & 0xffff, data & 0xffff, ret);
+                              __func__, reg & 0xffff, data & 0xffff, ret);
                        return ret;
                }
        }
@@ -82,7 +82,7 @@ static int sp887x_readreg (struct sp887x_state* state, u16 reg)
                         { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 2 }};
 
        if ((ret = i2c_transfer(state->i2c, msg, 2)) != 2) {
-               printk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
+               printk("%s: readreg error (ret == %i)\n", __func__, ret);
                return -1;
        }
 
@@ -91,7 +91,7 @@ static int sp887x_readreg (struct sp887x_state* state, u16 reg)
 
 static void sp887x_microcontroller_stop (struct sp887x_state* state)
 {
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
        sp887x_writereg(state, 0xf08, 0x000);
        sp887x_writereg(state, 0xf09, 0x000);
 
@@ -101,7 +101,7 @@ static void sp887x_microcontroller_stop (struct sp887x_state* state)
 
 static void sp887x_microcontroller_start (struct sp887x_state* state)
 {
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
        sp887x_writereg(state, 0xf08, 0x000);
        sp887x_writereg(state, 0xf09, 0x000);
 
@@ -112,7 +112,7 @@ static void sp887x_microcontroller_start (struct sp887x_state* state)
 static void sp887x_setup_agc (struct sp887x_state* state)
 {
        /* setup AGC parameters */
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
        sp887x_writereg(state, 0x33c, 0x054);
        sp887x_writereg(state, 0x33b, 0x04c);
        sp887x_writereg(state, 0x328, 0x000);
@@ -142,7 +142,7 @@ static int sp887x_initial_setup (struct dvb_frontend* fe, const struct firmware
        int fw_size = fw->size;
        unsigned char *mem = fw->data;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        /* ignore the first 10 bytes, then we expect 0x4000 bytes of firmware */
        if (fw_size < FW_SIZE+10)
@@ -155,7 +155,7 @@ static int sp887x_initial_setup (struct dvb_frontend* fe, const struct firmware
 
        sp887x_microcontroller_stop (state);
 
-       printk ("%s: firmware upload... ", __FUNCTION__);
+       printk ("%s: firmware upload... ", __func__);
 
        /* setup write pointer to -1 (end of memory) */
        /* bit 0x8000 in address is set to enable 13bit mode */
@@ -181,7 +181,7 @@ static int sp887x_initial_setup (struct dvb_frontend* fe, const struct firmware
 
                if ((err = i2c_writebytes (state, buf, c+2)) < 0) {
                        printk ("failed.\n");
-                       printk ("%s: i2c error (err == %i)\n", __FUNCTION__, err);
+                       printk ("%s: i2c error (err == %i)\n", __func__, err);
                        return err;
                }
        }
index 7ee78d7d916d1f8925c32ab5c36204825569bb40..04eff6e0eef3e6eb3b189a872d295aa356b70448 100644 (file)
@@ -24,7 +24,7 @@ extern struct dvb_frontend* sp887x_attach(const struct sp887x_config* config,
 static inline struct dvb_frontend* sp887x_attach(const struct sp887x_config* config,
                                          struct i2c_adapter* i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_SP887X
index 7c23775f77dbe0582734c49ee9ffe5e9f1904cbc..62caf802ed990b0343e50f8374c97f451b7a5e50 100644 (file)
@@ -58,7 +58,7 @@ static int stv0297_writereg(struct stv0297_state *state, u8 reg, u8 data)
 
        if (ret != 1)
                dprintk("%s: writereg error (reg == 0x%02x, val == 0x%02x, "
-                       "ret == %i)\n", __FUNCTION__, reg, data, ret);
+                       "ret == %i)\n", __func__, reg, data, ret);
 
        return (ret != 1) ? -1 : 0;
 }
@@ -75,16 +75,16 @@ static int stv0297_readreg(struct stv0297_state *state, u8 reg)
        // this device needs a STOP between the register and data
        if (state->config->stop_during_read) {
                if ((ret = i2c_transfer(state->i2c, &msg[0], 1)) != 1) {
-                       dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret);
+                       dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg, ret);
                        return -1;
                }
                if ((ret = i2c_transfer(state->i2c, &msg[1], 1)) != 1) {
-                       dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret);
+                       dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg, ret);
                        return -1;
                }
        } else {
                if ((ret = i2c_transfer(state->i2c, msg, 2)) != 2) {
-                       dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret);
+                       dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg, ret);
                        return -1;
                }
        }
@@ -115,16 +115,16 @@ static int stv0297_readregs(struct stv0297_state *state, u8 reg1, u8 * b, u8 len
        // this device needs a STOP between the register and data
        if (state->config->stop_during_read) {
                if ((ret = i2c_transfer(state->i2c, &msg[0], 1)) != 1) {
-                       dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret);
+                       dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg1, ret);
                        return -1;
                }
                if ((ret = i2c_transfer(state->i2c, &msg[1], 1)) != 1) {
-                       dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret);
+                       dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg1, ret);
                        return -1;
                }
        } else {
                if ((ret = i2c_transfer(state->i2c, msg, 2)) != 2) {
-                       dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret);
+                       dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg1, ret);
                        return -1;
                }
        }
index 69f4515df2b9a0d84dd370f484347e684a72e652..3f8f9468f3878ffcd450a3976f7aea9d159da9dc 100644 (file)
@@ -49,7 +49,7 @@ extern struct dvb_frontend* stv0297_attach(const struct stv0297_config* config,
 static inline struct dvb_frontend* stv0297_attach(const struct stv0297_config* config,
                                           struct i2c_adapter* i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_STV0297
index 035dd7ba65194577aec5a8b52f30bfccfe14779c..17556183e871629c2ae4fabc116c598ce233ea70 100644 (file)
@@ -86,7 +86,7 @@ static int stv0299_writeregI (struct stv0299_state* state, u8 reg, u8 data)
 
        if (ret != 1)
                dprintk("%s: writereg error (reg == 0x%02x, val == 0x%02x, "
-                       "ret == %i)\n", __FUNCTION__, reg, data, ret);
+                       "ret == %i)\n", __func__, reg, data, ret);
 
        return (ret != 1) ? -EREMOTEIO : 0;
 }
@@ -113,7 +113,7 @@ static u8 stv0299_readreg (struct stv0299_state* state, u8 reg)
 
        if (ret != 2)
                dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n",
-                               __FUNCTION__, reg, ret);
+                               __func__, reg, ret);
 
        return b1[0];
 }
@@ -127,14 +127,14 @@ static int stv0299_readregs (struct stv0299_state* state, u8 reg1, u8 *b, u8 len
        ret = i2c_transfer (state->i2c, msg, 2);
 
        if (ret != 2)
-               dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
+               dprintk("%s: readreg error (ret == %i)\n", __func__, ret);
 
        return ret == 2 ? 0 : ret;
 }
 
 static int stv0299_set_FEC (struct stv0299_state* state, fe_code_rate_t fec)
 {
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        switch (fec) {
        case FEC_AUTO:
@@ -174,7 +174,7 @@ static fe_code_rate_t stv0299_get_fec (struct stv0299_state* state)
                                             FEC_7_8, FEC_1_2 };
        u8 index;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        index = stv0299_readreg (state, 0x1b);
        index &= 0x7;
@@ -189,11 +189,11 @@ static int stv0299_wait_diseqc_fifo (struct stv0299_state* state, int timeout)
 {
        unsigned long start = jiffies;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        while (stv0299_readreg(state, 0x0a) & 1) {
                if (jiffies - start > timeout) {
-                       dprintk ("%s: timeout!!\n", __FUNCTION__);
+                       dprintk ("%s: timeout!!\n", __func__);
                        return -ETIMEDOUT;
                }
                msleep(10);
@@ -206,11 +206,11 @@ static int stv0299_wait_diseqc_idle (struct stv0299_state* state, int timeout)
 {
        unsigned long start = jiffies;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        while ((stv0299_readreg(state, 0x0a) & 3) != 2 ) {
                if (jiffies - start > timeout) {
-                       dprintk ("%s: timeout!!\n", __FUNCTION__);
+                       dprintk ("%s: timeout!!\n", __func__);
                        return -ETIMEDOUT;
                }
                msleep(10);
@@ -245,7 +245,7 @@ static int stv0299_get_symbolrate (struct stv0299_state* state)
        u8 sfr[3];
        s8 rtf;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        stv0299_readregs (state, 0x1f, sfr, 3);
        stv0299_readregs (state, 0x1a, (u8 *)&rtf, 1);
@@ -257,8 +257,8 @@ static int stv0299_get_symbolrate (struct stv0299_state* state)
        offset = (s32) rtf * (srate / 4096L);
        offset /= 128;
 
-       dprintk ("%s : srate = %i\n", __FUNCTION__, srate);
-       dprintk ("%s : ofset = %i\n", __FUNCTION__, offset);
+       dprintk ("%s : srate = %i\n", __func__, srate);
+       dprintk ("%s : ofset = %i\n", __func__, offset);
 
        srate += offset;
 
@@ -276,7 +276,7 @@ static int stv0299_send_diseqc_msg (struct dvb_frontend* fe,
        u8 val;
        int i;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        if (stv0299_wait_diseqc_idle (state, 100) < 0)
                return -ETIMEDOUT;
@@ -305,7 +305,7 @@ static int stv0299_send_diseqc_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t
        struct stv0299_state* state = fe->demodulator_priv;
        u8 val;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        if (stv0299_wait_diseqc_idle (state, 100) < 0)
                return -ETIMEDOUT;
@@ -355,7 +355,7 @@ static int stv0299_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag
        u8 reg0x08;
        u8 reg0x0c;
 
-       dprintk("%s: %s\n", __FUNCTION__,
+       dprintk("%s: %s\n", __func__,
                voltage == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" :
                voltage == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "??");
 
@@ -366,26 +366,32 @@ static int stv0299_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag
         *  H/V switching over OP0, OP1 and OP2 are LNB power enable bits
         */
        reg0x0c &= 0x0f;
-
-       if (voltage == SEC_VOLTAGE_OFF) {
-               stv0299_writeregI (state, 0x0c, 0x00); /*       LNB power off! */
-               return stv0299_writeregI (state, 0x08, 0x00); /*        LNB power off! */
-       }
-
-       stv0299_writeregI (state, 0x08, (reg0x08 & 0x3f) | (state->config->lock_output << 6));
+       reg0x08 = (reg0x08 & 0x3f) | (state->config->lock_output << 6);
 
        switch (voltage) {
        case SEC_VOLTAGE_13:
-               if (state->config->volt13_op0_op1 == STV0299_VOLT13_OP0) reg0x0c |= 0x10;
-               else reg0x0c |= 0x40;
-
-               return stv0299_writeregI(state, 0x0c, reg0x0c);
-
+               if (state->config->volt13_op0_op1 == STV0299_VOLT13_OP0)
+                       reg0x0c |= 0x10; /* OP1 off, OP0 on */
+               else
+                       reg0x0c |= 0x40; /* OP1 on, OP0 off */
+               break;
        case SEC_VOLTAGE_18:
-               return stv0299_writeregI(state, 0x0c, reg0x0c | 0x50);
+               reg0x0c |= 0x50; /* OP1 on, OP0 on */
+               break;
+       case SEC_VOLTAGE_OFF:
+               /* LNB power off! */
+               reg0x08 = 0x00;
+               reg0x0c = 0x00;
+               break;
        default:
                return -EINVAL;
        };
+
+       if (state->config->op0_off)
+               reg0x0c &= ~0x10;
+
+       stv0299_writeregI(state, 0x08, reg0x08);
+       return stv0299_writeregI(state, 0x0c, reg0x0c);
 }
 
 static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long cmd)
@@ -408,7 +414,7 @@ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long
 
        cmd = cmd << 1;
        if (debug_legacy_dish_switch)
-               printk ("%s switch command: 0x%04lx\n",__FUNCTION__, cmd);
+               printk ("%s switch command: 0x%04lx\n",__func__, cmd);
 
        do_gettimeofday (&nexttime);
        if (debug_legacy_dish_switch)
@@ -433,7 +439,7 @@ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long
        }
        if (debug_legacy_dish_switch) {
                printk ("%s(%d): switch delay (should be 32k followed by all 8k\n",
-                       __FUNCTION__, fe->dvb->num);
+                       __func__, fe->dvb->num);
                for (i = 1; i < 10; i++)
                        printk ("%d: %d\n", i, timeval_usec_diff(tv[i-1] , tv[i]));
        }
@@ -445,11 +451,20 @@ static int stv0299_init (struct dvb_frontend* fe)
 {
        struct stv0299_state* state = fe->demodulator_priv;
        int i;
+       u8 reg;
+       u8 val;
 
        dprintk("stv0299: init chip\n");
 
-       for (i=0; !(state->config->inittab[i] == 0xff && state->config->inittab[i+1] == 0xff); i+=2)
-               stv0299_writeregI(state, state->config->inittab[i], state->config->inittab[i+1]);
+       for (i = 0; ; i += 2)  {
+               reg = state->config->inittab[i];
+               val = state->config->inittab[i+1];
+               if (reg == 0xff && val == 0xff)
+                       break;
+               if (reg == 0x0c && state->config->op0_off)
+                       val &= ~0x10;
+               stv0299_writeregI(state, reg, val);
+       }
 
        return 0;
 }
@@ -461,7 +476,7 @@ static int stv0299_read_status(struct dvb_frontend* fe, fe_status_t* status)
        u8 signal = 0xff - stv0299_readreg (state, 0x18);
        u8 sync = stv0299_readreg (state, 0x1b);
 
-       dprintk ("%s : FE_READ_STATUS : VSTATUS: 0x%02x\n", __FUNCTION__, sync);
+       dprintk ("%s : FE_READ_STATUS : VSTATUS: 0x%02x\n", __func__, sync);
        *status = 0;
 
        if (signal > 10)
@@ -499,7 +514,7 @@ static int stv0299_read_signal_strength(struct dvb_frontend* fe, u16* strength)
        s32 signal =  0xffff - ((stv0299_readreg (state, 0x18) << 8)
                               | stv0299_readreg (state, 0x19));
 
-       dprintk ("%s : FE_READ_SIGNAL_STRENGTH : AGC2I: 0x%02x%02x, signal=0x%04x\n", __FUNCTION__,
+       dprintk ("%s : FE_READ_SIGNAL_STRENGTH : AGC2I: 0x%02x%02x, signal=0x%04x\n", __func__,
                 stv0299_readreg (state, 0x18),
                 stv0299_readreg (state, 0x19), (int) signal);
 
@@ -536,7 +551,7 @@ static int stv0299_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
        struct stv0299_state* state = fe->demodulator_priv;
        int invval = 0;
 
-       dprintk ("%s : FE_SET_FRONTEND\n", __FUNCTION__);
+       dprintk ("%s : FE_SET_FRONTEND\n", __func__);
 
        // set the inversion
        if (p->inversion == INVERSION_OFF) invval = 0;
index 33df9495908fb8a1a4f9d9afb67bd53b3756a6b8..3282f43022f5da37d2681e34a20c235e94828176 100644 (file)
 #include <linux/dvb/frontend.h>
 #include "dvb_frontend.h"
 
-#define STV0229_LOCKOUTPUT_0  0
-#define STV0229_LOCKOUTPUT_1  1
-#define STV0229_LOCKOUTPUT_CF 2
-#define STV0229_LOCKOUTPUT_LK 3
+#define STV0299_LOCKOUTPUT_0  0
+#define STV0299_LOCKOUTPUT_1  1
+#define STV0299_LOCKOUTPUT_CF 2
+#define STV0299_LOCKOUTPUT_LK 3
 
 #define STV0299_VOLT13_OP0 0
 #define STV0299_VOLT13_OP1 1
@@ -82,6 +82,9 @@ struct stv0299_config
        /* Is 13v controlled by OP0 or OP1? */
        u8 volt13_op0_op1:1;
 
+       /* Turn-off OP0? */
+       u8 op0_off:1;
+
        /* minimum delay before retuning */
        int min_delay_ms;
 
@@ -96,7 +99,7 @@ extern struct dvb_frontend* stv0299_attach(const struct stv0299_config* config,
 static inline struct dvb_frontend* stv0299_attach(const struct stv0299_config* config,
                                           struct i2c_adapter* i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_STV0299
index 45137d2ebfb9846b3462e20981eb0dd91adc0973..f648fdb64bb7dd33753522bb70e6619bc8c42f87 100644 (file)
@@ -79,7 +79,7 @@ static int _tda10021_writereg (struct tda10021_state* state, u8 reg, u8 data)
        if (ret != 1)
                printk("DVB: TDA10021(%d): %s, writereg error "
                        "(reg == 0x%02x, val == 0x%02x, ret == %i)\n",
-                       state->frontend.dvb->num, __FUNCTION__, reg, data, ret);
+                       state->frontend.dvb->num, __func__, reg, data, ret);
 
        msleep(10);
        return (ret != 1) ? -EREMOTEIO : 0;
@@ -97,7 +97,7 @@ static u8 tda10021_readreg (struct tda10021_state* state, u8 reg)
        // Don't print an error message if the id is read.
        if (ret != 2 && reg != 0x1a)
                printk("DVB: TDA10021: %s: readreg error (ret == %i)\n",
-                               __FUNCTION__, ret);
+                               __func__, ret);
        return b1[0];
 }
 
index 364bc01971a0c7c4071ac98d0fd9f6e5e86fced8..0727b80bc4d296a83f56317b9266fdbac705f562 100644 (file)
@@ -118,7 +118,7 @@ static u8 tda10023_readreg (struct tda10023_state* state, u8 reg)
        ret = i2c_transfer (state->i2c, msg, 2);
        if (ret != 2)
                printk("DVB: TDA10023: %s: readreg error (ret == %i)\n",
-                                __FUNCTION__, ret);
+                                __func__, ret);
        return b1[0];
 }
 
@@ -132,7 +132,7 @@ static int tda10023_writereg (struct tda10023_state* state, u8 reg, u8 data)
        if (ret != 1)
                printk("DVB: TDA10023(%d): %s, writereg error "
                        "(reg == 0x%02x, val == 0x%02x, ret == %i)\n",
-                       state->frontend.dvb->num, __FUNCTION__, reg, data, ret);
+                       state->frontend.dvb->num, __func__, reg, data, ret);
 
        return (ret != 1) ? -EREMOTEIO : 0;
 }
index e9094d8123f6bb5ffb02473eff90fa12efd42999..1bcc0d44b90bf789d33b73d5bb93b96014f6ec02 100644 (file)
@@ -40,7 +40,7 @@ extern struct dvb_frontend* tda10021_attach(const struct tda1002x_config* config
 static inline struct dvb_frontend* tda10021_attach(const struct tda1002x_config* config,
                                            struct i2c_adapter* i2c, u8 pwm)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_TDA10021
@@ -52,7 +52,7 @@ extern struct dvb_frontend* tda10023_attach(const struct tda1002x_config* config
 static inline struct dvb_frontend* tda10023_attach(const struct tda1002x_config* config,
                                            struct i2c_adapter* i2c, u8 pwm)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_TDA10023
diff --git a/drivers/media/dvb/frontends/tda10048.c b/drivers/media/dvb/frontends/tda10048.c
new file mode 100644 (file)
index 0000000..090fb7d
--- /dev/null
@@ -0,0 +1,841 @@
+/*
+    NXP TDA10048HN DVB OFDM demodulator driver
+
+    Copyright (C) 2008 Steven Toth <stoth@hauppauge.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include "dvb_frontend.h"
+#include "dvb_math.h"
+#include "tda10048.h"
+
+#define TDA10048_DEFAULT_FIRMWARE "dvb-fe-tda10048-1.0.fw"
+#define TDA10048_DEFAULT_FIRMWARE_SIZE 24878
+
+/* Register name definitions */
+#define TDA10048_IDENTITY          0x00
+#define TDA10048_VERSION           0x01
+#define TDA10048_DSP_CODE_CPT      0x0C
+#define TDA10048_DSP_CODE_IN       0x0E
+#define TDA10048_IN_CONF1          0x10
+#define TDA10048_IN_CONF2          0x11
+#define TDA10048_IN_CONF3          0x12
+#define TDA10048_OUT_CONF1         0x14
+#define TDA10048_OUT_CONF2         0x15
+#define TDA10048_OUT_CONF3         0x16
+#define TDA10048_AUTO              0x18
+#define TDA10048_SYNC_STATUS       0x1A
+#define TDA10048_CONF_C4_1         0x1E
+#define TDA10048_CONF_C4_2         0x1F
+#define TDA10048_CODE_IN_RAM       0x20
+#define TDA10048_CHANNEL_INFO_1_R  0x22
+#define TDA10048_CHANNEL_INFO_2_R  0x23
+#define TDA10048_CHANNEL_INFO1     0x24
+#define TDA10048_CHANNEL_INFO2     0x25
+#define TDA10048_TIME_ERROR_R      0x26
+#define TDA10048_TIME_ERROR        0x27
+#define TDA10048_FREQ_ERROR_LSB_R  0x28
+#define TDA10048_FREQ_ERROR_MSB_R  0x29
+#define TDA10048_FREQ_ERROR_LSB    0x2A
+#define TDA10048_FREQ_ERROR_MSB    0x2B
+#define TDA10048_IT_SEL            0x30
+#define TDA10048_IT_STAT           0x32
+#define TDA10048_DSP_AD_LSB        0x3C
+#define TDA10048_DSP_AD_MSB        0x3D
+#define TDA10048_DSP_REF_LSB       0x3E
+#define TDA10048_DSP_REF_MSB       0x3F
+#define TDA10048_CONF_TRISTATE1    0x44
+#define TDA10048_CONF_TRISTATE2    0x45
+#define TDA10048_CONF_POLARITY     0x46
+#define TDA10048_GPIO_SP_DS0       0x48
+#define TDA10048_GPIO_SP_DS1       0x49
+#define TDA10048_GPIO_SP_DS2       0x4A
+#define TDA10048_GPIO_SP_DS3       0x4B
+#define TDA10048_GPIO_OUT_SEL      0x4C
+#define TDA10048_GPIO_SELECT       0x4D
+#define TDA10048_IC_MODE           0x4E
+#define TDA10048_CONF_XO           0x50
+#define TDA10048_CONF_PLL1         0x51
+#define TDA10048_CONF_PLL2         0x52
+#define TDA10048_CONF_PLL3         0x53
+#define TDA10048_CONF_ADC          0x54
+#define TDA10048_CONF_ADC_2        0x55
+#define TDA10048_CONF_C1_1         0x60
+#define TDA10048_CONF_C1_3         0x62
+#define TDA10048_AGC_CONF          0x70
+#define TDA10048_AGC_THRESHOLD_LSB 0x72
+#define TDA10048_AGC_THRESHOLD_MSB 0x73
+#define TDA10048_AGC_RENORM        0x74
+#define TDA10048_AGC_GAINS         0x76
+#define TDA10048_AGC_TUN_MIN       0x78
+#define TDA10048_AGC_TUN_MAX       0x79
+#define TDA10048_AGC_IF_MIN        0x7A
+#define TDA10048_AGC_IF_MAX        0x7B
+#define TDA10048_AGC_TUN_LEVEL     0x7E
+#define TDA10048_AGC_IF_LEVEL      0x7F
+#define TDA10048_DIG_AGC_LEVEL     0x81
+#define TDA10048_FREQ_PHY2_LSB     0x86
+#define TDA10048_FREQ_PHY2_MSB     0x87
+#define TDA10048_TIME_INVWREF_LSB  0x88
+#define TDA10048_TIME_INVWREF_MSB  0x89
+#define TDA10048_TIME_WREF_LSB     0x8A
+#define TDA10048_TIME_WREF_MID1    0x8B
+#define TDA10048_TIME_WREF_MID2    0x8C
+#define TDA10048_TIME_WREF_MSB     0x8D
+#define TDA10048_NP_OUT            0xA2
+#define TDA10048_CELL_ID_LSB       0xA4
+#define TDA10048_CELL_ID_MSB       0xA5
+#define TDA10048_EXTTPS_ODD        0xAA
+#define TDA10048_EXTTPS_EVEN       0xAB
+#define TDA10048_TPS_LENGTH        0xAC
+#define TDA10048_FREE_REG_1        0xB2
+#define TDA10048_FREE_REG_2        0xB3
+#define TDA10048_CONF_C3_1         0xC0
+#define TDA10048_CYBER_CTRL        0xC2
+#define TDA10048_CBER_NMAX_LSB     0xC4
+#define TDA10048_CBER_NMAX_MSB     0xC5
+#define TDA10048_CBER_LSB          0xC6
+#define TDA10048_CBER_MSB          0xC7
+#define TDA10048_VBER_LSB          0xC8
+#define TDA10048_VBER_MID          0xC9
+#define TDA10048_VBER_MSB          0xCA
+#define TDA10048_CYBER_LUT         0xCC
+#define TDA10048_UNCOR_CTRL        0xCD
+#define TDA10048_UNCOR_CPT_LSB     0xCE
+#define TDA10048_UNCOR_CPT_MSB     0xCF
+#define TDA10048_SOFT_IT_C3        0xD6
+#define TDA10048_CONF_TS2          0xE0
+#define TDA10048_CONF_TS1          0xE1
+
+static unsigned int debug;
+
+#define dprintk(level, fmt, arg...)\
+       do { if (debug >= level)\
+               printk(KERN_DEBUG "tda10048: " fmt, ## arg);\
+       } while (0)
+
+struct tda10048_state {
+
+       struct i2c_adapter *i2c;
+
+       /* configuration settings */
+       const struct tda10048_config *config;
+       struct dvb_frontend frontend;
+
+       int fwloaded;
+};
+
+static struct init_tab {
+       u8      reg;
+       u16     data;
+} init_tab[] = {
+       { TDA10048_CONF_PLL1, 0x08 },
+       { TDA10048_CONF_ADC_2, 0x00 },
+       { TDA10048_CONF_C4_1, 0x00 },
+       { TDA10048_CONF_PLL1, 0x0f },
+       { TDA10048_CONF_PLL2, 0x0a },
+       { TDA10048_CONF_PLL3, 0x43 },
+       { TDA10048_FREQ_PHY2_LSB, 0x02 },
+       { TDA10048_FREQ_PHY2_MSB, 0x0a },
+       { TDA10048_TIME_WREF_LSB, 0xbd },
+       { TDA10048_TIME_WREF_MID1, 0xe4 },
+       { TDA10048_TIME_WREF_MID2, 0xa8 },
+       { TDA10048_TIME_WREF_MSB, 0x02 },
+       { TDA10048_TIME_INVWREF_LSB, 0x04 },
+       { TDA10048_TIME_INVWREF_MSB, 0x06 },
+       { TDA10048_CONF_C4_1, 0x00 },
+       { TDA10048_CONF_C1_1, 0xa8 },
+       { TDA10048_AGC_CONF, 0x16 },
+       { TDA10048_CONF_C1_3, 0x0b },
+       { TDA10048_AGC_TUN_MIN, 0x00 },
+       { TDA10048_AGC_TUN_MAX, 0xff },
+       { TDA10048_AGC_IF_MIN, 0x00 },
+       { TDA10048_AGC_IF_MAX, 0xff },
+       { TDA10048_AGC_THRESHOLD_MSB, 0x00 },
+       { TDA10048_AGC_THRESHOLD_LSB, 0x70 },
+       { TDA10048_CYBER_CTRL, 0x38 },
+       { TDA10048_AGC_GAINS, 0x12 },
+       { TDA10048_CONF_XO, 0x00 },
+       { TDA10048_CONF_TS1, 0x07 },
+       { TDA10048_IC_MODE, 0x00 },
+       { TDA10048_CONF_TS2, 0xc0 },
+       { TDA10048_CONF_TRISTATE1, 0x21 },
+       { TDA10048_CONF_TRISTATE2, 0x00 },
+       { TDA10048_CONF_POLARITY, 0x00 },
+       { TDA10048_CONF_C4_2, 0x04 },
+       { TDA10048_CONF_ADC, 0x60 },
+       { TDA10048_CONF_ADC_2, 0x10 },
+       { TDA10048_CONF_ADC, 0x60 },
+       { TDA10048_CONF_ADC_2, 0x00 },
+       { TDA10048_CONF_C1_1, 0xa8 },
+       { TDA10048_UNCOR_CTRL, 0x00 },
+       { TDA10048_CONF_C4_2, 0x04 },
+};
+
+static int tda10048_writereg(struct tda10048_state *state, u8 reg, u8 data)
+{
+       int ret;
+       u8 buf [] = { reg, data };
+       struct i2c_msg msg = {
+               .addr = state->config->demod_address,
+               .flags = 0, .buf = buf, .len = 2 };
+
+       dprintk(2, "%s(reg = 0x%02x, data = 0x%02x)\n", __func__, reg, data);
+
+       ret = i2c_transfer(state->i2c, &msg, 1);
+
+       if (ret != 1)
+               printk("%s: writereg error (ret == %i)\n", __func__, ret);
+
+       return (ret != 1) ? -1 : 0;
+}
+
+static u8 tda10048_readreg(struct tda10048_state *state, u8 reg)
+{
+       int ret;
+       u8 b0 [] = { reg };
+       u8 b1 [] = { 0 };
+       struct i2c_msg msg [] = {
+               { .addr = state->config->demod_address,
+                       .flags = 0, .buf = b0, .len = 1 },
+               { .addr = state->config->demod_address,
+                       .flags = I2C_M_RD, .buf = b1, .len = 1 } };
+
+       dprintk(2, "%s(reg = 0x%02x)\n", __func__, reg);
+
+       ret = i2c_transfer(state->i2c, msg, 2);
+
+       if (ret != 2)
+               printk(KERN_ERR "%s: readreg error (ret == %i)\n",
+                       __func__, ret);
+
+       return b1[0];
+}
+
+static int tda10048_writeregbulk(struct tda10048_state *state, u8 reg,
+       u8 *data, u16 len)
+{
+       int ret = -EREMOTEIO;
+       struct i2c_msg msg;
+       u8 *buf;
+
+       dprintk(2, "%s(%d, ?, len = %d)\n", __func__, reg, len);
+
+       buf = kmalloc(len + 1, GFP_KERNEL);
+       if (buf == NULL) {
+               ret = -ENOMEM;
+               goto error;
+       }
+
+       *buf = reg;
+       memcpy(buf + 1, data, len);
+
+       msg.addr = state->config->demod_address;
+       msg.flags = 0;
+       msg.buf = buf;
+       msg.len = len + 1;
+
+       dprintk(2, "%s():  write len = %d\n",
+               __func__, msg.len);
+
+       ret = i2c_transfer(state->i2c, &msg, 1);
+       if (ret != 1) {
+               printk(KERN_ERR "%s(): writereg error err %i\n",
+                        __func__, ret);
+               ret = -EREMOTEIO;
+       }
+
+error:
+       kfree(buf);
+
+       return ret;
+}
+
+static int tda10048_firmware_upload(struct dvb_frontend *fe)
+{
+       struct tda10048_state *state = fe->demodulator_priv;
+       const struct firmware *fw;
+       int ret;
+       int pos = 0;
+       int cnt;
+       u8 wlen = state->config->fwbulkwritelen;
+
+       if ((wlen != TDA10048_BULKWRITE_200) && (wlen != TDA10048_BULKWRITE_50))
+               wlen = TDA10048_BULKWRITE_200;
+
+       /* request the firmware, this will block and timeout */
+       printk(KERN_INFO "%s: waiting for firmware upload (%s)...\n",
+               __func__,
+               TDA10048_DEFAULT_FIRMWARE);
+
+       ret = request_firmware(&fw, TDA10048_DEFAULT_FIRMWARE,
+               &state->i2c->dev);
+       if (ret) {
+               printk(KERN_ERR "%s: Upload failed. (file not found?)\n",
+                       __func__);
+               return -EIO;
+       } else {
+               printk(KERN_INFO "%s: firmware read %Zu bytes.\n",
+                       __func__,
+                       fw->size);
+               ret = 0;
+       }
+
+       if (fw->size != TDA10048_DEFAULT_FIRMWARE_SIZE) {
+               printk(KERN_ERR "%s: firmware incorrect size\n", __func__);
+               return -EIO;
+       } else {
+               printk(KERN_INFO "%s: firmware uploading\n", __func__);
+
+               /* Soft reset */
+               tda10048_writereg(state, TDA10048_CONF_TRISTATE1,
+                       tda10048_readreg(state, TDA10048_CONF_TRISTATE1)
+                               & 0xfe);
+               tda10048_writereg(state, TDA10048_CONF_TRISTATE1,
+                       tda10048_readreg(state, TDA10048_CONF_TRISTATE1)
+                               | 0x01);
+
+               /* Put the demod into host download mode */
+               tda10048_writereg(state, TDA10048_CONF_C4_1,
+                       tda10048_readreg(state, TDA10048_CONF_C4_1) & 0xf9);
+
+               /* Boot the DSP */
+               tda10048_writereg(state, TDA10048_CONF_C4_1,
+                       tda10048_readreg(state, TDA10048_CONF_C4_1) | 0x08);
+
+               /* Prepare for download */
+               tda10048_writereg(state, TDA10048_DSP_CODE_CPT, 0);
+
+               /* Download the firmware payload */
+               while (pos < fw->size) {
+
+                       if ((fw->size - pos) > wlen)
+                               cnt = wlen;
+                       else
+                               cnt = fw->size - pos;
+
+                       tda10048_writeregbulk(state, TDA10048_DSP_CODE_IN,
+                               &fw->data[pos], cnt);
+
+                       pos += cnt;
+               }
+
+               ret = -EIO;
+               /* Wait up to 250ms for the DSP to boot */
+               for (cnt = 0; cnt < 250 ; cnt += 10) {
+
+                       msleep(10);
+
+                       if (tda10048_readreg(state, TDA10048_SYNC_STATUS)
+                               & 0x40) {
+                               ret = 0;
+                               break;
+                       }
+               }
+       }
+
+       release_firmware(fw);
+
+       if (ret == 0) {
+               printk(KERN_INFO "%s: firmware uploaded\n", __func__);
+               state->fwloaded = 1;
+       } else
+               printk(KERN_ERR "%s: firmware upload failed\n", __func__);
+
+       return ret;
+}
+
+static int tda10048_set_inversion(struct dvb_frontend *fe, int inversion)
+{
+       struct tda10048_state *state = fe->demodulator_priv;
+
+       dprintk(1, "%s(%d)\n", __func__, inversion);
+
+       if (inversion == TDA10048_INVERSION_ON)
+               tda10048_writereg(state, TDA10048_CONF_C1_1,
+                       tda10048_readreg(state, TDA10048_CONF_C1_1) | 0x20);
+       else
+               tda10048_writereg(state, TDA10048_CONF_C1_1,
+                       tda10048_readreg(state, TDA10048_CONF_C1_1) & 0xdf);
+
+       return 0;
+}
+
+/* Retrieve the demod settings */
+static int tda10048_get_tps(struct tda10048_state *state,
+       struct dvb_ofdm_parameters *p)
+{
+       u8 val;
+
+       /* Make sure the TPS regs are valid */
+       if (!(tda10048_readreg(state, TDA10048_AUTO) & 0x01))
+               return -EAGAIN;
+
+       val = tda10048_readreg(state, TDA10048_OUT_CONF2);
+       switch ((val & 0x60) >> 5) {
+       case 0: p->constellation =   QPSK; break;
+       case 1: p->constellation = QAM_16; break;
+       case 2: p->constellation = QAM_64; break;
+       }
+       switch ((val & 0x18) >> 3) {
+       case 0: p->hierarchy_information = HIERARCHY_NONE; break;
+       case 1: p->hierarchy_information =    HIERARCHY_1; break;
+       case 2: p->hierarchy_information =    HIERARCHY_2; break;
+       case 3: p->hierarchy_information =    HIERARCHY_4; break;
+       }
+       switch (val & 0x07) {
+       case 0: p->code_rate_HP = FEC_1_2; break;
+       case 1: p->code_rate_HP = FEC_2_3; break;
+       case 2: p->code_rate_HP = FEC_3_4; break;
+       case 3: p->code_rate_HP = FEC_5_6; break;
+       case 4: p->code_rate_HP = FEC_7_8; break;
+       }
+
+       val = tda10048_readreg(state, TDA10048_OUT_CONF3);
+       switch (val & 0x07) {
+       case 0: p->code_rate_LP = FEC_1_2; break;
+       case 1: p->code_rate_LP = FEC_2_3; break;
+       case 2: p->code_rate_LP = FEC_3_4; break;
+       case 3: p->code_rate_LP = FEC_5_6; break;
+       case 4: p->code_rate_LP = FEC_7_8; break;
+       }
+
+       val = tda10048_readreg(state, TDA10048_OUT_CONF1);
+       switch ((val & 0x0c) >> 2) {
+       case 0: p->guard_interval = GUARD_INTERVAL_1_32; break;
+       case 1: p->guard_interval = GUARD_INTERVAL_1_16; break;
+       case 2: p->guard_interval =  GUARD_INTERVAL_1_8; break;
+       case 3: p->guard_interval =  GUARD_INTERVAL_1_4; break;
+       }
+       switch (val & 0x02) {
+       case 0: p->transmission_mode = TRANSMISSION_MODE_2K; break;
+       case 1: p->transmission_mode = TRANSMISSION_MODE_8K; break;
+       }
+
+       return 0;
+}
+
+static int tda10048_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+       struct tda10048_state *state = fe->demodulator_priv;
+       dprintk(1, "%s(%d)\n", __func__, enable);
+
+       if (enable)
+               return tda10048_writereg(state, TDA10048_CONF_C4_1,
+                       tda10048_readreg(state, TDA10048_CONF_C4_1) | 0x02);
+       else
+               return tda10048_writereg(state, TDA10048_CONF_C4_1,
+                       tda10048_readreg(state, TDA10048_CONF_C4_1) & 0xfd);
+}
+
+static int tda10048_output_mode(struct dvb_frontend *fe, int serial)
+{
+       struct tda10048_state *state = fe->demodulator_priv;
+       dprintk(1, "%s(%d)\n", __func__, serial);
+
+       /* Ensure pins are out of tri-state */
+       tda10048_writereg(state, TDA10048_CONF_TRISTATE1, 0x21);
+       tda10048_writereg(state, TDA10048_CONF_TRISTATE2, 0x00);
+
+       if (serial) {
+               tda10048_writereg(state, TDA10048_IC_MODE, 0x80 | 0x20);
+               tda10048_writereg(state, TDA10048_CONF_TS2, 0xc0);
+       } else {
+               tda10048_writereg(state, TDA10048_IC_MODE, 0x00);
+               tda10048_writereg(state, TDA10048_CONF_TS2, 0x01);
+       }
+
+       return 0;
+}
+
+/* Talk to the demod, set the FEC, GUARD, QAM settings etc */
+/* TODO: Support manual tuning with specific params */
+static int tda10048_set_frontend(struct dvb_frontend *fe,
+       struct dvb_frontend_parameters *p)
+{
+       struct tda10048_state *state = fe->demodulator_priv;
+
+       dprintk(1, "%s(frequency=%d)\n", __func__, p->frequency);
+
+       if (fe->ops.tuner_ops.set_params) {
+
+               if (fe->ops.i2c_gate_ctrl)
+                       fe->ops.i2c_gate_ctrl(fe, 1);
+
+               fe->ops.tuner_ops.set_params(fe, p);
+
+               if (fe->ops.i2c_gate_ctrl)
+                       fe->ops.i2c_gate_ctrl(fe, 0);
+       }
+
+       /* Enable demod TPS auto detection and begin acquisition */
+       tda10048_writereg(state, TDA10048_AUTO, 0x57);
+
+       return 0;
+}
+
+/* Establish sane defaults and load firmware. */
+static int tda10048_init(struct dvb_frontend *fe)
+{
+       struct tda10048_state *state = fe->demodulator_priv;
+       int ret = 0, i;
+
+       dprintk(1, "%s()\n", __func__);
+
+       /* Apply register defaults */
+       for (i = 0; i < ARRAY_SIZE(init_tab); i++)
+               tda10048_writereg(state, init_tab[i].reg, init_tab[i].data);
+
+       if (state->fwloaded == 0)
+               ret = tda10048_firmware_upload(fe);
+
+       /* Set either serial or parallel */
+       tda10048_output_mode(fe, state->config->output_mode);
+
+       /* set inversion */
+       tda10048_set_inversion(fe, state->config->inversion);
+
+       /* Ensure we leave the gate closed */
+       tda10048_i2c_gate_ctrl(fe, 0);
+
+       return ret;
+}
+
+static int tda10048_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+       struct tda10048_state *state = fe->demodulator_priv;
+       u8 reg;
+
+       *status = 0;
+
+       reg = tda10048_readreg(state, TDA10048_SYNC_STATUS);
+
+       dprintk(1, "%s() status =0x%02x\n", __func__, reg);
+
+       if (reg & 0x02)
+               *status |= FE_HAS_CARRIER;
+
+       if (reg & 0x04)
+               *status |= FE_HAS_SIGNAL;
+
+       if (reg & 0x08) {
+               *status |= FE_HAS_LOCK;
+               *status |= FE_HAS_VITERBI;
+               *status |= FE_HAS_SYNC;
+       }
+
+       return 0;
+}
+
+static int tda10048_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+       struct tda10048_state *state = fe->demodulator_priv;
+
+       dprintk(1, "%s()\n", __func__);
+
+       /* TODO: A reset may be required here */
+       *ber = tda10048_readreg(state, TDA10048_CBER_MSB) << 8 |
+               tda10048_readreg(state, TDA10048_CBER_LSB);
+
+       return 0;
+}
+
+static int tda10048_read_signal_strength(struct dvb_frontend *fe,
+       u16 *signal_strength)
+{
+       struct tda10048_state *state = fe->demodulator_priv;
+       u8 v;
+
+       dprintk(1, "%s()\n", __func__);
+
+       *signal_strength = 65535;
+
+       v = tda10048_readreg(state, TDA10048_NP_OUT);
+       if (v > 0)
+               *signal_strength -= (v << 8) | v;
+
+       return 0;
+}
+
+/* SNR lookup table */
+static struct snr_tab {
+       u8 val;
+       u8 data;
+} snr_tab[] = {
+       {   0,   0 },
+       {   1, 246 },
+       {   2, 215 },
+       {   3, 198 },
+       {   4, 185 },
+       {   5, 176 },
+       {   6, 168 },
+       {   7, 161 },
+       {   8, 155 },
+       {   9, 150 },
+       {  10, 146 },
+       {  11, 141 },
+       {  12, 138 },
+       {  13, 134 },
+       {  14, 131 },
+       {  15, 128 },
+       {  16, 125 },
+       {  17, 122 },
+       {  18, 120 },
+       {  19, 118 },
+       {  20, 115 },
+       {  21, 113 },
+       {  22, 111 },
+       {  23, 109 },
+       {  24, 107 },
+       {  25, 106 },
+       {  26, 104 },
+       {  27, 102 },
+       {  28, 101 },
+       {  29,  99 },
+       {  30,  98 },
+       {  31,  96 },
+       {  32,  95 },
+       {  33,  94 },
+       {  34,  92 },
+       {  35,  91 },
+       {  36,  90 },
+       {  37,  89 },
+       {  38,  88 },
+       {  39,  86 },
+       {  40,  85 },
+       {  41,  84 },
+       {  42,  83 },
+       {  43,  82 },
+       {  44,  81 },
+       {  45,  80 },
+       {  46,  79 },
+       {  47,  78 },
+       {  48,  77 },
+       {  49,  76 },
+       {  50,  76 },
+       {  51,  75 },
+       {  52,  74 },
+       {  53,  73 },
+       {  54,  72 },
+       {  56,  71 },
+       {  57,  70 },
+       {  58,  69 },
+       {  60,  68 },
+       {  61,  67 },
+       {  63,  66 },
+       {  64,  65 },
+       {  66,  64 },
+       {  67,  63 },
+       {  68,  62 },
+       {  69,  62 },
+       {  70,  61 },
+       {  72,  60 },
+       {  74,  59 },
+       {  75,  58 },
+       {  77,  57 },
+       {  79,  56 },
+       {  81,  55 },
+       {  83,  54 },
+       {  85,  53 },
+       {  87,  52 },
+       {  89,  51 },
+       {  91,  50 },
+       {  93,  49 },
+       {  95,  48 },
+       {  97,  47 },
+       { 100,  46 },
+       { 102,  45 },
+       { 104,  44 },
+       { 107,  43 },
+       { 109,  42 },
+       { 112,  41 },
+       { 114,  40 },
+       { 117,  39 },
+       { 120,  38 },
+       { 123,  37 },
+       { 125,  36 },
+       { 128,  35 },
+       { 131,  34 },
+       { 134,  33 },
+       { 138,  32 },
+       { 141,  31 },
+       { 144,  30 },
+       { 147,  29 },
+       { 151,  28 },
+       { 154,  27 },
+       { 158,  26 },
+       { 162,  25 },
+       { 165,  24 },
+       { 169,  23 },
+       { 173,  22 },
+       { 177,  21 },
+       { 181,  20 },
+       { 186,  19 },
+       { 190,  18 },
+       { 194,  17 },
+       { 199,  16 },
+       { 204,  15 },
+       { 208,  14 },
+       { 213,  13 },
+       { 218,  12 },
+       { 223,  11 },
+       { 229,  10 },
+       { 234,   9 },
+       { 239,   8 },
+       { 245,   7 },
+       { 251,   6 },
+       { 255,   5 },
+};
+
+static int tda10048_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+       struct tda10048_state *state = fe->demodulator_priv;
+       u8 v;
+       int i, ret = -EINVAL;
+
+       dprintk(1, "%s()\n", __func__);
+
+       v = tda10048_readreg(state, TDA10048_NP_OUT);
+       for (i = 0; i < ARRAY_SIZE(snr_tab); i++) {
+               if (v <= snr_tab[i].val) {
+                       *snr = snr_tab[i].data;
+                       ret = 0;
+                       break;
+               }
+       }
+
+       return ret;
+}
+
+static int tda10048_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+       struct tda10048_state *state = fe->demodulator_priv;
+
+       dprintk(1, "%s()\n", __func__);
+
+       *ucblocks = tda10048_readreg(state, TDA10048_UNCOR_CPT_MSB) << 8 |
+               tda10048_readreg(state, TDA10048_UNCOR_CPT_LSB);
+
+       return 0;
+}
+
+static int tda10048_get_frontend(struct dvb_frontend *fe,
+       struct dvb_frontend_parameters *p)
+{
+       struct tda10048_state *state = fe->demodulator_priv;
+
+       dprintk(1, "%s()\n", __func__);
+
+       p->inversion = tda10048_readreg(state, TDA10048_CONF_C1_1)
+               & 0x20 ? INVERSION_ON : INVERSION_OFF;
+
+       return tda10048_get_tps(state, &p->u.ofdm);
+}
+
+static int tda10048_get_tune_settings(struct dvb_frontend *fe,
+       struct dvb_frontend_tune_settings *tune)
+{
+       tune->min_delay_ms = 1000;
+       return 0;
+}
+
+static void tda10048_release(struct dvb_frontend *fe)
+{
+       struct tda10048_state *state = fe->demodulator_priv;
+       dprintk(1, "%s()\n", __func__);
+       kfree(state);
+}
+
+static struct dvb_frontend_ops tda10048_ops;
+
+struct dvb_frontend *tda10048_attach(const struct tda10048_config *config,
+       struct i2c_adapter *i2c)
+{
+       struct tda10048_state *state = NULL;
+
+       dprintk(1, "%s()\n", __func__);
+
+       /* allocate memory for the internal state */
+       state = kmalloc(sizeof(struct tda10048_state), GFP_KERNEL);
+       if (state == NULL)
+               goto error;
+
+       /* setup the state */
+       state->config = config;
+       state->i2c = i2c;
+       state->fwloaded = 0;
+
+       /* check if the demod is present */
+       if (tda10048_readreg(state, TDA10048_IDENTITY) != 0x048)
+               goto error;
+
+       /* create dvb_frontend */
+       memcpy(&state->frontend.ops, &tda10048_ops,
+               sizeof(struct dvb_frontend_ops));
+       state->frontend.demodulator_priv = state;
+
+       /* Leave the gate closed */
+       tda10048_i2c_gate_ctrl(&state->frontend, 0);
+
+       return &state->frontend;
+
+error:
+       kfree(state);
+       return NULL;
+}
+EXPORT_SYMBOL(tda10048_attach);
+
+static struct dvb_frontend_ops tda10048_ops = {
+
+       .info = {
+               .name                   = "NXP TDA10048HN DVB-T",
+               .type                   = FE_OFDM,
+               .frequency_min          = 177000000,
+               .frequency_max          = 858000000,
+               .frequency_stepsize     = 166666,
+               .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+               FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+               FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+               FE_CAN_HIERARCHY_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
+               FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_RECOVER
+       },
+
+       .release = tda10048_release,
+       .init = tda10048_init,
+       .i2c_gate_ctrl = tda10048_i2c_gate_ctrl,
+       .set_frontend = tda10048_set_frontend,
+       .get_frontend = tda10048_get_frontend,
+       .get_tune_settings = tda10048_get_tune_settings,
+       .read_status = tda10048_read_status,
+       .read_ber = tda10048_read_ber,
+       .read_signal_strength = tda10048_read_signal_strength,
+       .read_snr = tda10048_read_snr,
+       .read_ucblocks = tda10048_read_ucblocks,
+};
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Enable verbose debug messages");
+
+MODULE_DESCRIPTION("NXP TDA10048HN DVB-T Demodulator driver");
+MODULE_AUTHOR("Steven Toth");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/tda10048.h b/drivers/media/dvb/frontends/tda10048.h
new file mode 100644 (file)
index 0000000..2b5c78e
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+    NXP TDA10048HN DVB OFDM demodulator driver
+
+    Copyright (C) 2008 Steven Toth <stoth@hauppauge.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef TDA10048_H
+#define TDA10048_H
+
+#include <linux/dvb/frontend.h>
+#include <linux/firmware.h>
+
+struct tda10048_config {
+
+       /* the demodulator's i2c address */
+       u8 demod_address;
+
+       /* serial/parallel output */
+#define TDA10048_PARALLEL_OUTPUT 0
+#define TDA10048_SERIAL_OUTPUT   1
+       u8 output_mode;
+
+#define TDA10048_BULKWRITE_200 200
+#define TDA10048_BULKWRITE_50  50
+       u8 fwbulkwritelen;
+
+       /* Spectral Inversion */
+#define TDA10048_INVERSION_OFF 0
+#define TDA10048_INVERSION_ON  1
+       u8 inversion;
+};
+
+#if defined(CONFIG_DVB_TDA10048) || \
+       (defined(CONFIG_DVB_TDA10048_MODULE) && defined(MODULE))
+extern struct dvb_frontend *tda10048_attach(
+       const struct tda10048_config *config,
+       struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *tda10048_attach(
+       const struct tda10048_config *config,
+       struct i2c_adapter *i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return NULL;
+}
+#endif /* CONFIG_DVB_TDA10048 */
+
+#endif /* TDA10048_H */
index 8415a8a5247a09381f196ead24b4935d5b680c73..49973846373e843b5fc4d64e6aa97b14922f3a45 100644 (file)
@@ -131,16 +131,16 @@ static int tda1004x_write_byteI(struct tda1004x_state *state, int reg, int data)
        u8 buf[] = { reg, data };
        struct i2c_msg msg = { .flags = 0, .buf = buf, .len = 2 };
 
-       dprintk("%s: reg=0x%x, data=0x%x\n", __FUNCTION__, reg, data);
+       dprintk("%s: reg=0x%x, data=0x%x\n", __func__, reg, data);
 
        msg.addr = state->config->demod_address;
        ret = i2c_transfer(state->i2c, &msg, 1);
 
        if (ret != 1)
                dprintk("%s: error reg=0x%x, data=0x%x, ret=%i\n",
-                       __FUNCTION__, reg, data, ret);
+                       __func__, reg, data, ret);
 
-       dprintk("%s: success reg=0x%x, data=0x%x, ret=%i\n", __FUNCTION__,
+       dprintk("%s: success reg=0x%x, data=0x%x, ret=%i\n", __func__,
                reg, data, ret);
        return (ret != 1) ? -1 : 0;
 }
@@ -153,19 +153,19 @@ static int tda1004x_read_byte(struct tda1004x_state *state, int reg)
        struct i2c_msg msg[] = {{ .flags = 0, .buf = b0, .len = 1 },
                                { .flags = I2C_M_RD, .buf = b1, .len = 1 }};
 
-       dprintk("%s: reg=0x%x\n", __FUNCTION__, reg);
+       dprintk("%s: reg=0x%x\n", __func__, reg);
 
        msg[0].addr = state->config->demod_address;
        msg[1].addr = state->config->demod_address;
        ret = i2c_transfer(state->i2c, msg, 2);
 
        if (ret != 2) {
-               dprintk("%s: error reg=0x%x, ret=%i\n", __FUNCTION__, reg,
+               dprintk("%s: error reg=0x%x, ret=%i\n", __func__, reg,
                        ret);
                return -1;
        }
 
-       dprintk("%s: success reg=0x%x, data=0x%x, ret=%i\n", __FUNCTION__,
+       dprintk("%s: success reg=0x%x, data=0x%x, ret=%i\n", __func__,
                reg, b1[0], ret);
        return b1[0];
 }
@@ -173,7 +173,7 @@ static int tda1004x_read_byte(struct tda1004x_state *state, int reg)
 static int tda1004x_write_mask(struct tda1004x_state *state, int reg, int mask, int data)
 {
        int val;
-       dprintk("%s: reg=0x%x, mask=0x%x, data=0x%x\n", __FUNCTION__, reg,
+       dprintk("%s: reg=0x%x, mask=0x%x, data=0x%x\n", __func__, reg,
                mask, data);
 
        // read a byte and check
@@ -194,7 +194,7 @@ static int tda1004x_write_buf(struct tda1004x_state *state, int reg, unsigned ch
        int i;
        int result;
 
-       dprintk("%s: reg=0x%x, len=0x%x\n", __FUNCTION__, reg, len);
+       dprintk("%s: reg=0x%x, len=0x%x\n", __func__, reg, len);
 
        result = 0;
        for (i = 0; i < len; i++) {
@@ -209,7 +209,7 @@ static int tda1004x_write_buf(struct tda1004x_state *state, int reg, unsigned ch
 static int tda1004x_enable_tuner_i2c(struct tda1004x_state *state)
 {
        int result;
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        result = tda1004x_write_mask(state, TDA1004X_CONFC4, 2, 2);
        msleep(20);
@@ -218,7 +218,7 @@ static int tda1004x_enable_tuner_i2c(struct tda1004x_state *state)
 
 static int tda1004x_disable_tuner_i2c(struct tda1004x_state *state)
 {
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        return tda1004x_write_mask(state, TDA1004X_CONFC4, 2, 0);
 }
@@ -345,7 +345,7 @@ static int tda1004x_do_upload(struct tda1004x_state *state,
                }
                pos += tx_size;
 
-               dprintk("%s: fw_pos=0x%x\n", __FUNCTION__, pos);
+               dprintk("%s: fw_pos=0x%x\n", __func__, pos);
        }
        // give the DSP a chance to settle 03/10/05 Hac
        msleep(100);
@@ -444,10 +444,10 @@ static void tda10046_init_plls(struct dvb_frontend* fe)
                tda1004x_write_byteI(state, TDA10046H_CONFPLL2, 0x03); // PLL M = 3
        }
        if (state->config->xtal_freq == TDA10046_XTAL_4M ) {
-               dprintk("%s: setting up PLLs for a 4 MHz Xtal\n", __FUNCTION__);
+               dprintk("%s: setting up PLLs for a 4 MHz Xtal\n", __func__);
                tda1004x_write_byteI(state, TDA10046H_CONFPLL3, 0); // PLL P = N = 0
        } else {
-               dprintk("%s: setting up PLLs for a 16 MHz Xtal\n", __FUNCTION__);
+               dprintk("%s: setting up PLLs for a 16 MHz Xtal\n", __func__);
                tda1004x_write_byteI(state, TDA10046H_CONFPLL3, 3); // PLL P = 0, N = 3
        }
        if(tda10046_clk53m)
@@ -488,7 +488,7 @@ static int tda10046_fwupload(struct dvb_frontend* fe)
        if (state->config->xtal_freq == TDA10046_XTAL_4M) {
                tda1004x_write_byteI(state, TDA1004X_CONFC4, 0);
        } else {
-               dprintk("%s: 16MHz Xtal, reducing I2C speed\n", __FUNCTION__);
+               dprintk("%s: 16MHz Xtal, reducing I2C speed\n", __func__);
                tda1004x_write_byteI(state, TDA1004X_CONFC4, 0x80);
        }
        tda1004x_write_mask(state, TDA10046H_CONF_TRISTATE1, 1, 0);
@@ -594,7 +594,7 @@ static int tda10045_init(struct dvb_frontend* fe)
 {
        struct tda1004x_state* state = fe->demodulator_priv;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        if (tda10045_fwupload(fe)) {
                printk("tda1004x: firmware upload failed\n");
@@ -624,7 +624,7 @@ static int tda10045_init(struct dvb_frontend* fe)
 static int tda10046_init(struct dvb_frontend* fe)
 {
        struct tda1004x_state* state = fe->demodulator_priv;
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        if (tda10046_fwupload(fe)) {
                printk("tda1004x: firmware upload failed\n");
@@ -686,7 +686,7 @@ static int tda1004x_set_fe(struct dvb_frontend* fe,
        int tmp;
        int inversion;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        if (state->demod_type == TDA1004X_DEMOD_TDA10046) {
                // setup auto offset
@@ -881,7 +881,7 @@ static int tda1004x_get_fe(struct dvb_frontend* fe, struct dvb_frontend_paramete
 {
        struct tda1004x_state* state = fe->demodulator_priv;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        // inversion status
        fe_params->inversion = INVERSION_OFF;
@@ -989,7 +989,7 @@ static int tda1004x_read_status(struct dvb_frontend* fe, fe_status_t * fe_status
        int cber;
        int vber;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        // read status
        status = tda1004x_read_byte(state, TDA1004X_STATUS_CD);
@@ -1048,7 +1048,7 @@ static int tda1004x_read_status(struct dvb_frontend* fe, fe_status_t * fe_status
        }
 
        // success
-       dprintk("%s: fe_status=0x%x\n", __FUNCTION__, *fe_status);
+       dprintk("%s: fe_status=0x%x\n", __func__, *fe_status);
        return 0;
 }
 
@@ -1058,7 +1058,7 @@ static int tda1004x_read_signal_strength(struct dvb_frontend* fe, u16 * signal)
        int tmp;
        int reg = 0;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        // determine the register to use
        switch (state->demod_type) {
@@ -1077,7 +1077,7 @@ static int tda1004x_read_signal_strength(struct dvb_frontend* fe, u16 * signal)
                return -EIO;
 
        *signal = (tmp << 8) | tmp;
-       dprintk("%s: signal=0x%x\n", __FUNCTION__, *signal);
+       dprintk("%s: signal=0x%x\n", __func__, *signal);
        return 0;
 }
 
@@ -1086,7 +1086,7 @@ static int tda1004x_read_snr(struct dvb_frontend* fe, u16 * snr)
        struct tda1004x_state* state = fe->demodulator_priv;
        int tmp;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        // read it
        tmp = tda1004x_read_byte(state, TDA1004X_SNR);
@@ -1095,7 +1095,7 @@ static int tda1004x_read_snr(struct dvb_frontend* fe, u16 * snr)
        tmp = 255 - tmp;
 
        *snr = ((tmp << 8) | tmp);
-       dprintk("%s: snr=0x%x\n", __FUNCTION__, *snr);
+       dprintk("%s: snr=0x%x\n", __func__, *snr);
        return 0;
 }
 
@@ -1106,7 +1106,7 @@ static int tda1004x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
        int tmp2;
        int counter;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        // read the UCBLOCKS and reset
        counter = 0;
@@ -1132,7 +1132,7 @@ static int tda1004x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
        else
                *ucblocks = 0xffffffff;
 
-       dprintk("%s: ucblocks=0x%x\n", __FUNCTION__, *ucblocks);
+       dprintk("%s: ucblocks=0x%x\n", __func__, *ucblocks);
        return 0;
 }
 
@@ -1141,7 +1141,7 @@ static int tda1004x_read_ber(struct dvb_frontend* fe, u32* ber)
        struct tda1004x_state* state = fe->demodulator_priv;
        int tmp;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        // read it in
        tmp = tda1004x_read_byte(state, TDA1004X_CBER_LSB);
@@ -1155,7 +1155,7 @@ static int tda1004x_read_ber(struct dvb_frontend* fe, u32* ber)
        // The address 0x20 should be read to cope with a TDA10046 bug
        tda1004x_read_byte(state, TDA1004X_CBER_RESET);
 
-       dprintk("%s: ber=0x%x\n", __FUNCTION__, *ber);
+       dprintk("%s: ber=0x%x\n", __func__, *ber);
        return 0;
 }
 
index abae84350142a023bfec7be21f257995b3d1ebfe..4e27ffb0f14e80d189056e66b8e6822e593d31a3 100644 (file)
@@ -94,7 +94,6 @@ struct tda1004x_config
 
        /* slave address and configuration of the tuner */
        u8 tuner_address;
-       u8 tuner_config;
        u8 antenna_switch;
 
        /* if the board uses another I2c Bridge (tda8290), its address */
@@ -128,13 +127,13 @@ extern struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config
 static inline struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config,
                                            struct i2c_adapter* i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 static inline struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config,
                                            struct i2c_adapter* i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_TDA1004X
index 0d2b69a99ad454385a2520a0debd7d5e11e0f9d5..a17ce3c4ad860c8959609e22c56679e5a004fda1 100644 (file)
@@ -43,7 +43,7 @@ struct tda10086_state {
        bool has_lock;
 };
 
-static int debug = 0;
+static int debug;
 #define dprintk(args...) \
        do { \
                if (debug) printk(KERN_DEBUG "tda10086: " args); \
@@ -60,7 +60,7 @@ static int tda10086_write_byte(struct tda10086_state *state, int reg, int data)
 
        if (ret != 1)
                dprintk("%s: error reg=0x%x, data=0x%x, ret=%i\n",
-                       __FUNCTION__, reg, data, ret);
+                       __func__, reg, data, ret);
 
        return (ret != 1) ? ret : 0;
 }
@@ -78,7 +78,7 @@ static int tda10086_read_byte(struct tda10086_state *state, int reg)
        ret = i2c_transfer(state->i2c, msg, 2);
 
        if (ret != 2) {
-               dprintk("%s: error reg=0x%x, ret=%i\n", __FUNCTION__, reg,
+               dprintk("%s: error reg=0x%x, ret=%i\n", __func__, reg,
                        ret);
                return ret;
        }
@@ -90,16 +90,16 @@ static int tda10086_write_mask(struct tda10086_state *state, int reg, int mask,
 {
        int val;
 
-       // read a byte and check
+       /* read a byte and check */
        val = tda10086_read_byte(state, reg);
        if (val < 0)
                return val;
 
-       // mask if off
+       /* mask if off */
        val = val & ~mask;
        val |= data & 0xff;
 
-       // write it out again
+       /* write it out again */
        return tda10086_write_byte(state, reg, val);
 }
 
@@ -108,62 +108,67 @@ static int tda10086_init(struct dvb_frontend* fe)
        struct tda10086_state* state = fe->demodulator_priv;
        u8 t22k_off = 0x80;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        if (state->config->diseqc_tone)
                t22k_off = 0;
-       // reset
+       /* reset */
        tda10086_write_byte(state, 0x00, 0x00);
        msleep(10);
 
-       // misc setup
+       /* misc setup */
        tda10086_write_byte(state, 0x01, 0x94);
-       tda10086_write_byte(state, 0x02, 0x35); // NOTE: TT drivers appear to disable CSWP
+       tda10086_write_byte(state, 0x02, 0x35); /* NOTE: TT drivers appear to disable CSWP */
        tda10086_write_byte(state, 0x03, 0xe4);
        tda10086_write_byte(state, 0x04, 0x43);
        tda10086_write_byte(state, 0x0c, 0x0c);
-       tda10086_write_byte(state, 0x1b, 0xb0); // noise threshold
-       tda10086_write_byte(state, 0x20, 0x89); // misc
-       tda10086_write_byte(state, 0x30, 0x04); // acquisition period length
-       tda10086_write_byte(state, 0x32, 0x00); // irq off
-       tda10086_write_byte(state, 0x31, 0x56); // setup AFC
-
-       // setup PLL (assumes 16Mhz XIN)
-       tda10086_write_byte(state, 0x55, 0x2c); // misc PLL setup
-       tda10086_write_byte(state, 0x3a, 0x0b); // M=12
-       tda10086_write_byte(state, 0x3b, 0x01); // P=2
-       tda10086_write_mask(state, 0x55, 0x20, 0x00); // powerup PLL
-
-       // setup TS interface
+       tda10086_write_byte(state, 0x1b, 0xb0); /* noise threshold */
+       tda10086_write_byte(state, 0x20, 0x89); /* misc */
+       tda10086_write_byte(state, 0x30, 0x04); /* acquisition period length */
+       tda10086_write_byte(state, 0x32, 0x00); /* irq off */
+       tda10086_write_byte(state, 0x31, 0x56); /* setup AFC */
+
+       /* setup PLL (this assumes SACLK = 96MHz) */
+       tda10086_write_byte(state, 0x55, 0x2c); /* misc PLL setup */
+       if (state->config->xtal_freq == TDA10086_XTAL_16M) {
+               tda10086_write_byte(state, 0x3a, 0x0b); /* M=12 */
+               tda10086_write_byte(state, 0x3b, 0x01); /* P=2 */
+       } else {
+               tda10086_write_byte(state, 0x3a, 0x17); /* M=24 */
+               tda10086_write_byte(state, 0x3b, 0x00); /* P=1 */
+       }
+       tda10086_write_mask(state, 0x55, 0x20, 0x00); /* powerup PLL */
+
+       /* setup TS interface */
        tda10086_write_byte(state, 0x11, 0x81);
        tda10086_write_byte(state, 0x12, 0x81);
-       tda10086_write_byte(state, 0x19, 0x40); // parallel mode A + MSBFIRST
-       tda10086_write_byte(state, 0x56, 0x80); // powerdown WPLL - unused in the mode we use
-       tda10086_write_byte(state, 0x57, 0x08); // bypass WPLL - unused in the mode we use
+       tda10086_write_byte(state, 0x19, 0x40); /* parallel mode A + MSBFIRST */
+       tda10086_write_byte(state, 0x56, 0x80); /* powerdown WPLL - unused in the mode we use */
+       tda10086_write_byte(state, 0x57, 0x08); /* bypass WPLL - unused in the mode we use */
        tda10086_write_byte(state, 0x10, 0x2a);
 
-       // setup ADC
-       tda10086_write_byte(state, 0x58, 0x61); // ADC setup
-       tda10086_write_mask(state, 0x58, 0x01, 0x00); // powerup ADC
+       /* setup ADC */
+       tda10086_write_byte(state, 0x58, 0x61); /* ADC setup */
+       tda10086_write_mask(state, 0x58, 0x01, 0x00); /* powerup ADC */
 
-       // setup AGC
+       /* setup AGC */
        tda10086_write_byte(state, 0x05, 0x0B);
        tda10086_write_byte(state, 0x37, 0x63);
-       tda10086_write_byte(state, 0x3f, 0x0a); // NOTE: flydvb varies it
+       tda10086_write_byte(state, 0x3f, 0x0a); /* NOTE: flydvb varies it */
        tda10086_write_byte(state, 0x40, 0x64);
        tda10086_write_byte(state, 0x41, 0x4f);
        tda10086_write_byte(state, 0x42, 0x43);
 
-       // setup viterbi
-       tda10086_write_byte(state, 0x1a, 0x11); // VBER 10^6, DVB, QPSK
+       /* setup viterbi */
+       tda10086_write_byte(state, 0x1a, 0x11); /* VBER 10^6, DVB, QPSK */
 
-       // setup carrier recovery
+       /* setup carrier recovery */
        tda10086_write_byte(state, 0x3d, 0x80);
 
-       // setup SEC
-       tda10086_write_byte(state, 0x36, t22k_off); // all SEC off, 22k tone
-       tda10086_write_byte(state, 0x34, (((1<<19) * (22000/1000)) / (SACLK/1000)));      // } tone frequency
-       tda10086_write_byte(state, 0x35, (((1<<19) * (22000/1000)) / (SACLK/1000)) >> 8); // }
+       /* setup SEC */
+       tda10086_write_byte(state, 0x36, t22k_off); /* all SEC off, 22k tone */
+       tda10086_write_byte(state, 0x34, (((1<<19) * (22000/1000)) / (SACLK/1000)));
+       tda10086_write_byte(state, 0x35, (((1<<19) * (22000/1000)) / (SACLK/1000)) >> 8);
 
        return 0;
 }
@@ -173,7 +178,7 @@ static void tda10086_diseqc_wait(struct tda10086_state *state)
        unsigned long timeout = jiffies + msecs_to_jiffies(200);
        while (!(tda10086_read_byte(state, 0x50) & 0x01)) {
                if(time_after(jiffies, timeout)) {
-                       printk("%s: diseqc queue not ready, command may be lost.\n", __FUNCTION__);
+                       printk("%s: diseqc queue not ready, command may be lost.\n", __func__);
                        break;
                }
                msleep(10);
@@ -185,7 +190,7 @@ static int tda10086_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
        struct tda10086_state* state = fe->demodulator_priv;
        u8 t22k_off = 0x80;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        if (state->config->diseqc_tone)
                t22k_off = 0;
@@ -211,7 +216,7 @@ static int tda10086_send_master_cmd (struct dvb_frontend* fe,
        u8 oldval;
        u8 t22k_off = 0x80;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        if (state->config->diseqc_tone)
                t22k_off = 0;
@@ -239,7 +244,7 @@ static int tda10086_send_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t minic
        u8 oldval = tda10086_read_byte(state, 0x36);
        u8 t22k_off = 0x80;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        if (state->config->diseqc_tone)
                t22k_off = 0;
@@ -266,7 +271,7 @@ static int tda10086_set_inversion(struct tda10086_state *state,
 {
        u8 invval = 0x80;
 
-       dprintk ("%s %i %i\n", __FUNCTION__, fe_params->inversion, state->config->invert);
+       dprintk ("%s %i %i\n", __func__, fe_params->inversion, state->config->invert);
 
        switch(fe_params->inversion) {
        case INVERSION_OFF:
@@ -300,9 +305,9 @@ static int tda10086_set_symbol_rate(struct tda10086_state *state,
        u32 bdri;
        u32 symbol_rate = fe_params->u.qpsk.symbol_rate;
 
-       dprintk ("%s %i\n", __FUNCTION__, symbol_rate);
+       dprintk ("%s %i\n", __func__, symbol_rate);
 
-       // setup the decimation and anti-aliasing filters..
+       /* setup the decimation and anti-aliasing filters.. */
        if (symbol_rate < (u32) (SACLK * 0.0137)) {
                dfn=4;
                afs=1;
@@ -339,13 +344,13 @@ static int tda10086_set_symbol_rate(struct tda10086_state *state,
                byp=1;
        }
 
-       // calculate BDR
+       /* calculate BDR */
        big = (1ULL<<21) * ((u64) symbol_rate/1000ULL) * (1ULL<<dfn);
        big += ((SACLK/1000ULL)-1ULL);
        do_div(big, (SACLK/1000ULL));
        bdr = big & 0xfffff;
 
-       // calculate BDRI
+       /* calculate BDRI */
        tmp = (1<<dfn)*(symbol_rate/1000);
        bdri = ((32 * (SACLK/1000)) + (tmp-1)) / tmp;
 
@@ -366,7 +371,7 @@ static int tda10086_set_fec(struct tda10086_state *state,
 {
        u8 fecval;
 
-       dprintk ("%s %i\n", __FUNCTION__, fe_params->u.qpsk.fec_inner);
+       dprintk ("%s %i\n", __func__, fe_params->u.qpsk.fec_inner);
 
        switch(fe_params->u.qpsk.fec_inner) {
        case FEC_1_2:
@@ -412,13 +417,13 @@ static int tda10086_set_frontend(struct dvb_frontend* fe,
        u32 freq = 0;
        int freqoff;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
-       // modify parameters for tuning
+       /* modify parameters for tuning */
        tda10086_write_byte(state, 0x02, 0x35);
        state->has_lock = false;
 
-       // set params
+       /* set params */
        if (fe->ops.tuner_ops.set_params) {
                fe->ops.tuner_ops.set_params(fe, fe_params);
                if (fe->ops.i2c_gate_ctrl)
@@ -430,7 +435,7 @@ static int tda10086_set_frontend(struct dvb_frontend* fe,
                        fe->ops.i2c_gate_ctrl(fe, 0);
        }
 
-       // calcluate the frequency offset (in *Hz* not kHz)
+       /* calcluate the frequency offset (in *Hz* not kHz) */
        freqoff = fe_params->frequency - freq;
        freqoff = ((1<<16) * freqoff) / (SACLK/1000);
        tda10086_write_byte(state, 0x3d, 0x80 | ((freqoff >> 8) & 0x7f));
@@ -443,7 +448,7 @@ static int tda10086_set_frontend(struct dvb_frontend* fe,
        if ((ret = tda10086_set_fec(state, fe_params)) < 0)
                return ret;
 
-       // soft reset + disable TS output until lock
+       /* soft reset + disable TS output until lock */
        tda10086_write_mask(state, 0x10, 0x40, 0x40);
        tda10086_write_mask(state, 0x00, 0x01, 0x00);
 
@@ -459,13 +464,13 @@ static int tda10086_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_pa
        int tmp;
        u64 tmp64;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
-       // check for invalid symbol rate
+       /* check for invalid symbol rate */
        if (fe_params->u.qpsk.symbol_rate < 500000)
                return -EINVAL;
 
-       // calculate the updated frequency (note: we convert from Hz->kHz)
+       /* calculate the updated frequency (note: we convert from Hz->kHz) */
        tmp64 = tda10086_read_byte(state, 0x52);
        tmp64 |= (tda10086_read_byte(state, 0x51) << 8);
        if (tmp64 & 0x8000)
@@ -474,7 +479,7 @@ static int tda10086_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_pa
        do_div(tmp64, (1ULL<<15) * (1ULL<<1));
        fe_params->frequency = (int) state->frequency + (int) tmp64;
 
-       // the inversion
+       /* the inversion */
        val = tda10086_read_byte(state, 0x0c);
        if (val & 0x80) {
                switch(val & 0x40) {
@@ -505,7 +510,7 @@ static int tda10086_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_pa
                }
        }
 
-       // calculate the updated symbol rate
+       /* calculate the updated symbol rate */
        tmp = tda10086_read_byte(state, 0x1d);
        if (tmp & 0x80)
                tmp |= 0xffffff00;
@@ -513,7 +518,7 @@ static int tda10086_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_pa
        tmp = ((state->symbol_rate/1000) * tmp) / (1000000/1000);
        fe_params->u.qpsk.symbol_rate = state->symbol_rate + tmp;
 
-       // the FEC
+       /* the FEC */
        val = (tda10086_read_byte(state, 0x0d) & 0x70) >> 4;
        switch(val) {
        case 0x00:
@@ -550,7 +555,7 @@ static int tda10086_read_status(struct dvb_frontend* fe, fe_status_t *fe_status)
        struct tda10086_state* state = fe->demodulator_priv;
        u8 val;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        val = tda10086_read_byte(state, 0x0e);
        *fe_status = 0;
@@ -566,7 +571,7 @@ static int tda10086_read_status(struct dvb_frontend* fe, fe_status_t *fe_status)
                *fe_status |= FE_HAS_LOCK;
                if (!state->has_lock) {
                        state->has_lock = true;
-                       // modify parameters for stable reception
+                       /* modify parameters for stable reception */
                        tda10086_write_byte(state, 0x02, 0x00);
                }
        }
@@ -579,7 +584,7 @@ static int tda10086_read_signal_strength(struct dvb_frontend* fe, u16 * signal)
        struct tda10086_state* state = fe->demodulator_priv;
        u8 _str;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        _str = 0xff - tda10086_read_byte(state, 0x43);
        *signal = (_str << 8) | _str;
@@ -592,7 +597,7 @@ static int tda10086_read_snr(struct dvb_frontend* fe, u16 * snr)
        struct tda10086_state* state = fe->demodulator_priv;
        u8 _snr;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        _snr = 0xff - tda10086_read_byte(state, 0x1c);
        *snr = (_snr << 8) | _snr;
@@ -604,12 +609,12 @@ static int tda10086_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
 {
        struct tda10086_state* state = fe->demodulator_priv;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
-       // read it
+       /* read it */
        *ucblocks = tda10086_read_byte(state, 0x18) & 0x7f;
 
-       // reset counter
+       /* reset counter */
        tda10086_write_byte(state, 0x18, 0x00);
        tda10086_write_byte(state, 0x18, 0x80);
 
@@ -620,9 +625,9 @@ static int tda10086_read_ber(struct dvb_frontend* fe, u32* ber)
 {
        struct tda10086_state* state = fe->demodulator_priv;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
-       // read it
+       /* read it */
        *ber = 0;
        *ber |= tda10086_read_byte(state, 0x15);
        *ber |= tda10086_read_byte(state, 0x16) << 8;
@@ -635,7 +640,7 @@ static int tda10086_sleep(struct dvb_frontend* fe)
 {
        struct tda10086_state* state = fe->demodulator_priv;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        tda10086_write_mask(state, 0x00, 0x08, 0x08);
 
@@ -646,7 +651,7 @@ static int tda10086_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
 {
        struct tda10086_state* state = fe->demodulator_priv;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        if (enable) {
                tda10086_write_mask(state, 0x00, 0x10, 0x10);
@@ -737,7 +742,7 @@ struct dvb_frontend* tda10086_attach(const struct tda10086_config* config,
 {
        struct tda10086_state *state;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        /* allocate memory for the internal state */
        state = kmalloc(sizeof(struct tda10086_state), GFP_KERNEL);
index eeceaeee78ffb8407171ee62cb2880f8cce5068d..61148c558d8d8eb1a8ec236e0a58b63e5063f6cb 100644 (file)
 #include <linux/dvb/frontend.h>
 #include <linux/firmware.h>
 
+enum tda10086_xtal {
+       TDA10086_XTAL_16M,
+       TDA10086_XTAL_4M
+};
+
 struct tda10086_config
 {
        /* the demodulator's i2c address */
@@ -36,6 +41,9 @@ struct tda10086_config
 
        /* do we need the diseqc signal with carrier? */
        u8 diseqc_tone;
+
+       /* frequency of the reference xtal */
+       enum tda10086_xtal xtal_freq;
 };
 
 #if defined(CONFIG_DVB_TDA10086) || (defined(CONFIG_DVB_TDA10086_MODULE) && defined(MODULE))
@@ -45,9 +53,9 @@ extern struct dvb_frontend* tda10086_attach(const struct tda10086_config* config
 static inline struct dvb_frontend* tda10086_attach(const struct tda10086_config* config,
                                                   struct i2c_adapter* i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
-#endif // CONFIG_DVB_TDA10086
+#endif /* CONFIG_DVB_TDA10086 */
 
-#endif // TDA10086_H
+#endif /* TDA10086_H */
index bca57099061366badc9cc4fec3dc8dde982ca02f..e27a7620a32f20b2f68990bc968714b270e168eb 100644 (file)
@@ -125,16 +125,16 @@ int tda18271_read_regs(struct dvb_frontend *fe)
        unsigned char buf = 0x00;
        int ret;
        struct i2c_msg msg[] = {
-               { .addr = priv->i2c_addr, .flags = 0,
+               { .addr = priv->i2c_props.addr, .flags = 0,
                  .buf = &buf, .len = 1 },
-               { .addr = priv->i2c_addr, .flags = I2C_M_RD,
+               { .addr = priv->i2c_props.addr, .flags = I2C_M_RD,
                  .buf = regs, .len = 16 }
        };
 
        tda18271_i2c_gate_ctrl(fe, 1);
 
        /* read all registers */
-       ret = i2c_transfer(priv->i2c_adap, msg, 2);
+       ret = i2c_transfer(priv->i2c_props.adap, msg, 2);
 
        tda18271_i2c_gate_ctrl(fe, 0);
 
@@ -155,16 +155,16 @@ int tda18271_read_extended(struct dvb_frontend *fe)
        unsigned char buf = 0x00;
        int ret, i;
        struct i2c_msg msg[] = {
-               { .addr = priv->i2c_addr, .flags = 0,
+               { .addr = priv->i2c_props.addr, .flags = 0,
                  .buf = &buf, .len = 1 },
-               { .addr = priv->i2c_addr, .flags = I2C_M_RD,
+               { .addr = priv->i2c_props.addr, .flags = I2C_M_RD,
                  .buf = regdump, .len = TDA18271_NUM_REGS }
        };
 
        tda18271_i2c_gate_ctrl(fe, 1);
 
        /* read all registers */
-       ret = i2c_transfer(priv->i2c_adap, msg, 2);
+       ret = i2c_transfer(priv->i2c_props.adap, msg, 2);
 
        tda18271_i2c_gate_ctrl(fe, 0);
 
@@ -192,7 +192,7 @@ int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len)
        struct tda18271_priv *priv = fe->tuner_priv;
        unsigned char *regs = priv->tda18271_regs;
        unsigned char buf[TDA18271_NUM_REGS + 1];
-       struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
+       struct i2c_msg msg = { .addr = priv->i2c_props.addr, .flags = 0,
                               .buf = buf, .len = len + 1 };
        int i, ret;
 
@@ -205,7 +205,7 @@ int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len)
        tda18271_i2c_gate_ctrl(fe, 1);
 
        /* write registers */
-       ret = i2c_transfer(priv->i2c_adap, &msg, 1);
+       ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);
 
        tda18271_i2c_gate_ctrl(fe, 0);
 
@@ -217,13 +217,29 @@ int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len)
 
 /*---------------------------------------------------------------------*/
 
+int tda18271_charge_pump_source(struct dvb_frontend *fe,
+                               enum tda18271_pll pll, int force)
+{
+       struct tda18271_priv *priv = fe->tuner_priv;
+       unsigned char *regs = priv->tda18271_regs;
+
+       int r_cp = (pll == TDA18271_CAL_PLL) ? R_EB7 : R_EB4;
+
+       regs[r_cp] &= ~0x20;
+       regs[r_cp] |= ((force & 1) << 5);
+       tda18271_write_regs(fe, r_cp, 1);
+
+       return 0;
+}
+
 int tda18271_init_regs(struct dvb_frontend *fe)
 {
        struct tda18271_priv *priv = fe->tuner_priv;
        unsigned char *regs = priv->tda18271_regs;
 
        tda_dbg("initializing registers for device @ %d-%04x\n",
-               i2c_adapter_id(priv->i2c_adap), priv->i2c_addr);
+               i2c_adapter_id(priv->i2c_props.adap),
+               priv->i2c_props.addr);
 
        /* initialize registers */
        switch (priv->id) {
@@ -310,7 +326,12 @@ int tda18271_init_regs(struct dvb_frontend *fe)
        regs[R_EB22] = 0x48;
        regs[R_EB23] = 0xb0;
 
-       tda18271_write_regs(fe, 0x00, TDA18271_NUM_REGS);
+       if (priv->small_i2c) {
+               tda18271_write_regs(fe, 0x00, 0x10);
+               tda18271_write_regs(fe, 0x10, 0x10);
+               tda18271_write_regs(fe, 0x20, 0x07);
+       } else
+               tda18271_write_regs(fe, 0x00, TDA18271_NUM_REGS);
 
        /* setup agc1 gain */
        regs[R_EB17] = 0x00;
@@ -349,24 +370,15 @@ int tda18271_init_regs(struct dvb_frontend *fe)
        regs[R_MD2] = 0x08;
        regs[R_MD3] = 0x00;
 
-       switch (priv->id) {
-       case TDA18271HDC1:
-               tda18271_write_regs(fe, R_EP3, 11);
-               break;
-       case TDA18271HDC2:
-               tda18271_write_regs(fe, R_EP3, 12);
-               break;
-       };
+       tda18271_write_regs(fe, R_EP3, 11);
 
        if ((priv->id) == TDA18271HDC2) {
                /* main pll cp source on */
-               regs[R_EB4] = 0x61;
-               tda18271_write_regs(fe, R_EB4, 1);
+               tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 1);
                msleep(1);
 
                /* main pll cp source off */
-               regs[R_EB4] = 0x41;
-               tda18271_write_regs(fe, R_EB4, 1);
+               tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 0);
        }
 
        msleep(5); /* pll locking */
@@ -398,6 +410,7 @@ int tda18271_init_regs(struct dvb_frontend *fe)
        tda18271_write_regs(fe, R_EP3, 11);
        msleep(5); /* pll locking */
 
+       /* launch detector */
        tda18271_write_regs(fe, R_EP1, 1);
        msleep(5); /* wanted mid measurement */
 
index dfe72aaec3802188f3f385d3171d80617c7d903e..b262100ae897db7b8806f89658c2bf9cad658e45 100644 (file)
@@ -31,30 +31,23 @@ static int tda18271_cal_on_startup;
 module_param_named(cal, tda18271_cal_on_startup, int, 0644);
 MODULE_PARM_DESC(cal, "perform RF tracking filter calibration on startup");
 
-static LIST_HEAD(tda18271_list);
 static DEFINE_MUTEX(tda18271_list_mutex);
+static LIST_HEAD(hybrid_tuner_instance_list);
 
 /*---------------------------------------------------------------------*/
 
-static int tda18271_ir_cal_init(struct dvb_frontend *fe)
+static inline int charge_pump_source(struct dvb_frontend *fe, int force)
 {
        struct tda18271_priv *priv = fe->tuner_priv;
-       unsigned char *regs = priv->tda18271_regs;
-
-       tda18271_read_regs(fe);
-
-       /* test IR_CAL_OK to see if we need init */
-       if ((regs[R_EP1] & 0x08) == 0)
-               tda18271_init_regs(fe);
-
-       return 0;
+       return tda18271_charge_pump_source(fe,
+                                          (priv->role == TDA18271_SLAVE) ?
+                                          TDA18271_CAL_PLL :
+                                          TDA18271_MAIN_PLL, force);
 }
 
-/* ------------------------------------------------------------------ */
-
 static int tda18271_channel_configuration(struct dvb_frontend *fe,
-                                         u32 ifc, u32 freq, u32 bw, u8 std,
-                                         int radio)
+                                         struct tda18271_std_map_item *map,
+                                         u32 freq, u32 bw)
 {
        struct tda18271_priv *priv = fe->tuner_priv;
        unsigned char *regs = priv->tda18271_regs;
@@ -64,38 +57,34 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe,
 
        /* set standard */
        regs[R_EP3]  &= ~0x1f; /* clear std bits */
-       regs[R_EP3]  |= std;
+       regs[R_EP3]  |= (map->agc_mode << 3) | map->std;
+
+       /* set rfagc to high speed mode */
+       regs[R_EP3] &= ~0x04;
 
        /* set cal mode to normal */
        regs[R_EP4]  &= ~0x03;
 
        /* update IF output level & IF notch frequency */
        regs[R_EP4]  &= ~0x1c; /* clear if level bits */
+       regs[R_EP4]  |= (map->if_lvl << 2);
 
        switch (priv->mode) {
        case TDA18271_ANALOG:
                regs[R_MPD]  &= ~0x80; /* IF notch = 0 */
                break;
        case TDA18271_DIGITAL:
-               regs[R_EP4]  |= 0x04; /* IF level = 1 */
                regs[R_MPD]  |= 0x80; /* IF notch = 1 */
                break;
        }
 
-       if (radio)
-               regs[R_EP4]  |=  0x80;
-       else
-               regs[R_EP4]  &= ~0x80;
+       /* update FM_RFn */
+       regs[R_EP4]  &= ~0x80;
+       regs[R_EP4]  |= map->fm_rfn << 7;
 
-       /* update RF_TOP / IF_TOP */
-       switch (priv->mode) {
-       case TDA18271_ANALOG:
-               regs[R_EB22]  = 0x2c;
-               break;
-       case TDA18271_DIGITAL:
-               regs[R_EB22]  = 0x37;
-               break;
-       }
+       /* update rf top / if top */
+       regs[R_EB22]  = 0x00;
+       regs[R_EB22] |= map->rfagc_top;
        tda18271_write_regs(fe, R_EB22, 1);
 
        /* --------------------------------------------------------------- */
@@ -117,8 +106,14 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe,
 
        /* dual tuner and agc1 extra configuration */
 
-       /* main vco when Master, cal vco when slave */
-       regs[R_EB1]  |= 0x04; /* FIXME: assumes master */
+       switch (priv->role) {
+       case TDA18271_MASTER:
+               regs[R_EB1]  |= 0x04; /* main vco */
+               break;
+       case TDA18271_SLAVE:
+               regs[R_EB1]  &= ~0x04; /* cal vco */
+               break;
+       }
 
        /* agc1 always active */
        regs[R_EB1]  &= ~0x02;
@@ -130,25 +125,40 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe,
 
        /* --------------------------------------------------------------- */
 
-       N = freq + ifc;
+       N = map->if_freq * 1000 + freq;
 
-       /* FIXME: assumes master */
-       tda18271_calc_main_pll(fe, N);
-       tda18271_write_regs(fe, R_MPD, 4);
+       switch (priv->role) {
+       case TDA18271_MASTER:
+               tda18271_calc_main_pll(fe, N);
+               tda18271_write_regs(fe, R_MPD, 4);
+               break;
+       case TDA18271_SLAVE:
+               tda18271_calc_cal_pll(fe, N);
+               tda18271_write_regs(fe, R_CPD, 4);
+
+               regs[R_MPD] = regs[R_CPD] & 0x7f;
+               tda18271_write_regs(fe, R_MPD, 1);
+               break;
+       }
 
        tda18271_write_regs(fe, R_TM, 7);
 
-       /* main pll charge pump source */
-       regs[R_EB4] |= 0x20;
-       tda18271_write_regs(fe, R_EB4, 1);
+       /* force charge pump source */
+       charge_pump_source(fe, 1);
 
        msleep(1);
 
-       /* normal operation for the main pll */
-       regs[R_EB4] &= ~0x20;
-       tda18271_write_regs(fe, R_EB4, 1);
+       /* return pll to normal operation */
+       charge_pump_source(fe, 0);
 
-       msleep(5);
+       msleep(20);
+
+       /* set rfagc to normal speed mode */
+       if (map->fm_rfn)
+               regs[R_EP3] &= ~0x04;
+       else
+               regs[R_EP3] |= 0x04;
+       tda18271_write_regs(fe, R_EP3, 1);
 
        return 0;
 }
@@ -195,8 +205,10 @@ static int tda18271_read_thermometer(struct dvb_frontend *fe)
        return tm;
 }
 
-static int tda18271_rf_tracking_filters_correction(struct dvb_frontend *fe,
-                                                  u32 freq)
+/* ------------------------------------------------------------------ */
+
+static int tda18271c2_rf_tracking_filters_correction(struct dvb_frontend *fe,
+                                                    u32 freq)
 {
        struct tda18271_priv *priv = fe->tuner_priv;
        struct tda18271_rf_tracking_filter_cal *map = priv->rf_cal_state;
@@ -296,12 +308,10 @@ static int tda18271_calibrate_rf(struct dvb_frontend *fe, u32 freq)
        tda18271_write_regs(fe, R_EB13, 1);
 
        /* main pll charge pump source */
-       regs[R_EB4]  |= 0x20;
-       tda18271_write_regs(fe, R_EB4, 1);
+       tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 1);
 
        /* cal pll charge pump source */
-       regs[R_EB7]  |= 0x20;
-       tda18271_write_regs(fe, R_EB7, 1);
+       tda18271_charge_pump_source(fe, TDA18271_CAL_PLL, 1);
 
        /* force dcdc converter to 0 V */
        regs[R_EB14] = 0x00;
@@ -320,8 +330,8 @@ static int tda18271_calibrate_rf(struct dvb_frontend *fe, u32 freq)
        /* set the internal calibration signal */
        N = freq;
 
-       tda18271_calc_main_pll(fe, N);
-       tda18271_write_regs(fe, R_MPD, 4);
+       tda18271_calc_cal_pll(fe, N);
+       tda18271_write_regs(fe, R_CPD, 4);
 
        /* downconvert internal calibration */
        N += 1000000;
@@ -339,14 +349,12 @@ static int tda18271_calibrate_rf(struct dvb_frontend *fe, u32 freq)
        /* --------------------------------------------------------------- */
 
        /* normal operation for the main pll */
-       regs[R_EB4] &= ~0x20;
-       tda18271_write_regs(fe, R_EB4, 1);
+       tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 0);
 
        /* normal operation for the cal pll  */
-       regs[R_EB7] &= ~0x20;
-       tda18271_write_regs(fe, R_EB7, 1);
+       tda18271_charge_pump_source(fe, TDA18271_CAL_PLL, 0);
 
-       msleep(5); /* plls locking */
+       msleep(10); /* plls locking */
 
        /* launch the rf tracking filters calibration */
        regs[R_EB20]  |= 0x20;
@@ -443,7 +451,7 @@ static int tda18271_powerscan(struct dvb_frontend *fe,
 
                count += 200;
 
-               if (count < count_limit)
+               if (count <= count_limit)
                        continue;
 
                if (sgn <= 0)
@@ -587,7 +595,7 @@ static int tda18271_calc_rf_filter_curve(struct dvb_frontend *fe)
 
 /* ------------------------------------------------------------------ */
 
-static int tda18271_rf_cal_init(struct dvb_frontend *fe)
+static int tda18271c2_rf_cal_init(struct dvb_frontend *fe)
 {
        struct tda18271_priv *priv = fe->tuner_priv;
        unsigned char *regs = priv->tda18271_regs;
@@ -610,63 +618,13 @@ static int tda18271_rf_cal_init(struct dvb_frontend *fe)
        return 0;
 }
 
-static int tda18271_init(struct dvb_frontend *fe)
-{
-       struct tda18271_priv *priv = fe->tuner_priv;
-
-       mutex_lock(&priv->lock);
-
-       /* power up */
-       tda18271_set_standby_mode(fe, 0, 0, 0);
-
-       /* initialization */
-       tda18271_ir_cal_init(fe);
-
-       if (priv->id == TDA18271HDC2)
-               tda18271_rf_cal_init(fe);
-
-       mutex_unlock(&priv->lock);
-
-       return 0;
-}
-
-static int tda18271c2_tune(struct dvb_frontend *fe,
-                          u32 ifc, u32 freq, u32 bw, u8 std, int radio)
-{
-       struct tda18271_priv *priv = fe->tuner_priv;
-
-       tda_dbg("freq = %d, ifc = %d\n", freq, ifc);
-
-       tda18271_init(fe);
-
-       mutex_lock(&priv->lock);
-
-       tda18271_rf_tracking_filters_correction(fe, freq);
-
-       tda18271_channel_configuration(fe, ifc, freq, bw, std, radio);
-
-       mutex_unlock(&priv->lock);
-
-       return 0;
-}
-
-/* ------------------------------------------------------------------ */
-
-static int tda18271c1_tune(struct dvb_frontend *fe,
-                          u32 ifc, u32 freq, u32 bw, u8 std, int radio)
+static int tda18271c1_rf_tracking_filter_calibration(struct dvb_frontend *fe,
+                                                    u32 freq, u32 bw)
 {
        struct tda18271_priv *priv = fe->tuner_priv;
        unsigned char *regs = priv->tda18271_regs;
        u32 N = 0;
 
-       tda18271_init(fe);
-
-       mutex_lock(&priv->lock);
-
-       tda_dbg("freq = %d, ifc = %d\n", freq, ifc);
-
-       /* RF tracking filter calibration */
-
        /* calculate bp filter */
        tda18271_calc_bp_filter(fe, &freq);
        tda18271_write_regs(fe, R_EP1, 1);
@@ -737,7 +695,7 @@ static int tda18271c1_tune(struct dvb_frontend *fe,
 
        regs[R_EB7]   = 0x40;
        tda18271_write_regs(fe, R_EB7, 1);
-       msleep(10);
+       msleep(10); /* pll locking */
 
        regs[R_EB20]  = 0xec;
        tda18271_write_regs(fe, R_EB20, 1);
@@ -752,74 +710,70 @@ static int tda18271c1_tune(struct dvb_frontend *fe,
        if (0 == tda18271_calc_rf_cal(fe, &freq))
                tda18271_write_regs(fe, R_EB14, 1);
 
-       /* Channel Configuration */
+       return 0;
+}
 
-       switch (priv->mode) {
-       case TDA18271_ANALOG:
-               regs[R_EB22]  = 0x2c;
-               break;
-       case TDA18271_DIGITAL:
-               regs[R_EB22]  = 0x37;
-               break;
-       }
-       tda18271_write_regs(fe, R_EB22, 1);
+/* ------------------------------------------------------------------ */
 
-       regs[R_EP1]  |= 0x40; /* set dis power level on */
+static int tda18271_ir_cal_init(struct dvb_frontend *fe)
+{
+       struct tda18271_priv *priv = fe->tuner_priv;
+       unsigned char *regs = priv->tda18271_regs;
 
-       /* set standard */
-       regs[R_EP3]  &= ~0x1f; /* clear std bits */
+       tda18271_read_regs(fe);
 
-       /* see table 22 */
-       regs[R_EP3]  |= std;
+       /* test IR_CAL_OK to see if we need init */
+       if ((regs[R_EP1] & 0x08) == 0)
+               tda18271_init_regs(fe);
 
-       regs[R_EP4]  &= ~0x03; /* set cal mode to normal */
+       return 0;
+}
 
-       regs[R_EP4]  &= ~0x1c; /* clear if level bits */
-       switch (priv->mode) {
-       case TDA18271_ANALOG:
-               regs[R_MPD]  &= ~0x80; /* IF notch = 0 */
-               break;
-       case TDA18271_DIGITAL:
-               regs[R_EP4]  |= 0x04;
-               regs[R_MPD]  |= 0x80;
-               break;
-       }
+static int tda18271_init(struct dvb_frontend *fe)
+{
+       struct tda18271_priv *priv = fe->tuner_priv;
 
-       if (radio)
-               regs[R_EP4]  |=  0x80;
-       else
-               regs[R_EP4]  &= ~0x80;
+       mutex_lock(&priv->lock);
 
-       /* image rejection validity */
-       tda18271_calc_ir_measure(fe, &freq);
+       /* power up */
+       tda18271_set_standby_mode(fe, 0, 0, 0);
 
-       /* calculate MAIN PLL */
-       N = freq + ifc;
+       /* initialization */
+       tda18271_ir_cal_init(fe);
 
-       tda18271_calc_main_pll(fe, N);
+       if (priv->id == TDA18271HDC2)
+               tda18271c2_rf_cal_init(fe);
 
-       tda18271_write_regs(fe, R_TM, 15);
-       msleep(5);
        mutex_unlock(&priv->lock);
 
        return 0;
 }
 
-static inline int tda18271_tune(struct dvb_frontend *fe,
-                               u32 ifc, u32 freq, u32 bw, u8 std, int radio)
+static int tda18271_tune(struct dvb_frontend *fe,
+                        struct tda18271_std_map_item *map, u32 freq, u32 bw)
 {
        struct tda18271_priv *priv = fe->tuner_priv;
-       int ret = -EINVAL;
+
+       tda_dbg("freq = %d, ifc = %d, bw = %d, agc_mode = %d, std = %d\n",
+               freq, map->if_freq, bw, map->agc_mode, map->std);
+
+       tda18271_init(fe);
+
+       mutex_lock(&priv->lock);
 
        switch (priv->id) {
        case TDA18271HDC1:
-               ret = tda18271c1_tune(fe, ifc, freq, bw, std, radio);
+               tda18271c1_rf_tracking_filter_calibration(fe, freq, bw);
                break;
        case TDA18271HDC2:
-               ret = tda18271c2_tune(fe, ifc, freq, bw, std, radio);
+               tda18271c2_rf_tracking_filters_correction(fe, freq);
                break;
        }
-       return ret;
+       tda18271_channel_configuration(fe, map, freq, bw);
+
+       mutex_unlock(&priv->lock);
+
+       return 0;
 }
 
 /* ------------------------------------------------------------------ */
@@ -829,9 +783,8 @@ static int tda18271_set_params(struct dvb_frontend *fe,
 {
        struct tda18271_priv *priv = fe->tuner_priv;
        struct tda18271_std_map *std_map = &priv->std;
+       struct tda18271_std_map_item *map;
        int ret;
-       u8 std;
-       u16 sgIF;
        u32 bw, freq = params->frequency;
 
        priv->mode = TDA18271_DIGITAL;
@@ -840,13 +793,11 @@ static int tda18271_set_params(struct dvb_frontend *fe,
                switch (params->u.vsb.modulation) {
                case VSB_8:
                case VSB_16:
-                       std  = std_map->atsc_6.std_bits;
-                       sgIF = std_map->atsc_6.if_freq;
+                       map = &std_map->atsc_6;
                        break;
                case QAM_64:
                case QAM_256:
-                       std  = std_map->qam_6.std_bits;
-                       sgIF = std_map->qam_6.if_freq;
+                       map = &std_map->qam_6;
                        break;
                default:
                        tda_warn("modulation not set!\n");
@@ -861,18 +812,15 @@ static int tda18271_set_params(struct dvb_frontend *fe,
                switch (params->u.ofdm.bandwidth) {
                case BANDWIDTH_6_MHZ:
                        bw = 6000000;
-                       std  = std_map->dvbt_6.std_bits;
-                       sgIF = std_map->dvbt_6.if_freq;
+                       map = &std_map->dvbt_6;
                        break;
                case BANDWIDTH_7_MHZ:
                        bw = 7000000;
-                       std  = std_map->dvbt_7.std_bits;
-                       sgIF = std_map->dvbt_7.if_freq;
+                       map = &std_map->dvbt_7;
                        break;
                case BANDWIDTH_8_MHZ:
                        bw = 8000000;
-                       std  = std_map->dvbt_8.std_bits;
-                       sgIF = std_map->dvbt_8.if_freq;
+                       map = &std_map->dvbt_8;
                        break;
                default:
                        tda_warn("bandwidth not set!\n");
@@ -887,7 +835,7 @@ static int tda18271_set_params(struct dvb_frontend *fe,
        if (fe->ops.analog_ops.standby)
                fe->ops.analog_ops.standby(fe);
 
-       ret = tda18271_tune(fe, sgIF * 1000, freq, bw, std, 0);
+       ret = tda18271_tune(fe, map, freq, bw);
 
        if (ret < 0)
                goto fail;
@@ -904,57 +852,46 @@ static int tda18271_set_analog_params(struct dvb_frontend *fe,
 {
        struct tda18271_priv *priv = fe->tuner_priv;
        struct tda18271_std_map *std_map = &priv->std;
+       struct tda18271_std_map_item *map;
        char *mode;
-       int ret, radio = 0;
-       u8 std;
-       u16 sgIF;
+       int ret;
        u32 freq = params->frequency * 62500;
 
        priv->mode = TDA18271_ANALOG;
 
        if (params->mode == V4L2_TUNER_RADIO) {
-               radio = 1;
                freq = freq / 1000;
-               std  = std_map->fm_radio.std_bits;
-               sgIF = std_map->fm_radio.if_freq;
+               map = &std_map->fm_radio;
                mode = "fm";
        } else if (params->std & V4L2_STD_MN) {
-               std  = std_map->atv_mn.std_bits;
-               sgIF = std_map->atv_mn.if_freq;
+               map = &std_map->atv_mn;
                mode = "MN";
        } else if (params->std & V4L2_STD_B) {
-               std  = std_map->atv_b.std_bits;
-               sgIF = std_map->atv_b.if_freq;
+               map = &std_map->atv_b;
                mode = "B";
        } else if (params->std & V4L2_STD_GH) {
-               std  = std_map->atv_gh.std_bits;
-               sgIF = std_map->atv_gh.if_freq;
+               map = &std_map->atv_gh;
                mode = "GH";
        } else if (params->std & V4L2_STD_PAL_I) {
-               std  = std_map->atv_i.std_bits;
-               sgIF = std_map->atv_i.if_freq;
+               map = &std_map->atv_i;
                mode = "I";
        } else if (params->std & V4L2_STD_DK) {
-               std  = std_map->atv_dk.std_bits;
-               sgIF = std_map->atv_dk.if_freq;
+               map = &std_map->atv_dk;
                mode = "DK";
        } else if (params->std & V4L2_STD_SECAM_L) {
-               std  = std_map->atv_l.std_bits;
-               sgIF = std_map->atv_l.if_freq;
+               map = &std_map->atv_l;
                mode = "L";
        } else if (params->std & V4L2_STD_SECAM_LC) {
-               std  = std_map->atv_lc.std_bits;
-               sgIF = std_map->atv_lc.if_freq;
+               map = &std_map->atv_lc;
                mode = "L'";
        } else {
-               std  = std_map->atv_i.std_bits;
-               sgIF = std_map->atv_i.if_freq;
+               map = &std_map->atv_i;
                mode = "xx";
        }
 
        tda_dbg("setting tda18271 to system %s\n", mode);
 
-       ret = tda18271_tune(fe, sgIF * 1000, freq, 0, std, radio);
+       ret = tda18271_tune(fe, map, freq, 0);
 
        if (ret < 0)
                goto fail;
@@ -986,16 +923,9 @@ static int tda18271_release(struct dvb_frontend *fe)
 
        mutex_lock(&tda18271_list_mutex);
 
-       priv->count--;
+       if (priv)
+               hybrid_tuner_release_state(priv);
 
-       if (!priv->count) {
-               tda_dbg("destroying instance @ %d-%04x\n",
-                       i2c_adapter_id(priv->i2c_adap),
-                       priv->i2c_addr);
-               list_del(&priv->tda18271_list);
-
-               kfree(priv);
-       }
        mutex_unlock(&tda18271_list_mutex);
 
        fe->tuner_priv = NULL;
@@ -1020,15 +950,20 @@ static int tda18271_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
 /* ------------------------------------------------------------------ */
 
 #define tda18271_update_std(std_cfg, name) do {                                \
-       if (map->std_cfg.if_freq + map->std_cfg.std_bits > 0) {         \
+       if (map->std_cfg.if_freq +                                      \
+               map->std_cfg.agc_mode + map->std_cfg.std +              \
+               map->std_cfg.if_lvl + map->std_cfg.rfagc_top > 0) {     \
                tda_dbg("Using custom std config for %s\n", name);      \
                memcpy(&std->std_cfg, &map->std_cfg,                    \
                        sizeof(struct tda18271_std_map_item));          \
        } } while (0)
 
 #define tda18271_dump_std_item(std_cfg, name) do {                     \
-       tda_dbg("(%s) if freq = %d, std bits = 0x%02x\n",               \
-               name, std->std_cfg.if_freq, std->std_cfg.std_bits);     \
+       tda_dbg("(%s) if_freq = %d, agc_mode = %d, std = %d, "          \
+               "if_lvl = %d, rfagc_top = 0x%02x\n",                    \
+               name, std->std_cfg.if_freq,                             \
+               std->std_cfg.agc_mode, std->std_cfg.std,                \
+               std->std_cfg.if_lvl, std->std_cfg.rfagc_top);           \
        } while (0)
 
 static int tda18271_dump_std_map(struct dvb_frontend *fe)
@@ -1037,20 +972,20 @@ static int tda18271_dump_std_map(struct dvb_frontend *fe)
        struct tda18271_std_map *std = &priv->std;
 
        tda_dbg("========== STANDARD MAP SETTINGS ==========\n");
-       tda18271_dump_std_item(fm_radio, "fm");
-       tda18271_dump_std_item(atv_b,  "pal b");
-       tda18271_dump_std_item(atv_dk, "pal dk");
-       tda18271_dump_std_item(atv_gh, "pal gh");
-       tda18271_dump_std_item(atv_i,  "pal i");
-       tda18271_dump_std_item(atv_l,  "pal l");
-       tda18271_dump_std_item(atv_lc, "pal l'");
+       tda18271_dump_std_item(fm_radio, "  fm  ");
+       tda18271_dump_std_item(atv_b,  "atv b ");
+       tda18271_dump_std_item(atv_dk, "atv dk");
+       tda18271_dump_std_item(atv_gh, "atv gh");
+       tda18271_dump_std_item(atv_i,  "atv i ");
+       tda18271_dump_std_item(atv_l,  "atv l ");
+       tda18271_dump_std_item(atv_lc, "atv l'");
        tda18271_dump_std_item(atv_mn, "atv mn");
        tda18271_dump_std_item(atsc_6, "atsc 6");
        tda18271_dump_std_item(dvbt_6, "dvbt 6");
        tda18271_dump_std_item(dvbt_7, "dvbt 7");
        tda18271_dump_std_item(dvbt_8, "dvbt 8");
-       tda18271_dump_std_item(qam_6,  "qam 6");
-       tda18271_dump_std_item(qam_8,  "qam 8");
+       tda18271_dump_std_item(qam_6,  "qam 6 ");
+       tda18271_dump_std_item(qam_8,  "qam 8 ");
 
        return 0;
 }
@@ -1109,7 +1044,8 @@ static int tda18271_get_id(struct dvb_frontend *fe)
        }
 
        tda_info("%s detected @ %d-%04x%s\n", name,
-                i2c_adapter_id(priv->i2c_adap), priv->i2c_addr,
+                i2c_adapter_id(priv->i2c_props.adap),
+                priv->i2c_props.addr,
                 (0 == ret) ? "" : ", device not supported.");
 
        return ret;
@@ -1136,45 +1072,28 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
                                     struct tda18271_config *cfg)
 {
        struct tda18271_priv *priv = NULL;
-       int state_found = 0;
+       int instance;
 
        mutex_lock(&tda18271_list_mutex);
 
-       list_for_each_entry(priv, &tda18271_list, tda18271_list) {
-               if ((i2c_adapter_id(priv->i2c_adap) == i2c_adapter_id(i2c)) &&
-                   (priv->i2c_addr == addr)) {
-                       tda_dbg("attaching existing tuner @ %d-%04x\n",
-                               i2c_adapter_id(priv->i2c_adap),
-                               priv->i2c_addr);
-                       priv->count++;
-                       fe->tuner_priv = priv;
-                       state_found = 1;
-                       /* allow dvb driver to override i2c gate setting */
-                       if ((cfg) && (cfg->gate != TDA18271_GATE_ANALOG))
-                               priv->gate = cfg->gate;
-                       break;
-               }
-       }
-       if (state_found == 0) {
-               tda_dbg("creating new tuner instance @ %d-%04x\n",
-                       i2c_adapter_id(i2c), addr);
-
-               priv = kzalloc(sizeof(struct tda18271_priv), GFP_KERNEL);
-               if (priv == NULL) {
-                       mutex_unlock(&tda18271_list_mutex);
-                       return NULL;
-               }
-
-               priv->i2c_addr = addr;
-               priv->i2c_adap = i2c;
+       instance = hybrid_tuner_request_state(struct tda18271_priv, priv,
+                                             hybrid_tuner_instance_list,
+                                             i2c, addr, "tda18271");
+       switch (instance) {
+       case 0:
+               goto fail;
+               break;
+       case 1:
+               /* new tuner instance */
                priv->gate = (cfg) ? cfg->gate : TDA18271_GATE_AUTO;
+               priv->role = (cfg) ? cfg->role : TDA18271_MASTER;
                priv->cal_initialized = false;
                mutex_init(&priv->lock);
-               priv->count++;
 
                fe->tuner_priv = priv;
 
-               list_add_tail(&priv->tda18271_list, &tda18271_list);
+               if (cfg)
+                       priv->small_i2c = cfg->small_i2c;
 
                if (tda18271_get_id(fe) < 0)
                        goto fail;
@@ -1186,9 +1105,18 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
                tda18271_init_regs(fe);
 
                if ((tda18271_cal_on_startup) && (priv->id == TDA18271HDC2))
-                       tda18271_rf_cal_init(fe);
+                       tda18271c2_rf_cal_init(fe);
 
                mutex_unlock(&priv->lock);
+               break;
+       default:
+               /* existing tuner instance */
+               fe->tuner_priv = priv;
+
+               /* allow dvb driver to override i2c gate setting */
+               if ((cfg) && (cfg->gate != TDA18271_GATE_ANALOG))
+                       priv->gate = cfg->gate;
+               break;
        }
 
        /* override default std map with values in config struct */
@@ -1200,7 +1128,7 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
        memcpy(&fe->ops.tuner_ops, &tda18271_tuner_ops,
               sizeof(struct dvb_tuner_ops));
 
-       if (tda18271_debug & DBG_MAP)
+       if (tda18271_debug & (DBG_MAP | DBG_ADV))
                tda18271_dump_std_map(fe);
 
        return fe;
@@ -1214,7 +1142,7 @@ EXPORT_SYMBOL_GPL(tda18271_attach);
 MODULE_DESCRIPTION("NXP TDA18271HD analog / digital tuner driver");
 MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
 MODULE_LICENSE("GPL");
-MODULE_VERSION("0.2");
+MODULE_VERSION("0.3");
 
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
index 7b939a5325fb970189feeb998913f37e49d11e19..2bc5eb368ea2853109298eb7bf1a7ee4e4b4625b 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/mutex.h>
+#include "tuner-i2c.h"
 #include "tda18271.h"
 
 #define R_ID     0x00  /* ID byte                */
@@ -85,6 +86,11 @@ struct tda18271_rf_tracking_filter_cal {
        int rf_b2;
 };
 
+enum tda18271_pll {
+       TDA18271_MAIN_PLL,
+       TDA18271_CAL_PLL,
+};
+
 enum tda18271_mode {
        TDA18271_ANALOG,
        TDA18271_DIGITAL,
@@ -98,19 +104,19 @@ enum tda18271_ver {
 };
 
 struct tda18271_priv {
-       u8 i2c_addr;
-       struct i2c_adapter *i2c_adap;
        unsigned char tda18271_regs[TDA18271_NUM_REGS];
 
-       struct list_head tda18271_list;
+       struct list_head        hybrid_tuner_instance_list;
+       struct tuner_i2c_props  i2c_props;
 
        enum tda18271_mode mode;
+       enum tda18271_role role;
        enum tda18271_i2c_gate gate;
        enum tda18271_ver id;
 
-       unsigned int count;
        unsigned int tm_rfcal;
        unsigned int cal_initialized:1;
+       unsigned int small_i2c:1;
 
        struct tda18271_map_layout *maps;
        struct tda18271_std_map std;
@@ -133,7 +139,7 @@ extern int tda18271_debug;
 #define DBG_CAL  16
 
 #define tda_printk(kern, fmt, arg...) \
-       printk(kern "%s: " fmt, __FUNCTION__, ##arg)
+       printk(kern "%s: " fmt, __func__, ##arg)
 
 #define dprintk(kern, lvl, fmt, arg...) do {\
        if (tda18271_debug & lvl) \
@@ -188,6 +194,8 @@ extern int tda18271_read_extended(struct dvb_frontend *fe);
 extern int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len);
 extern int tda18271_init_regs(struct dvb_frontend *fe);
 
+extern int tda18271_charge_pump_source(struct dvb_frontend *fe,
+                                      enum tda18271_pll pll, int force);
 extern int tda18271_set_standby_mode(struct dvb_frontend *fe,
                                     int sm, int sm_lt, int sm_xt);
 
index e94afcfdc5bce96fbae91878560fbdabcd830510..83e7561960c185aa7e92a43739bd22ae169677fd 100644 (file)
@@ -1187,37 +1187,65 @@ fail:
 /*---------------------------------------------------------------------*/
 
 static struct tda18271_std_map tda18271c1_std_map = {
-       .fm_radio = { .if_freq = 1250, .std_bits = 0x18 },
-       .atv_b    = { .if_freq = 6750, .std_bits = 0x0e },
-       .atv_dk   = { .if_freq = 7750, .std_bits = 0x0f },
-       .atv_gh   = { .if_freq = 7750, .std_bits = 0x0f },
-       .atv_i    = { .if_freq = 7750, .std_bits = 0x0f },
-       .atv_l    = { .if_freq = 7750, .std_bits = 0x0f },
-       .atv_lc   = { .if_freq = 1250, .std_bits = 0x0f },
-       .atv_mn   = { .if_freq = 5750, .std_bits = 0x0d },
-       .atsc_6   = { .if_freq = 3250, .std_bits = 0x1c },
-       .dvbt_6   = { .if_freq = 3300, .std_bits = 0x1c },
-       .dvbt_7   = { .if_freq = 3800, .std_bits = 0x1d },
-       .dvbt_8   = { .if_freq = 4300, .std_bits = 0x1e },
-       .qam_6    = { .if_freq = 4000, .std_bits = 0x1d },
-       .qam_8    = { .if_freq = 5000, .std_bits = 0x1f },
+       .fm_radio = { .if_freq = 1250, .fm_rfn = 1, .agc_mode = 3, .std = 0,
+                     .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x18 */
+       .atv_b    = { .if_freq = 6750, .fm_rfn = 0, .agc_mode = 1, .std = 6,
+                     .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0e */
+       .atv_dk   = { .if_freq = 7750, .fm_rfn = 0, .agc_mode = 1, .std = 7,
+                     .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0f */
+       .atv_gh   = { .if_freq = 7750, .fm_rfn = 0, .agc_mode = 1, .std = 7,
+                     .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0f */
+       .atv_i    = { .if_freq = 7750, .fm_rfn = 0, .agc_mode = 1, .std = 7,
+                     .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0f */
+       .atv_l    = { .if_freq = 7750, .fm_rfn = 0, .agc_mode = 1, .std = 7,
+                     .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0f */
+       .atv_lc   = { .if_freq = 1250, .fm_rfn = 0, .agc_mode = 1, .std = 7,
+                     .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0f */
+       .atv_mn   = { .if_freq = 5750, .fm_rfn = 0, .agc_mode = 1, .std = 5,
+                     .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0d */
+       .atsc_6   = { .if_freq = 3250, .fm_rfn = 0, .agc_mode = 3, .std = 4,
+                     .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1c */
+       .dvbt_6   = { .if_freq = 3300, .fm_rfn = 0, .agc_mode = 3, .std = 4,
+                     .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1c */
+       .dvbt_7   = { .if_freq = 3800, .fm_rfn = 0, .agc_mode = 3, .std = 5,
+                     .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1d */
+       .dvbt_8   = { .if_freq = 4300, .fm_rfn = 0, .agc_mode = 3, .std = 6,
+                     .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1e */
+       .qam_6    = { .if_freq = 4000, .fm_rfn = 0, .agc_mode = 3, .std = 5,
+                     .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1d */
+       .qam_8    = { .if_freq = 5000, .fm_rfn = 0, .agc_mode = 3, .std = 7,
+                     .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1f */
 };
 
 static struct tda18271_std_map tda18271c2_std_map = {
-       .fm_radio = { .if_freq = 1250, .std_bits = 0x18 },
-       .atv_b    = { .if_freq = 6000, .std_bits = 0x0d },
-       .atv_dk   = { .if_freq = 6900, .std_bits = 0x0e },
-       .atv_gh   = { .if_freq = 7100, .std_bits = 0x0e },
-       .atv_i    = { .if_freq = 7250, .std_bits = 0x0e },
-       .atv_l    = { .if_freq = 6900, .std_bits = 0x0e },
-       .atv_lc   = { .if_freq = 1250, .std_bits = 0x0e },
-       .atv_mn   = { .if_freq = 5400, .std_bits = 0x0c },
-       .atsc_6   = { .if_freq = 3250, .std_bits = 0x1c },
-       .dvbt_6   = { .if_freq = 3300, .std_bits = 0x1c },
-       .dvbt_7   = { .if_freq = 3500, .std_bits = 0x1c },
-       .dvbt_8   = { .if_freq = 4000, .std_bits = 0x1d },
-       .qam_6    = { .if_freq = 4000, .std_bits = 0x1d },
-       .qam_8    = { .if_freq = 5000, .std_bits = 0x1f },
+       .fm_radio = { .if_freq = 1250, .fm_rfn = 1, .agc_mode = 3, .std = 0,
+                     .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x18 */
+       .atv_b    = { .if_freq = 6000, .fm_rfn = 0, .agc_mode = 1, .std = 5,
+                     .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0d */
+       .atv_dk   = { .if_freq = 6900, .fm_rfn = 0, .agc_mode = 1, .std = 6,
+                     .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0e */
+       .atv_gh   = { .if_freq = 7100, .fm_rfn = 0, .agc_mode = 1, .std = 6,
+                     .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0e */
+       .atv_i    = { .if_freq = 7250, .fm_rfn = 0, .agc_mode = 1, .std = 6,
+                     .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0e */
+       .atv_l    = { .if_freq = 6900, .fm_rfn = 0, .agc_mode = 1, .std = 6,
+                     .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0e */
+       .atv_lc   = { .if_freq = 1250, .fm_rfn = 0, .agc_mode = 1, .std = 6,
+                     .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0e */
+       .atv_mn   = { .if_freq = 5400, .fm_rfn = 0, .agc_mode = 1, .std = 4,
+                     .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0c */
+       .atsc_6   = { .if_freq = 3250, .fm_rfn = 0, .agc_mode = 3, .std = 4,
+                     .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1c */
+       .dvbt_6   = { .if_freq = 3300, .fm_rfn = 0, .agc_mode = 3, .std = 4,
+                     .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1c */
+       .dvbt_7   = { .if_freq = 3500, .fm_rfn = 0, .agc_mode = 3, .std = 4,
+                     .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1c */
+       .dvbt_8   = { .if_freq = 4000, .fm_rfn = 0, .agc_mode = 3, .std = 5,
+                     .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1d */
+       .qam_6    = { .if_freq = 4000, .fm_rfn = 0, .agc_mode = 3, .std = 5,
+                     .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1d */
+       .qam_8    = { .if_freq = 5000, .fm_rfn = 0, .agc_mode = 3, .std = 7,
+                     .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1f */
 };
 
 /*---------------------------------------------------------------------*/
index 24b0e35a2ab3c7ae3b3134af19895ba4220407eb..0e7af8d05a38cb91c074b7310bad34b93ad33073 100644 (file)
 
 struct tda18271_std_map_item {
        u16 if_freq;
-       u8 std_bits;
+
+       /* EP3[4:3] */
+       unsigned int agc_mode:2;
+       /* EP3[2:0] */
+       unsigned int std:3;
+       /* EP4[7] */
+       unsigned int fm_rfn:1;
+       /* EP4[4:2] */
+       unsigned int if_lvl:3;
+       /* EB22[6:0] */
+       unsigned int rfagc_top:7;
 };
 
 struct tda18271_std_map {
@@ -46,6 +56,11 @@ struct tda18271_std_map {
        struct tda18271_std_map_item qam_8;
 };
 
+enum tda18271_role {
+       TDA18271_MASTER = 0,
+       TDA18271_SLAVE,
+};
+
 enum tda18271_i2c_gate {
        TDA18271_GATE_AUTO = 0,
        TDA18271_GATE_ANALOG,
@@ -56,8 +71,14 @@ struct tda18271_config {
        /* override default if freq / std settings (optional) */
        struct tda18271_std_map *std_map;
 
+       /* master / slave tuner: master uses main pll, slave uses cal pll */
+       enum tda18271_role role;
+
        /* use i2c gate provided by analog or digital demod */
        enum tda18271_i2c_gate gate;
+
+       /* some i2c providers cant write all 39 registers at once */
+       unsigned int small_i2c:1;
 };
 
 #if defined(CONFIG_DVB_TDA18271) || (defined(CONFIG_DVB_TDA18271_MODULE) && defined(MODULE))
@@ -70,7 +91,7 @@ static inline struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe,
                                                   struct i2c_adapter *i2c,
                                                   struct tda18271_config *cfg)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif
index 011b74f798a031207fbe71eb7313c106b377bf73..5b843b2e67e874c03f79cdfb1407680e16ee99ad 100644 (file)
@@ -68,7 +68,7 @@ static int tda8083_writereg (struct tda8083_state* state, u8 reg, u8 data)
 
        if (ret != 1)
                dprintk ("%s: writereg error (reg %02x, ret == %i)\n",
-                       __FUNCTION__, reg, ret);
+                       __func__, reg, ret);
 
        return (ret != 1) ? -1 : 0;
 }
@@ -83,7 +83,7 @@ static int tda8083_readregs (struct tda8083_state* state, u8 reg1, u8 *b, u8 len
 
        if (ret != 2)
                dprintk ("%s: readreg error (reg %02x, ret == %i)\n",
-                       __FUNCTION__, reg1, ret);
+                       __func__, reg1, ret);
 
        return ret == 2 ? 0 : -1;
 }
index 2d3307999f21cf3b47674de73586e55f769405bb..5a03c14a10e80fc4f0276347b5003b78f411f95c 100644 (file)
@@ -42,7 +42,7 @@ extern struct dvb_frontend* tda8083_attach(const struct tda8083_config* config,
 static inline struct dvb_frontend* tda8083_attach(const struct tda8083_config* config,
                                           struct i2c_adapter* i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_TDA8083
index bd3ebc2848352b75301f08d6bcafd771ec629564..a051554b5e2589aeb32060ebb0a41c1c38b65e84 100644 (file)
@@ -26,7 +26,7 @@
 
 #include "tda826x.h"
 
-static int debug = 0;
+static int debug;
 #define dprintk(args...) \
        do { \
                if (debug) printk(KERN_DEBUG "tda826x: " args); \
@@ -54,7 +54,7 @@ static int tda826x_sleep(struct dvb_frontend *fe)
        u8 buf [] = { 0x00, 0x8d };
        struct i2c_msg msg = { .addr = priv->i2c_address, .flags = 0, .buf = buf, .len = 2 };
 
-       dprintk("%s:\n", __FUNCTION__);
+       dprintk("%s:\n", __func__);
 
        if (!priv->has_loopthrough)
                buf[1] = 0xad;
@@ -62,7 +62,7 @@ static int tda826x_sleep(struct dvb_frontend *fe)
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 1);
        if ((ret = i2c_transfer (priv->i2c, &msg, 1)) != 1) {
-               dprintk("%s: i2c error\n", __FUNCTION__);
+               dprintk("%s: i2c error\n", __func__);
        }
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 0);
@@ -75,13 +75,24 @@ static int tda826x_set_params(struct dvb_frontend *fe, struct dvb_frontend_param
        struct tda826x_priv *priv = fe->tuner_priv;
        int ret;
        u32 div;
+       u32 ksyms;
+       u32 bandwidth;
        u8 buf [11];
        struct i2c_msg msg = { .addr = priv->i2c_address, .flags = 0, .buf = buf, .len = 11 };
 
-       dprintk("%s:\n", __FUNCTION__);
+       dprintk("%s:\n", __func__);
 
        div = (params->frequency + (1000-1)) / 1000;
 
+       /* BW = ((1 + RO) * SR/2 + 5) * 1.3      [SR in MSPS, BW in MHz] */
+       /* with R0 = 0.35 and some transformations: */
+       ksyms = params->u.qpsk.symbol_rate / 1000;
+       bandwidth = (878 * ksyms + 6500000) / 1000000 + 1;
+       if (bandwidth < 5)
+               bandwidth = 5;
+       else if (bandwidth > 36)
+               bandwidth = 36;
+
        buf[0] = 0x00; // subaddress
        buf[1] = 0x09; // powerdown RSSI + the magic value 1
        if (!priv->has_loopthrough)
@@ -89,7 +100,7 @@ static int tda826x_set_params(struct dvb_frontend *fe, struct dvb_frontend_param
        buf[2] = (1<<5) | 0x0b; // 1Mhz + 0.45 VCO
        buf[3] = div >> 7;
        buf[4] = div << 1;
-       buf[5] = 0x77; // baseband cut-off 19 MHz
+       buf[5] = ((bandwidth - 5) << 3) | 7; /* baseband cut-off */
        buf[6] = 0xfe; // baseband gain 9 db + no RF attenuation
        buf[7] = 0x83; // charge pumps at high, tests off
        buf[8] = 0x80; // recommended value 4 for AMPVCO + disable ports.
@@ -99,7 +110,7 @@ static int tda826x_set_params(struct dvb_frontend *fe, struct dvb_frontend_param
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 1);
        if ((ret = i2c_transfer (priv->i2c, &msg, 1)) != 1) {
-               dprintk("%s: i2c error\n", __FUNCTION__);
+               dprintk("%s: i2c error\n", __func__);
        }
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 0);
@@ -138,7 +149,7 @@ struct dvb_frontend *tda826x_attach(struct dvb_frontend *fe, int addr, struct i2
        };
        int ret;
 
-       dprintk("%s:\n", __FUNCTION__);
+       dprintk("%s:\n", __func__);
 
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 1);
index ad998119596183264e0ef9b06907e377a73dff3e..89e97926ab23acb4dcd78f7537d9988d4b62ce16 100644 (file)
@@ -45,7 +45,7 @@ static inline struct dvb_frontend* tda826x_attach(struct dvb_frontend *fe,
                                                  struct i2c_adapter *i2c,
                                                  int has_loopthrough)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_TDA826X
index 229b11987a589fed652c00934c91101f59867eeb..d30d2c9094d9b0fcdde74cd3212d9f5cbd700b95 100644 (file)
@@ -25,7 +25,7 @@
 
 #include "tda827x.h"
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
 
@@ -142,7 +142,7 @@ static int tda827xo_set_params(struct dvb_frontend *fe,
        int i, tuner_freq, if_freq;
        u32 N;
 
-       dprintk("%s:\n", __FUNCTION__);
+       dprintk("%s:\n", __func__);
        switch (params->u.ofdm.bandwidth) {
        case BANDWIDTH_6_MHZ:
                if_freq = 4000000;
@@ -186,7 +186,7 @@ static int tda827xo_set_params(struct dvb_frontend *fe,
                fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer(priv->i2c_adap, &msg, 1) != 1) {
                printk("%s: could not write to tuner at addr: 0x%02x\n",
-                      __FUNCTION__, priv->i2c_addr << 1);
+                      __func__, priv->i2c_addr << 1);
                return -EIO;
        }
        msleep(500);
@@ -212,7 +212,7 @@ static int tda827xo_sleep(struct dvb_frontend *fe)
        struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
                               .buf = buf, .len = sizeof(buf) };
 
-       dprintk("%s:\n", __FUNCTION__);
+       dprintk("%s:\n", __func__);
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 1);
        i2c_transfer(priv->i2c_adap, &msg, 1);
@@ -389,6 +389,79 @@ static struct tda827xa_data tda827xa_analog[] = {
        { .lomax =         0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0}
 };
 
+static int tda827xa_sleep(struct dvb_frontend *fe)
+{
+       struct tda827x_priv *priv = fe->tuner_priv;
+       static u8 buf[] = { 0x30, 0x90 };
+       struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
+                              .buf = buf, .len = sizeof(buf) };
+
+       dprintk("%s:\n", __func__);
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+
+       i2c_transfer(priv->i2c_adap, &msg, 1);
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0);
+
+       if (priv->cfg && priv->cfg->sleep)
+               priv->cfg->sleep(fe);
+
+       return 0;
+}
+
+static void tda827xa_lna_gain(struct dvb_frontend *fe, int high,
+                             struct analog_parameters *params)
+{
+       struct tda827x_priv *priv = fe->tuner_priv;
+       unsigned char buf[] = {0x22, 0x01};
+       int arg;
+       int gp_func;
+       struct i2c_msg msg = { .addr = priv->cfg->switch_addr, .flags = 0,
+                              .buf = buf, .len = sizeof(buf) };
+
+       if (NULL == priv->cfg) {
+               dprintk("tda827x_config not defined, cannot set LNA gain!\n");
+               return;
+       }
+       if (priv->cfg->config) {
+               if (high)
+                       dprintk("setting LNA to high gain\n");
+               else
+                       dprintk("setting LNA to low gain\n");
+       }
+       switch (priv->cfg->config) {
+       case 0: /* no LNA */
+               break;
+       case 1: /* switch is GPIO 0 of tda8290 */
+       case 2:
+               if (params == NULL) {
+                       gp_func = 0;
+                       arg  = 0;
+               } else {
+                       /* turn Vsync on */
+                       gp_func = 1;
+                       if (params->std & V4L2_STD_MN)
+                               arg = 1;
+                       else
+                               arg = 0;
+               }
+               if (priv->cfg->tuner_callback)
+                       priv->cfg->tuner_callback(priv->i2c_adap->algo_data,
+                                                               gp_func, arg);
+               buf[1] = high ? 0 : 1;
+               if (priv->cfg->config == 2)
+                       buf[1] = high ? 1 : 0;
+               i2c_transfer(priv->i2c_adap, &msg, 1);
+               break;
+       case 3: /* switch with GPIO of saa713x */
+               if (priv->cfg->tuner_callback)
+                       priv->cfg->tuner_callback(priv->i2c_adap->algo_data, 0, high);
+               break;
+       }
+}
+
 static int tda827xa_set_params(struct dvb_frontend *fe,
                               struct dvb_frontend_parameters *params)
 {
@@ -401,9 +474,9 @@ static int tda827xa_set_params(struct dvb_frontend *fe,
        int i, tuner_freq, if_freq;
        u32 N;
 
-       dprintk("%s:\n", __FUNCTION__);
-       if (priv->cfg && priv->cfg->lna_gain)
-               priv->cfg->lna_gain(fe, 1);
+       dprintk("%s:\n", __func__);
+
+       tda827xa_lna_gain(fe, 1, NULL);
        msleep(20);
 
        switch (params->u.ofdm.bandwidth) {
@@ -444,7 +517,7 @@ static int tda827xa_set_params(struct dvb_frontend *fe,
                fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer(priv->i2c_adap, &msg, 1) != 1) {
                printk("%s: could not write to tuner at addr: 0x%02x\n",
-                      __FUNCTION__, priv->i2c_addr << 1);
+                      __func__, priv->i2c_addr << 1);
                return -EIO;
        }
        buf[0] = 0x90;
@@ -474,8 +547,7 @@ static int tda827xa_set_params(struct dvb_frontend *fe,
        buf[1] >>= 4;
        dprintk("tda8275a AGC2 gain is: %d\n", buf[1]);
        if ((buf[1]) < 2) {
-               if (priv->cfg && priv->cfg->lna_gain)
-                       priv->cfg->lna_gain(fe, 0);
+               tda827xa_lna_gain(fe, 0, NULL);
                buf[0] = 0x60;
                buf[1] = 0x0c;
                if (fe->ops.i2c_gate_ctrl)
@@ -523,75 +595,6 @@ static int tda827xa_set_params(struct dvb_frontend *fe,
        return 0;
 }
 
-static int tda827xa_sleep(struct dvb_frontend *fe)
-{
-       struct tda827x_priv *priv = fe->tuner_priv;
-       static u8 buf[] = { 0x30, 0x90 };
-       struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
-                              .buf = buf, .len = sizeof(buf) };
-
-       dprintk("%s:\n", __FUNCTION__);
-       if (fe->ops.i2c_gate_ctrl)
-               fe->ops.i2c_gate_ctrl(fe, 1);
-
-       i2c_transfer(priv->i2c_adap, &msg, 1);
-
-       if (fe->ops.i2c_gate_ctrl)
-               fe->ops.i2c_gate_ctrl(fe, 0);
-
-       if (priv->cfg && priv->cfg->sleep)
-               priv->cfg->sleep(fe);
-
-       return 0;
-}
-
-/* ------------------------------------------------------------------ */
-
-static void tda827xa_lna_gain(struct dvb_frontend *fe, int high,
-                             struct analog_parameters *params)
-{
-       struct tda827x_priv *priv = fe->tuner_priv;
-       unsigned char buf[] = {0x22, 0x01};
-       int arg;
-       struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
-                              .buf = buf, .len = sizeof(buf) };
-
-       if (NULL == priv->cfg) {
-               dprintk("tda827x_config not defined, cannot set LNA gain!\n");
-               return;
-       }
-
-       if (priv->cfg->config) {
-               if (high)
-                       dprintk("setting LNA to high gain\n");
-               else
-                       dprintk("setting LNA to low gain\n");
-       }
-       switch (*priv->cfg->config) {
-       case 0: /* no LNA */
-               break;
-       case 1: /* switch is GPIO 0 of tda8290 */
-       case 2:
-               /* turn Vsync on */
-               if (params->std & V4L2_STD_MN)
-                       arg = 1;
-               else
-                       arg = 0;
-               if (priv->cfg->tuner_callback)
-                       priv->cfg->tuner_callback(priv->i2c_adap->algo_data,
-                                                 1, arg);
-               buf[1] = high ? 0 : 1;
-               if (*priv->cfg->config == 2)
-                       buf[1] = high ? 1 : 0;
-               i2c_transfer(priv->i2c_adap, &msg, 1);
-               break;
-       case 3: /* switch with GPIO of saa713x */
-               if (priv->cfg->tuner_callback)
-                       priv->cfg->tuner_callback(priv->i2c_adap->algo_data,
-                                                 0, high);
-               break;
-       }
-}
 
 static int tda827xa_set_analog_params(struct dvb_frontend *fe,
                                      struct analog_parameters *params)
@@ -726,7 +729,7 @@ static int tda827x_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
 static int tda827x_init(struct dvb_frontend *fe)
 {
        struct tda827x_priv *priv = fe->tuner_priv;
-       dprintk("%s:\n", __FUNCTION__);
+       dprintk("%s:\n", __func__);
        if (priv->cfg && priv->cfg->init)
                priv->cfg->init(fe);
 
@@ -794,7 +797,7 @@ static int tda827x_probe_version(struct dvb_frontend *fe)
                fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer(priv->i2c_adap, &msg, 1) != 1) {
                printk("%s: could not read from tuner at addr: 0x%02x\n",
-                      __FUNCTION__, msg.addr << 1);
+                      __func__, msg.addr << 1);
                return -EIO;
        }
        if ((data & 0x3c) == 0) {
@@ -818,7 +821,7 @@ struct dvb_frontend *tda827x_attach(struct dvb_frontend *fe, int addr,
 {
        struct tda827x_priv *priv = NULL;
 
-       dprintk("%s:\n", __FUNCTION__);
+       dprintk("%s:\n", __func__);
        priv = kzalloc(sizeof(struct tda827x_priv), GFP_KERNEL);
        if (priv == NULL)
                return NULL;
index 92eb65b4012b37dcb28abb204f132ac34d8b1c29..b73c23570dab67e094482ebf31b77dcea29d4fe3 100644 (file)
 struct tda827x_config
 {
        /* saa7134 - provided callbacks */
-       void (*lna_gain) (struct dvb_frontend *fe, int high);
        int (*init) (struct dvb_frontend *fe);
        int (*sleep) (struct dvb_frontend *fe);
 
        /* interface to tda829x driver */
-       unsigned int *config;
+       unsigned int config;
+       int          switch_addr;
        int (*tuner_callback) (void *dev, int command, int arg);
 
        void (*agcf)(struct dvb_frontend *fe);
@@ -61,7 +61,7 @@ static inline struct dvb_frontend* tda827x_attach(struct dvb_frontend *fe,
                                                  struct i2c_adapter *i2c,
                                                  struct tda827x_config *cfg)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_TDA827X
index 6ba0029dcf2eee56e93315d10f089a47772f5a3d..1790baee014c4c7cb0f1f3cdf749d386d978ebbc 100644 (file)
@@ -58,7 +58,7 @@ static int tua6100_sleep(struct dvb_frontend *fe)
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 1);
        if ((ret = i2c_transfer (priv->i2c, &msg, 1)) != 1) {
-               printk("%s: i2c error\n", __FUNCTION__);
+               printk("%s: i2c error\n", __func__);
        }
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 0);
index 03a665e7df6d733b2067650ca394ee9640280eaf..f83dbd5e42ae642dff9410681d1a114d08a17a3e 100644 (file)
@@ -39,7 +39,7 @@ extern struct dvb_frontend *tua6100_attach(struct dvb_frontend *fe, int addr, st
 #else
 static inline struct dvb_frontend* tua6100_attach(struct dvb_frontend *fe, int addr, struct i2c_adapter *i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_TUA6100
index 8791701c8f25c8a9288d842ae865c4ba6bd656aa..a184597f1d9be0002b8f567b245a849abef6553c 100644 (file)
@@ -66,7 +66,7 @@ static int ves1820_writereg(struct ves1820_state *state, u8 reg, u8 data)
 
        if (ret != 1)
                printk("ves1820: %s(): writereg error (reg == 0x%02x, "
-                       "val == 0x%02x, ret == %i)\n", __FUNCTION__, reg, data, ret);
+                       "val == 0x%02x, ret == %i)\n", __func__, reg, data, ret);
 
        return (ret != 1) ? -EREMOTEIO : 0;
 }
@@ -85,7 +85,7 @@ static u8 ves1820_readreg(struct ves1820_state *state, u8 reg)
 
        if (ret != 2)
                printk("ves1820: %s(): readreg error (reg == 0x%02x, "
-               "ret == %i)\n", __FUNCTION__, reg, ret);
+               "ret == %i)\n", __func__, reg, ret);
 
        return b1[0];
 }
index e4a2a324046af986ac35c41a256ccdba3001408e..e902ed634ec301ea3ffe59fc3a5e0400a438cd4f 100644 (file)
@@ -48,7 +48,7 @@ extern struct dvb_frontend* ves1820_attach(const struct ves1820_config* config,
 static inline struct dvb_frontend* ves1820_attach(const struct ves1820_config* config,
                                           struct i2c_adapter* i2c, u8 pwm)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_VES1820
index 23fd0303c91b486a38776ab80fc8c915a0e9d364..bd558960bd87222eed8a71e7f696554e461ea9be 100644 (file)
@@ -48,7 +48,7 @@ struct ves1x93_state {
        u8 demod_type;
 };
 
-static int debug = 0;
+static int debug;
 #define dprintk        if (debug) printk
 
 #define DEMOD_VES1893          0
@@ -98,7 +98,7 @@ static int ves1x93_writereg (struct ves1x93_state* state, u8 reg, u8 data)
        int err;
 
        if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
-               dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __FUNCTION__, err, reg, data);
+               dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __func__, err, reg, data);
                return -EREMOTEIO;
        }
 
@@ -179,7 +179,7 @@ static int ves1x93_set_symbolrate (struct ves1x93_state* state, u32 srate)
        u32 tmp;
        u32 FIN;
 
-       dprintk("%s: srate == %d\n", __FUNCTION__, (unsigned int) srate);
+       dprintk("%s: srate == %d\n", __func__, (unsigned int) srate);
 
        if (srate > state->config->xin/2)
                srate = state->config->xin/2;
@@ -266,7 +266,7 @@ static int ves1x93_init (struct dvb_frontend* fe)
        int i;
        int val;
 
-       dprintk("%s: init chip\n", __FUNCTION__);
+       dprintk("%s: init chip\n", __func__);
 
        for (i = 0; i < state->tab_size; i++) {
                if (state->init_1x93_wtab[i]) {
index d507f8966f816fb2aa4cff8222e2be2ab011cd46..8a5a49e808f63a152298e1b8f58247cdd0249e63 100644 (file)
@@ -47,7 +47,7 @@ extern struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config,
 static inline struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config,
                                           struct i2c_adapter* i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_VES1X93
index f642ca200b596096c2f85167faeeeef4ec6b091f..43d35bdb221f0ab367953d557d9c29d4fae2b077 100644 (file)
@@ -151,7 +151,7 @@ typedef struct {
 #define FM_Radio_INPUT2        21
 #define FM_Radio_INPUT1        22
 
-XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = {
+static XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = {
        {"M/N-NTSC/PAL-BTSC", 0x0400, 0x8020},
        {"M/N-NTSC/PAL-A2",   0x0600, 0x8020},
        {"M/N-NTSC/PAL-EIAJ", 0x0440, 0x8020},
@@ -209,7 +209,7 @@ static void xc5000_TunerReset(struct dvb_frontend *fe)
        struct xc5000_priv *priv = fe->tuner_priv;
        int ret;
 
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
 
        if (priv->cfg->tuner_callback) {
                ret = priv->cfg->tuner_callback(priv->cfg->priv,
@@ -330,7 +330,7 @@ static int xc_load_i2c_sequence(struct dvb_frontend *fe, u8 i2c_sequence[])
 
 static int xc_initialize(struct xc5000_priv *priv)
 {
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
        return xc_write_reg(priv, XREG_INIT, 0);
 }
 
@@ -338,9 +338,9 @@ static int xc_SetTVStandard(struct xc5000_priv *priv,
        u16 VideoMode, u16 AudioMode)
 {
        int ret;
-       dprintk(1, "%s(0x%04x,0x%04x)\n", __FUNCTION__, VideoMode, AudioMode);
+       dprintk(1, "%s(0x%04x,0x%04x)\n", __func__, VideoMode, AudioMode);
        dprintk(1, "%s() Standard = %s\n",
-               __FUNCTION__,
+               __func__,
                XC5000_Standard[priv->video_standard].Name);
 
        ret = xc_write_reg(priv, XREG_VIDEO_MODE, VideoMode);
@@ -361,7 +361,7 @@ static int xc_shutdown(struct xc5000_priv *priv)
 
 static int xc_SetSignalSource(struct xc5000_priv *priv, u16 rf_mode)
 {
-       dprintk(1, "%s(%d) Source = %s\n", __FUNCTION__, rf_mode,
+       dprintk(1, "%s(%d) Source = %s\n", __func__, rf_mode,
                rf_mode == XC_RF_MODE_AIR ? "ANTENNA" : "CABLE");
 
        if ((rf_mode != XC_RF_MODE_AIR) && (rf_mode != XC_RF_MODE_CABLE))
@@ -369,7 +369,7 @@ static int xc_SetSignalSource(struct xc5000_priv *priv, u16 rf_mode)
                rf_mode = XC_RF_MODE_CABLE;
                printk(KERN_ERR
                        "%s(), Invalid mode, defaulting to CABLE",
-                       __FUNCTION__);
+                       __func__);
        }
        return xc_write_reg(priv, XREG_SIGNALSOURCE, rf_mode);
 }
@@ -380,7 +380,7 @@ static int xc_set_RF_frequency(struct xc5000_priv *priv, u32 freq_hz)
 {
        u16 freq_code;
 
-       dprintk(1, "%s(%u)\n", __FUNCTION__, freq_hz);
+       dprintk(1, "%s(%u)\n", __func__, freq_hz);
 
        if ((freq_hz > xc5000_tuner_ops.info.frequency_max) ||
                (freq_hz < xc5000_tuner_ops.info.frequency_min))
@@ -396,7 +396,7 @@ static int xc_set_IF_frequency(struct xc5000_priv *priv, u32 freq_khz)
 {
        u32 freq_code = (freq_khz * 1024)/1000;
        dprintk(1, "%s(freq_khz = %d) freq_code = 0x%x\n",
-               __FUNCTION__, freq_khz, freq_code);
+               __func__, freq_khz, freq_code);
 
        return xc_write_reg(priv, XREG_IF_OUT, freq_code);
 }
@@ -488,7 +488,7 @@ static int xc_tune_channel(struct xc5000_priv *priv, u32 freq_hz)
 {
        int found = 0;
 
-       dprintk(1, "%s(%u)\n", __FUNCTION__, freq_hz);
+       dprintk(1, "%s(%u)\n", __func__, freq_hz);
 
        if (xc_set_RF_frequency(priv, freq_hz) != XC_RESULT_SUCCESS)
                return 0;
@@ -627,12 +627,12 @@ static int xc5000_set_params(struct dvb_frontend *fe,
        struct xc5000_priv *priv = fe->tuner_priv;
        int ret;
 
-       dprintk(1, "%s() frequency=%d (Hz)\n", __FUNCTION__, params->frequency);
+       dprintk(1, "%s() frequency=%d (Hz)\n", __func__, params->frequency);
 
        switch(params->u.vsb.modulation) {
        case VSB_8:
        case VSB_16:
-               dprintk(1, "%s() VSB modulation\n", __FUNCTION__);
+               dprintk(1, "%s() VSB modulation\n", __func__);
                priv->rf_mode = XC_RF_MODE_AIR;
                priv->freq_hz = params->frequency - 1750000;
                priv->bandwidth = BANDWIDTH_6_MHZ;
@@ -641,7 +641,7 @@ static int xc5000_set_params(struct dvb_frontend *fe,
        case QAM_64:
        case QAM_256:
        case QAM_AUTO:
-               dprintk(1, "%s() QAM modulation\n", __FUNCTION__);
+               dprintk(1, "%s() QAM modulation\n", __func__);
                priv->rf_mode = XC_RF_MODE_CABLE;
                priv->freq_hz = params->frequency - 1750000;
                priv->bandwidth = BANDWIDTH_6_MHZ;
@@ -652,7 +652,7 @@ static int xc5000_set_params(struct dvb_frontend *fe,
        }
 
        dprintk(1, "%s() frequency=%d (compensated)\n",
-               __FUNCTION__, priv->freq_hz);
+               __func__, priv->freq_hz);
 
        ret = xc_SetSignalSource(priv, priv->rf_mode);
        if (ret != XC_RESULT_SUCCESS) {
@@ -697,7 +697,7 @@ static int xc5000_set_analog_params(struct dvb_frontend *fe,
                xc_load_fw_and_init_tuner(fe);
 
        dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n",
-               __FUNCTION__, params->frequency);
+               __func__, params->frequency);
 
        priv->rf_mode = XC_RF_MODE_CABLE; /* Fix me: it could be air. */
 
@@ -775,7 +775,7 @@ tune_channel:
 static int xc5000_get_frequency(struct dvb_frontend *fe, u32 *freq)
 {
        struct xc5000_priv *priv = fe->tuner_priv;
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
        *freq = priv->freq_hz;
        return 0;
 }
@@ -783,7 +783,7 @@ static int xc5000_get_frequency(struct dvb_frontend *fe, u32 *freq)
 static int xc5000_get_bandwidth(struct dvb_frontend *fe, u32 *bw)
 {
        struct xc5000_priv *priv = fe->tuner_priv;
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
 
        *bw = priv->bandwidth;
        return 0;
@@ -796,7 +796,7 @@ static int xc5000_get_status(struct dvb_frontend *fe, u32 *status)
 
        xc_get_lock_status(priv, &lock_status);
 
-       dprintk(1, "%s() lock_status = 0x%08x\n", __FUNCTION__, lock_status);
+       dprintk(1, "%s() lock_status = 0x%08x\n", __func__, lock_status);
 
        *status = lock_status;
 
@@ -836,7 +836,7 @@ static int xc5000_sleep(struct dvb_frontend *fe)
        struct xc5000_priv *priv = fe->tuner_priv;
        int ret;
 
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
 
        /* On Pinnacle PCTV HD 800i, the tuner cannot be reinitialized
         * once shutdown without reloading the driver. Maybe I am not
@@ -848,7 +848,7 @@ static int xc5000_sleep(struct dvb_frontend *fe)
        if(ret != XC_RESULT_SUCCESS) {
                printk(KERN_ERR
                        "xc5000: %s() unable to shutdown tuner\n",
-                       __FUNCTION__);
+                       __func__);
                return -EREMOTEIO;
        }
        else {
@@ -860,7 +860,7 @@ static int xc5000_sleep(struct dvb_frontend *fe)
 static int xc5000_init(struct dvb_frontend *fe)
 {
        struct xc5000_priv *priv = fe->tuner_priv;
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
 
        if (xc_load_fw_and_init_tuner(fe) != XC_RESULT_SUCCESS) {
                printk(KERN_ERR "xc5000: Unable to initialise tuner\n");
@@ -875,7 +875,7 @@ static int xc5000_init(struct dvb_frontend *fe)
 
 static int xc5000_release(struct dvb_frontend *fe)
 {
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
        kfree(fe->tuner_priv);
        fe->tuner_priv = NULL;
        return 0;
@@ -907,7 +907,7 @@ struct dvb_frontend * xc5000_attach(struct dvb_frontend *fe,
        struct xc5000_priv *priv = NULL;
        u16 id = 0;
 
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
 
        priv = kzalloc(sizeof(struct xc5000_priv), GFP_KERNEL);
        if (priv == NULL)
index 32a5f1c86a16d699eb9fb116aaaf2548462613e8..b890883a0cdc224a8f888000564b7eb4f63635bc 100644 (file)
@@ -55,7 +55,7 @@ static inline struct dvb_frontend* xc5000_attach(struct dvb_frontend *fe,
                                                 struct i2c_adapter *i2c,
                                                 struct xc5000_config *cfg)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_TUNER_XC5000
index 276e3b631dc211eedaf9612af4d48a5b04a84a80..36a5a1c101d5b91386a23796959857cabcd632df 100644 (file)
@@ -46,7 +46,7 @@ static int debug;
                if (debug) printk(KERN_DEBUG "zl10353: " args); \
        } while (0)
 
-static int debug_regs = 0;
+static int debug_regs;
 
 static int zl10353_single_write(struct dvb_frontend *fe, u8 reg, u8 val)
 {
@@ -88,7 +88,7 @@ static int zl10353_read_register(struct zl10353_state *state, u8 reg)
 
        if (ret != 2) {
                printk("%s: readreg error (reg=%d, ret==%i)\n",
-                      __FUNCTION__, reg, ret);
+                      __func__, reg, ret);
                return ret;
        }
 
@@ -152,7 +152,7 @@ static void zl10353_calc_nominal_rate(struct dvb_frontend *fe,
        *nominal_rate = value;
 
        dprintk("%s: bw %d, adc_clock %d => 0x%x\n",
-               __FUNCTION__, bw, adc_clock, *nominal_rate);
+               __func__, bw, adc_clock, *nominal_rate);
 }
 
 static void zl10353_calc_input_freq(struct dvb_frontend *fe,
@@ -181,7 +181,7 @@ static void zl10353_calc_input_freq(struct dvb_frontend *fe,
        *input_freq = -value;
 
        dprintk("%s: if2 %d, ife %d, adc_clock %d => %d / 0x%x\n",
-               __FUNCTION__, if2, ife, adc_clock, -(int)value, *input_freq);
+               __func__, if2, ife, adc_clock, -(int)value, *input_freq);
 }
 
 static int zl10353_sleep(struct dvb_frontend *fe)
index fc734c22b5fa9d8231aa723698eb43746ba1d290..fdbb88ff75fe80eebba27d7c94c67022c84e9f30 100644 (file)
@@ -47,7 +47,7 @@ extern struct dvb_frontend* zl10353_attach(const struct zl10353_config *config,
 static inline struct dvb_frontend* zl10353_attach(const struct zl10353_config *config,
                                           struct i2c_adapter *i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif /* CONFIG_DVB_ZL10353 */
index 08a2599ed74a7463293ae0e8858642fd6b495d84..960ed5763ae1300f929538210bdbb509d36c4be0 100644 (file)
@@ -39,6 +39,8 @@
 #include "dvbdev.h"
 #include "tda1004x.h"
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 #define DRIVER_NAME            "pluto2"
 
 #define REG_PIDn(n)            ((n) << 2)      /* PID n pattern registers */
@@ -662,7 +664,8 @@ static int __devinit pluto2_probe(struct pci_dev *pdev,
                goto err_pluto_hw_exit;
 
        /* dvb */
-       ret = dvb_register_adapter(&pluto->dvb_adapter, DRIVER_NAME, THIS_MODULE, &pdev->dev);
+       ret = dvb_register_adapter(&pluto->dvb_adapter, DRIVER_NAME,
+                                  THIS_MODULE, &pdev->dev, adapter_nr);
        if (ret < 0)
                goto err_i2c_del_adapter;
 
index 0e5701bdff19472bd08ec89a6b3219f9f634310e..747e7f1a6267be0a9d3d9cf4eb1d4766c97691b5 100644 (file)
@@ -112,6 +112,8 @@ MODULE_PARM_DESC(wss_cfg_16_9, "WSS 16:9 - default 0x0007 - bit 15: disable, 14:
 module_param(tv_standard, int, 0444);
 MODULE_PARM_DESC(tv_standard, "TV standard: 0 PAL (default), 1 NTSC");
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 static void restart_feeds(struct av7110 *av7110);
 
 static int av7110_num;
@@ -359,7 +361,7 @@ static inline void start_debi_dma(struct av7110 *av7110, int dir,
 {
        dprintk(8, "%c %08lx %u\n", dir == DEBI_READ ? 'R' : 'W', addr, len);
        if (saa7146_wait_for_debi_done(av7110->dev, 0)) {
-               printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __FUNCTION__);
+               printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __func__);
                return;
        }
 
@@ -497,7 +499,7 @@ static void gpioirq(unsigned long data)
                       saa7146_read(av7110->dev, SSR));
 
        if (saa7146_wait_for_debi_done(av7110->dev, 0)) {
-               printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __FUNCTION__);
+               printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __func__);
                BUG(); /* maybe we should try resetting the debi? */
        }
 
@@ -827,7 +829,7 @@ static int StartHWFilter(struct dvb_demux_filter *dvbdmxfilter)
        if (ret != 0 || handle >= 32) {
                printk("dvb-ttpci: %s error  buf %04x %04x %04x %04x  "
                                "ret %d  handle %04x\n",
-                               __FUNCTION__, buf[0], buf[1], buf[2], buf[3],
+                               __func__, buf[0], buf[1], buf[2], buf[3],
                                ret, handle);
                dvbdmxfilter->hw_handle = 0xffff;
                if (!ret)
@@ -854,7 +856,7 @@ static int StopHWFilter(struct dvb_demux_filter *dvbdmxfilter)
        handle = dvbdmxfilter->hw_handle;
        if (handle >= 32) {
                printk("%s tried to stop invalid filter %04x, filter type = %x\n",
-                               __FUNCTION__, handle, dvbdmxfilter->type);
+                               __func__, handle, dvbdmxfilter->type);
                return -EINVAL;
        }
 
@@ -867,7 +869,7 @@ static int StopHWFilter(struct dvb_demux_filter *dvbdmxfilter)
        if (ret != 0 || answ[1] != handle) {
                printk("dvb-ttpci: %s error  cmd %04x %04x %04x  ret %x  "
                                "resp %04x %04x  pid %d\n",
-                               __FUNCTION__, buf[0], buf[1], buf[2], ret,
+                               __func__, buf[0], buf[1], buf[2], ret,
                                answ[0], answ[1], dvbdmxfilter->feed->pid);
                if (!ret)
                        ret = -1;
@@ -1122,7 +1124,7 @@ static int dvb_get_stc(struct dmx_demux *demux, unsigned int num,
 
        ret = av7110_fw_request(av7110, &tag, 0, fwstc, 4);
        if (ret) {
-               printk(KERN_ERR "%s: av7110_fw_request error\n", __FUNCTION__);
+               printk(KERN_ERR "%s: av7110_fw_request error\n", __func__);
                return ret;
        }
        dprintk(2, "fwstc = %04hx %04hx %04hx %04hx\n",
@@ -2461,7 +2463,7 @@ static int __devinit av7110_attach(struct saa7146_dev* dev,
                goto err_kfree_0;
 
        ret = dvb_register_adapter(&av7110->dvb_adapter, av7110->card_name,
-                                  THIS_MODULE, &dev->pci->dev);
+                                  THIS_MODULE, &dev->pci->dev, adapter_nr);
        if (ret < 0)
                goto err_put_firmware_1;
 
index 39fbf7d5cffbca70e6abcada285ec0d176147783..e494e04eeee8fb7b8ac2922cbfb8e90d4e0c211c 100644 (file)
@@ -40,7 +40,7 @@
 extern int av7110_debug;
 
 #define dprintk(level,args...) \
-           do { if ((av7110_debug & level)) { printk("dvb-ttpci: %s(): ", __FUNCTION__); printk(args); } } while (0)
+           do { if ((av7110_debug & level)) { printk("dvb-ttpci: %s(): ", __func__); printk(args); } } while (0)
 
 #define MAXFILT 32
 
index a468aa2e485475ba5583765b0e643781943f4ae1..9d81074b31dfe7b2b3ca105234f3d518c2c8d3d8 100644 (file)
@@ -53,11 +53,11 @@ int av7110_debiwrite(struct av7110 *av7110, u32 config,
        struct saa7146_dev *dev = av7110->dev;
 
        if (count <= 0 || count > 32764) {
-               printk("%s: invalid count %d\n", __FUNCTION__, count);
+               printk("%s: invalid count %d\n", __func__, count);
                return -1;
        }
        if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) {
-               printk("%s: wait_for_debi_done failed\n", __FUNCTION__);
+               printk("%s: wait_for_debi_done failed\n", __func__);
                return -1;
        }
        saa7146_write(dev, DEBI_CONFIG, config);
@@ -76,11 +76,11 @@ u32 av7110_debiread(struct av7110 *av7110, u32 config, int addr, int count)
        u32 result = 0;
 
        if (count > 32764 || count <= 0) {
-               printk("%s: invalid count %d\n", __FUNCTION__, count);
+               printk("%s: invalid count %d\n", __func__, count);
                return 0;
        }
        if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) {
-               printk("%s: wait_for_debi_done #1 failed\n", __FUNCTION__);
+               printk("%s: wait_for_debi_done #1 failed\n", __func__);
                return 0;
        }
        saa7146_write(dev, DEBI_AD, av7110->debi_bus);
@@ -91,7 +91,7 @@ u32 av7110_debiread(struct av7110 *av7110, u32 config, int addr, int count)
        if (count > 4)
                return count;
        if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) {
-               printk("%s: wait_for_debi_done #2 failed\n", __FUNCTION__);
+               printk("%s: wait_for_debi_done #2 failed\n", __func__);
                return 0;
        }
 
@@ -332,7 +332,7 @@ int av7110_wait_msgstate(struct av7110 *av7110, u16 flags)
                        break;
                if (err) {
                        printk(KERN_ERR "%s: timeout waiting for MSGSTATE %04x\n",
-                               __FUNCTION__, stat & flags);
+                               __func__, stat & flags);
                        return -ETIMEDOUT;
                }
                msleep(1);
@@ -362,7 +362,7 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
                if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0)
                        break;
                if (err) {
-                       printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __FUNCTION__);
+                       printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __func__);
                        av7110->arm_errors++;
                        return -ETIMEDOUT;
                }
@@ -379,7 +379,7 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
                if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0)
                        break;
                if (err) {
-                       printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for HANDSHAKE_REG\n", __FUNCTION__);
+                       printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for HANDSHAKE_REG\n", __func__);
                        return -ETIMEDOUT;
                }
                msleep(1);
@@ -419,14 +419,14 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
                        stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
                        if (stat & flags[0]) {
                                printk(KERN_ERR "%s: %s QUEUE overflow\n",
-                                       __FUNCTION__, type);
+                                       __func__, type);
                                return -1;
                        }
                        if ((stat & flags[1]) == 0)
                                break;
                        if (err) {
                                printk(KERN_ERR "%s: timeout waiting on busy %s QUEUE\n",
-                                       __FUNCTION__, type);
+                                       __func__, type);
                                return -ETIMEDOUT;
                        }
                        msleep(1);
@@ -454,7 +454,7 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
                        break;
                if (err) {
                        printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND %d to complete\n",
-                              __FUNCTION__, (buf[0] >> 8) & 0xff);
+                              __func__, (buf[0] >> 8) & 0xff);
                        return -ETIMEDOUT;
                }
                msleep(1);
@@ -462,11 +462,11 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
 
        stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
        if (stat & GPMQOver) {
-               printk(KERN_ERR "dvb-ttpci: %s(): GPMQOver\n", __FUNCTION__);
+               printk(KERN_ERR "dvb-ttpci: %s(): GPMQOver\n", __func__);
                return -ENOSPC;
        }
        else if (stat & OSDQOver) {
-               printk(KERN_ERR "dvb-ttpci: %s(): OSDQOver\n", __FUNCTION__);
+               printk(KERN_ERR "dvb-ttpci: %s(): OSDQOver\n", __func__);
                return -ENOSPC;
        }
 #endif
@@ -491,7 +491,7 @@ static int av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
        mutex_unlock(&av7110->dcomlock);
        if (ret && ret!=-ERESTARTSYS)
                printk(KERN_ERR "dvb-ttpci: %s(): av7110_send_fw_cmd error %d\n",
-                      __FUNCTION__, ret);
+                      __func__, ret);
        return ret;
 }
 
@@ -575,7 +575,7 @@ int av7110_fw_request(struct av7110 *av7110, u16 *request_buf,
                if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0)
                        break;
                if (err) {
-                       printk(KERN_ERR "%s: timeout waiting for COMMAND to complete\n", __FUNCTION__);
+                       printk(KERN_ERR "%s: timeout waiting for COMMAND to complete\n", __func__);
                        mutex_unlock(&av7110->dcomlock);
                        return -ETIMEDOUT;
                }
@@ -591,7 +591,7 @@ int av7110_fw_request(struct av7110 *av7110, u16 *request_buf,
                if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0)
                        break;
                if (err) {
-                       printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n", __FUNCTION__);
+                       printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n", __func__);
                        mutex_unlock(&av7110->dcomlock);
                        return -ETIMEDOUT;
                }
@@ -602,12 +602,12 @@ int av7110_fw_request(struct av7110 *av7110, u16 *request_buf,
 #ifdef COM_DEBUG
        stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
        if (stat & GPMQOver) {
-               printk(KERN_ERR "%s: GPMQOver\n", __FUNCTION__);
+               printk(KERN_ERR "%s: GPMQOver\n", __func__);
                mutex_unlock(&av7110->dcomlock);
                return -1;
        }
        else if (stat & OSDQOver) {
-               printk(KERN_ERR "%s: OSDQOver\n", __FUNCTION__);
+               printk(KERN_ERR "%s: OSDQOver\n", __func__);
                mutex_unlock(&av7110->dcomlock);
                return -1;
        }
@@ -741,7 +741,7 @@ static int FlushText(struct av7110 *av7110)
                        break;
                if (err) {
                        printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for BUFF1_BASE == 0\n",
-                              __FUNCTION__);
+                              __func__);
                        mutex_unlock(&av7110->dcomlock);
                        return -ETIMEDOUT;
                }
@@ -768,7 +768,7 @@ static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, char *buf)
                        break;
                if (ret) {
                        printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for BUFF1_BASE == 0\n",
-                              __FUNCTION__);
+                              __func__);
                        mutex_unlock(&av7110->dcomlock);
                        return -ETIMEDOUT;
                }
@@ -782,7 +782,7 @@ static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, char *buf)
                        break;
                if (ret) {
                        printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for HANDSHAKE_REG\n",
-                              __FUNCTION__);
+                              __func__);
                        mutex_unlock(&av7110->dcomlock);
                        return -ETIMEDOUT;
                }
index a283e1de83facf6edc5ebae02b6ae232d477b885..23a1c6380d3f22964ef98ead022c3b3442901536 100644 (file)
@@ -133,7 +133,7 @@ static void av7110_emit_key(unsigned long parm)
                break;
 
        default:
-               printk("%s invalid protocol %x\n", __FUNCTION__, ir->protocol);
+               printk("%s invalid protocol %x\n", __func__, ir->protocol);
                return;
        }
 
@@ -143,7 +143,7 @@ static void av7110_emit_key(unsigned long parm)
        keycode = ir->key_map[data];
 
        dprintk(16, "%s: code %08x -> addr %i data 0x%02x -> keycode %i\n",
-               __FUNCTION__, ircom, addr, data, keycode);
+               __func__, ircom, addr, data, keycode);
 
        /* check device address */
        if (!(ir->device_mask & (1 << addr)))
@@ -151,7 +151,7 @@ static void av7110_emit_key(unsigned long parm)
 
        if (!keycode) {
                printk ("%s: code %08x -> addr %i data 0x%02x -> unknown key!\n",
-                       __FUNCTION__, ircom, addr, data);
+                       __func__, ircom, addr, data);
                return;
        }
 
index e2f066fb796727c1f0f7bf1c8196a562d25c1839..b4a0cc5dc935ffec2c9310385c7816d1e24f40a4 100644 (file)
@@ -573,7 +573,7 @@ static int av7110_vbi_reset(struct inode *inode, struct file *file)
        struct saa7146_dev *dev = fh->dev;
        struct av7110 *av7110 = (struct av7110*) dev->ext_priv;
 
-       dprintk(2, "%s\n", __FUNCTION__);
+       dprintk(2, "%s\n", __func__);
        av7110->wssMode = 0;
        av7110->wssData = 0;
        if (FW_VERSION(av7110->arm_app) < 0x2623)
@@ -590,7 +590,7 @@ static ssize_t av7110_vbi_write(struct file *file, const char __user *data, size
        struct v4l2_sliced_vbi_data d;
        int rc;
 
-       dprintk(2, "%s\n", __FUNCTION__);
+       dprintk(2, "%s\n", __func__);
        if (FW_VERSION(av7110->arm_app) < 0x2623 || !av7110->wssMode || count != sizeof d)
                return -EINVAL;
        if (copy_from_user(&d, data, count))
index 2d64d557b9770f3d13b8fd3ccf8add46ac7c66aa..b30a5288e484fb837e2985c41180be506de01a8b 100644 (file)
@@ -178,7 +178,7 @@ static int ciintf_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 addre
        udelay(1);
 
        result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 3, 1, 0, 0);
-       if ((result == -ETIMEDOUT) || ((result == 0xff) && ((address & 3) < 2))) {
+       if (result == -ETIMEDOUT) {
                ciintf_slot_shutdown(ca, slot);
                printk(KERN_INFO "budget-av: cam ejected 3\n");
                return -ETIMEDOUT;
@@ -577,7 +577,7 @@ static struct stv0299_config typhoon_config = {
        .mclk = 88000000UL,
        .invert = 0,
        .skip_reinit = 0,
-       .lock_output = STV0229_LOCKOUTPUT_1,
+       .lock_output = STV0299_LOCKOUTPUT_1,
        .volt13_op0_op1 = STV0299_VOLT13_OP0,
        .min_delay_ms = 100,
        .set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
@@ -590,7 +590,7 @@ static struct stv0299_config cinergy_1200s_config = {
        .mclk = 88000000UL,
        .invert = 0,
        .skip_reinit = 0,
-       .lock_output = STV0229_LOCKOUTPUT_0,
+       .lock_output = STV0299_LOCKOUTPUT_0,
        .volt13_op0_op1 = STV0299_VOLT13_OP0,
        .min_delay_ms = 100,
        .set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
@@ -602,7 +602,7 @@ static struct stv0299_config cinergy_1200s_1894_0010_config = {
        .mclk = 88000000UL,
        .invert = 1,
        .skip_reinit = 0,
-       .lock_output = STV0229_LOCKOUTPUT_1,
+       .lock_output = STV0299_LOCKOUTPUT_1,
        .volt13_op0_op1 = STV0299_VOLT13_OP0,
        .min_delay_ms = 100,
        .set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
@@ -869,7 +869,7 @@ static struct stv0299_config philips_sd1878_config = {
        .mclk = 88000000UL,
        .invert = 0,
        .skip_reinit = 0,
-       .lock_output = STV0229_LOCKOUTPUT_1,
+       .lock_output = STV0299_LOCKOUTPUT_1,
        .volt13_op0_op1 = STV0299_VOLT13_OP0,
        .min_delay_ms = 100,
        .set_symbol_rate = philips_sd1878_ci_set_symbol_rate,
@@ -941,6 +941,12 @@ static void frontend_init(struct budget_av *budget_av)
        switch (saa->pci->subsystem_device) {
 
        case SUBID_DVBS_KNC1:
+               /*
+                * maybe that setting is needed for other dvb-s cards as well,
+                * but so far it has been only confirmed for this type
+                */
+               budget_av->reinitialise_demod = 1;
+               /* fall through */
        case SUBID_DVBS_KNC1_PLUS:
        case SUBID_DVBS_EASYWATCH_1:
                if (saa->pci->subsystem_vendor == 0x1894) {
index 509349211d4fc40594fb99a27980eeed2ae66e31..6530323d540617259db6c46f4bc7150d3b9858d1 100644 (file)
@@ -86,7 +86,7 @@ static int rc5_device = -1;
 module_param(rc5_device, int, 0644);
 MODULE_PARM_DESC(rc5_device, "only IR commands to given RC5 device (device = 0 - 31, any device = 255, default: autodetect)");
 
-static int ir_debug = 0;
+static int ir_debug;
 module_param(ir_debug, int, 0644);
 MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding");
 
@@ -728,7 +728,7 @@ static struct stv0299_config philips_su1278_tt_config = {
        .mclk = 64000000UL,
        .invert = 0,
        .skip_reinit = 1,
-       .lock_output = STV0229_LOCKOUTPUT_1,
+       .lock_output = STV0299_LOCKOUTPUT_1,
        .volt13_op0_op1 = STV0299_VOLT13_OP1,
        .min_delay_ms = 50,
        .set_symbol_rate = philips_su1278_tt_set_symbol_rate,
@@ -1121,7 +1121,7 @@ static void frontend_init(struct budget_ci *budget_ci)
 
                        budget_ci->budget.dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
                        if (dvb_attach(lnbp21_attach, budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, LNBP21_LLC, 0) == NULL) {
-                               printk("%s: No LNBP21 found!\n", __FUNCTION__);
+                               printk("%s: No LNBP21 found!\n", __func__);
                                dvb_frontend_detach(budget_ci->budget.dvb_frontend);
                                budget_ci->budget.dvb_frontend = NULL;
                        }
index 0252081f013c56d86d3217d37c5a586f67c7da6e..18cac4b12ab28f73fb97a25f219788438b703bee 100644 (file)
@@ -57,6 +57,8 @@ module_param_named(bufsize, dma_buffer_size, int, 0444);
 MODULE_PARM_DESC(debug, "Turn on/off budget debugging (default:off).");
 MODULE_PARM_DESC(bufsize, "DMA buffer size in KB, default: 188, min: 188, max: 1410 (Activy: 564)");
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 /****************************************************************************
  * TT budget / WinTV Nova
  ****************************************************************************/
@@ -223,7 +225,7 @@ static void vpeirq(unsigned long data)
 
        if (budget->buffer_warnings && time_after(jiffies, budget->buffer_warning_time)) {
                printk("%s %s: used %d times >80%% of buffer (%u bytes now)\n",
-                       budget->dev->name, __FUNCTION__, budget->buffer_warnings, count);
+                       budget->dev->name, __func__, budget->buffer_warnings, count);
                budget->buffer_warning_time = jiffies + BUFFER_WARNING_WAIT;
                budget->buffer_warnings = 0;
        }
@@ -471,9 +473,10 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
                budget->buffer_width, budget->buffer_height);
        printk("%s: dma buffer size %u\n", budget->dev->name, budget->buffer_size);
 
-       if ((ret = dvb_register_adapter(&budget->dvb_adapter, budget->card->name, owner, &budget->dev->pci->dev)) < 0) {
+       ret = dvb_register_adapter(&budget->dvb_adapter, budget->card->name,
+                                  owner, &budget->dev->pci->dev, adapter_nr);
+       if (ret < 0)
                return ret;
-       }
 
        /* set dd1 stream a & b */
        saa7146_write(dev, DD1_STREAM_B, 0x00000000);
index 14b00f57b5de80ce18d57211dd5c6b9e8c6179da..2293d80c6e5131fcad7feed54d7823581571ac65 100644 (file)
@@ -45,6 +45,7 @@
 #include "tda826x.h"
 #include "lnbp21.h"
 #include "bsru6.h"
+#include "bsbe1.h"
 
 static int diseqc_method;
 module_param(diseqc_method, int, 0444);
@@ -257,11 +258,17 @@ static struct ves1820_config alps_tdbe2_config = {
 
 static int grundig_29504_401_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
 {
-       struct budget* budget = (struct budget*) fe->dvb->priv;
+       struct budget *budget = fe->dvb->priv;
+       u8 *tuner_addr = fe->tuner_priv;
        u32 div;
        u8 cfg, cpump, band_select;
        u8 data[4];
-       struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
+       struct i2c_msg msg = { .flags = 0, .buf = data, .len = sizeof(data) };
+
+       if (tuner_addr)
+               msg.addr = *tuner_addr;
+       else
+               msg.addr = 0x61;
 
        div = (36125000 + params->frequency) / 166666;
 
@@ -292,6 +299,12 @@ static struct l64781_config grundig_29504_401_config = {
        .demod_address = 0x55,
 };
 
+static struct l64781_config grundig_29504_401_config_activy = {
+       .demod_address = 0x54,
+};
+
+static u8 tuner_address_grundig_29504_401_activy = 0x60;
+
 static int grundig_29504_451_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
 {
        struct budget* budget = (struct budget*) fe->dvb->priv;
@@ -346,14 +359,48 @@ static int s5h1420_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend
 static struct s5h1420_config s5h1420_config = {
        .demod_address = 0x53,
        .invert = 1,
+       .cdclk_polarity = 1,
 };
 
 static struct tda10086_config tda10086_config = {
        .demod_address = 0x0e,
        .invert = 0,
        .diseqc_tone = 1,
+       .xtal_freq = TDA10086_XTAL_16M,
 };
 
+static struct stv0299_config alps_bsru6_config_activy = {
+       .demod_address = 0x68,
+       .inittab = alps_bsru6_inittab,
+       .mclk = 88000000UL,
+       .invert = 1,
+       .op0_off = 1,
+       .min_delay_ms = 100,
+       .set_symbol_rate = alps_bsru6_set_symbol_rate,
+};
+
+static struct stv0299_config alps_bsbe1_config_activy = {
+       .demod_address = 0x68,
+       .inittab = alps_bsbe1_inittab,
+       .mclk = 88000000UL,
+       .invert = 1,
+       .op0_off = 1,
+       .min_delay_ms = 100,
+       .set_symbol_rate = alps_bsbe1_set_symbol_rate,
+};
+
+
+static int i2c_readreg(struct i2c_adapter *i2c, u8 adr, u8 reg)
+{
+       u8 val;
+       struct i2c_msg msg[] = {
+               { .addr = adr, .flags = 0, .buf = &reg, .len = 1 },
+               { .addr = adr, .flags = I2C_M_RD, .buf = &val, .len = 1 }
+       };
+
+       return (i2c_transfer(i2c, msg, 2) != 2) ? -EIO : val;
+}
+
 static u8 read_pwm(struct budget* budget)
 {
        u8 b = 0xff;
@@ -369,6 +416,8 @@ static u8 read_pwm(struct budget* budget)
 
 static void frontend_init(struct budget *budget)
 {
+       (void)alps_bsbe1_config; /* avoid warning */
+
        switch(budget->dev->pci->subsystem_device) {
        case 0x1003: // Hauppauge/TT Nova budget (stv0299/ALPS BSRU6(tsa5059) OR ves1893/ALPS BSRV2(sp5659))
        case 0x1013:
@@ -414,15 +463,43 @@ static void frontend_init(struct budget *budget)
                }
                break;
 
-       case 0x4f60: // Fujitsu Siemens Activy Budget-S PCI rev AL (stv0299/ALPS BSRU6(tsa5059))
-               budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsru6_config, &budget->i2c_adap);
-               if (budget->dvb_frontend) {
-                       budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
-                       budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
-                       budget->dvb_frontend->ops.set_voltage = siemens_budget_set_voltage;
-                       budget->dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
+       case 0x4f60: /* Fujitsu Siemens Activy Budget-S PCI rev AL (stv0299/tsa5059) */
+       {
+               int subtype = i2c_readreg(&budget->i2c_adap, 0x50, 0x67);
+
+               if (subtype < 0)
+                       break;
+               /* fixme: find a better way to identify the card */
+               if (subtype < 0x36) {
+                       /* assume ALPS BSRU6 */
+                       budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsru6_config_activy, &budget->i2c_adap);
+                       if (budget->dvb_frontend) {
+                               printk(KERN_INFO "budget: tuner ALPS BSRU6 detected\n");
+                               budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
+                               budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
+                               budget->dvb_frontend->ops.set_voltage = siemens_budget_set_voltage;
+                               budget->dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
+                               break;
+                       }
+               } else {
+                       /* assume ALPS BSBE1 */
+                       /* reset tuner */
+                       saa7146_setgpio(budget->dev, 3, SAA7146_GPIO_OUTLO);
+                       msleep(50);
+                       saa7146_setgpio(budget->dev, 3, SAA7146_GPIO_OUTHI);
+                       msleep(250);
+                       budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsbe1_config_activy, &budget->i2c_adap);
+                       if (budget->dvb_frontend) {
+                               printk(KERN_INFO "budget: tuner ALPS BSBE1 detected\n");
+                               budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;
+                               budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
+                               budget->dvb_frontend->ops.set_voltage = siemens_budget_set_voltage;
+                               budget->dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
+                               break;
+                       }
                }
                break;
+       }
 
        case 0x4f61: // Fujitsu Siemens Activy Budget-S PCI rev GR (tda8083/Grundig 29504-451(tsa5522))
                budget->dvb_frontend = dvb_attach(tda8083_attach, &grundig_29504_451_config, &budget->i2c_adap);
@@ -433,12 +510,20 @@ static void frontend_init(struct budget *budget)
                }
                break;
 
+       case 0x5f61: /* Fujitsu Siemens Activy Budget-T PCI rev GR (L64781/Grundig 29504-401(tsa5060)) */
+               budget->dvb_frontend = dvb_attach(l64781_attach, &grundig_29504_401_config_activy, &budget->i2c_adap);
+               if (budget->dvb_frontend) {
+                       budget->dvb_frontend->tuner_priv = &tuner_address_grundig_29504_401_activy;
+                       budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params;
+               }
+               break;
+
        case 0x1016: // Hauppauge/TT Nova-S SE (samsung s5h1420/????(tda8260))
                budget->dvb_frontend = dvb_attach(s5h1420_attach, &s5h1420_config, &budget->i2c_adap);
                if (budget->dvb_frontend) {
                        budget->dvb_frontend->ops.tuner_ops.set_params = s5h1420_tuner_set_params;
                        if (dvb_attach(lnbp21_attach, budget->dvb_frontend, &budget->i2c_adap, 0, 0) == NULL) {
-                               printk("%s: No LNBP21 found!\n", __FUNCTION__);
+                               printk("%s: No LNBP21 found!\n", __func__);
                                goto error_out;
                        }
                        break;
@@ -454,9 +539,9 @@ static void frontend_init(struct budget *budget)
                budget->dvb_frontend = dvb_attach(tda10086_attach, &tda10086_config, &budget->i2c_adap);
                if (budget->dvb_frontend) {
                        if (dvb_attach(tda826x_attach, budget->dvb_frontend, 0x60, &budget->i2c_adap, 0) == NULL)
-                               printk("%s: No tda826x found!\n", __FUNCTION__);
+                               printk("%s: No tda826x found!\n", __func__);
                        if (dvb_attach(lnbp21_attach, budget->dvb_frontend, &budget->i2c_adap, 0, 0) == NULL) {
-                               printk("%s: No LNBP21 found!\n", __FUNCTION__);
+                               printk("%s: No LNBP21 found!\n", __func__);
                                goto error_out;
                        }
                        break;
@@ -537,6 +622,7 @@ MAKE_BUDGET_INFO(satel,     "SATELCO Multimedia PCI",       BUDGET_TT_HW_DISEQC);
 MAKE_BUDGET_INFO(ttbs1401, "TT-Budget-S-1401 PCI", BUDGET_TT);
 MAKE_BUDGET_INFO(fsacs0, "Fujitsu Siemens Activy Budget-S PCI (rev GR/grundig frontend)", BUDGET_FS_ACTIVY);
 MAKE_BUDGET_INFO(fsacs1, "Fujitsu Siemens Activy Budget-S PCI (rev AL/alps frontend)", BUDGET_FS_ACTIVY);
+MAKE_BUDGET_INFO(fsact,         "Fujitsu Siemens Activy Budget-T PCI (rev GR/Grundig frontend)", BUDGET_FS_ACTIVY);
 
 static struct pci_device_id pci_tbl[] = {
        MAKE_EXTENSION_PCI(ttbs,  0x13c2, 0x1003),
@@ -547,6 +633,7 @@ static struct pci_device_id pci_tbl[] = {
        MAKE_EXTENSION_PCI(ttbs1401, 0x13c2, 0x1018),
        MAKE_EXTENSION_PCI(fsacs1,0x1131, 0x4f60),
        MAKE_EXTENSION_PCI(fsacs0,0x1131, 0x4f61),
+       MAKE_EXTENSION_PCI(fsact, 0x1131, 0x5f61),
        {
                .vendor    = 0,
        }
index d764ffa728b0c48bfc1ba5864d529d72803b1dfe..dd450b739bff9bb21d56c2bc8d2dae3d6c4dab54 100644 (file)
@@ -1,3 +1,4 @@
+
 #ifndef __BUDGET_DVB__
 #define __BUDGET_DVB__
 
@@ -21,7 +22,7 @@ extern int budget_debug;
 #endif
 
 #define dprintk(level,args...) \
-           do { if ((budget_debug & level)) { printk("%s: %s(): ", KBUILD_MODNAME, __FUNCTION__); printk(args); } } while (0)
+           do { if ((budget_debug & level)) { printk("%s: %s(): ", KBUILD_MODNAME, __func__); printk(args); } } while (0)
 
 struct budget_info {
        char *name;
index 1f31e91195b0c6817718d5ca4f6658247064416f..7dd54b3026a251c9eb4ba7fbd69dc71fbdd8edb1 100644 (file)
@@ -95,7 +95,7 @@ static int ttpci_eeprom_read_encodedMAC(struct i2c_adapter *adapter, u8 * encode
                { .addr = 0x50, .flags = I2C_M_RD, .buf = encodedMAC, .len = 20 }
        };
 
-       /* dprintk("%s\n", __FUNCTION__); */
+       /* dprintk("%s\n", __func__); */
 
        ret = i2c_transfer(adapter, msg, 2);
 
index 7902ae1d9a181c80e205eac147fdb92d3f704ee4..732ce4de512eaa392e12151150adb7c7940a19cf 100644 (file)
 */
 
 static int debug;
-
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 #define dprintk(x...) do { if (debug) printk(KERN_DEBUG x); } while (0)
 
 #define ISO_BUF_COUNT      4
@@ -153,12 +154,12 @@ static int ttusb_cmd(struct ttusb *ttusb,
                           (u8 *) data, len, &actual_len, 1000);
        if (err != 0) {
                dprintk("%s: usb_bulk_msg(send) failed, err == %i!\n",
-                       __FUNCTION__, err);
+                       __func__, err);
                mutex_unlock(&ttusb->semusb);
                return err;
        }
        if (actual_len != len) {
-               dprintk("%s: only wrote %d of %d bytes\n", __FUNCTION__,
+               dprintk("%s: only wrote %d of %d bytes\n", __func__,
                        actual_len, len);
                mutex_unlock(&ttusb->semusb);
                return -1;
@@ -168,7 +169,7 @@ static int ttusb_cmd(struct ttusb *ttusb,
                           ttusb->last_result, 32, &actual_len, 1000);
 
        if (err != 0) {
-               printk("%s: failed, receive error %d\n", __FUNCTION__,
+               printk("%s: failed, receive error %d\n", __func__,
                       err);
                mutex_unlock(&ttusb->semusb);
                return err;
@@ -229,7 +230,7 @@ static int ttusb_i2c_msg(struct ttusb *ttusb,
                if (err || b[0] != 0x55 || b[1] != id) {
                        dprintk
                            ("%s: usb_bulk_msg(recv) failed, err == %i, id == %02x, b == ",
-                            __FUNCTION__, err, id);
+                            __func__, err, id);
                        return -EREMOTEIO;
                }
 
@@ -273,7 +274,7 @@ static int master_xfer(struct i2c_adapter* adapter, struct i2c_msg *msg, int num
                                    snd_buf, snd_len, rcv_buf, rcv_len);
 
                if (err < rcv_len) {
-                       dprintk("%s: i == %i\n", __FUNCTION__, i);
+                       dprintk("%s: i == %i\n", __func__, i);
                        break;
                }
 
@@ -327,7 +328,7 @@ static int ttusb_boot_dsp(struct ttusb *ttusb)
       done:
        if (err) {
                dprintk("%s: usb_bulk_msg() failed, return value %i!\n",
-                       __FUNCTION__, err);
+                       __func__, err);
        }
 
        return err;
@@ -427,7 +428,7 @@ static int ttusb_init_controller(struct ttusb *ttusb)
        if ((err = ttusb_result(ttusb, get_version, sizeof(get_version))))
                return err;
 
-       dprintk("%s: stc-version: %c%c%c%c%c\n", __FUNCTION__,
+       dprintk("%s: stc-version: %c%c%c%c%c\n", __func__,
                get_version[4], get_version[5], get_version[6],
                get_version[7], get_version[8]);
 
@@ -437,7 +438,7 @@ static int ttusb_init_controller(struct ttusb *ttusb)
            memcmp(get_version + 4, "V 2.2", 5)) {
                printk
                    ("%s: unknown STC version %c%c%c%c%c, please report!\n",
-                    __FUNCTION__, get_version[4], get_version[5],
+                    __func__, get_version[4], get_version[5],
                     get_version[6], get_version[7], get_version[8]);
        }
 
@@ -453,7 +454,7 @@ static int ttusb_init_controller(struct ttusb *ttusb)
            ttusb_result(ttusb, get_dsp_version, sizeof(get_dsp_version));
        if (err)
                return err;
-       printk("%s: dsp-version: %c%c%c\n", __FUNCTION__,
+       printk("%s: dsp-version: %c%c%c\n", __func__,
               get_dsp_version[4], get_dsp_version[5], get_dsp_version[6]);
        return 0;
 }
@@ -476,7 +477,7 @@ static int ttusb_send_diseqc(struct dvb_frontend* fe,
        /* Diseqc */
        if ((err = ttusb_cmd(ttusb, b, 4 + b[3], 0))) {
                dprintk("%s: usb_bulk_msg() failed, return value %i!\n",
-                       __FUNCTION__, err);
+                       __func__, err);
        }
 
        return err;
@@ -494,7 +495,7 @@ static int ttusb_update_lnb(struct ttusb *ttusb)
        /* SetLNB */
        if ((err = ttusb_cmd(ttusb, b, sizeof(b), 0))) {
                dprintk("%s: usb_bulk_msg() failed, return value %i!\n",
-                       __FUNCTION__, err);
+                       __func__, err);
        }
 
        return err;
@@ -528,7 +529,7 @@ static void ttusb_set_led_freq(struct ttusb *ttusb, u8 freq)
        err = ttusb_cmd(ttusb, b, sizeof(b), 0);
        if (err) {
                dprintk("%s: usb_bulk_msg() failed, return value %i!\n",
-                       __FUNCTION__, err);
+                       __func__, err);
        }
 }
 #endif
@@ -542,7 +543,7 @@ static void ttusb_handle_sec_data(struct ttusb_channel *channel,
                                  const u8 * data, int len);
 #endif
 
-static int numpkt = 0, numts, numstuff, numsec, numinvalid;
+static int numpkt, numts, numstuff, numsec, numinvalid;
 static unsigned long lastj;
 
 static void ttusb_process_muxpack(struct ttusb *ttusb, const u8 * muxpack,
@@ -554,7 +555,7 @@ static void ttusb_process_muxpack(struct ttusb *ttusb, const u8 * muxpack,
                csum ^= le16_to_cpup((u16 *) (muxpack + i));
        if (csum) {
                printk("%s: muxpack with incorrect checksum, ignoring\n",
-                      __FUNCTION__);
+                      __func__);
                numinvalid++;
                return;
        }
@@ -563,7 +564,7 @@ static void ttusb_process_muxpack(struct ttusb *ttusb, const u8 * muxpack,
        cc &= 0x7FFF;
        if ((cc != ttusb->cc) && (ttusb->cc != -1))
                printk("%s: cc discontinuity (%d frames missing)\n",
-                      __FUNCTION__, (cc - ttusb->cc) & 0x7FFF);
+                      __func__, (cc - ttusb->cc) & 0x7FFF);
        ttusb->cc = (cc + 1) & 0x7FFF;
        if (muxpack[0] & 0x80) {
 #ifdef TTUSB_HWSECTIONS
@@ -613,7 +614,7 @@ static void ttusb_process_frame(struct ttusb *ttusb, u8 * data, int len)
        int maxwork = 1024;
        while (len) {
                if (!(maxwork--)) {
-                       printk("%s: too much work\n", __FUNCTION__);
+                       printk("%s: too much work\n", __func__);
                        break;
                }
 
@@ -632,7 +633,7 @@ static void ttusb_process_frame(struct ttusb *ttusb, u8 * data, int len)
 #else
                                if (ttusb->insync) {
                                        printk("%s: lost sync.\n",
-                                              __FUNCTION__);
+                                              __func__);
                                        ttusb->insync = 0;
                                }
 #endif
@@ -691,7 +692,7 @@ static void ttusb_process_frame(struct ttusb *ttusb, u8 * data, int len)
                                        else {
                                                dprintk
                                                    ("%s: invalid state: first byte is %x\n",
-                                                    __FUNCTION__,
+                                                    __func__,
                                                     ttusb->muxpack[0]);
                                                ttusb->mux_state = 0;
                                        }
@@ -740,7 +741,7 @@ static void ttusb_iso_irq(struct urb *urb)
 
 #if 0
        printk("%s: status %d, errcount == %d, length == %i\n",
-              __FUNCTION__,
+              __func__,
               urb->status, urb->error_count, urb->actual_length);
 #endif
 
@@ -833,7 +834,7 @@ static int ttusb_start_iso_xfer(struct ttusb *ttusb)
        int i, j, err, buffer_offset = 0;
 
        if (ttusb->iso_streaming) {
-               printk("%s: iso xfer already running!\n", __FUNCTION__);
+               printk("%s: iso xfer already running!\n", __func__);
                return 0;
        }
 
@@ -869,7 +870,7 @@ static int ttusb_start_iso_xfer(struct ttusb *ttusb)
                        ttusb_stop_iso_xfer(ttusb);
                        printk
                            ("%s: failed urb submission (%i: err = %i)!\n",
-                            __FUNCTION__, i, err);
+                            __func__, i, err);
                        return err;
                }
        }
@@ -1005,7 +1006,7 @@ static int stc_release(struct inode *inode, struct file *file)
        return 0;
 }
 
-static struct file_operations stc_fops = {
+static const struct file_operations stc_fops = {
        .owner = THIS_MODULE,
        .read = stc_read,
        .open = stc_open,
@@ -1313,7 +1314,7 @@ static struct stv0299_config alps_stv0299_config = {
        .mclk = 88000000UL,
        .invert = 1,
        .skip_reinit = 0,
-       .lock_output = STV0229_LOCKOUTPUT_1,
+       .lock_output = STV0299_LOCKOUTPUT_1,
        .volt13_op0_op1 = STV0299_VOLT13_OP1,
        .min_delay_ms = 100,
        .set_symbol_rate = alps_stv0299_set_symbol_rate,
@@ -1643,7 +1644,7 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i
        struct ttusb *ttusb;
        int result;
 
-       dprintk("%s: TTUSB DVB connected\n", __FUNCTION__);
+       dprintk("%s: TTUSB DVB connected\n", __func__);
 
        udev = interface_to_usbdev(intf);
 
@@ -1669,7 +1670,10 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i
 
        mutex_unlock(&ttusb->semi2c);
 
-       if ((result = dvb_register_adapter(&ttusb->adapter, "Technotrend/Hauppauge Nova-USB", THIS_MODULE, &udev->dev)) < 0) {
+       result = dvb_register_adapter(&ttusb->adapter,
+                                     "Technotrend/Hauppauge Nova-USB",
+                                     THIS_MODULE, &udev->dev, adapter_nr);
+       if (result < 0) {
                ttusb_free_iso_urbs(ttusb);
                kfree(ttusb);
                return result;
@@ -1773,7 +1777,7 @@ static void ttusb_disconnect(struct usb_interface *intf)
 
        kfree(ttusb);
 
-       dprintk("%s: TTUSB DVB disconnected\n", __FUNCTION__);
+       dprintk("%s: TTUSB DVB disconnected\n", __func__);
 }
 
 static struct usb_device_id ttusb_table[] = {
index 1ec981d98b91bf60da958e0530dccca725b68474..42eee04daa5da4407c4d383982aeffbf51c1f15c 100644 (file)
@@ -52,6 +52,8 @@ MODULE_PARM_DESC(output_pva, "Output PVA from dvr device (default:off)");
 module_param(enable_rc, int, 0644);
 MODULE_PARM_DESC(enable_rc, "Turn on/off IR remote control(default: off)");
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 #define dprintk        if (debug) printk
 
 #define DRIVER_NAME            "TechnoTrend/Hauppauge DEC USB"
@@ -217,11 +219,11 @@ static void ttusb_dec_handle_irq( struct urb *urb)
                case -ETIME:
                        /* this urb is dead, cleanup */
                        dprintk("%s:urb shutting down with status: %d\n",
-                                       __FUNCTION__, urb->status);
+                                       __func__, urb->status);
                        return;
                default:
                        dprintk("%s:nonzero status received: %d\n",
-                                       __FUNCTION__,urb->status);
+                                       __func__,urb->status);
                        goto exit;
        }
 
@@ -235,7 +237,7 @@ static void ttusb_dec_handle_irq( struct urb *urb)
                 * keyrepeat signal is recieved for lets say 200ms.
                 * this should/could be added later ...
                 * for now lets report each signal as a key down and up*/
-               dprintk("%s:rc signal:%d\n", __FUNCTION__, buffer[4]);
+               dprintk("%s:rc signal:%d\n", __func__, buffer[4]);
                input_report_key(dec->rc_input_dev, rc_keys[buffer[4] - 1], 1);
                input_sync(dec->rc_input_dev);
                input_report_key(dec->rc_input_dev, rc_keys[buffer[4] - 1], 0);
@@ -245,7 +247,7 @@ static void ttusb_dec_handle_irq( struct urb *urb)
 exit:  retval = usb_submit_urb(urb, GFP_ATOMIC);
        if(retval)
                printk("%s - usb_commit_urb failed with result: %d\n",
-                       __FUNCTION__, retval);
+                       __func__, retval);
 }
 
 static u16 crc16(u16 crc, const u8 *buf, size_t len)
@@ -268,7 +270,7 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
        int result, actual_len, i;
        u8 *b;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        b = kmalloc(COMMAND_PACKET_SIZE + 4, GFP_KERNEL);
        if (!b)
@@ -276,7 +278,7 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
 
        if ((result = mutex_lock_interruptible(&dec->usb_mutex))) {
                kfree(b);
-               printk("%s: Failed to lock usb mutex.\n", __FUNCTION__);
+               printk("%s: Failed to lock usb mutex.\n", __func__);
                return result;
        }
 
@@ -289,7 +291,7 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
                memcpy(&b[4], params, param_length);
 
        if (debug) {
-               printk("%s: command: ", __FUNCTION__);
+               printk("%s: command: ", __func__);
                for (i = 0; i < param_length + 4; i++)
                        printk("0x%02X ", b[i]);
                printk("\n");
@@ -300,7 +302,7 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
 
        if (result) {
                printk("%s: command bulk message failed: error %d\n",
-                      __FUNCTION__, result);
+                      __func__, result);
                mutex_unlock(&dec->usb_mutex);
                kfree(b);
                return result;
@@ -311,13 +313,13 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
 
        if (result) {
                printk("%s: result bulk message failed: error %d\n",
-                      __FUNCTION__, result);
+                      __func__, result);
                mutex_unlock(&dec->usb_mutex);
                kfree(b);
                return result;
        } else {
                if (debug) {
-                       printk("%s: result: ", __FUNCTION__);
+                       printk("%s: result: ", __func__);
                        for (i = 0; i < actual_len; i++)
                                printk("0x%02X ", b[i]);
                        printk("\n");
@@ -343,7 +345,7 @@ static int ttusb_dec_get_stb_state (struct ttusb_dec *dec, unsigned int *mode,
        int result;
        unsigned int tmp;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        result = ttusb_dec_send_command(dec, 0x08, 0, NULL, &c_length, c);
        if (result)
@@ -400,7 +402,7 @@ static void ttusb_dec_set_pids(struct ttusb_dec *dec)
        u16 audio = htons(dec->pid[DMX_PES_AUDIO]);
        u16 video = htons(dec->pid[DMX_PES_VIDEO]);
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        memcpy(&b[0], &pcr, 2);
        memcpy(&b[2], &audio, 2);
@@ -419,12 +421,12 @@ static void ttusb_dec_set_pids(struct ttusb_dec *dec)
 static void ttusb_dec_process_pva(struct ttusb_dec *dec, u8 *pva, int length)
 {
        if (length < 8) {
-               printk("%s: packet too short - discarding\n", __FUNCTION__);
+               printk("%s: packet too short - discarding\n", __func__);
                return;
        }
 
        if (length > 8 + MAX_PVA_LENGTH) {
-               printk("%s: packet too long - discarding\n", __FUNCTION__);
+               printk("%s: packet too long - discarding\n", __func__);
                return;
        }
 
@@ -507,7 +509,7 @@ static void ttusb_dec_process_pva(struct ttusb_dec *dec, u8 *pva, int length)
                break;
 
        default:
-               printk("%s: unknown PVA type: %02x.\n", __FUNCTION__,
+               printk("%s: unknown PVA type: %02x.\n", __func__,
                       pva[2]);
                break;
        }
@@ -546,7 +548,7 @@ static void ttusb_dec_process_packet(struct ttusb_dec *dec)
        u16 packet_id;
 
        if (dec->packet_length % 2) {
-               printk("%s: odd sized packet - discarding\n", __FUNCTION__);
+               printk("%s: odd sized packet - discarding\n", __func__);
                return;
        }
 
@@ -554,7 +556,7 @@ static void ttusb_dec_process_packet(struct ttusb_dec *dec)
                csum ^= ((dec->packet[i] << 8) + dec->packet[i + 1]);
 
        if (csum) {
-               printk("%s: checksum failed - discarding\n", __FUNCTION__);
+               printk("%s: checksum failed - discarding\n", __func__);
                return;
        }
 
@@ -563,7 +565,7 @@ static void ttusb_dec_process_packet(struct ttusb_dec *dec)
 
        if ((packet_id != dec->next_packet_id) && dec->next_packet_id) {
                printk("%s: warning: lost packets between %u and %u\n",
-                      __FUNCTION__, dec->next_packet_id - 1, packet_id);
+                      __func__, dec->next_packet_id - 1, packet_id);
        }
 
        if (packet_id == 0xffff)
@@ -652,7 +654,7 @@ static void ttusb_dec_process_urb_frame(struct ttusb_dec *dec, u8 *b,
                                        dec->packet_state = 7;
                                } else {
                                        printk("%s: unknown packet type: "
-                                              "%02x%02x\n", __FUNCTION__,
+                                              "%02x%02x\n", __func__,
                                               dec->packet[0], dec->packet[1]);
                                        dec->packet_state = 0;
                                }
@@ -724,7 +726,7 @@ static void ttusb_dec_process_urb_frame(struct ttusb_dec *dec, u8 *b,
 
                default:
                        printk("%s: illegal packet state encountered.\n",
-                              __FUNCTION__);
+                              __func__);
                        dec->packet_state = 0;
                }
        }
@@ -792,7 +794,7 @@ static void ttusb_dec_process_urb(struct urb *urb)
        } else {
                 /* -ENOENT is expected when unlinking urbs */
                if (urb->status != -ENOENT)
-                       dprintk("%s: urb error: %d\n", __FUNCTION__,
+                       dprintk("%s: urb error: %d\n", __func__,
                                urb->status);
        }
 
@@ -804,7 +806,7 @@ static void ttusb_dec_setup_urbs(struct ttusb_dec *dec)
 {
        int i, j, buffer_offset = 0;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        for (i = 0; i < ISO_BUF_COUNT; i++) {
                int frame_offset = 0;
@@ -834,7 +836,7 @@ static void ttusb_dec_stop_iso_xfer(struct ttusb_dec *dec)
 {
        int i;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        if (mutex_lock_interruptible(&dec->iso_mutex))
                return;
@@ -889,7 +891,7 @@ static int ttusb_dec_start_iso_xfer(struct ttusb_dec *dec)
 {
        int i, result;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        if (mutex_lock_interruptible(&dec->iso_mutex))
                return -EAGAIN;
@@ -905,7 +907,7 @@ static int ttusb_dec_start_iso_xfer(struct ttusb_dec *dec)
                        if ((result = usb_submit_urb(dec->iso_urb[i],
                                                     GFP_ATOMIC))) {
                                printk("%s: failed urb submission %d: "
-                                      "error %d\n", __FUNCTION__, i, result);
+                                      "error %d\n", __func__, i, result);
 
                                while (i) {
                                        usb_kill_urb(dec->iso_urb[i - 1]);
@@ -932,7 +934,7 @@ static int ttusb_dec_start_ts_feed(struct dvb_demux_feed *dvbdmxfeed)
        u8 b0[] = { 0x05 };
        int result = 0;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        dprintk("  ts_type:");
 
@@ -1012,7 +1014,7 @@ static int ttusb_dec_start_sec_feed(struct dvb_demux_feed *dvbdmxfeed)
        unsigned long flags;
        u8 x = 1;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        pid = htons(dvbdmxfeed->pid);
        memcpy(&b0[0], &pid, 2);
@@ -1052,7 +1054,7 @@ static int ttusb_dec_start_feed(struct dvb_demux_feed *dvbdmxfeed)
 {
        struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        if (!dvbdmx->dmx.frontend)
                return -EINVAL;
@@ -1113,7 +1115,7 @@ static int ttusb_dec_stop_sec_feed(struct dvb_demux_feed *dvbdmxfeed)
 
 static int ttusb_dec_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
 {
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        switch (dvbdmxfeed->type) {
        case DMX_TYPE_TS:
@@ -1132,7 +1134,7 @@ static void ttusb_dec_free_iso_urbs(struct ttusb_dec *dec)
 {
        int i;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        for (i = 0; i < ISO_BUF_COUNT; i++)
                usb_free_urb(dec->iso_urb[i]);
@@ -1147,7 +1149,7 @@ static int ttusb_dec_alloc_iso_urbs(struct ttusb_dec *dec)
 {
        int i;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        dec->iso_buffer = pci_alloc_consistent(NULL,
                                               ISO_FRAME_SIZE *
@@ -1214,7 +1216,7 @@ static int ttusb_init_rc( struct ttusb_dec *dec)
 
        dec->rc_input_dev = input_dev;
        if (usb_submit_urb(dec->irq_urb, GFP_KERNEL))
-               printk("%s: usb_submit_urb failed\n",__FUNCTION__);
+               printk("%s: usb_submit_urb failed\n",__func__);
        /* enable irq pipe */
        ttusb_dec_send_command(dec,0xb0,sizeof(b),b,NULL,NULL);
 
@@ -1223,7 +1225,7 @@ static int ttusb_init_rc( struct ttusb_dec *dec)
 
 static void ttusb_dec_init_v_pes(struct ttusb_dec *dec)
 {
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        dec->v_pes[0] = 0x00;
        dec->v_pes[1] = 0x00;
@@ -1233,7 +1235,7 @@ static void ttusb_dec_init_v_pes(struct ttusb_dec *dec)
 
 static int ttusb_dec_init_usb(struct ttusb_dec *dec)
 {
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        mutex_init(&dec->usb_mutex);
        mutex_init(&dec->iso_mutex);
@@ -1281,11 +1283,11 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
        u32 crc32_csum, crc32_check, tmp;
        const struct firmware *fw_entry = NULL;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        if (request_firmware(&fw_entry, dec->firmware_name, &dec->udev->dev)) {
                printk(KERN_ERR "%s: Firmware (%s) unavailable.\n",
-                      __FUNCTION__, dec->firmware_name);
+                      __func__, dec->firmware_name);
                return 1;
        }
 
@@ -1294,7 +1296,7 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
 
        if (firmware_size < 60) {
                printk("%s: firmware size too small for DSP code (%zu < 60).\n",
-                       __FUNCTION__, firmware_size);
+                       __func__, firmware_size);
                release_firmware(fw_entry);
                return -1;
        }
@@ -1308,7 +1310,7 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
        if (crc32_csum != crc32_check) {
                printk("%s: crc32 check of DSP code failed (calculated "
                       "0x%08x != 0x%08x in file), file invalid.\n",
-                       __FUNCTION__, crc32_csum, crc32_check);
+                       __func__, crc32_csum, crc32_check);
                release_firmware(fw_entry);
                return -1;
        }
@@ -1376,7 +1378,7 @@ static int ttusb_dec_init_stb(struct ttusb_dec *dec)
        int result;
        unsigned int mode, model, version;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        result = ttusb_dec_get_stb_state(dec, &mode, &model, &version);
 
@@ -1415,7 +1417,7 @@ static int ttusb_dec_init_stb(struct ttusb_dec *dec)
                        default:
                                printk(KERN_ERR "%s: unknown model returned "
                                       "by firmware (%08x) - please report\n",
-                                      __FUNCTION__, model);
+                                      __func__, model);
                                return -1;
                                break;
                        }
@@ -1434,12 +1436,14 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
 {
        int result;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        if ((result = dvb_register_adapter(&dec->adapter,
-                                          dec->model_name, THIS_MODULE, &dec->udev->dev)) < 0) {
+                                          dec->model_name, THIS_MODULE,
+                                          &dec->udev->dev,
+                                          adapter_nr)) < 0) {
                printk("%s: dvb_register_adapter failed: error %d\n",
-                      __FUNCTION__, result);
+                      __func__, result);
 
                return result;
        }
@@ -1454,7 +1458,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
        dec->demux.write_to_decoder = NULL;
 
        if ((result = dvb_dmx_init(&dec->demux)) < 0) {
-               printk("%s: dvb_dmx_init failed: error %d\n", __FUNCTION__,
+               printk("%s: dvb_dmx_init failed: error %d\n", __func__,
                       result);
 
                dvb_unregister_adapter(&dec->adapter);
@@ -1468,7 +1472,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
 
        if ((result = dvb_dmxdev_init(&dec->dmxdev, &dec->adapter)) < 0) {
                printk("%s: dvb_dmxdev_init failed: error %d\n",
-                      __FUNCTION__, result);
+                      __func__, result);
 
                dvb_dmx_release(&dec->demux);
                dvb_unregister_adapter(&dec->adapter);
@@ -1480,7 +1484,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
 
        if ((result = dec->demux.dmx.add_frontend(&dec->demux.dmx,
                                                  &dec->frontend)) < 0) {
-               printk("%s: dvb_dmx_init failed: error %d\n", __FUNCTION__,
+               printk("%s: dvb_dmx_init failed: error %d\n", __func__,
                       result);
 
                dvb_dmxdev_release(&dec->dmxdev);
@@ -1492,7 +1496,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
 
        if ((result = dec->demux.dmx.connect_frontend(&dec->demux.dmx,
                                                      &dec->frontend)) < 0) {
-               printk("%s: dvb_dmx_init failed: error %d\n", __FUNCTION__,
+               printk("%s: dvb_dmx_init failed: error %d\n", __func__,
                       result);
 
                dec->demux.dmx.remove_frontend(&dec->demux.dmx, &dec->frontend);
@@ -1510,7 +1514,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
 
 static void ttusb_dec_exit_dvb(struct ttusb_dec *dec)
 {
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        dvb_net_release(&dec->dvb_net);
        dec->demux.dmx.close(&dec->demux.dmx);
@@ -1528,7 +1532,7 @@ static void ttusb_dec_exit_dvb(struct ttusb_dec *dec)
 static void ttusb_dec_exit_rc(struct ttusb_dec *dec)
 {
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
        /* we have to check whether the irq URB is already submitted.
          * As the irq is submitted after the interface is changed,
          * this is the best method i figured out.
@@ -1552,7 +1556,7 @@ static void ttusb_dec_exit_usb(struct ttusb_dec *dec)
 {
        int i;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        dec->iso_stream_count = 0;
 
@@ -1612,12 +1616,12 @@ static int ttusb_dec_probe(struct usb_interface *intf,
        struct usb_device *udev;
        struct ttusb_dec *dec;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        udev = interface_to_usbdev(intf);
 
        if (!(dec = kzalloc(sizeof(struct ttusb_dec), GFP_KERNEL))) {
-               printk("%s: couldn't allocate memory.\n", __FUNCTION__);
+               printk("%s: couldn't allocate memory.\n", __func__);
                return -ENOMEM;
        }
 
@@ -1692,7 +1696,7 @@ static void ttusb_dec_disconnect(struct usb_interface *intf)
 
        usb_set_intfdata(intf, NULL);
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        if (dec->active) {
                ttusb_dec_exit_tasklet(dec);
@@ -1749,7 +1753,7 @@ static int __init ttusb_dec_init(void)
        int result;
 
        if ((result = usb_register(&ttusb_dec_driver)) < 0) {
-               printk("%s: initialisation failed: error %d.\n", __FUNCTION__,
+               printk("%s: initialisation failed: error %d.\n", __func__,
                       result);
                return result;
        }
index a6fb1d6a7b5dd168394933b9abb609ae3c7f6c19..eb5eaeccd7c4db2dc16e8ee948f08802d7851cb3 100644 (file)
@@ -53,7 +53,7 @@ static int ttusbdecfe_read_status(struct dvb_frontend* fe, fe_status_t* status)
                return ret;
 
        if(len != 4) {
-               printk(KERN_ERR "%s: unexpected reply\n", __FUNCTION__);
+               printk(KERN_ERR "%s: unexpected reply\n", __func__);
                return -EIO;
        }
 
@@ -70,7 +70,7 @@ static int ttusbdecfe_read_status(struct dvb_frontend* fe, fe_status_t* status)
                        break;
                default:
                        pr_info("%s: returned unknown value: %d\n",
-                               __FUNCTION__, result[3]);
+                               __func__, result[3]);
                        return -EIO;
        }
 
index 36c0e365150241ebe1561c7aaa09d738cddbcf15..4e3f83e4e48f34f4f2878df5823c00f3f0729bc7 100644 (file)
@@ -438,7 +438,9 @@ static const struct file_operations usb_dsbr100_fops = {
        .open           = usb_dsbr100_open,
        .release        = usb_dsbr100_close,
        .ioctl          = video_ioctl2,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .llseek         = no_llseek,
 };
 
index 3ae56fef8c92f58ce4d2b2123606b795e0adf503..09fe6f1cdf14b124d8b10fcc64e91bc91625649e 100644 (file)
@@ -221,7 +221,9 @@ static const struct file_operations pcm20_fops = {
        .open           = video_exclusive_open,
        .release        = video_exclusive_release,
        .ioctl          = pcm20_ioctl,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .llseek         = no_llseek,
 };
 
index aed11477378bd5bf018a9d7a4eec1e9c960ca86e..06dfed9ef4c7194d043999d23ed7eda35e9025c4 100644 (file)
@@ -19,7 +19,7 @@
 #include "miropcm20-rds-core.h"
 
 static char * text_buffer;
-static int rds_users = 0;
+static int rds_users;
 
 
 static int rds_f_open(struct inode *in, struct file *fi)
index c69bde39a2336c8ae623001bc7465139abc4f693..1ec18ed1a73365dbfad685238648f63faeba4177 100644 (file)
@@ -382,7 +382,9 @@ static const struct file_operations rtrack_fops = {
        .open           = video_exclusive_open,
        .release        = video_exclusive_release,
        .ioctl          = video_ioctl2,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .llseek         = no_llseek,
 };
 
index 9b1f7a99dac0ac4c6b71dcfb836ef5d4fc18bf68..46cdb549eac736eb1321777e9616e2f7fe5070d8 100644 (file)
@@ -346,7 +346,9 @@ static const struct file_operations aztech_fops = {
        .open           = video_exclusive_open,
        .release        = video_exclusive_release,
        .ioctl          = video_ioctl2,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .llseek         = no_llseek,
 };
 
index 57b9e3adc8f0249c831bf93dcbf49658d859d608..b14db53ea456514153ee49ae0a61759c3d522847 100644 (file)
@@ -69,13 +69,13 @@ static struct v4l2_queryctrl radio_qctrl[] = {
 
 static int io=-1;              /* default to isapnp activation */
 static int radio_nr = -1;
-static int users=0;
-static int curtuner=0;
-static int tunestat=0;
-static int sigstrength=0;
+static int users;
+static int curtuner;
+static int tunestat;
+static int sigstrength;
 static wait_queue_head_t read_queue;
 static struct timer_list readtimer;
-static __u8 rdsin=0,rdsout=0,rdsstat=0;
+static __u8 rdsin, rdsout, rdsstat;
 static unsigned char rdsbuf[RDS_BUFFER];
 static spinlock_t cadet_io_lock;
 
@@ -563,7 +563,9 @@ static const struct file_operations cadet_fops = {
        .read           = cadet_read,
        .ioctl          = video_ioctl2,
        .poll           = cadet_poll,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .llseek         = no_llseek,
 };
 
index 99a3231313332b5736e43dd218352a9a15454115..de49be971480fd8ec1b569904f8d329fd3ee821f 100644 (file)
@@ -368,7 +368,9 @@ static const struct file_operations gemtek_pci_fops = {
        .open           = video_exclusive_open,
        .release        = video_exclusive_release,
        .ioctl          = video_ioctl2,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .llseek         = no_llseek,
 };
 
index 246422b49267ca3bf1a6bd3efa425cd778de2c42..81f6aeb1cd1154d62e707d41d620381fa100c25c 100644 (file)
@@ -397,7 +397,9 @@ static const struct file_operations gemtek_fops = {
        .open           = video_exclusive_open,
        .release        = video_exclusive_release,
        .ioctl          = video_ioctl2,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .llseek         = no_llseek
 };
 
index bc51f4d23a5a176abbc61007d7d8dbfdec21e5e9..bddd3c409aa95a84112b1930ea0844ab060b4150 100644 (file)
@@ -100,7 +100,9 @@ static const struct file_operations maestro_fops = {
        .open           = video_exclusive_open,
        .release        = video_exclusive_release,
        .ioctl          = video_ioctl2,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .llseek         = no_llseek,
 };
 
index 8e184cfc1c94aa897665f73e6a21fec40c26d973..0133ecf3e040b0905f157581283c384f6ec7b876 100644 (file)
@@ -103,7 +103,9 @@ static const struct file_operations maxiradio_fops = {
        .open           = video_exclusive_open,
        .release        = video_exclusive_release,
        .ioctl          = video_ioctl2,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .llseek         = no_llseek,
 };
 
index 82aedfc95d4f3883b0e487402a53d21631baf494..070802103dc34d52176b87fa78c43511f2ce3798 100644 (file)
@@ -288,7 +288,9 @@ static const struct file_operations rtrack2_fops = {
        .open           = video_exclusive_open,
        .release        = video_exclusive_release,
        .ioctl          = video_ioctl2,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .llseek         = no_llseek,
 };
 
index 53e1148573778de36291239684bd1d9b0093fe2a..66e052fd3909aa3531ce5e7b1e22bfe91f865537 100644 (file)
@@ -288,7 +288,9 @@ static const struct file_operations fmi_fops = {
        .open           = video_exclusive_open,
        .release        = video_exclusive_release,
        .ioctl          = video_ioctl2,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .llseek         = no_llseek,
 };
 
index ebc5fbbc38bb3534b408cccd0785e2a5e2ea80fd..b0ccf7cb5952a8c0edda2ef0588a0800fe1a6682 100644 (file)
@@ -29,6 +29,8 @@ static struct mutex lock;
 #include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
 #define RADIO_VERSION KERNEL_VERSION(0,0,2)
 
+#define AUD_VOL_INDEX 1
+
 static struct v4l2_queryctrl radio_qctrl[] = {
        {
                .id            = V4L2_CID_AUDIO_MUTE,
@@ -37,13 +39,14 @@ static struct v4l2_queryctrl radio_qctrl[] = {
                .maximum       = 1,
                .default_value = 1,
                .type          = V4L2_CTRL_TYPE_BOOLEAN,
-       },{
+       },
+       [AUD_VOL_INDEX] = {
                .id            = V4L2_CID_AUDIO_VOLUME,
                .name          = "Volume",
                .minimum       = 0,
-               .maximum       = 65535,
-               .step          = 1<<12,
-               .default_value = 0xff,
+               .maximum       = 15,
+               .step          = 1,
+               .default_value = 0,
                .type          = V4L2_CTRL_TYPE_INTEGER,
        }
 };
@@ -61,7 +64,7 @@ static struct v4l2_queryctrl radio_qctrl[] = {
 struct fmr2_device
 {
        int port;
-       int curvol; /* 0-65535, if not volume 0 or 65535 */
+       int curvol; /* 0-15 */
        int mute;
        int stereo; /* card is producing stereo audio */
        unsigned long curfreq; /* freq in kHz */
@@ -176,51 +179,35 @@ static int fmr2_setfreq(struct fmr2_device *dev)
 /* !!! not tested, in my card this does't work !!! */
 static int fmr2_setvolume(struct fmr2_device *dev)
 {
-       int i,a,n, port = dev->port;
+       int vol[16] = { 0x021, 0x084, 0x090, 0x104,
+                       0x110, 0x204, 0x210, 0x402,
+                       0x404, 0x408, 0x410, 0x801,
+                       0x802, 0x804, 0x808, 0x810 };
+       int i, a, port = dev->port;
+       int n = vol[dev->curvol & 0x0f];
 
-       if (dev->card_type != 11) return 1;
+       if (dev->card_type != 11)
+               return 1;
 
-       switch( (dev->curvol+(1<<11)) >> 12 )
-       {
-       case 0: case 1: n = 0x21; break;
-       case 2: n = 0x84; break;
-       case 3: n = 0x90; break;
-       case 4: n = 0x104; break;
-       case 5: n = 0x110; break;
-       case 6: n = 0x204; break;
-       case 7: n = 0x210; break;
-       case 8: n = 0x402; break;
-       case 9: n = 0x404; break;
-       default:
-       case 10: n = 0x408; break;
-       case 11: n = 0x410; break;
-       case 12: n = 0x801; break;
-       case 13: n = 0x802; break;
-       case 14: n = 0x804; break;
-       case 15: n = 0x808; break;
-       case 16: n = 0x810; break;
-       }
-       for(i=12;--i>=0;)
-       {
+       for (i = 12; --i >= 0; ) {
                a = ((n >> i) & 1) << 6; /* if (a=0) a= 0; else a= 0x40; */
-               outb(a|4, port);
-               wait(4,port);
-               outb(a|0x24, port);
-               wait(4,port);
-               outb(a|4, port);
-               wait(4,port);
+               outb(a | 4, port);
+               wait(4, port);
+               outb(a | 0x24, port);
+               wait(4, port);
+               outb(a | 4, port);
+               wait(4, port);
        }
-       for(i=6;--i>=0;)
-       {
+       for (i = 6; --i >= 0; ) {
                a = ((0x18 >> i) & 1) << 6;
-               outb(a|4, port);
+               outb(a | 4, port);
                wait(4,port);
-               outb(a|0x24, port);
+               outb(a | 0x24, port);
                wait(4,port);
                outb(a|4, port);
                wait(4,port);
        }
-       wait(4,port);
+       wait(4, port);
        outb(0x14, port);
 
        return 0;
@@ -312,16 +299,10 @@ static int vidioc_queryctrl(struct file *file, void *priv,
                                        struct v4l2_queryctrl *qc)
 {
        int i;
-       struct video_device *dev = video_devdata(file);
-       struct fmr2_device *fmr2 = dev->priv;
 
        for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
-               if ((fmr2->card_type != 11)
-                               && V4L2_CID_AUDIO_VOLUME)
-                       radio_qctrl[i].step = 65535;
                if (qc->id && qc->id == radio_qctrl[i].id) {
-                       memcpy(qc, &(radio_qctrl[i]),
-                                               sizeof(*qc));
+                       memcpy(qc, &radio_qctrl[i], sizeof(*qc));
                        return 0;
                }
        }
@@ -354,24 +335,13 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
        switch (ctrl->id) {
        case V4L2_CID_AUDIO_MUTE:
                fmr2->mute = ctrl->value;
-               if (fmr2->card_type != 11) {
-                       if (!fmr2->mute)
-                               fmr2->curvol = 65535;
-                       else
-                               fmr2->curvol = 0;
-               }
                break;
        case V4L2_CID_AUDIO_VOLUME:
-               fmr2->curvol = ctrl->value;
-               if (fmr2->card_type != 11) {
-                       if (fmr2->curvol) {
-                               fmr2->curvol = 65535;
-                               fmr2->mute = 0;
-                       } else {
-                               fmr2->curvol = 0;
-                               fmr2->mute = 1;
-                       }
-               }
+               if (ctrl->value > radio_qctrl[AUD_VOL_INDEX].maximum)
+                       fmr2->curvol = radio_qctrl[AUD_VOL_INDEX].maximum;
+               else
+                       fmr2->curvol = ctrl->value;
+
                break;
        default:
                return -EINVAL;
@@ -387,6 +357,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
        mutex_lock(&lock);
        if (fmr2->curvol && !fmr2->mute) {
                fmr2_setvolume(fmr2);
+               /* Set frequency and unmute card */
                fmr2_setfreq(fmr2);
        } else
                fmr2_mute(fmr2->port);
@@ -433,7 +404,9 @@ static const struct file_operations fmr2_fops = {
        .open           = video_exclusive_open,
        .release        = video_exclusive_release,
        .ioctl          = video_ioctl2,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .llseek         = no_llseek,
 };
 
@@ -487,6 +460,11 @@ static int __init fmr2_init(void)
        fmr2_product_info(&fmr2_unit);
        mutex_unlock(&lock);
        debug_print((KERN_DEBUG "card_type %d\n", fmr2_unit.card_type));
+
+       /* Only card_type == 11 implements volume */
+       if (fmr2_unit.card_type != 11)
+               radio_qctrl[AUD_VOL_INDEX].maximum = 1;
+
        return 0;
 }
 
index 649f14d2c01340e4bdea2bee6d4b1910ee39e496..77354ca6e8e928005cfcf631ed97d698bfd9b1ab 100644 (file)
@@ -85,6 +85,7 @@
  *             Oliver Neukum <oliver@neukum.org>
  *             Version 1.0.7
  *             - usb autosuspend support
+ *             - unplugging fixed
  *
  * ToDo:
  * - add seeking support
 /* driver definitions */
 #define DRIVER_AUTHOR "Tobias Lorenz <tobias.lorenz@gmx.net>"
 #define DRIVER_NAME "radio-si470x"
-#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 6)
+#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 7)
 #define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver"
 #define DRIVER_DESC "USB radio driver for Si470x FM Radio Receivers"
-#define DRIVER_VERSION "1.0.6"
+#define DRIVER_VERSION "1.0.7"
 
 
 /* kernel includes */
@@ -424,6 +425,7 @@ struct si470x_device {
 
        /* driver management */
        unsigned int users;
+       unsigned char disconnected;
 
        /* Silabs internal registers (0..15) */
        unsigned short registers[RADIO_REGISTER_NUM];
@@ -439,6 +441,12 @@ struct si470x_device {
 };
 
 
+/*
+ * Lock to prevent kfree of data before all users have releases the device.
+ */
+static DEFINE_MUTEX(open_close_lock);
+
+
 /*
  * The frequency is set in units of 62.5 Hz when using V4L2_TUNER_CAP_LOW,
  * 62.5 kHz otherwise.
@@ -577,7 +585,7 @@ static int si470x_get_rds_registers(struct si470x_device *radio)
                usb_rcvintpipe(radio->usbdev, 1),
                (void *) &buf, sizeof(buf), &size, usb_timeout);
        if (size != sizeof(buf))
-               printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_register: "
+              printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_registers: "
                        "return size differs: %d != %zu\n", size, sizeof(buf));
        if (retval < 0)
                printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_registers: "
@@ -875,6 +883,8 @@ static void si470x_work(struct work_struct *work)
        struct si470x_device *radio = container_of(work, struct si470x_device,
                work.work);
 
+       if (radio->disconnected)
+              return;
        if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
                return;
 
@@ -1001,13 +1011,21 @@ static int si470x_fops_open(struct inode *inode, struct file *file)
 static int si470x_fops_release(struct inode *inode, struct file *file)
 {
        struct si470x_device *radio = video_get_drvdata(video_devdata(file));
-       int retval;
+       int retval = 0;
 
        if (!radio)
                return -ENODEV;
 
+       mutex_lock(&open_close_lock);
        radio->users--;
        if (radio->users == 0) {
+              if (radio->disconnected) {
+                      video_unregister_device(radio->videodev);
+                      kfree(radio->buffer);
+                      kfree(radio);
+                      goto done;
+              }
+
                /* stop rds reception */
                cancel_delayed_work_sync(&radio->work);
 
@@ -1016,10 +1034,11 @@ static int si470x_fops_release(struct inode *inode, struct file *file)
 
                retval = si470x_stop(radio);
                usb_autopm_put_interface(radio->intf);
-               return retval;
        }
 
-       return 0;
+done:
+       mutex_unlock(&open_close_lock);
+       return retval;
 }
 
 
@@ -1032,7 +1051,9 @@ static const struct file_operations si470x_fops = {
        .read           = si470x_fops_read,
        .poll           = si470x_fops_poll,
        .ioctl          = video_ioctl2,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .open           = si470x_fops_open,
        .release        = si470x_fops_release,
 };
@@ -1157,6 +1178,9 @@ static int si470x_vidioc_g_ctrl(struct file *file, void *priv,
 {
        struct si470x_device *radio = video_get_drvdata(video_devdata(file));
 
+       if (radio->disconnected)
+              return -EIO;
+
        switch (ctrl->id) {
        case V4L2_CID_AUDIO_VOLUME:
                ctrl->value = radio->registers[SYSCONFIG2] &
@@ -1181,6 +1205,9 @@ static int si470x_vidioc_s_ctrl(struct file *file, void *priv,
        struct si470x_device *radio = video_get_drvdata(video_devdata(file));
        int retval;
 
+       if (radio->disconnected)
+              return -EIO;
+
        switch (ctrl->id) {
        case V4L2_CID_AUDIO_VOLUME:
                radio->registers[SYSCONFIG2] &= ~SYSCONFIG2_VOLUME;
@@ -1243,6 +1270,8 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv,
        struct si470x_device *radio = video_get_drvdata(video_devdata(file));
        int retval;
 
+       if (radio->disconnected)
+              return -EIO;
        if (tuner->index > 0)
                return -EINVAL;
 
@@ -1299,6 +1328,8 @@ static int si470x_vidioc_s_tuner(struct file *file, void *priv,
        struct si470x_device *radio = video_get_drvdata(video_devdata(file));
        int retval;
 
+       if (radio->disconnected)
+              return -EIO;
        if (tuner->index > 0)
                return -EINVAL;
 
@@ -1324,6 +1355,9 @@ static int si470x_vidioc_g_frequency(struct file *file, void *priv,
 {
        struct si470x_device *radio = video_get_drvdata(video_devdata(file));
 
+       if (radio->disconnected)
+              return -EIO;
+
        freq->type = V4L2_TUNER_RADIO;
        freq->frequency = si470x_get_freq(radio);
 
@@ -1340,6 +1374,8 @@ static int si470x_vidioc_s_frequency(struct file *file, void *priv,
        struct si470x_device *radio = video_get_drvdata(video_devdata(file));
        int retval;
 
+       if (radio->disconnected)
+              return -EIO;
        if (freq->type != V4L2_TUNER_RADIO)
                return -EINVAL;
 
@@ -1510,11 +1546,16 @@ static void si470x_usb_driver_disconnect(struct usb_interface *intf)
 {
        struct si470x_device *radio = usb_get_intfdata(intf);
 
+       mutex_lock(&open_close_lock);
+       radio->disconnected = 1;
        cancel_delayed_work_sync(&radio->work);
        usb_set_intfdata(intf, NULL);
-       video_unregister_device(radio->videodev);
-       kfree(radio->buffer);
-       kfree(radio);
+       if (radio->users == 0) {
+              video_unregister_device(radio->videodev);
+              kfree(radio->buffer);
+              kfree(radio);
+       }
+       mutex_unlock(&open_close_lock);
 }
 
 
index 535ffe8c81028508ac773c05510a8f895c35678d..acc32080e9bdefef40bc84d0e2e0bbf09f758a42 100644 (file)
@@ -360,7 +360,9 @@ static const struct file_operations terratec_fops = {
        .open           = video_exclusive_open,
        .release        = video_exclusive_release,
        .ioctl          = video_ioctl2,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .llseek         = no_llseek,
 };
 
index c11981fed827deb3572f828ce0dc6f7dc39058cf..4ebdfbadeb9ce6160d7d7ea023b87cc6d13860c3 100644 (file)
@@ -340,7 +340,9 @@ static const struct file_operations trust_fops = {
        .open           = video_exclusive_open,
        .release        = video_exclusive_release,
        .ioctl          = video_ioctl2,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .llseek         = no_llseek,
 };
 
index 1366326474e5b664951ffe06944cfddccf140e9c..18f2abd7e2552e985d670551b1abc729c0d24d5f 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/init.h>                /* Initdata                       */
 #include <linux/ioport.h>      /* request_region                 */
 #include <linux/proc_fs.h>     /* radio card status report       */
+#include <linux/seq_file.h>
 #include <asm/io.h>            /* outb, outb_p                   */
 #include <asm/uaccess.h>       /* copy to/from user              */
 #include <linux/videodev2.h>   /* kernel radio structs           */
@@ -93,9 +94,6 @@ static int typhoon_setfreq(struct typhoon_device *dev, unsigned long frequency);
 static void typhoon_mute(struct typhoon_device *dev);
 static void typhoon_unmute(struct typhoon_device *dev);
 static int typhoon_setvol(struct typhoon_device *dev, int vol);
-#ifdef CONFIG_RADIO_TYPHOON_PROC_FS
-static int typhoon_get_info(char *buf, char **start, off_t offset, int len);
-#endif
 
 static void typhoon_setvol_generic(struct typhoon_device *dev, int vol)
 {
@@ -340,7 +338,9 @@ static const struct file_operations typhoon_fops = {
        .open           = video_exclusive_open,
        .release        = video_exclusive_release,
        .ioctl          = video_ioctl2,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .llseek         = no_llseek,
 };
 
@@ -366,30 +366,39 @@ static struct video_device typhoon_radio =
 
 #ifdef CONFIG_RADIO_TYPHOON_PROC_FS
 
-static int typhoon_get_info(char *buf, char **start, off_t offset, int len)
+static int typhoon_proc_show(struct seq_file *m, void *v)
 {
-       char *out = buf;
-
        #ifdef MODULE
            #define MODULEPROCSTRING "Driver loaded as a module"
        #else
            #define MODULEPROCSTRING "Driver compiled into kernel"
        #endif
 
-       /* output must be kept under PAGE_SIZE */
-       out += sprintf(out, BANNER);
-       out += sprintf(out, "Load type: " MODULEPROCSTRING "\n\n");
-       out += sprintf(out, "frequency = %lu kHz\n",
+       seq_puts(m, BANNER);
+       seq_puts(m, "Load type: " MODULEPROCSTRING "\n\n");
+       seq_printf(m, "frequency = %lu kHz\n",
                typhoon_unit.curfreq >> 4);
-       out += sprintf(out, "volume = %d\n", typhoon_unit.curvol);
-       out += sprintf(out, "mute = %s\n", typhoon_unit.muted ?
+       seq_printf(m, "volume = %d\n", typhoon_unit.curvol);
+       seq_printf(m, "mute = %s\n", typhoon_unit.muted ?
                "on" : "off");
-       out += sprintf(out, "iobase = 0x%x\n", typhoon_unit.iobase);
-       out += sprintf(out, "mute frequency = %lu kHz\n",
+       seq_printf(m, "iobase = 0x%x\n", typhoon_unit.iobase);
+       seq_printf(m, "mute frequency = %lu kHz\n",
                typhoon_unit.mutefreq >> 4);
-       return out - buf;
+       return 0;
 }
 
+static int typhoon_proc_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, typhoon_proc_show, NULL);
+}
+
+static const struct file_operations typhoon_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = typhoon_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
 #endif /* CONFIG_RADIO_TYPHOON_PROC_FS */
 
 MODULE_AUTHOR("Dr. Henrik Seidel");
@@ -404,7 +413,7 @@ MODULE_PARM_DESC(io, "I/O address of the Typhoon card (0x316 or 0x336)");
 module_param(radio_nr, int, 0);
 
 #ifdef MODULE
-static unsigned long mutefreq = 0;
+static unsigned long mutefreq;
 module_param(mutefreq, ulong, 0);
 MODULE_PARM_DESC(mutefreq, "Frequency used when muting the card (in kHz)");
 #endif
@@ -450,8 +459,7 @@ static int __init typhoon_init(void)
        typhoon_mute(&typhoon_unit);
 
 #ifdef CONFIG_RADIO_TYPHOON_PROC_FS
-       if (!create_proc_info_entry("driver/radio-typhoon", 0, NULL,
-                                   typhoon_get_info))
+       if (!proc_create("driver/radio-typhoon", 0, NULL, &typhoon_proc_fops))
                printk(KERN_ERR "radio-typhoon: registering /proc/driver/radio-typhoon failed\n");
 #endif
 
index 203f4373eeb8f7ea189cd3ef2705a1ba9c7f55c2..43773c56c62f0fcd45e25f87629591d51fb5d5ce 100644 (file)
@@ -401,7 +401,9 @@ static const struct file_operations zoltrix_fops =
        .open           = video_exclusive_open,
        .release        = video_exclusive_release,
        .ioctl          = video_ioctl2,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .llseek         = no_llseek,
 };
 
index f888f84e83d7769dc6ee811feb637cbec1442cd9..2b81bb54d81f6bf2789deaef9578ea68acda71cf 100644 (file)
@@ -278,6 +278,15 @@ config VIDEO_SAA711X
          To compile this driver as a module, choose M here: the
          module will be called saa7115.
 
+config VIDEO_SAA717X
+       tristate "Philips SAA7171/3/4 audio/video decoders"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the Philips SAA7171/3/4 audio/video decoders.
+
+         To compile this driver as a module, choose M here: the
+         module will be called saa717x.
+
 config VIDEO_SAA7191
        tristate "Philips SAA7191 video decoder"
        depends on VIDEO_V4L1 && I2C
@@ -697,6 +706,8 @@ source "drivers/media/video/cx88/Kconfig"
 
 source "drivers/media/video/cx23885/Kconfig"
 
+source "drivers/media/video/au0828/Kconfig"
+
 source "drivers/media/video/ivtv/Kconfig"
 
 source drivers/media/video/omap/Kconfig
@@ -855,4 +866,49 @@ config USB_STKWEBCAM
 
 endif # V4L_USB_DRIVERS
 
+config SOC_CAMERA
+       tristate "SoC camera support"
+       depends on VIDEO_V4L2
+       select VIDEOBUF_DMA_SG
+       help
+         SoC Camera is a common API to several cameras, not connecting
+         over a bus like PCI or USB. For example some i2c camera connected
+         directly to the data bus of an SoC.
+
+config SOC_CAMERA_MT9M001
+       tristate "mt9m001 support"
+       depends on SOC_CAMERA
+       select GPIO_PCA953X if MT9M001_PCA9536_SWITCH
+       help
+         This driver supports MT9M001 cameras from Micron, monochrome
+         and colour models.
+
+config MT9M001_PCA9536_SWITCH
+       bool "pca9536 datawidth switch for mt9m001"
+       depends on SOC_CAMERA_MT9M001 && GENERIC_GPIO
+       help
+         Select this if your MT9M001 camera uses a PCA9536 I2C GPIO
+         extender to switch between 8 and 10 bit datawidth modes
+
+config SOC_CAMERA_MT9V022
+       tristate "mt9v022 support"
+       depends on SOC_CAMERA
+       select GPIO_PCA953X if MT9V022_PCA9536_SWITCH
+       help
+         This driver supports MT9V022 cameras from Micron
+
+config MT9V022_PCA9536_SWITCH
+       bool "pca9536 datawidth switch for mt9v022"
+       depends on SOC_CAMERA_MT9V022 && GENERIC_GPIO
+       help
+         Select this if your MT9V022 camera uses a PCA9536 I2C GPIO
+         extender to switch between 8 and 10 bit datawidth modes
+
+config VIDEO_PXA27x
+       tristate "PXA27x Quick Capture Interface driver"
+       depends on VIDEO_DEV && PXA27x
+       select SOC_CAMERA
+       ---help---
+         This is a v4l2 driver for the PXA27x Quick Capture Interface
+
 endif # VIDEO_CAPTURE_DRIVERS
index 812afcdeb698951a8c56d1784d29e99d27739f9f..384bec1e86cfeda2ae29a4729749dd085f1191d8 100644 (file)
@@ -4,7 +4,7 @@
 
 zr36067-objs   :=      zoran_procfs.o zoran_device.o \
                        zoran_driver.o zoran_card.o
-tuner-objs     :=      tuner-core.o tuner-types.o
+tuner-objs     :=      tuner-core.o
 
 msp3400-objs   :=      msp3400-driver.o msp3400-kthreads.o
 
@@ -38,6 +38,7 @@ obj-$(CONFIG_VIDEO_SAA7110) += saa7110.o
 obj-$(CONFIG_VIDEO_SAA7111) += saa7111.o
 obj-$(CONFIG_VIDEO_SAA7114) += saa7114.o
 obj-$(CONFIG_VIDEO_SAA711X) += saa7115.o
+obj-$(CONFIG_VIDEO_SAA717X) += saa717x.o
 obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o
 obj-$(CONFIG_VIDEO_SAA7185) += saa7185.o
 obj-$(CONFIG_VIDEO_SAA7191) += saa7191.o
@@ -87,6 +88,8 @@ obj-$(CONFIG_VIDEO_TUNER) += tuner.o
 
 obj-$(CONFIG_TUNER_XC2028) += tuner-xc2028.o
 obj-$(CONFIG_TUNER_SIMPLE) += tuner-simple.o
+# tuner-types will be merged into tuner-simple, in the future
+obj-$(CONFIG_TUNER_SIMPLE) += tuner-types.o
 obj-$(CONFIG_TUNER_MT20XX) += mt20xx.o
 obj-$(CONFIG_TUNER_TDA8290) += tda8290.o
 obj-$(CONFIG_TUNER_TEA5767) += tea5767.o
@@ -138,5 +141,12 @@ obj-$(CONFIG_VIDEO_IVTV) += ivtv/
 obj-$(CONFIG_VIDEO_VIVI) += vivi.o
 obj-$(CONFIG_VIDEO_CX23885) += cx23885/
 
+obj-$(CONFIG_VIDEO_PXA27x)     += pxa_camera.o
+obj-$(CONFIG_SOC_CAMERA)       += soc_camera.o
+obj-$(CONFIG_SOC_CAMERA_MT9M001)       += mt9m001.o
+obj-$(CONFIG_SOC_CAMERA_MT9V022)       += mt9v022.o
+
+obj-$(CONFIG_VIDEO_AU0828) += au0828/
+
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
 EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
index fea2e723e34b965da2853c58a9d2618d6f0a98f2..f794f2dbfb327be6c979baedcfd6decca8f3df67 100644 (file)
@@ -56,7 +56,7 @@ MODULE_LICENSE("GPL");
 #define I2C_NAME(x) (x)->name
 
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0-1)");
 
index 10d4d89623f15431080c3fda94b37164c4dc67fd..8ee07a68f7026527ed2eb4e5f8624955f27464d6 100644 (file)
@@ -52,7 +52,7 @@ MODULE_LICENSE("GPL");
 #define I2C_NAME(s) (s)->name
 
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0-1)");
 
index c94a4d0f280475c987b306d9716596c35d9256b7..8c7d1958856b600f515c51716d960b2aaaf7f167 100644 (file)
@@ -125,8 +125,8 @@ static unsigned char        yuv[MAX_AR_FRAME_BYTES];
 /* default frequency */
 #define DEFAULT_FREQ   50      /* 50 or 75 (MHz) is available as BCLK */
 static int freq = DEFAULT_FREQ;        /* BCLK: available 50 or 70 (MHz) */
-static int vga = 0;            /* default mode(0:QVGA mode, other:VGA mode) */
-static int vga_interlace = 0;  /* 0 is normal mode for, else interlace mode */
+static int vga;                        /* default mode(0:QVGA mode, other:VGA mode) */
+static int vga_interlace;      /* 0 is normal mode for, else interlace mode */
 module_param(freq, int, 0);
 module_param(vga, int, 0);
 module_param(vga_interlace, int, 0);
@@ -747,7 +747,9 @@ static const struct file_operations ar_fops = {
        .release        = video_exclusive_release,
        .read           = ar_read,
        .ioctl          = ar_ioctl,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .llseek         = no_llseek,
 };
 
diff --git a/drivers/media/video/au0828/Kconfig b/drivers/media/video/au0828/Kconfig
new file mode 100644 (file)
index 0000000..c97c4bd
--- /dev/null
@@ -0,0 +1,12 @@
+
+config VIDEO_AU0828
+       tristate "Auvitek AU0828 support"
+       depends on VIDEO_DEV && I2C && INPUT
+       select I2C_ALGOBIT
+       select DVB_AU8522 if !DVB_FE_CUSTOMIZE
+       select DVB_TUNER_XC5000 if !DVB_FE_CUSTOMIZE
+       ---help---
+         This is a video4linux driver for Auvitek's USB device.
+
+         To compile this driver as a module, choose M here: the
+         module will be called au0828
diff --git a/drivers/media/video/au0828/Makefile b/drivers/media/video/au0828/Makefile
new file mode 100644 (file)
index 0000000..9f4f572
--- /dev/null
@@ -0,0 +1,9 @@
+au0828-objs    := au0828-core.o au0828-i2c.o au0828-cards.o au0828-dvb.o
+
+obj-$(CONFIG_VIDEO_AU0828) += au0828.o
+
+EXTRA_CFLAGS += -Idrivers/media/video
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
+EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+
+EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
diff --git a/drivers/media/video/au0828/au0828-cards.c b/drivers/media/video/au0828/au0828-cards.c
new file mode 100644 (file)
index 0000000..8ca91f8
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ *  Driver for the Auvitek USB bridge
+ *
+ *  Copyright (c) 2008 Steven Toth <stoth@hauppauge.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "au0828.h"
+#include "au0828-cards.h"
+
+struct au0828_board au0828_boards[] = {
+       [AU0828_BOARD_UNKNOWN] = {
+               .name   = "Unknown board",
+       },
+       [AU0828_BOARD_HAUPPAUGE_HVR850] = {
+               .name   = "Hauppauge HVR850",
+       },
+       [AU0828_BOARD_HAUPPAUGE_HVR950Q] = {
+               .name   = "Hauppauge HVR950Q",
+       },
+       [AU0828_BOARD_DVICO_FUSIONHDTV7] = {
+               .name   = "DViCO FusionHDTV USB",
+       },
+};
+const unsigned int au0828_bcount = ARRAY_SIZE(au0828_boards);
+
+/* Tuner callback function for au0828 boards. Currently only needed
+ * for HVR1500Q, which has an xc5000 tuner.
+ */
+int au0828_tuner_callback(void *priv, int command, int arg)
+{
+       struct au0828_dev *dev = priv;
+
+       dprintk(1, "%s()\n", __func__);
+
+       switch (dev->board) {
+       case AU0828_BOARD_HAUPPAUGE_HVR850:
+       case AU0828_BOARD_HAUPPAUGE_HVR950Q:
+       case AU0828_BOARD_DVICO_FUSIONHDTV7:
+               if (command == 0) {
+                       /* Tuner Reset Command from xc5000 */
+                       /* Drive the tuner into reset and out */
+                       au0828_clear(dev, REG_001, 2);
+                       mdelay(200);
+                       au0828_set(dev, REG_001, 2);
+                       mdelay(50);
+                       return 0;
+               } else {
+                       printk(KERN_ERR
+                               "%s(): Unknown command.\n", __func__);
+                       return -EINVAL;
+               }
+               break;
+       }
+
+       return 0; /* Should never be here */
+}
+
+static void hauppauge_eeprom(struct au0828_dev *dev, u8 *eeprom_data)
+{
+       struct tveeprom tv;
+
+       tveeprom_hauppauge_analog(&dev->i2c_client, &tv, eeprom_data);
+
+       /* Make sure we support the board model */
+       switch (tv.model) {
+       case 72001: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and basic analog video */
+       case 72301: /* WinTV-HVR850 (Retail, IR, ATSC and basic analog video */
+               break;
+       default:
+               printk(KERN_WARNING "%s: warning: "
+                      "unknown hauppauge model #%d\n", __func__, tv.model);
+               break;
+       }
+
+       printk(KERN_INFO "%s: hauppauge eeprom: model=%d\n",
+              __func__, tv.model);
+}
+
+void au0828_card_setup(struct au0828_dev *dev)
+{
+       static u8 eeprom[256];
+
+       dprintk(1, "%s()\n", __func__);
+
+       if (dev->i2c_rc == 0) {
+               dev->i2c_client.addr = 0xa0 >> 1;
+               tveeprom_read(&dev->i2c_client, eeprom, sizeof(eeprom));
+       }
+
+       switch (dev->board) {
+       case AU0828_BOARD_HAUPPAUGE_HVR850:
+       case AU0828_BOARD_HAUPPAUGE_HVR950Q:
+               if (dev->i2c_rc == 0)
+                       hauppauge_eeprom(dev, eeprom+0xa0);
+               break;
+       }
+}
+
+/*
+ * The bridge has between 8 and 12 gpios.
+ * Regs 1 and 0 deal with output enables.
+ * Regs 3 and 2 deal with direction.
+ */
+void au0828_gpio_setup(struct au0828_dev *dev)
+{
+       dprintk(1, "%s()\n", __func__);
+
+       switch (dev->board) {
+       case AU0828_BOARD_HAUPPAUGE_HVR850:
+       case AU0828_BOARD_HAUPPAUGE_HVR950Q:
+               /* GPIO's
+                * 4 - CS5340
+                * 5 - AU8522 Demodulator
+                * 6 - eeprom W/P
+                * 9 - XC5000 Tuner
+                */
+
+               /* Into reset */
+               au0828_write(dev, REG_003, 0x02);
+               au0828_write(dev, REG_002, 0x88 | 0x20);
+               au0828_write(dev, REG_001, 0x0);
+               au0828_write(dev, REG_000, 0x0);
+               msleep(100);
+
+               /* Out of reset */
+               au0828_write(dev, REG_003, 0x02);
+               au0828_write(dev, REG_001, 0x02);
+               au0828_write(dev, REG_002, 0x88 | 0x20);
+               au0828_write(dev, REG_000, 0x88 | 0x20 | 0x40);
+               msleep(250);
+               break;
+       case AU0828_BOARD_DVICO_FUSIONHDTV7:
+               /* GPIO's
+                * 6 - ?
+                * 8 - AU8522 Demodulator
+                * 9 - XC5000 Tuner
+                */
+
+               /* Into reset */
+               au0828_write(dev, REG_003, 0x02);
+               au0828_write(dev, REG_002, 0xa0);
+               au0828_write(dev, REG_001, 0x0);
+               au0828_write(dev, REG_000, 0x0);
+               msleep(100);
+
+               /* Out of reset */
+               au0828_write(dev, REG_003, 0x02);
+               au0828_write(dev, REG_002, 0xa0);
+               au0828_write(dev, REG_001, 0x02);
+               au0828_write(dev, REG_000, 0xa0);
+               msleep(250);
+               break;
+       }
+}
+
+/* table of devices that work with this driver */
+struct usb_device_id au0828_usb_id_table [] = {
+       { USB_DEVICE(0x2040, 0x7200),
+               .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
+       { USB_DEVICE(0x2040, 0x7240),
+               .driver_info = AU0828_BOARD_HAUPPAUGE_HVR850 },
+       { USB_DEVICE(0x0fe9, 0xd620),
+               .driver_info = AU0828_BOARD_DVICO_FUSIONHDTV7 },
+       { },
+};
+
+MODULE_DEVICE_TABLE(usb, au0828_usb_id_table);
diff --git a/drivers/media/video/au0828/au0828-cards.h b/drivers/media/video/au0828/au0828-cards.h
new file mode 100644 (file)
index 0000000..e26f54a
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ *  Driver for the Auvitek USB bridge
+ *
+ *  Copyright (c) 2008 Steven Toth <stoth@hauppauge.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define AU0828_BOARD_UNKNOWN           0
+#define AU0828_BOARD_HAUPPAUGE_HVR950Q 1
+#define AU0828_BOARD_HAUPPAUGE_HVR850  2
+#define AU0828_BOARD_DVICO_FUSIONHDTV7 3
diff --git a/drivers/media/video/au0828/au0828-core.c b/drivers/media/video/au0828/au0828-core.c
new file mode 100644 (file)
index 0000000..e65d564
--- /dev/null
@@ -0,0 +1,270 @@
+/*
+ *  Driver for the Auvitek USB bridge
+ *
+ *  Copyright (c) 2008 Steven Toth <stoth@hauppauge.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <linux/mutex.h>
+
+#include "au0828.h"
+
+/*
+ * 1 = General debug messages
+ * 2 = USB handling
+ * 4 = I2C related
+ * 8 = Bridge related
+ */
+unsigned int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable debug messages");
+
+unsigned int usb_debug;
+module_param(usb_debug, int, 0644);
+MODULE_PARM_DESC(usb_debug, "enable usb debug messages");
+
+unsigned int bridge_debug;
+module_param(bridge_debug, int, 0644);
+MODULE_PARM_DESC(bridge_debug, "enable bridge debug messages");
+
+#define _AU0828_BULKPIPE 0x03
+#define _BULKPIPESIZE 0xffff
+
+static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value,
+       u16 index, unsigned char *cp, u16 size);
+static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value,
+       u16 index, unsigned char *cp, u16 size);
+
+/* USB Direction */
+#define CMD_REQUEST_IN         0x00
+#define CMD_REQUEST_OUT                0x01
+
+u32 au0828_readreg(struct au0828_dev *dev, u16 reg)
+{
+       recv_control_msg(dev, CMD_REQUEST_IN, 0, reg, dev->ctrlmsg, 1);
+       dprintk(8, "%s(0x%x) = 0x%x\n", __func__, reg, dev->ctrlmsg[0]);
+       return dev->ctrlmsg[0];
+}
+
+u32 au0828_writereg(struct au0828_dev *dev, u16 reg, u32 val)
+{
+       dprintk(8, "%s(0x%x, 0x%x)\n", __func__, reg, val);
+       return send_control_msg(dev, CMD_REQUEST_OUT, val, reg,
+                               dev->ctrlmsg, 0);
+}
+
+static void cmd_msg_dump(struct au0828_dev *dev)
+{
+       int i;
+
+       for (i = 0; i < sizeof(dev->ctrlmsg); i += 16)
+               dprintk(2, "%s() %02x %02x %02x %02x %02x %02x %02x %02x "
+                               "%02x %02x %02x %02x %02x %02x %02x %02x\n",
+                       __func__,
+                       dev->ctrlmsg[i+0], dev->ctrlmsg[i+1],
+                       dev->ctrlmsg[i+2], dev->ctrlmsg[i+3],
+                       dev->ctrlmsg[i+4], dev->ctrlmsg[i+5],
+                       dev->ctrlmsg[i+6], dev->ctrlmsg[i+7],
+                       dev->ctrlmsg[i+8], dev->ctrlmsg[i+9],
+                       dev->ctrlmsg[i+10], dev->ctrlmsg[i+11],
+                       dev->ctrlmsg[i+12], dev->ctrlmsg[i+13],
+                       dev->ctrlmsg[i+14], dev->ctrlmsg[i+15]);
+}
+
+static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value,
+       u16 index, unsigned char *cp, u16 size)
+{
+       int status = -ENODEV;
+       mutex_lock(&dev->mutex);
+       if (dev->usbdev) {
+
+               /* cp must be memory that has been allocated by kmalloc */
+               status = usb_control_msg(dev->usbdev,
+                               usb_sndctrlpipe(dev->usbdev, 0),
+                               request,
+                               USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                               value, index,
+                               cp, size, 1000);
+
+               status = min(status, 0);
+
+               if (status < 0) {
+                       printk(KERN_ERR "%s() Failed sending control message, error %d.\n",
+                               __func__, status);
+               }
+
+       }
+       mutex_unlock(&dev->mutex);
+       return status;
+}
+
+static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value,
+       u16 index, unsigned char *cp, u16 size)
+{
+       int status = -ENODEV;
+       mutex_lock(&dev->mutex);
+       if (dev->usbdev) {
+
+               memset(dev->ctrlmsg, 0, sizeof(dev->ctrlmsg));
+
+               /* cp must be memory that has been allocated by kmalloc */
+               status = usb_control_msg(dev->usbdev,
+                               usb_rcvctrlpipe(dev->usbdev, 0),
+                               request,
+                               USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                               value, index,
+                               cp, size, 1000);
+
+               status = min(status, 0);
+
+               if (status < 0) {
+                       printk(KERN_ERR "%s() Failed receiving control message, error %d.\n",
+                               __func__, status);
+               } else
+                       cmd_msg_dump(dev);
+       }
+       mutex_unlock(&dev->mutex);
+       return status;
+}
+
+static void au0828_usb_disconnect(struct usb_interface *interface)
+{
+       struct au0828_dev *dev = usb_get_intfdata(interface);
+
+       dprintk(1, "%s()\n", __func__);
+
+       /* Digital TV */
+       au0828_dvb_unregister(dev);
+
+       /* I2C */
+       au0828_i2c_unregister(dev);
+
+       usb_set_intfdata(interface, NULL);
+
+       mutex_lock(&dev->mutex);
+       dev->usbdev = NULL;
+       mutex_unlock(&dev->mutex);
+
+       kfree(dev);
+
+}
+
+static int au0828_usb_probe(struct usb_interface *interface,
+       const struct usb_device_id *id)
+{
+       int ifnum;
+       struct au0828_dev *dev;
+       struct usb_device *usbdev = interface_to_usbdev(interface);
+
+       ifnum = interface->altsetting->desc.bInterfaceNumber;
+
+       if (ifnum != 0)
+               return -ENODEV;
+
+       dprintk(1, "%s() vendor id 0x%x device id 0x%x ifnum:%d\n", __func__,
+               le16_to_cpu(usbdev->descriptor.idVendor),
+               le16_to_cpu(usbdev->descriptor.idProduct),
+               ifnum);
+
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+       if (dev == NULL) {
+               printk(KERN_ERR "%s() Unable to allocate memory\n", __func__);
+               return -ENOMEM;
+       }
+
+       mutex_init(&dev->mutex);
+       mutex_init(&dev->dvb.lock);
+       dev->usbdev = usbdev;
+       dev->board = id->driver_info;
+
+       usb_set_intfdata(interface, dev);
+
+       /* Power Up the bridge */
+       au0828_write(dev, REG_600, 1 << 4);
+
+       /* Bring up the GPIO's and supporting devices */
+       au0828_gpio_setup(dev);
+
+       /* I2C */
+       au0828_i2c_register(dev);
+
+       /* Setup */
+       au0828_card_setup(dev);
+
+       /* Digital TV */
+       au0828_dvb_register(dev);
+
+       printk(KERN_INFO "Registered device AU0828 [%s]\n",
+               au0828_boards[dev->board].name == NULL ? "Unset" :
+               au0828_boards[dev->board].name);
+
+       return 0;
+}
+
+static struct usb_driver au0828_usb_driver = {
+       .name           = DRIVER_NAME,
+       .probe          = au0828_usb_probe,
+       .disconnect     = au0828_usb_disconnect,
+       .id_table       = au0828_usb_id_table,
+};
+
+static int __init au0828_init(void)
+{
+       int ret;
+
+       if (debug)
+               printk(KERN_INFO "%s() Debugging is enabled\n", __func__);
+
+       if (usb_debug) {
+               printk(KERN_INFO "%s() USB Debugging is enabled\n", __func__);
+               debug |= 2;
+       }
+
+       if (i2c_debug) {
+               printk(KERN_INFO "%s() I2C Debugging is enabled\n", __func__);
+               debug |= 4;
+       }
+
+       if (bridge_debug) {
+               printk(KERN_INFO "%s() Bridge Debugging is enabled\n",
+                      __func__);
+               debug |= 8;
+       }
+
+       printk(KERN_INFO "au0828 driver loaded\n");
+
+       ret = usb_register(&au0828_usb_driver);
+       if (ret)
+               printk(KERN_ERR "usb_register failed, error = %d\n", ret);
+
+       return ret;
+}
+
+static void __exit au0828_exit(void)
+{
+       usb_deregister(&au0828_usb_driver);
+}
+
+module_init(au0828_init);
+module_exit(au0828_exit);
+
+MODULE_DESCRIPTION("Driver for Auvitek AU0828 based products");
+MODULE_AUTHOR("Steven Toth <stoth@hauppauge.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/au0828/au0828-dvb.c b/drivers/media/video/au0828/au0828-dvb.c
new file mode 100644 (file)
index 0000000..85d0ae9
--- /dev/null
@@ -0,0 +1,373 @@
+/*
+ *  Driver for the Auvitek USB bridge
+ *
+ *  Copyright (c) 2008 Steven Toth <stoth@hauppauge.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/suspend.h>
+#include <media/v4l2-common.h>
+
+#include "au0828.h"
+#include "au8522.h"
+#include "xc5000.h"
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+#define _AU0828_BULKPIPE 0x83
+#define _BULKPIPESIZE 0xe522
+
+static struct au8522_config hauppauge_hvr950q_config = {
+       .demod_address = 0x8e >> 1,
+       .status_mode   = AU8522_DEMODLOCKING,
+};
+
+static struct xc5000_config hauppauge_hvr950q_tunerconfig = {
+       .i2c_address      = 0x61,
+       .if_khz           = 6000,
+       .tuner_callback   = au0828_tuner_callback
+};
+
+/*-------------------------------------------------------------------*/
+static void urb_completion(struct urb *purb)
+{
+       u8 *ptr;
+       struct au0828_dev *dev = purb->context;
+       int ptype = usb_pipetype(purb->pipe);
+
+       dprintk(2, "%s()\n", __func__);
+
+       if (!dev)
+               return;
+
+       if (dev->urb_streaming == 0)
+               return;
+
+       if (ptype != PIPE_BULK) {
+               printk(KERN_ERR "%s() Unsupported URB type %d\n",
+                      __func__, ptype);
+               return;
+       }
+
+       ptr = (u8 *)purb->transfer_buffer;
+
+       /* Feed the transport payload into the kernel demux */
+       dvb_dmx_swfilter_packets(&dev->dvb.demux,
+               purb->transfer_buffer, purb->actual_length / 188);
+
+       /* Clean the buffer before we requeue */
+       memset(purb->transfer_buffer, 0, URB_BUFSIZE);
+
+       /* Requeue URB */
+       usb_submit_urb(purb, GFP_ATOMIC);
+}
+
+static int stop_urb_transfer(struct au0828_dev *dev)
+{
+       int i;
+
+       dprintk(2, "%s()\n", __func__);
+
+       for (i = 0; i < URB_COUNT; i++) {
+               usb_kill_urb(dev->urbs[i]);
+               kfree(dev->urbs[i]->transfer_buffer);
+               usb_free_urb(dev->urbs[i]);
+       }
+
+       dev->urb_streaming = 0;
+
+       return 0;
+}
+
+static int start_urb_transfer(struct au0828_dev *dev)
+{
+       struct urb *purb;
+       int i, ret = -ENOMEM;
+
+       dprintk(2, "%s()\n", __func__);
+
+       if (dev->urb_streaming) {
+               dprintk(2, "%s: iso xfer already running!\n", __func__);
+               return 0;
+       }
+
+       for (i = 0; i < URB_COUNT; i++) {
+
+               dev->urbs[i] = usb_alloc_urb(0, GFP_KERNEL);
+               if (!dev->urbs[i])
+                       goto err;
+
+               purb = dev->urbs[i];
+
+               purb->transfer_buffer = kzalloc(URB_BUFSIZE, GFP_KERNEL);
+               if (!purb->transfer_buffer) {
+                       usb_free_urb(purb);
+                       dev->urbs[i] = 0;
+                       goto err;
+               }
+
+               purb->status = -EINPROGRESS;
+               usb_fill_bulk_urb(purb,
+                                 dev->usbdev,
+                                 usb_rcvbulkpipe(dev->usbdev, _AU0828_BULKPIPE),
+                                 purb->transfer_buffer,
+                                 URB_BUFSIZE,
+                                 urb_completion,
+                                 dev);
+
+       }
+
+       for (i = 0; i < URB_COUNT; i++) {
+               ret = usb_submit_urb(dev->urbs[i], GFP_ATOMIC);
+               if (ret != 0) {
+                       stop_urb_transfer(dev);
+                       printk(KERN_ERR "%s: failed urb submission, "
+                              "err = %d\n", __func__, ret);
+                       return ret;
+               }
+       }
+
+       dev->urb_streaming = 1;
+       ret = 0;
+
+err:
+       return ret;
+}
+
+static int au0828_dvb_start_feed(struct dvb_demux_feed *feed)
+{
+       struct dvb_demux *demux = feed->demux;
+       struct au0828_dev *dev = (struct au0828_dev *) demux->priv;
+       struct au0828_dvb *dvb = &dev->dvb;
+       int ret = 0;
+
+       dprintk(1, "%s()\n", __func__);
+
+       if (!demux->dmx.frontend)
+               return -EINVAL;
+
+       if (dvb) {
+               mutex_lock(&dvb->lock);
+               if (dvb->feeding++ == 0) {
+                       /* Start transport */
+                       au0828_write(dev, 0x608, 0x90);
+                       au0828_write(dev, 0x609, 0x72);
+                       au0828_write(dev, 0x60a, 0x71);
+                       au0828_write(dev, 0x60b, 0x01);
+                       ret = start_urb_transfer(dev);
+               }
+               mutex_unlock(&dvb->lock);
+       }
+
+       return ret;
+}
+
+static int au0828_dvb_stop_feed(struct dvb_demux_feed *feed)
+{
+       struct dvb_demux *demux = feed->demux;
+       struct au0828_dev *dev = (struct au0828_dev *) demux->priv;
+       struct au0828_dvb *dvb = &dev->dvb;
+       int ret = 0;
+
+       dprintk(1, "%s()\n", __func__);
+
+       if (dvb) {
+               mutex_lock(&dvb->lock);
+               if (--dvb->feeding == 0) {
+                       /* Stop transport */
+                       au0828_write(dev, 0x608, 0x00);
+                       au0828_write(dev, 0x609, 0x00);
+                       au0828_write(dev, 0x60a, 0x00);
+                       au0828_write(dev, 0x60b, 0x00);
+                       ret = stop_urb_transfer(dev);
+               }
+               mutex_unlock(&dvb->lock);
+       }
+
+       return ret;
+}
+
+int dvb_register(struct au0828_dev *dev)
+{
+       struct au0828_dvb *dvb = &dev->dvb;
+       int result;
+
+       dprintk(1, "%s()\n", __func__);
+
+       /* register adapter */
+       result = dvb_register_adapter(&dvb->adapter, DRIVER_NAME, THIS_MODULE,
+                                     &dev->usbdev->dev, adapter_nr);
+       if (result < 0) {
+               printk(KERN_ERR "%s: dvb_register_adapter failed "
+                      "(errno = %d)\n", DRIVER_NAME, result);
+               goto fail_adapter;
+       }
+       dvb->adapter.priv = dev;
+
+       /* register frontend */
+       result = dvb_register_frontend(&dvb->adapter, dvb->frontend);
+       if (result < 0) {
+               printk(KERN_ERR "%s: dvb_register_frontend failed "
+                      "(errno = %d)\n", DRIVER_NAME, result);
+               goto fail_frontend;
+       }
+
+       /* register demux stuff */
+       dvb->demux.dmx.capabilities =
+               DMX_TS_FILTERING | DMX_SECTION_FILTERING |
+               DMX_MEMORY_BASED_FILTERING;
+       dvb->demux.priv       = dev;
+       dvb->demux.filternum  = 256;
+       dvb->demux.feednum    = 256;
+       dvb->demux.start_feed = au0828_dvb_start_feed;
+       dvb->demux.stop_feed  = au0828_dvb_stop_feed;
+       result = dvb_dmx_init(&dvb->demux);
+       if (result < 0) {
+               printk(KERN_ERR "%s: dvb_dmx_init failed (errno = %d)\n",
+                      DRIVER_NAME, result);
+               goto fail_dmx;
+       }
+
+       dvb->dmxdev.filternum    = 256;
+       dvb->dmxdev.demux        = &dvb->demux.dmx;
+       dvb->dmxdev.capabilities = 0;
+       result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter);
+       if (result < 0) {
+               printk(KERN_ERR "%s: dvb_dmxdev_init failed (errno = %d)\n",
+                      DRIVER_NAME, result);
+               goto fail_dmxdev;
+       }
+
+       dvb->fe_hw.source = DMX_FRONTEND_0;
+       result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw);
+       if (result < 0) {
+               printk(KERN_ERR "%s: add_frontend failed "
+                      "(DMX_FRONTEND_0, errno = %d)\n", DRIVER_NAME, result);
+               goto fail_fe_hw;
+       }
+
+       dvb->fe_mem.source = DMX_MEMORY_FE;
+       result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem);
+       if (result < 0) {
+               printk(KERN_ERR "%s: add_frontend failed "
+                      "(DMX_MEMORY_FE, errno = %d)\n", DRIVER_NAME, result);
+               goto fail_fe_mem;
+       }
+
+       result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw);
+       if (result < 0) {
+               printk(KERN_ERR "%s: connect_frontend failed (errno = %d)\n",
+                      DRIVER_NAME, result);
+               goto fail_fe_conn;
+       }
+
+       /* register network adapter */
+       dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx);
+       return 0;
+
+fail_fe_conn:
+       dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
+fail_fe_mem:
+       dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
+fail_fe_hw:
+       dvb_dmxdev_release(&dvb->dmxdev);
+fail_dmxdev:
+       dvb_dmx_release(&dvb->demux);
+fail_dmx:
+       dvb_unregister_frontend(dvb->frontend);
+fail_frontend:
+       dvb_frontend_detach(dvb->frontend);
+       dvb_unregister_adapter(&dvb->adapter);
+fail_adapter:
+       return result;
+}
+
+void au0828_dvb_unregister(struct au0828_dev *dev)
+{
+       struct au0828_dvb *dvb = &dev->dvb;
+
+       dprintk(1, "%s()\n", __func__);
+
+       if (dvb->frontend == NULL)
+               return;
+
+       dvb_net_release(&dvb->net);
+       dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
+       dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
+       dvb_dmxdev_release(&dvb->dmxdev);
+       dvb_dmx_release(&dvb->demux);
+       dvb_unregister_frontend(dvb->frontend);
+       dvb_frontend_detach(dvb->frontend);
+       dvb_unregister_adapter(&dvb->adapter);
+}
+
+/* All the DVB attach calls go here, this function get's modified
+ * for each new card. No other function in this file needs
+ * to change.
+ */
+int au0828_dvb_register(struct au0828_dev *dev)
+{
+       struct au0828_dvb *dvb = &dev->dvb;
+       int ret;
+
+       dprintk(1, "%s()\n", __func__);
+
+       /* init frontend */
+       switch (dev->board) {
+       case AU0828_BOARD_HAUPPAUGE_HVR850:
+       case AU0828_BOARD_HAUPPAUGE_HVR950Q:
+       case AU0828_BOARD_DVICO_FUSIONHDTV7:
+               dvb->frontend = dvb_attach(au8522_attach,
+                               &hauppauge_hvr950q_config,
+                               &dev->i2c_adap);
+               if (dvb->frontend != NULL) {
+                       hauppauge_hvr950q_tunerconfig.priv = dev;
+                       dvb_attach(xc5000_attach, dvb->frontend,
+                               &dev->i2c_adap,
+                               &hauppauge_hvr950q_tunerconfig);
+               }
+               break;
+       default:
+               printk(KERN_WARNING "The frontend of your DVB/ATSC card "
+                      "isn't supported yet\n");
+               break;
+       }
+       if (NULL == dvb->frontend) {
+               printk(KERN_ERR "%s() Frontend initialization failed\n",
+                      __func__);
+               return -1;
+       }
+
+       /* Put the analog decoder in standby to keep it quiet */
+       au0828_call_i2c_clients(dev, TUNER_SET_STANDBY, NULL);
+
+       if (dvb->frontend->ops.analog_ops.standby)
+               dvb->frontend->ops.analog_ops.standby(dvb->frontend);
+
+       /* register everything */
+       ret = dvb_register(dev);
+       if (ret < 0) {
+               if (dvb->frontend->ops.release)
+                       dvb->frontend->ops.release(dvb->frontend);
+               return ret;
+       }
+
+       return 0;
+}
diff --git a/drivers/media/video/au0828/au0828-i2c.c b/drivers/media/video/au0828/au0828-i2c.c
new file mode 100644 (file)
index 0000000..94c8b74
--- /dev/null
@@ -0,0 +1,385 @@
+/*
+ *  Driver for the Auvitek AU0828 USB bridge
+ *
+ *  Copyright (c) 2008 Steven Toth <stoth@hauppauge.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+
+#include "au0828.h"
+
+#include <media/v4l2-common.h>
+
+unsigned int i2c_debug;
+module_param(i2c_debug, int, 0444);
+MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
+
+unsigned int i2c_scan;
+module_param(i2c_scan, int, 0444);
+MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
+
+#define I2C_WAIT_DELAY 512
+#define I2C_WAIT_RETRY 64
+
+static inline int i2c_slave_did_write_ack(struct i2c_adapter *i2c_adap)
+{
+       struct au0828_dev *dev = i2c_adap->algo_data;
+       return au0828_read(dev, REG_201) & 0x08 ? 0 : 1;
+}
+
+static inline int i2c_slave_did_read_ack(struct i2c_adapter *i2c_adap)
+{
+       struct au0828_dev *dev = i2c_adap->algo_data;
+       return au0828_read(dev, REG_201) & 0x02 ? 0 : 1;
+}
+
+static int i2c_wait_read_ack(struct i2c_adapter *i2c_adap)
+{
+       int count;
+
+       for (count = 0; count < I2C_WAIT_RETRY; count++) {
+               if (!i2c_slave_did_read_ack(i2c_adap))
+                       break;
+               udelay(I2C_WAIT_DELAY);
+       }
+
+       if (I2C_WAIT_RETRY == count)
+               return 0;
+
+       return 1;
+}
+
+static inline int i2c_is_read_busy(struct i2c_adapter *i2c_adap)
+{
+       struct au0828_dev *dev = i2c_adap->algo_data;
+       return au0828_read(dev, REG_201) & 0x01 ? 0 : 1;
+}
+
+static int i2c_wait_read_done(struct i2c_adapter *i2c_adap)
+{
+       int count;
+
+       for (count = 0; count < I2C_WAIT_RETRY; count++) {
+               if (!i2c_is_read_busy(i2c_adap))
+                       break;
+               udelay(I2C_WAIT_DELAY);
+       }
+
+       if (I2C_WAIT_RETRY == count)
+               return 0;
+
+       return 1;
+}
+
+static inline int i2c_is_write_done(struct i2c_adapter *i2c_adap)
+{
+       struct au0828_dev *dev = i2c_adap->algo_data;
+       return au0828_read(dev, REG_201) & 0x04 ? 1 : 0;
+}
+
+static int i2c_wait_write_done(struct i2c_adapter *i2c_adap)
+{
+       int count;
+
+       for (count = 0; count < I2C_WAIT_RETRY; count++) {
+               if (i2c_is_write_done(i2c_adap))
+                       break;
+               udelay(I2C_WAIT_DELAY);
+       }
+
+       if (I2C_WAIT_RETRY == count)
+               return 0;
+
+       return 1;
+}
+
+static inline int i2c_is_busy(struct i2c_adapter *i2c_adap)
+{
+       struct au0828_dev *dev = i2c_adap->algo_data;
+       return au0828_read(dev, REG_201) & 0x10 ? 1 : 0;
+}
+
+static int i2c_wait_done(struct i2c_adapter *i2c_adap)
+{
+       int count;
+
+       for (count = 0; count < I2C_WAIT_RETRY; count++) {
+               if (!i2c_is_busy(i2c_adap))
+                       break;
+               udelay(I2C_WAIT_DELAY);
+       }
+
+       if (I2C_WAIT_RETRY == count)
+               return 0;
+
+       return 1;
+}
+
+/* FIXME: Implement join handling correctly */
+static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
+       const struct i2c_msg *msg, int joined_rlen)
+{
+       int i, strobe = 0;
+       struct au0828_dev *dev = i2c_adap->algo_data;
+
+       dprintk(4, "%s()\n", __func__);
+
+       au0828_write(dev, REG_2FF, 0x01);
+       au0828_write(dev, REG_202, 0x07);
+
+       /* Hardware needs 8 bit addresses */
+       au0828_write(dev, REG_203, msg->addr << 1);
+
+       dprintk(4, "SEND: %02x\n", msg->addr);
+
+       for (i = 0; i < msg->len;) {
+
+               dprintk(4, " %02x\n", msg->buf[i]);
+
+               au0828_write(dev, REG_205, msg->buf[i]);
+
+               strobe++;
+               i++;
+
+               if ((strobe >= 4) || (i >= msg->len)) {
+
+                       /* Strobe the byte into the bus */
+                       if (i < msg->len)
+                               au0828_write(dev, REG_200, 0x41);
+                       else
+                               au0828_write(dev, REG_200, 0x01);
+
+                       /* Reset strobe trigger */
+                       strobe = 0;
+
+                       if (!i2c_wait_write_done(i2c_adap))
+                               return -EIO;
+
+               }
+
+       }
+       if (!i2c_wait_done(i2c_adap))
+               return -EIO;
+
+       dprintk(4, "\n");
+
+       return msg->len;
+}
+
+/* FIXME: Implement join handling correctly */
+static int i2c_readbytes(struct i2c_adapter *i2c_adap,
+       const struct i2c_msg *msg, int joined)
+{
+       struct au0828_dev *dev = i2c_adap->algo_data;
+       int i;
+
+       dprintk(4, "%s()\n", __func__);
+
+       au0828_write(dev, REG_2FF, 0x01);
+       au0828_write(dev, REG_202, 0x07);
+
+       /* Hardware needs 8 bit addresses */
+       au0828_write(dev, REG_203, msg->addr << 1);
+
+       dprintk(4, " RECV:\n");
+
+       /* Deal with i2c_scan */
+       if (msg->len == 0) {
+               au0828_write(dev, REG_200, 0x20);
+               if (i2c_wait_read_ack(i2c_adap))
+                       return -EIO;
+               return 0;
+       }
+
+       for (i = 0; i < msg->len;) {
+
+               i++;
+
+               if (i < msg->len)
+                       au0828_write(dev, REG_200, 0x60);
+               else
+                       au0828_write(dev, REG_200, 0x20);
+
+               if (!i2c_wait_read_done(i2c_adap))
+                       return -EIO;
+
+               msg->buf[i-1] = au0828_read(dev, REG_209) & 0xff;
+
+               dprintk(4, " %02x\n", msg->buf[i-1]);
+       }
+       if (!i2c_wait_done(i2c_adap))
+               return -EIO;
+
+       dprintk(4, "\n");
+
+       return msg->len;
+}
+
+static int i2c_xfer(struct i2c_adapter *i2c_adap,
+                   struct i2c_msg *msgs, int num)
+{
+       int i, retval = 0;
+
+       dprintk(4, "%s(num = %d)\n", __func__, num);
+
+       for (i = 0; i < num; i++) {
+               dprintk(4, "%s(num = %d) addr = 0x%02x  len = 0x%x\n",
+                       __func__, num, msgs[i].addr, msgs[i].len);
+               if (msgs[i].flags & I2C_M_RD) {
+                       /* read */
+                       retval = i2c_readbytes(i2c_adap, &msgs[i], 0);
+               } else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) &&
+                          msgs[i].addr == msgs[i + 1].addr) {
+                       /* write then read from same address */
+                       retval = i2c_sendbytes(i2c_adap, &msgs[i],
+                                              msgs[i + 1].len);
+                       if (retval < 0)
+                               goto err;
+                       i++;
+                       retval = i2c_readbytes(i2c_adap, &msgs[i], 1);
+               } else {
+                       /* write */
+                       retval = i2c_sendbytes(i2c_adap, &msgs[i], 0);
+               }
+               if (retval < 0)
+                       goto err;
+       }
+       return num;
+
+err:
+       return retval;
+}
+
+static int attach_inform(struct i2c_client *client)
+{
+       dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n",
+               client->driver->driver.name, client->addr, client->name);
+
+       if (!client->driver->command)
+               return 0;
+
+       return 0;
+}
+
+static int detach_inform(struct i2c_client *client)
+{
+       dprintk(1, "i2c detach [client=%s]\n", client->name);
+
+       return 0;
+}
+
+void au0828_call_i2c_clients(struct au0828_dev *dev,
+                             unsigned int cmd, void *arg)
+{
+       if (dev->i2c_rc != 0)
+               return;
+
+       i2c_clients_command(&dev->i2c_adap, cmd, arg);
+}
+
+static u32 au0828_functionality(struct i2c_adapter *adap)
+{
+       return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm au0828_i2c_algo_template = {
+       .master_xfer    = i2c_xfer,
+       .functionality  = au0828_functionality,
+};
+
+/* ----------------------------------------------------------------------- */
+
+static struct i2c_adapter au0828_i2c_adap_template = {
+       .name              = DRIVER_NAME,
+       .owner             = THIS_MODULE,
+       .id                = I2C_HW_B_AU0828,
+       .algo              = &au0828_i2c_algo_template,
+       .class             = I2C_CLASS_TV_ANALOG,
+       .client_register   = attach_inform,
+       .client_unregister = detach_inform,
+};
+
+static struct i2c_client au0828_i2c_client_template = {
+       .name   = "au0828 internal",
+};
+
+static char *i2c_devs[128] = {
+       [0x8e >> 1] = "au8522",
+       [0xa0 >> 1] = "eeprom",
+       [0xc2 >> 1] = "tuner/xc5000",
+};
+
+static void do_i2c_scan(char *name, struct i2c_client *c)
+{
+       unsigned char buf;
+       int i, rc;
+
+       for (i = 0; i < 128; i++) {
+               c->addr = i;
+               rc = i2c_master_recv(c, &buf, 0);
+               if (rc < 0)
+                       continue;
+               printk(KERN_INFO "%s: i2c scan: found device @ 0x%x  [%s]\n",
+                      name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
+       }
+}
+
+/* init + register i2c algo-bit adapter */
+int au0828_i2c_register(struct au0828_dev *dev)
+{
+       dprintk(1, "%s()\n", __func__);
+
+       memcpy(&dev->i2c_adap, &au0828_i2c_adap_template,
+              sizeof(dev->i2c_adap));
+       memcpy(&dev->i2c_algo, &au0828_i2c_algo_template,
+              sizeof(dev->i2c_algo));
+       memcpy(&dev->i2c_client, &au0828_i2c_client_template,
+              sizeof(dev->i2c_client));
+
+       dev->i2c_adap.dev.parent = &dev->usbdev->dev;
+
+       strlcpy(dev->i2c_adap.name, DRIVER_NAME,
+               sizeof(dev->i2c_adap.name));
+
+       dev->i2c_algo.data = dev;
+       dev->i2c_adap.algo_data = dev;
+       i2c_set_adapdata(&dev->i2c_adap, dev);
+       i2c_add_adapter(&dev->i2c_adap);
+
+       dev->i2c_client.adapter = &dev->i2c_adap;
+
+       if (0 == dev->i2c_rc) {
+               printk(KERN_INFO "%s: i2c bus registered\n", DRIVER_NAME);
+               if (i2c_scan)
+                       do_i2c_scan(DRIVER_NAME, &dev->i2c_client);
+       } else
+               printk(KERN_INFO "%s: i2c bus register FAILED\n", DRIVER_NAME);
+
+       return dev->i2c_rc;
+}
+
+int au0828_i2c_unregister(struct au0828_dev *dev)
+{
+       i2c_del_adapter(&dev->i2c_adap);
+       return 0;
+}
+
diff --git a/drivers/media/video/au0828/au0828-reg.h b/drivers/media/video/au0828/au0828-reg.h
new file mode 100644 (file)
index 0000000..3982755
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ *  Driver for the Auvitek USB bridge
+ *
+ *  Copyright (c) 2008 Steven Toth <stoth@hauppauge.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* We'll start to rename these registers once we have a better
+ * understanding of their meaning.
+ */
+#define REG_000 0x000
+#define REG_001 0x001
+#define REG_002 0x002
+#define REG_003 0x003
+
+#define REG_200 0x200
+#define REG_201 0x201
+#define REG_202 0x202
+#define REG_203 0x203
+#define REG_205 0x205
+#define REG_209 0x209
+#define REG_2FF 0x2ff
+
+#define REG_600 0x600
diff --git a/drivers/media/video/au0828/au0828.h b/drivers/media/video/au0828/au0828.h
new file mode 100644 (file)
index 0000000..0200b9f
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ *  Driver for the Auvitek AU0828 USB bridge
+ *
+ *  Copyright (c) 2008 Steven Toth <stoth@hauppauge.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/usb.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <media/tveeprom.h>
+
+/* DVB */
+#include "demux.h"
+#include "dmxdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+#include "dvbdev.h"
+
+#include "au0828-reg.h"
+#include "au0828-cards.h"
+
+#define DRIVER_NAME "au0828"
+#define URB_COUNT   16
+#define URB_BUFSIZE (0xe522)
+
+struct au0828_board {
+       char *name;
+};
+
+struct au0828_dvb {
+       struct mutex lock;
+       struct dvb_adapter adapter;
+       struct dvb_frontend *frontend;
+       struct dvb_demux demux;
+       struct dmxdev dmxdev;
+       struct dmx_frontend fe_hw;
+       struct dmx_frontend fe_mem;
+       struct dvb_net net;
+       int feeding;
+};
+
+struct au0828_dev {
+       struct mutex mutex;
+       struct usb_device       *usbdev;
+       int                     board;
+       u8                      ctrlmsg[64];
+
+       /* I2C */
+       struct i2c_adapter              i2c_adap;
+       struct i2c_algo_bit_data        i2c_algo;
+       struct i2c_client               i2c_client;
+       u32                             i2c_rc;
+
+       /* Digital */
+       struct au0828_dvb               dvb;
+
+       /* USB / URB Related */
+       int             urb_streaming;
+       struct urb      *urbs[URB_COUNT];
+
+};
+
+struct au0828_buff {
+       struct au0828_dev       *dev;
+       struct urb              *purb;
+       struct list_head        buff_list;
+};
+
+/* ----------------------------------------------------------- */
+#define au0828_read(dev, reg) au0828_readreg(dev, reg)
+#define au0828_write(dev, reg, value) au0828_writereg(dev, reg, value)
+#define au0828_andor(dev, reg, mask, value)                            \
+        au0828_writereg(dev, reg,                                      \
+       (au0828_readreg(dev, reg) & ~(mask)) | ((value) & (mask)))
+
+#define au0828_set(dev, reg, bit) au0828_andor(dev, (reg), (bit), (bit))
+#define au0828_clear(dev, reg, bit) au0828_andor(dev, (reg), (bit), 0)
+
+/* ----------------------------------------------------------- */
+/* au0828-core.c */
+extern u32 au0828_read(struct au0828_dev *dev, u16 reg);
+extern u32 au0828_write(struct au0828_dev *dev, u16 reg, u32 val);
+extern unsigned int debug;
+extern unsigned int usb_debug;
+extern unsigned int bridge_debug;
+
+/* ----------------------------------------------------------- */
+/* au0828-cards.c */
+extern struct au0828_board au0828_boards[];
+extern struct usb_device_id au0828_usb_id_table[];
+extern const unsigned int au0828_bcount;
+extern void au0828_gpio_setup(struct au0828_dev *dev);
+extern int au0828_tuner_callback(void *priv, int command, int arg);
+extern void au0828_card_setup(struct au0828_dev *dev);
+
+/* ----------------------------------------------------------- */
+/* au0828-i2c.c */
+extern int au0828_i2c_register(struct au0828_dev *dev);
+extern int au0828_i2c_unregister(struct au0828_dev *dev);
+extern void au0828_call_i2c_clients(struct au0828_dev *dev,
+       unsigned int cmd, void *arg);
+extern unsigned int i2c_debug;
+
+/* ----------------------------------------------------------- */
+/* au0828-dvb.c */
+extern int au0828_dvb_register(struct au0828_dev *dev);
+extern void au0828_dvb_unregister(struct au0828_dev *dev);
+
+#define dprintk(level, fmt, arg...)\
+       do { if (debug & level)\
+               printk(KERN_DEBUG DRIVER_NAME "/0: " fmt, ## arg);\
+       } while (0)
index e663cc045c41c7a1748145b0b78f7ea41860c628..8bfd5c75cb3a736b04218cb697a870c8d5ab936d 100644 (file)
@@ -57,7 +57,7 @@ MODULE_LICENSE("GPL");
 #define I2C_NAME(s) (s)->name
 
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0-1)");
 
index 7dee2e3235ad5619a735c0c74db3c4c67d25cd32..98ee2d8feb34ecbcb5282112e1b49a0e7b5957f6 100644 (file)
@@ -56,7 +56,7 @@ MODULE_LICENSE("GPL");
 #define I2C_NAME(s) (s)->name
 
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0-1)");
 
index 7374c02dd183fc1a5d457b8899828dab9c195dd8..f20a01cfc73e442dea087f4962c09cad5f603a12 100644 (file)
@@ -71,6 +71,8 @@ static void kodicom4400r_init(struct bttv *btv);
 static void sigmaSLC_muxsel(struct bttv *btv, unsigned int input);
 static void sigmaSQ_muxsel(struct bttv *btv, unsigned int input);
 
+static void geovision_muxsel(struct bttv *btv, unsigned int input);
+
 static int terratec_active_radio_upgrade(struct bttv *btv);
 static int tea5757_read(struct bttv *btv);
 static int tea5757_write(struct bttv *btv, int value);
@@ -301,6 +303,7 @@ static struct CARD {
        { 0xd50018ac, BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE,    "DViCO FusionHDTV 5 Lite" },
        { 0x00261822, BTTV_BOARD_TWINHAN_DST,   "DNTV Live! Mini "},
        { 0xd200dbc0, BTTV_BOARD_DVICO_FUSIONHDTV_2,    "DViCO FusionHDTV 2" },
+       { 0x763c008a, BTTV_BOARD_GEOVISION_GV600,       "GeoVision GV-600" },
 
        { 0, -1, NULL }
 };
@@ -576,6 +579,8 @@ struct tvcard bttv_tvcards[] = {
                .needs_tvaudio  = 1,
                .pll            = PLL_28,
                .tuner_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
        },
        [BTTV_BOARD_WINVIEW_601] = {
                .name           = "Leadtek WinView 601",
@@ -2322,7 +2327,7 @@ struct tvcard bttv_tvcards[] = {
                .tuner          = 0,
                .svhs           = 2,
                .muxsel         = { 2, 3, 1, 0 },
-               .tuner_type     = TUNER_PHILIPS_ATSC,
+               .tuner_type     = TUNER_PHILIPS_FCV1236D,
                .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
                .has_dvb        = 1,
@@ -2961,7 +2966,7 @@ struct tvcard bttv_tvcards[] = {
        [BTTV_BOARD_DVICO_FUSIONHDTV_2] = {
                .name           = "DViCO FusionHDTV 2",
                .tuner          = 0,
-               .tuner_type     = TUNER_PHILIPS_ATSC, /* FCV1236D */
+               .tuner_type     = TUNER_PHILIPS_FCV1236D,
                .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
                .video_inputs   = 3,
@@ -2992,6 +2997,45 @@ struct tvcard bttv_tvcards[] = {
                .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
        },
+       [BTTV_BOARD_GEOVISION_GV600] = {
+               /* emhn@usb.ve */
+               .name             = "Geovision GV-600",
+               .video_inputs     = 16,
+               .audio_inputs     = 0,
+               .tuner            = UNSET,
+               .svhs             = UNSET,
+               .gpiomask         = 0x0,
+               .muxsel           = { 2, 2, 2, 2, 2, 2, 2, 2,
+                                     2, 2, 2, 2, 2, 2, 2, 2 },
+               .muxsel_hook      = geovision_muxsel,
+               .gpiomux          = { 0 },
+               .no_msp34xx       = 1,
+               .pll              = PLL_28,
+               .tuner_type       = UNSET,
+               .tuner_addr       = ADDR_UNSET,
+               .radio_addr       = ADDR_UNSET,
+       },
+       [BTTV_BOARD_KOZUMI_KTV_01C] = {
+               /* Mauro Lacy <mauro@lacy.com.ar>
+                * Based on MagicTV and Conceptronic CONTVFMi */
+
+               .name           = "Kozumi KTV-01C",
+               .video_inputs   = 3,
+               .audio_inputs   = 1,
+               .tuner          = 0,
+               .svhs           = 2,
+               .gpiomask       = 0x008007,
+               .muxsel         = { 2, 3, 1, 1 },
+               .gpiomux        = { 0, 1, 2, 2 }, /* CONTVFMi */
+               .gpiomute       = 3, /* CONTVFMi */
+               .needs_tvaudio  = 0,
+               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3, /* TCL MK3 */
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .pll            = PLL_28,
+               .has_radio      = 1,
+               .has_remote     = 1,
+       },
 };
 
 static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards);
@@ -3331,6 +3375,13 @@ static void sigmaSLC_muxsel(struct bttv *btv, unsigned int input)
        gpio_bits( 3<<9, inmux<<9 );
 }
 
+static void geovision_muxsel(struct bttv *btv, unsigned int input)
+{
+       unsigned int inmux = input % 16;
+       gpio_inout(0xf, 0xf);
+       gpio_bits(0xf, inmux);
+}
+
 /* ----------------------------------------------------------------------- */
 
 static void bttv_reset_audio(struct bttv *btv)
index fcf8f2d208a843890df86252ee7579f52cfb385e..2ca3e9cfb2bbbaf0887e70e23624268002e328f5 100644 (file)
@@ -2372,7 +2372,7 @@ static int setup_window(struct bttv_fh *fh, struct bttv *btv,
        if (check_btres(fh, RESOURCE_OVERLAY)) {
                struct bttv_buffer *new;
 
-               new = videobuf_pci_alloc(sizeof(*new));
+               new = videobuf_sg_alloc(sizeof(*new));
                new->crop = btv->crop[!!fh->do_crop].rect;
                bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
                retval = bttv_switch_overlay(btv,fh,new);
@@ -2760,7 +2760,7 @@ static int bttv_overlay(struct file *file, void *f, unsigned int on)
        mutex_lock(&fh->cap.vb_lock);
        if (on) {
                fh->ov.tvnorm = btv->tvnorm;
-               new = videobuf_pci_alloc(sizeof(*new));
+               new = videobuf_sg_alloc(sizeof(*new));
                new->crop = btv->crop[!!fh->do_crop].rect;
                bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
        } else {
@@ -2834,7 +2834,7 @@ static int bttv_s_fbuf(struct file *file, void *f,
                if (check_btres(fh, RESOURCE_OVERLAY)) {
                        struct bttv_buffer *new;
 
-                       new = videobuf_pci_alloc(sizeof(*new));
+                       new = videobuf_sg_alloc(sizeof(*new));
                        new->crop = btv->crop[!!fh->do_crop].rect;
                        bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
                        retval = bttv_switch_overlay(btv, fh, new);
@@ -3117,12 +3117,18 @@ static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop)
 
 static int bttv_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
 {
+       if (unlikely(a->index))
+               return -EINVAL;
+
        strcpy(a->name, "audio");
        return 0;
 }
 
 static int bttv_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
 {
+       if (unlikely(a->index))
+               return -EINVAL;
+
        return 0;
 }
 
@@ -3184,7 +3190,7 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait)
                        /* need to capture a new frame */
                        if (locked_btres(fh->btv,RESOURCE_VIDEO_STREAM))
                                goto err;
-                       fh->cap.read_buf = videobuf_pci_alloc(fh->cap.msize);
+                       fh->cap.read_buf = videobuf_sg_alloc(fh->cap.msize);
                        if (NULL == fh->cap.read_buf)
                                goto err;
                        fh->cap.read_buf->memory = V4L2_MEMORY_USERPTR;
@@ -3251,14 +3257,14 @@ static int bttv_open(struct inode *inode, struct file *file)
        fh->ov.setup_ok = 0;
        v4l2_prio_open(&btv->prio,&fh->prio);
 
-       videobuf_queue_pci_init(&fh->cap, &bttv_video_qops,
-                           btv->c.pci, &btv->s_lock,
+       videobuf_queue_sg_init(&fh->cap, &bttv_video_qops,
+                           &btv->c.pci->dev, &btv->s_lock,
                            V4L2_BUF_TYPE_VIDEO_CAPTURE,
                            V4L2_FIELD_INTERLACED,
                            sizeof(struct bttv_buffer),
                            fh);
-       videobuf_queue_pci_init(&fh->vbi, &bttv_vbi_qops,
-                           btv->c.pci, &btv->s_lock,
+       videobuf_queue_sg_init(&fh->vbi, &bttv_vbi_qops,
+                           &btv->c.pci->dev, &btv->s_lock,
                            V4L2_BUF_TYPE_VBI_CAPTURE,
                            V4L2_FIELD_SEQ_TB,
                            sizeof(struct bttv_buffer),
@@ -3457,6 +3463,9 @@ static int radio_release(struct inode *inode, struct file *file)
        struct bttv *btv = fh->btv;
        struct rds_command cmd;
 
+       file->private_data = NULL;
+       kfree(fh);
+
        btv->radio_user--;
 
        bttv_call_i2c_clients(btv, RDS_CMD_CLOSE, &cmd);
@@ -3510,7 +3519,7 @@ static int radio_enum_input(struct file *file, void *priv,
                return -EINVAL;
 
        strcpy(i->name, "Radio");
-        i->type = V4L2_INPUT_TYPE_TUNER;
+       i->type = V4L2_INPUT_TYPE_TUNER;
 
        return 0;
 }
@@ -3518,10 +3527,9 @@ static int radio_enum_input(struct file *file, void *priv,
 static int radio_g_audio(struct file *file, void *priv,
                                        struct v4l2_audio *a)
 {
-       if (a->index != 0)
+       if (unlikely(a->index))
                return -EINVAL;
 
-       memset(a, 0, sizeof(*a));
        strcpy(a->name, "Radio");
 
        return 0;
@@ -3543,11 +3551,17 @@ static int radio_s_tuner(struct file *file, void *priv,
 static int radio_s_audio(struct file *file, void *priv,
                                        struct v4l2_audio *a)
 {
+       if (unlikely(a->index))
+               return -EINVAL;
+
        return 0;
 }
 
 static int radio_s_input(struct file *filp, void *priv, unsigned int i)
 {
+       if (unlikely(i))
+               return -EINVAL;
+
        return 0;
 }
 
index fc9ecb21eec6e66311e773126f93f3ab74bfe582..a38af98f4cae9e33ad4f47cd1873407a47c34dab 100644 (file)
@@ -278,6 +278,12 @@ int bttv_input_init(struct bttv *btv)
                ir->mask_keyup   = 0x004000;
                ir->polling      = 50; /* ms */
                break;
+       case BTTV_BOARD_KOZUMI_KTV_01C:
+               ir_codes         = ir_codes_pctv_sedna;
+               ir->mask_keycode = 0x001f00;
+               ir->mask_keyup   = 0x006000;
+               ir->polling      = 50; /* ms */
+               break;
        }
        if (NULL == ir_codes) {
                dprintk(KERN_INFO "Ooops: IR config error [card=%d]\n", btv->c.type);
index 75fa82c7c7351179ef5120a17d487f0e0cb43ae0..bfdbc469e30f379e6e75bdf4a2abaf63fcc28c4d 100644 (file)
@@ -54,7 +54,7 @@
 #define VBI_DEFLINES 16
 
 static unsigned int vbibufs = 4;
-static unsigned int vbi_debug = 0;
+static unsigned int vbi_debug;
 
 module_param(vbibufs,   int, 0444);
 module_param(vbi_debug, int, 0644);
index bf4c339a520c879d5bf1a04e5c213d6a63f2cc5a..f2393202904b795a6528fab8745ea821b7627c6a 100644 (file)
@@ -19,6 +19,7 @@
 #include <media/ir-common.h>
 #include <media/ir-kbd-i2c.h>
 #include <media/i2c-addr.h>
+#include <media/tuner.h>
 
 /* ---------------------------------------------------------- */
 /* exported by bttv-cards.c                                   */
 #define BTTV_BOARD_VOODOOTV_200                   0x93
 #define BTTV_BOARD_DVICO_FUSIONHDTV_2     0x94
 #define BTTV_BOARD_TYPHOON_TVTUNERPCI     0x95
+#define BTTV_BOARD_GEOVISION_GV600        0x96
+#define BTTV_BOARD_KOZUMI_KTV_01C          0x97
 
 
 /* more card-specific defines */
index 1305d315cfc50227445b952fda59b009b7b3af0d..03816b73f847560571a1bccd3693bdc5502d1666 100644 (file)
@@ -42,7 +42,6 @@
 
 #include <linux/device.h>
 #include <media/videobuf-dma-sg.h>
-#include <media/tuner.h>
 #include <media/tveeprom.h>
 #include <media/ir-common.h>
 
index 032265383df25203eabf1816a8a94f4bf43daa2d..b364adaae78d8e8262043a5e2c3734249ca01c51 100644 (file)
@@ -523,7 +523,7 @@ static inline int qc_readbytes(struct qcam_device *q, char buffer[])
        int ret=1;
        unsigned int hi, lo;
        unsigned int hi2, lo2;
-       static int state = 0;
+       static int state;
 
        if (buffer == NULL)
        {
@@ -898,7 +898,9 @@ static const struct file_operations qcam_fops = {
        .open           = video_exclusive_open,
        .release        = video_exclusive_release,
        .ioctl          = qcam_ioctl,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .read           = qcam_read,
        .llseek         = no_llseek,
 };
@@ -912,7 +914,7 @@ static struct video_device qcam_template=
 
 #define MAX_CAMS 4
 static struct qcam_device *qcams[MAX_CAMS];
-static unsigned int num_cams = 0;
+static unsigned int num_cams;
 
 static int init_bwqcam(struct parport *port)
 {
index cf1546b5a7f1b33e8f8f7d8e865fa54f4fe518e5..fe1e67bb1ca860b6a946afb0ed6804654c8bf4ce 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/videodev.h>
 #include <media/v4l2-common.h>
 #include <linux/mutex.h>
+#include <linux/jiffies.h>
 
 #include <asm/uaccess.h>
 
@@ -69,7 +70,7 @@ struct qcam_device {
 
 static int parport[MAX_CAMS] = { [1 ... MAX_CAMS-1] = -1 };
 static int probe = 2;
-static int force_rgb = 0;
+static int force_rgb;
 static int video_nr = -1;
 
 static inline void qcam_set_ack(struct qcam_device *qcam, unsigned int i)
@@ -95,7 +96,8 @@ static unsigned int qcam_await_ready1(struct qcam_device *qcam,
        unsigned long oldjiffies = jiffies;
        unsigned int i;
 
-       for (oldjiffies = jiffies; (jiffies - oldjiffies) < msecs_to_jiffies(40); )
+       for (oldjiffies = jiffies;
+            time_before(jiffies, oldjiffies + msecs_to_jiffies(40)); )
                if (qcam_ready1(qcam) == value)
                        return 0;
 
@@ -120,7 +122,8 @@ static unsigned int qcam_await_ready2(struct qcam_device *qcam, int value)
        unsigned long oldjiffies = jiffies;
        unsigned int i;
 
-       for (oldjiffies = jiffies; (jiffies - oldjiffies) < msecs_to_jiffies(40); )
+       for (oldjiffies = jiffies;
+            time_before(jiffies, oldjiffies + msecs_to_jiffies(40)); )
                if (qcam_ready2(qcam) == value)
                        return 0;
 
@@ -689,7 +692,9 @@ static const struct file_operations qcam_fops = {
        .open           = video_exclusive_open,
        .release        = video_exclusive_release,
        .ioctl          = qcam_ioctl,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .read           = qcam_read,
        .llseek         = no_llseek,
 };
@@ -741,7 +746,7 @@ static struct qcam_device *qcam_init(struct parport *port)
 }
 
 static struct qcam_device *qcams[MAX_CAMS];
-static unsigned int num_cams = 0;
+static unsigned int num_cams;
 
 static int init_cqcam(struct parport *port)
 {
index 7ae499c9c54c8785e497e9ddabdcde740c017f01..5195b1f3378a627d60dd66452033ae1f2e56f353 100644 (file)
@@ -65,7 +65,7 @@ MODULE_SUPPORTED_DEVICE("Video");
  */
 
 #define MAX_DMA_BUFS 3
-static int alloc_bufs_at_read = 0;
+static int alloc_bufs_at_read;
 module_param(alloc_bufs_at_read, bool, 0444);
 MODULE_PARM_DESC(alloc_bufs_at_read,
                "Non-zero value causes DMA buffers to be allocated when the "
@@ -99,7 +99,7 @@ MODULE_PARM_DESC(max_buffers,
                "will be allowed to allocate.  These buffers are big and live "
                "in vmalloc space.");
 
-static int flip = 0;
+static int flip;
 module_param(flip, bool, 0444);
 MODULE_PARM_DESC(flip,
                "If set, the sensor will be instructed to flip the image "
index 7c630f5ee7258faccf51b06180c76859e5f502da..2a81376ef5038dadaf621e2441588bab05eed4c6 100644 (file)
@@ -3792,7 +3792,9 @@ static const struct file_operations cpia_fops = {
        .read           = cpia_read,
        .mmap           = cpia_mmap,
        .ioctl          = cpia_ioctl,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .llseek         = no_llseek,
 };
 
index 78392fb6f94ea3dd8b430f338024b73d86a5842c..5096058bf5793a68b3ea69d748913cd34caaa3e6 100644 (file)
@@ -412,11 +412,11 @@ void cpia_unregister_camera(struct cam_data *cam);
 /* ErrorCode */
 #define ERROR_FLICKER_BELOW_MIN_EXP     0x01 /*flicker exposure got below minimum exposure */
 #define ALOG(fmt,args...) printk(fmt, ##args)
-#define LOG(fmt,args...) ALOG(KERN_INFO __FILE__ ":%s(%d):" fmt, __FUNCTION__ , __LINE__ , ##args)
+#define LOG(fmt,args...) ALOG(KERN_INFO __FILE__ ":%s(%d):" fmt, __func__ , __LINE__ , ##args)
 
 #ifdef _CPIA_DEBUG_
 #define ADBG(fmt,args...) printk(fmt, jiffies, ##args)
-#define DBG(fmt,args...) ADBG(KERN_DEBUG __FILE__" (%ld):%s(%d):" fmt, __FUNCTION__, __LINE__ , ##args)
+#define DBG(fmt,args...) ADBG(KERN_DEBUG __FILE__" (%ld):%s(%d):" fmt, __func__, __LINE__ , ##args)
 #else
 #define DBG(fmn,args...) do {} while(0)
 #endif
index a76bd786cf13474f3f16c5f2282f050f3bb39e4e..c8b9fdb700ff123138790e58452f4953dd3ef52b 100644 (file)
@@ -34,7 +34,7 @@
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 
-//#define _CPIA2_DEBUG_
+/* #define _CPIA2_DEBUG_ */
 
 #include "cpia2patch.h"
 
@@ -48,7 +48,7 @@ static const char *block_name[] = {
 };
 #endif
 
-static unsigned int debugs_on = 0;//DEBUG_REG;
+static unsigned int debugs_on; /* default 0 - DEBUG_REG */
 
 
 /******************************************************************************
@@ -570,7 +570,7 @@ int cpia2_send_command(struct camera_data *cam, struct cpia2_command *cmd)
                            block_name[block_index]);
                break;
        default:
-               LOG("%s: invalid request mode\n",__FUNCTION__);
+               LOG("%s: invalid request mode\n",__func__);
                return -EINVAL;
        }
 
@@ -952,7 +952,7 @@ static int set_default_user_mode(struct camera_data *cam)
                        frame_rate = CPIA2_VP_FRAMERATE_30;
                break;
        default:
-               LOG("%s: Invalid sensor flag value 0x%0X\n",__FUNCTION__,
+               LOG("%s: Invalid sensor flag value 0x%0X\n",__func__,
                    cam->params.version.sensor_flags);
                return -EINVAL;
        }
@@ -2356,12 +2356,12 @@ long cpia2_read(struct camera_data *cam,
        }
 
        if (!buf) {
-               ERR("%s: buffer NULL\n",__FUNCTION__);
+               ERR("%s: buffer NULL\n",__func__);
                return -EINVAL;
        }
 
        if (!cam) {
-               ERR("%s: Internal error, camera_data NULL!\n",__FUNCTION__);
+               ERR("%s: Internal error, camera_data NULL!\n",__func__);
                return -EINVAL;
        }
 
@@ -2370,7 +2370,7 @@ long cpia2_read(struct camera_data *cam,
                return -ERESTARTSYS;
 
        if (!cam->present) {
-               LOG("%s: camera removed\n",__FUNCTION__);
+               LOG("%s: camera removed\n",__func__);
                mutex_unlock(&cam->busy_lock);
                return 0;       /* EOF */
        }
@@ -2434,7 +2434,7 @@ unsigned int cpia2_poll(struct camera_data *cam, struct file *filp,
        unsigned int status=0;
 
        if(!cam) {
-               ERR("%s: Internal error, camera_data not found!\n",__FUNCTION__);
+               ERR("%s: Internal error, camera_data not found!\n",__func__);
                return POLLERR;
        }
 
index d8e929863a88d9305ecaefff2b8378fd06b9d374..a4574740350df30cf6bd3cb84592b8c84d39f779 100644 (file)
@@ -84,7 +84,7 @@ static struct usb_driver cpia2_driver = {
  *****************************************************************************/
 static void process_frame(struct camera_data *cam)
 {
-       static int frame_count = 0;
+       static int frame_count;
 
        unsigned char *inbuff = cam->workbuff->data;
 
index e378abec806d21ddb75145ed7bb788bc620b57fc..7ce2789fa976213188419ced61d709339fbf134e 100644 (file)
@@ -1927,7 +1927,9 @@ static const struct file_operations fops_template = {
        .poll           = cpia2_v4l_poll,
        .ioctl          = cpia2_ioctl,
        .llseek         = no_llseek,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .mmap           = cpia2_mmap,
 };
 
index 9da4726eb9b981a21250565bbaaa8ed190052c3b..ef1f89399983549adc9192a9f9fd79259abcdc97 100644 (file)
@@ -170,7 +170,7 @@ static void cpia_usb_complete(struct urb *urb)
        /* resubmit */
        urb->dev = ucpia->dev;
        if ((i = usb_submit_urb(urb, GFP_ATOMIC)) != 0)
-               printk(KERN_ERR "%s: usb_submit_urb ret %d\n", __FUNCTION__,  i);
+               printk(KERN_ERR "%s: usb_submit_urb ret %d\n", __func__,  i);
 }
 
 static int cpia_usb_open(void *privdata)
index 1fd326fe41136cd271717eb9b89582701782131f..ca5fbce3a9095bc07dca912ce74e19387f5a4f02 100644 (file)
@@ -8,6 +8,7 @@ config VIDEO_CX23885
        select VIDEO_TVEEPROM
        select VIDEO_IR
        select VIDEOBUF_DVB
+       select VIDEO_CX25840
        select DVB_TUNER_MT2131 if !DVB_FE_CUSTOMISE
        select DVB_S5H1409 if !DVB_FE_CUSTOMISE
        select DVB_LGDT330X if !DVB_FE_CUSTOMISE
@@ -16,6 +17,7 @@ config VIDEO_CX23885
        select TUNER_TDA8290 if !DVB_FE_CUSTOMIZE
        select DVB_TDA18271 if !DVB_FE_CUSTOMIZE
        select DVB_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.
index 32c90be506029374d8e901c82938ec64b12390a1..d7b0721af062611215e6b516ec5c86e970911414 100644 (file)
@@ -1,4 +1,4 @@
-cx23885-objs   := cx23885-cards.o cx23885-video.o cx23885-vbi.o cx23885-core.o cx23885-i2c.o cx23885-dvb.o
+cx23885-objs   := cx23885-cards.o cx23885-video.o cx23885-vbi.o cx23885-core.o cx23885-i2c.o cx23885-dvb.o cx23885-417.o
 
 obj-$(CONFIG_VIDEO_CX23885) += cx23885.o
 
diff --git a/drivers/media/video/cx23885/cx23885-417.c b/drivers/media/video/cx23885/cx23885-417.c
new file mode 100644 (file)
index 0000000..acdd3b6
--- /dev/null
@@ -0,0 +1,1764 @@
+/*
+ *
+ *  Support for a cx23417 mpeg encoder via cx23885 host port.
+ *
+ *    (c) 2004 Jelle Foks <jelle@foks.8m.com>
+ *    (c) 2004 Gerd Knorr <kraxel@bytesex.org>
+ *    (c) 2008 Steven Toth <stoth@hauppauge.com>
+ *      - CX23885/7/8 support
+ *
+ *  Includes parts from the ivtv driver( http://ivtv.sourceforge.net/),
+ *
+ *  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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/firmware.h>
+#include <media/v4l2-common.h>
+#include <media/cx2341x.h>
+
+#include "cx23885.h"
+#include "media/cx2341x.h"
+
+#define CX23885_FIRM_IMAGE_SIZE 376836
+#define CX23885_FIRM_IMAGE_NAME "v4l-cx23885-enc.fw"
+
+static unsigned int mpegbufs = 32;
+module_param(mpegbufs, int, 0644);
+MODULE_PARM_DESC(mpegbufs, "number of mpeg buffers, range 2-32");
+static unsigned int mpeglines = 32;
+module_param(mpeglines, int, 0644);
+MODULE_PARM_DESC(mpeglines, "number of lines in an MPEG buffer, range 2-32");
+static unsigned int mpeglinesize = 512;
+module_param(mpeglinesize, int, 0644);
+MODULE_PARM_DESC(mpeglinesize,
+       "number of bytes in each line of an MPEG buffer, range 512-1024");
+
+static unsigned int v4l_debug;
+module_param(v4l_debug, int, 0644);
+MODULE_PARM_DESC(v4l_debug, "enable V4L debug messages");
+
+#define dprintk(level, fmt, arg...)\
+       do { if (v4l_debug >= level) \
+               printk(KERN_DEBUG "%s: " fmt, dev->name , ## arg);\
+       } while (0)
+
+static struct cx23885_tvnorm cx23885_tvnorms[] = {
+       {
+               .name      = "NTSC-M",
+               .id        = V4L2_STD_NTSC_M,
+       }, {
+               .name      = "NTSC-JP",
+               .id        = V4L2_STD_NTSC_M_JP,
+       }, {
+               .name      = "PAL-BG",
+               .id        = V4L2_STD_PAL_BG,
+       }, {
+               .name      = "PAL-DK",
+               .id        = V4L2_STD_PAL_DK,
+       }, {
+               .name      = "PAL-I",
+               .id        = V4L2_STD_PAL_I,
+       }, {
+               .name      = "PAL-M",
+               .id        = V4L2_STD_PAL_M,
+       }, {
+               .name      = "PAL-N",
+               .id        = V4L2_STD_PAL_N,
+       }, {
+               .name      = "PAL-Nc",
+               .id        = V4L2_STD_PAL_Nc,
+       }, {
+               .name      = "PAL-60",
+               .id        = V4L2_STD_PAL_60,
+       }, {
+               .name      = "SECAM-L",
+               .id        = V4L2_STD_SECAM_L,
+       }, {
+               .name      = "SECAM-DK",
+               .id        = V4L2_STD_SECAM_DK,
+       }
+};
+
+/* ------------------------------------------------------------------ */
+enum cx23885_capture_type {
+       CX23885_MPEG_CAPTURE,
+       CX23885_RAW_CAPTURE,
+       CX23885_RAW_PASSTHRU_CAPTURE
+};
+enum cx23885_capture_bits {
+       CX23885_RAW_BITS_NONE             = 0x00,
+       CX23885_RAW_BITS_YUV_CAPTURE      = 0x01,
+       CX23885_RAW_BITS_PCM_CAPTURE      = 0x02,
+       CX23885_RAW_BITS_VBI_CAPTURE      = 0x04,
+       CX23885_RAW_BITS_PASSTHRU_CAPTURE = 0x08,
+       CX23885_RAW_BITS_TO_HOST_CAPTURE  = 0x10
+};
+enum cx23885_capture_end {
+       CX23885_END_AT_GOP, /* stop at the end of gop, generate irq */
+       CX23885_END_NOW, /* stop immediately, no irq */
+};
+enum cx23885_framerate {
+       CX23885_FRAMERATE_NTSC_30, /* NTSC: 30fps */
+       CX23885_FRAMERATE_PAL_25   /* PAL: 25fps */
+};
+enum cx23885_stream_port {
+       CX23885_OUTPUT_PORT_MEMORY,
+       CX23885_OUTPUT_PORT_STREAMING,
+       CX23885_OUTPUT_PORT_SERIAL
+};
+enum cx23885_data_xfer_status {
+       CX23885_MORE_BUFFERS_FOLLOW,
+       CX23885_LAST_BUFFER,
+};
+enum cx23885_picture_mask {
+       CX23885_PICTURE_MASK_NONE,
+       CX23885_PICTURE_MASK_I_FRAMES,
+       CX23885_PICTURE_MASK_I_P_FRAMES = 0x3,
+       CX23885_PICTURE_MASK_ALL_FRAMES = 0x7,
+};
+enum cx23885_vbi_mode_bits {
+       CX23885_VBI_BITS_SLICED,
+       CX23885_VBI_BITS_RAW,
+};
+enum cx23885_vbi_insertion_bits {
+       CX23885_VBI_BITS_INSERT_IN_XTENSION_USR_DATA,
+       CX23885_VBI_BITS_INSERT_IN_PRIVATE_PACKETS = 0x1 << 1,
+       CX23885_VBI_BITS_SEPARATE_STREAM = 0x2 << 1,
+       CX23885_VBI_BITS_SEPARATE_STREAM_USR_DATA = 0x4 << 1,
+       CX23885_VBI_BITS_SEPARATE_STREAM_PRV_DATA = 0x5 << 1,
+};
+enum cx23885_dma_unit {
+       CX23885_DMA_BYTES,
+       CX23885_DMA_FRAMES,
+};
+enum cx23885_dma_transfer_status_bits {
+       CX23885_DMA_TRANSFER_BITS_DONE = 0x01,
+       CX23885_DMA_TRANSFER_BITS_ERROR = 0x04,
+       CX23885_DMA_TRANSFER_BITS_LL_ERROR = 0x10,
+};
+enum cx23885_pause {
+       CX23885_PAUSE_ENCODING,
+       CX23885_RESUME_ENCODING,
+};
+enum cx23885_copyright {
+       CX23885_COPYRIGHT_OFF,
+       CX23885_COPYRIGHT_ON,
+};
+enum cx23885_notification_type {
+       CX23885_NOTIFICATION_REFRESH,
+};
+enum cx23885_notification_status {
+       CX23885_NOTIFICATION_OFF,
+       CX23885_NOTIFICATION_ON,
+};
+enum cx23885_notification_mailbox {
+       CX23885_NOTIFICATION_NO_MAILBOX = -1,
+};
+enum cx23885_field1_lines {
+       CX23885_FIELD1_SAA7114 = 0x00EF, /* 239 */
+       CX23885_FIELD1_SAA7115 = 0x00F0, /* 240 */
+       CX23885_FIELD1_MICRONAS = 0x0105, /* 261 */
+};
+enum cx23885_field2_lines {
+       CX23885_FIELD2_SAA7114 = 0x00EF, /* 239 */
+       CX23885_FIELD2_SAA7115 = 0x00F0, /* 240 */
+       CX23885_FIELD2_MICRONAS = 0x0106, /* 262 */
+};
+enum cx23885_custom_data_type {
+       CX23885_CUSTOM_EXTENSION_USR_DATA,
+       CX23885_CUSTOM_PRIVATE_PACKET,
+};
+enum cx23885_mute {
+       CX23885_UNMUTE,
+       CX23885_MUTE,
+};
+enum cx23885_mute_video_mask {
+       CX23885_MUTE_VIDEO_V_MASK = 0x0000FF00,
+       CX23885_MUTE_VIDEO_U_MASK = 0x00FF0000,
+       CX23885_MUTE_VIDEO_Y_MASK = 0xFF000000,
+};
+enum cx23885_mute_video_shift {
+       CX23885_MUTE_VIDEO_V_SHIFT = 8,
+       CX23885_MUTE_VIDEO_U_SHIFT = 16,
+       CX23885_MUTE_VIDEO_Y_SHIFT = 24,
+};
+
+/* defines below are from ivtv-driver.h */
+#define IVTV_CMD_HW_BLOCKS_RST 0xFFFFFFFF
+
+/* Firmware API commands */
+#define IVTV_API_STD_TIMEOUT 500
+
+/* Registers */
+/* IVTV_REG_OFFSET */
+#define IVTV_REG_ENC_SDRAM_REFRESH (0x07F8)
+#define IVTV_REG_ENC_SDRAM_PRECHARGE (0x07FC)
+#define IVTV_REG_SPU (0x9050)
+#define IVTV_REG_HW_BLOCKS (0x9054)
+#define IVTV_REG_VPU (0x9058)
+#define IVTV_REG_APU (0xA064)
+
+/**** Bit definitions for MC417_RWD and MC417_OEN registers  ***
+  bits 31-16
++-----------+
+| Reserved  |
++-----------+
+  bit 15  bit 14  bit 13 bit 12  bit 11  bit 10  bit 9   bit 8
++-------+-------+-------+-------+-------+-------+-------+-------+
+| MIWR# | MIRD# | MICS# |MIRDY# |MIADDR3|MIADDR2|MIADDR1|MIADDR0|
++-------+-------+-------+-------+-------+-------+-------+-------+
+ bit 7   bit 6   bit 5   bit 4   bit 3   bit 2   bit 1   bit 0
++-------+-------+-------+-------+-------+-------+-------+-------+
+|MIDATA7|MIDATA6|MIDATA5|MIDATA4|MIDATA3|MIDATA2|MIDATA1|MIDATA0|
++-------+-------+-------+-------+-------+-------+-------+-------+
+***/
+#define MC417_MIWR     0x8000
+#define MC417_MIRD     0x4000
+#define MC417_MICS     0x2000
+#define MC417_MIRDY    0x1000
+#define MC417_MIADDR   0x0F00
+#define MC417_MIDATA   0x00FF
+
+/* MIADDR* nibble definitions */
+#define  MCI_MEMORY_DATA_BYTE0          0x000
+#define  MCI_MEMORY_DATA_BYTE1          0x100
+#define  MCI_MEMORY_DATA_BYTE2          0x200
+#define  MCI_MEMORY_DATA_BYTE3          0x300
+#define  MCI_MEMORY_ADDRESS_BYTE2       0x400
+#define  MCI_MEMORY_ADDRESS_BYTE1       0x500
+#define  MCI_MEMORY_ADDRESS_BYTE0       0x600
+#define  MCI_REGISTER_DATA_BYTE0        0x800
+#define  MCI_REGISTER_DATA_BYTE1        0x900
+#define  MCI_REGISTER_DATA_BYTE2        0xA00
+#define  MCI_REGISTER_DATA_BYTE3        0xB00
+#define  MCI_REGISTER_ADDRESS_BYTE0     0xC00
+#define  MCI_REGISTER_ADDRESS_BYTE1     0xD00
+#define  MCI_REGISTER_MODE              0xE00
+
+/* Read and write modes */
+#define  MCI_MODE_REGISTER_READ         0
+#define  MCI_MODE_REGISTER_WRITE        1
+#define  MCI_MODE_MEMORY_READ           0
+#define  MCI_MODE_MEMORY_WRITE          0x40
+
+/*** Bit definitions for MC417_CTL register ****
+ bits 31-6   bits 5-4   bit 3    bits 2-1       Bit 0
++--------+-------------+--------+--------------+------------+
+|Reserved|MC417_SPD_CTL|Reserved|MC417_GPIO_SEL|UART_GPIO_EN|
++--------+-------------+--------+--------------+------------+
+***/
+#define MC417_SPD_CTL(x)       (((x) << 4) & 0x00000030)
+#define MC417_GPIO_SEL(x)      (((x) << 1) & 0x00000006)
+#define MC417_UART_GPIO_EN     0x00000001
+
+/* Values for speed control */
+#define MC417_SPD_CTL_SLOW     0x1
+#define MC417_SPD_CTL_MEDIUM   0x0
+#define MC417_SPD_CTL_FAST     0x3     /* b'1x, but we use b'11 */
+
+/* Values for GPIO select */
+#define MC417_GPIO_SEL_GPIO3   0x3
+#define MC417_GPIO_SEL_GPIO2   0x2
+#define MC417_GPIO_SEL_GPIO1   0x1
+#define MC417_GPIO_SEL_GPIO0   0x0
+
+void cx23885_mc417_init(struct cx23885_dev *dev)
+{
+       u32 regval;
+
+       dprintk(2, "%s()\n", __func__);
+
+       /* Configure MC417_CTL register to defaults. */
+       regval = MC417_SPD_CTL(MC417_SPD_CTL_FAST)      |
+                MC417_GPIO_SEL(MC417_GPIO_SEL_GPIO3)   |
+                MC417_UART_GPIO_EN;
+       cx_write(MC417_CTL, regval);
+
+       /* Configure MC417_OEN to defaults. */
+       regval = MC417_MIRDY;
+       cx_write(MC417_OEN, regval);
+
+       /* Configure MC417_RWD to defaults. */
+       regval = MC417_MIWR | MC417_MIRD | MC417_MICS;
+       cx_write(MC417_RWD, regval);
+}
+
+static int mc417_wait_ready(struct cx23885_dev *dev)
+{
+       u32 mi_ready;
+       unsigned long timeout = jiffies + msecs_to_jiffies(1);
+
+       for (;;) {
+               mi_ready = cx_read(MC417_RWD) & MC417_MIRDY;
+               if (mi_ready != 0)
+                       return 0;
+               if (time_after(jiffies, timeout))
+                       return -1;
+               udelay(1);
+       }
+}
+
+static int mc417_register_write(struct cx23885_dev *dev, u16 address, u32 value)
+{
+       u32 regval;
+
+       /* Enable MC417 GPIO outputs except for MC417_MIRDY,
+        * which is an input.
+        */
+       cx_write(MC417_OEN, MC417_MIRDY);
+
+       /* Write data byte 0 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE0 |
+               (value & 0x000000FF);
+       cx_write(MC417_RWD, regval);
+
+       /* Transition CS/WR to effect write transaction across bus. */
+       regval |= MC417_MICS | MC417_MIWR;
+       cx_write(MC417_RWD, regval);
+
+       /* Write data byte 1 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE1 |
+               ((value >> 8) & 0x000000FF);
+       cx_write(MC417_RWD, regval);
+       regval |= MC417_MICS | MC417_MIWR;
+       cx_write(MC417_RWD, regval);
+
+       /* Write data byte 2 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE2 |
+               ((value >> 16) & 0x000000FF);
+       cx_write(MC417_RWD, regval);
+       regval |= MC417_MICS | MC417_MIWR;
+       cx_write(MC417_RWD, regval);
+
+       /* Write data byte 3 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE3 |
+               ((value >> 24) & 0x000000FF);
+       cx_write(MC417_RWD, regval);
+       regval |= MC417_MICS | MC417_MIWR;
+       cx_write(MC417_RWD, regval);
+
+       /* Write address byte 0 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_ADDRESS_BYTE0 |
+               (address & 0xFF);
+       cx_write(MC417_RWD, regval);
+       regval |= MC417_MICS | MC417_MIWR;
+       cx_write(MC417_RWD, regval);
+
+       /* Write address byte 1 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_ADDRESS_BYTE1 |
+               ((address >> 8) & 0xFF);
+       cx_write(MC417_RWD, regval);
+       regval |= MC417_MICS | MC417_MIWR;
+       cx_write(MC417_RWD, regval);
+
+       /* Indicate that this is a write. */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_MODE |
+               MCI_MODE_REGISTER_WRITE;
+       cx_write(MC417_RWD, regval);
+       regval |= MC417_MICS | MC417_MIWR;
+       cx_write(MC417_RWD, regval);
+
+       /* Wait for the trans to complete (MC417_MIRDY asserted). */
+       return mc417_wait_ready(dev);
+}
+
+static int mc417_register_read(struct cx23885_dev *dev, u16 address, u32 *value)
+{
+       int retval;
+       u32 regval;
+       u32 tempval;
+       u32 dataval;
+
+       /* Enable MC417 GPIO outputs except for MC417_MIRDY,
+        * which is an input.
+        */
+       cx_write(MC417_OEN, MC417_MIRDY);
+
+       /* Write address byte 0 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_ADDRESS_BYTE0 |
+               ((address & 0x00FF));
+       cx_write(MC417_RWD, regval);
+       regval |= MC417_MICS | MC417_MIWR;
+       cx_write(MC417_RWD, regval);
+
+       /* Write address byte 1 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_ADDRESS_BYTE1 |
+               ((address >> 8) & 0xFF);
+       cx_write(MC417_RWD, regval);
+       regval |= MC417_MICS | MC417_MIWR;
+       cx_write(MC417_RWD, regval);
+
+       /* Indicate that this is a register read. */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_MODE |
+               MCI_MODE_REGISTER_READ;
+       cx_write(MC417_RWD, regval);
+       regval |= MC417_MICS | MC417_MIWR;
+       cx_write(MC417_RWD, regval);
+
+       /* Wait for the trans to complete (MC417_MIRDY asserted). */
+       retval = mc417_wait_ready(dev);
+
+       /* switch the DAT0-7 GPIO[10:3] to input mode */
+       cx_write(MC417_OEN, MC417_MIRDY | MC417_MIDATA);
+
+       /* Read data byte 0 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE0;
+       cx_write(MC417_RWD, regval);
+
+       /* Transition RD to effect read transaction across bus.
+        * Transtion 0x5000 -> 0x9000 correct (RD/RDY -> WR/RDY)?
+        * Should it be 0x9000 -> 0xF000 (also why is RDY being set, its
+        * input only...)
+        */
+       regval = MC417_MIWR | MC417_MIRDY | MCI_REGISTER_DATA_BYTE0;
+       cx_write(MC417_RWD, regval);
+
+       /* Collect byte */
+       tempval = cx_read(MC417_RWD);
+       dataval = tempval & 0x000000FF;
+
+       /* Bring CS and RD high. */
+       regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
+       cx_write(MC417_RWD, regval);
+
+       /* Read data byte 1 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE1;
+       cx_write(MC417_RWD, regval);
+       regval = MC417_MIWR | MC417_MIRDY | MCI_REGISTER_DATA_BYTE1;
+       cx_write(MC417_RWD, regval);
+       tempval = cx_read(MC417_RWD);
+       dataval |= ((tempval & 0x000000FF) << 8);
+       regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
+       cx_write(MC417_RWD, regval);
+
+       /* Read data byte 2 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE2;
+       cx_write(MC417_RWD, regval);
+       regval = MC417_MIWR | MC417_MIRDY | MCI_REGISTER_DATA_BYTE2;
+       cx_write(MC417_RWD, regval);
+       tempval = cx_read(MC417_RWD);
+       dataval |= ((tempval & 0x000000FF) << 16);
+       regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
+       cx_write(MC417_RWD, regval);
+
+       /* Read data byte 3 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE3;
+       cx_write(MC417_RWD, regval);
+       regval = MC417_MIWR | MC417_MIRDY | MCI_REGISTER_DATA_BYTE3;
+       cx_write(MC417_RWD, regval);
+       tempval = cx_read(MC417_RWD);
+       dataval |= ((tempval & 0x000000FF) << 24);
+       regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
+       cx_write(MC417_RWD, regval);
+
+       *value  = dataval;
+
+       return retval;
+}
+
+int mc417_memory_write(struct cx23885_dev *dev, u32 address, u32 value)
+{
+       u32 regval;
+
+       /* Enable MC417 GPIO outputs except for MC417_MIRDY,
+        * which is an input.
+        */
+       cx_write(MC417_OEN, MC417_MIRDY);
+
+       /* Write data byte 0 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE0 |
+               (value & 0x000000FF);
+       cx_write(MC417_RWD, regval);
+
+       /* Transition CS/WR to effect write transaction across bus. */
+       regval |= MC417_MICS | MC417_MIWR;
+       cx_write(MC417_RWD, regval);
+
+       /* Write data byte 1 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE1 |
+               ((value >> 8) & 0x000000FF);
+       cx_write(MC417_RWD, regval);
+       regval |= MC417_MICS | MC417_MIWR;
+       cx_write(MC417_RWD, regval);
+
+       /* Write data byte 2 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE2 |
+               ((value >> 16) & 0x000000FF);
+       cx_write(MC417_RWD, regval);
+       regval |= MC417_MICS | MC417_MIWR;
+       cx_write(MC417_RWD, regval);
+
+       /* Write data byte 3 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE3 |
+               ((value >> 24) & 0x000000FF);
+       cx_write(MC417_RWD, regval);
+       regval |= MC417_MICS | MC417_MIWR;
+       cx_write(MC417_RWD, regval);
+
+       /* Write address byte 2 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE2 |
+               MCI_MODE_MEMORY_WRITE | ((address >> 16) & 0x3F);
+       cx_write(MC417_RWD, regval);
+       regval |= MC417_MICS | MC417_MIWR;
+       cx_write(MC417_RWD, regval);
+
+       /* Write address byte 1 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE1 |
+               ((address >> 8) & 0xFF);
+       cx_write(MC417_RWD, regval);
+       regval |= MC417_MICS | MC417_MIWR;
+       cx_write(MC417_RWD, regval);
+
+       /* Write address byte 0 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE0 |
+               (address & 0xFF);
+       cx_write(MC417_RWD, regval);
+       regval |= MC417_MICS | MC417_MIWR;
+       cx_write(MC417_RWD, regval);
+
+       /* Wait for the trans to complete (MC417_MIRDY asserted). */
+       return mc417_wait_ready(dev);
+}
+
+int mc417_memory_read(struct cx23885_dev *dev, u32 address, u32 *value)
+{
+       int retval;
+       u32 regval;
+       u32 tempval;
+       u32 dataval;
+
+       /* Enable MC417 GPIO outputs except for MC417_MIRDY,
+        * which is an input.
+        */
+       cx_write(MC417_OEN, MC417_MIRDY);
+
+       /* Write address byte 2 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE2 |
+               MCI_MODE_MEMORY_READ | ((address >> 16) & 0x3F);
+       cx_write(MC417_RWD, regval);
+       regval |= MC417_MICS | MC417_MIWR;
+       cx_write(MC417_RWD, regval);
+
+       /* Write address byte 1 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE1 |
+               ((address >> 8) & 0xFF);
+       cx_write(MC417_RWD, regval);
+       regval |= MC417_MICS | MC417_MIWR;
+       cx_write(MC417_RWD, regval);
+
+       /* Write address byte 0 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE0 |
+               (address & 0xFF);
+       cx_write(MC417_RWD, regval);
+       regval |= MC417_MICS | MC417_MIWR;
+       cx_write(MC417_RWD, regval);
+
+       /* Wait for the trans to complete (MC417_MIRDY asserted). */
+       retval = mc417_wait_ready(dev);
+
+       /* switch the DAT0-7 GPIO[10:3] to input mode */
+       cx_write(MC417_OEN, MC417_MIRDY | MC417_MIDATA);
+
+       /* Read data byte 3 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE3;
+       cx_write(MC417_RWD, regval);
+
+       /* Transition RD to effect read transaction across bus. */
+       regval = MC417_MIWR | MC417_MIRDY | MCI_MEMORY_DATA_BYTE3;
+       cx_write(MC417_RWD, regval);
+
+       /* Collect byte */
+       tempval = cx_read(MC417_RWD);
+       dataval = ((tempval & 0x000000FF) << 24);
+
+       /* Bring CS and RD high. */
+       regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
+       cx_write(MC417_RWD, regval);
+
+       /* Read data byte 2 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE2;
+       cx_write(MC417_RWD, regval);
+       regval = MC417_MIWR | MC417_MIRDY | MCI_MEMORY_DATA_BYTE2;
+       cx_write(MC417_RWD, regval);
+       tempval = cx_read(MC417_RWD);
+       dataval |= ((tempval & 0x000000FF) << 16);
+       regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
+       cx_write(MC417_RWD, regval);
+
+       /* Read data byte 1 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE1;
+       cx_write(MC417_RWD, regval);
+       regval = MC417_MIWR | MC417_MIRDY | MCI_MEMORY_DATA_BYTE1;
+       cx_write(MC417_RWD, regval);
+       tempval = cx_read(MC417_RWD);
+       dataval |= ((tempval & 0x000000FF) << 8);
+       regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
+       cx_write(MC417_RWD, regval);
+
+       /* Read data byte 0 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE0;
+       cx_write(MC417_RWD, regval);
+       regval = MC417_MIWR | MC417_MIRDY | MCI_MEMORY_DATA_BYTE0;
+       cx_write(MC417_RWD, regval);
+       tempval = cx_read(MC417_RWD);
+       dataval |= (tempval & 0x000000FF);
+       regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
+       cx_write(MC417_RWD, regval);
+
+       *value  = dataval;
+
+       return retval;
+}
+
+/* ------------------------------------------------------------------ */
+
+/* MPEG encoder API */
+char *cmd_to_str(int cmd)
+{
+       switch (cmd) {
+       case CX2341X_ENC_PING_FW:
+               return  "PING_FW";
+       case CX2341X_ENC_START_CAPTURE:
+               return  "START_CAPTURE";
+       case CX2341X_ENC_STOP_CAPTURE:
+               return  "STOP_CAPTURE";
+       case CX2341X_ENC_SET_AUDIO_ID:
+               return  "SET_AUDIO_ID";
+       case CX2341X_ENC_SET_VIDEO_ID:
+               return  "SET_VIDEO_ID";
+       case CX2341X_ENC_SET_PCR_ID:
+               return  "SET_PCR_PID";
+       case CX2341X_ENC_SET_FRAME_RATE:
+               return  "SET_FRAME_RATE";
+       case CX2341X_ENC_SET_FRAME_SIZE:
+               return  "SET_FRAME_SIZE";
+       case CX2341X_ENC_SET_BIT_RATE:
+               return  "SET_BIT_RATE";
+       case CX2341X_ENC_SET_GOP_PROPERTIES:
+               return  "SET_GOP_PROPERTIES";
+       case CX2341X_ENC_SET_ASPECT_RATIO:
+               return  "SET_ASPECT_RATIO";
+       case CX2341X_ENC_SET_DNR_FILTER_MODE:
+               return  "SET_DNR_FILTER_PROPS";
+       case CX2341X_ENC_SET_DNR_FILTER_PROPS:
+               return  "SET_DNR_FILTER_PROPS";
+       case CX2341X_ENC_SET_CORING_LEVELS:
+               return  "SET_CORING_LEVELS";
+       case CX2341X_ENC_SET_SPATIAL_FILTER_TYPE:
+               return  "SET_SPATIAL_FILTER_TYPE";
+       case CX2341X_ENC_SET_VBI_LINE:
+               return  "SET_VBI_LINE";
+       case CX2341X_ENC_SET_STREAM_TYPE:
+               return  "SET_STREAM_TYPE";
+       case CX2341X_ENC_SET_OUTPUT_PORT:
+               return  "SET_OUTPUT_PORT";
+       case CX2341X_ENC_SET_AUDIO_PROPERTIES:
+               return  "SET_AUDIO_PROPERTIES";
+       case CX2341X_ENC_HALT_FW:
+               return  "HALT_FW";
+       case CX2341X_ENC_GET_VERSION:
+               return  "GET_VERSION";
+       case CX2341X_ENC_SET_GOP_CLOSURE:
+               return  "SET_GOP_CLOSURE";
+       case CX2341X_ENC_GET_SEQ_END:
+               return  "GET_SEQ_END";
+       case CX2341X_ENC_SET_PGM_INDEX_INFO:
+               return  "SET_PGM_INDEX_INFO";
+       case CX2341X_ENC_SET_VBI_CONFIG:
+               return  "SET_VBI_CONFIG";
+       case CX2341X_ENC_SET_DMA_BLOCK_SIZE:
+               return  "SET_DMA_BLOCK_SIZE";
+       case CX2341X_ENC_GET_PREV_DMA_INFO_MB_10:
+               return  "GET_PREV_DMA_INFO_MB_10";
+       case CX2341X_ENC_GET_PREV_DMA_INFO_MB_9:
+               return  "GET_PREV_DMA_INFO_MB_9";
+       case CX2341X_ENC_SCHED_DMA_TO_HOST:
+               return  "SCHED_DMA_TO_HOST";
+       case CX2341X_ENC_INITIALIZE_INPUT:
+               return  "INITIALIZE_INPUT";
+       case CX2341X_ENC_SET_FRAME_DROP_RATE:
+               return  "SET_FRAME_DROP_RATE";
+       case CX2341X_ENC_PAUSE_ENCODER:
+               return  "PAUSE_ENCODER";
+       case CX2341X_ENC_REFRESH_INPUT:
+               return  "REFRESH_INPUT";
+       case CX2341X_ENC_SET_COPYRIGHT:
+               return  "SET_COPYRIGHT";
+       case CX2341X_ENC_SET_EVENT_NOTIFICATION:
+               return  "SET_EVENT_NOTIFICATION";
+       case CX2341X_ENC_SET_NUM_VSYNC_LINES:
+               return  "SET_NUM_VSYNC_LINES";
+       case CX2341X_ENC_SET_PLACEHOLDER:
+               return  "SET_PLACEHOLDER";
+       case CX2341X_ENC_MUTE_VIDEO:
+               return  "MUTE_VIDEO";
+       case CX2341X_ENC_MUTE_AUDIO:
+               return  "MUTE_AUDIO";
+       case CX2341X_ENC_MISC:
+               return  "MISC";
+       default:
+               return "UNKNOWN";
+       }
+}
+
+static int cx23885_mbox_func(void *priv,
+                            u32 command,
+                            int in,
+                            int out,
+                            u32 data[CX2341X_MBOX_MAX_DATA])
+{
+       struct cx23885_dev *dev = priv;
+       unsigned long timeout;
+       u32 value, flag, retval = 0;
+       int i;
+
+       dprintk(3, "%s: command(0x%X) = %s\n", __func__, command,
+               cmd_to_str(command));
+
+       /* this may not be 100% safe if we can't read any memory location
+          without side effects */
+       mc417_memory_read(dev, dev->cx23417_mailbox - 4, &value);
+       if (value != 0x12345678) {
+               printk(KERN_ERR
+                       "Firmware and/or mailbox pointer not initialized "
+                       "or corrupted, signature = 0x%x, cmd = %s\n", value,
+                       cmd_to_str(command));
+               return -1;
+       }
+
+       /* This read looks at 32 bits, but flag is only 8 bits.
+        * Seems we also bail if CMD or TIMEOUT bytes are set???
+        */
+       mc417_memory_read(dev, dev->cx23417_mailbox, &flag);
+       if (flag) {
+               printk(KERN_ERR "ERROR: Mailbox appears to be in use "
+                       "(%x), cmd = %s\n", flag, cmd_to_str(command));
+               return -1;
+       }
+
+       flag |= 1; /* tell 'em we're working on it */
+       mc417_memory_write(dev, dev->cx23417_mailbox, flag);
+
+       /* write command + args + fill remaining with zeros */
+       /* command code */
+       mc417_memory_write(dev, dev->cx23417_mailbox + 1, command);
+       mc417_memory_write(dev, dev->cx23417_mailbox + 3,
+               IVTV_API_STD_TIMEOUT); /* timeout */
+       for (i = 0; i < in; i++) {
+               mc417_memory_write(dev, dev->cx23417_mailbox + 4 + i, data[i]);
+               dprintk(3, "API Input %d = %d\n", i, data[i]);
+       }
+       for (; i < CX2341X_MBOX_MAX_DATA; i++)
+               mc417_memory_write(dev, dev->cx23417_mailbox + 4 + i, 0);
+
+       flag |= 3; /* tell 'em we're done writing */
+       mc417_memory_write(dev, dev->cx23417_mailbox, flag);
+
+       /* wait for firmware to handle the API command */
+       timeout = jiffies + msecs_to_jiffies(10);
+       for (;;) {
+               mc417_memory_read(dev, dev->cx23417_mailbox, &flag);
+               if (0 != (flag & 4))
+                       break;
+               if (time_after(jiffies, timeout)) {
+                       printk(KERN_ERR "ERROR: API Mailbox timeout\n");
+                       return -1;
+               }
+               udelay(10);
+       }
+
+       /* read output values */
+       for (i = 0; i < out; i++) {
+               mc417_memory_read(dev, dev->cx23417_mailbox + 4 + i, data + i);
+               dprintk(3, "API Output %d = %d\n", i, data[i]);
+       }
+
+       mc417_memory_read(dev, dev->cx23417_mailbox + 2, &retval);
+       dprintk(3, "API result = %d\n", retval);
+
+       flag = 0;
+       mc417_memory_write(dev, dev->cx23417_mailbox, flag);
+
+       return retval;
+}
+
+/* We don't need to call the API often, so using just one
+ * mailbox will probably suffice
+ */
+static int cx23885_api_cmd(struct cx23885_dev *dev,
+                          u32 command,
+                          u32 inputcnt,
+                          u32 outputcnt,
+                          ...)
+{
+       u32 data[CX2341X_MBOX_MAX_DATA];
+       va_list vargs;
+       int i, err;
+
+       dprintk(3, "%s() cmds = 0x%08x\n", __func__, command);
+
+       va_start(vargs, outputcnt);
+       for (i = 0; i < inputcnt; i++)
+               data[i] = va_arg(vargs, int);
+
+       err = cx23885_mbox_func(dev, command, inputcnt, outputcnt, data);
+       for (i = 0; i < outputcnt; i++) {
+               int *vptr = va_arg(vargs, int *);
+               *vptr = data[i];
+       }
+       va_end(vargs);
+
+       return err;
+}
+
+static int cx23885_find_mailbox(struct cx23885_dev *dev)
+{
+       u32 signature[4] = {
+               0x12345678, 0x34567812, 0x56781234, 0x78123456
+       };
+       int signaturecnt = 0;
+       u32 value;
+       int i;
+
+       dprintk(2, "%s()\n", __func__);
+
+       for (i = 0; i < CX23885_FIRM_IMAGE_SIZE; i++) {
+               mc417_memory_read(dev, i, &value);
+               if (value == signature[signaturecnt])
+                       signaturecnt++;
+               else
+                       signaturecnt = 0;
+               if (4 == signaturecnt) {
+                       dprintk(1, "Mailbox signature found at 0x%x\n", i+1);
+                       return i+1;
+               }
+       }
+       printk(KERN_ERR "Mailbox signature values not found!\n");
+       return -1;
+}
+
+static int cx23885_load_firmware(struct cx23885_dev *dev)
+{
+       static const unsigned char magic[8] = {
+               0xa7, 0x0d, 0x00, 0x00, 0x66, 0xbb, 0x55, 0xaa
+       };
+       const struct firmware *firmware;
+       int i, retval = 0;
+       u32 value = 0;
+       u32 gpio_output = 0;
+       u32 checksum = 0;
+       u32 *dataptr;
+
+       dprintk(2, "%s()\n", __func__);
+
+       /* Save GPIO settings before reset of APU */
+       retval |= mc417_memory_read(dev, 0x9020, &gpio_output);
+       retval |= mc417_memory_read(dev, 0x900C, &value);
+
+       retval  = mc417_register_write(dev,
+               IVTV_REG_VPU, 0xFFFFFFED);
+       retval |= mc417_register_write(dev,
+               IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST);
+       retval |= mc417_register_write(dev,
+               IVTV_REG_ENC_SDRAM_REFRESH, 0x80000800);
+       retval |= mc417_register_write(dev,
+               IVTV_REG_ENC_SDRAM_PRECHARGE, 0x1A);
+       retval |= mc417_register_write(dev,
+               IVTV_REG_APU, 0);
+
+       if (retval != 0) {
+               printk(KERN_ERR "%s: Error with mc417_register_write\n",
+                       __func__);
+               return -1;
+       }
+
+       retval = request_firmware(&firmware, CX23885_FIRM_IMAGE_NAME,
+                                 &dev->pci->dev);
+
+       if (retval != 0) {
+               printk(KERN_ERR
+                       "ERROR: Hotplug firmware request failed (%s).\n",
+                       CX2341X_FIRM_ENC_FILENAME);
+               printk(KERN_ERR "Please fix your hotplug setup, the board will "
+                       "not work without firmware loaded!\n");
+               return -1;
+       }
+
+       if (firmware->size != CX23885_FIRM_IMAGE_SIZE) {
+               printk(KERN_ERR "ERROR: Firmware size mismatch "
+                       "(have %zd, expected %d)\n",
+                       firmware->size, CX23885_FIRM_IMAGE_SIZE);
+               release_firmware(firmware);
+               return -1;
+       }
+
+       if (0 != memcmp(firmware->data, magic, 8)) {
+               printk(KERN_ERR
+                       "ERROR: Firmware magic mismatch, wrong file?\n");
+               release_firmware(firmware);
+               return -1;
+       }
+
+       /* transfer to the chip */
+       dprintk(2, "Loading firmware ...\n");
+       dataptr = (u32 *)firmware->data;
+       for (i = 0; i < (firmware->size >> 2); i++) {
+               value = *dataptr;
+               checksum += ~value;
+               if (mc417_memory_write(dev, i, value) != 0) {
+                       printk(KERN_ERR "ERROR: Loading firmware failed!\n");
+                       release_firmware(firmware);
+                       return -1;
+               }
+               dataptr++;
+       }
+
+       /* read back to verify with the checksum */
+       dprintk(1, "Verifying firmware ...\n");
+       for (i--; i >= 0; i--) {
+               if (mc417_memory_read(dev, i, &value) != 0) {
+                       printk(KERN_ERR "ERROR: Reading firmware failed!\n");
+                       release_firmware(firmware);
+                       return -1;
+               }
+               checksum -= ~value;
+       }
+       if (checksum) {
+               printk(KERN_ERR
+                       "ERROR: Firmware load failed (checksum mismatch).\n");
+               release_firmware(firmware);
+               return -1;
+       }
+       release_firmware(firmware);
+       dprintk(1, "Firmware upload successful.\n");
+
+       retval |= mc417_register_write(dev, IVTV_REG_HW_BLOCKS,
+               IVTV_CMD_HW_BLOCKS_RST);
+
+       /* Restore GPIO settings, make sure EIO14 is enabled as an output. */
+       dprintk(2, "%s: GPIO output EIO 0-15 was = 0x%x\n",
+               __func__, gpio_output);
+       /* Power-up seems to have GPIOs AFU. This was causing digital side
+        * to fail at power-up. Seems GPIOs should be set to 0x10ff0411 at
+        * power-up.
+        * gpio_output |= (1<<14);
+        */
+       /* Note: GPIO14 is specific to the HVR1800 here */
+       gpio_output = 0x10ff0411 | (1<<14);
+       retval |= mc417_register_write(dev, 0x9020, gpio_output | (1<<14));
+       dprintk(2, "%s: GPIO output EIO 0-15 now = 0x%x\n",
+               __func__, gpio_output);
+
+       dprintk(1, "%s: GPIO value  EIO 0-15 was = 0x%x\n",
+               __func__, value);
+       value |= (1<<14);
+       dprintk(1, "%s: GPIO value  EIO 0-15 now = 0x%x\n",
+               __func__, value);
+       retval |= mc417_register_write(dev, 0x900C, value);
+
+       retval |= mc417_register_read(dev, IVTV_REG_VPU, &value);
+       retval |= mc417_register_write(dev, IVTV_REG_VPU, value & 0xFFFFFFE8);
+
+       if (retval < 0)
+               printk(KERN_ERR "%s: Error with mc417_register_write\n",
+                       __func__);
+       return 0;
+}
+
+void cx23885_417_check_encoder(struct cx23885_dev *dev)
+{
+       u32 status, seq;
+
+       status = seq = 0;
+       cx23885_api_cmd(dev, CX2341X_ENC_GET_SEQ_END, 0, 2, &status, &seq);
+       dprintk(1, "%s() status = %d, seq = %d\n", __func__, status, seq);
+}
+
+static void cx23885_codec_settings(struct cx23885_dev *dev)
+{
+       dprintk(1, "%s()\n", __func__);
+
+       /* assign frame size */
+       cx23885_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
+                               dev->ts1.height, dev->ts1.width);
+
+       dev->mpeg_params.width = dev->ts1.width;
+       dev->mpeg_params.height = dev->ts1.height;
+       dev->mpeg_params.is_50hz =
+               (dev->encodernorm.id & V4L2_STD_625_50) != 0;
+
+       cx2341x_update(dev, cx23885_mbox_func, NULL, &dev->mpeg_params);
+
+       cx23885_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 3, 1);
+       cx23885_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 4, 1);
+}
+
+static int cx23885_initialize_codec(struct cx23885_dev *dev)
+{
+       int version;
+       int retval;
+       u32 i, data[7];
+
+       dprintk(1, "%s()\n", __func__);
+
+       retval = cx23885_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */
+       if (retval < 0) {
+               dprintk(2, "%s() PING OK\n", __func__);
+               retval = cx23885_load_firmware(dev);
+               if (retval < 0) {
+                       printk(KERN_ERR "%s() f/w load failed\n", __func__);
+                       return retval;
+               }
+               dev->cx23417_mailbox = cx23885_find_mailbox(dev);
+               if (dev->cx23417_mailbox < 0) {
+                       printk(KERN_ERR "%s() mailbox < 0, error\n",
+                               __func__);
+                       return -1;
+               }
+               retval = cx23885_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0);
+               if (retval < 0) {
+                       printk(KERN_ERR
+                               "ERROR: cx23417 firmware ping failed!\n");
+                       return -1;
+               }
+               retval = cx23885_api_cmd(dev, CX2341X_ENC_GET_VERSION, 0, 1,
+                       &version);
+               if (retval < 0) {
+                       printk(KERN_ERR "ERROR: cx23417 firmware get encoder :"
+                               "version failed!\n");
+                       return -1;
+               }
+               dprintk(1, "cx23417 firmware version is 0x%08x\n", version);
+               msleep(200);
+       }
+
+       cx23885_codec_settings(dev);
+       msleep(60);
+
+       cx23885_api_cmd(dev, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, 0,
+               CX23885_FIELD1_SAA7115, CX23885_FIELD2_SAA7115);
+       cx23885_api_cmd(dev, CX2341X_ENC_SET_PLACEHOLDER, 12, 0,
+               CX23885_CUSTOM_EXTENSION_USR_DATA, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0);
+
+       /* Setup to capture VBI */
+       data[0] = 0x0001BD00;
+       data[1] = 1;          /* frames per interrupt */
+       data[2] = 4;          /* total bufs */
+       data[3] = 0x91559155; /* start codes */
+       data[4] = 0x206080C0; /* stop codes */
+       data[5] = 6;          /* lines */
+       data[6] = 64;         /* BPL */
+
+       cx23885_api_cmd(dev, CX2341X_ENC_SET_VBI_CONFIG, 7, 0, data[0], data[1],
+               data[2], data[3], data[4], data[5], data[6]);
+
+       for (i = 2; i <= 24; i++) {
+               int valid;
+
+               valid = ((i >= 19) && (i <= 21));
+               cx23885_api_cmd(dev, CX2341X_ENC_SET_VBI_LINE, 5, 0, i,
+                               valid, 0 , 0, 0);
+               cx23885_api_cmd(dev, CX2341X_ENC_SET_VBI_LINE, 5, 0,
+                               i | 0x80000000, valid, 0, 0, 0);
+       }
+
+       cx23885_api_cmd(dev, CX2341X_ENC_MUTE_AUDIO, 1, 0, CX23885_UNMUTE);
+       msleep(60);
+
+       /* initialize the video input */
+       cx23885_api_cmd(dev, CX2341X_ENC_INITIALIZE_INPUT, 0, 0);
+       msleep(60);
+
+       /* Enable VIP style pixel invalidation so we work with scaled mode */
+       mc417_memory_write(dev, 2120, 0x00000080);
+
+       /* start capturing to the host interface */
+       cx23885_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0,
+               CX23885_MPEG_CAPTURE, CX23885_RAW_BITS_NONE);
+       msleep(10);
+
+       return 0;
+}
+
+/* ------------------------------------------------------------------ */
+
+static int bb_buf_setup(struct videobuf_queue *q,
+       unsigned int *count, unsigned int *size)
+{
+       struct cx23885_fh *fh = q->priv_data;
+
+       fh->dev->ts1.ts_packet_size  = mpeglinesize;
+       fh->dev->ts1.ts_packet_count = mpeglines;
+
+       *size = fh->dev->ts1.ts_packet_size * fh->dev->ts1.ts_packet_count;
+       *count = mpegbufs;
+
+       return 0;
+}
+
+static int bb_buf_prepare(struct videobuf_queue *q,
+       struct videobuf_buffer *vb, enum v4l2_field field)
+{
+       struct cx23885_fh *fh = q->priv_data;
+       return cx23885_buf_prepare(q, &fh->dev->ts1,
+               (struct cx23885_buffer *)vb,
+               field);
+}
+
+static void bb_buf_queue(struct videobuf_queue *q,
+       struct videobuf_buffer *vb)
+{
+       struct cx23885_fh *fh = q->priv_data;
+       cx23885_buf_queue(&fh->dev->ts1, (struct cx23885_buffer *)vb);
+}
+
+static void bb_buf_release(struct videobuf_queue *q,
+       struct videobuf_buffer *vb)
+{
+       cx23885_free_buffer(q, (struct cx23885_buffer *)vb);
+}
+
+static struct videobuf_queue_ops cx23885_qops = {
+       .buf_setup    = bb_buf_setup,
+       .buf_prepare  = bb_buf_prepare,
+       .buf_queue    = bb_buf_queue,
+       .buf_release  = bb_buf_release,
+};
+
+/* ------------------------------------------------------------------ */
+
+static const u32 *ctrl_classes[] = {
+       cx2341x_mpeg_ctrls,
+       NULL
+};
+
+static int cx23885_queryctrl(struct cx23885_dev *dev,
+       struct v4l2_queryctrl *qctrl)
+{
+       qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
+       if (qctrl->id == 0)
+               return -EINVAL;
+
+       /* MPEG V4L2 controls */
+       if (cx2341x_ctrl_query(&dev->mpeg_params, qctrl))
+               qctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
+
+       return 0;
+}
+
+static int cx23885_querymenu(struct cx23885_dev *dev,
+       struct v4l2_querymenu *qmenu)
+{
+       struct v4l2_queryctrl qctrl;
+
+       qctrl.id = qmenu->id;
+       cx23885_queryctrl(dev, &qctrl);
+       return v4l2_ctrl_query_menu(qmenu, &qctrl,
+               cx2341x_ctrl_get_menu(qmenu->id));
+}
+
+int cx23885_do_ioctl(struct inode *inode, struct file *file, int radio,
+       struct cx23885_dev *dev, unsigned int cmd, void *arg,
+       v4l2_kioctl driver_ioctl)
+{
+       int err;
+
+       switch (cmd) {
+       /* ---------- tv norms ---------- */
+       case VIDIOC_ENUMSTD:
+       {
+               struct v4l2_standard *e = arg;
+               unsigned int i;
+
+               i = e->index;
+               if (i >= ARRAY_SIZE(cx23885_tvnorms))
+                       return -EINVAL;
+               err = v4l2_video_std_construct(e,
+                       cx23885_tvnorms[e->index].id,
+                       cx23885_tvnorms[e->index].name);
+               e->index = i;
+               if (err < 0)
+                       return err;
+               return 0;
+       }
+       case VIDIOC_G_STD:
+       {
+               v4l2_std_id *id = arg;
+
+               *id = dev->encodernorm.id;
+               return 0;
+       }
+       case VIDIOC_S_STD:
+       {
+               v4l2_std_id *id = arg;
+               unsigned int i;
+
+               for (i = 0; i < ARRAY_SIZE(cx23885_tvnorms); i++)
+                       if (*id & cx23885_tvnorms[i].id)
+                               break;
+               if (i == ARRAY_SIZE(cx23885_tvnorms))
+                       return -EINVAL;
+               dev->encodernorm = cx23885_tvnorms[i];
+
+               return 0;
+       }
+
+       /* ------ input switching ---------- */
+       case VIDIOC_ENUMINPUT:
+       {
+               struct cx23885_input *input;
+               struct v4l2_input *i = arg;
+               unsigned int n;
+
+               n = i->index;
+               if (n >= 4)
+                       return -EINVAL;
+               input = &cx23885_boards[dev->board].input[n];
+               if (input->type == 0)
+                       return -EINVAL;
+               memset(i, 0, sizeof(*i));
+               i->index = n;
+               /* FIXME
+                * strcpy(i->name, input->name); */
+               strcpy(i->name, "unset");
+               if (input->type == CX23885_VMUX_TELEVISION ||
+                   input->type == CX23885_VMUX_CABLE)
+                       i->type = V4L2_INPUT_TYPE_TUNER;
+               else
+                       i->type  = V4L2_INPUT_TYPE_CAMERA;
+
+               for (n = 0; n < ARRAY_SIZE(cx23885_tvnorms); n++)
+                       i->std |= cx23885_tvnorms[n].id;
+               return 0;
+       }
+       case VIDIOC_G_INPUT:
+       {
+               unsigned int *i = arg;
+
+               *i = dev->input;
+               return 0;
+       }
+       case VIDIOC_S_INPUT:
+       {
+               unsigned int *i = arg;
+
+               if (*i >= 4)
+                       return -EINVAL;
+
+               return 0;
+       }
+
+       /* --- tuner ioctls ------------------------------------------ */
+       case VIDIOC_G_TUNER:
+       {
+               struct v4l2_tuner *t = arg;
+
+               if (UNSET == dev->tuner_type)
+                       return -EINVAL;
+               if (0 != t->index)
+                       return -EINVAL;
+               memset(t, 0, sizeof(*t));
+               strcpy(t->name, "Television");
+               cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_G_TUNER, t);
+               cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_G_TUNER, t);
+
+               dprintk(1, "VIDIOC_G_TUNER: tuner type %d\n", t->type);
+
+               return 0;
+       }
+       case VIDIOC_S_TUNER:
+       {
+               struct v4l2_tuner *t = arg;
+
+               if (UNSET == dev->tuner_type)
+                       return -EINVAL;
+
+               /* Update the A/V core */
+               cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_TUNER, t);
+
+               return 0;
+       }
+       case VIDIOC_G_FREQUENCY:
+       {
+               struct v4l2_frequency *f = arg;
+
+               memset(f, 0, sizeof(*f));
+               if (UNSET == dev->tuner_type)
+                       return -EINVAL;
+               f->type = V4L2_TUNER_ANALOG_TV;
+               f->frequency = dev->freq;
+
+               /* Assumption that tuner is always on bus 1 */
+               cx23885_call_i2c_clients(&dev->i2c_bus[1],
+                       VIDIOC_G_FREQUENCY, f);
+
+               return 0;
+       }
+       case VIDIOC_S_FREQUENCY:
+       {
+               struct v4l2_frequency *f = arg;
+
+               dprintk(1, "VIDIOC_S_FREQUENCY: dev type %d, f\n",
+                       dev->tuner_type);
+               dprintk(1, "VIDIOC_S_FREQUENCY: f tuner %d, f type %d\n",
+                       f->tuner, f->type);
+               if (UNSET == dev->tuner_type)
+                       return -EINVAL;
+               if (f->tuner != 0)
+                       return -EINVAL;
+               if (f->type != V4L2_TUNER_ANALOG_TV)
+                       return -EINVAL;
+               dev->freq = f->frequency;
+
+               /* Assumption that tuner is always on bus 1 */
+               cx23885_call_i2c_clients(&dev->i2c_bus[1],
+                       VIDIOC_S_FREQUENCY, f);
+               return 0;
+       }
+       case VIDIOC_S_CTRL:
+       {
+               /* Update the A/V core */
+               cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_CTRL, arg);
+               return 0;
+       }
+       default:
+               /* Convert V4L ioctl to V4L2 and call mpeg_do_ioctl
+                * (driver_ioctl) */
+               return v4l_compat_translate_ioctl(inode, file, cmd, arg,
+                                                 driver_ioctl);
+       }
+
+       return 0;
+}
+
+static int mpeg_do_ioctl(struct inode *inode, struct file *file,
+                        unsigned int cmd, void *arg)
+{
+       struct cx23885_fh  *fh  = file->private_data;
+       struct cx23885_dev *dev = fh->dev;
+       struct cx23885_tsport  *tsport = &dev->ts1;
+
+       if (v4l_debug > 1)
+               v4l_print_ioctl(dev->name, cmd);
+
+       switch (cmd) {
+
+       /* --- capabilities ------------------------------------------ */
+       case VIDIOC_QUERYCAP:
+       {
+               struct v4l2_capability *cap = arg;
+
+               memset(cap, 0, sizeof(*cap));
+               strcpy(cap->driver, dev->name);
+               strlcpy(cap->card, cx23885_boards[tsport->dev->board].name,
+                       sizeof(cap->card));
+               sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
+               cap->version = CX23885_VERSION_CODE;
+               cap->capabilities =
+                       V4L2_CAP_VIDEO_CAPTURE |
+                       V4L2_CAP_READWRITE     |
+                       V4L2_CAP_STREAMING     |
+                       0;
+               if (UNSET != dev->tuner_type)
+                       cap->capabilities |= V4L2_CAP_TUNER;
+
+               return 0;
+       }
+
+       /* --- capture ioctls ---------------------------------------- */
+       case VIDIOC_ENUM_FMT:
+       {
+               struct v4l2_fmtdesc *f = arg;
+               int index;
+
+               index = f->index;
+               if (index != 0)
+                       return -EINVAL;
+
+               memset(f, 0, sizeof(*f));
+               f->index = index;
+               strlcpy(f->description, "MPEG", sizeof(f->description));
+               f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               f->pixelformat = V4L2_PIX_FMT_MPEG;
+               return 0;
+       }
+       case VIDIOC_G_FMT:
+       {
+               struct v4l2_format *f = arg;
+
+               memset(f, 0, sizeof(*f));
+               f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
+               f->fmt.pix.bytesperline = 0;
+               f->fmt.pix.sizeimage    =
+                       dev->ts1.ts_packet_size * dev->ts1.ts_packet_count;
+               f->fmt.pix.colorspace   = 0;
+               f->fmt.pix.width        = dev->ts1.width;
+               f->fmt.pix.height       = dev->ts1.height;
+               f->fmt.pix.field        = fh->mpegq.field;
+               dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d, f: %d\n",
+                       dev->ts1.width, dev->ts1.height, fh->mpegq.field);
+               return 0;
+       }
+       case VIDIOC_TRY_FMT:
+       {
+               struct v4l2_format *f = arg;
+
+               f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
+               f->fmt.pix.bytesperline = 0;
+               f->fmt.pix.sizeimage    =
+                       dev->ts1.ts_packet_size * dev->ts1.ts_packet_count;
+               f->fmt.pix.sizeimage    =
+               f->fmt.pix.colorspace   = 0;
+               dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n",
+                       dev->ts1.width, dev->ts1.height, fh->mpegq.field);
+               return 0;
+       }
+       case VIDIOC_S_FMT:
+       {
+               struct v4l2_format *f = arg;
+
+               f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
+               f->fmt.pix.bytesperline = 0;
+               f->fmt.pix.sizeimage    =
+                       dev->ts1.ts_packet_size * dev->ts1.ts_packet_count;
+               f->fmt.pix.colorspace   = 0;
+               dprintk(1, "VIDIOC_S_FMT: w: %d, h: %d, f: %d\n",
+                       f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field);
+               return 0;
+       }
+
+       /* --- streaming capture ------------------------------------- */
+       case VIDIOC_REQBUFS:
+               return videobuf_reqbufs(&fh->mpegq, arg);
+
+       case VIDIOC_QUERYBUF:
+               return videobuf_querybuf(&fh->mpegq, arg);
+
+       case VIDIOC_QBUF:
+               return videobuf_qbuf(&fh->mpegq, arg);
+
+       case VIDIOC_DQBUF:
+               return videobuf_dqbuf(&fh->mpegq, arg,
+                                     file->f_flags & O_NONBLOCK);
+
+       case VIDIOC_STREAMON:
+               return videobuf_streamon(&fh->mpegq);
+
+       case VIDIOC_STREAMOFF:
+               return videobuf_streamoff(&fh->mpegq);
+
+       case VIDIOC_G_EXT_CTRLS:
+       {
+               struct v4l2_ext_controls *f = arg;
+
+               if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
+                       return -EINVAL;
+               return cx2341x_ext_ctrls(&dev->mpeg_params, 0, f, cmd);
+       }
+       case VIDIOC_S_EXT_CTRLS:
+       case VIDIOC_TRY_EXT_CTRLS:
+       {
+               struct v4l2_ext_controls *f = arg;
+               struct cx2341x_mpeg_params p;
+               int err;
+
+               if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
+                       return -EINVAL;
+               p = dev->mpeg_params;
+               err = cx2341x_ext_ctrls(&p, 0, f, cmd);
+               if (err == 0 && cmd == VIDIOC_S_EXT_CTRLS) {
+                       err = cx2341x_update(dev, cx23885_mbox_func,
+                               &dev->mpeg_params, &p);
+                       dev->mpeg_params = p;
+               }
+               return err;
+       }
+       case VIDIOC_S_FREQUENCY:
+       {
+               cx23885_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
+                       CX23885_END_NOW, CX23885_MPEG_CAPTURE,
+                       CX23885_RAW_BITS_NONE);
+               cx23885_do_ioctl(inode, file, 0, dev, cmd, arg,
+                       mpeg_do_ioctl);
+               cx23885_initialize_codec(dev);
+
+               return 0;
+       }
+       case VIDIOC_LOG_STATUS:
+       {
+               char name[32 + 2];
+
+               snprintf(name, sizeof(name), "%s/2", dev->name);
+               printk(KERN_INFO
+                       "%s/2: ============  START LOG STATUS  ============\n",
+                      dev->name);
+               cx23885_call_i2c_clients(&dev->i2c_bus[0], VIDIOC_LOG_STATUS,
+                       NULL);
+               cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_LOG_STATUS,
+                       NULL);
+               cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_LOG_STATUS,
+                       NULL);
+               cx2341x_log_status(&dev->mpeg_params, name);
+               printk(KERN_INFO
+                       "%s/2: =============  END LOG STATUS  =============\n",
+                      dev->name);
+               return 0;
+       }
+       case VIDIOC_QUERYMENU:
+               return cx23885_querymenu(dev, arg);
+       case VIDIOC_QUERYCTRL:
+       {
+               struct v4l2_queryctrl *c = arg;
+
+               return cx23885_queryctrl(dev, c);
+       }
+
+       default:
+               return cx23885_do_ioctl(inode, file, 0, dev, cmd, arg,
+                               mpeg_do_ioctl);
+       }
+       return 0;
+}
+
+static int mpeg_ioctl(struct inode *inode, struct file *file,
+                       unsigned int cmd, unsigned long arg)
+{
+       return video_usercopy(inode, file, cmd, arg, mpeg_do_ioctl);
+}
+
+static int mpeg_open(struct inode *inode, struct file *file)
+{
+       int minor = iminor(inode);
+       struct cx23885_dev *h, *dev = NULL;
+       struct list_head *list;
+       struct cx23885_fh *fh;
+
+       dprintk(2, "%s()\n", __func__);
+
+       list_for_each(list, &cx23885_devlist) {
+               h = list_entry(list, struct cx23885_dev, devlist);
+               if (h->v4l_device->minor == minor) {
+                       dev = h;
+                       break;
+               }
+       }
+
+       if (dev == NULL)
+               return -ENODEV;
+
+       /* allocate + initialize per filehandle data */
+       fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+       if (NULL == fh)
+               return -ENOMEM;
+
+       file->private_data = fh;
+       fh->dev      = dev;
+
+       videobuf_queue_sg_init(&fh->mpegq, &cx23885_qops,
+                           &dev->pci->dev, &dev->ts1.slock,
+                           V4L2_BUF_TYPE_VIDEO_CAPTURE,
+                           V4L2_FIELD_INTERLACED,
+                           sizeof(struct cx23885_buffer),
+                           fh);
+
+       return 0;
+}
+
+static int mpeg_release(struct inode *inode, struct file *file)
+{
+       struct cx23885_fh  *fh  = file->private_data;
+       struct cx23885_dev *dev = fh->dev;
+
+       dprintk(2, "%s()\n", __func__);
+
+       /* FIXME: Review this crap */
+       /* Shut device down on last close */
+       if (atomic_cmpxchg(&fh->v4l_reading, 1, 0) == 1) {
+               if (atomic_dec_return(&dev->v4l_reader_count) == 0) {
+                       /* stop mpeg capture */
+                       cx23885_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
+                               CX23885_END_NOW, CX23885_MPEG_CAPTURE,
+                               CX23885_RAW_BITS_NONE);
+
+                       msleep(500);
+                       cx23885_417_check_encoder(dev);
+
+                       cx23885_cancel_buffers(&fh->dev->ts1);
+               }
+       }
+
+       if (fh->mpegq.streaming)
+               videobuf_streamoff(&fh->mpegq);
+       if (fh->mpegq.reading)
+               videobuf_read_stop(&fh->mpegq);
+
+       videobuf_mmap_free(&fh->mpegq);
+       file->private_data = NULL;
+       kfree(fh);
+
+       return 0;
+}
+
+static ssize_t mpeg_read(struct file *file, char __user *data,
+       size_t count, loff_t *ppos)
+{
+       struct cx23885_fh *fh = file->private_data;
+       struct cx23885_dev *dev = fh->dev;
+
+       dprintk(2, "%s()\n", __func__);
+
+       /* Deal w/ A/V decoder * and mpeg encoder sync issues. */
+       /* Start mpeg encoder on first read. */
+       if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) {
+               if (atomic_inc_return(&dev->v4l_reader_count) == 1) {
+                       if (cx23885_initialize_codec(dev) < 0)
+                               return -EINVAL;
+               }
+       }
+
+       return videobuf_read_stream(&fh->mpegq, data, count, ppos, 0,
+                                   file->f_flags & O_NONBLOCK);
+}
+
+static unsigned int mpeg_poll(struct file *file,
+       struct poll_table_struct *wait)
+{
+       struct cx23885_fh *fh = file->private_data;
+       struct cx23885_dev *dev = fh->dev;
+
+       dprintk(2, "%s\n", __func__);
+
+       return videobuf_poll_stream(file, &fh->mpegq, wait);
+}
+
+static int mpeg_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct cx23885_fh *fh = file->private_data;
+       struct cx23885_dev *dev = fh->dev;
+
+       dprintk(2, "%s()\n", __func__);
+
+       return videobuf_mmap_mapper(&fh->mpegq, vma);
+}
+
+static struct file_operations mpeg_fops = {
+       .owner         = THIS_MODULE,
+       .open          = mpeg_open,
+       .release       = mpeg_release,
+       .read          = mpeg_read,
+       .poll          = mpeg_poll,
+       .mmap          = mpeg_mmap,
+       .ioctl         = mpeg_ioctl,
+       .llseek        = no_llseek,
+};
+
+static struct video_device cx23885_mpeg_template = {
+       .name          = "cx23885",
+       .type          = VID_TYPE_CAPTURE |
+                               VID_TYPE_TUNER |
+                               VID_TYPE_SCALES |
+                               VID_TYPE_MPEG_ENCODER,
+       .fops          = &mpeg_fops,
+       .minor         = -1,
+};
+
+void cx23885_417_unregister(struct cx23885_dev *dev)
+{
+       dprintk(1, "%s()\n", __func__);
+
+       if (dev->v4l_device) {
+               if (-1 != dev->v4l_device->minor)
+                       video_unregister_device(dev->v4l_device);
+               else
+                       video_device_release(dev->v4l_device);
+               dev->v4l_device = NULL;
+       }
+}
+
+static struct video_device *cx23885_video_dev_alloc(
+       struct cx23885_tsport *tsport,
+       struct pci_dev *pci,
+       struct video_device *template,
+       char *type)
+{
+       struct video_device *vfd;
+       struct cx23885_dev *dev = tsport->dev;
+
+       dprintk(1, "%s()\n", __func__);
+
+       vfd = video_device_alloc();
+       if (NULL == vfd)
+               return NULL;
+       *vfd = *template;
+       vfd->minor   = -1;
+       snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name,
+               type, cx23885_boards[tsport->dev->board].name);
+       vfd->dev     = &pci->dev;
+       vfd->release = video_device_release;
+       return vfd;
+}
+
+int cx23885_417_register(struct cx23885_dev *dev)
+{
+       /* FIXME: Port1 hardcoded here */
+       int err = -ENODEV;
+       struct cx23885_tsport *tsport = &dev->ts1;
+
+       dprintk(1, "%s()\n", __func__);
+
+       if (cx23885_boards[dev->board].portb != CX23885_MPEG_ENCODER)
+               return err;
+
+       /* Set default TV standard */
+       dev->encodernorm = cx23885_tvnorms[0];
+
+       if (dev->encodernorm.id & V4L2_STD_525_60)
+               tsport->height = 480;
+       else
+               tsport->height = 576;
+
+       tsport->width = 720;
+       cx2341x_fill_defaults(&dev->mpeg_params);
+
+       dev->mpeg_params.port = CX2341X_PORT_SERIAL;
+
+       /* Allocate and initialize V4L video device */
+       dev->v4l_device = cx23885_video_dev_alloc(tsport,
+               dev->pci, &cx23885_mpeg_template, "mpeg");
+       err = video_register_device(dev->v4l_device,
+               VFL_TYPE_GRABBER, -1);
+       if (err < 0) {
+               printk(KERN_INFO "%s: can't register mpeg device\n", dev->name);
+               return err;
+       }
+
+       /* Initialize MC417 registers */
+       cx23885_mc417_init(dev);
+
+       printk(KERN_INFO "%s: registered device video%d [mpeg]\n",
+              dev->name, dev->v4l_device->minor & 0x1f);
+
+       return 0;
+}
index dfa269838e012d8ceb9d6580d2e39f4e03676171..6ebf58724a0134d27737b015a0acced695252ce0 100644 (file)
@@ -73,6 +73,7 @@ struct cx23885_board cx23885_boards[] = {
        [CX23885_BOARD_HAUPPAUGE_HVR1800] = {
                .name           = "Hauppauge WinTV-HVR1800",
                .porta          = CX23885_ANALOG_VIDEO,
+               .portb          = CX23885_MPEG_ENCODER,
                .portc          = CX23885_MPEG_DVB,
                .tuner_type     = TUNER_PHILIPS_TDA8290,
                .tuner_addr     = 0x42, /* 0x84 >> 1 */
@@ -130,6 +131,18 @@ struct cx23885_board cx23885_boards[] = {
                .name           = "Hauppauge WinTV-HVR1500",
                .portc          = CX23885_MPEG_DVB,
        },
+       [CX23885_BOARD_HAUPPAUGE_HVR1200] = {
+               .name           = "Hauppauge WinTV-HVR1200",
+               .portc          = CX23885_MPEG_DVB,
+       },
+       [CX23885_BOARD_HAUPPAUGE_HVR1700] = {
+               .name           = "Hauppauge WinTV-HVR1700",
+               .portc          = CX23885_MPEG_DVB,
+       },
+       [CX23885_BOARD_HAUPPAUGE_HVR1400] = {
+               .name           = "Hauppauge WinTV-HVR1400",
+               .portc          = CX23885_MPEG_DVB,
+       },
 };
 const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards);
 
@@ -181,6 +194,18 @@ struct cx23885_subid cx23885_subids[] = {
                .subvendor = 0x0070,
                .subdevice = 0x7717,
                .card      = CX23885_BOARD_HAUPPAUGE_HVR1500,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x71d1,
+               .card      = CX23885_BOARD_HAUPPAUGE_HVR1200,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x8101,
+               .card      = CX23885_BOARD_HAUPPAUGE_HVR1700,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x8010,
+               .card      = CX23885_BOARD_HAUPPAUGE_HVR1400,
        },
 };
 const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids);
@@ -235,6 +260,12 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data)
        case 79561: /* WinTV-HVR1250 (PCIe, OEM, No IR, half height, ATSC and Basic analog */
        case 79571: /* WinTV-HVR1250 (PCIe, OEM, No IR, full height, ATSC and Basic analog */
        case 79671: /* WinTV-HVR1250 (PCIe, OEM, No IR, half height, ATSC and Basic analog */
+       case 80019:
+               /* WinTV-HVR1400 (Express Card, Retail, IR,
+                * DVB-T and Basic analog */
+       case 81519:
+               /* WinTV-HVR1700 (PCIe, Retail, No IR, half height,
+                * DVB-T and MPEG2 HW Encoder */
                break;
        default:
                printk("%s: warning: unknown hauppauge model #%d\n", dev->name, tv.model);
@@ -264,7 +295,7 @@ int cx23885_tuner_callback(void *priv, int command, int arg)
                }
                else {
                        printk(KERN_ERR
-                               "%s(): Unknow command.\n", __FUNCTION__);
+                               "%s(): Unknow command.\n", __func__);
                        return -EINVAL;
                }
                break;
@@ -306,6 +337,10 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
                /* GPIO-15-18 cx23417 READY, CS, RD, WR */
                /* GPIO-19 IR_RX */
 
+               /* CX23417 GPIO's */
+               /* EIO15 Zilog Reset */
+               /* EIO14 S5H1409/CX24227 Reset */
+
                /* Force the TDA8295A into reset and back */
                cx_set(GP0_IO, 0x00040004);
                mdelay(20);
@@ -314,6 +349,50 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
                cx_set(GP0_IO, 0x00040004);
                mdelay(20);
                break;
+       case CX23885_BOARD_HAUPPAUGE_HVR1200:
+               /* GPIO-0 tda10048 demodulator reset */
+               /* GPIO-2 tda18271 tuner reset */
+
+               /* Put the parts into reset and back */
+               cx_set(GP0_IO, 0x00050000);
+               mdelay(20);
+               cx_clear(GP0_IO, 0x00000005);
+               mdelay(20);
+               cx_set(GP0_IO, 0x00050005);
+               break;
+       case CX23885_BOARD_HAUPPAUGE_HVR1700:
+               /* GPIO-0 TDA10048 demodulator reset */
+               /* GPIO-2 TDA8295A Reset */
+               /* GPIO-3-10 cx23417 data0-7 */
+               /* GPIO-11-14 cx23417 addr0-3 */
+               /* GPIO-15-18 cx23417 READY, CS, RD, WR */
+
+               /* The following GPIO's are on the interna AVCore (cx25840) */
+               /* GPIO-19 IR_RX */
+               /* GPIO-20 IR_TX 416/DVBT Select */
+               /* GPIO-21 IIS DAT */
+               /* GPIO-22 IIS WCLK */
+               /* GPIO-23 IIS BCLK */
+
+               /* Put the parts into reset and back */
+               cx_set(GP0_IO, 0x00050000);
+               mdelay(20);
+               cx_clear(GP0_IO, 0x00000005);
+               mdelay(20);
+               cx_set(GP0_IO, 0x00050005);
+               break;
+       case CX23885_BOARD_HAUPPAUGE_HVR1400:
+               /* GPIO-0  Dibcom7000p demodulator reset */
+               /* GPIO-2  xc3028L tuner reset */
+               /* GPIO-13 LED */
+
+               /* Put the parts into reset and back */
+               cx_set(GP0_IO, 0x00050000);
+               mdelay(20);
+               cx_clear(GP0_IO, 0x00000005);
+               mdelay(20);
+               cx_set(GP0_IO, 0x00050005);
+               break;
        }
 }
 
@@ -324,6 +403,8 @@ int cx23885_ir_init(struct cx23885_dev *dev)
        case CX23885_BOARD_HAUPPAUGE_HVR1500:
        case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
        case CX23885_BOARD_HAUPPAUGE_HVR1800:
+       case CX23885_BOARD_HAUPPAUGE_HVR1200:
+       case CX23885_BOARD_HAUPPAUGE_HVR1400:
                /* FIXME: Implement me */
                break;
        }
@@ -348,11 +429,14 @@ void cx23885_card_setup(struct cx23885_dev *dev)
        case CX23885_BOARD_HAUPPAUGE_HVR1250:
        case CX23885_BOARD_HAUPPAUGE_HVR1500:
        case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
+       case CX23885_BOARD_HAUPPAUGE_HVR1400:
                if (dev->i2c_bus[0].i2c_rc == 0)
                        hauppauge_eeprom(dev, eeprom+0x80);
                break;
        case CX23885_BOARD_HAUPPAUGE_HVR1800:
        case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
+       case CX23885_BOARD_HAUPPAUGE_HVR1200:
+       case CX23885_BOARD_HAUPPAUGE_HVR1700:
                if (dev->i2c_bus[0].i2c_rc == 0)
                        hauppauge_eeprom(dev, eeprom+0xc0);
                break;
@@ -364,17 +448,45 @@ void cx23885_card_setup(struct cx23885_dev *dev)
                ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
                ts1->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
                break;
+       case CX23885_BOARD_HAUPPAUGE_HVR1800:
+               /* Defaults for VID B - Analog encoder */
+               /* DREQ_POL, SMODE, PUNC_CLK, MCLK_POL Serial bus + punc clk */
+               ts1->gen_ctrl_val    = 0x10e;
+               ts1->ts_clk_en_val   = 0x1; /* Enable TS_CLK */
+               ts1->src_sel_val     = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
+
+               /* APB_TSVALERR_POL (active low)*/
+               ts1->vld_misc_val    = 0x2000;
+               ts1->hw_sop_ctrl_val = (0x47 << 16 | 188 << 4 | 0xc);
+
+               /* Defaults for VID C */
+               ts2->gen_ctrl_val  = 0xc; /* Serial bus + punctured clock */
+               ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
+               ts2->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
+               break;
        case CX23885_BOARD_HAUPPAUGE_HVR1250:
        case CX23885_BOARD_HAUPPAUGE_HVR1500:
        case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
-       case CX23885_BOARD_HAUPPAUGE_HVR1800:
        case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
+       case CX23885_BOARD_HAUPPAUGE_HVR1200:
+       case CX23885_BOARD_HAUPPAUGE_HVR1700:
+       case CX23885_BOARD_HAUPPAUGE_HVR1400:
        default:
                ts2->gen_ctrl_val  = 0xc; /* Serial bus + punctured clock */
                ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
                ts2->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
        }
 
+       /* Certain boards support analog, or require the avcore to be
+        * loaded, ensure this happens.
+        */
+       switch (dev->board) {
+       case CX23885_BOARD_HAUPPAUGE_HVR1800:
+       case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
+       case CX23885_BOARD_HAUPPAUGE_HVR1700:
+               request_module("cx25840");
+               break;
+       }
 }
 
 /* ------------------------------------------------------------------ */
index 7f10b273598fd460101c995d8af958845f8958ac..f24abcd06dea0eb1027630be34ca934daa87d6e8 100644 (file)
@@ -190,25 +190,25 @@ static struct sram_channel cx23887_sram_channels[] = {
 static int cx23885_risc_decode(u32 risc)
 {
        static char *instr[16] = {
-               [ RISC_SYNC    >> 28 ] = "sync",
-               [ RISC_WRITE   >> 28 ] = "write",
-               [ RISC_WRITEC  >> 28 ] = "writec",
-               [ RISC_READ    >> 28 ] = "read",
-               [ RISC_READC   >> 28 ] = "readc",
-               [ RISC_JUMP    >> 28 ] = "jump",
-               [ RISC_SKIP    >> 28 ] = "skip",
-               [ RISC_WRITERM >> 28 ] = "writerm",
-               [ RISC_WRITECM >> 28 ] = "writecm",
-               [ RISC_WRITECR >> 28 ] = "writecr",
+               [RISC_SYNC    >> 28] = "sync",
+               [RISC_WRITE   >> 28] = "write",
+               [RISC_WRITEC  >> 28] = "writec",
+               [RISC_READ    >> 28] = "read",
+               [RISC_READC   >> 28] = "readc",
+               [RISC_JUMP    >> 28] = "jump",
+               [RISC_SKIP    >> 28] = "skip",
+               [RISC_WRITERM >> 28] = "writerm",
+               [RISC_WRITECM >> 28] = "writecm",
+               [RISC_WRITECR >> 28] = "writecr",
        };
        static int incr[16] = {
-               [ RISC_WRITE   >> 28 ] = 3,
-               [ RISC_JUMP    >> 28 ] = 3,
-               [ RISC_SKIP    >> 28 ] = 1,
-               [ RISC_SYNC    >> 28 ] = 1,
-               [ RISC_WRITERM >> 28 ] = 3,
-               [ RISC_WRITECM >> 28 ] = 3,
-               [ RISC_WRITECR >> 28 ] = 4,
+               [RISC_WRITE   >> 28] = 3,
+               [RISC_JUMP    >> 28] = 3,
+               [RISC_SKIP    >> 28] = 1,
+               [RISC_SYNC    >> 28] = 1,
+               [RISC_WRITERM >> 28] = 3,
+               [RISC_WRITECM >> 28] = 3,
+               [RISC_WRITECR >> 28] = 4,
        };
        static char *bits[] = {
                "12",   "13",   "14",   "resync",
@@ -260,7 +260,7 @@ void cx23885_wakeup(struct cx23885_tsport *port,
        }
        if (bc != 1)
                printk("%s: %d buffers handled (should be 1)\n",
-                      __FUNCTION__, bc);
+                      __func__, bc);
 }
 
 int cx23885_sram_channel_setup(struct cx23885_dev *dev,
@@ -272,7 +272,7 @@ int cx23885_sram_channel_setup(struct cx23885_dev *dev,
 
        if (ch->cmds_start == 0)
        {
-               dprintk(1, "%s() Erasing channel [%s]\n", __FUNCTION__,
+               dprintk(1, "%s() Erasing channel [%s]\n", __func__,
                        ch->name);
                cx_write(ch->ptr1_reg, 0);
                cx_write(ch->ptr2_reg, 0);
@@ -280,7 +280,7 @@ int cx23885_sram_channel_setup(struct cx23885_dev *dev,
                cx_write(ch->cnt1_reg, 0);
                return 0;
        } else {
-               dprintk(1, "%s() Configuring channel [%s]\n", __FUNCTION__,
+               dprintk(1, "%s() Configuring channel [%s]\n", __func__,
                        ch->name);
        }
 
@@ -297,7 +297,7 @@ int cx23885_sram_channel_setup(struct cx23885_dev *dev,
 
        /* write CDT */
        for (i = 0; i < lines; i++) {
-               dprintk(2, "%s() 0x%08x <- 0x%08x\n", __FUNCTION__, cdt + 16*i,
+               dprintk(2, "%s() 0x%08x <- 0x%08x\n", __func__, cdt + 16*i,
                        ch->fifo_start + bpl*i);
                cx_write(cdt + 16*i, ch->fifo_start + bpl*i);
                cx_write(cdt + 16*i +  4, 0);
@@ -449,7 +449,7 @@ static void cx23885_shutdown(struct cx23885_dev *dev)
 
 static void cx23885_reset(struct cx23885_dev *dev)
 {
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
 
        cx23885_shutdown(dev);
 
@@ -482,7 +482,7 @@ static void cx23885_reset(struct cx23885_dev *dev)
 
 static int cx23885_pci_quirks(struct cx23885_dev *dev)
 {
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
 
        /* The cx23885 bridge has a weird bug which causes NMI to be asserted
         * when DMA begins if RDR_TLCTL0 bit4 is not cleared. It does not
@@ -513,11 +513,13 @@ int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
 
 static int cx23885_init_tsport(struct cx23885_dev *dev, struct cx23885_tsport *port, int portno)
 {
-       dprintk(1, "%s(portno=%d)\n", __FUNCTION__, portno);
+       dprintk(1, "%s(portno=%d)\n", __func__, portno);
 
        /* Transport bus init dma queue  - Common settings */
        port->dma_ctl_val        = 0x11; /* Enable RISC controller and Fifo */
        port->ts_int_msk_val     = 0x1111; /* TS port bits for RISC */
+       port->vld_misc_val       = 0x0;
+       port->hw_sop_ctrl_val    = (0x47 << 16 | 188 << 4);
 
        spin_lock_init(&port->slock);
        port->dev = dev;
@@ -544,7 +546,7 @@ static int cx23885_init_tsport(struct cx23885_dev *dev, struct cx23885_tsport *p
                port->reg_ts_clk_en      = VID_B_TS_CLK_EN;
                port->reg_src_sel        = VID_B_SRC_SEL;
                port->reg_ts_int_msk     = VID_B_INT_MSK;
-               port->reg_ts_int_stat   = VID_B_INT_STAT;
+               port->reg_ts_int_stat    = VID_B_INT_STAT;
                port->sram_chno          = SRAM_CH03; /* VID_B */
                port->pci_irqmask        = 0x02; /* VID_B bit1 */
                break;
@@ -604,14 +606,14 @@ static void cx23885_dev_checkrevision(struct cx23885_dev *dev)
                break;
        default:
                printk(KERN_ERR "%s() New hardware revision found 0x%x\n",
-                       __FUNCTION__, dev->hwrevision);
+                       __func__, dev->hwrevision);
        }
        if (dev->hwrevision)
                printk(KERN_INFO "%s() Hardware revision = 0x%02x\n",
-                       __FUNCTION__, dev->hwrevision);
+                       __func__, dev->hwrevision);
        else
                printk(KERN_ERR "%s() Hardware revision unknown 0x%x\n",
-                       __FUNCTION__, dev->hwrevision);
+                       __func__, dev->hwrevision);
 }
 
 static int cx23885_dev_setup(struct cx23885_dev *dev)
@@ -644,7 +646,7 @@ static int cx23885_dev_setup(struct cx23885_dev *dev)
                BUG();
 
        dprintk(1, "%s() Memory configured for PCIe bridge type %d\n",
-               __FUNCTION__, dev->bridge);
+               __func__, dev->bridge);
 
        /* board config */
        dev->board = UNSET;
@@ -697,10 +699,12 @@ static int cx23885_dev_setup(struct cx23885_dev *dev)
        dev->i2c_bus[2].reg_wdata = I2C3_WDATA;
        dev->i2c_bus[2].i2c_period = (0x07 << 24); /* 1.95MHz */
 
-       if(cx23885_boards[dev->board].portb == CX23885_MPEG_DVB)
+       if ((cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) ||
+               (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER))
                cx23885_init_tsport(dev, &dev->ts1, 1);
 
-       if(cx23885_boards[dev->board].portc == CX23885_MPEG_DVB)
+       if ((cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) ||
+               (cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER))
                cx23885_init_tsport(dev, &dev->ts2, 2);
 
        if (get_resources(dev) < 0) {
@@ -734,9 +738,9 @@ static int cx23885_dev_setup(struct cx23885_dev *dev)
        dev->radio_addr = cx23885_boards[dev->board].radio_addr;
 
        dprintk(1, "%s() tuner_type = 0x%x tuner_addr = 0x%x\n",
-               __FUNCTION__, dev->tuner_type, dev->tuner_addr);
+               __func__, dev->tuner_type, dev->tuner_addr);
        dprintk(1, "%s() radio_type = 0x%x radio_addr = 0x%x\n",
-               __FUNCTION__, dev->radio_type, dev->radio_addr);
+               __func__, dev->radio_type, dev->radio_addr);
 
        /* init hardware */
        cx23885_reset(dev);
@@ -744,28 +748,43 @@ static int cx23885_dev_setup(struct cx23885_dev *dev)
        cx23885_i2c_register(&dev->i2c_bus[0]);
        cx23885_i2c_register(&dev->i2c_bus[1]);
        cx23885_i2c_register(&dev->i2c_bus[2]);
-       cx23885_call_i2c_clients (&dev->i2c_bus[0], TUNER_SET_STANDBY, NULL);
        cx23885_card_setup(dev);
+       cx23885_call_i2c_clients (&dev->i2c_bus[0], TUNER_SET_STANDBY, NULL);
        cx23885_ir_init(dev);
 
        if (cx23885_boards[dev->board].porta == CX23885_ANALOG_VIDEO) {
                if (cx23885_video_register(dev) < 0) {
                        printk(KERN_ERR "%s() Failed to register analog "
-                               "video adapters on VID_A\n", __FUNCTION__);
+                               "video adapters on VID_A\n", __func__);
                }
        }
 
        if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) {
                if (cx23885_dvb_register(&dev->ts1) < 0) {
                        printk(KERN_ERR "%s() Failed to register dvb adapters on VID_B\n",
-                              __FUNCTION__);
+                              __func__);
+               }
+       } else
+       if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER) {
+               if (cx23885_417_register(dev) < 0) {
+                       printk(KERN_ERR
+                               "%s() Failed to register 417 on VID_B\n",
+                              __func__);
                }
        }
 
        if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) {
                if (cx23885_dvb_register(&dev->ts2) < 0) {
-                       printk(KERN_ERR "%s() Failed to register dvb adapters on VID_C\n",
-                              __FUNCTION__);
+                       printk(KERN_ERR
+                               "%s() Failed to register dvb on VID_C\n",
+                              __func__);
+               }
+       } else
+       if (cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER) {
+               if (cx23885_417_register(dev) < 0) {
+                       printk(KERN_ERR
+                               "%s() Failed to register 417 on VID_C\n",
+                              __func__);
                }
        }
 
@@ -785,12 +804,18 @@ static void cx23885_dev_unregister(struct cx23885_dev *dev)
        if (cx23885_boards[dev->board].porta == CX23885_ANALOG_VIDEO)
                cx23885_video_unregister(dev);
 
-       if(cx23885_boards[dev->board].portb == CX23885_MPEG_DVB)
+       if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB)
                cx23885_dvb_unregister(&dev->ts1);
 
-       if(cx23885_boards[dev->board].portc == CX23885_MPEG_DVB)
+       if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER)
+               cx23885_417_unregister(dev);
+
+       if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB)
                cx23885_dvb_unregister(&dev->ts2);
 
+       if (cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER)
+               cx23885_417_unregister(dev);
+
        cx23885_i2c_unregister(&dev->i2c_bus[2]);
        cx23885_i2c_unregister(&dev->i2c_bus[1]);
        cx23885_i2c_unregister(&dev->i2c_bus[0]);
@@ -952,7 +977,7 @@ void cx23885_free_buffer(struct videobuf_queue *q, struct cx23885_buffer *buf)
        videobuf_waiton(&buf->vb, 0, 0);
        videobuf_dma_unmap(q, dma);
        videobuf_dma_free(dma);
-       btcx_riscmem_free((struct pci_dev *)q->dev, &buf->risc);
+       btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc);
        buf->vb.state = VIDEOBUF_NEEDS_INIT;
 }
 
@@ -960,50 +985,50 @@ static void cx23885_tsport_reg_dump(struct cx23885_tsport *port)
 {
        struct cx23885_dev *dev = port->dev;
 
-       dprintk(1, "%s() Register Dump\n", __FUNCTION__);
-       dprintk(1, "%s() DEV_CNTRL2               0x%08X\n", __FUNCTION__,
+       dprintk(1, "%s() Register Dump\n", __func__);
+       dprintk(1, "%s() DEV_CNTRL2               0x%08X\n", __func__,
                cx_read(DEV_CNTRL2));
-       dprintk(1, "%s() PCI_INT_MSK              0x%08X\n", __FUNCTION__,
+       dprintk(1, "%s() PCI_INT_MSK              0x%08X\n", __func__,
                cx_read(PCI_INT_MSK));
-       dprintk(1, "%s() AUD_INT_INT_MSK          0x%08X\n", __FUNCTION__,
+       dprintk(1, "%s() AUD_INT_INT_MSK          0x%08X\n", __func__,
                cx_read(AUDIO_INT_INT_MSK));
-       dprintk(1, "%s() AUD_INT_DMA_CTL          0x%08X\n", __FUNCTION__,
+       dprintk(1, "%s() AUD_INT_DMA_CTL          0x%08X\n", __func__,
                cx_read(AUD_INT_DMA_CTL));
-       dprintk(1, "%s() AUD_EXT_INT_MSK          0x%08X\n", __FUNCTION__,
+       dprintk(1, "%s() AUD_EXT_INT_MSK          0x%08X\n", __func__,
                cx_read(AUDIO_EXT_INT_MSK));
-       dprintk(1, "%s() AUD_EXT_DMA_CTL          0x%08X\n", __FUNCTION__,
+       dprintk(1, "%s() AUD_EXT_DMA_CTL          0x%08X\n", __func__,
                cx_read(AUD_EXT_DMA_CTL));
-       dprintk(1, "%s() PAD_CTRL                 0x%08X\n", __FUNCTION__,
+       dprintk(1, "%s() PAD_CTRL                 0x%08X\n", __func__,
                cx_read(PAD_CTRL));
-       dprintk(1, "%s() ALT_PIN_OUT_SEL          0x%08X\n", __FUNCTION__,
+       dprintk(1, "%s() ALT_PIN_OUT_SEL          0x%08X\n", __func__,
                cx_read(ALT_PIN_OUT_SEL));
-       dprintk(1, "%s() GPIO2                    0x%08X\n", __FUNCTION__,
+       dprintk(1, "%s() GPIO2                    0x%08X\n", __func__,
                cx_read(GPIO2));
-       dprintk(1, "%s() gpcnt(0x%08X)          0x%08X\n", __FUNCTION__,
+       dprintk(1, "%s() gpcnt(0x%08X)          0x%08X\n", __func__,
                port->reg_gpcnt, cx_read(port->reg_gpcnt));
-       dprintk(1, "%s() gpcnt_ctl(0x%08X)      0x%08x\n", __FUNCTION__,
+       dprintk(1, "%s() gpcnt_ctl(0x%08X)      0x%08x\n", __func__,
                port->reg_gpcnt_ctl, cx_read(port->reg_gpcnt_ctl));
-       dprintk(1, "%s() dma_ctl(0x%08X)        0x%08x\n", __FUNCTION__,
+       dprintk(1, "%s() dma_ctl(0x%08X)        0x%08x\n", __func__,
                port->reg_dma_ctl, cx_read(port->reg_dma_ctl));
-       dprintk(1, "%s() src_sel(0x%08X)        0x%08x\n", __FUNCTION__,
+       dprintk(1, "%s() src_sel(0x%08X)        0x%08x\n", __func__,
                port->reg_src_sel, cx_read(port->reg_src_sel));
-       dprintk(1, "%s() lngth(0x%08X)          0x%08x\n", __FUNCTION__,
+       dprintk(1, "%s() lngth(0x%08X)          0x%08x\n", __func__,
                port->reg_lngth, cx_read(port->reg_lngth));
-       dprintk(1, "%s() hw_sop_ctrl(0x%08X)    0x%08x\n", __FUNCTION__,
+       dprintk(1, "%s() hw_sop_ctrl(0x%08X)    0x%08x\n", __func__,
                port->reg_hw_sop_ctrl, cx_read(port->reg_hw_sop_ctrl));
-       dprintk(1, "%s() gen_ctrl(0x%08X)       0x%08x\n", __FUNCTION__,
+       dprintk(1, "%s() gen_ctrl(0x%08X)       0x%08x\n", __func__,
                port->reg_gen_ctrl, cx_read(port->reg_gen_ctrl));
-       dprintk(1, "%s() bd_pkt_status(0x%08X)  0x%08x\n", __FUNCTION__,
+       dprintk(1, "%s() bd_pkt_status(0x%08X)  0x%08x\n", __func__,
                port->reg_bd_pkt_status, cx_read(port->reg_bd_pkt_status));
-       dprintk(1, "%s() sop_status(0x%08X)     0x%08x\n", __FUNCTION__,
+       dprintk(1, "%s() sop_status(0x%08X)     0x%08x\n", __func__,
                port->reg_sop_status, cx_read(port->reg_sop_status));
-       dprintk(1, "%s() fifo_ovfl_stat(0x%08X) 0x%08x\n", __FUNCTION__,
+       dprintk(1, "%s() fifo_ovfl_stat(0x%08X) 0x%08x\n", __func__,
                port->reg_fifo_ovfl_stat, cx_read(port->reg_fifo_ovfl_stat));
-       dprintk(1, "%s() vld_misc(0x%08X)       0x%08x\n", __FUNCTION__,
+       dprintk(1, "%s() vld_misc(0x%08X)       0x%08x\n", __func__,
                port->reg_vld_misc, cx_read(port->reg_vld_misc));
-       dprintk(1, "%s() ts_clk_en(0x%08X)      0x%08x\n", __FUNCTION__,
+       dprintk(1, "%s() ts_clk_en(0x%08X)      0x%08x\n", __func__,
                port->reg_ts_clk_en, cx_read(port->reg_ts_clk_en));
-       dprintk(1, "%s() ts_int_msk(0x%08X)     0x%08x\n", __FUNCTION__,
+       dprintk(1, "%s() ts_int_msk(0x%08X)     0x%08x\n", __func__,
                port->reg_ts_int_msk, cx_read(port->reg_ts_int_msk));
 }
 
@@ -1012,8 +1037,9 @@ static int cx23885_start_dma(struct cx23885_tsport *port,
                             struct cx23885_buffer   *buf)
 {
        struct cx23885_dev *dev = port->dev;
+       u32 reg;
 
-       dprintk(1, "%s() w: %d, h: %d, f: %d\n", __FUNCTION__,
+       dprintk(1, "%s() w: %d, h: %d, f: %d\n", __func__,
                buf->vb.width, buf->vb.height, buf->vb.field);
 
        /* setup fifo + format */
@@ -1031,21 +1057,24 @@ static int cx23885_start_dma(struct cx23885_tsport *port,
        if ( (!(cx23885_boards[dev->board].portb & CX23885_MPEG_DVB)) &&
                (!(cx23885_boards[dev->board].portc & CX23885_MPEG_DVB)) ) {
                printk( "%s() Failed. Unsupported value in .portb/c (0x%08x)/(0x%08x)\n",
-                       __FUNCTION__,
+                       __func__,
                        cx23885_boards[dev->board].portb,
                        cx23885_boards[dev->board].portc );
                return -EINVAL;
        }
 
+       if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER)
+               cx23885_av_clk(dev, 0);
+
        udelay(100);
 
        /* If the port supports SRC SELECT, configure it */
        if(port->reg_src_sel)
                cx_write(port->reg_src_sel, port->src_sel_val);
 
-       cx_write(port->reg_hw_sop_ctrl, 0x47 << 16 | 188 << 4);
+       cx_write(port->reg_hw_sop_ctrl, port->hw_sop_ctrl_val);
        cx_write(port->reg_ts_clk_en, port->ts_clk_en_val);
-       cx_write(port->reg_vld_misc, 0x00);
+       cx_write(port->reg_vld_misc, port->vld_misc_val);
        cx_write(port->reg_gen_ctrl, port->gen_ctrl_val);
        udelay(100);
 
@@ -1054,11 +1083,26 @@ static int cx23885_start_dma(struct cx23885_tsport *port,
        cx_write(port->reg_gpcnt_ctl, 3);
        q->count = 1;
 
+       if (cx23885_boards[dev->board].portb & CX23885_MPEG_ENCODER) {
+
+               reg = cx_read(PAD_CTRL);
+               reg = reg & ~0x1;    /* Clear TS1_OE */
+
+               /* FIXME, bit 2 writing here is questionable */
+               /* set TS1_SOP_OE and TS1_OE_HI */
+               reg = reg | 0xa;
+               cx_write(PAD_CTRL, reg);
+
+               /* FIXME and these two registers should be documented. */
+               cx_write(CLK_DELAY, cx_read(CLK_DELAY) | 0x80000011);
+               cx_write(ALT_PIN_OUT_SEL, 0x10100045);
+       }
+
        switch(dev->bridge) {
        case CX23885_BRIDGE_885:
        case CX23885_BRIDGE_887:
                /* enable irqs */
-               dprintk(1, "%s() enabling TS int's and DMA\n", __FUNCTION__ );
+               dprintk(1, "%s() enabling TS int's and DMA\n", __func__ );
                cx_set(port->reg_ts_int_msk,  port->ts_int_msk_val);
                cx_set(port->reg_dma_ctl, port->dma_ctl_val);
                cx_set(PCI_INT_MSK, dev->pci_irqmask | port->pci_irqmask);
@@ -1069,6 +1113,9 @@ static int cx23885_start_dma(struct cx23885_tsport *port,
 
        cx_set(DEV_CNTRL2, (1<<5)); /* Enable RISC controller */
 
+       if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER)
+               cx23885_av_clk(dev, 1);
+
        if (debug > 4)
                cx23885_tsport_reg_dump(port);
 
@@ -1078,12 +1125,32 @@ static int cx23885_start_dma(struct cx23885_tsport *port,
 static int cx23885_stop_dma(struct cx23885_tsport *port)
 {
        struct cx23885_dev *dev = port->dev;
-       dprintk(1, "%s()\n", __FUNCTION__);
+       u32 reg;
+
+       dprintk(1, "%s()\n", __func__);
 
        /* Stop interrupts and DMA */
        cx_clear(port->reg_ts_int_msk, port->ts_int_msk_val);
        cx_clear(port->reg_dma_ctl, port->dma_ctl_val);
 
+       if (cx23885_boards[dev->board].portb & CX23885_MPEG_ENCODER) {
+
+               reg = cx_read(PAD_CTRL);
+
+               /* Set TS1_OE */
+               reg = reg | 0x1;
+
+               /* clear TS1_SOP_OE and TS1_OE_HI */
+               reg = reg & ~0xa;
+               cx_write(PAD_CTRL, reg);
+               cx_write(port->reg_src_sel, 0);
+               cx_write(port->reg_gen_ctrl, 8);
+
+       }
+
+       if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER)
+               cx23885_av_clk(dev, 0);
+
        return 0;
 }
 
@@ -1093,13 +1160,13 @@ int cx23885_restart_queue(struct cx23885_tsport *port,
        struct cx23885_dev *dev = port->dev;
        struct cx23885_buffer *buf;
 
-       dprintk(5, "%s()\n", __FUNCTION__);
+       dprintk(5, "%s()\n", __func__);
        if (list_empty(&q->active))
        {
                struct cx23885_buffer *prev;
                prev = NULL;
 
-               dprintk(5, "%s() queue is empty\n", __FUNCTION__);
+               dprintk(5, "%s() queue is empty\n", __func__);
 
                for (;;) {
                        if (list_empty(&q->queued))
@@ -1154,7 +1221,7 @@ int cx23885_buf_prepare(struct videobuf_queue *q, struct cx23885_tsport *port,
        int size = port->ts_packet_size * port->ts_packet_count;
        int rc;
 
-       dprintk(1, "%s: %p\n", __FUNCTION__, buf);
+       dprintk(1, "%s: %p\n", __func__, buf);
        if (0 != buf->vb.baddr  &&  buf->vb.bsize < size)
                return -EINVAL;
 
@@ -1197,7 +1264,7 @@ void cx23885_buf_queue(struct cx23885_tsport *port, struct cx23885_buffer *buf)
                buf->count    = cx88q->count++;
                mod_timer(&cx88q->timeout, jiffies + BUFFER_TIMEOUT);
                dprintk(1, "[%p/%d] %s - first active\n",
-                       buf, buf->vb.i, __FUNCTION__);
+                       buf, buf->vb.i, __func__);
        } else {
                dprintk( 1, "queue is not empty - append to active\n" );
                prev = list_entry(cx88q->active.prev, struct cx23885_buffer,
@@ -1208,7 +1275,7 @@ void cx23885_buf_queue(struct cx23885_tsport *port, struct cx23885_buffer *buf)
                prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
                prev->risc.jmp[2] = cpu_to_le32(0); /* 64 bit bits 63-32 */
                dprintk( 1, "[%p/%d] %s - append to active\n",
-                        buf, buf->vb.i, __FUNCTION__);
+                        buf, buf->vb.i, __func__);
        }
 }
 
@@ -1239,13 +1306,23 @@ static void do_cancel_buffers(struct cx23885_tsport *port, char *reason,
        spin_unlock_irqrestore(&port->slock, flags);
 }
 
+void cx23885_cancel_buffers(struct cx23885_tsport *port)
+{
+       struct cx23885_dev *dev = port->dev;
+       struct cx23885_dmaqueue *q = &port->mpegq;
+
+       dprintk(1, "%s()\n", __FUNCTION__);
+       del_timer_sync(&q->timeout);
+       cx23885_stop_dma(port);
+       do_cancel_buffers(port, "cancel", 0);
+}
 
 static void cx23885_timeout(unsigned long data)
 {
        struct cx23885_tsport *port = (struct cx23885_tsport *)data;
        struct cx23885_dev *dev = port->dev;
 
-       dprintk(1, "%s()\n",__FUNCTION__);
+       dprintk(1, "%s()\n",__func__);
 
        if (debug > 5)
                cx23885_sram_channel_dump(dev, &dev->sram_channels[ port->sram_chno ]);
@@ -1254,16 +1331,77 @@ static void cx23885_timeout(unsigned long data)
        do_cancel_buffers(port, "timeout", 1);
 }
 
+int cx23885_irq_417(struct cx23885_dev *dev, u32 status)
+{
+       /* FIXME: port1 assumption here. */
+       struct cx23885_tsport *port = &dev->ts1;
+       int count = 0;
+       int handled = 0;
+
+       if (status == 0)
+               return handled;
+
+       count = cx_read(port->reg_gpcnt);
+       dprintk(7, "status: 0x%08x  mask: 0x%08x count: 0x%x\n",
+               status, cx_read(port->reg_ts_int_msk), count);
+
+       if ((status & VID_B_MSK_BAD_PKT)         ||
+               (status & VID_B_MSK_OPC_ERR)     ||
+               (status & VID_B_MSK_VBI_OPC_ERR) ||
+               (status & VID_B_MSK_SYNC)        ||
+               (status & VID_B_MSK_VBI_SYNC)    ||
+               (status & VID_B_MSK_OF)          ||
+               (status & VID_B_MSK_VBI_OF)) {
+               printk(KERN_ERR "%s: V4L mpeg risc op code error, status "
+                       "= 0x%x\n", dev->name, status);
+               if (status & VID_B_MSK_BAD_PKT)
+                       dprintk(1, "        VID_B_MSK_BAD_PKT\n");
+               if (status & VID_B_MSK_OPC_ERR)
+                       dprintk(1, "        VID_B_MSK_OPC_ERR\n");
+               if (status & VID_B_MSK_VBI_OPC_ERR)
+                       dprintk(1, "        VID_B_MSK_VBI_OPC_ERR\n");
+               if (status & VID_B_MSK_SYNC)
+                       dprintk(1, "        VID_B_MSK_SYNC\n");
+               if (status & VID_B_MSK_VBI_SYNC)
+                       dprintk(1, "        VID_B_MSK_VBI_SYNC\n");
+               if (status & VID_B_MSK_OF)
+                       dprintk(1, "        VID_B_MSK_OF\n");
+               if (status & VID_B_MSK_VBI_OF)
+                       dprintk(1, "        VID_B_MSK_VBI_OF\n");
+
+               cx_clear(port->reg_dma_ctl, port->dma_ctl_val);
+               cx23885_sram_channel_dump(dev,
+                       &dev->sram_channels[port->sram_chno]);
+               cx23885_417_check_encoder(dev);
+       } else if (status & VID_B_MSK_RISCI1) {
+               dprintk(7, "        VID_B_MSK_RISCI1\n");
+               spin_lock(&port->slock);
+               cx23885_wakeup(port, &port->mpegq, count);
+               spin_unlock(&port->slock);
+       } else if (status & VID_B_MSK_RISCI2) {
+               dprintk(7, "        VID_B_MSK_RISCI2\n");
+               spin_lock(&port->slock);
+               cx23885_restart_queue(port, &port->mpegq);
+               spin_unlock(&port->slock);
+       }
+       if (status) {
+               cx_write(port->reg_ts_int_stat, status);
+               handled = 1;
+       }
+
+       return handled;
+}
+
 static int cx23885_irq_ts(struct cx23885_tsport *port, u32 status)
 {
        struct cx23885_dev *dev = port->dev;
        int handled = 0;
        u32 count;
 
-       if ( (status & VID_BC_MSK_OPC_ERR) ||
-            (status & VID_BC_MSK_BAD_PKT) ||
-            (status & VID_BC_MSK_SYNC) ||
-            (status & VID_BC_MSK_OF))
+       if ((status & VID_BC_MSK_OPC_ERR) ||
+               (status & VID_BC_MSK_BAD_PKT) ||
+               (status & VID_BC_MSK_SYNC) ||
+               (status & VID_BC_MSK_OF))
        {
                if (status & VID_BC_MSK_OPC_ERR)
                        dprintk(7, " (VID_BC_MSK_OPC_ERR 0x%08x)\n", VID_BC_MSK_OPC_ERR);
@@ -1277,7 +1415,8 @@ static int cx23885_irq_ts(struct cx23885_tsport *port, u32 status)
                printk(KERN_ERR "%s: mpeg risc op code error\n", dev->name);
 
                cx_clear(port->reg_dma_ctl, port->dma_ctl_val);
-               cx23885_sram_channel_dump(dev, &dev->sram_channels[ port->sram_chno ]);
+               cx23885_sram_channel_dump(dev,
+                       &dev->sram_channels[port->sram_chno]);
 
        } else if (status & VID_BC_MSK_RISCI1) {
 
@@ -1378,11 +1517,17 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id)
        if (ts1_status) {
                if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB)
                        handled += cx23885_irq_ts(ts1, ts1_status);
+               else
+               if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER)
+                       handled += cx23885_irq_417(dev, ts1_status);
        }
 
        if (ts2_status) {
                if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB)
                        handled += cx23885_irq_ts(ts2, ts2_status);
+               else
+               if (cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER)
+                       handled += cx23885_irq_417(dev, ts2_status);
        }
 
        if (vida_status)
@@ -1422,7 +1567,8 @@ static int __devinit cx23885_initdev(struct pci_dev *pci_dev,
        printk(KERN_INFO "%s/0: found at %s, rev: %d, irq: %d, "
               "latency: %d, mmio: 0x%llx\n", dev->name,
               pci_name(pci_dev), dev->pci_rev, pci_dev->irq,
-              dev->pci_lat, (unsigned long long)pci_resource_start(pci_dev,0));
+              dev->pci_lat,
+               (unsigned long long)pci_resource_start(pci_dev, 0));
 
        pci_set_master(pci_dev);
        if (!pci_dma_supported(pci_dev, 0xffffffff)) {
index ed465c007cea64d201b001b20100827c10825608..870d6e197d65152f8c54b1ef0efcf848edbfd6f6 100644 (file)
 #include "tda18271.h"
 #include "lgdt330x.h"
 #include "xc5000.h"
+#include "tda10048.h"
 #include "dvb-pll.h"
 #include "tuner-xc2028.h"
-#include "tuner-xc2028-types.h"
+#include "tuner-simple.h"
+#include "dib7000p.h"
+#include "dibx000_common.h"
 
 static unsigned int debug;
 
@@ -53,6 +56,8 @@ static unsigned int alt_tuner;
 module_param(alt_tuner, int, 0644);
 MODULE_PARM_DESC(alt_tuner, "Enable alternate tuner configuration");
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 /* ------------------------------------------------------------------ */
 
 static int dvb_buf_setup(struct videobuf_queue *q,
@@ -104,6 +109,13 @@ static struct s5h1409_config hauppauge_generic_config = {
        .mpeg_timing   = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
 };
 
+static struct tda10048_config hauppauge_hvr1200_config = {
+       .demod_address    = 0x10 >> 1,
+       .output_mode      = TDA10048_SERIAL_OUTPUT,
+       .fwbulkwritelen   = TDA10048_BULKWRITE_200,
+       .inversion        = TDA10048_INVERSION_ON
+};
+
 static struct s5h1409_config hauppauge_ezqam_config = {
        .demod_address = 0x32 >> 1,
        .output_mode   = S5H1409_SERIAL_OUTPUT,
@@ -164,8 +176,10 @@ static struct tda829x_config tda829x_no_probe = {
 };
 
 static struct tda18271_std_map hauppauge_tda18271_std_map = {
-       .atsc_6   = { .if_freq = 5380, .std_bits = 0x1b },
-       .qam_6    = { .if_freq = 4000, .std_bits = 0x18 },
+       .atsc_6   = { .if_freq = 5380, .agc_mode = 3, .std = 3,
+                     .if_lvl = 6, .rfagc_top = 0x37 },
+       .qam_6    = { .if_freq = 4000, .agc_mode = 3, .std = 0,
+                     .if_lvl = 6, .rfagc_top = 0x37 },
 };
 
 static struct tda18271_config hauppauge_tda18271_config = {
@@ -173,6 +187,96 @@ static struct tda18271_config hauppauge_tda18271_config = {
        .gate    = TDA18271_GATE_ANALOG,
 };
 
+static struct tda18271_config hauppauge_hvr1200_tuner_config = {
+       .gate    = TDA18271_GATE_ANALOG,
+};
+
+struct dibx000_agc_config xc3028_agc_config = {
+       BAND_VHF | BAND_UHF,    /* band_caps */
+
+       /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=0,
+        * P_agc_inv_pwm1=0, P_agc_inv_pwm2=0,
+        * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0,
+        * P_agc_nb_est=2, P_agc_write=0
+        */
+       (0 << 15) | (0 << 14) | (0 << 11) | (0 << 10) | (0 << 9) | (0 << 8) |
+               (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), /* setup */
+
+       712,    /* inv_gain */
+       21,     /* time_stabiliz */
+
+       0,      /* alpha_level */
+       118,    /* thlock */
+
+       0,      /* wbd_inv */
+       2867,   /* wbd_ref */
+       0,      /* wbd_sel */
+       2,      /* wbd_alpha */
+
+       0,      /* agc1_max */
+       0,      /* agc1_min */
+       39718,  /* agc2_max */
+       9930,   /* agc2_min */
+       0,      /* agc1_pt1 */
+       0,      /* agc1_pt2 */
+       0,      /* agc1_pt3 */
+       0,      /* agc1_slope1 */
+       0,      /* agc1_slope2 */
+       0,      /* agc2_pt1 */
+       128,    /* agc2_pt2 */
+       29,     /* agc2_slope1 */
+       29,     /* agc2_slope2 */
+
+       17,     /* alpha_mant */
+       27,     /* alpha_exp */
+       23,     /* beta_mant */
+       51,     /* beta_exp */
+
+       1,      /* perform_agc_softsplit */
+};
+
+/* PLL Configuration for COFDM BW_MHz = 8.000000
+ * With external clock = 30.000000 */
+struct dibx000_bandwidth_config xc3028_bw_config = {
+       60000,  /* internal */
+       30000,  /* sampling */
+       1,      /* pll_cfg: prediv */
+       8,      /* pll_cfg: ratio */
+       3,      /* pll_cfg: range */
+       1,      /* pll_cfg: reset */
+       0,      /* pll_cfg: bypass */
+       0,      /* misc: refdiv */
+       0,      /* misc: bypclk_div */
+       1,      /* misc: IO_CLK_en_core */
+       1,      /* misc: ADClkSrc */
+       0,      /* misc: modulo */
+       (3 << 14) | (1 << 12) | (524 << 0), /* sad_cfg: refsel, sel, freq_15k */
+       (1 << 25) | 5816102, /* ifreq = 5.200000 MHz */
+       20452225, /* timf */
+       30000000  /* xtal_hz */
+};
+
+static struct dib7000p_config hauppauge_hvr1400_dib7000_config = {
+       .output_mpeg2_in_188_bytes = 1,
+       .hostbus_diversity = 1,
+       .tuner_is_baseband = 0,
+       .update_lna  = NULL,
+
+       .agc_config_count = 1,
+       .agc = &xc3028_agc_config,
+       .bw  = &xc3028_bw_config,
+
+       .gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS,
+       .gpio_val = DIB7000P_GPIO_DEFAULT_VALUES,
+       .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
+
+       .pwm_freq_div = 0,
+       .agc_control  = NULL,
+       .spur_protect = 0,
+
+       .output_mode = OUTMODE_MPEG2_SERIAL,
+};
+
 static int cx23885_hvr1500_xc3028_callback(void *ptr, int command, int arg)
 {
        struct cx23885_tsport *port = ptr;
@@ -182,7 +286,7 @@ static int cx23885_hvr1500_xc3028_callback(void *ptr, int command, int arg)
        case XC2028_TUNER_RESET:
                /* Send the tuner in then out of reset */
                /* GPIO-2 xc3028 tuner */
-               dprintk(1, "%s: XC2028_TUNER_RESET %d\n", __FUNCTION__, arg);
+               dprintk(1, "%s: XC2028_TUNER_RESET %d\n", __func__, arg);
 
                cx_set(GP0_IO, 0x00040000);
                cx_clear(GP0_IO, 0x00000004);
@@ -192,10 +296,10 @@ static int cx23885_hvr1500_xc3028_callback(void *ptr, int command, int arg)
                msleep(5);
                break;
        case XC2028_RESET_CLK:
-               dprintk(1, "%s: XC2028_RESET_CLK %d\n", __FUNCTION__, arg);
+               dprintk(1, "%s: XC2028_RESET_CLK %d\n", __func__, arg);
                break;
        default:
-               dprintk(1, "%s: unknown command %d, arg %d\n", __FUNCTION__,
+               dprintk(1, "%s: unknown command %d, arg %d\n", __func__,
                        command, arg);
                return -EINVAL;
        }
@@ -271,8 +375,9 @@ static int dvb_register(struct cx23885_tsport *port)
                                                &fusionhdtv_5_express,
                                                &i2c_bus->i2c_adap);
                if (port->dvb.frontend != NULL) {
-                       dvb_attach(dvb_pll_attach, port->dvb.frontend, 0x61,
-                                  &i2c_bus->i2c_adap, DVB_PLL_LG_TDVS_H06XF);
+                       dvb_attach(simple_tuner_attach, port->dvb.frontend,
+                                  &i2c_bus->i2c_adap, 0x61,
+                                  TUNER_LG_TDVS_H06XF);
                }
                break;
        case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
@@ -297,13 +402,52 @@ static int dvb_register(struct cx23885_tsport *port)
                        struct xc2028_config cfg = {
                                .i2c_adap  = &i2c_bus->i2c_adap,
                                .i2c_addr  = 0x61,
-                               .video_dev = port,
                                .callback  = cx23885_hvr1500_xc3028_callback,
                        };
                        static struct xc2028_ctrl ctl = {
                                .fname       = "xc3028-v27.fw",
                                .max_len     = 64,
-                               .scode_table = OREN538,
+                               .scode_table = XC3028_FE_OREN538,
+                       };
+
+                       fe = dvb_attach(xc2028_attach,
+                                       port->dvb.frontend, &cfg);
+                       if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
+                               fe->ops.tuner_ops.set_config(fe, &ctl);
+               }
+               break;
+       case CX23885_BOARD_HAUPPAUGE_HVR1200:
+       case CX23885_BOARD_HAUPPAUGE_HVR1700:
+               i2c_bus = &dev->i2c_bus[0];
+               port->dvb.frontend = dvb_attach(tda10048_attach,
+                       &hauppauge_hvr1200_config,
+                       &i2c_bus->i2c_adap);
+               if (port->dvb.frontend != NULL) {
+                       dvb_attach(tda829x_attach, port->dvb.frontend,
+                               &dev->i2c_bus[1].i2c_adap, 0x42,
+                               &tda829x_no_probe);
+                       dvb_attach(tda18271_attach, port->dvb.frontend,
+                               0x60, &dev->i2c_bus[1].i2c_adap,
+                               &hauppauge_hvr1200_tuner_config);
+               }
+               break;
+       case CX23885_BOARD_HAUPPAUGE_HVR1400:
+               i2c_bus = &dev->i2c_bus[0];
+               port->dvb.frontend = dvb_attach(dib7000p_attach,
+                       &i2c_bus->i2c_adap,
+                       0x12, &hauppauge_hvr1400_dib7000_config);
+               if (port->dvb.frontend != NULL) {
+                       struct dvb_frontend *fe;
+                       struct xc2028_config cfg = {
+                               .i2c_adap  = &dev->i2c_bus[1].i2c_adap,
+                               .i2c_addr  = 0x64,
+                               .callback  = cx23885_hvr1500_xc3028_callback,
+                       };
+                       static struct xc2028_ctrl ctl = {
+                               .fname   = "xc3028L-v36.fw",
+                               .max_len = 64,
+                               .demod   = 5000,
+                               .d2633   = 1
                        };
 
                        fe = dvb_attach(xc2028_attach,
@@ -330,7 +474,7 @@ static int dvb_register(struct cx23885_tsport *port)
 
        /* register everything */
        return videobuf_dvb_register(&port->dvb, THIS_MODULE, port,
-                                    &dev->pci->dev);
+                                    &dev->pci->dev, adapter_nr);
 }
 
 int cx23885_dvb_register(struct cx23885_tsport *port)
@@ -338,7 +482,7 @@ int cx23885_dvb_register(struct cx23885_tsport *port)
        struct cx23885_dev *dev = port->dev;
        int err;
 
-       dprintk(1, "%s\n", __FUNCTION__);
+       dprintk(1, "%s\n", __func__);
        dprintk(1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
                dev->board,
                dev->name,
@@ -349,12 +493,12 @@ int cx23885_dvb_register(struct cx23885_tsport *port)
 
        /* dvb stuff */
        printk("%s: cx23885 based dvb card\n", dev->name);
-       videobuf_queue_pci_init(&port->dvb.dvbq, &dvb_qops, dev->pci, &port->slock,
+       videobuf_queue_sg_init(&port->dvb.dvbq, &dvb_qops, &dev->pci->dev, &port->slock,
                            V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_TOP,
                            sizeof(struct cx23885_buffer), port);
        err = dvb_register(port);
        if (err != 0)
-               printk("%s() dvb_register failed err = %d\n", __FUNCTION__, err);
+               printk("%s() dvb_register failed err = %d\n", __func__, err);
 
        return err;
 }
index 92fe0bd37c84293e9b27e3933d142eaf4c7196ec..c6bb0a05bc1c147fd61527ab3a47bdf790577924 100644 (file)
@@ -33,7 +33,7 @@ static unsigned int i2c_debug;
 module_param(i2c_debug, int, 0644);
 MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
 
-static unsigned int i2c_scan = 0;
+static unsigned int i2c_scan;
 module_param(i2c_scan, int, 0444);
 MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
 
@@ -87,10 +87,10 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
        int retval, cnt;
 
        if (joined_rlen)
-               dprintk(1, "%s(msg->wlen=%d, nextmsg->rlen=%d)\n", __FUNCTION__,
+               dprintk(1, "%s(msg->wlen=%d, nextmsg->rlen=%d)\n", __func__,
                        msg->len, joined_rlen);
        else
-               dprintk(1, "%s(msg->len=%d)\n", __FUNCTION__, msg->len);
+               dprintk(1, "%s(msg->len=%d)\n", __func__, msg->len);
 
        /* Deal with i2c probe functions with zero payload */
        if (msg->len == 0) {
@@ -101,7 +101,7 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
                if (!i2c_slave_did_ack(i2c_adap))
                        return -EIO;
 
-               dprintk(1, "%s() returns 0\n", __FUNCTION__);
+               dprintk(1, "%s() returns 0\n", __func__);
                return 0;
        }
 
@@ -176,7 +176,7 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap,
 
 
        if (i2c_debug && !joined)
-               dprintk(1, "%s(msg->len=%d)\n", __FUNCTION__, msg->len);
+               dprintk(1, "%s(msg->len=%d)\n", __func__, msg->len);
 
        /* Deal with i2c probe functions with zero payload */
        if (msg->len == 0) {
@@ -188,7 +188,7 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap,
                        return -EIO;
 
 
-               dprintk(1, "%s() returns 0\n", __FUNCTION__);
+               dprintk(1, "%s() returns 0\n", __func__);
                return 0;
        }
 
@@ -238,11 +238,11 @@ static int i2c_xfer(struct i2c_adapter *i2c_adap,
        struct cx23885_dev *dev = bus->dev;
        int i, retval = 0;
 
-       dprintk(1, "%s(num = %d)\n", __FUNCTION__, num);
+       dprintk(1, "%s(num = %d)\n", __func__, num);
 
        for (i = 0 ; i < num; i++) {
                dprintk(1, "%s(num = %d) addr = 0x%02x  len = 0x%x\n",
-                       __FUNCTION__, num, msgs[i].addr, msgs[i].len);
+                       __func__, num, msgs[i].addr, msgs[i].len);
                if (msgs[i].flags & I2C_M_RD) {
                        /* read */
                        retval = i2c_readbytes(i2c_adap, &msgs[i], 0);
@@ -353,6 +353,8 @@ static struct i2c_client cx23885_i2c_client_template = {
 };
 
 static char *i2c_devs[128] = {
+       [0x10 >> 1]   = "tda10048",
+       [0x12 >> 1]   = "dib7000pc",
        [ 0x1c >> 1 ] = "lgdt3303",
        [ 0x86 >> 1 ] = "tda9887",
        [ 0x32 >> 1 ] = "cx24227",
@@ -360,7 +362,8 @@ static char *i2c_devs[128] = {
        [ 0x84 >> 1 ] = "tda8295",
        [ 0xa0 >> 1 ] = "eeprom",
        [ 0xc0 >> 1 ] = "tuner/mt2131/tda8275",
-       [ 0xc2 >> 1 ] = "tuner/mt2131/tda8275/xc5000",
+       [0xc2 >> 1] = "tuner/mt2131/tda8275/xc5000/xc3028",
+       [0xc8 >> 1]   = "tuner/xc3028L",
 };
 
 static void do_i2c_scan(char *name, struct i2c_client *c)
@@ -383,7 +386,7 @@ int cx23885_i2c_register(struct cx23885_i2c *bus)
 {
        struct cx23885_dev *dev = bus->dev;
 
-       dprintk(1, "%s(bus = %d)\n", __FUNCTION__, bus->nr);
+       dprintk(1, "%s(bus = %d)\n", __func__, bus->nr);
 
        memcpy(&bus->i2c_adap, &cx23885_i2c_adap_template,
               sizeof(bus->i2c_adap));
@@ -420,6 +423,29 @@ int cx23885_i2c_unregister(struct cx23885_i2c *bus)
        return 0;
 }
 
+void cx23885_av_clk(struct cx23885_dev *dev, int enable)
+{
+       /* write 0 to bus 2 addr 0x144 via i2x_xfer() */
+       char buffer[3];
+       struct i2c_msg msg;
+       dprintk(1, "%s(enabled = %d)\n", __func__, enable);
+
+       /* Register 0x144 */
+       buffer[0] = 0x01;
+       buffer[1] = 0x44;
+       if (enable == 1)
+               buffer[2] = 0x05;
+       else
+               buffer[2] = 0x00;
+
+       msg.addr = 0x44;
+       msg.flags = I2C_M_TEN;
+       msg.len = 3;
+       msg.buf = buffer;
+
+       i2c_xfer(&dev->i2c_bus[2].i2c_adap, &msg, 1);
+}
+
 /* ----------------------------------------------------------------------- */
 
 /*
index d3c4d2c5cbe05c69c41cc5c685f3bcdb1c3244c2..84652210a28c6fee3d24fbd626de2c4a56d2db97 100644 (file)
@@ -141,7 +141,7 @@ static struct cx23885_fmt *format_by_fourcc(unsigned int fourcc)
                if (formats[i].fourcc == fourcc)
                        return formats+i;
 
-       printk(KERN_ERR "%s(0x%08x) NOT FOUND\n", __FUNCTION__, fourcc);
+       printk(KERN_ERR "%s(0x%08x) NOT FOUND\n", __func__, fourcc);
        return NULL;
 }
 
@@ -292,13 +292,13 @@ void cx23885_video_wakeup(struct cx23885_dev *dev,
        }
        if (bc != 1)
                printk(KERN_ERR "%s: %d buffers handled (should be 1)\n",
-                       __FUNCTION__, bc);
+                       __func__, bc);
 }
 
 int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm)
 {
        dprintk(1, "%s(norm = 0x%08x) name: [%s]\n",
-               __FUNCTION__,
+               __func__,
                (unsigned int)norm,
                v4l2_norm_to_name(norm));
 
@@ -319,7 +319,7 @@ struct video_device *cx23885_vdev_init(struct cx23885_dev *dev,
                                    char *type)
 {
        struct video_device *vfd;
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
 
        vfd = video_device_alloc();
        if (NULL == vfd)
@@ -358,7 +358,7 @@ EXPORT_SYMBOL(cx23885_ctrl_query);
 static int res_get(struct cx23885_dev *dev, struct cx23885_fh *fh,
        unsigned int bit)
 {
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
        if (fh->resources & bit)
                /* have it already allocated */
                return 1;
@@ -392,7 +392,7 @@ static void res_free(struct cx23885_dev *dev, struct cx23885_fh *fh,
        unsigned int bits)
 {
        BUG_ON((fh->resources & bits) != bits);
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
 
        mutex_lock(&dev->lock);
        fh->resources  &= ~bits;
@@ -407,7 +407,7 @@ int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input)
        memset(&route, 0, sizeof(route));
 
        dprintk(1, "%s() video_mux: %d [vmux=%d, gpio=0x%x,0x%x,0x%x,0x%x]\n",
-               __FUNCTION__,
+               __func__,
                input, INPUT(input)->vmux,
                INPUT(input)->gpio0, INPUT(input)->gpio1,
                INPUT(input)->gpio2, INPUT(input)->gpio3);
@@ -427,7 +427,7 @@ EXPORT_SYMBOL(cx23885_video_mux);
 int cx23885_set_scale(struct cx23885_dev *dev, unsigned int width,
        unsigned int height, enum v4l2_field field)
 {
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
        return 0;
 }
 
@@ -435,7 +435,7 @@ static int cx23885_start_video_dma(struct cx23885_dev *dev,
                           struct cx23885_dmaqueue *q,
                           struct cx23885_buffer *buf)
 {
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
 
        /* setup fifo + format */
        cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH01],
@@ -463,7 +463,7 @@ static int cx23885_restart_video_queue(struct cx23885_dev *dev,
 {
        struct cx23885_buffer *buf, *prev;
        struct list_head *item;
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
 
        if (!list_empty(&q->active)) {
                buf = list_entry(q->active.next, struct cx23885_buffer,
@@ -579,13 +579,13 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
                        if (dev->tvnorm & V4L2_STD_NTSC) {
                                /* cx25840 transmits NTSC bottom field first */
                                dprintk(1, "%s() Creating NTSC risc\n",
-                                       __FUNCTION__);
+                                       __func__);
                                line0_offset = buf->bpl;
                                line1_offset = 0;
                        } else {
                                /* All other formats are top field first */
                                dprintk(1, "%s() Creating PAL/SECAM risc\n",
-                                       __FUNCTION__);
+                                       __func__);
                                line0_offset = 0;
                                line1_offset = buf->bpl;
                        }
@@ -765,8 +765,8 @@ static int video_open(struct inode *inode, struct file *file)
        fh->height   = 240;
        fh->fmt      = format_by_fourcc(V4L2_PIX_FMT_BGR24);
 
-       videobuf_queue_pci_init(&fh->vidq, &cx23885_video_qops,
-                           dev->pci, &dev->slock,
+       videobuf_queue_sg_init(&fh->vidq, &cx23885_video_qops,
+                           &dev->pci->dev, &dev->slock,
                            V4L2_BUF_TYPE_VIDEO_CAPTURE,
                            V4L2_FIELD_INTERLACED,
                            sizeof(struct cx23885_buffer),
@@ -885,7 +885,7 @@ static int video_mmap(struct file *file, struct vm_area_struct *vma)
 
 int cx23885_get_control(struct cx23885_dev *dev, struct v4l2_control *ctl)
 {
-       dprintk(1, "%s() calling cx25840(VIDIOC_G_CTRL)\n", __FUNCTION__);
+       dprintk(1, "%s() calling cx25840(VIDIOC_G_CTRL)\n", __func__);
        cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_G_CTRL, ctl);
        return 0;
 }
@@ -894,7 +894,7 @@ EXPORT_SYMBOL(cx23885_get_control);
 int cx23885_set_control(struct cx23885_dev *dev, struct v4l2_control *ctl)
 {
        dprintk(1, "%s() calling cx25840(VIDIOC_S_CTRL)"
-               " (disabled - no action)\n", __FUNCTION__);
+               " (disabled - no action)\n", __func__);
        return 0;
 }
 EXPORT_SYMBOL(cx23885_set_control);
@@ -990,7 +990,7 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv,
        struct cx23885_dev *dev  = ((struct cx23885_fh *)priv)->dev;
        int err;
 
-       dprintk(2, "%s()\n", __FUNCTION__);
+       dprintk(2, "%s()\n", __func__);
        err = vidioc_try_fmt_cap(file, priv, f);
 
        if (0 != err)
@@ -999,7 +999,7 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv,
        fh->width      = f->fmt.pix.width;
        fh->height     = f->fmt.pix.height;
        fh->vidq.field = f->fmt.pix.field;
-       dprintk(2, "%s() width=%d height=%d field=%d\n", __FUNCTION__,
+       dprintk(2, "%s() width=%d height=%d field=%d\n", __func__,
                fh->width, fh->height, fh->vidq.field);
        cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_FMT, f);
        return 0;
@@ -1101,7 +1101,7 @@ static int vidioc_streamon(struct file *file, void *priv,
 {
        struct cx23885_fh *fh = priv;
        struct cx23885_dev *dev = fh->dev;
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
 
        if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE))
                return -EINVAL;
@@ -1118,7 +1118,7 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
        struct cx23885_fh *fh = priv;
        struct cx23885_dev *dev = fh->dev;
        int err, res;
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
 
        if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
                return -EINVAL;
@@ -1136,7 +1136,7 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
 static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *tvnorms)
 {
        struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
 
        mutex_lock(&dev->lock);
        cx23885_set_tvnorm(dev, *tvnorms);
@@ -1159,7 +1159,7 @@ int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i)
                [CX23885_VMUX_DEBUG]      = "for debug only",
        };
        unsigned int n;
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
 
        n = i->index;
        if (n >= 4)
@@ -1184,7 +1184,7 @@ static int vidioc_enum_input(struct file *file, void *priv,
                                struct v4l2_input *i)
 {
        struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
        return cx23885_enum_input(dev, i);
 }
 
@@ -1193,7 +1193,7 @@ static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
        struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
 
        *i = dev->input;
-       dprintk(1, "%s() returns %d\n", __FUNCTION__, *i);
+       dprintk(1, "%s() returns %d\n", __func__, *i);
        return 0;
 }
 
@@ -1201,10 +1201,10 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
 {
        struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
 
-       dprintk(1, "%s(%d)\n", __FUNCTION__, i);
+       dprintk(1, "%s(%d)\n", __func__, i);
 
        if (i >= 4) {
-               dprintk(1, "%s() -EINVAL\n", __FUNCTION__);
+               dprintk(1, "%s() -EINVAL\n", __func__);
                return -EINVAL;
        }
 
@@ -1389,7 +1389,7 @@ int cx23885_video_irq(struct cx23885_dev *dev, u32 status)
                return handled;
        cx_write(VID_A_INT_STAT, status);
 
-       dprintk(2, "%s() status = 0x%08x\n", __FUNCTION__, status);
+       dprintk(2, "%s() status = 0x%08x\n", __func__, status);
        /* risc op code error */
        if (status & (1 << 16)) {
                printk(KERN_WARNING "%s/0: video risc op code error\n",
@@ -1487,7 +1487,7 @@ static const struct file_operations radio_fops = {
 
 void cx23885_video_unregister(struct cx23885_dev *dev)
 {
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
        cx_clear(PCI_INT_MSK, 1);
 
        if (dev->video_dev) {
@@ -1505,7 +1505,7 @@ int cx23885_video_register(struct cx23885_dev *dev)
 {
        int err;
 
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
        spin_lock_init(&dev->slock);
 
        /* Initialize VBI template */
index 7cb2179f26227456ed25a507ee8ac20a1da3047b..32af87f25e7bbb769a711d1bd6cf125e1bfd3a39 100644 (file)
@@ -32,6 +32,7 @@
 
 #include "btcx-risc.h"
 #include "cx23885-reg.h"
+#include "media/cx2341x.h"
 
 #include <linux/version.h>
 #include <linux/mutex.h>
@@ -59,6 +60,9 @@
 #define CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP   4
 #define CX23885_BOARD_HAUPPAUGE_HVR1500Q       5
 #define CX23885_BOARD_HAUPPAUGE_HVR1500        6
+#define CX23885_BOARD_HAUPPAUGE_HVR1200        7
+#define CX23885_BOARD_HAUPPAUGE_HVR1700        8
+#define CX23885_BOARD_HAUPPAUGE_HVR1400        9
 
 /* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM B/G/H/LC */
 #define CX23885_NORMS (\
@@ -154,6 +158,7 @@ typedef enum {
        CX23885_MPEG_UNDEFINED = 0,
        CX23885_MPEG_DVB,
        CX23885_ANALOG_VIDEO,
+       CX23885_MPEG_ENCODER,
 } port_t;
 
 struct cx23885_board {
@@ -252,6 +257,8 @@ struct cx23885_tsport {
        u32                        gen_ctrl_val;
        u32                        ts_clk_en_val;
        u32                        src_sel_val;
+       u32                        vld_misc_val;
+       u32                        hw_sop_ctrl_val;
 };
 
 struct cx23885_dev {
@@ -312,6 +319,14 @@ struct cx23885_dev {
        struct cx23885_dmaqueue    vidq;
        struct cx23885_dmaqueue    vbiq;
        spinlock_t                 slock;
+
+       /* MPEG Encoder ONLY settings */
+       u32                        cx23417_mailbox;
+       struct cx2341x_mpeg_params mpeg_params;
+       struct video_device        *v4l_device;
+       atomic_t                   v4l_reader_count;
+       struct cx23885_tvnorm      encodernorm;
+
 };
 
 extern struct list_head cx23885_devlist;
@@ -431,6 +446,18 @@ extern int cx23885_i2c_register(struct cx23885_i2c *bus);
 extern int cx23885_i2c_unregister(struct cx23885_i2c *bus);
 extern void cx23885_call_i2c_clients(struct cx23885_i2c *bus, unsigned int cmd,
                                     void *arg);
+extern void cx23885_av_clk(struct cx23885_dev *dev, int enable);
+
+/* ----------------------------------------------------------- */
+/* cx23885-417.c                                               */
+extern int cx23885_417_register(struct cx23885_dev *dev);
+extern void cx23885_417_unregister(struct cx23885_dev *dev);
+extern int cx23885_irq_417(struct cx23885_dev *dev, u32 status);
+extern void cx23885_417_check_encoder(struct cx23885_dev *dev);
+extern void cx23885_mc417_init(struct cx23885_dev *dev);
+extern int mc417_memory_read(struct cx23885_dev *dev, u32 address, u32 *value);
+extern int mc417_memory_write(struct cx23885_dev *dev, u32 address, u32 value);
+
 
 /* ----------------------------------------------------------- */
 /* tv norms                                                    */
index 756a1eeb274e0da969e49a0ad6424e7ea3339035..7fde678b2c4a5fbb0785af63a77cfbee86cb22d2 100644 (file)
@@ -352,7 +352,7 @@ static void cx23885_initialize(struct i2c_client *client)
 static void input_change(struct i2c_client *client)
 {
        struct cx25840_state *state = i2c_get_clientdata(client);
-       v4l2_std_id std = cx25840_get_v4lstd(client);
+       v4l2_std_id std = state->std;
 
        /* Follow step 8c and 8d of section 3.16 in the cx25840 datasheet */
        if (std & V4L2_STD_SECAM) {
@@ -523,32 +523,34 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp
 
 /* ----------------------------------------------------------------------- */
 
-static int set_v4lstd(struct i2c_client *client, v4l2_std_id std)
+static int set_v4lstd(struct i2c_client *client)
 {
-       u8 fmt=0;       /* zero is autodetect */
+       struct cx25840_state *state = i2c_get_clientdata(client);
+       u8 fmt = 0;     /* zero is autodetect */
+       u8 pal_m = 0;
 
        /* First tests should be against specific std */
-       if (std == V4L2_STD_NTSC_M_JP) {
-               fmt=0x2;
-       } else if (std == V4L2_STD_NTSC_443) {
-               fmt=0x3;
-       } else if (std == V4L2_STD_PAL_M) {
-               fmt=0x5;
-       } else if (std == V4L2_STD_PAL_N) {
-               fmt=0x6;
-       } else if (std == V4L2_STD_PAL_Nc) {
-               fmt=0x7;
-       } else if (std == V4L2_STD_PAL_60) {
-               fmt=0x8;
+       if (state->std == V4L2_STD_NTSC_M_JP) {
+               fmt = 0x2;
+       } else if (state->std == V4L2_STD_NTSC_443) {
+               fmt = 0x3;
+       } else if (state->std == V4L2_STD_PAL_M) {
+               pal_m = 1;
+               fmt = 0x5;
+       } else if (state->std == V4L2_STD_PAL_N) {
+               fmt = 0x6;
+       } else if (state->std == V4L2_STD_PAL_Nc) {
+               fmt = 0x7;
+       } else if (state->std == V4L2_STD_PAL_60) {
+               fmt = 0x8;
        } else {
                /* Then, test against generic ones */
-               if (std & V4L2_STD_NTSC) {
-                       fmt=0x1;
-               } else if (std & V4L2_STD_PAL) {
-                       fmt=0x4;
-               } else if (std & V4L2_STD_SECAM) {
-                       fmt=0xc;
-               }
+               if (state->std & V4L2_STD_NTSC)
+                       fmt = 0x1;
+               else if (state->std & V4L2_STD_PAL)
+                       fmt = 0x4;
+               else if (state->std & V4L2_STD_SECAM)
+                       fmt = 0xc;
        }
 
        v4l_dbg(1, cx25840_debug, client, "changing video std to fmt %i\n",fmt);
@@ -563,42 +565,13 @@ static int set_v4lstd(struct i2c_client *client, v4l2_std_id std)
                cx25840_and_or(client, 0x47b, ~6, 0);
        }
        cx25840_and_or(client, 0x400, ~0xf, fmt);
+       cx25840_and_or(client, 0x403, ~0x3, pal_m);
        cx25840_vbi_setup(client);
+       if (!state->is_cx25836)
+               input_change(client);
        return 0;
 }
 
-v4l2_std_id cx25840_get_v4lstd(struct i2c_client * client)
-{
-       struct cx25840_state *state = i2c_get_clientdata(client);
-       /* check VID_FMT_SEL first */
-       u8 fmt = cx25840_read(client, 0x400) & 0xf;
-
-       if (!fmt) {
-               /* check AFD_FMT_STAT if set to autodetect */
-               fmt = cx25840_read(client, 0x40d) & 0xf;
-       }
-
-       switch (fmt) {
-       case 0x1:
-       {
-               /* if the audio std is A2-M, then this is the South Korean
-                  NTSC standard */
-               if (!state->is_cx25836 && cx25840_read(client, 0x805) == 2)
-                       return V4L2_STD_NTSC_M_KR;
-               return V4L2_STD_NTSC_M;
-       }
-       case 0x2: return V4L2_STD_NTSC_M_JP;
-       case 0x3: return V4L2_STD_NTSC_443;
-       case 0x4: return V4L2_STD_PAL;
-       case 0x5: return V4L2_STD_PAL_M;
-       case 0x6: return V4L2_STD_PAL_N;
-       case 0x7: return V4L2_STD_PAL_Nc;
-       case 0x8: return V4L2_STD_PAL_60;
-       case 0xc: return V4L2_STD_SECAM;
-       default: return V4L2_STD_UNKNOWN;
-       }
-}
-
 /* ----------------------------------------------------------------------- */
 
 static int set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
@@ -718,9 +691,10 @@ static int get_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt)
 
 static int set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt)
 {
+       struct cx25840_state *state = i2c_get_clientdata(client);
        struct v4l2_pix_format *pix;
        int HSC, VSC, Vsrc, Hsrc, filter, Vlines;
-       int is_50Hz = !(cx25840_get_v4lstd(client) & V4L2_STD_525_60);
+       int is_50Hz = !(state->std & V4L2_STD_525_60);
 
        switch (fmt->type) {
        case V4L2_BUF_TYPE_VIDEO_CAPTURE:
@@ -1096,12 +1070,15 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
        }
 
        case VIDIOC_G_STD:
-               *(v4l2_std_id *)arg = cx25840_get_v4lstd(client);
+               *(v4l2_std_id *)arg = state->std;
                break;
 
        case VIDIOC_S_STD:
+               if (state->radio == 0 && state->std == *(v4l2_std_id *)arg)
+                       return 0;
                state->radio = 0;
-               return set_v4lstd(client, *(v4l2_std_id *)arg);
+               state->std = *(v4l2_std_id *)arg;
+               return set_v4lstd(client);
 
        case AUDC_SET_RADIO:
                state->radio = 1;
@@ -1291,6 +1268,12 @@ static int cx25840_probe(struct i2c_client *client)
        state->id = id;
        state->rev = device_id;
 
+       if (state->is_cx23885) {
+               /* Drive GPIO2 direction and values */
+               cx25840_write(client, 0x160, 0x1d);
+               cx25840_write(client, 0x164, 0x00);
+       }
+
        return 0;
 }
 
index 95093edc9186d669395a0e6b531ba6b186de1fcb..8bf797f48b09d0779d7f7a6423dc0a29954bbf7b 100644 (file)
@@ -38,6 +38,7 @@ struct cx25840_state {
        struct i2c_client *c;
        int pvr150_workaround;
        int radio;
+       v4l2_std_id std;
        enum cx25840_video_input vid_input;
        enum cx25840_audio_input aud_input;
        u32 audclk_freq;
@@ -60,7 +61,6 @@ int cx25840_write4(struct i2c_client *client, u16 addr, u32 value);
 u8 cx25840_read(struct i2c_client *client, u16 addr);
 u32 cx25840_read4(struct i2c_client *client, u16 addr);
 int cx25840_and_or(struct i2c_client *client, u16 addr, unsigned mask, u8 value);
-v4l2_std_id cx25840_get_v4lstd(struct i2c_client *client);
 
 /* ----------------------------------------------------------------------- */
 /* cx25850-firmware.c                                                      */
index 1ddf724a2c74ca6332dd52e1f702dfc4bf18aba0..620d295947abd5299ac86337eceb3407e1d3527e 100644 (file)
@@ -79,11 +79,9 @@ static int check_fw_load(struct i2c_client *client, int size)
        return 0;
 }
 
-static int fw_write(struct i2c_client *client, u8 * data, int size)
+static int fw_write(struct i2c_client *client, u8 *data, int size)
 {
-       int sent;
-
-       if ((sent = i2c_master_send(client, data, size)) < size) {
+       if (i2c_master_send(client, data, size) < size) {
                v4l_err(client, "firmware load i2c failure\n");
                return -ENOSYS;
        }
@@ -96,7 +94,7 @@ int cx25840_loadfw(struct i2c_client *client)
        struct cx25840_state *state = i2c_get_clientdata(client);
        const struct firmware *fw = NULL;
        u8 buffer[4], *ptr;
-       int size, send, retval;
+       int size, retval;
 
        if (state->is_cx23885)
                firmware = FWFILE_CX23885;
@@ -124,8 +122,7 @@ int cx25840_loadfw(struct i2c_client *client)
        while (size > 0) {
                ptr[0] = 0x08;
                ptr[1] = 0x02;
-               send = size > (FWSEND - 2) ? FWSEND : size + 2;
-               retval = fw_write(client, ptr, send);
+               retval = fw_write(client, ptr, min(FWSEND, size + 2));
 
                if (retval < 0) {
                        release_firmware(fw);
index 6828f59b9d83555dee36e0e7a11656f8a6cfbe92..c754b9d13369f580e1b6a02fd8da07dcdc414e42 100644 (file)
@@ -85,7 +85,7 @@ static int decode_vps(u8 * dst, u8 * p)
 void cx25840_vbi_setup(struct i2c_client *client)
 {
        struct cx25840_state *state = i2c_get_clientdata(client);
-       v4l2_std_id std = cx25840_get_v4lstd(client);
+       v4l2_std_id std = state->std;
        int hblank,hactive,burst,vblank,vactive,sc,vblank656,src_decimation;
        int luma_lpf,uv_lpf, comb;
        u32 pll_int,pll_frac,pll_post;
@@ -242,7 +242,7 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg)
                        0, 0, V4L2_SLICED_VPS, 0, 0,    /* 9 */
                        0, 0, 0, 0
                };
-               int is_pal = !(cx25840_get_v4lstd(client) & V4L2_STD_525_60);
+               int is_pal = !(state->std & V4L2_STD_525_60);
                int i;
 
                fmt = arg;
@@ -279,7 +279,7 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg)
 
        case VIDIOC_S_FMT:
        {
-               int is_pal = !(cx25840_get_v4lstd(client) & V4L2_STD_525_60);
+               int is_pal = !(state->std & V4L2_STD_525_60);
                int vbi_offset = is_pal ? 1 : 0;
                int i, x;
                u8 lcr[24];
index 49d3813a9b48e69ac83ac84d8368d94a212fe945..bcf6d9ba063da738dc77f811308467f3a955cff4 100644 (file)
@@ -57,6 +57,7 @@ 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 TUNER_SIMPLE if !DVB_FE_CUSTOMISE
        ---help---
          This adds support for DVB/ATSC cards based on the
          Conexant 2388x chip.
index 316b106c3511b2a15981e692c6e4c7cd9884c6cd..e976fc6bef7ccc7c6ec747fc5594f7a720aff505 100644 (file)
@@ -283,7 +283,7 @@ static int dsp_buffer_free(snd_cx88_card_t *chip)
        BUG_ON(!chip->dma_size);
 
        dprintk(2,"Freeing buffer\n");
-       videobuf_pci_dma_unmap(chip->pci, chip->dma_risc);
+       videobuf_sg_dma_unmap(&chip->pci->dev, chip->dma_risc);
        videobuf_dma_free(chip->dma_risc);
        btcx_riscmem_free(chip->pci,&chip->buf->risc);
        kfree(chip->buf);
@@ -385,7 +385,7 @@ static int snd_cx88_hw_params(struct snd_pcm_substream * substream,
        BUG_ON(!chip->dma_size);
        BUG_ON(chip->num_periods & (chip->num_periods-1));
 
-       buf = videobuf_pci_alloc(sizeof(*buf));
+       buf = videobuf_sg_alloc(sizeof(*buf));
        if (NULL == buf)
                return -ENOMEM;
 
@@ -396,14 +396,14 @@ static int snd_cx88_hw_params(struct snd_pcm_substream * substream,
        buf->vb.height = chip->num_periods;
        buf->vb.size   = chip->dma_size;
 
-       dma=videobuf_to_dma(&buf->vb);
+       dma = videobuf_to_dma(&buf->vb);
        videobuf_dma_init(dma);
        ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE,
                        (PAGE_ALIGN(buf->vb.size) >> PAGE_SHIFT));
        if (ret < 0)
                goto error;
 
-       ret = videobuf_pci_dma_map(chip->pci,dma);
+       ret = videobuf_sg_dma_map(&chip->pci->dev, dma);
        if (ret < 0)
                goto error;
 
@@ -494,7 +494,7 @@ static snd_pcm_uframes_t snd_cx88_pointer(struct snd_pcm_substream *substream)
 
        count = atomic_read(&chip->count);
 
-//     dprintk(2, "%s - count %d (+%u), period %d, frame %lu\n", __FUNCTION__,
+//     dprintk(2, "%s - count %d (+%u), period %d, frame %lu\n", __func__,
 //             count, new, count & (runtime->periods-1),
 //             runtime->period_size * (count & (runtime->periods-1)));
        return runtime->period_size * (count & (runtime->periods-1));
@@ -690,10 +690,8 @@ MODULE_DEVICE_TABLE(pci, cx88_audio_pci_tbl);
 static int snd_cx88_free(snd_cx88_card_t *chip)
 {
 
-       if (chip->irq >= 0){
-               synchronize_irq(chip->irq);
+       if (chip->irq >= 0)
                free_irq(chip->irq, chip);
-       }
 
        cx88_core_put(chip->core,chip->pci);
 
index a99e9d5950aa0da61483288f4da687f56a427844..61c4f72644b8d2e56ee391915d51409d1922c425 100644 (file)
@@ -45,7 +45,7 @@ static unsigned int mpegbufs = 32;
 module_param(mpegbufs,int,0644);
 MODULE_PARM_DESC(mpegbufs,"number of mpeg buffers, range 2-32");
 
-static unsigned int debug = 0;
+static unsigned int debug;
 module_param(debug,int,0644);
 MODULE_PARM_DESC(debug,"enable debug messages [blackbird]");
 
@@ -314,7 +314,7 @@ static int blackbird_mbox_func(void *priv, u32 command, int in, int out, u32 dat
        u32 value, flag, retval;
        int i;
 
-       dprintk(1,"%s: 0x%X\n", __FUNCTION__, command);
+       dprintk(1,"%s: 0x%X\n", __func__, command);
 
        /* this may not be 100% safe if we can't read any memory location
           without side effects */
@@ -693,7 +693,7 @@ static int blackbird_queryctrl(struct cx8802_dev *dev, struct v4l2_queryctrl *qc
                return -EINVAL;
 
        /* Standard V4L2 controls */
-       if (cx8800_ctrl_query(qctrl) == 0)
+       if (cx8800_ctrl_query(dev->core, qctrl) == 0)
                return 0;
 
        /* MPEG V4L2 controls */
@@ -933,7 +933,7 @@ static int vidioc_queryctrl (struct file *file, void *priv,
        qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
        if (unlikely(qctrl->id == 0))
                return -EINVAL;
-       return cx8800_ctrl_query(qctrl);
+       return cx8800_ctrl_query(dev->core, qctrl);
 }
 
 static int vidioc_enum_input (struct file *file, void *priv,
@@ -1055,7 +1055,7 @@ static int mpeg_open(struct inode *inode, struct file *file)
 
        dev = cx8802_get_device(inode);
 
-       dprintk( 1, "%s\n", __FUNCTION__);
+       dprintk( 1, "%s\n", __func__);
 
        if (dev == NULL)
                return -ENODEV;
@@ -1065,7 +1065,7 @@ static int mpeg_open(struct inode *inode, struct file *file)
        if (drv) {
                err = drv->request_acquire(drv);
                if(err != 0) {
-                       dprintk(1,"%s: Unable to acquire hardware, %d\n", __FUNCTION__, err);
+                       dprintk(1,"%s: Unable to acquire hardware, %d\n", __func__, err);
                        return err;
                }
        }
@@ -1087,8 +1087,8 @@ static int mpeg_open(struct inode *inode, struct file *file)
        file->private_data = fh;
        fh->dev      = dev;
 
-       videobuf_queue_pci_init(&fh->mpegq, &blackbird_qops,
-                           dev->pci, &dev->slock,
+       videobuf_queue_sg_init(&fh->mpegq, &blackbird_qops,
+                           &dev->pci->dev, &dev->slock,
                            V4L2_BUF_TYPE_VIDEO_CAPTURE,
                            V4L2_FIELD_INTERLACED,
                            sizeof(struct cx88_buffer),
@@ -1284,7 +1284,7 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv)
        struct cx8802_dev *dev = core->dvbdev;
        int err;
 
-       dprintk( 1, "%s\n", __FUNCTION__);
+       dprintk( 1, "%s\n", __func__);
        dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
                core->boardnr,
                core->name,
index 8c9a8adf52de2c2b5af95ed32d0805968857b20f..620159d05506d1c55675ce9ada91c999c14adce0 100644 (file)
@@ -44,6 +44,16 @@ static unsigned int latency = UNSET;
 module_param(latency,int,0444);
 MODULE_PARM_DESC(latency,"pci latency timer");
 
+#define info_printk(core, fmt, arg...) \
+       printk(KERN_INFO "%s: " fmt, core->name , ## arg)
+
+#define warn_printk(core, fmt, arg...) \
+       printk(KERN_WARNING "%s: " fmt, core->name , ## arg)
+
+#define err_printk(core, fmt, arg...) \
+       printk(KERN_ERR "%s: " fmt, core->name , ## arg)
+
+
 /* ------------------------------------------------------------------ */
 /* board config info                                                  */
 
@@ -1354,6 +1364,10 @@ static const struct cx88_board cx88_boards[] = {
                }},
                /* fixme: Add radio support */
                .mpeg           = CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD,
+               .radio = {
+                       .type   = CX88_RADIO,
+                       .gpio0  = 0xe780,
+               },
        },
        [CX88_BOARD_ADSTECH_PTV_390] = {
                .name           = "ADS Tech Instant Video PCI",
@@ -1401,6 +1415,245 @@ static const struct cx88_board cx88_boards[] = {
                }},
                .mpeg           = CX88_MPEG_DVB,
        },
+       [CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO] = {
+               .name           = "DViCO FusionHDTV 5 PCI nano",
+               /* xc3008 tuner, digital only for now */
+               .tuner_type     = TUNER_ABSENT,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x000027df, /* Unconfirmed */
+               }, {
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x000027df, /* Unconfirmed */
+                       .audioroute = 1,
+               }, {
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x000027df, /* Unconfirmed */
+                       .audioroute = 1,
+               } },
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_PINNACLE_HYBRID_PCTV] = {
+               .name           = "Pinnacle Hybrid PCTV",
+               .tuner_type     = TUNER_XC2028,
+               .tuner_addr     = 0x61,
+               .input          = { {
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+               }, {
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+               }, {
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+               } },
+               .radio = {
+                       .type   = CX88_RADIO,
+                       .gpio0  = 0x004ff,
+                       .gpio1  = 0x010ff,
+                       .gpio2  = 0x0ff,
+               },
+       },
+       [CX88_BOARD_WINFAST_TV2000_XP_GLOBAL] = {
+               .name           = "Winfast TV2000 XP Global",
+               .tuner_type     = TUNER_XC2028,
+               .tuner_addr     = 0x61,
+               .input          = { {
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x0400, /* pin 2:mute = 0 (off?) */
+                       .gpio1  = 0x0000,
+                       .gpio2  = 0x0800, /* pin 19:audio = 0 (tv) */
+
+               }, {
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x0400, /* probably?  or 0x0404 to turn mute on */
+                       .gpio1  = 0x0000,
+                       .gpio2  = 0x0808, /* pin 19:audio = 1 (line) */
+
+               }, {
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+               } },
+               .radio = {
+                       .type   = CX88_RADIO,
+                       .gpio0  = 0x004ff,
+                       .gpio1  = 0x010ff,
+                       .gpio2  = 0x0ff,
+               },
+       },
+       [CX88_BOARD_POWERCOLOR_REAL_ANGEL] = {
+               .name           = "PowerColor Real Angel 330",
+               .tuner_type     = TUNER_XC2028,
+               .tuner_addr     = 0x61,
+               .input          = { {
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0 = 0x00ff,
+                       .gpio1 = 0xf35d,
+                       .gpio3 = 0x0000,
+               }, {
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0 = 0x00ff,
+                       .gpio1 = 0xf37d,
+                       .gpio3 = 0x0000,
+               }, {
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x000ff,
+                       .gpio1  = 0x0f37d,
+                       .gpio3  = 0x00000,
+               } },
+               .radio = {
+                       .type   = CX88_RADIO,
+                       .gpio0  = 0x000ff,
+                       .gpio1  = 0x0f35d,
+                       .gpio3  = 0x00000,
+               },
+       },
+       [CX88_BOARD_GENIATECH_X8000_MT] = {
+               /* Also PowerColor Real Angel 330 and Geniatech X800 OEM */
+               .name           = "Geniatech X8000-MT DVBT",
+               .tuner_type     = TUNER_XC2028,
+               .tuner_addr     = 0x61,
+               .input          = { {
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x00000000,
+                       .gpio1  = 0x00e3e341,
+                       .gpio2  = 0x00000000,
+                       .gpio3  = 0x00000000,
+               }, {
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x00000000,
+                       .gpio1  = 0x00e3e361,
+                       .gpio2  = 0x00000000,
+                       .gpio3  = 0x00000000,
+               }, {
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x00000000,
+                       .gpio1  = 0x00e3e361,
+                       .gpio2  = 0x00000000,
+                       .gpio3  = 0x00000000,
+               } },
+               .radio = {
+                       .type   = CX88_RADIO,
+                       .gpio0  = 0x00000000,
+                       .gpio1  = 0x00e3e341,
+                       .gpio2  = 0x00000000,
+                       .gpio3  = 0x00000000,
+               },
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO] = {
+               .name           = "DViCO FusionHDTV DVB-T PRO",
+               .tuner_type     = TUNER_ABSENT, /* XXX: Has XC3028 */
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = { {
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x000067df,
+               }, {
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x000067df,
+               } },
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD] = {
+               .name           = "DViCO FusionHDTV 7 Gold",
+               .tuner_type     = TUNER_XC5000,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x10df,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x16d9,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x16d9,
+               }},
+       },
+       [CX88_BOARD_PROLINK_PV_8000GT] = {
+               .name           = "Prolink Pixelview MPEG 8000GT",
+               .tuner_type     = TUNER_XC2028,
+               .tuner_addr     = 0x61,
+               .input          = { {
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0 = 0x0ff,
+                       .gpio2 = 0x0cfb,
+               }, {
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio2 = 0x0cfb,
+               }, {
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio2 = 0x0cfb,
+               } },
+               .radio = {
+                       .type   = CX88_RADIO,
+                       .gpio2 = 0x0cfb,
+               },
+       },
+       /* Both radio, analog and ATSC work with this board.
+          However, for analog to work, s5h1409 gate should be open,
+          otherwise, tuner-xc3028 won't be detected.
+          A proper fix require using the newer i2c methods to add
+          tuner-xc3028 without doing an i2c probe.
+        */
+       [CX88_BOARD_KWORLD_ATSC_120] = {
+               .name           = "Kworld PlusTV HD PCI 120 (ATSC 120)",
+               .tuner_type     = TUNER_XC2028,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = { {
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x000000ff,
+                       .gpio1  = 0x0000f35d,
+                       .gpio2  = 0x00000000,
+               }, {
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x000000ff,
+                       .gpio1  = 0x0000f37e,
+                       .gpio2  = 0x00000000,
+               }, {
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x000000ff,
+                       .gpio1  = 0x0000f37e,
+                       .gpio2  = 0x00000000,
+               } },
+               .radio = {
+                       .type   = CX88_RADIO,
+                       .gpio0  = 0x000000ff,
+                       .gpio1  = 0x0000f35d,
+                       .gpio2  = 0x00000000,
+               },
+               .mpeg           = CX88_MPEG_DVB,
+       },
 };
 
 /* ------------------------------------------------------------------ */
@@ -1605,7 +1858,11 @@ static const struct cx88_subid cx88_subids[] = {
                .subdevice = 0xdb11,
                .card      = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS,
                /* Re-branded DViCO: UltraView DVB-T Plus */
-       },{
+       }, {
+               .subvendor = 0x18ac,
+               .subdevice = 0xdb30,
+               .card      = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO,
+       }, {
                .subvendor = 0x17de,
                .subdevice = 0x0840,
                .card      = CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT,
@@ -1714,6 +1971,38 @@ static const struct cx88_subid cx88_subids[] = {
                .subvendor = 0x11bd,
                .subdevice = 0x0051,
                .card      = CX88_BOARD_PINNACLE_PCTV_HD_800i,
+       }, {
+               .subvendor = 0x18ac,
+               .subdevice = 0xd530,
+               .card      = CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO,
+       }, {
+               .subvendor = 0x12ab,
+               .subdevice = 0x1788,
+               .card      = CX88_BOARD_PINNACLE_HYBRID_PCTV,
+       }, {
+               .subvendor = 0x14f1,
+               .subdevice = 0xea3d,
+               .card      = CX88_BOARD_POWERCOLOR_REAL_ANGEL,
+       }, {
+               .subvendor = 0x107d,
+               .subdevice = 0x6f18,
+               .card      = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL,
+       }, {
+               .subvendor = 0x14f1,
+               .subdevice = 0x8852,
+               .card      = CX88_BOARD_GENIATECH_X8000_MT,
+       }, {
+               .subvendor = 0x18ac,
+               .subdevice = 0xd610,
+               .card      = CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD,
+       }, {
+               .subvendor = 0x1554,
+               .subdevice = 0x4935,
+               .card      = CX88_BOARD_PROLINK_PV_8000GT,
+       }, {
+               .subvendor = 0x17de,
+               .subdevice = 0x08c1,
+               .card      = CX88_BOARD_KWORLD_ATSC_120,
        },
 };
 
@@ -1731,17 +2020,16 @@ static void leadtek_eeprom(struct cx88_core *core, u8 *eeprom_data)
        if (eeprom_data[4] != 0x7d ||
            eeprom_data[5] != 0x10 ||
            eeprom_data[7] != 0x66) {
-               printk(KERN_WARNING "%s: Leadtek eeprom invalid.\n",
-                      core->name);
+               warn_printk(core, "Leadtek eeprom invalid.\n");
                return;
        }
 
        core->board.tuner_type = (eeprom_data[6] == 0x13) ?
                TUNER_PHILIPS_FM1236_MK3 : TUNER_PHILIPS_FM1216ME_MK3;
 
-       printk(KERN_INFO "%s: Leadtek Winfast 2000XP Expert config: "
-              "tuner=%d, eeprom[0]=0x%02x\n",
-              core->name, core->board.tuner_type, eeprom_data[0]);
+       info_printk(core, "Leadtek Winfast 2000XP Expert config: "
+                   "tuner=%d, eeprom[0]=0x%02x\n",
+                   core->board.tuner_type, eeprom_data[0]);
 }
 
 static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data)
@@ -1785,13 +2073,12 @@ static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data)
                /* known */
                break;
        default:
-               printk("%s: warning: unknown hauppauge model #%d\n",
-                      core->name, tv.model);
+               warn_printk(core, "warning: unknown hauppauge model #%d\n",
+                           tv.model);
                break;
        }
 
-       printk(KERN_INFO "%s: hauppauge eeprom: model=%d\n",
-                       core->name, tv.model);
+       info_printk(core, "hauppauge eeprom: model=%d\n", tv.model);
 }
 
 /* ----------------------------------------------------------------------- */
@@ -1837,8 +2124,7 @@ static void gdi_eeprom(struct cx88_core *core, u8 *eeprom_data)
        char *name = (eeprom_data[0x0d] < ARRAY_SIZE(gdi_tuner))
                ? gdi_tuner[eeprom_data[0x0d]].name : NULL;
 
-       printk(KERN_INFO "%s: GDI: tuner=%s\n", core->name,
-              name ? name : "unknown");
+       info_printk(core, "GDI: tuner=%s\n", name ? name : "unknown");
        if (NULL == name)
                return;
        core->board.tuner_type = gdi_tuner[eeprom_data[0x0d]].id;
@@ -1846,6 +2132,75 @@ static void gdi_eeprom(struct cx88_core *core, u8 *eeprom_data)
                CX88_RADIO : 0;
 }
 
+/* ------------------------------------------------------------------- */
+/* some Divco specific stuff                                           */
+static int cx88_dvico_xc2028_callback(struct cx88_core *core,
+                                     int command, int arg)
+{
+       switch (command) {
+       case XC2028_TUNER_RESET:
+               cx_write(MO_GP0_IO, 0x101000);
+               mdelay(5);
+               cx_set(MO_GP0_IO, 0x101010);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+
+/* ----------------------------------------------------------------------- */
+/* some Geniatech specific stuff                                           */
+
+static int cx88_xc3028_geniatech_tuner_callback(struct cx88_core *core,
+                                               int command, int mode)
+{
+       switch (command) {
+       case XC2028_TUNER_RESET:
+               switch (INPUT(core->input).type) {
+               case CX88_RADIO:
+                       break;
+               case CX88_VMUX_DVB:
+                       cx_write(MO_GP1_IO, 0x030302);
+                       mdelay(50);
+                       break;
+               default:
+                       cx_write(MO_GP1_IO, 0x030301);
+                       mdelay(50);
+               }
+               cx_write(MO_GP1_IO, 0x101010);
+               mdelay(50);
+               cx_write(MO_GP1_IO, 0x101000);
+               mdelay(50);
+               cx_write(MO_GP1_IO, 0x101010);
+               mdelay(50);
+               return 0;
+       }
+       return -EINVAL;
+}
+
+/* ------------------------------------------------------------------- */
+/* some Divco specific stuff                                           */
+static int cx88_pv_8000gt_callback(struct cx88_core *core,
+                                  int command, int arg)
+{
+       switch (command) {
+       case XC2028_TUNER_RESET:
+               cx_write(MO_GP2_IO, 0xcf7);
+               mdelay(50);
+               cx_write(MO_GP2_IO, 0xef5);
+               mdelay(50);
+               cx_write(MO_GP2_IO, 0xcf7);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 /* ----------------------------------------------------------------------- */
 /* some DViCO specific stuff                                               */
 
@@ -1874,32 +2229,85 @@ static void dvico_fusionhdtv_hybrid_init(struct cx88_core *core)
                msg.len = (i != 12 ? 5 : 2);
                err = i2c_transfer(&core->i2c_adap, &msg, 1);
                if (err != 1) {
-                       printk("dvico_fusionhdtv_hybrid_init buf %d failed (err = %d)!\n", i, err);
+                       warn_printk(core, "dvico_fusionhdtv_hybrid_init buf %d "
+                                         "failed (err = %d)!\n", i, err);
                        return;
                }
        }
 }
 
+static int cx88_xc2028_tuner_callback(struct cx88_core *core,
+                                     int command, int arg)
+{
+       /* Board-specific callbacks */
+       switch (core->boardnr) {
+       case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
+       case CX88_BOARD_POWERCOLOR_REAL_ANGEL:
+       case CX88_BOARD_GENIATECH_X8000_MT:
+       case CX88_BOARD_KWORLD_ATSC_120:
+               return cx88_xc3028_geniatech_tuner_callback(core,
+                                                       command, arg);
+       case CX88_BOARD_PROLINK_PV_8000GT:
+               return cx88_pv_8000gt_callback(core, command, arg);
+       case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
+               return cx88_dvico_xc2028_callback(core, command, arg);
+       }
+
+       switch (command) {
+       case XC2028_TUNER_RESET:
+               switch (INPUT(core->input).type) {
+               case CX88_RADIO:
+                       info_printk(core, "setting GPIO to radio!\n");
+                       cx_write(MO_GP0_IO, 0x4ff);
+                       mdelay(250);
+                       cx_write(MO_GP2_IO, 0xff);
+                       mdelay(250);
+                       break;
+               case CX88_VMUX_DVB:     /* Digital TV*/
+               default:                /* Analog TV */
+                       info_printk(core, "setting GPIO to TV!\n");
+                       break;
+               }
+               cx_write(MO_GP1_IO, 0x101010);
+               mdelay(250);
+               cx_write(MO_GP1_IO, 0x101000);
+               mdelay(250);
+               cx_write(MO_GP1_IO, 0x101010);
+               mdelay(250);
+               return 0;
+       }
+       return -EINVAL;
+}
+
 /* ----------------------------------------------------------------------- */
 /* Tuner callback function. Currently only needed for the Pinnacle        *
  * PCTV HD 800i with an xc5000 sillicon tuner. This is used for both      *
  * analog tuner attach (tuner-core.c) and dvb tuner attach (cx88-dvb.c)    */
 
-int cx88_tuner_callback(void *priv, int command, int arg)
+static int cx88_xc5000_tuner_callback(struct cx88_core *core,
+                                     int command, int arg)
 {
-       struct i2c_algo_bit_data *i2c_algo = priv;
-       struct cx88_core *core = i2c_algo->data;
-
-       switch(core->boardnr) {
+       switch (core->boardnr) {
        case CX88_BOARD_PINNACLE_PCTV_HD_800i:
-               if(command == 0) { /* This is the reset command from xc5000 */
+               if (command == 0) { /* This is the reset command from xc5000 */
                        /* Reset XC5000 tuner via SYS_RSTO_pin */
                        cx_write(MO_SRST_IO, 0);
                        msleep(10);
                        cx_write(MO_SRST_IO, 1);
                        return 0;
+               } else {
+                       err_printk(core, "xc5000: unknown tuner "
+                                  "callback command.\n");
+                       return -EINVAL;
                }
-               else {
+               break;
+       case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD:
+               if (command == 0) { /* This is the reset command from xc5000 */
+                       cx_clear(MO_GP0_IO, 0x00000010);
+                       msleep(10);
+                       cx_set(MO_GP0_IO, 0x00000010);
+                       return 0;
+               } else {
                        printk(KERN_ERR
                                "xc5000: unknown tuner callback command.\n");
                        return -EINVAL;
@@ -1908,6 +2316,36 @@ int cx88_tuner_callback(void *priv, int command, int arg)
        }
        return 0; /* Should never be here */
 }
+
+int cx88_tuner_callback(void *priv, int command, int arg)
+{
+       struct i2c_algo_bit_data *i2c_algo = priv;
+       struct cx88_core *core;
+
+       if (!i2c_algo) {
+               printk(KERN_ERR "cx88: Error - i2c private data undefined.\n");
+               return -EINVAL;
+       }
+
+       core = i2c_algo->data;
+
+       if (!core) {
+               printk(KERN_ERR "cx88: Error - device struct undefined.\n");
+               return -EINVAL;
+       }
+
+       switch (core->board.tuner_type) {
+               case TUNER_XC2028:
+                       info_printk(core, "Calling XC2028/3028 callback\n");
+                       return cx88_xc2028_tuner_callback(core, command, arg);
+               case TUNER_XC5000:
+                       info_printk(core, "Calling XC5000 callback\n");
+                       return cx88_xc5000_tuner_callback(core, command, arg);
+       }
+       err_printk(core, "Error: Calling callback for tuner %d\n",
+                  core->board.tuner_type);
+       return -EINVAL;
+}
 EXPORT_SYMBOL(cx88_tuner_callback);
 
 /* ----------------------------------------------------------------------- */
@@ -1918,23 +2356,25 @@ static void cx88_card_list(struct cx88_core *core, struct pci_dev *pci)
 
        if (0 == pci->subsystem_vendor &&
            0 == pci->subsystem_device) {
-               printk("%s: Your board has no valid PCI Subsystem ID and thus can't\n"
+               printk(KERN_ERR
+                      "%s: Your board has no valid PCI Subsystem ID and thus can't\n"
                       "%s: be autodetected.  Please pass card=<n> insmod option to\n"
                       "%s: workaround that.  Redirect complaints to the vendor of\n"
                       "%s: the TV card.  Best regards,\n"
                       "%s:         -- tux\n",
                       core->name,core->name,core->name,core->name,core->name);
        } else {
-               printk("%s: Your board isn't known (yet) to the driver.  You can\n"
+               printk(KERN_ERR
+                      "%s: Your board isn't known (yet) to the driver.  You can\n"
                       "%s: try to pick one of the existing card configs via\n"
                       "%s: card=<n> insmod option.  Updating to the latest\n"
                       "%s: version might help as well.\n",
                       core->name,core->name,core->name,core->name);
        }
-       printk("%s: Here is a list of valid choices for the card=<n> insmod option:\n",
-              core->name);
+       err_printk(core, "Here is a list of valid choices for the card=<n> "
+                  "insmod option:\n");
        for (i = 0; i < ARRAY_SIZE(cx88_boards); i++)
-               printk("%s:    card=%d -> %s\n",
+               printk(KERN_ERR "%s:    card=%d -> %s\n",
                       core->name, i, cx88_boards[i].name);
 }
 
@@ -1951,9 +2391,57 @@ static void cx88_card_setup_pre_i2c(struct cx88_core *core)
                cx_set(MO_GP0_IO, 0x00000080); /* 702 out of reset */
                udelay(1000);
                break;
+
+       case CX88_BOARD_PROLINK_PV_8000GT:
+               cx_write(MO_GP2_IO, 0xcf7);
+               mdelay(50);
+               cx_write(MO_GP2_IO, 0xef5);
+               mdelay(50);
+               cx_write(MO_GP2_IO, 0xcf7);
+               msleep(10);
+               break;
+
+        case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD:
+               /* Enable the xc5000 tuner */
+               cx_set(MO_GP0_IO, 0x00001010);
+               break;
        }
 }
 
+/*
+ * Sets board-dependent xc3028 configuration
+ */
+void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl)
+{
+       memset(ctl, 0, sizeof(*ctl));
+
+       ctl->fname   = XC2028_DEFAULT_FIRMWARE;
+       ctl->max_len = 64;
+
+       switch (core->boardnr) {
+       case CX88_BOARD_POWERCOLOR_REAL_ANGEL:
+               /* Doesn't work with firmware version 2.7 */
+               ctl->fname = "xc3028-v25.fw";
+               break;
+       case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
+               ctl->scode_table = XC3028_FE_ZARLINK456;
+               break;
+       case CX88_BOARD_KWORLD_ATSC_120:
+       case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
+               ctl->demod = XC3028_FE_OREN538;
+               break;
+       case CX88_BOARD_PROLINK_PV_8000GT:
+               /*
+                * This board uses non-MTS firmware
+                */
+               break;
+       default:
+               ctl->demod = XC3028_FE_OREN538;
+               ctl->mts = 1;
+       }
+}
+EXPORT_SYMBOL_GPL(cx88_setup_xc3028);
+
 static void cx88_card_setup(struct cx88_core *core)
 {
        static u8 eeprom[256];
@@ -1991,6 +2479,13 @@ static void cx88_card_setup(struct cx88_core *core)
                cx_write(MO_GP0_IO, 0x000007f8);
                cx_write(MO_GP1_IO, 0x00000001);
                break;
+       case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
+               /* GPIO0:0 is hooked to demod reset */
+               /* GPIO0:4 is hooked to xc3028 reset */
+               cx_write(MO_GP0_IO, 0x00111100);
+               msleep(1);
+               cx_write(MO_GP0_IO, 0x00111111);
+               break;
        case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL:
                /* GPIO0:6 is hooked to FX2 reset pin */
                cx_set(MO_GP0_IO, 0x00004040);
@@ -2038,10 +2533,8 @@ static void cx88_card_setup(struct cx88_core *core)
                        for (i = 0; i < ARRAY_SIZE(buffer); i++)
                                if (2 != i2c_master_send(&core->i2c_client,
                                                        buffer[i],2))
-                                       printk(KERN_WARNING
-                                               "%s: Unable to enable "
-                                               "tuner(%i).\n",
-                                               core->name, i);
+                                       warn_printk(core, "Unable to enable "
+                                                   "tuner(%i).\n", i);
                }
                break;
        case CX88_BOARD_MSI_TVANYWHERE_MASTER:
@@ -2062,6 +2555,22 @@ static void cx88_card_setup(struct cx88_core *core)
                cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &tea5767_cfg);
        }
        }
+
+       if (core->board.tuner_type == TUNER_XC2028) {
+               struct v4l2_priv_tun_config  xc2028_cfg;
+               struct xc2028_ctrl           ctl;
+
+               /* Fills device-dependent initialization parameters */
+               cx88_setup_xc3028(core, &ctl);
+
+               /* Sends parameters to xc2028/3028 tuner */
+               memset(&xc2028_cfg, 0, sizeof(xc2028_cfg));
+               xc2028_cfg.tuner = TUNER_XC2028;
+               xc2028_cfg.priv  = &ctl;
+               info_printk(core, "Asking xc2028/3028 to load firmware %s\n",
+                           ctl.fname);
+               cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &xc2028_cfg);
+       }
 }
 
 /* ------------------------------------------------------------------ */
@@ -2178,9 +2687,8 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr)
 
        memcpy(&core->board, &cx88_boards[core->boardnr], sizeof(core->board));
 
-       printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
-               core->name,pci->subsystem_vendor,
-               pci->subsystem_device, core->board.name,
+       info_printk(core, "subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
+               pci->subsystem_vendor, pci->subsystem_device, core->board.name,
                core->boardnr, card[core->nr] == core->boardnr ?
                "insmod option" : "autodetected");
 
@@ -2189,8 +2697,8 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr)
        if (radio[core->nr] != UNSET)
                core->board.radio_type = radio[core->nr];
 
-       printk(KERN_INFO "%s: TV tuner type %d, Radio tuner type %d\n",
-              core->name, core->board.tuner_type, core->board.radio_type);
+       info_printk(core, "TV tuner type %d, Radio tuner type %d\n",
+                   core->board.tuner_type, core->board.radio_type);
 
        /* init hardware */
        cx88_reset(core);
@@ -2207,12 +2715,3 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr)
 
        return core;
 }
-
-/* ------------------------------------------------------------------ */
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
- */
index 01e2ac98970b3d14310bbf52660f85271ef1326b..c4d1aff1fdb4911f186344f59594110a70604c2e 100644 (file)
@@ -47,15 +47,15 @@ MODULE_LICENSE("GPL");
 
 /* ------------------------------------------------------------------ */
 
-static unsigned int core_debug = 0;
+static unsigned int core_debug;
 module_param(core_debug,int,0644);
 MODULE_PARM_DESC(core_debug,"enable debug messages [core]");
 
-static unsigned int nicam = 0;
+static unsigned int nicam;
 module_param(nicam,int,0644);
 MODULE_PARM_DESC(nicam,"tv audio is nicam");
 
-static unsigned int nocomb = 0;
+static unsigned int nocomb;
 module_param(nocomb,int,0644);
 MODULE_PARM_DESC(nocomb,"disable comb filter");
 
@@ -219,7 +219,7 @@ cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf)
        videobuf_waiton(&buf->vb,0,0);
        videobuf_dma_unmap(q, dma);
        videobuf_dma_free(dma);
-       btcx_riscmem_free((struct pci_dev *)q->dev, &buf->risc);
+       btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc);
        buf->vb.state = VIDEOBUF_NEEDS_INIT;
 }
 
@@ -548,7 +548,7 @@ void cx88_wakeup(struct cx88_core *core,
                mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
        }
        if (bc != 1)
-               printk("%s: %d buffers handled (should be 1)\n",__FUNCTION__,bc);
+               printk("%s: %d buffers handled (should be 1)\n",__func__,bc);
 }
 
 void cx88_shutdown(struct cx88_core *core)
@@ -577,7 +577,7 @@ void cx88_shutdown(struct cx88_core *core)
 
 int cx88_reset(struct cx88_core *core)
 {
-       dprintk(1,"%s\n",__FUNCTION__);
+       dprintk(1,"%s\n",__func__);
        cx88_shutdown(core);
 
        /* clear irq status */
@@ -929,7 +929,10 @@ int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm)
 
        dprintk(1,"set_tvnorm: MO_INPUT_FORMAT  0x%08x [old=0x%08x]\n",
                cxiformat, cx_read(MO_INPUT_FORMAT) & 0x0f);
-       cx_andor(MO_INPUT_FORMAT, 0xf, cxiformat);
+       /* Chroma AGC must be disabled if SECAM is used, we enable it
+          by default on PAL and NTSC */
+       cx_andor(MO_INPUT_FORMAT, 0x40f,
+                norm & V4L2_STD_SECAM ? cxiformat : cxiformat | 0x400);
 
        // FIXME: as-is from DScaler
        dprintk(1,"set_tvnorm: MO_OUTPUT_FORMAT 0x%08x [old=0x%08x]\n",
index f7b41eb1bb5a63a689c6e105718f20a262d0a2a0..f1251b844e0823c48128b27fd03b437be611e578 100644 (file)
 #include "nxt200x.h"
 #include "cx24123.h"
 #include "isl6421.h"
+#include "tuner-simple.h"
+#include "tda9887.h"
 
 MODULE_DESCRIPTION("driver for cx2388x based DVB cards");
 MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
 MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
 MODULE_LICENSE("GPL");
 
-static unsigned int debug = 0;
+static unsigned int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug,"enable debug messages [dvb]");
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 #define dprintk(level,fmt, arg...)     if (debug >= level) \
        printk(KERN_DEBUG "%s/2-dvb: " fmt, core->name, ## arg)
 
@@ -235,6 +239,19 @@ static struct zl10353_config dvico_fusionhdtv_hybrid = {
        .no_tuner      = 1,
 };
 
+static struct zl10353_config dvico_fusionhdtv_xc3028 = {
+       .demod_address = 0x0f,
+       .if2           = 45600,
+       .no_tuner      = 1,
+};
+
+static struct mt352_config dvico_fusionhdtv_mt352_xc3028 = {
+       .demod_address = 0x0f,
+       .if2 = 4560,
+       .no_tuner = 1,
+       .demod_init = dvico_fusionhdtv_demod_init,
+};
+
 static struct zl10353_config dvico_fusionhdtv_plus_v1_1 = {
        .demod_address = 0x0f,
 };
@@ -266,7 +283,7 @@ static int lgdt330x_pll_rf_set(struct dvb_frontend* fe, int index)
        struct cx8802_dev *dev= fe->dvb->priv;
        struct cx88_core *core = dev->core;
 
-       dprintk(1, "%s: index = %d\n", __FUNCTION__, index);
+       dprintk(1, "%s: index = %d\n", __func__, index);
        if (index == 0)
                cx_clear(MO_GP0_IO, 8);
        else
@@ -357,6 +374,40 @@ static int geniatech_dvbs_set_voltage(struct dvb_frontend *fe,
        return 0;
 }
 
+static int cx88_pci_nano_callback(void *ptr, int command, int arg)
+{
+       struct cx88_core *core = ptr;
+
+       switch (command) {
+       case XC2028_TUNER_RESET:
+               /* Send the tuner in then out of reset */
+               dprintk(1, "%s: XC2028_TUNER_RESET %d\n", __func__, arg);
+
+               switch (core->boardnr) {
+               case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
+                       /* GPIO-4 xc3028 tuner */
+
+                       cx_set(MO_GP0_IO, 0x00001000);
+                       cx_clear(MO_GP0_IO, 0x00000010);
+                       msleep(100);
+                       cx_set(MO_GP0_IO, 0x00000010);
+                       msleep(100);
+                       break;
+               }
+
+               break;
+       case XC2028_RESET_CLK:
+               dprintk(1, "%s: XC2028_RESET_CLK %d\n", __func__, arg);
+               break;
+       default:
+               dprintk(1, "%s: unknown command %d, arg %d\n", __func__,
+                       command, arg);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 static struct cx24123_config geniatech_dvbs_config = {
        .demod_address = 0x55,
        .set_ts_params = cx24123_set_ts_param,
@@ -383,12 +434,76 @@ static struct s5h1409_config pinnacle_pctv_hd_800i_config = {
        .mpeg_timing   = S5H1409_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK,
 };
 
+static struct s5h1409_config dvico_hdtv5_pci_nano_config = {
+       .demod_address = 0x32 >> 1,
+       .output_mode   = S5H1409_SERIAL_OUTPUT,
+       .gpio          = S5H1409_GPIO_OFF,
+       .inversion     = S5H1409_INVERSION_OFF,
+       .status_mode   = S5H1409_DEMODLOCKING,
+       .mpeg_timing   = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
+};
+
+static struct s5h1409_config kworld_atsc_120_config = {
+       .demod_address = 0x32 >> 1,
+       .output_mode   = S5H1409_SERIAL_OUTPUT,
+       .gpio          = S5H1409_GPIO_OFF,
+       .inversion     = S5H1409_INVERSION_OFF,
+       .status_mode   = S5H1409_DEMODLOCKING,
+       .mpeg_timing   = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
+};
+
 static struct xc5000_config pinnacle_pctv_hd_800i_tuner_config = {
        .i2c_address    = 0x64,
        .if_khz         = 5380,
        .tuner_callback = cx88_tuner_callback,
 };
 
+static struct zl10353_config cx88_geniatech_x8000_mt = {
+       .demod_address = (0x1e >> 1),
+       .no_tuner = 1,
+};
+
+static int attach_xc3028(u8 addr, struct cx8802_dev *dev)
+{
+       struct dvb_frontend *fe;
+       struct xc2028_ctrl ctl;
+       struct xc2028_config cfg = {
+               .i2c_adap  = &dev->core->i2c_adap,
+               .i2c_addr  = addr,
+               .ctrl      = &ctl,
+               .callback  = cx88_tuner_callback,
+       };
+
+       if (!dev->dvb.frontend) {
+               printk(KERN_ERR "%s/2: dvb frontend not attached. "
+                               "Can't attach xc3028\n",
+                      dev->core->name);
+               return -EINVAL;
+       }
+
+       /*
+        * Some xc3028 devices may be hidden by an I2C gate. This is known
+        * to happen with some s5h1409-based devices.
+        * Now that I2C gate is open, sets up xc3028 configuration
+        */
+       cx88_setup_xc3028(dev->core, &ctl);
+
+       fe = dvb_attach(xc2028_attach, dev->dvb.frontend, &cfg);
+       if (!fe) {
+               printk(KERN_ERR "%s/2: xc3028 attach failed\n",
+                      dev->core->name);
+               dvb_frontend_detach(dev->dvb.frontend);
+               dvb_unregister_frontend(dev->dvb.frontend);
+               dev->dvb.frontend = NULL;
+               return -EINVAL;
+       }
+
+       printk(KERN_INFO "%s/2: xc3028 attached\n",
+              dev->core->name);
+
+       return 0;
+}
+
 static int dvb_register(struct cx8802_dev *dev)
 {
        /* init struct videobuf_dvb */
@@ -429,8 +544,9 @@ static int dvb_register(struct cx8802_dev *dev)
                                               &hauppauge_hvr_config,
                                               &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
-                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
-                                  &dev->core->i2c_adap, DVB_PLL_FMD1216ME);
+                       dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+                                  &dev->core->i2c_adap, 0x61,
+                                  TUNER_PHILIPS_FMD1216ME_MK3);
                }
                break;
        case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
@@ -497,8 +613,9 @@ static int dvb_register(struct cx8802_dev *dev)
                dev->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_pro_config,
                                               &dev->vp3054->adap);
                if (dev->dvb.frontend != NULL) {
-                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
-                                  &dev->core->i2c_adap, DVB_PLL_FMD1216ME);
+                       dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+                                  &dev->core->i2c_adap, 0x61,
+                                  TUNER_PHILIPS_FMD1216ME_MK3);
                }
 #else
                printk(KERN_ERR "%s/2: built without vp3054 support\n", dev->core->name);
@@ -509,18 +626,36 @@ static int dvb_register(struct cx8802_dev *dev)
                                               &dvico_fusionhdtv_hybrid,
                                               &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
-                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
-                                  &dev->core->i2c_adap,
-                                  DVB_PLL_THOMSON_FE6600);
+                       dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+                                  &dev->core->i2c_adap, 0x61,
+                                  TUNER_THOMSON_FE6600);
                }
                break;
+       case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
+               dev->dvb.frontend = dvb_attach(zl10353_attach,
+                                              &dvico_fusionhdtv_xc3028,
+                                              &dev->core->i2c_adap);
+               if (dev->dvb.frontend == NULL)
+                       dev->dvb.frontend = dvb_attach(mt352_attach,
+                                               &dvico_fusionhdtv_mt352_xc3028,
+                                               &dev->core->i2c_adap);
+               /*
+                * On this board, the demod provides the I2C bus pullup.
+                * We must not permit gate_ctrl to be performed, or
+                * the xc3028 cannot communicate on the bus.
+                */
+               if (dev->dvb.frontend)
+                       dev->dvb.frontend->ops.i2c_gate_ctrl = NULL;
+               if (attach_xc3028(0x61, dev) < 0)
+                       return -EINVAL;
+               break;
        case CX88_BOARD_PCHDTV_HD3000:
                dev->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000,
                                               &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
-                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
-                                  &dev->core->i2c_adap,
-                                  DVB_PLL_THOMSON_DTT761X);
+                       dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+                                  &dev->core->i2c_adap, 0x61,
+                                  TUNER_THOMSON_DTT761X);
                }
                break;
        case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q:
@@ -540,9 +675,9 @@ static int dvb_register(struct cx8802_dev *dev)
                                               &fusionhdtv_3_gold,
                                               &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
-                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
-                                  &dev->core->i2c_adap,
-                                  DVB_PLL_MICROTUNE_4042);
+                       dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+                                  &dev->core->i2c_adap, 0x61,
+                                  TUNER_MICROTUNE_4042FI5);
                }
                }
                break;
@@ -560,9 +695,9 @@ static int dvb_register(struct cx8802_dev *dev)
                                               &fusionhdtv_3_gold,
                                               &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
-                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
-                                  &dev->core->i2c_adap,
-                                  DVB_PLL_THOMSON_DTT761X);
+                       dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+                                  &dev->core->i2c_adap, 0x61,
+                                  TUNER_THOMSON_DTT761X);
                }
                }
                break;
@@ -580,9 +715,11 @@ static int dvb_register(struct cx8802_dev *dev)
                                               &fusionhdtv_5_gold,
                                               &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
-                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
-                                  &dev->core->i2c_adap,
-                                  DVB_PLL_LG_TDVS_H06XF);
+                       dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+                                  &dev->core->i2c_adap, 0x61,
+                                  TUNER_LG_TDVS_H06XF);
+                       dvb_attach(tda9887_attach, dev->dvb.frontend,
+                                  &dev->core->i2c_adap, 0x43);
                }
                }
                break;
@@ -600,9 +737,11 @@ static int dvb_register(struct cx8802_dev *dev)
                                               &pchdtv_hd5500,
                                               &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
-                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
-                                  &dev->core->i2c_adap,
-                                  DVB_PLL_LG_TDVS_H06XF);
+                       dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+                                  &dev->core->i2c_adap, 0x61,
+                                  TUNER_LG_TDVS_H06XF);
+                       dvb_attach(tda9887_attach, dev->dvb.frontend,
+                                  &dev->core->i2c_adap, 0x43);
                }
                }
                break;
@@ -611,8 +750,9 @@ static int dvb_register(struct cx8802_dev *dev)
                                               &ati_hdtvwonder,
                                               &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
-                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
-                                  NULL, DVB_PLL_TUV1236D);
+                       dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+                                  &dev->core->i2c_adap, 0x61,
+                                  TUNER_PHILIPS_TUV1236D);
                }
                break;
        case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
@@ -658,14 +798,62 @@ static int dvb_register(struct cx8802_dev *dev)
                                   &pinnacle_pctv_hd_800i_tuner_config);
                }
                break;
+       case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
+               dev->dvb.frontend = dvb_attach(s5h1409_attach,
+                                               &dvico_hdtv5_pci_nano_config,
+                                               &dev->core->i2c_adap);
+               if (dev->dvb.frontend != NULL) {
+                       struct dvb_frontend *fe;
+                       struct xc2028_config cfg = {
+                               .i2c_adap  = &dev->core->i2c_adap,
+                               .i2c_addr  = 0x61,
+                               .callback  = cx88_pci_nano_callback,
+                       };
+                       static struct xc2028_ctrl ctl = {
+                               .fname       = "xc3028-v27.fw",
+                               .max_len     = 64,
+                               .scode_table = XC3028_FE_OREN538,
+                       };
+
+                       fe = dvb_attach(xc2028_attach,
+                                       dev->dvb.frontend, &cfg);
+                       if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
+                               fe->ops.tuner_ops.set_config(fe, &ctl);
+               }
+               break;
+        case CX88_BOARD_PINNACLE_HYBRID_PCTV:
+               dev->dvb.frontend = dvb_attach(zl10353_attach,
+                                              &cx88_geniatech_x8000_mt,
+                                              &dev->core->i2c_adap);
+               if (attach_xc3028(0x61, dev) < 0)
+                       return -EINVAL;
+               break;
+        case CX88_BOARD_GENIATECH_X8000_MT:
+               dev->ts_gen_cntrl = 0x00;
+
+               dev->dvb.frontend = dvb_attach(zl10353_attach,
+                                              &cx88_geniatech_x8000_mt,
+                                              &dev->core->i2c_adap);
+               if (attach_xc3028(0x61, dev) < 0)
+                       return -EINVAL;
+               break;
+        case CX88_BOARD_KWORLD_ATSC_120:
+               dev->dvb.frontend = dvb_attach(s5h1409_attach,
+                                              &kworld_atsc_120_config,
+                                              &dev->core->i2c_adap);
+               if (attach_xc3028(0x61, dev) < 0)
+                       return -EINVAL;
+               break;
        default:
                printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n",
                       dev->core->name);
                break;
        }
        if (NULL == dev->dvb.frontend) {
-               printk(KERN_ERR "%s/2: frontend initialization failed\n", dev->core->name);
-               return -1;
+               printk(KERN_ERR
+                      "%s/2: frontend initialization failed\n",
+                      dev->core->name);
+               return -EINVAL;
        }
 
        /* Ensure all frontends negotiate bus access */
@@ -675,7 +863,8 @@ static int dvb_register(struct cx8802_dev *dev)
        cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);
 
        /* register everything */
-       return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, &dev->pci->dev);
+       return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev,
+                                    &dev->pci->dev, adapter_nr);
 }
 
 /* ----------------------------------------------------------- */
@@ -685,7 +874,7 @@ static int cx8802_dvb_advise_acquire(struct cx8802_driver *drv)
 {
        struct cx88_core *core = drv->core;
        int err = 0;
-       dprintk( 1, "%s\n", __FUNCTION__);
+       dprintk( 1, "%s\n", __func__);
 
        switch (core->boardnr) {
        case CX88_BOARD_HAUPPAUGE_HVR1300:
@@ -708,7 +897,7 @@ static int cx8802_dvb_advise_release(struct cx8802_driver *drv)
 {
        struct cx88_core *core = drv->core;
        int err = 0;
-       dprintk( 1, "%s\n", __FUNCTION__);
+       dprintk( 1, "%s\n", __func__);
 
        switch (core->boardnr) {
        case CX88_BOARD_HAUPPAUGE_HVR1300:
@@ -726,7 +915,7 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv)
        struct cx8802_dev *dev = drv->core->dvbdev;
        int err;
 
-       dprintk( 1, "%s\n", __FUNCTION__);
+       dprintk( 1, "%s\n", __func__);
        dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
                core->boardnr,
                core->name,
@@ -744,8 +933,8 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv)
 
        /* dvb stuff */
        printk(KERN_INFO "%s/2: cx2388x based DVB/ATSC card\n", core->name);
-       videobuf_queue_pci_init(&dev->dvb.dvbq, &dvb_qops,
-                           dev->pci, &dev->slock,
+       videobuf_queue_sg_init(&dev->dvb.dvbq, &dvb_qops,
+                           &dev->pci->dev, &dev->slock,
                            V4L2_BUF_TYPE_VIDEO_CAPTURE,
                            V4L2_FIELD_TOP,
                            sizeof(struct cx88_buffer),
@@ -764,7 +953,8 @@ static int cx8802_dvb_remove(struct cx8802_driver *drv)
        struct cx8802_dev *dev = drv->core->dvbdev;
 
        /* dvb */
-       videobuf_dvb_unregister(&dev->dvb);
+       if (dev->dvb.frontend)
+               videobuf_dvb_unregister(&dev->dvb);
 
        vp3054_i2c_remove(dev);
 
index 566b26af523e74b132113ed968af94782dddc472..c6b44732a082fd743b6fbbc3ac39f4ab511e514f 100644 (file)
 #include "cx88.h"
 #include <media/v4l2-common.h>
 
-static unsigned int i2c_debug = 0;
+static unsigned int i2c_debug;
 module_param(i2c_debug, int, 0644);
 MODULE_PARM_DESC(i2c_debug,"enable debug messages [i2c]");
 
-static unsigned int i2c_scan = 0;
+static unsigned int i2c_scan;
 module_param(i2c_scan, int, 0444);
 MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time");
 
index bb0911b4d2f683ada952b8197d31c8f7445b667b..53526d997a4e97923231ead7736fa2f9c9c089cf 100644 (file)
@@ -57,7 +57,7 @@ struct cx88_IR {
        u32 mask_keyup;
 };
 
-static int ir_debug = 0;
+static int ir_debug;
 module_param(ir_debug, int, 0644);     /* debug level [IR] */
 MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]");
 
@@ -258,6 +258,13 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
                ir->mask_keyup = 0x80;
                ir->polling = 1; /* ms */
                break;
+       case CX88_BOARD_PROLINK_PV_8000GT:
+               ir_codes = ir_codes_pixelview_new;
+               ir->gpio_addr = MO_GP1_IO;
+               ir->mask_keycode = 0x3f;
+               ir->mask_keyup = 0x80;
+               ir->polling = 1; /* ms */
+               break;
        case CX88_BOARD_KWORLD_LTV883:
                ir_codes = ir_codes_pixelview;
                ir->gpio_addr = MO_GP1_IO;
@@ -310,6 +317,12 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
                ir_type = IR_TYPE_RC5;
                ir->sampling = 1;
                break;
+       case CX88_BOARD_POWERCOLOR_REAL_ANGEL:
+               ir_codes = ir_codes_powercolor_real_angel;
+               ir->gpio_addr = MO_GP2_IO;
+               ir->mask_keycode = 0x7e;
+               ir->polling = 100; /* ms */
+               break;
        }
 
        if (NULL == ir_codes) {
index e357f415db06601ceab9333994d90aa4d51f4bfa..a6b061c2644a7d72446a0a79713180c64e3d6c8d 100644 (file)
@@ -39,7 +39,7 @@ MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
 MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
 MODULE_LICENSE("GPL");
 
-static unsigned int debug = 0;
+static unsigned int debug;
 module_param(debug,int,0644);
 MODULE_PARM_DESC(debug,"enable debug messages [mpeg]");
 
@@ -146,7 +146,7 @@ static int cx8802_start_dma(struct cx8802_dev    *dev,
                cx_write(TS_GEN_CNTRL, 0x06); /* punctured clock TS & posedge driven */
                udelay(100);
        } else {
-               printk( "%s() Failed. Unsupported value in .mpeg (0x%08x)\n", __FUNCTION__,
+               printk( "%s() Failed. Unsupported value in .mpeg (0x%08x)\n", __func__,
                        core->board.mpeg );
                return -EINVAL;
        }
@@ -247,7 +247,7 @@ int cx8802_buf_prepare(struct videobuf_queue *q, struct cx8802_dev *dev,
        struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
        int rc;
 
-       dprintk(1, "%s: %p\n", __FUNCTION__, buf);
+       dprintk(1, "%s: %p\n", __func__, buf);
        if (0 != buf->vb.baddr  &&  buf->vb.bsize < size)
                return -EINVAL;
 
@@ -289,7 +289,7 @@ void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf)
                buf->count    = cx88q->count++;
                mod_timer(&cx88q->timeout, jiffies+BUFFER_TIMEOUT);
                dprintk(1,"[%p/%d] %s - first active\n",
-                       buf, buf->vb.i, __FUNCTION__);
+                       buf, buf->vb.i, __func__);
 
        } else {
                dprintk( 1, "queue is not empty - append to active\n" );
@@ -299,7 +299,7 @@ void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf)
                buf->count    = cx88q->count++;
                prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
                dprintk( 1, "[%p/%d] %s - append to active\n",
-                       buf, buf->vb.i, __FUNCTION__);
+                       buf, buf->vb.i, __func__);
        }
 }
 
@@ -342,7 +342,7 @@ static void cx8802_timeout(unsigned long data)
 {
        struct cx8802_dev *dev = (struct cx8802_dev*)data;
 
-       dprintk(1, "%s\n",__FUNCTION__);
+       dprintk(1, "%s\n",__func__);
 
        if (debug)
                cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH28]);
@@ -613,6 +613,8 @@ static int cx8802_request_acquire(struct cx8802_driver *drv)
            core->active_type_id != drv->type_id)
                return -EBUSY;
 
+       core->input = CX88_VMUX_DVB;
+
        if (drv->advise_acquire)
        {
                mutex_lock(&drv->core->lock);
@@ -623,7 +625,7 @@ static int cx8802_request_acquire(struct cx8802_driver *drv)
                }
                mutex_unlock(&drv->core->lock);
 
-               mpeg_dbg(1,"%s() Post acquire GPIO=%x\n", __FUNCTION__, cx_read(MO_GP0_IO));
+               mpeg_dbg(1,"%s() Post acquire GPIO=%x\n", __func__, cx_read(MO_GP0_IO));
        }
 
        return 0;
@@ -639,7 +641,7 @@ static int cx8802_request_release(struct cx8802_driver *drv)
        {
                drv->advise_release(drv);
                core->active_type_id = CX88_BOARD_NONE;
-               mpeg_dbg(1,"%s() Post release GPIO=%x\n", __FUNCTION__, cx_read(MO_GP0_IO));
+               mpeg_dbg(1,"%s() Post release GPIO=%x\n", __func__, cx_read(MO_GP0_IO));
        }
        mutex_unlock(&drv->core->lock);
 
@@ -813,7 +815,7 @@ static void __devexit cx8802_remove(struct pci_dev *pci_dev)
 
        dev = pci_get_drvdata(pci_dev);
 
-       dprintk( 1, "%s\n", __FUNCTION__);
+       dprintk( 1, "%s\n", __func__);
 
        if (!list_empty(&dev->drvlist)) {
                struct cx8802_driver *drv, *tmp;
index 76e5c78d8ae44c8698af8611db3fabdf30830fd6..3a1977f41e277ddd681694398ae8de01335cdf5a 100644 (file)
 
 #include "cx88.h"
 
-static unsigned int audio_debug = 0;
+static unsigned int audio_debug;
 module_param(audio_debug, int, 0644);
 MODULE_PARM_DESC(audio_debug, "enable debug messages [audio]");
 
-static unsigned int always_analog = 0;
+static unsigned int always_analog;
 module_param(always_analog,int,0644);
 MODULE_PARM_DESC(always_analog,"force analog audio out");
 
-static unsigned int radio_deemphasis = 0;
+static unsigned int radio_deemphasis;
 module_param(radio_deemphasis,int,0644);
 MODULE_PARM_DESC(radio_deemphasis, "Radio deemphasis time constant, "
                 "0=None, 1=50us (elsewhere), 2=75us (USA)");
@@ -265,12 +265,12 @@ static void set_audio_standard_BTSC(struct cx88_core *core, unsigned int sap,
        mode |= EN_FMRADIO_EN_RDS;
 
        if (sap) {
-               dprintk("%s SAP (status: unknown)\n", __FUNCTION__);
+               dprintk("%s SAP (status: unknown)\n", __func__);
                set_audio_start(core, SEL_SAP);
                set_audio_registers(core, btsc_sap);
                set_audio_finish(core, mode);
        } else {
-               dprintk("%s (status: known-good)\n", __FUNCTION__);
+               dprintk("%s (status: known-good)\n", __func__);
                set_audio_start(core, SEL_BTSC);
                set_audio_registers(core, btsc);
                set_audio_finish(core, mode);
@@ -351,16 +351,16 @@ static void set_audio_standard_NICAM(struct cx88_core *core, u32 mode)
        set_audio_start(core,SEL_NICAM);
        switch (core->tvaudio) {
        case WW_L:
-               dprintk("%s SECAM-L NICAM (status: devel)\n", __FUNCTION__);
+               dprintk("%s SECAM-L NICAM (status: devel)\n", __func__);
                set_audio_registers(core, nicam_l);
                break;
        case WW_I:
-               dprintk("%s PAL-I NICAM (status: known-good)\n", __FUNCTION__);
+               dprintk("%s PAL-I NICAM (status: known-good)\n", __func__);
                set_audio_registers(core, nicam_bgdki_common);
                set_audio_registers(core, nicam_i);
                break;
        default:
-               dprintk("%s PAL-BGDK NICAM (status: known-good)\n", __FUNCTION__);
+               dprintk("%s PAL-BGDK NICAM (status: known-good)\n", __func__);
                set_audio_registers(core, nicam_bgdki_common);
                set_audio_registers(core, nicam_default);
                break;
@@ -600,28 +600,28 @@ static void set_audio_standard_A2(struct cx88_core *core, u32 mode)
        set_audio_start(core, SEL_A2);
        switch (core->tvaudio) {
        case WW_BG:
-               dprintk("%s PAL-BG A1/2 (status: known-good)\n", __FUNCTION__);
+               dprintk("%s PAL-BG A1/2 (status: known-good)\n", __func__);
                set_audio_registers(core, a2_bgdk_common);
                set_audio_registers(core, a2_bg);
                set_audio_registers(core, a2_deemph50);
                break;
        case WW_DK:
-               dprintk("%s PAL-DK A1/2 (status: known-good)\n", __FUNCTION__);
+               dprintk("%s PAL-DK A1/2 (status: known-good)\n", __func__);
                set_audio_registers(core, a2_bgdk_common);
                set_audio_registers(core, a2_dk);
                set_audio_registers(core, a2_deemph50);
                break;
        case WW_I:
-               dprintk("%s PAL-I A1 (status: known-good)\n", __FUNCTION__);
+               dprintk("%s PAL-I A1 (status: known-good)\n", __func__);
                set_audio_registers(core, a1_i);
                set_audio_registers(core, a2_deemph50);
                break;
        case WW_L:
-               dprintk("%s AM-L (status: devel)\n", __FUNCTION__);
+               dprintk("%s AM-L (status: devel)\n", __func__);
                set_audio_registers(core, am_l);
                break;
        default:
-               dprintk("%s Warning: wrong value\n", __FUNCTION__);
+               dprintk("%s Warning: wrong value\n", __func__);
                return;
                break;
        };
@@ -637,7 +637,7 @@ static void set_audio_standard_EIAJ(struct cx88_core *core)
 
                { /* end of list */ },
        };
-       dprintk("%s (status: unknown)\n", __FUNCTION__);
+       dprintk("%s (status: unknown)\n", __func__);
 
        set_audio_start(core, SEL_EIAJ);
        set_audio_registers(core, eiaj);
@@ -691,7 +691,7 @@ static void set_audio_standard_FM(struct cx88_core *core,
                { /* end of list */ },
        };
 
-       dprintk("%s (status: unknown)\n", __FUNCTION__);
+       dprintk("%s (status: unknown)\n", __func__);
        set_audio_start(core, SEL_FMRADIO);
 
        switch (deemph) {
index d96ecfcf393a06d0ad99920a9c044d6c71c0ca19..0943060682bcd4ebf6039f32e3288f3d391fa76b 100644 (file)
@@ -11,7 +11,7 @@ static unsigned int vbibufs = 4;
 module_param(vbibufs,int,0644);
 MODULE_PARM_DESC(vbibufs,"number of vbi buffers, range 2-32");
 
-static unsigned int vbi_debug = 0;
+static unsigned int vbi_debug;
 module_param(vbi_debug,int,0644);
 MODULE_PARM_DESC(vbi_debug,"enable debug messages [vbi]");
 
index 227179620d13cbe00695e5bbac05efe7a44f51fc..eea23f95edb751d42f9dce1588f817038e0ba5bf 100644 (file)
@@ -63,11 +63,11 @@ MODULE_PARM_DESC(video_nr,"video device numbers");
 MODULE_PARM_DESC(vbi_nr,"vbi device numbers");
 MODULE_PARM_DESC(radio_nr,"radio device numbers");
 
-static unsigned int video_debug = 0;
+static unsigned int video_debug;
 module_param(video_debug,int,0644);
 MODULE_PARM_DESC(video_debug,"enable debug messages [video]");
 
-static unsigned int irq_debug = 0;
+static unsigned int irq_debug;
 module_param(irq_debug,int,0644);
 MODULE_PARM_DESC(irq_debug,"enable debug messages [IRQ handler]");
 
@@ -228,6 +228,30 @@ static struct cx88_ctrl cx8800_ctls[] = {
                .mask                  = 0x00ff,
                .shift                 = 0,
        },{
+               .v = {
+                       .id            = V4L2_CID_CHROMA_AGC,
+                       .name          = "Chroma AGC",
+                       .minimum       = 0,
+                       .maximum       = 1,
+                       .default_value = 0x1,
+                       .type          = V4L2_CTRL_TYPE_BOOLEAN,
+               },
+               .reg                   = MO_INPUT_FORMAT,
+               .mask                  = 1 << 10,
+               .shift                 = 10,
+       }, {
+               .v = {
+                       .id            = V4L2_CID_COLOR_KILLER,
+                       .name          = "Color killer",
+                       .minimum       = 0,
+                       .maximum       = 1,
+                       .default_value = 0x1,
+                       .type          = V4L2_CTRL_TYPE_BOOLEAN,
+               },
+               .reg                   = MO_INPUT_FORMAT,
+               .mask                  = 1 << 9,
+               .shift                 = 9,
+       }, {
        /* --- audio --- */
                .v = {
                        .id            = V4L2_CID_AUDIO_MUTE,
@@ -282,6 +306,8 @@ const u32 cx88_user_ctrls[] = {
        V4L2_CID_AUDIO_VOLUME,
        V4L2_CID_AUDIO_BALANCE,
        V4L2_CID_AUDIO_MUTE,
+       V4L2_CID_CHROMA_AGC,
+       V4L2_CID_COLOR_KILLER,
        0
 };
 EXPORT_SYMBOL(cx88_user_ctrls);
@@ -291,7 +317,7 @@ static const u32 *ctrl_classes[] = {
        NULL
 };
 
-int cx8800_ctrl_query(struct v4l2_queryctrl *qctrl)
+int cx8800_ctrl_query(struct cx88_core *core, struct v4l2_queryctrl *qctrl)
 {
        int i;
 
@@ -306,6 +332,11 @@ int cx8800_ctrl_query(struct v4l2_queryctrl *qctrl)
                return 0;
        }
        *qctrl = cx8800_ctls[i].v;
+       /* Report chroma AGC as inactive when SECAM is selected */
+       if (cx8800_ctls[i].v.id == V4L2_CID_CHROMA_AGC &&
+           core->tvnorm & V4L2_STD_SECAM)
+               qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+
        return 0;
 }
 EXPORT_SYMBOL(cx8800_ctrl_query);
@@ -776,14 +807,14 @@ static int video_open(struct inode *inode, struct file *file)
        fh->height   = 240;
        fh->fmt      = format_by_fourcc(V4L2_PIX_FMT_BGR24);
 
-       videobuf_queue_pci_init(&fh->vidq, &cx8800_video_qops,
-                           dev->pci, &dev->slock,
+       videobuf_queue_sg_init(&fh->vidq, &cx8800_video_qops,
+                           &dev->pci->dev, &dev->slock,
                            V4L2_BUF_TYPE_VIDEO_CAPTURE,
                            V4L2_FIELD_INTERLACED,
                            sizeof(struct cx88_buffer),
                            fh);
-       videobuf_queue_pci_init(&fh->vbiq, &cx8800_vbi_qops,
-                           dev->pci, &dev->slock,
+       videobuf_queue_sg_init(&fh->vbiq, &cx8800_vbi_qops,
+                           &dev->pci->dev, &dev->slock,
                            V4L2_BUF_TYPE_VBI_CAPTURE,
                            V4L2_FIELD_SEQ_TB,
                            sizeof(struct cx88_buffer),
@@ -976,6 +1007,12 @@ int cx88_set_control(struct cx88_core *core, struct v4l2_control *ctl)
                }
                mask=0xffff;
                break;
+       case V4L2_CID_CHROMA_AGC:
+               /* Do not allow chroma AGC to be enabled for SECAM */
+               value = ((ctl->value - c->off) << c->shift) & c->mask;
+               if (core->tvnorm & V4L2_STD_SECAM && value)
+                       return -EINVAL;
+               break;
        default:
                value = ((ctl->value - c->off) << c->shift) & c->mask;
                break;
@@ -1268,10 +1305,12 @@ static int vidioc_s_input (struct file *file, void *priv, unsigned int i)
 static int vidioc_queryctrl (struct file *file, void *priv,
                                struct v4l2_queryctrl *qctrl)
 {
+       struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
+
        qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
        if (unlikely(qctrl->id == 0))
                return -EINVAL;
-       return cx8800_ctrl_query(qctrl);
+       return cx8800_ctrl_query(core, qctrl);
 }
 
 static int vidioc_g_ctrl (struct file *file, void *priv,
@@ -1832,8 +1871,11 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
 
        switch (core->boardnr) {
        case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD:
-               request_module("ir-kbd-i2c");
+       case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD:
                request_module("rtc-isl1208");
+               /* break intentionally omitted */
+       case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
+               request_module("ir-kbd-i2c");
        }
 
        /* register v4l devices */
@@ -1917,6 +1959,9 @@ static void __devexit cx8800_finidev(struct pci_dev *pci_dev)
                core->kthread = NULL;
        }
 
+       if (core->ir)
+               cx88_ir_stop(core, core->ir);
+
        cx88_shutdown(core); /* FIXME */
        pci_disable_device(pci_dev);
 
index 37e6d2e4002f54f229f9daff57894462b7ce603c..14ac173f40711e66ca3a2ad51a82dc7c4c222a7d 100644 (file)
@@ -37,6 +37,7 @@
 
 #include "btcx-risc.h"
 #include "cx88-reg.h"
+#include "tuner-xc2028.h"
 
 #include <linux/version.h>
 #include <linux/mutex.h>
@@ -211,6 +212,15 @@ extern struct sram_channel cx88_sram_channels[];
 #define CX88_BOARD_HAUPPAUGE_HVR1300       56
 #define CX88_BOARD_ADSTECH_PTV_390         57
 #define CX88_BOARD_PINNACLE_PCTV_HD_800i   58
+#define CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO 59
+#define CX88_BOARD_PINNACLE_HYBRID_PCTV    60
+#define CX88_BOARD_WINFAST_TV2000_XP_GLOBAL 61
+#define CX88_BOARD_POWERCOLOR_REAL_ANGEL   62
+#define CX88_BOARD_GENIATECH_X8000_MT      63
+#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO 64
+#define CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD 65
+#define CX88_BOARD_PROLINK_PV_8000GT       66
+#define CX88_BOARD_KWORLD_ATSC_120         67
 
 enum cx88_itype {
        CX88_VMUX_COMPOSITE1 = 1,
@@ -595,6 +605,7 @@ extern int cx88_tuner_callback(void *dev, int command, int arg);
 extern int cx88_get_resources(const struct cx88_core *core,
                              struct pci_dev *pci);
 extern struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr);
+extern void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl);
 
 /* ----------------------------------------------------------- */
 /* cx88-tvaudio.c                                              */
@@ -640,7 +651,8 @@ void cx8802_cancel_buffers(struct cx8802_dev *dev);
 /* ----------------------------------------------------------- */
 /* cx88-video.c*/
 extern const u32 cx88_user_ctrls[];
-extern int cx8800_ctrl_query(struct v4l2_queryctrl *qctrl);
+extern int cx8800_ctrl_query(struct cx88_core *core,
+                            struct v4l2_queryctrl *qctrl);
 int cx88_enum_input (struct cx88_core  *core,struct v4l2_input *i);
 int cx88_set_freq (struct cx88_core  *core,struct v4l2_frequency *f);
 int cx88_get_control(struct cx88_core *core, struct v4l2_control *ctl);
index d14d803566a3577ff7affaaab0a34e75d13eccb4..cbd92635993d8f1ce7c298f31f79337bb9155681 100644 (file)
@@ -1,5 +1,12 @@
 /*
  * dabdata.h - dab usb firmware and bitstream data
+ *
+ * Copyright (C) 1999 BayCom GmbH
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that redistributions of source
+ * code retain the above copyright notice and this comment without
+ * modification.
  */
 
 static INTEL_HEX_RECORD firmware[] = {
index a5731f90be0f842d39aa1a941c50d0ab31d3f6e9..8d1f8ee2a533a48ea3e793b11399873e9d00cd6b 100644 (file)
@@ -205,7 +205,7 @@ static void dabusb_iso_complete (struct urb *purb)
 /*-------------------------------------------------------------------*/
 static int dabusb_alloc_buffers (pdabusb_t s)
 {
-       int buffers = 0;
+       int transfer_len = 0;
        pbuff_t b;
        unsigned int pipe = usb_rcvisocpipe (s->usbdev, _DABUSB_ISOPIPE);
        int pipesize = usb_maxpacket (s->usbdev, pipe, usb_pipeout (pipe));
@@ -216,7 +216,7 @@ static int dabusb_alloc_buffers (pdabusb_t s)
        dbg("dabusb_alloc_buffers pipesize:%d packets:%d transfer_buffer_len:%d",
                 pipesize, packets, transfer_buffer_length);
 
-       while (buffers < (s->total_buffer_size << 10)) {
+       while (transfer_len < (s->total_buffer_size << 10)) {
                b = kzalloc(sizeof (buff_t), GFP_KERNEL);
                if (!b) {
                        err("kzalloc(sizeof(buff_t))==NULL");
@@ -251,10 +251,10 @@ static int dabusb_alloc_buffers (pdabusb_t s)
                        b->purb->iso_frame_desc[i].length = pipesize;
                }
 
-               buffers += transfer_buffer_length;
+               transfer_len += transfer_buffer_length;
                list_add_tail (&b->buff_list, &s->free_buff_list);
        }
-       s->got_mem = buffers;
+       s->got_mem = transfer_len;
 
        return 0;
 
index 9ceb6b2f394920af86ff64bc7be36f3a080c3cfb..88d6df71d051a0acc6e2208926e41a0e4a673634 100644 (file)
 
 #define DPC_BOARD_CAN_DO_VBI(dev)   (dev->revision != 0)
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "debug verbosity");
 
-static int dpc_num = 0;
+static int dpc_num;
 
 #define DPC_INPUTS     2
 static struct v4l2_input dpc_inputs[DPC_INPUTS] = {
index 0f7a0bd86ff4e87a0485f90f162f876a1f2f1202..9caffed2b6b8302637cde0ad128c791cc5ce364e 100644 (file)
@@ -1,11 +1,13 @@
 config VIDEO_EM28XX
-       tristate "Empia EM2800/2820/2840 USB video capture support"
+       tristate "Empia EM28xx USB video capture support"
        depends on VIDEO_DEV && I2C && INPUT
        select VIDEO_TUNER
        select VIDEO_TVEEPROM
        select VIDEO_IR
+       select VIDEOBUF_VMALLOC
        select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO
        select VIDEO_TVP5150 if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_MSP3400 if VIDEO_HELPER_CHIPS_AUTO
        ---help---
          This is a video4linux driver for Empia 28xx based TV cards.
 
@@ -27,3 +29,13 @@ config VIDEO_EM28XX_ALSA
          To compile this driver as a module, choose M here: the
          module will be called em28xx-alsa
 
+config VIDEO_EM28XX_DVB
+       tristate "DVB/ATSC Support for em28xx based TV cards"
+       depends on VIDEO_EM28XX && DVB_CORE
+       select DVB_LGDT330X if !DVB_FE_CUSTOMISE
+       select DVB_ZL10353 if !DVB_FE_CUSTOMISE
+       select VIDEOBUF_DVB
+       select FW_LOADER
+       ---help---
+         This adds support for DVB cards based on the
+         Empiatech em28xx chips.
index 0924550992d0e4f37781bf66b5166ef30ce9a8de..3d1c3cc337fe65c7407d728afab04990bdcd4e98 100644 (file)
@@ -5,6 +5,7 @@ em28xx-alsa-objs := em28xx-audio.o
 
 obj-$(CONFIG_VIDEO_EM28XX) += em28xx.o
 obj-$(CONFIG_VIDEO_EM28XX_ALSA) += em28xx-alsa.o
+obj-$(CONFIG_VIDEO_EM28XX_DVB) += em28xx-dvb.o
 
 EXTRA_CFLAGS += -Idrivers/media/video
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
index 8c67f678266aa83c35104e3f8f80e9e7395d8ebb..92b2a6db4fdc15edea12a61ccbdcfa522da7a534 100644 (file)
@@ -51,7 +51,7 @@ MODULE_PARM_DESC(debug, "activates debug info");
 #define dprintk(fmt, arg...) do {                                      \
            if (debug)                                                  \
                printk(KERN_INFO "em28xx-audio %s: " fmt,               \
-                                 __FUNCTION__, ##arg);                 \
+                                 __func__, ##arg);             \
        } while (0)
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
index aae7753fef117d1c7b12f0bcc30a83a1f018c19e..50ccf377120488e0d61a40776b4e2a162b529915 100644 (file)
@@ -36,7 +36,6 @@
 #include <media/v4l2-common.h>
 
 #include "em28xx.h"
-#include "tuner-xc2028.h"
 
 static int tuner = -1;
 module_param(tuner, int, 0444);
@@ -52,26 +51,6 @@ struct em28xx_hash_table {
        unsigned int  tuner;
 };
 
-/* Boards supported by driver */
-
-#define EM2800_BOARD_UNKNOWN                   0
-#define EM2820_BOARD_UNKNOWN                   1
-#define EM2820_BOARD_TERRATEC_CINERGY_250      2
-#define EM2820_BOARD_PINNACLE_USB_2            3
-#define EM2820_BOARD_HAUPPAUGE_WINTV_USB_2      4
-#define EM2820_BOARD_MSI_VOX_USB_2              5
-#define EM2800_BOARD_TERRATEC_CINERGY_200       6
-#define EM2800_BOARD_LEADTEK_WINFAST_USBII      7
-#define EM2800_BOARD_KWORLD_USB2800             8
-#define EM2820_BOARD_PINNACLE_DVC_90           9
-#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900   10
-#define EM2880_BOARD_TERRATEC_HYBRID_XS                11
-#define EM2820_BOARD_KWORLD_PVRTV2800RF                12
-#define EM2880_BOARD_TERRATEC_PRODIGY_XS       13
-#define EM2820_BOARD_PROLINK_PLAYTV_USB2       14
-#define EM2800_BOARD_VGEAR_POCKETTV             15
-#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950   16
-
 struct em28xx_board em28xx_boards[] = {
        [EM2800_BOARD_UNKNOWN] = {
                .name         = "Unknown EM2800 video grabber",
@@ -200,6 +179,7 @@ struct em28xx_board em28xx_boards[] = {
                .tuner_type     = TUNER_XC2028,
                .mts_firmware   = 1,
                .has_12mhz_i2s  = 1,
+               .has_dvb        = 1,
                .decoder        = EM28XX_TVP5150,
                .input          = { {
                        .type     = EM28XX_VMUX_TELEVISION,
@@ -214,9 +194,6 @@ struct em28xx_board em28xx_boards[] = {
                        .vmux     = TVP5150_SVIDEO,
                        .amux     = 1,
                } },
-
-               /* gpio's 4, 1, 0 */
-               .analog_gpio = 0x003d2d,
        },
        [EM2880_BOARD_TERRATEC_HYBRID_XS] = {
                .name         = "Terratec Hybrid XS",
@@ -331,7 +308,7 @@ struct em28xx_board em28xx_boards[] = {
                .name         = "Kworld USB2800",
                .is_em2800    = 1,
                .vchannels    = 3,
-               .tuner_type   = TUNER_PHILIPS_ATSC,
+               .tuner_type   = TUNER_PHILIPS_FCV1236D,
                .tda9887_conf = TDA9887_PRESENT,
                .decoder      = EM28XX_SAA7113,
                .input          = { {
@@ -453,7 +430,36 @@ struct usb_device_id em28xx_id_table [] = {
 };
 MODULE_DEVICE_TABLE(usb, em28xx_id_table);
 
-/* EEPROM hash table for devices with generic USB IDs */
+/*
+ *  Reset sequences for analog/digital modes
+ */
+
+/* Board Hauppauge WinTV HVR 900 analog */
+static struct em28xx_reg_seq hauppauge_wintv_hvr_900_analog[] = {
+       {EM28XX_R08_GPIO,       0x2d,   ~EM_GPIO_4,     10},
+       {0x05,                  0xff,   0x10,           10},
+       {  -1,                  -1,     -1,             -1},
+};
+
+/* Board Hauppauge WinTV HVR 900 digital */
+static struct em28xx_reg_seq hauppauge_wintv_hvr_900_digital[] = {
+       {EM28XX_R08_GPIO,       0x2e,   ~EM_GPIO_4,     10},
+       {EM2880_R04_GPO,        0x04,   0x0f,           10},
+       {EM2880_R04_GPO,        0x0c,   0x0f,           10},
+       { -1,                   -1,     -1,             -1},
+};
+
+/* Board Hauppauge WinTV HVR 900 tuner_callback */
+static struct em28xx_reg_seq hauppauge_wintv_hvr_900_tuner_callback[] = {
+       {EM28XX_R08_GPIO,       EM_GPIO_4,      EM_GPIO_4,      10},
+       {EM28XX_R08_GPIO,       0,              EM_GPIO_4,      10},
+       {EM28XX_R08_GPIO,       EM_GPIO_4,      EM_GPIO_4,      10},
+       {  -1,                  -1,             -1,             -1},
+};
+
+/*
+ * EEPROM hash table for devices with generic USB IDs
+ */
 static struct em28xx_hash_table em28xx_eeprom_hash [] = {
        /* P/N: SA 60002070465 Tuner: TVF7533-MF */
        {0x6ce05a8f, EM2820_BOARD_PROLINK_PLAYTV_USB2, TUNER_YMEC_TVF_5533MF},
@@ -465,79 +471,113 @@ static struct em28xx_hash_table em28xx_i2c_hash[] = {
        {0xf51200e3, EM2800_BOARD_VGEAR_POCKETTV, TUNER_LG_PAL_NEW_TAPC},
 };
 
+int em28xx_tuner_callback(void *ptr, int command, int arg)
+{
+       int rc = 0;
+       struct em28xx *dev = ptr;
+
+       if (dev->tuner_type != TUNER_XC2028)
+               return 0;
+
+       if (command != XC2028_TUNER_RESET)
+               return 0;
+
+       if (dev->mode == EM28XX_ANALOG_MODE)
+               rc = em28xx_gpio_set(dev, dev->tun_analog_gpio);
+       else
+               rc = em28xx_gpio_set(dev, dev->tun_digital_gpio);
+
+       return rc;
+}
+EXPORT_SYMBOL_GPL(em28xx_tuner_callback);
+
+static void em28xx_set_model(struct em28xx *dev)
+{
+       dev->is_em2800 = em28xx_boards[dev->model].is_em2800;
+       dev->has_msp34xx = em28xx_boards[dev->model].has_msp34xx;
+       dev->tda9887_conf = em28xx_boards[dev->model].tda9887_conf;
+       dev->decoder = em28xx_boards[dev->model].decoder;
+       dev->video_inputs = em28xx_boards[dev->model].vchannels;
+       dev->has_12mhz_i2s = em28xx_boards[dev->model].has_12mhz_i2s;
+       dev->max_range_640_480 = em28xx_boards[dev->model].max_range_640_480;
+       dev->has_dvb = em28xx_boards[dev->model].has_dvb;
+}
+
 /* Since em28xx_pre_card_setup() requires a proper dev->model,
  * this won't work for boards with generic PCI IDs
  */
 void em28xx_pre_card_setup(struct em28xx *dev)
 {
+       int rc;
+
+       rc = em28xx_read_reg(dev, EM2880_R04_GPO);
+       if (rc >= 0)
+               dev->reg_gpo = rc;
+
+       dev->wait_after_write = 5;
+       rc = em28xx_read_reg(dev, EM28XX_R0A_CHIPID);
+       if (rc > 0) {
+               switch (rc) {
+               case CHIP_ID_EM2883:
+                       em28xx_info("chip ID is em2882/em2883\n");
+                       dev->wait_after_write = 0;
+                       break;
+               default:
+                       em28xx_info("em28xx chip ID = %d\n", rc);
+               }
+       }
+       em28xx_set_model(dev);
+
        /* request some modules */
        switch (dev->model) {
        case EM2880_BOARD_TERRATEC_PRODIGY_XS:
        case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
-       case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950:
        case EM2880_BOARD_TERRATEC_HYBRID_XS:
-               em28xx_write_regs(dev, XCLK_REG, "\x27", 1);
-               em28xx_write_regs(dev, I2C_CLK_REG, "\x40", 1);
-               em28xx_write_regs(dev, 0x08, "\xff", 1);
-               em28xx_write_regs(dev, 0x04, "\x00", 1);
-               msleep(100);
-               em28xx_write_regs(dev, 0x04, "\x08", 1);
-               msleep(100);
-               em28xx_write_regs(dev, 0x08, "\xff", 1);
-               msleep(50);
-               em28xx_write_regs(dev, 0x08, "\x2d", 1);
+       case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950:
+               em28xx_write_regs(dev, EM28XX_R0F_XCLK,    "\x27", 1);
+               em28xx_write_regs(dev, EM28XX_R06_I2C_CLK, "\x40", 1);
                msleep(50);
-               em28xx_write_regs(dev, 0x08, "\x3d", 1);
+
+               /* Sets GPO/GPIO sequences for this device */
+               dev->analog_gpio      = hauppauge_wintv_hvr_900_analog;
+               dev->digital_gpio     = hauppauge_wintv_hvr_900_digital;
+               dev->tun_analog_gpio  = hauppauge_wintv_hvr_900_tuner_callback;
+               dev->tun_digital_gpio = hauppauge_wintv_hvr_900_tuner_callback;
+
                break;
        }
+
+       em28xx_gpio_set(dev, dev->tun_analog_gpio);
+       em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
+
+       /* Unlock device */
+       em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED);
 }
 
-static int em28xx_tuner_callback(void *ptr, int command, int arg)
+static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl)
 {
-       int rc = 0;
-       struct em28xx *dev = ptr;
+       memset(ctl, 0, sizeof(*ctl));
 
-       if (dev->tuner_type != TUNER_XC2028)
-               return 0;
-
-       switch (command) {
-       case XC2028_TUNER_RESET:
-       {
-               /* GPIO and initialization codes for analog TV and radio
-                  This code should be complemented for DTV, since reset
-                  codes are different.
-                */
-
-               dev->em28xx_write_regs_req(dev, 0x00, 0x48, "\x00", 1);
-               dev->em28xx_write_regs_req(dev, 0x00, 0x12, "\x67", 1);
-
-               if (dev->analog_gpio) {
-                       char gpio0 = dev->analog_gpio & 0xff;
-                       char gpio1 = (dev->analog_gpio >> 8) & 0xff;
-                       char gpio4 = dev->analog_gpio >> 24;
-
-                       if (gpio4) {
-                               dev->em28xx_write_regs(dev, 0x04, &gpio4, 1);
-                               msleep(140);
-                       }
-
-                       msleep(6);
-                       dev->em28xx_write_regs(dev, 0x08, &gpio0, 1);
-                       msleep(10);
-                       dev->em28xx_write_regs(dev, 0x08, &gpio1, 1);
-                       msleep(5);
-               }
+       ctl->fname   = XC2028_DEFAULT_FIRMWARE;
+       ctl->max_len = 64;
+       ctl->mts = em28xx_boards[dev->model].mts_firmware;
 
+       switch (dev->model) {
+       case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
+               ctl->demod = XC3028_FE_ZARLINK456;
                break;
+       case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950:
+               /* FIXME: Better to specify the needed IF */
+               ctl->demod = XC3028_FE_DEFAULT;
+               break;
+       default:
+               ctl->demod = XC3028_FE_OREN538;
        }
-       }
-       return rc;
 }
 
 static void em28xx_config_tuner(struct em28xx *dev)
 {
        struct v4l2_priv_tun_config  xc2028_cfg;
-       struct xc2028_ctrl           ctl;
        struct tuner_setup           tun_setup;
        struct v4l2_frequency        f;
 
@@ -552,11 +592,9 @@ static void em28xx_config_tuner(struct em28xx *dev)
        em28xx_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup);
 
        if (dev->tuner_type == TUNER_XC2028) {
-               memset(&ctl, 0, sizeof(ctl));
+               struct xc2028_ctrl           ctl;
 
-               ctl.fname   = XC2028_DEFAULT_FIRMWARE;
-               ctl.max_len = 64;
-               ctl.mts = em28xx_boards[dev->model].mts_firmware;
+               em28xx_setup_xc3028(dev, &ctl);
 
                xc2028_cfg.tuner = TUNER_XC2028;
                xc2028_cfg.priv  = &ctl;
@@ -654,19 +692,6 @@ static int em28xx_hint_board(struct em28xx *dev)
        return -1;
 }
 
-
-static void em28xx_set_model(struct em28xx *dev)
-{
-       dev->is_em2800 = em28xx_boards[dev->model].is_em2800;
-       dev->has_msp34xx = em28xx_boards[dev->model].has_msp34xx;
-       dev->tda9887_conf = em28xx_boards[dev->model].tda9887_conf;
-       dev->decoder = em28xx_boards[dev->model].decoder;
-       dev->video_inputs = em28xx_boards[dev->model].vchannels;
-       dev->analog_gpio = em28xx_boards[dev->model].analog_gpio;
-       dev->has_12mhz_i2s = em28xx_boards[dev->model].has_12mhz_i2s;
-       dev->max_range_640_480 = em28xx_boards[dev->model].max_range_640_480;
-}
-
 /* ----------------------------------------------------------------------- */
 void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir)
 {
index c1caaa855b99b16e9d09962a0000e5d48817bd5f..f8c41d8c74c4173be55d517b1647b2bf244d27bf 100644 (file)
 
 /* #define ENABLE_DEBUG_ISOC_FRAMES */
 
-static unsigned int core_debug = 0;
+static unsigned int core_debug;
 module_param(core_debug,int,0644);
 MODULE_PARM_DESC(core_debug,"enable debug messages [core]");
 
 #define em28xx_coredbg(fmt, arg...) do {\
        if (core_debug) \
                printk(KERN_INFO "%s %s :"fmt, \
-                        dev->name, __FUNCTION__ , ##arg); } while (0)
+                        dev->name, __func__ , ##arg); } while (0)
 
-static unsigned int reg_debug = 0;
+static unsigned int reg_debug;
 module_param(reg_debug,int,0644);
 MODULE_PARM_DESC(reg_debug,"enable debug messages [URB reg]");
 
 #define em28xx_regdbg(fmt, arg...) do {\
        if (reg_debug) \
                printk(KERN_INFO "%s %s :"fmt, \
-                        dev->name, __FUNCTION__ , ##arg); } while (0)
-
-static unsigned int isoc_debug = 0;
-module_param(isoc_debug,int,0644);
-MODULE_PARM_DESC(isoc_debug,"enable debug messages [isoc transfers]");
-
-#define em28xx_isocdbg(fmt, arg...) do {\
-       if (isoc_debug) \
-               printk(KERN_INFO "%s %s :"fmt, \
-                        dev->name, __FUNCTION__ , ##arg); } while (0)
+                        dev->name, __func__ , ##arg); } while (0)
 
 static int alt = EM28XX_PINOUT;
 module_param(alt, int, 0644);
 MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint");
 
-
-/*
- * em28xx_request_buffers()
- * allocate a number of buffers
- */
-u32 em28xx_request_buffers(struct em28xx *dev, u32 count)
-{
-       const size_t imagesize = PAGE_ALIGN(dev->frame_size);   /*needs to be page aligned cause the buffers can be mapped individually! */
-       void *buff = NULL;
-       u32 i;
-       em28xx_coredbg("requested %i buffers with size %zi\n",
-                       count, imagesize);
-       if (count > EM28XX_NUM_FRAMES)
-               count = EM28XX_NUM_FRAMES;
-
-       dev->num_frames = count;
-       while (dev->num_frames > 0) {
-               if ((buff = vmalloc_32(dev->num_frames * imagesize))) {
-                       memset(buff, 0, dev->num_frames * imagesize);
-                       break;
-               }
-               dev->num_frames--;
-       }
-
-       for (i = 0; i < dev->num_frames; i++) {
-               dev->frame[i].bufmem = buff + i * imagesize;
-               dev->frame[i].buf.index = i;
-               dev->frame[i].buf.m.offset = i * imagesize;
-               dev->frame[i].buf.length = dev->frame_size;
-               dev->frame[i].buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               dev->frame[i].buf.sequence = 0;
-               dev->frame[i].buf.field = V4L2_FIELD_NONE;
-               dev->frame[i].buf.memory = V4L2_MEMORY_MMAP;
-               dev->frame[i].buf.flags = 0;
-       }
-       return dev->num_frames;
-}
-
-/*
- * em28xx_queue_unusedframes()
- * add all frames that are not currently in use to the inbuffer queue
- */
-void em28xx_queue_unusedframes(struct em28xx *dev)
-{
-       unsigned long lock_flags;
-       u32 i;
-
-       for (i = 0; i < dev->num_frames; i++)
-               if (dev->frame[i].state == F_UNUSED) {
-                       dev->frame[i].state = F_QUEUED;
-                       spin_lock_irqsave(&dev->queue_lock, lock_flags);
-                       list_add_tail(&dev->frame[i].frame, &dev->inqueue);
-                       spin_unlock_irqrestore(&dev->queue_lock, lock_flags);
-               }
-}
-
-/*
- * em28xx_release_buffers()
- * free frame buffers
- */
-void em28xx_release_buffers(struct em28xx *dev)
-{
-       if (dev->num_frames) {
-               vfree(dev->frame[0].bufmem);
-               dev->num_frames = 0;
-       }
-}
+/* FIXME */
+#define em28xx_isocdbg(fmt, arg...) do {\
+       if (core_debug) \
+               printk(KERN_INFO "%s %s :"fmt, \
+                        dev->name, __func__ , ##arg); } while (0)
 
 /*
  * em28xx_read_reg_req()
@@ -148,11 +77,11 @@ int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg,
                              USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
                              0x0000, reg, buf, len, HZ);
 
-       if (reg_debug){
+       if (reg_debug) {
                printk(ret < 0 ? " failed!\n" : "%02x values: ", ret);
-               for (byte = 0; byte < len; byte++) {
+               for (byte = 0; byte < len; byte++)
                        printk(" %02x", (unsigned char)buf[byte]);
-               }
+
                printk("\n");
        }
 
@@ -205,7 +134,10 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf,
        unsigned char *bufs;
 
        if (dev->state & DEV_DISCONNECTED)
-               return(-ENODEV);
+               return -ENODEV;
+
+       if (len < 1)
+               return -EINVAL;
 
        bufs = kmalloc(len, GFP_KERNEL);
 
@@ -214,8 +146,8 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf,
        if (reg_debug) {
                int i;
                for (i = 0; i < len; ++i)
-                       printk (" %02x", (unsigned char)buf[i]);
-               printk ("\n");
+                       printk(" %02x", (unsigned char)buf[i]);
+               printk("\n");
        }
 
        if (!bufs)
@@ -224,14 +156,32 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf,
        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);
-       msleep(5);              /* FIXME: magic number */
+       if (dev->wait_after_write)
+               msleep(dev->wait_after_write);
+
        kfree(bufs);
        return ret;
 }
 
 int em28xx_write_regs(struct em28xx *dev, u16 reg, char *buf, int len)
 {
-       return em28xx_write_regs_req(dev, USB_REQ_GET_STATUS, reg, buf, len);
+       int rc;
+
+       rc = em28xx_write_regs_req(dev, USB_REQ_GET_STATUS, reg, buf, len);
+
+       /* Stores GPO/GPIO values at the cache, if changed
+          Only write values should be stored, since input on a GPIO
+          register will return the input bits.
+          Not sure what happens on reading GPO register.
+        */
+       if (rc >= 0) {
+               if (reg == EM2880_R04_GPO)
+                       dev->reg_gpo = buf[0];
+               else if (reg == EM28XX_R08_GPIO)
+                       dev->reg_gpio = buf[0];
+       }
+
+       return rc;
 }
 
 /*
@@ -244,9 +194,20 @@ static int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val,
 {
        int oldval;
        u8 newval;
-       if ((oldval = em28xx_read_reg(dev, reg)) < 0)
+
+       /* Uses cache for gpo/gpio registers */
+       if (reg == EM2880_R04_GPO)
+               oldval = dev->reg_gpo;
+       else if (reg == EM28XX_R08_GPIO)
+               oldval = dev->reg_gpio;
+       else
+               oldval = em28xx_read_reg(dev, reg);
+
+       if (oldval < 0)
                return oldval;
+
        newval = (((u8) oldval) & ~bitmask) | (val & bitmask);
+
        return em28xx_write_regs(dev, reg, &newval, 1);
 }
 
@@ -258,20 +219,26 @@ static int em28xx_write_ac97(struct em28xx *dev, u8 reg, u8 *val)
 {
        int ret, i;
        u8 addr = reg & 0x7f;
-       if ((ret = em28xx_write_regs(dev, AC97LSB_REG, val, 2)) < 0)
+
+       ret = em28xx_write_regs(dev, EM28XX_R40_AC97LSB, val, 2);
+       if (ret < 0)
                return ret;
-       if ((ret = em28xx_write_regs(dev, AC97ADDR_REG, &addr, 1)) < 0)
+
+       ret = em28xx_write_regs(dev, EM28XX_R42_AC97ADDR, &addr, 1);
+       if (ret < 0)
                return ret;
 
        /* Wait up to 50 ms for AC97 command to complete */
        for (i = 0; i < 10; i++) {
-               if ((ret = em28xx_read_reg(dev, AC97BUSY_REG)) < 0)
+               ret = em28xx_read_reg(dev, EM28XX_R43_AC97BUSY);
+               if (ret < 0)
                        return ret;
+
                if (!(ret & 0x01))
                        return 0;
                msleep(5);
        }
-       em28xx_warn ("AC97 command still being executed: not handled properly!\n");
+       em28xx_warn("AC97 command still being executed: not handled properly!\n");
        return 0;
 }
 
@@ -289,7 +256,7 @@ static int em28xx_set_audio_source(struct em28xx *dev)
                else
                        input = EM2800_AUDIO_SRC_TUNER;
 
-               ret = em28xx_write_regs(dev, EM2800_AUDIOSRC_REG, &input, 1);
+               ret = em28xx_write_regs(dev, EM2800_R08_AUDIOSRC, &input, 1);
                if (ret < 0)
                        return ret;
        }
@@ -315,7 +282,7 @@ static int em28xx_set_audio_source(struct em28xx *dev)
                }
        }
 
-       ret = em28xx_write_reg_bits(dev, AUDIOSRC_REG, input, 0xc0);
+       ret = em28xx_write_reg_bits(dev, EM28XX_R0E_AUDIOSRC, input, 0xc0);
        if (ret < 0)
                return ret;
        msleep(5);
@@ -323,11 +290,11 @@ static int em28xx_set_audio_source(struct em28xx *dev)
        /* Sets AC97 mixer registers
           This is seems to be needed, even for non-ac97 configs
         */
-       ret = em28xx_write_ac97(dev, VIDEO_AC97, video);
+       ret = em28xx_write_ac97(dev, EM28XX_R14_VIDEO_AC97, video);
        if (ret < 0)
                return ret;
 
-       ret = em28xx_write_ac97(dev, LINE_IN_AC97, line);
+       ret = em28xx_write_ac97(dev, EM28XX_R10_LINE_IN_AC97, line);
 
        return ret;
 }
@@ -343,7 +310,7 @@ int em28xx_audio_analog_set(struct em28xx *dev)
 
        /* Mute */
        s[1] |= 0x80;
-       ret = em28xx_write_ac97(dev, MASTER_AC97, s);
+       ret = em28xx_write_ac97(dev, EM28XX_R02_MASTER_AC97, s);
 
        if (ret < 0)
                return ret;
@@ -354,7 +321,7 @@ int em28xx_audio_analog_set(struct em28xx *dev)
        if (!dev->mute)
                xclk |= 0x80;
 
-       ret = em28xx_write_reg_bits(dev, XCLK_REG, xclk, 0xa7);
+       ret = em28xx_write_reg_bits(dev, EM28XX_R0F_XCLK, xclk, 0xa7);
        if (ret < 0)
                return ret;
        msleep(10);
@@ -365,7 +332,7 @@ int em28xx_audio_analog_set(struct em28xx *dev)
        /* Unmute device */
        if (!dev->mute)
                s[1] &= ~0x80;
-       ret = em28xx_write_ac97(dev, MASTER_AC97, s);
+       ret = em28xx_write_ac97(dev, EM28XX_R02_MASTER_AC97, s);
 
        return ret;
 }
@@ -373,50 +340,68 @@ EXPORT_SYMBOL_GPL(em28xx_audio_analog_set);
 
 int em28xx_colorlevels_set_default(struct em28xx *dev)
 {
-       em28xx_write_regs(dev, YGAIN_REG, "\x10", 1);   /* contrast */
-       em28xx_write_regs(dev, YOFFSET_REG, "\x00", 1); /* brightness */
-       em28xx_write_regs(dev, UVGAIN_REG, "\x10", 1);  /* saturation */
-       em28xx_write_regs(dev, UOFFSET_REG, "\x00", 1);
-       em28xx_write_regs(dev, VOFFSET_REG, "\x00", 1);
-       em28xx_write_regs(dev, SHARPNESS_REG, "\x00", 1);
-
-       em28xx_write_regs(dev, GAMMA_REG, "\x20", 1);
-       em28xx_write_regs(dev, RGAIN_REG, "\x20", 1);
-       em28xx_write_regs(dev, GGAIN_REG, "\x20", 1);
-       em28xx_write_regs(dev, BGAIN_REG, "\x20", 1);
-       em28xx_write_regs(dev, ROFFSET_REG, "\x00", 1);
-       em28xx_write_regs(dev, GOFFSET_REG, "\x00", 1);
-       return em28xx_write_regs(dev, BOFFSET_REG, "\x00", 1);
+       em28xx_write_regs(dev, EM28XX_R20_YGAIN, "\x10", 1);    /* contrast */
+       em28xx_write_regs(dev, EM28XX_R21_YOFFSET, "\x00", 1);  /* brightness */
+       em28xx_write_regs(dev, EM28XX_R22_UVGAIN, "\x10", 1);   /* saturation */
+       em28xx_write_regs(dev, EM28XX_R23_UOFFSET, "\x00", 1);
+       em28xx_write_regs(dev, EM28XX_R24_VOFFSET, "\x00", 1);
+       em28xx_write_regs(dev, EM28XX_R25_SHARPNESS, "\x00", 1);
+
+       em28xx_write_regs(dev, EM28XX_R14_GAMMA, "\x20", 1);
+       em28xx_write_regs(dev, EM28XX_R15_RGAIN, "\x20", 1);
+       em28xx_write_regs(dev, EM28XX_R16_GGAIN, "\x20", 1);
+       em28xx_write_regs(dev, EM28XX_R17_BGAIN, "\x20", 1);
+       em28xx_write_regs(dev, EM28XX_R18_ROFFSET, "\x00", 1);
+       em28xx_write_regs(dev, EM28XX_R19_GOFFSET, "\x00", 1);
+       return em28xx_write_regs(dev, EM28XX_R1A_BOFFSET, "\x00", 1);
 }
 
 int em28xx_capture_start(struct em28xx *dev, int start)
 {
-       int ret;
+       int rc;
        /* FIXME: which is the best order? */
        /* video registers are sampled by VREF */
-       if ((ret = em28xx_write_reg_bits(dev, USBSUSP_REG, start ? 0x10 : 0x00,
-                                         0x10)) < 0)
-               return ret;
+       rc = em28xx_write_reg_bits(dev, EM28XX_R0C_USBSUSP,
+                                  start ? 0x10 : 0x00, 0x10);
+       if (rc < 0)
+               return rc;
+
+       if (!start) {
+               /* disable video capture */
+               rc = em28xx_write_regs(dev, EM28XX_R12_VINENABLE, "\x27", 1);
+               return rc;
+       }
+
        /* enable video capture */
-       return em28xx_write_regs(dev, VINENABLE_REG, start ? "\x67" : "\x27", 1);
+       rc = em28xx_write_regs_req(dev, 0x00, 0x48, "\x00", 1);
+
+       if (dev->mode == EM28XX_ANALOG_MODE)
+               rc = em28xx_write_regs(dev, EM28XX_R12_VINENABLE, "\x67", 1);
+       else
+               rc = em28xx_write_regs(dev, EM28XX_R12_VINENABLE, "\x37", 1);
+
+       msleep(6);
+
+       return rc;
 }
 
 int em28xx_outfmt_set_yuv422(struct em28xx *dev)
 {
-       em28xx_write_regs(dev, OUTFMT_REG, "\x34", 1);
-       em28xx_write_regs(dev, VINMODE_REG, "\x10", 1);
-       return em28xx_write_regs(dev, VINCTRL_REG, "\x11", 1);
+       em28xx_write_regs(dev, EM28XX_R27_OUTFMT, "\x34", 1);
+       em28xx_write_regs(dev, EM28XX_R10_VINMODE, "\x10", 1);
+       return em28xx_write_regs(dev, EM28XX_R11_VINCTRL, "\x11", 1);
 }
 
 static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax,
                                  u8 ymin, u8 ymax)
 {
-       em28xx_coredbg("em28xx Scale: (%d,%d)-(%d,%d)\n", xmin, ymin, xmax, ymax);
+       em28xx_coredbg("em28xx Scale: (%d,%d)-(%d,%d)\n",
+                       xmin, ymin, xmax, ymax);
 
-       em28xx_write_regs(dev, XMIN_REG, &xmin, 1);
-       em28xx_write_regs(dev, XMAX_REG, &xmax, 1);
-       em28xx_write_regs(dev, YMIN_REG, &ymin, 1);
-       return em28xx_write_regs(dev, YMAX_REG, &ymax, 1);
+       em28xx_write_regs(dev, EM28XX_R28_XMIN, &xmin, 1);
+       em28xx_write_regs(dev, EM28XX_R29_XMAX, &xmax, 1);
+       em28xx_write_regs(dev, EM28XX_R2A_YMIN, &ymin, 1);
+       return em28xx_write_regs(dev, EM28XX_R2B_YMAX, &ymax, 1);
 }
 
 static int em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart,
@@ -426,34 +411,36 @@ static int em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart,
        u8 cheight = height;
        u8 overflow = (height >> 7 & 0x02) | (width >> 8 & 0x01);
 
-       em28xx_coredbg("em28xx Area Set: (%d,%d)\n", (width | (overflow & 2) << 7),
+       em28xx_coredbg("em28xx Area Set: (%d,%d)\n",
+                       (width | (overflow & 2) << 7),
                        (height | (overflow & 1) << 8));
 
-       em28xx_write_regs(dev, HSTART_REG, &hstart, 1);
-       em28xx_write_regs(dev, VSTART_REG, &vstart, 1);
-       em28xx_write_regs(dev, CWIDTH_REG, &cwidth, 1);
-       em28xx_write_regs(dev, CHEIGHT_REG, &cheight, 1);
-       return em28xx_write_regs(dev, OFLOW_REG, &overflow, 1);
+       em28xx_write_regs(dev, EM28XX_R1C_HSTART, &hstart, 1);
+       em28xx_write_regs(dev, EM28XX_R1D_VSTART, &vstart, 1);
+       em28xx_write_regs(dev, EM28XX_R1E_CWIDTH, &cwidth, 1);
+       em28xx_write_regs(dev, EM28XX_R1F_CHEIGHT, &cheight, 1);
+       return em28xx_write_regs(dev, EM28XX_R1B_OFLOW, &overflow, 1);
 }
 
 static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v)
 {
        u8 mode;
        /* the em2800 scaler only supports scaling down to 50% */
-       if(dev->is_em2800)
+       if (dev->is_em2800)
                mode = (v ? 0x20 : 0x00) | (h ? 0x10 : 0x00);
        else {
                u8 buf[2];
                buf[0] = h;
                buf[1] = h >> 8;
-               em28xx_write_regs(dev, HSCALELOW_REG, (char *)buf, 2);
+               em28xx_write_regs(dev, EM28XX_R30_HSCALELOW, (char *)buf, 2);
                buf[0] = v;
                buf[1] = v >> 8;
-               em28xx_write_regs(dev, VSCALELOW_REG, (char *)buf, 2);
-               /* it seems that both H and V scalers must be active to work correctly */
+               em28xx_write_regs(dev, EM28XX_R32_VSCALELOW, (char *)buf, 2);
+               /* it seems that both H and V scalers must be active
+                  to work correctly */
                mode = (h || v)? 0x30: 0x00;
        }
-       return em28xx_write_reg_bits(dev, COMPR_REG, mode, 0x30);
+       return em28xx_write_reg_bits(dev, EM28XX_R26_COMPR, mode, 0x30);
 }
 
 /* FIXME: this only function read values from dev */
@@ -469,376 +456,271 @@ int em28xx_resolution_set(struct em28xx *dev)
        return em28xx_scaler_set(dev, dev->hscale, dev->vscale);
 }
 
-
-/******************* isoc transfer handling ****************************/
-
-#ifdef ENABLE_DEBUG_ISOC_FRAMES
-static void em28xx_isoc_dump(struct urb *urb)
+int em28xx_set_alternate(struct em28xx *dev)
 {
-       int len = 0;
-       int ntrans = 0;
+       int errCode, prev_alt = dev->alt;
        int i;
+       unsigned int min_pkt_size = dev->width * 2 + 4;
 
-       printk(KERN_DEBUG "isocIrq: sf=%d np=%d ec=%x\n",
-              urb->start_frame, urb->number_of_packets,
-              urb->error_count);
-       for (i = 0; i < urb->number_of_packets; i++) {
-               unsigned char *buf =
-                               urb->transfer_buffer +
-                               urb->iso_frame_desc[i].offset;
-               int alen = urb->iso_frame_desc[i].actual_length;
-               if (alen > 0) {
-                       if (buf[0] == 0x88) {
-                               ntrans++;
-                               len += alen;
-                       } else if (buf[0] == 0x22) {
-                               printk(KERN_DEBUG
-                                               "= l=%d nt=%d bpp=%d\n",
-                               len - 4 * ntrans, ntrans,
-                               ntrans == 0 ? 0 : len / ntrans);
-                               ntrans = 1;
-                               len = alen;
-                       } else
-                               printk(KERN_DEBUG "!\n");
+       /* When image size is bigger than a certain value,
+          the frame size should be increased, otherwise, only
+          green screen will be received.
+        */
+       if (dev->width * 2 * dev->height > 720 * 240 * 2)
+               min_pkt_size *= 2;
+
+       for (i = 0; i < dev->num_alt; i++) {
+               /* stop when the selected alt setting offers enough bandwidth */
+               if (dev->alt_max_pkt_size[i] >= min_pkt_size) {
+                       dev->alt = i;
+                       break;
+               /* otherwise make sure that we end up with the maximum bandwidth
+                  because the min_pkt_size equation might be wrong...
+               */
+               } else if (dev->alt_max_pkt_size[i] >
+                          dev->alt_max_pkt_size[dev->alt])
+                       dev->alt = i;
+       }
+
+       if (dev->alt != prev_alt) {
+               em28xx_coredbg("minimum isoc packet size: %u (alt=%d)\n",
+                               min_pkt_size, dev->alt);
+               dev->max_pkt_size = dev->alt_max_pkt_size[dev->alt];
+               em28xx_coredbg("setting alternate %d with wMaxPacketSize=%u\n",
+                              dev->alt, dev->max_pkt_size);
+               errCode = usb_set_interface(dev->udev, 0, dev->alt);
+               if (errCode < 0) {
+                       em28xx_errdev("cannot change alternate number to %d (error=%i)\n",
+                                       dev->alt, errCode);
+                       return errCode;
                }
-               printk(KERN_DEBUG "   n=%d s=%d al=%d %x\n", i,
-                      urb->iso_frame_desc[i].status,
-                      urb->iso_frame_desc[i].actual_length,
-                      (unsigned int)
-                                      *((unsigned char *)(urb->transfer_buffer +
-                                      urb->iso_frame_desc[i].
-                                      offset)));
        }
+       return 0;
 }
-#endif
 
-static inline int em28xx_isoc_video(struct em28xx *dev,struct em28xx_frame_t **f,
-                                   unsigned long *lock_flags, unsigned char buf)
+int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio)
 {
-       if (!(buf & 0x01)) {
-               if ((*f)->state == F_GRABBING) {
-                       /*previous frame is incomplete */
-                       if ((*f)->fieldbytesused < dev->field_size) {
-                               (*f)->state = F_ERROR;
-                               em28xx_isocdbg ("dropping incomplete bottom field (%i missing bytes)",
-                                        dev->field_size-(*f)->fieldbytesused);
-                       } else {
-                               (*f)->state = F_DONE;
-                               (*f)->buf.bytesused = dev->frame_size;
-                       }
-               }
-               if ((*f)->state == F_DONE || (*f)->state == F_ERROR) {
-                       /* move current frame to outqueue and get next free buffer from inqueue */
-                       spin_lock_irqsave(&dev-> queue_lock, *lock_flags);
-                       list_move_tail(&(*f)->frame, &dev->outqueue);
-                       if (!list_empty(&dev->inqueue))
-                               (*f) = list_entry(dev-> inqueue.next,
-                       struct em28xx_frame_t,frame);
-                       else
-                               (*f) = NULL;
-                       spin_unlock_irqrestore(&dev->queue_lock,*lock_flags);
-               }
-               if (!(*f)) {
-                       em28xx_isocdbg ("new frame but no buffer is free");
-                       return -1;
-               }
-               do_gettimeofday(&(*f)->buf.timestamp);
-               (*f)->buf.sequence = ++dev->frame_count;
-               (*f)->buf.field = V4L2_FIELD_INTERLACED;
-               (*f)->state = F_GRABBING;
-               (*f)->buf.bytesused = 0;
-               (*f)->top_field = 1;
-               (*f)->fieldbytesused = 0;
-       } else {
-                                       /* acquiring bottom field */
-               if ((*f)->state == F_GRABBING) {
-                       if (!(*f)->top_field) {
-                               (*f)->state = F_ERROR;
-                               em28xx_isocdbg ("unexpected begin of bottom field; discarding it");
-                       } else if ((*f)-> fieldbytesused < dev->field_size - 172) {
-                               (*f)->state = F_ERROR;
-                               em28xx_isocdbg ("dropping incomplete top field (%i missing bytes)",
-                                        dev->field_size-(*f)->fieldbytesused);
-                       } else {
-                               (*f)->top_field = 0;
-                               (*f)->fieldbytesused = 0;
-                       }
+       int rc = 0;
+
+       if (!gpio)
+               return rc;
+
+       dev->em28xx_write_regs_req(dev, 0x00, 0x48, "\x00", 1);
+       if (dev->mode == EM28XX_ANALOG_MODE)
+               dev->em28xx_write_regs_req(dev, 0x00, 0x12, "\x67", 1);
+       else
+               dev->em28xx_write_regs_req(dev, 0x00, 0x12, "\x37", 1);
+       msleep(6);
+
+       /* Send GPIO reset sequences specified at board entry */
+       while (gpio->sleep >= 0) {
+               if (gpio->reg >= 0) {
+                       rc = em28xx_write_reg_bits(dev,
+                                                  gpio->reg,
+                                                  gpio->val,
+                                                  gpio->mask);
+                       if (rc < 0)
+                               return rc;
                }
+               if (gpio->sleep > 0)
+                       msleep(gpio->sleep);
+
+               gpio++;
        }
-       return (0);
+       return rc;
 }
 
-static inline void em28xx_isoc_video_copy(struct em28xx *dev,
-                                         struct em28xx_frame_t **f, unsigned char *buf, int len)
+int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode)
 {
-       void *fieldstart, *startwrite, *startread;
-       int linesdone, currlinedone, offset, lencopy,remain;
+       if (dev->mode == set_mode)
+               return 0;
 
-       if(dev->frame_size != (*f)->buf.length){
-               em28xx_err("frame_size %i and buf.length %i are different!!!\n",dev->frame_size,(*f)->buf.length);
-               return;
+       if (set_mode == EM28XX_MODE_UNDEFINED) {
+               dev->mode = set_mode;
+               return 0;
        }
 
-       if ((*f)->fieldbytesused + len > dev->field_size)
-               len =dev->field_size - (*f)->fieldbytesused;
-
-       if (buf[0] != 0x88 && buf[0] != 0x22) {
-               em28xx_isocdbg("frame is not complete\n");
-               startread = buf;
-               len+=4;
-       } else
-               startread = buf + 4;
-
-       remain = len;
+       dev->mode = set_mode;
 
-       if ((*f)->top_field)
-               fieldstart = (*f)->bufmem;
+       if (dev->mode == EM28XX_DIGITAL_MODE)
+               return em28xx_gpio_set(dev, dev->digital_gpio);
        else
-               fieldstart = (*f)->bufmem + dev->bytesperline;
-
-       linesdone = (*f)->fieldbytesused / dev->bytesperline;
-       currlinedone = (*f)->fieldbytesused % dev->bytesperline;
-       offset = linesdone * dev->bytesperline * 2 + currlinedone;
-       startwrite = fieldstart + offset;
-       lencopy = dev->bytesperline - currlinedone;
-       lencopy = lencopy > remain ? remain : lencopy;
-
-       memcpy(startwrite, startread, lencopy);
-       remain -= lencopy;
-
-       while (remain > 0) {
-               startwrite += lencopy + dev->bytesperline;
-               startread += lencopy;
-               if (dev->bytesperline > remain)
-                       lencopy = remain;
-               else
-                       lencopy = dev->bytesperline;
-
-               memcpy(startwrite, startread, lencopy);
-               remain -= lencopy;
-       }
-
-       (*f)->fieldbytesused += len;
+               return em28xx_gpio_set(dev, dev->analog_gpio);
 }
+EXPORT_SYMBOL_GPL(em28xx_set_mode);
+
+/* ------------------------------------------------------------------
+       URB control
+   ------------------------------------------------------------------*/
 
 /*
- * em28xx_isoIrq()
- * handles the incoming isoc urbs and fills the frames from our inqueue
+ * IRQ callback, called by URB callback
  */
-static void em28xx_isocIrq(struct urb *urb)
+static void em28xx_irq_callback(struct urb *urb)
 {
-       struct em28xx *dev = urb->context;
-       int i, status;
-       struct em28xx_frame_t **f;
-       unsigned long lock_flags;
-
-       if (!dev)
-               return;
-#ifdef ENABLE_DEBUG_ISOC_FRAMES
-       if (isoc_debug>1)
-               em28xx_isoc_dump(urb);
-#endif
-
-       if (urb->status == -ENOENT)
-               return;
-
-       f = &dev->frame_current;
-
-       if (dev->stream == STREAM_INTERRUPT) {
-               dev->stream = STREAM_OFF;
-               if ((*f))
-                       (*f)->state = F_QUEUED;
-               em28xx_isocdbg("stream interrupted");
-               wake_up_interruptible(&dev->wait_stream);
-       }
-
-       if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
-               return;
-
-       if (dev->stream == STREAM_ON && !list_empty(&dev->inqueue)) {
-               if (!(*f))
-                       (*f) = list_entry(dev->inqueue.next,
-               struct em28xx_frame_t, frame);
-
-               for (i = 0; i < urb->number_of_packets; i++) {
-                       unsigned char *buf = urb->transfer_buffer +
-                                       urb->iso_frame_desc[i].offset;
-                       int len = urb->iso_frame_desc[i].actual_length - 4;
-
-                       if (urb->iso_frame_desc[i].status) {
-                               em28xx_isocdbg("data error: [%d] len=%d, status=%d", i,
-                                       urb->iso_frame_desc[i].actual_length,
-                                       urb->iso_frame_desc[i].status);
-                               if (urb->iso_frame_desc[i].status != -EPROTO)
-                                       continue;
-                       }
-                       if (urb->iso_frame_desc[i].actual_length <= 0) {
-                               em28xx_isocdbg("packet %d is empty",i);
-                               continue;
-                       }
-                       if (urb->iso_frame_desc[i].actual_length >
-                           urb->iso_frame_desc[i].length) {
-                               em28xx_isocdbg("packet bigger than packet size");
-                               continue;
-                       }
-                       /*new frame */
-                       if (buf[0] == 0x22 && buf[1] == 0x5a) {
-                               em28xx_isocdbg("Video frame, length=%i!",len);
-
-                               if (em28xx_isoc_video(dev,f,&lock_flags,buf[2]))
-                               break;
-                       } else if (buf[0]==0x33 && buf[1]==0x95 && buf[2]==0x00) {
-                               em28xx_isocdbg("VBI HEADER!!!");
-                       }
+       struct em28xx_dmaqueue  *dma_q = urb->context;
+       struct em28xx *dev = container_of(dma_q, struct em28xx, vidq);
+       int rc, i;
 
-                       /* actual copying */
-                       if ((*f)->state == F_GRABBING) {
-                               em28xx_isoc_video_copy(dev,f,buf, len);
-                       }
-               }
-       }
+       /* Copy data from URB */
+       spin_lock(&dev->slock);
+       rc = dev->isoc_ctl.isoc_copy(dev, urb);
+       spin_unlock(&dev->slock);
 
+       /* Reset urb buffers */
        for (i = 0; i < urb->number_of_packets; i++) {
                urb->iso_frame_desc[i].status = 0;
                urb->iso_frame_desc[i].actual_length = 0;
        }
-
        urb->status = 0;
-       if ((status = usb_submit_urb(urb, GFP_ATOMIC))) {
-               em28xx_errdev("resubmit of urb failed (error=%i)\n", status);
-               dev->state |= DEV_MISCONFIGURED;
+
+       urb->status = usb_submit_urb(urb, GFP_ATOMIC);
+       if (urb->status) {
+               em28xx_isocdbg("urb resubmit failed (error=%i)\n",
+                              urb->status);
        }
-       wake_up_interruptible(&dev->wait_frame);
-       return;
 }
 
 /*
- * em28xx_uninit_isoc()
- * deallocates the buffers and urbs allocated during em28xx_init_iosc()
+ * Stop and Deallocate URBs
  */
 void em28xx_uninit_isoc(struct em28xx *dev)
 {
+       struct urb *urb;
        int i;
 
-       for (i = 0; i < EM28XX_NUM_BUFS; i++) {
-               if (dev->urb[i]) {
-                       usb_kill_urb(dev->urb[i]);
-                       if (dev->transfer_buffer[i]) {
+       em28xx_isocdbg("em28xx: called em28xx_uninit_isoc\n");
+
+       dev->isoc_ctl.nfields = -1;
+       for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
+               urb = dev->isoc_ctl.urb[i];
+               if (urb) {
+                       usb_kill_urb(urb);
+                       usb_unlink_urb(urb);
+                       if (dev->isoc_ctl.transfer_buffer[i]) {
                                usb_buffer_free(dev->udev,
-                                               dev->urb[i]->transfer_buffer_length,
-                                               dev->transfer_buffer[i],
-                                               dev->urb[i]->transfer_dma);
+                                       urb->transfer_buffer_length,
+                                       dev->isoc_ctl.transfer_buffer[i],
+                                       urb->transfer_dma);
                        }
-                       usb_free_urb(dev->urb[i]);
+                       usb_free_urb(urb);
+                       dev->isoc_ctl.urb[i] = NULL;
                }
-               dev->urb[i] = NULL;
-               dev->transfer_buffer[i] = NULL;
+               dev->isoc_ctl.transfer_buffer[i] = NULL;
        }
+
+       kfree(dev->isoc_ctl.urb);
+       kfree(dev->isoc_ctl.transfer_buffer);
+
+       dev->isoc_ctl.urb = NULL;
+       dev->isoc_ctl.transfer_buffer = NULL;
+       dev->isoc_ctl.num_bufs = 0;
+
        em28xx_capture_start(dev, 0);
 }
+EXPORT_SYMBOL_GPL(em28xx_uninit_isoc);
 
 /*
- * em28xx_init_isoc()
- * allocates transfer buffers and submits the urbs for isoc transfer
+ * Allocate URBs and start IRQ
  */
-int em28xx_init_isoc(struct em28xx *dev)
+int em28xx_init_isoc(struct em28xx *dev, int max_packets,
+                    int num_bufs, int max_pkt_size,
+                    int (*isoc_copy) (struct em28xx *dev, struct urb *urb))
 {
-       /* change interface to 3 which allows the biggest packet sizes */
-       int i, errCode;
-       int sb_size;
-
-       em28xx_set_alternate(dev);
-       sb_size = EM28XX_NUM_PACKETS * dev->max_pkt_size;
-
-       /* reset streaming vars */
-       dev->frame_current = NULL;
-       dev->frame_count = 0;
-
-       /* allocate urbs */
-       for (i = 0; i < EM28XX_NUM_BUFS; i++) {
-               struct urb *urb;
-               int j;
-               /* allocate transfer buffer */
-               urb = usb_alloc_urb(EM28XX_NUM_PACKETS, GFP_KERNEL);
-               if (!urb){
-                       em28xx_errdev("cannot alloc urb %i\n", i);
+       struct em28xx_dmaqueue *dma_q = &dev->vidq;
+       int i;
+       int sb_size, pipe;
+       struct urb *urb;
+       int j, k;
+       int rc;
+
+       em28xx_isocdbg("em28xx: called em28xx_prepare_isoc\n");
+
+       /* De-allocates all pending stuff */
+       em28xx_uninit_isoc(dev);
+
+       dev->isoc_ctl.isoc_copy = isoc_copy;
+       dev->isoc_ctl.num_bufs = num_bufs;
+
+       dev->isoc_ctl.urb = kzalloc(sizeof(void *)*num_bufs,  GFP_KERNEL);
+       if (!dev->isoc_ctl.urb) {
+               em28xx_errdev("cannot alloc memory for usb buffers\n");
+               return -ENOMEM;
+       }
+
+       dev->isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs,
+                                             GFP_KERNEL);
+       if (!dev->isoc_ctl.urb) {
+               em28xx_errdev("cannot allocate memory for usbtransfer\n");
+               kfree(dev->isoc_ctl.urb);
+               return -ENOMEM;
+       }
+
+       dev->isoc_ctl.max_pkt_size = max_pkt_size;
+       dev->isoc_ctl.buf = NULL;
+
+       sb_size = max_packets * dev->isoc_ctl.max_pkt_size;
+
+       /* allocate urbs and transfer buffers */
+       for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
+               urb = usb_alloc_urb(max_packets, GFP_KERNEL);
+               if (!urb) {
+                       em28xx_err("cannot alloc isoc_ctl.urb %i\n", i);
                        em28xx_uninit_isoc(dev);
                        return -ENOMEM;
                }
-               dev->transfer_buffer[i] = usb_buffer_alloc(dev->udev, sb_size,
-                                                          GFP_KERNEL,
-                                                          &urb->transfer_dma);
-               if (!dev->transfer_buffer[i]) {
-                       em28xx_errdev
-                                       ("unable to allocate %i bytes for transfer buffer %i\n",
-                                        sb_size, i);
+               dev->isoc_ctl.urb[i] = urb;
+
+               dev->isoc_ctl.transfer_buffer[i] = usb_buffer_alloc(dev->udev,
+                       sb_size, GFP_KERNEL, &urb->transfer_dma);
+               if (!dev->isoc_ctl.transfer_buffer[i]) {
+                       em28xx_err("unable to allocate %i bytes for transfer"
+                                       " buffer %i%s\n",
+                                       sb_size, i,
+                                       in_interrupt()?" while in int":"");
                        em28xx_uninit_isoc(dev);
-                       usb_free_urb(urb);
                        return -ENOMEM;
                }
-               memset(dev->transfer_buffer[i], 0, sb_size);
-               urb->dev = dev->udev;
-               urb->context = dev;
-               urb->pipe = usb_rcvisocpipe(dev->udev, 0x82);
-               urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
-               urb->interval = 1;
-               urb->transfer_buffer = dev->transfer_buffer[i];
-               urb->complete = em28xx_isocIrq;
-               urb->number_of_packets = EM28XX_NUM_PACKETS;
-               urb->transfer_buffer_length = sb_size;
-               for (j = 0; j < EM28XX_NUM_PACKETS; j++) {
-                       urb->iso_frame_desc[j].offset = j * dev->max_pkt_size;
-                       urb->iso_frame_desc[j].length = dev->max_pkt_size;
+               memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size);
+
+               /* FIXME: this is a hack - should be
+                       'desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK'
+                       should also be using 'desc.bInterval'
+                */
+               pipe = usb_rcvisocpipe(dev->udev,
+                       dev->mode == EM28XX_ANALOG_MODE ? 0x82 : 0x84);
+
+               usb_fill_int_urb(urb, dev->udev, pipe,
+                                dev->isoc_ctl.transfer_buffer[i], sb_size,
+                                em28xx_irq_callback, dma_q, 1);
+
+               urb->number_of_packets = max_packets;
+               urb->transfer_flags = URB_ISO_ASAP;
+
+               k = 0;
+               for (j = 0; j < max_packets; j++) {
+                       urb->iso_frame_desc[j].offset = k;
+                       urb->iso_frame_desc[j].length =
+                                               dev->isoc_ctl.max_pkt_size;
+                       k += dev->isoc_ctl.max_pkt_size;
                }
-               dev->urb[i] = urb;
        }
 
-       /* submit urbs */
-       em28xx_coredbg("Submitting %d urbs of %d packets (%d each)\n",
-                      EM28XX_NUM_BUFS, EM28XX_NUM_PACKETS, dev->max_pkt_size);
-       for (i = 0; i < EM28XX_NUM_BUFS; i++) {
-               errCode = usb_submit_urb(dev->urb[i], GFP_KERNEL);
-               if (errCode) {
-                       em28xx_errdev("submit of urb %i failed (error=%i)\n", i,
-                                     errCode);
-                       em28xx_uninit_isoc(dev);
-                       return errCode;
-               }
-       }
-
-       return 0;
-}
-
-int em28xx_set_alternate(struct em28xx *dev)
-{
-       int errCode, prev_alt = dev->alt;
-       int i;
-       unsigned int min_pkt_size = dev->bytesperline+4;
-
-       /* When image size is bigger than a ceirtain value,
-          the frame size should be increased, otherwise, only
-          green screen will be received.
-        */
-       if (dev->frame_size > 720*240*2)
-               min_pkt_size *= 2;
+       init_waitqueue_head(&dma_q->wq);
 
-       for (i = 0; i < dev->num_alt; i++)
-               if (dev->alt_max_pkt_size[i] >= min_pkt_size)
-                       break;
-       dev->alt = i;
+       em28xx_capture_start(dev, 1);
 
-       if (dev->alt != prev_alt) {
-               em28xx_coredbg("minimum isoc packet size: %u (alt=%d)\n",
-                               min_pkt_size, dev->alt);
-               dev->max_pkt_size = dev->alt_max_pkt_size[dev->alt];
-               em28xx_coredbg("setting alternate %d with wMaxPacketSize=%u\n",
-                              dev->alt, dev->max_pkt_size);
-               errCode = usb_set_interface(dev->udev, 0, dev->alt);
-               if (errCode < 0) {
-                       em28xx_errdev ("cannot change alternate number to %d (error=%i)\n",
-                                       dev->alt, errCode);
-                       return errCode;
+       /* submit urbs and enables IRQ */
+       for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
+               rc = usb_submit_urb(dev->isoc_ctl.urb[i], GFP_ATOMIC);
+               if (rc) {
+                       em28xx_err("submit of urb %i failed (error=%i)\n", i,
+                                  rc);
+                       em28xx_uninit_isoc(dev);
+                       return rc;
                }
        }
+
        return 0;
 }
+EXPORT_SYMBOL_GPL(em28xx_init_isoc);
diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c
new file mode 100644 (file)
index 0000000..7df8157
--- /dev/null
@@ -0,0 +1,474 @@
+/*
+ DVB device driver for em28xx
+
+ (c) 2008 Mauro Carvalho Chehab <mchehab@infradead.org>
+
+ (c) 2008 Devin Heitmueller <devin.heitmueller@gmail.com>
+       - Fixes for the driver to properly work with HVR-950
+
+ (c) 2008 Aidan Thornton <makosoft@googlemail.com>
+
+ Based on cx88-dvb, saa7134-dvb and videobuf-dvb originally written by:
+       (c) 2004, 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au>
+       (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
+
+ 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/usb.h>
+
+#include "em28xx.h"
+#include <media/v4l2-common.h>
+#include <media/videobuf-vmalloc.h>
+
+#include "lgdt330x.h"
+#include "zl10353.h"
+
+MODULE_DESCRIPTION("driver for em28xx based DVB cards");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
+MODULE_LICENSE("GPL");
+
+static unsigned int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable debug messages [dvb]");
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+#define dprintk(level, fmt, arg...) do {                       \
+if (debug >= level)                                            \
+       printk(KERN_DEBUG "%s/2-dvb: " fmt, dev->name, ## arg); \
+} while (0)
+
+#define EM28XX_DVB_NUM_BUFS 5
+#define EM28XX_DVB_MAX_PACKETSIZE 564
+#define EM28XX_DVB_MAX_PACKETS 64
+
+struct em28xx_dvb {
+       struct dvb_frontend        *frontend;
+
+       /* feed count management */
+       struct mutex               lock;
+       int                        nfeeds;
+
+       /* general boilerplate stuff */
+       struct dvb_adapter         adapter;
+       struct dvb_demux           demux;
+       struct dmxdev              dmxdev;
+       struct dmx_frontend        fe_hw;
+       struct dmx_frontend        fe_mem;
+       struct dvb_net             net;
+};
+
+
+static inline void print_err_status(struct em28xx *dev,
+                                    int packet, int status)
+{
+       char *errmsg = "Unknown";
+
+       switch (status) {
+       case -ENOENT:
+               errmsg = "unlinked synchronuously";
+               break;
+       case -ECONNRESET:
+               errmsg = "unlinked asynchronuously";
+               break;
+       case -ENOSR:
+               errmsg = "Buffer error (overrun)";
+               break;
+       case -EPIPE:
+               errmsg = "Stalled (device not responding)";
+               break;
+       case -EOVERFLOW:
+               errmsg = "Babble (bad cable?)";
+               break;
+       case -EPROTO:
+               errmsg = "Bit-stuff error (bad cable?)";
+               break;
+       case -EILSEQ:
+               errmsg = "CRC/Timeout (could be anything)";
+               break;
+       case -ETIME:
+               errmsg = "Device does not respond";
+               break;
+       }
+       if (packet < 0) {
+               dprintk(1, "URB status %d [%s].\n", status, errmsg);
+       } else {
+               dprintk(1, "URB packet %d, status %d [%s].\n",
+                       packet, status, errmsg);
+       }
+}
+
+static inline int dvb_isoc_copy(struct em28xx *dev, struct urb *urb)
+{
+       int i;
+
+       if (!dev)
+               return 0;
+
+       if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
+               return 0;
+
+       if (urb->status < 0) {
+               print_err_status(dev, -1, urb->status);
+               if (urb->status == -ENOENT)
+                       return 0;
+       }
+
+       for (i = 0; i < urb->number_of_packets; i++) {
+               int status = urb->iso_frame_desc[i].status;
+
+               if (status < 0) {
+                       print_err_status(dev, i, status);
+                       if (urb->iso_frame_desc[i].status != -EPROTO)
+                               continue;
+               }
+
+               dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer +
+                                urb->iso_frame_desc[i].offset,
+                                urb->iso_frame_desc[i].actual_length);
+       }
+
+       return 0;
+}
+
+static int start_streaming(struct em28xx_dvb *dvb)
+{
+       int rc;
+       struct em28xx *dev = dvb->adapter.priv;
+
+       usb_set_interface(dev->udev, 0, 1);
+       rc = em28xx_set_mode(dev, EM28XX_DIGITAL_MODE);
+       if (rc < 0)
+               return rc;
+
+       return em28xx_init_isoc(dev, EM28XX_DVB_MAX_PACKETS,
+                               EM28XX_DVB_NUM_BUFS, EM28XX_DVB_MAX_PACKETSIZE,
+                               dvb_isoc_copy);
+}
+
+static int stop_streaming(struct em28xx_dvb *dvb)
+{
+       struct em28xx *dev = dvb->adapter.priv;
+
+       em28xx_uninit_isoc(dev);
+
+       em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED);
+
+       return 0;
+}
+
+static int start_feed(struct dvb_demux_feed *feed)
+{
+       struct dvb_demux *demux  = feed->demux;
+       struct em28xx_dvb *dvb = demux->priv;
+       int rc, ret;
+
+       if (!demux->dmx.frontend)
+               return -EINVAL;
+
+       mutex_lock(&dvb->lock);
+       dvb->nfeeds++;
+       rc = dvb->nfeeds;
+
+       if (dvb->nfeeds == 1) {
+               ret = start_streaming(dvb);
+               if (ret < 0)
+                       rc = ret;
+       }
+
+       mutex_unlock(&dvb->lock);
+       return rc;
+}
+
+static int stop_feed(struct dvb_demux_feed *feed)
+{
+       struct dvb_demux *demux  = feed->demux;
+       struct em28xx_dvb *dvb = demux->priv;
+       int err = 0;
+
+       mutex_lock(&dvb->lock);
+       dvb->nfeeds--;
+
+       if (0 == dvb->nfeeds)
+               err = stop_streaming(dvb);
+
+       mutex_unlock(&dvb->lock);
+       return err;
+}
+
+
+
+/* ------------------------------------------------------------------ */
+static int em28xx_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire)
+{
+       struct em28xx *dev = fe->dvb->priv;
+
+       if (acquire)
+               return em28xx_set_mode(dev, EM28XX_DIGITAL_MODE);
+       else
+               return em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED);
+}
+
+/* ------------------------------------------------------------------ */
+
+static struct lgdt330x_config em2880_lgdt3303_dev = {
+       .demod_address = 0x0e,
+       .demod_chip = LGDT3303,
+};
+
+static struct zl10353_config em28xx_zl10353_with_xc3028 = {
+       .demod_address = (0x1e >> 1),
+       .no_tuner = 1,
+       .parallel_ts = 1,
+       .if2 = 45600,
+};
+
+/* ------------------------------------------------------------------ */
+
+static int attach_xc3028(u8 addr, struct em28xx *dev)
+{
+       struct dvb_frontend *fe;
+       struct xc2028_config cfg;
+
+       memset(&cfg, 0, sizeof(cfg));
+       cfg.i2c_adap  = &dev->i2c_adap;
+       cfg.i2c_addr  = addr;
+       cfg.callback  = em28xx_tuner_callback;
+
+       if (!dev->dvb->frontend) {
+               printk(KERN_ERR "%s/2: dvb frontend not attached. "
+                               "Can't attach xc3028\n",
+                      dev->name);
+               return -EINVAL;
+       }
+
+       fe = dvb_attach(xc2028_attach, dev->dvb->frontend, &cfg);
+       if (!fe) {
+               printk(KERN_ERR "%s/2: xc3028 attach failed\n",
+                      dev->name);
+               dvb_frontend_detach(dev->dvb->frontend);
+               dvb_unregister_frontend(dev->dvb->frontend);
+               dev->dvb->frontend = NULL;
+               return -EINVAL;
+       }
+
+       printk(KERN_INFO "%s/2: xc3028 attached\n", dev->name);
+
+       return 0;
+}
+
+/* ------------------------------------------------------------------ */
+
+int register_dvb(struct em28xx_dvb *dvb,
+                struct module *module,
+                struct em28xx *dev,
+                struct device *device)
+{
+       int result;
+
+       mutex_init(&dvb->lock);
+
+       /* register adapter */
+       result = dvb_register_adapter(&dvb->adapter, dev->name, module, device,
+                                     adapter_nr);
+       if (result < 0) {
+               printk(KERN_WARNING "%s: dvb_register_adapter failed (errno = %d)\n",
+                      dev->name, result);
+               goto fail_adapter;
+       }
+
+       /* Ensure all frontends negotiate bus access */
+       dvb->frontend->ops.ts_bus_ctrl = em28xx_dvb_bus_ctrl;
+
+       dvb->adapter.priv = dev;
+
+       /* register frontend */
+       result = dvb_register_frontend(&dvb->adapter, dvb->frontend);
+       if (result < 0) {
+               printk(KERN_WARNING "%s: dvb_register_frontend failed (errno = %d)\n",
+                      dev->name, result);
+               goto fail_frontend;
+       }
+
+       /* register demux stuff */
+       dvb->demux.dmx.capabilities =
+               DMX_TS_FILTERING | DMX_SECTION_FILTERING |
+               DMX_MEMORY_BASED_FILTERING;
+       dvb->demux.priv       = dvb;
+       dvb->demux.filternum  = 256;
+       dvb->demux.feednum    = 256;
+       dvb->demux.start_feed = start_feed;
+       dvb->demux.stop_feed  = stop_feed;
+
+       result = dvb_dmx_init(&dvb->demux);
+       if (result < 0) {
+               printk(KERN_WARNING "%s: dvb_dmx_init failed (errno = %d)\n",
+                      dev->name, result);
+               goto fail_dmx;
+       }
+
+       dvb->dmxdev.filternum    = 256;
+       dvb->dmxdev.demux        = &dvb->demux.dmx;
+       dvb->dmxdev.capabilities = 0;
+       result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter);
+       if (result < 0) {
+               printk(KERN_WARNING "%s: dvb_dmxdev_init failed (errno = %d)\n",
+                      dev->name, result);
+               goto fail_dmxdev;
+       }
+
+       dvb->fe_hw.source = DMX_FRONTEND_0;
+       result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw);
+       if (result < 0) {
+               printk(KERN_WARNING "%s: add_frontend failed (DMX_FRONTEND_0, errno = %d)\n",
+                      dev->name, result);
+               goto fail_fe_hw;
+       }
+
+       dvb->fe_mem.source = DMX_MEMORY_FE;
+       result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem);
+       if (result < 0) {
+               printk(KERN_WARNING "%s: add_frontend failed (DMX_MEMORY_FE, errno = %d)\n",
+                      dev->name, result);
+               goto fail_fe_mem;
+       }
+
+       result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw);
+       if (result < 0) {
+               printk(KERN_WARNING "%s: connect_frontend failed (errno = %d)\n",
+                      dev->name, result);
+               goto fail_fe_conn;
+       }
+
+       /* register network adapter */
+       dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx);
+       return 0;
+
+fail_fe_conn:
+       dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
+fail_fe_mem:
+       dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
+fail_fe_hw:
+       dvb_dmxdev_release(&dvb->dmxdev);
+fail_dmxdev:
+       dvb_dmx_release(&dvb->demux);
+fail_dmx:
+       dvb_unregister_frontend(dvb->frontend);
+fail_frontend:
+       dvb_frontend_detach(dvb->frontend);
+       dvb_unregister_adapter(&dvb->adapter);
+fail_adapter:
+       return result;
+}
+
+static void unregister_dvb(struct em28xx_dvb *dvb)
+{
+       dvb_net_release(&dvb->net);
+       dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
+       dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
+       dvb_dmxdev_release(&dvb->dmxdev);
+       dvb_dmx_release(&dvb->demux);
+       dvb_unregister_frontend(dvb->frontend);
+       dvb_frontend_detach(dvb->frontend);
+       dvb_unregister_adapter(&dvb->adapter);
+}
+
+
+static int dvb_init(struct em28xx *dev)
+{
+       int result = 0;
+       struct em28xx_dvb *dvb;
+
+       dvb = kzalloc(sizeof(struct em28xx_dvb), GFP_KERNEL);
+
+       if (dvb == NULL) {
+               printk(KERN_INFO "em28xx_dvb: memory allocation failed\n");
+               return -ENOMEM;
+       }
+       dev->dvb = dvb;
+
+       em28xx_set_mode(dev, EM28XX_DIGITAL_MODE);
+       /* init frontend */
+       switch (dev->model) {
+       case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950:
+               dvb->frontend = dvb_attach(lgdt330x_attach,
+                                          &em2880_lgdt3303_dev,
+                                          &dev->i2c_adap);
+               if (attach_xc3028(0x61, dev) < 0) {
+                       result = -EINVAL;
+                       goto out_free;
+               }
+               break;
+       case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
+               dvb->frontend = dvb_attach(zl10353_attach,
+                                          &em28xx_zl10353_with_xc3028,
+                                          &dev->i2c_adap);
+               if (attach_xc3028(0x61, dev) < 0) {
+                       result = -EINVAL;
+                       goto out_free;
+               }
+               break;
+       default:
+               printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card"
+                               " isn't supported yet\n",
+                      dev->name);
+               break;
+       }
+       if (NULL == dvb->frontend) {
+               printk(KERN_ERR
+                      "%s/2: frontend initialization failed\n",
+                      dev->name);
+               result = -EINVAL;
+               goto out_free;
+       }
+
+       /* register everything */
+       result = register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev);
+
+       if (result < 0)
+               goto out_free;
+
+       em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED);
+       printk(KERN_INFO "Successfully loaded em28xx-dvb\n");
+       return 0;
+
+out_free:
+       em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED);
+       kfree(dvb);
+       dev->dvb = NULL;
+       return result;
+}
+
+static int dvb_fini(struct em28xx *dev)
+{
+       if (dev->dvb) {
+               unregister_dvb(dev->dvb);
+               dev->dvb = NULL;
+       }
+
+       return 0;
+}
+
+static struct em28xx_ops dvb_ops = {
+       .id   = EM28XX_DVB,
+       .name = "Em28xx dvb Extension",
+       .init = dvb_init,
+       .fini = dvb_fini,
+};
+
+static int __init em28xx_dvb_register(void)
+{
+       return em28xx_register_extension(&dvb_ops);
+}
+
+static void __exit em28xx_dvb_unregister(void)
+{
+       em28xx_unregister_extension(&dvb_ops);
+}
+
+module_init(em28xx_dvb_register);
+module_exit(em28xx_dvb_unregister);
index cacd04d46e99eb85145c9ee5e14ed0cff792bfde..6a78fd294cabfaef3343ce7fb9b94e85ea031bc0 100644 (file)
 
 /* ----------------------------------------------------------- */
 
-static unsigned int i2c_scan = 0;
+static unsigned int i2c_scan;
 module_param(i2c_scan, int, 0444);
 MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
 
-static unsigned int i2c_debug = 0;
+static unsigned int i2c_debug;
 module_param(i2c_debug, int, 0644);
 MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
 
-#define dprintk1(lvl,fmt, args...) if (i2c_debug>=lvl) do {\
-                       printk(fmt, ##args); } while (0)
-#define dprintk2(lvl,fmt, args...) if (i2c_debug>=lvl) do{ \
-                       printk(KERN_DEBUG "%s at %s: " fmt, \
-                       dev->name, __FUNCTION__ , ##args); } while (0)
+
+#define dprintk1(lvl, fmt, args...)                    \
+do {                                                   \
+       if (i2c_debug >= lvl) {                         \
+       printk(fmt, ##args);                            \
+      }                                                        \
+} while (0)
+
+#define dprintk2(lvl, fmt, args...)                    \
+do {                                                   \
+       if (i2c_debug >= lvl) {                         \
+               printk(KERN_DEBUG "%s at %s: " fmt,     \
+                      dev->name, __func__ , ##args);   \
+      }                                                \
+} while (0)
 
 /*
  * em2800_i2c_send_max4()
@@ -235,16 +245,16 @@ static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap,
                return 0;
        for (i = 0; i < num; i++) {
                addr = msgs[i].addr << 1;
-               dprintk2(2,"%s %s addr=%x len=%d:",
+               dprintk2(2, "%s %s addr=%x len=%d:",
                         (msgs[i].flags & I2C_M_RD) ? "read" : "write",
                         i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len);
-               if (!msgs[i].len) {     /* no len: check only for device presence */
+               if (!msgs[i].len) { /* no len: check only for device presence */
                        if (dev->is_em2800)
                                rc = em2800_i2c_check_for_device(dev, addr);
                        else
                                rc = em28xx_i2c_check_for_device(dev, addr);
                        if (rc < 0) {
-                               dprintk2(2," no device\n");
+                               dprintk2(2, " no device\n");
                                return rc;
                        }
 
@@ -258,14 +268,13 @@ static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap,
                                rc = em28xx_i2c_recv_bytes(dev, addr,
                                                           msgs[i].buf,
                                                           msgs[i].len);
-                       if (i2c_debug>=2) {
-                               for (byte = 0; byte < msgs[i].len; byte++) {
+                       if (i2c_debug >= 2) {
+                               for (byte = 0; byte < msgs[i].len; byte++)
                                        printk(" %02x", msgs[i].buf[byte]);
-                               }
                        }
                } else {
                        /* write bytes */
-                       if (i2c_debug>=2) {
+                       if (i2c_debug >= 2) {
                                for (byte = 0; byte < msgs[i].len; byte++)
                                        printk(" %02x", msgs[i].buf[byte]);
                        }
@@ -281,13 +290,13 @@ static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap,
                }
                if (rc < 0)
                        goto err;
-               if (i2c_debug>=2)
+               if (i2c_debug >= 2)
                        printk("\n");
        }
 
        return num;
-      err:
-       dprintk2(2," ERROR: %i\n", rc);
+err:
+       dprintk2(2, " ERROR: %i\n", rc);
        return rc;
 }
 
@@ -330,7 +339,9 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len)
                return -1;
 
        buf = 0;
-       if (1 != (err = i2c_master_send(&dev->i2c_client, &buf, 1))) {
+
+       err = i2c_master_send(&dev->i2c_client, &buf, 1);
+       if (err != 1) {
                printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n",
                       dev->name, err);
                return -1;
@@ -403,8 +414,10 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len)
                break;
        }
        printk(KERN_INFO "Table at 0x%02x, strings=0x%04x, 0x%04x, 0x%04x\n",
-                               em_eeprom->string_idx_table,em_eeprom->string1,
-                               em_eeprom->string2,em_eeprom->string3);
+                               em_eeprom->string_idx_table,
+                               em_eeprom->string1,
+                               em_eeprom->string2,
+                               em_eeprom->string3);
 
        return 0;
 }
@@ -430,58 +443,61 @@ static int attach_inform(struct i2c_client *client)
        struct em28xx *dev = client->adapter->algo_data;
 
        switch (client->addr << 1) {
-               case 0x86:
-               case 0x84:
-               case 0x96:
-               case 0x94:
-               {
-                       struct v4l2_priv_tun_config tda9887_cfg;
-
-                       struct tuner_setup tun_setup;
-
-                       tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
-                       tun_setup.type = TUNER_TDA9887;
-                       tun_setup.addr = client->addr;
-
-                       em28xx_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup);
-
-                       tda9887_cfg.tuner = TUNER_TDA9887;
-                       tda9887_cfg.priv = &dev->tda9887_conf;
-                       em28xx_i2c_call_clients(dev, TUNER_SET_CONFIG,
-                                               &tda9887_cfg);
-                       break;
-               }
-               case 0x42:
-                       dprintk1(1,"attach_inform: saa7114 detected.\n");
-                       break;
-               case 0x4a:
-                       dprintk1(1,"attach_inform: saa7113 detected.\n");
-                       break;
-               case 0xa0:
-                       dprintk1(1,"attach_inform: eeprom detected.\n");
-                       break;
-               case 0x60:
-               case 0x8e:
-               {
-                       struct IR_i2c *ir = i2c_get_clientdata(client);
-                       dprintk1(1,"attach_inform: IR detected (%s).\n",ir->phys);
-                       em28xx_set_ir(dev,ir);
-                       break;
-               }
-               case 0x80:
-               case 0x88:
-                       dprintk1(1,"attach_inform: msp34xx detected.\n");
-                       break;
-               case 0xb8:
-               case 0xba:
-                       dprintk1(1,"attach_inform: tvp5150 detected.\n");
-                       break;
-
-               default:
-                       if (!dev->tuner_addr)
-                               dev->tuner_addr = client->addr;
-
-                       dprintk1(1,"attach inform: detected I2C address %x\n", client->addr << 1);
+       case 0x86:
+       case 0x84:
+       case 0x96:
+       case 0x94:
+       {
+               struct v4l2_priv_tun_config tda9887_cfg;
+
+               struct tuner_setup tun_setup;
+
+               tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
+               tun_setup.type = TUNER_TDA9887;
+               tun_setup.addr = client->addr;
+
+               em28xx_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR,
+                       &tun_setup);
+
+               tda9887_cfg.tuner = TUNER_TDA9887;
+               tda9887_cfg.priv = &dev->tda9887_conf;
+               em28xx_i2c_call_clients(dev, TUNER_SET_CONFIG,
+                                       &tda9887_cfg);
+               break;
+       }
+       case 0x42:
+               dprintk1(1, "attach_inform: saa7114 detected.\n");
+               break;
+       case 0x4a:
+               dprintk1(1, "attach_inform: saa7113 detected.\n");
+               break;
+       case 0xa0:
+               dprintk1(1, "attach_inform: eeprom detected.\n");
+               break;
+       case 0x60:
+       case 0x8e:
+       {
+               struct IR_i2c *ir = i2c_get_clientdata(client);
+               dprintk1(1, "attach_inform: IR detected (%s).\n",
+                       ir->phys);
+               em28xx_set_ir(dev, ir);
+               break;
+       }
+       case 0x80:
+       case 0x88:
+               dprintk1(1, "attach_inform: msp34xx detected.\n");
+               break;
+       case 0xb8:
+       case 0xba:
+               dprintk1(1, "attach_inform: tvp5150 detected.\n");
+               break;
+
+       default:
+               if (!dev->tuner_addr)
+                       dev->tuner_addr = client->addr;
+
+               dprintk1(1, "attach inform: detected I2C address %x\n",
+                               client->addr << 1);
 
        }
 
index 10da2fd8d9875072fe3476ed683266c450c4f08d..bb5807159b8d28638e46c01d7f0621861aedeed4 100644 (file)
 
 static unsigned int ir_debug;
 module_param(ir_debug, int, 0644);
-MODULE_PARM_DESC(ir_debug,"enable debug messages [IR]");
+MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]");
 
-#define dprintk(fmt, arg...)   if (ir_debug) \
-       printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg)
+#define dprintk(fmt, arg...) \
+       if (ir_debug) { \
+               printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg); \
+       }
 
 /* ----------------------------------------------------------------------- */
 
@@ -44,7 +46,7 @@ int em28xx_get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
        unsigned char b;
 
        /* poll IR chip */
-       if (1 != i2c_master_recv(&ir->c,&b,1)) {
+       if (1 != i2c_master_recv(&ir->c, &b, 1)) {
                dprintk("read error\n");
                return -EIO;
        }
@@ -74,24 +76,25 @@ int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
        unsigned char code;
 
        /* poll IR chip */
-       if (2 != i2c_master_recv(&ir->c,buf,2))
+       if (2 != i2c_master_recv(&ir->c, buf, 2))
                return -EIO;
 
        /* Does eliminate repeated parity code */
-       if (buf[1]==0xff)
+       if (buf[1] == 0xff)
                return 0;
 
-       ir->old=buf[1];
+       ir->old = buf[1];
 
        /* Rearranges bits to the right order */
-       code   ((buf[0]&0x01)<<5) | /* 0010 0000 */
+       code =   ((buf[0]&0x01)<<5) | /* 0010 0000 */
                 ((buf[0]&0x02)<<3) | /* 0001 0000 */
                 ((buf[0]&0x04)<<1) | /* 0000 1000 */
                 ((buf[0]&0x08)>>1) | /* 0000 0100 */
                 ((buf[0]&0x10)>>3) | /* 0000 0010 */
                 ((buf[0]&0x20)>>5);  /* 0000 0001 */
 
-       dprintk("ir hauppauge (em2840): code=0x%02x (rcv=0x%02x)\n",code,buf[0]);
+       dprintk("ir hauppauge (em2840): code=0x%02x (rcv=0x%02x)\n",
+                       code, buf[0]);
 
        /* return key */
        *ir_key = code;
@@ -106,15 +109,14 @@ int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key,
 
        /* poll IR chip */
 
-       if (3 != i2c_master_recv(&ir->c,buf,3)) {
+       if (3 != i2c_master_recv(&ir->c, buf, 3)) {
                dprintk("read error\n");
                return -EIO;
        }
 
        dprintk("key %02x\n", buf[2]&0x3f);
-       if (buf[0]!=0x00){
+       if (buf[0] != 0x00)
                return 0;
-       }
 
        *ir_key = buf[2]&0x3f;
        *ir_raw = buf[2]&0x3f;
diff --git a/drivers/media/video/em28xx/em28xx-reg.h b/drivers/media/video/em28xx/em28xx-reg.h
new file mode 100644 (file)
index 0000000..9058bed
--- /dev/null
@@ -0,0 +1,88 @@
+#define EM_GPIO_0  (1 << 0)
+#define EM_GPIO_1  (1 << 1)
+#define EM_GPIO_2  (1 << 2)
+#define EM_GPIO_3  (1 << 3)
+#define EM_GPIO_4  (1 << 4)
+#define EM_GPIO_5  (1 << 5)
+#define EM_GPIO_6  (1 << 6)
+#define EM_GPIO_7  (1 << 7)
+
+#define EM_GPO_0   (1 << 0)
+#define EM_GPO_1   (1 << 1)
+#define EM_GPO_2   (1 << 2)
+#define EM_GPO_3   (1 << 3)
+
+/* em2800 registers */
+#define EM2800_R08_AUDIOSRC 0x08
+
+/* em28xx registers */
+
+       /* GPIO/GPO registers */
+#define EM2880_R04_GPO 0x04    /* em2880-em2883 only */
+#define EM28XX_R08_GPIO        0x08    /* em2820 or upper */
+
+#define EM28XX_R06_I2C_CLK     0x06
+#define EM28XX_R0A_CHIPID      0x0a
+#define EM28XX_R0C_USBSUSP     0x0c    /* */
+
+#define EM28XX_R0E_AUDIOSRC    0x0e
+#define EM28XX_R0F_XCLK        0x0f
+
+#define EM28XX_R10_VINMODE     0x10
+#define EM28XX_R11_VINCTRL     0x11
+#define EM28XX_R12_VINENABLE   0x12    /* */
+
+#define EM28XX_R14_GAMMA       0x14
+#define EM28XX_R15_RGAIN       0x15
+#define EM28XX_R16_GGAIN       0x16
+#define EM28XX_R17_BGAIN       0x17
+#define EM28XX_R18_ROFFSET     0x18
+#define EM28XX_R19_GOFFSET     0x19
+#define EM28XX_R1A_BOFFSET     0x1a
+
+#define EM28XX_R1B_OFLOW       0x1b
+#define EM28XX_R1C_HSTART      0x1c
+#define EM28XX_R1D_VSTART      0x1d
+#define EM28XX_R1E_CWIDTH      0x1e
+#define EM28XX_R1F_CHEIGHT     0x1f
+
+#define EM28XX_R20_YGAIN       0x20
+#define EM28XX_R21_YOFFSET     0x21
+#define EM28XX_R22_UVGAIN      0x22
+#define EM28XX_R23_UOFFSET     0x23
+#define EM28XX_R24_VOFFSET     0x24
+#define EM28XX_R25_SHARPNESS   0x25
+
+#define EM28XX_R26_COMPR       0x26
+#define EM28XX_R27_OUTFMT      0x27
+
+#define EM28XX_R28_XMIN        0x28
+#define EM28XX_R29_XMAX        0x29
+#define EM28XX_R2A_YMIN        0x2a
+#define EM28XX_R2B_YMAX        0x2b
+
+#define EM28XX_R30_HSCALELOW   0x30
+#define EM28XX_R31_HSCALEHIGH  0x31
+#define EM28XX_R32_VSCALELOW   0x32
+#define EM28XX_R33_VSCALEHIGH  0x33
+
+#define EM28XX_R40_AC97LSB     0x40
+#define EM28XX_R41_AC97MSB     0x41
+#define EM28XX_R42_AC97ADDR    0x42
+#define EM28XX_R43_AC97BUSY    0x43
+
+/* em202 registers */
+#define EM28XX_R02_MASTER_AC97 0x02
+#define EM28XX_R10_LINE_IN_AC97    0x10
+#define EM28XX_R14_VIDEO_AC97  0x14
+
+/* register settings */
+#define EM2800_AUDIO_SRC_TUNER  0x0d
+#define EM2800_AUDIO_SRC_LINE   0x0c
+#define EM28XX_AUDIO_SRC_TUNER 0xc0
+#define EM28XX_AUDIO_SRC_LINE  0x80
+
+/* FIXME: Need to be populated with the other chip ID's */
+enum em28xx_chip_id {
+       CHIP_ID_EM2883 = 36,
+};
index 4abe6701a7700894624b17ad7db40547248b2f67..8996175cc95075bca9c42c89501a2adc51bd12fc 100644 (file)
@@ -1,5 +1,6 @@
 /*
-   em28xx-video.c - driver for Empia EM2800/EM2820/2840 USB video capture devices
+   em28xx-video.c - driver for Empia EM2800/EM2820/2840 USB
+                   video capture devices
 
    Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it>
                      Markus Rechberger <mrechberger@gmail.com>
 #define em28xx_videodbg(fmt, arg...) do {\
        if (video_debug) \
                printk(KERN_INFO "%s %s :"fmt, \
-                        dev->name, __FUNCTION__ , ##arg); } while (0)
+                        dev->name, __func__ , ##arg); } while (0)
+
+static unsigned int isoc_debug;
+module_param(isoc_debug, int, 0644);
+MODULE_PARM_DESC(isoc_debug, "enable debug messages [isoc transfers]");
+
+#define em28xx_isocdbg(fmt, arg...) \
+do {\
+       if (isoc_debug) { \
+               printk(KERN_INFO "%s %s :"fmt, \
+                        dev->name, __func__ , ##arg); \
+       } \
+  } while (0)
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
@@ -74,9 +87,9 @@ MODULE_PARM_DESC(video_nr, "video device numbers");
 MODULE_PARM_DESC(vbi_nr,   "vbi device numbers");
 MODULE_PARM_DESC(radio_nr, "radio device numbers");
 
-static unsigned int video_debug = 0;
-module_param(video_debug,int,0644);
-MODULE_PARM_DESC(video_debug,"enable debug messages [video]");
+static unsigned int video_debug;
+module_param(video_debug, int, 0644);
+MODULE_PARM_DESC(video_debug, "enable debug messages [video]");
 
 /* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS */
 static unsigned long em28xx_devused;
@@ -93,7 +106,7 @@ static struct v4l2_queryctrl em28xx_qctrl[] = {
                .step = 0x1,
                .default_value = 0x1f,
                .flags = 0,
-       },{
+       }, {
                .id = V4L2_CID_AUDIO_MUTE,
                .type = V4L2_CTRL_TYPE_BOOLEAN,
                .name = "Mute",
@@ -107,8 +120,391 @@ static struct v4l2_queryctrl em28xx_qctrl[] = {
 
 static struct usb_driver em28xx_usb_driver;
 
+/* ------------------------------------------------------------------
+       DMA and thread functions
+   ------------------------------------------------------------------*/
+
+/*
+ * Announces that a buffer were filled and request the next
+ */
+static inline void buffer_filled(struct em28xx *dev,
+                                 struct em28xx_dmaqueue *dma_q,
+                                 struct em28xx_buffer *buf)
+{
+       /* Advice that buffer was filled */
+       em28xx_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i);
+       buf->vb.state = VIDEOBUF_DONE;
+       buf->vb.field_count++;
+       do_gettimeofday(&buf->vb.ts);
 
-/*********************  v4l2 interface  ******************************************/
+       dev->isoc_ctl.buf = NULL;
+
+       list_del(&buf->vb.queue);
+       wake_up(&buf->vb.done);
+}
+
+/*
+ * Identify the buffer header type and properly handles
+ */
+static void em28xx_copy_video(struct em28xx *dev,
+                             struct em28xx_dmaqueue  *dma_q,
+                             struct em28xx_buffer *buf,
+                             unsigned char *p,
+                             unsigned char *outp, unsigned long len)
+{
+       void *fieldstart, *startwrite, *startread;
+       int  linesdone, currlinedone, offset, lencopy, remain;
+       int bytesperline = dev->width << 1;
+
+       if (dma_q->pos + len > buf->vb.size)
+               len = buf->vb.size - dma_q->pos;
+
+       if (p[0] != 0x88 && p[0] != 0x22) {
+               em28xx_isocdbg("frame is not complete\n");
+               len += 4;
+       } else
+               p += 4;
+
+       startread = p;
+       remain = len;
+
+       /* Interlaces frame */
+       if (buf->top_field)
+               fieldstart = outp;
+       else
+               fieldstart = outp + bytesperline;
+
+       linesdone = dma_q->pos / bytesperline;
+       currlinedone = dma_q->pos % bytesperline;
+       offset = linesdone * bytesperline * 2 + currlinedone;
+       startwrite = fieldstart + offset;
+       lencopy = bytesperline - currlinedone;
+       lencopy = lencopy > remain ? remain : lencopy;
+
+       if ((char *)startwrite + lencopy > (char *)outp + buf->vb.size) {
+               em28xx_isocdbg("Overflow of %zi bytes past buffer end (1)\n",
+                              ((char *)startwrite + lencopy) -
+                              ((char *)outp + buf->vb.size));
+               lencopy = remain = (char *)outp + buf->vb.size - (char *)startwrite;
+       }
+       if (lencopy <= 0)
+               return;
+       memcpy(startwrite, startread, lencopy);
+
+       remain -= lencopy;
+
+       while (remain > 0) {
+               startwrite += lencopy + bytesperline;
+               startread += lencopy;
+               if (bytesperline > remain)
+                       lencopy = remain;
+               else
+                       lencopy = bytesperline;
+
+               if ((char *)startwrite + lencopy > (char *)outp + buf->vb.size) {
+                       em28xx_isocdbg("Overflow of %zi bytes past buffer end (2)\n",
+                                      ((char *)startwrite + lencopy) -
+                                      ((char *)outp + buf->vb.size));
+                       lencopy = remain = (char *)outp + buf->vb.size -
+                                          (char *)startwrite;
+               }
+               if (lencopy <= 0)
+                       break;
+
+               memcpy(startwrite, startread, lencopy);
+
+               remain -= lencopy;
+       }
+
+       dma_q->pos += len;
+}
+
+static inline void print_err_status(struct em28xx *dev,
+                                    int packet, int status)
+{
+       char *errmsg = "Unknown";
+
+       switch (status) {
+       case -ENOENT:
+               errmsg = "unlinked synchronuously";
+               break;
+       case -ECONNRESET:
+               errmsg = "unlinked asynchronuously";
+               break;
+       case -ENOSR:
+               errmsg = "Buffer error (overrun)";
+               break;
+       case -EPIPE:
+               errmsg = "Stalled (device not responding)";
+               break;
+       case -EOVERFLOW:
+               errmsg = "Babble (bad cable?)";
+               break;
+       case -EPROTO:
+               errmsg = "Bit-stuff error (bad cable?)";
+               break;
+       case -EILSEQ:
+               errmsg = "CRC/Timeout (could be anything)";
+               break;
+       case -ETIME:
+               errmsg = "Device does not respond";
+               break;
+       }
+       if (packet < 0) {
+               em28xx_isocdbg("URB status %d [%s].\n", status, errmsg);
+       } else {
+               em28xx_isocdbg("URB packet %d, status %d [%s].\n",
+                              packet, status, errmsg);
+       }
+}
+
+/*
+ * video-buf generic routine to get the next available buffer
+ */
+static inline void get_next_buf(struct em28xx_dmaqueue *dma_q,
+                                         struct em28xx_buffer **buf)
+{
+       struct em28xx *dev = container_of(dma_q, struct em28xx, vidq);
+       char *outp;
+
+       if (list_empty(&dma_q->active)) {
+               em28xx_isocdbg("No active queue to serve\n");
+               dev->isoc_ctl.buf = NULL;
+               *buf = NULL;
+               return;
+       }
+
+       /* Get the next buffer */
+       *buf = list_entry(dma_q->active.next, struct em28xx_buffer, vb.queue);
+
+       /* Cleans up buffer - Usefull for testing for frame/URB loss */
+       outp = videobuf_to_vmalloc(&(*buf)->vb);
+       memset(outp, 0, (*buf)->vb.size);
+
+       dev->isoc_ctl.buf = *buf;
+
+       return;
+}
+
+/*
+ * Controls the isoc copy of each urb packet
+ */
+static inline int em28xx_isoc_copy(struct em28xx *dev, struct urb *urb)
+{
+       struct em28xx_buffer    *buf;
+       struct em28xx_dmaqueue  *dma_q = urb->context;
+       unsigned char *outp = NULL;
+       int i, len = 0, rc = 1;
+       unsigned char *p;
+
+       if (!dev)
+               return 0;
+
+       if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
+               return 0;
+
+       if (urb->status < 0) {
+               print_err_status(dev, -1, urb->status);
+               if (urb->status == -ENOENT)
+                       return 0;
+       }
+
+       buf = dev->isoc_ctl.buf;
+       if (buf != NULL)
+               outp = videobuf_to_vmalloc(&buf->vb);
+
+       for (i = 0; i < urb->number_of_packets; i++) {
+               int status = urb->iso_frame_desc[i].status;
+
+               if (status < 0) {
+                       print_err_status(dev, i, status);
+                       if (urb->iso_frame_desc[i].status != -EPROTO)
+                               continue;
+               }
+
+               len = urb->iso_frame_desc[i].actual_length - 4;
+
+               if (urb->iso_frame_desc[i].actual_length <= 0) {
+                       /* em28xx_isocdbg("packet %d is empty",i); - spammy */
+                       continue;
+               }
+               if (urb->iso_frame_desc[i].actual_length >
+                                               dev->max_pkt_size) {
+                       em28xx_isocdbg("packet bigger than packet size");
+                       continue;
+               }
+
+               p = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
+
+               /* FIXME: incomplete buffer checks where removed to make
+                  logic simpler. Impacts of those changes should be evaluated
+                */
+               if (p[0] == 0x33 && p[1] == 0x95 && p[2] == 0x00) {
+                       em28xx_isocdbg("VBI HEADER!!!\n");
+                       /* FIXME: Should add vbi copy */
+                       continue;
+               }
+               if (p[0] == 0x22 && p[1] == 0x5a) {
+                       em28xx_isocdbg("Video frame %d, length=%i, %s\n", p[2],
+                                      len, (p[2] & 1)? "odd" : "even");
+
+                       if (!(p[2] & 1)) {
+                               if (buf != NULL)
+                                       buffer_filled(dev, dma_q, buf);
+                               get_next_buf(dma_q, &buf);
+                               if (buf == NULL)
+                                       outp = NULL;
+                               else
+                                       outp = videobuf_to_vmalloc(&buf->vb);
+                       }
+
+                       if (buf != NULL) {
+                               if (p[2] & 1)
+                                       buf->top_field = 0;
+                               else
+                                       buf->top_field = 1;
+                       }
+
+                       dma_q->pos = 0;
+               }
+               if (buf != NULL)
+                       em28xx_copy_video(dev, dma_q, buf, p, outp, len);
+       }
+       return rc;
+}
+
+/* ------------------------------------------------------------------
+       Videobuf operations
+   ------------------------------------------------------------------*/
+
+static int
+buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size)
+{
+       struct em28xx_fh *fh = vq->priv_data;
+       struct em28xx        *dev = fh->dev;
+       struct v4l2_frequency f;
+
+       *size = 16 * fh->dev->width * fh->dev->height >> 3;
+       if (0 == *count)
+               *count = EM28XX_DEF_BUF;
+
+       if (*count < EM28XX_MIN_BUF)
+               *count = EM28XX_MIN_BUF;
+
+       /* Ask tuner to go to analog mode */
+       memset(&f, 0, sizeof(f));
+       f.frequency = dev->ctl_freq;
+
+       em28xx_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, &f);
+
+       return 0;
+}
+
+/* This is called *without* dev->slock held; please keep it that way */
+static void free_buffer(struct videobuf_queue *vq, struct em28xx_buffer *buf)
+{
+       struct em28xx_fh     *fh  = vq->priv_data;
+       struct em28xx        *dev = fh->dev;
+       unsigned long flags = 0;
+       if (in_interrupt())
+               BUG();
+
+       /* We used to wait for the buffer to finish here, but this didn't work
+          because, as we were keeping the state as VIDEOBUF_QUEUED,
+          videobuf_queue_cancel marked it as finished for us.
+          (Also, it could wedge forever if the hardware was misconfigured.)
+
+          This should be safe; by the time we get here, the buffer isn't
+          queued anymore. If we ever start marking the buffers as
+          VIDEOBUF_ACTIVE, it won't be, though.
+       */
+       spin_lock_irqsave(&dev->slock, flags);
+       if (dev->isoc_ctl.buf == buf)
+               dev->isoc_ctl.buf = NULL;
+       spin_unlock_irqrestore(&dev->slock, flags);
+
+       videobuf_vmalloc_free(&buf->vb);
+       buf->vb.state = VIDEOBUF_NEEDS_INIT;
+}
+
+static int
+buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
+                                               enum v4l2_field field)
+{
+       struct em28xx_fh     *fh  = vq->priv_data;
+       struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb);
+       struct em28xx        *dev = fh->dev;
+       int                  rc = 0, urb_init = 0;
+
+       /* FIXME: It assumes depth = 16 */
+       /* The only currently supported format is 16 bits/pixel */
+       buf->vb.size = 16 * dev->width * dev->height >> 3;
+
+       if (0 != buf->vb.baddr  &&  buf->vb.bsize < buf->vb.size)
+               return -EINVAL;
+
+       buf->vb.width  = dev->width;
+       buf->vb.height = dev->height;
+       buf->vb.field  = field;
+
+       if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+               rc = videobuf_iolock(vq, &buf->vb, NULL);
+               if (rc < 0)
+                       goto fail;
+       }
+
+       if (!dev->isoc_ctl.num_bufs)
+               urb_init = 1;
+
+       if (urb_init) {
+               rc = em28xx_init_isoc(dev, EM28XX_NUM_PACKETS,
+                                     EM28XX_NUM_BUFS, dev->max_pkt_size,
+                                     em28xx_isoc_copy);
+               if (rc < 0)
+                       goto fail;
+       }
+
+       buf->vb.state = VIDEOBUF_PREPARED;
+       return 0;
+
+fail:
+       free_buffer(vq, buf);
+       return rc;
+}
+
+static void
+buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+       struct em28xx_buffer    *buf     = container_of(vb, struct em28xx_buffer, vb);
+       struct em28xx_fh        *fh      = vq->priv_data;
+       struct em28xx           *dev     = fh->dev;
+       struct em28xx_dmaqueue  *vidq    = &dev->vidq;
+
+       buf->vb.state = VIDEOBUF_QUEUED;
+       list_add_tail(&buf->vb.queue, &vidq->active);
+
+}
+
+static void buffer_release(struct videobuf_queue *vq,
+                               struct videobuf_buffer *vb)
+{
+       struct em28xx_buffer   *buf  = container_of(vb, struct em28xx_buffer, vb);
+       struct em28xx_fh       *fh   = vq->priv_data;
+       struct em28xx          *dev  = (struct em28xx *)fh->dev;
+
+       em28xx_isocdbg("em28xx: called buffer_release\n");
+
+       free_buffer(vq, buf);
+}
+
+static struct videobuf_queue_ops em28xx_video_qops = {
+       .buf_setup      = buffer_setup,
+       .buf_prepare    = buffer_prepare,
+       .buf_queue      = buffer_queue,
+       .buf_release    = buffer_release,
+};
+
+/*********************  v4l2 interface  **************************************/
 
 /*
  * em28xx_config()
@@ -123,9 +519,9 @@ static int em28xx_config(struct em28xx *dev)
 
        /* enable vbi capturing */
 
-/*     em28xx_write_regs_req(dev,0x00,0x0e,"\xC0",1); audio register */
-/*     em28xx_write_regs_req(dev,0x00,0x0f,"\x80",1); clk register */
-       em28xx_write_regs_req(dev,0x00,0x11,"\x51",1);
+/*     em28xx_write_regs_req(dev, 0x00, 0x0e, "\xC0", 1); audio register */
+/*     em28xx_write_regs_req(dev, 0x00, 0x0f, "\x80", 1); clk register */
+       em28xx_write_regs_req(dev, 0x00, 0x11, "\x51", 1);
 
        dev->mute = 1;          /* maybe not the right place... */
        dev->volume = 0x1f;
@@ -152,23 +548,6 @@ static void em28xx_config_i2c(struct em28xx *dev)
        em28xx_i2c_call_clients(dev, VIDIOC_STREAMON, NULL);
 }
 
-/*
- * em28xx_empty_framequeues()
- * prepare queues for incoming and outgoing frames
- */
-static void em28xx_empty_framequeues(struct em28xx *dev)
-{
-       u32 i;
-
-       INIT_LIST_HEAD(&dev->inqueue);
-       INIT_LIST_HEAD(&dev->outqueue);
-
-       for (i = 0; i < EM28XX_NUM_FRAMES; i++) {
-               dev->frame[i].state = F_UNUSED;
-               dev->frame[i].buf.bytesused = 0;
-       }
-}
-
 static void video_mux(struct em28xx *dev, int index)
 {
        struct v4l2_routing route;
@@ -181,12 +560,15 @@ static void video_mux(struct em28xx *dev, int index)
        em28xx_i2c_call_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route);
 
        if (dev->has_msp34xx) {
-               if (dev->i2s_speed)
-                       em28xx_i2c_call_clients(dev, VIDIOC_INT_I2S_CLOCK_FREQ, &dev->i2s_speed);
+               if (dev->i2s_speed) {
+                       em28xx_i2c_call_clients(dev, VIDIOC_INT_I2S_CLOCK_FREQ,
+                               &dev->i2s_speed);
+               }
                route.input = dev->ctl_ainput;
                route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1);
                /* Note: this is msp3400 specific */
-               em28xx_i2c_call_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING, &route);
+               em28xx_i2c_call_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING,
+                       &route);
        }
 
        em28xx_audio_analog_set(dev);
@@ -202,15 +584,12 @@ static int res_get(struct em28xx_fh *fh)
        if (fh->stream_on)
                return rc;
 
-       mutex_lock(&dev->lock);
-
        if (dev->stream_on)
-               rc = -EINVAL;
-       else {
-               dev->stream_on = 1;
-               fh->stream_on  = 1;
-       }
+               return -EINVAL;
 
+       mutex_lock(&dev->lock);
+       dev->stream_on = 1;
+       fh->stream_on  = 1;
        mutex_unlock(&dev->lock);
        return rc;
 }
@@ -230,33 +609,6 @@ static void res_free(struct em28xx_fh *fh)
        mutex_unlock(&dev->lock);
 }
 
-/*
- * em28xx_vm_open()
- */
-static void em28xx_vm_open(struct vm_area_struct *vma)
-{
-       struct em28xx_frame_t *f = vma->vm_private_data;
-       f->vma_use_count++;
-}
-
-/*
- * em28xx_vm_close()
- */
-static void em28xx_vm_close(struct vm_area_struct *vma)
-{
-       /* NOTE: buffers are not freed here */
-       struct em28xx_frame_t *f = vma->vm_private_data;
-
-       if (f->vma_use_count)
-               f->vma_use_count--;
-}
-
-static struct vm_operations_struct em28xx_vm_ops = {
-       .open = em28xx_vm_open,
-       .close = em28xx_vm_close,
-};
-
-
 /*
  * em28xx_get_ctrl()
  * return the current saturation, brightness or contrast, mute state
@@ -296,34 +648,6 @@ static int em28xx_set_ctrl(struct em28xx *dev, const struct v4l2_control *ctrl)
        }
 }
 
-/*
- * em28xx_stream_interrupt()
- * stops streaming
- */
-static int em28xx_stream_interrupt(struct em28xx *dev)
-{
-       int rc = 0;
-
-       /* stop reading from the device */
-
-       dev->stream = STREAM_INTERRUPT;
-       rc = wait_event_timeout(dev->wait_stream,
-                               (dev->stream == STREAM_OFF) ||
-                               (dev->state & DEV_DISCONNECTED),
-                               EM28XX_URB_TIMEOUT);
-
-       if (rc) {
-               dev->state |= DEV_MISCONFIGURED;
-               em28xx_videodbg("device is misconfigured; close and "
-                       "open /dev/video%d again\n",
-                               dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN);
-               return rc;
-       }
-
-       return 0;
-}
-
-
 static int check_dev(struct em28xx *dev)
 {
        if (dev->state & DEV_DISCONNECTED) {
@@ -370,8 +694,8 @@ static int vidioc_g_fmt_cap(struct file *file, void *priv,
        f->fmt.pix.width = dev->width;
        f->fmt.pix.height = dev->height;
        f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
-       f->fmt.pix.bytesperline = dev->bytesperline;
-       f->fmt.pix.sizeimage = dev->frame_size;
+       f->fmt.pix.bytesperline = dev->width * 2;
+       f->fmt.pix.sizeimage = f->fmt.pix.bytesperline  * dev->height;
        f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
 
        /* FIXME: TOP? NONE? BOTTOM? ALTENATE? */
@@ -447,7 +771,7 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv,
 {
        struct em28xx_fh      *fh  = priv;
        struct em28xx         *dev = fh->dev;
-       int                   rc, i;
+       int                   rc;
 
        rc = check_dev(dev);
        if (rc < 0)
@@ -457,49 +781,34 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv,
 
        mutex_lock(&dev->lock);
 
-       for (i = 0; i < dev->num_frames; i++)
-               if (dev->frame[i].vma_use_count) {
-                       em28xx_videodbg("VIDIOC_S_FMT failed. "
-                                       "Unmap the buffers first.\n");
-                       rc = -EINVAL;
-                       goto err;
-               }
-
-       /* stop io in case it is already in progress */
-       if (dev->stream == STREAM_ON) {
-               em28xx_videodbg("VIDIOC_SET_FMT: interrupting stream\n");
-               rc = em28xx_stream_interrupt(dev);
-               if (rc < 0)
-                       goto err;
+       if (videobuf_queue_is_busy(&fh->vb_vidq)) {
+               em28xx_errdev("%s queue busy\n", __func__);
+               rc = -EBUSY;
+               goto out;
        }
 
-       em28xx_release_buffers(dev);
-       dev->io = IO_NONE;
+       if (dev->stream_on && !fh->stream_on) {
+               em28xx_errdev("%s device in use by another fh\n", __func__);
+               rc = -EBUSY;
+               goto out;
+       }
 
        /* set new image size */
        dev->width = f->fmt.pix.width;
        dev->height = f->fmt.pix.height;
-       dev->frame_size = dev->width * dev->height * 2;
-       dev->field_size = dev->frame_size >> 1;
-       dev->bytesperline = dev->width * 2;
        get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
 
-       /* FIXME: This is really weird! Why capture is starting with
-          this ioctl ???
-        */
-       em28xx_uninit_isoc(dev);
        em28xx_set_alternate(dev);
-       em28xx_capture_start(dev, 1);
        em28xx_resolution_set(dev);
-       em28xx_init_isoc(dev);
+
        rc = 0;
 
-err:
+out:
        mutex_unlock(&dev->lock);
        return rc;
 }
 
-static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm)
+static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * norm)
 {
        struct em28xx_fh   *fh  = priv;
        struct em28xx      *dev = fh->dev;
@@ -524,9 +833,6 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm)
        /* set new image size */
        dev->width = f.fmt.pix.width;
        dev->height = f.fmt.pix.height;
-       dev->frame_size = dev->width * dev->height * 2;
-       dev->field_size = dev->frame_size >> 1;
-       dev->bytesperline = dev->width * 2;
        get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
 
        em28xx_resolution_set(dev);
@@ -619,11 +925,11 @@ static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
 
        index = dev->ctl_ainput;
 
-       if (index == 0) {
+       if (index == 0)
                strcpy(a->name, "Television");
-       } else {
+       else
                strcpy(a->name, "Line In");
-       }
+
        a->capability = V4L2_AUDCAP_STEREO;
        a->index = index;
 
@@ -834,9 +1140,9 @@ static int vidioc_s_frequency(struct file *file, void *priv,
 static int em28xx_reg_len(int reg)
 {
        switch (reg) {
-       case AC97LSB_REG:
-       case HSCALELOW_REG:
-       case VSCALELOW_REG:
+       case EM28XX_R40_AC97LSB:
+       case EM28XX_R30_HSCALELOW:
+       case EM28XX_R32_VSCALELOW:
                return 2;
        default:
                return 1;
@@ -918,23 +1224,11 @@ static int vidioc_streamon(struct file *file, void *priv,
        if (rc < 0)
                return rc;
 
-       if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || dev->io != IO_MMAP)
-               return -EINVAL;
-
-       if (list_empty(&dev->inqueue))
-               return -EINVAL;
-
-       mutex_lock(&dev->lock);
 
-       if (unlikely(res_get(fh) < 0)) {
-               mutex_unlock(&dev->lock);
+       if (unlikely(res_get(fh) < 0))
                return -EBUSY;
-       }
 
-       dev->stream = STREAM_ON;        /* FIXME: Start video capture here? */
-
-       mutex_unlock(&dev->lock);
-       return 0;
+       return (videobuf_streamon(&fh->vb_vidq));
 }
 
 static int vidioc_streamoff(struct file *file, void *priv,
@@ -948,23 +1242,14 @@ static int vidioc_streamoff(struct file *file, void *priv,
        if (rc < 0)
                return rc;
 
-       if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || dev->io != IO_MMAP)
+       if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+       if (type != fh->type)
                return -EINVAL;
 
-       mutex_lock(&dev->lock);
-
-       if (dev->stream == STREAM_ON) {
-               em28xx_videodbg("VIDIOC_STREAMOFF: interrupting stream\n");
-               rc = em28xx_stream_interrupt(dev);
-               if (rc < 0) {
-                       mutex_unlock(&dev->lock);
-                       return rc;
-               }
-       }
-
-       em28xx_empty_framequeues(dev);
+       videobuf_streamoff(&fh->vb_vidq);
+       res_free(fh);
 
-       mutex_unlock(&dev->lock);
        return 0;
 }
 
@@ -1058,53 +1343,13 @@ static int vidioc_reqbufs(struct file *file, void *priv,
 {
        struct em28xx_fh      *fh  = priv;
        struct em28xx         *dev = fh->dev;
-       u32                   i;
        int                   rc;
 
        rc = check_dev(dev);
        if (rc < 0)
                return rc;
 
-       if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
-               rb->memory != V4L2_MEMORY_MMAP)
-               return -EINVAL;
-
-       if (dev->io == IO_READ) {
-               em28xx_videodbg("method is set to read;"
-                               " close and open the device again to"
-                               " choose the mmap I/O method\n");
-               return -EINVAL;
-       }
-
-       for (i = 0; i < dev->num_frames; i++)
-               if (dev->frame[i].vma_use_count) {
-                       em28xx_videodbg("VIDIOC_REQBUFS failed; "
-                                       "previous buffers are still mapped\n");
-                       return -EINVAL;
-               }
-
-       mutex_lock(&dev->lock);
-
-       if (dev->stream == STREAM_ON) {
-               em28xx_videodbg("VIDIOC_REQBUFS: interrupting stream\n");
-               rc = em28xx_stream_interrupt(dev);
-               if (rc < 0) {
-                       mutex_unlock(&dev->lock);
-                       return rc;
-               }
-       }
-
-       em28xx_empty_framequeues(dev);
-
-       em28xx_release_buffers(dev);
-       if (rb->count)
-               rb->count = em28xx_request_buffers(dev, rb->count);
-
-       dev->frame_current = NULL;
-       dev->io = rb->count ? IO_MMAP : IO_NONE;
-
-       mutex_unlock(&dev->lock);
-       return 0;
+       return (videobuf_reqbufs(&fh->vb_vidq, rb));
 }
 
 static int vidioc_querybuf(struct file *file, void *priv,
@@ -1118,52 +1363,20 @@ static int vidioc_querybuf(struct file *file, void *priv,
        if (rc < 0)
                return rc;
 
-       if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
-               b->index >= dev->num_frames || dev->io != IO_MMAP)
-               return -EINVAL;
-
-       mutex_lock(&dev->lock);
-
-       memcpy(b, &dev->frame[b->index].buf, sizeof(*b));
-
-       if (dev->frame[b->index].vma_use_count)
-               b->flags |= V4L2_BUF_FLAG_MAPPED;
-
-       if (dev->frame[b->index].state == F_DONE)
-               b->flags |= V4L2_BUF_FLAG_DONE;
-       else if (dev->frame[b->index].state != F_UNUSED)
-               b->flags |= V4L2_BUF_FLAG_QUEUED;
-
-       mutex_unlock(&dev->lock);
-       return 0;
+       return (videobuf_querybuf(&fh->vb_vidq, b));
 }
 
 static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
 {
        struct em28xx_fh      *fh  = priv;
        struct em28xx         *dev = fh->dev;
-       unsigned long         lock_flags;
        int                   rc;
 
        rc = check_dev(dev);
        if (rc < 0)
                return rc;
 
-       if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE  || dev->io != IO_MMAP ||
-                                               b->index >= dev->num_frames)
-               return -EINVAL;
-
-       if (dev->frame[b->index].state != F_UNUSED)
-               return -EAGAIN;
-
-       dev->frame[b->index].state = F_QUEUED;
-
-       /* add frame to fifo */
-       spin_lock_irqsave(&dev->queue_lock, lock_flags);
-       list_add_tail(&dev->frame[b->index].frame, &dev->inqueue);
-       spin_unlock_irqrestore(&dev->queue_lock, lock_flags);
-
-       return 0;
+       return (videobuf_qbuf(&fh->vb_vidq, b));
 }
 
 static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
@@ -1171,46 +1384,24 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
        struct em28xx_fh      *fh  = priv;
        struct em28xx         *dev = fh->dev;
        int                   rc;
-       struct em28xx_frame_t *f;
-       unsigned long         lock_flags;
 
        rc = check_dev(dev);
        if (rc < 0)
                return rc;
 
-       if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || dev->io != IO_MMAP)
-               return -EINVAL;
-
-       if (list_empty(&dev->outqueue)) {
-               if (dev->stream == STREAM_OFF)
-                       return -EINVAL;
-
-               if (file->f_flags & O_NONBLOCK)
-                       return -EAGAIN;
-
-               rc = wait_event_interruptible(dev->wait_frame,
-                                       (!list_empty(&dev->outqueue)) ||
-                                       (dev->state & DEV_DISCONNECTED));
-               if (rc)
-                       return rc;
-
-               if (dev->state & DEV_DISCONNECTED)
-                       return -ENODEV;
-       }
-
-       spin_lock_irqsave(&dev->queue_lock, lock_flags);
-       f = list_entry(dev->outqueue.next, struct em28xx_frame_t, frame);
-       list_del(dev->outqueue.next);
-       spin_unlock_irqrestore(&dev->queue_lock, lock_flags);
-
-       f->state = F_UNUSED;
-       memcpy(b, &f->buf, sizeof(*b));
+       return (videobuf_dqbuf(&fh->vb_vidq, b,
+                               file->f_flags & O_NONBLOCK));
+}
 
-       if (f->vma_use_count)
-               b->flags |= V4L2_BUF_FLAG_MAPPED;
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
+{
+       struct em28xx_fh  *fh = priv;
 
-       return 0;
+       return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8);
 }
+#endif
+
 
 /* ----------------------------------------------------------- */
 /* RADIO ESPECIFIC IOCTLS                                      */
@@ -1316,17 +1507,18 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
 {
        int minor = iminor(inode);
        int errCode = 0, radio = 0;
-       struct em28xx *h,*dev = NULL;
+       struct em28xx *h, *dev = NULL;
        struct em28xx_fh *fh;
+       enum v4l2_buf_type fh_type = 0;
 
        list_for_each_entry(h, &em28xx_devlist, devlist) {
                if (h->vdev->minor == minor) {
                        dev  = h;
-                       dev->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+                       fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
                }
                if (h->vbi_dev->minor == minor) {
                        dev  = h;
-                       dev->type = V4L2_BUF_TYPE_VBI_CAPTURE;
+                       fh_type = V4L2_BUF_TYPE_VBI_CAPTURE;
                }
                if (h->radio_dev &&
                    h->radio_dev->minor == minor) {
@@ -1338,10 +1530,10 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
                return -ENODEV;
 
        em28xx_videodbg("open minor=%d type=%s users=%d\n",
-                               minor,v4l2_type_names[dev->type],dev->users);
+                               minor, v4l2_type_names[fh_type], dev->users);
 
-       fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL);
 
+       fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL);
        if (!fh) {
                em28xx_errdev("em28xx-video.c: Out of memory?!\n");
                return -ENOMEM;
@@ -1349,28 +1541,24 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
        mutex_lock(&dev->lock);
        fh->dev = dev;
        fh->radio = radio;
+       fh->type = fh_type;
        filp->private_data = fh;
 
-       if (dev->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) {
+       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) {
                dev->width = norm_maxw(dev);
                dev->height = norm_maxh(dev);
-               dev->frame_size = dev->width * dev->height * 2;
-               dev->field_size = dev->frame_size >> 1; /*both_fileds ? dev->frame_size>>1 : dev->frame_size; */
-               dev->bytesperline = dev->width * 2;
                dev->hscale = 0;
                dev->vscale = 0;
 
+               em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
                em28xx_set_alternate(dev);
-               em28xx_capture_start(dev, 1);
                em28xx_resolution_set(dev);
 
+               /* Needed, since GPIO might have disabled power of
+                  some i2c device
+                */
+               em28xx_config_i2c(dev);
 
-               /* start the transfer */
-               errCode = em28xx_init_isoc(dev);
-               if (errCode)
-                       goto err;
-
-               em28xx_empty_framequeues(dev);
        }
        if (fh->radio) {
                em28xx_videodbg("video_open: setting radio device\n");
@@ -1379,8 +1567,12 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
 
        dev->users++;
 
-err:
+       videobuf_queue_vmalloc_init(&fh->vb_vidq, &em28xx_video_qops,
+                       NULL, &dev->slock, fh->type, V4L2_FIELD_INTERLACED,
+                       sizeof(struct em28xx_buffer), fh);
+
        mutex_unlock(&dev->lock);
+
        return errCode;
 }
 
@@ -1423,12 +1615,13 @@ static void em28xx_release_resources(struct em28xx *dev)
        usb_put_dev(dev->udev);
 
        /* Mark device as unused */
-       em28xx_devused&=~(1<<dev->devno);
+       em28xx_devused &= ~(1<<dev->devno);
 }
 
 /*
  * em28xx_v4l2_close()
- * stops streaming and deallocates all resources allocated by the v4l2 calls and ioctls
+ * stops streaming and deallocates all resources allocated by the v4l2
+ * calls and ioctls
  */
 static int em28xx_v4l2_close(struct inode *inode, struct file *filp)
 {
@@ -1445,9 +1638,8 @@ static int em28xx_v4l2_close(struct inode *inode, struct file *filp)
        mutex_lock(&dev->lock);
 
        if (dev->users == 1) {
-               em28xx_uninit_isoc(dev);
-               em28xx_release_buffers(dev);
-               dev->io = IO_NONE;
+               videobuf_stop(&fh->vb_vidq);
+               videobuf_mmap_free(&fh->vb_vidq);
 
                /* the device is already disconnect,
                   free the remaining resources */
@@ -1458,6 +1650,10 @@ static int em28xx_v4l2_close(struct inode *inode, struct file *filp)
                        return 0;
                }
 
+               /* do this before setting alternate! */
+               em28xx_uninit_isoc(dev);
+               em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED);
+
                /* set alternate 0 */
                dev->alt = 0;
                em28xx_videodbg("setting alternate 0\n");
@@ -1479,135 +1675,29 @@ static int em28xx_v4l2_close(struct inode *inode, struct file *filp)
  * will allocate buffers when called for the first time
  */
 static ssize_t
-em28xx_v4l2_read(struct file *filp, char __user * buf, size_t count,
-                loff_t * f_pos)
+em28xx_v4l2_read(struct file *filp, char __user *buf, size_t count,
+                loff_t *pos)
 {
-       struct em28xx_frame_t *f, *i;
-       unsigned long lock_flags;
-       int ret = 0;
        struct em28xx_fh *fh = filp->private_data;
        struct em28xx *dev = fh->dev;
+       int rc;
+
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
 
        /* FIXME: read() is not prepared to allow changing the video
           resolution while streaming. Seems a bug at em28xx_set_fmt
         */
 
-       if (unlikely(res_get(fh) < 0))
-               return -EBUSY;
-
-       mutex_lock(&dev->lock);
-
-       if (dev->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               em28xx_videodbg("V4l2_Buf_type_videocapture is set\n");
+       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               if (unlikely(res_get(fh)))
+                       return -EBUSY;
 
-       if (dev->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
-               em28xx_videodbg("V4L2_BUF_TYPE_VBI_CAPTURE is set\n");
-               em28xx_videodbg("not supported yet! ...\n");
-               if (copy_to_user(buf, "", 1)) {
-                       mutex_unlock(&dev->lock);
-                       return -EFAULT;
-               }
-               mutex_unlock(&dev->lock);
-               return (1);
-       }
-       if (dev->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {
-               em28xx_videodbg("V4L2_BUF_TYPE_SLICED_VBI_CAPTURE is set\n");
-               em28xx_videodbg("not supported yet! ...\n");
-               if (copy_to_user(buf, "", 1)) {
-                       mutex_unlock(&dev->lock);
-                       return -EFAULT;
-               }
-               mutex_unlock(&dev->lock);
-               return (1);
+               return videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0,
+                                       filp->f_flags & O_NONBLOCK);
        }
-
-       if (dev->state & DEV_DISCONNECTED) {
-               em28xx_videodbg("device not present\n");
-               mutex_unlock(&dev->lock);
-               return -ENODEV;
-       }
-
-       if (dev->state & DEV_MISCONFIGURED) {
-               em28xx_videodbg("device misconfigured; close and open it again\n");
-               mutex_unlock(&dev->lock);
-               return -EIO;
-       }
-
-       if (dev->io == IO_MMAP) {
-               em28xx_videodbg ("IO method is set to mmap; close and open"
-                               " the device again to choose the read method\n");
-               mutex_unlock(&dev->lock);
-               return -EINVAL;
-       }
-
-       if (dev->io == IO_NONE) {
-               if (!em28xx_request_buffers(dev, EM28XX_NUM_READ_FRAMES)) {
-                       em28xx_errdev("read failed, not enough memory\n");
-                       mutex_unlock(&dev->lock);
-                       return -ENOMEM;
-               }
-               dev->io = IO_READ;
-               dev->stream = STREAM_ON;
-               em28xx_queue_unusedframes(dev);
-       }
-
-       if (!count) {
-               mutex_unlock(&dev->lock);
-               return 0;
-       }
-
-       if (list_empty(&dev->outqueue)) {
-               if (filp->f_flags & O_NONBLOCK) {
-                       mutex_unlock(&dev->lock);
-                       return -EAGAIN;
-               }
-               ret = wait_event_interruptible
-                   (dev->wait_frame,
-                    (!list_empty(&dev->outqueue)) ||
-                    (dev->state & DEV_DISCONNECTED));
-               if (ret) {
-                       mutex_unlock(&dev->lock);
-                       return ret;
-               }
-               if (dev->state & DEV_DISCONNECTED) {
-                       mutex_unlock(&dev->lock);
-                       return -ENODEV;
-               }
-               dev->video_bytesread = 0;
-       }
-
-       f = list_entry(dev->outqueue.prev, struct em28xx_frame_t, frame);
-
-       em28xx_queue_unusedframes(dev);
-
-       if (count > f->buf.length)
-               count = f->buf.length;
-
-       if ((dev->video_bytesread + count) > dev->frame_size)
-               count = dev->frame_size - dev->video_bytesread;
-
-       if (copy_to_user(buf, f->bufmem+dev->video_bytesread, count)) {
-               em28xx_err("Error while copying to user\n");
-               return -EFAULT;
-       }
-       dev->video_bytesread += count;
-
-       if (dev->video_bytesread == dev->frame_size) {
-               spin_lock_irqsave(&dev->queue_lock, lock_flags);
-               list_for_each_entry(i, &dev->outqueue, frame)
-                                   i->state = F_UNUSED;
-               INIT_LIST_HEAD(&dev->outqueue);
-               spin_unlock_irqrestore(&dev->queue_lock, lock_flags);
-
-               em28xx_queue_unusedframes(dev);
-               dev->video_bytesread = 0;
-       }
-
-       *f_pos += count;
-
-       mutex_unlock(&dev->lock);
-
-       return count;
+       return 0;
 }
 
 /*
@@ -1616,46 +1706,21 @@ em28xx_v4l2_read(struct file *filp, char __user * buf, size_t count,
  */
 static unsigned int em28xx_v4l2_poll(struct file *filp, poll_table * wait)
 {
-       unsigned int mask = 0;
        struct em28xx_fh *fh = filp->private_data;
        struct em28xx *dev = fh->dev;
+       int rc;
+
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
 
        if (unlikely(res_get(fh) < 0))
                return POLLERR;
 
-       mutex_lock(&dev->lock);
-
-       if (dev->state & DEV_DISCONNECTED) {
-               em28xx_videodbg("device not present\n");
-       } else if (dev->state & DEV_MISCONFIGURED) {
-               em28xx_videodbg("device is misconfigured; close and open it again\n");
-       } else {
-               if (dev->io == IO_NONE) {
-                       if (!em28xx_request_buffers
-                           (dev, EM28XX_NUM_READ_FRAMES)) {
-                               em28xx_warn
-                                   ("poll() failed, not enough memory\n");
-                       } else {
-                               dev->io = IO_READ;
-                               dev->stream = STREAM_ON;
-                       }
-               }
-
-               if (dev->io == IO_READ) {
-                       em28xx_queue_unusedframes(dev);
-                       poll_wait(filp, &dev->wait_frame, wait);
-
-                       if (!list_empty(&dev->outqueue))
-                               mask |= POLLIN | POLLRDNORM;
-
-                       mutex_unlock(&dev->lock);
-
-                       return mask;
-               }
-       }
+       if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type)
+               return POLLERR;
 
-       mutex_unlock(&dev->lock);
-       return POLLERR;
+       return videobuf_poll_stream(filp, &fh->vb_vidq, wait);
 }
 
 /*
@@ -1665,69 +1730,23 @@ static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
 {
        struct em28xx_fh *fh    = filp->private_data;
        struct em28xx    *dev   = fh->dev;
-       unsigned long    size   = vma->vm_end - vma->vm_start;
-       unsigned long    start  = vma->vm_start;
-       void             *pos;
-       u32              i;
+       int              rc;
 
        if (unlikely(res_get(fh) < 0))
                return -EBUSY;
 
-       mutex_lock(&dev->lock);
-
-       if (dev->state & DEV_DISCONNECTED) {
-               em28xx_videodbg("mmap: device not present\n");
-               mutex_unlock(&dev->lock);
-               return -ENODEV;
-       }
-
-       if (dev->state & DEV_MISCONFIGURED) {
-               em28xx_videodbg ("mmap: Device is misconfigured; close and "
-                                               "open it again\n");
-               mutex_unlock(&dev->lock);
-               return -EIO;
-       }
-
-       if (dev->io != IO_MMAP || !(vma->vm_flags & VM_WRITE)) {
-               mutex_unlock(&dev->lock);
-               return -EINVAL;
-       }
-
-       if (size > PAGE_ALIGN(dev->frame[0].buf.length))
-               size = PAGE_ALIGN(dev->frame[0].buf.length);
-
-       for (i = 0; i < dev->num_frames; i++) {
-               if ((dev->frame[i].buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff)
-                       break;
-       }
-       if (i == dev->num_frames) {
-               em28xx_videodbg("mmap: user supplied mapping address is out of range\n");
-               mutex_unlock(&dev->lock);
-               return -EINVAL;
-       }
-
-       /* VM_IO is eventually going to replace PageReserved altogether */
-       vma->vm_flags |= VM_IO;
-       vma->vm_flags |= VM_RESERVED;   /* avoid to swap out this VMA */
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
 
-       pos = dev->frame[i].bufmem;
-       while (size > 0) {      /* size is page-aligned */
-               if (vm_insert_page(vma, start, vmalloc_to_page(pos))) {
-                       em28xx_videodbg("mmap: vm_insert_page failed\n");
-                       mutex_unlock(&dev->lock);
-                       return -EAGAIN;
-               }
-               start += PAGE_SIZE;
-               pos += PAGE_SIZE;
-               size -= PAGE_SIZE;
-       }
+       rc = videobuf_mmap_mapper(&fh->vb_vidq, vma);
 
-       vma->vm_ops = &em28xx_vm_ops;
-       vma->vm_private_data = &dev->frame[i];
+       em28xx_videodbg("vma start=0x%08lx, size=%ld, ret=%d\n",
+               (unsigned long)vma->vm_start,
+               (unsigned long)vma->vm_end-(unsigned long)vma->vm_start,
+               rc);
 
-       em28xx_vm_open(vma);
-       mutex_unlock(&dev->lock);
-       return 0;
+       return rc;
 }
 
 static const struct file_operations em28xx_v4l_fops = {
@@ -1790,6 +1809,9 @@ static const struct video_device em28xx_video_template = {
        .vidioc_g_register          = vidioc_g_register,
        .vidioc_s_register          = vidioc_s_register,
 #endif
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+       .vidiocgmbuf                = vidiocgmbuf,
+#endif
 
        .tvnorms                    = V4L2_STD_ALL,
        .current_norm               = V4L2_STD_PAL,
@@ -1818,7 +1840,7 @@ static struct video_device em28xx_radio_template = {
 #endif
 };
 
-/******************************** usb interface *****************************************/
+/******************************** usb interface ******************************/
 
 
 static LIST_HEAD(em28xx_extension_devlist);
@@ -1875,6 +1897,7 @@ static struct video_device *em28xx_vdev_init(struct em28xx *dev,
        vfd->dev = &dev->udev->dev;
        vfd->release = video_device_release;
        vfd->type = type;
+       vfd->debug = video_debug;
 
        snprintf(vfd->name, sizeof(vfd->name), "%s %s",
                 dev->name, type_name);
@@ -1898,7 +1921,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
 
        dev->udev = udev;
        mutex_init(&dev->lock);
-       spin_lock_init(&dev->queue_lock);
+       spin_lock_init(&dev->slock);
        init_waitqueue_head(&dev->open);
        init_waitqueue_head(&dev->wait_frame);
        init_waitqueue_head(&dev->wait_stream);
@@ -1910,10 +1933,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
        dev->em28xx_read_reg_req = em28xx_read_reg_req;
        dev->is_em2800 = em28xx_boards[dev->model].is_em2800;
 
-       errCode = em28xx_read_reg(dev, CHIPID_REG);
-       if (errCode >= 0)
-               em28xx_info("em28xx chip ID = %d\n", errCode);
-
        em28xx_pre_card_setup(dev);
 
        errCode = em28xx_config(dev);
@@ -1946,10 +1965,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
        dev->width = maxw;
        dev->height = maxh;
        dev->interlaced = EM28XX_INTERLACED_DEFAULT;
-       dev->field_size = dev->width * dev->height;
-       dev->frame_size =
-           dev->interlaced ? dev->field_size << 1 : dev->field_size;
-       dev->bytesperline = dev->width * 2;
        dev->hscale = 0;
        dev->vscale = 0;
        dev->ctl_input = 2;
@@ -2005,6 +2020,10 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
                            dev->radio_dev->minor & 0x1f);
        }
 
+       /* init video dma queues */
+       INIT_LIST_HEAD(&dev->vidq.active);
+       INIT_LIST_HEAD(&dev->vidq.queued);
+
 
        if (dev->has_msp34xx) {
                /* Send a reset to other chips via gpio */
@@ -2048,6 +2067,9 @@ static void request_module_async(struct work_struct *work)
                request_module("snd-usb-audio");
        else
                request_module("em28xx-alsa");
+
+       if (dev->has_dvb)
+               request_module("em28xx-dvb");
 }
 
 static void request_modules(struct em28xx *dev)
@@ -2077,22 +2099,24 @@ static int em28xx_usb_probe(struct usb_interface *interface,
        ifnum = interface->altsetting[0].desc.bInterfaceNumber;
 
        /* Check to see next free device and mark as used */
-       nr=find_first_zero_bit(&em28xx_devused,EM28XX_MAXBOARDS);
-       em28xx_devused|=1<<nr;
+       nr = find_first_zero_bit(&em28xx_devused, EM28XX_MAXBOARDS);
+       em28xx_devused |= 1<<nr;
 
        /* Don't register audio interfaces */
        if (interface->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) {
                em28xx_err(DRIVER_NAME " audio device (%04x:%04x): interface %i, class %i\n",
-                               udev->descriptor.idVendor,udev->descriptor.idProduct,
+                               udev->descriptor.idVendor,
+                               udev->descriptor.idProduct,
                                ifnum,
                                interface->altsetting[0].desc.bInterfaceClass);
 
-               em28xx_devused&=~(1<<nr);
+               em28xx_devused &= ~(1<<nr);
                return -ENODEV;
        }
 
        em28xx_err(DRIVER_NAME " new video device (%04x:%04x): interface %i, class %i\n",
-                       udev->descriptor.idVendor,udev->descriptor.idProduct,
+                       udev->descriptor.idVendor,
+                       udev->descriptor.idProduct,
                        ifnum,
                        interface->altsetting[0].desc.bInterfaceClass);
 
@@ -2102,18 +2126,19 @@ static int em28xx_usb_probe(struct usb_interface *interface,
        if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) !=
            USB_ENDPOINT_XFER_ISOC) {
                em28xx_err(DRIVER_NAME " probing error: endpoint is non-ISO endpoint!\n");
-               em28xx_devused&=~(1<<nr);
+               em28xx_devused &= ~(1<<nr);
                return -ENODEV;
        }
        if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) {
                em28xx_err(DRIVER_NAME " probing error: endpoint is ISO OUT endpoint!\n");
-               em28xx_devused&=~(1<<nr);
+               em28xx_devused &= ~(1<<nr);
                return -ENODEV;
        }
 
        if (nr >= EM28XX_MAXBOARDS) {
-               printk (DRIVER_NAME ": Supports only %i em28xx boards.\n",EM28XX_MAXBOARDS);
-               em28xx_devused&=~(1<<nr);
+               printk(DRIVER_NAME ": Supports only %i em28xx boards.\n",
+                               EM28XX_MAXBOARDS);
+               em28xx_devused &= ~(1<<nr);
                return -ENOMEM;
        }
 
@@ -2121,7 +2146,7 @@ static int em28xx_usb_probe(struct usb_interface *interface,
        dev = kzalloc(sizeof(*dev), GFP_KERNEL);
        if (dev == NULL) {
                em28xx_err(DRIVER_NAME ": out of memory!\n");
-               em28xx_devused&=~(1<<nr);
+               em28xx_devused &= ~(1<<nr);
                return -ENOMEM;
        }
 
@@ -2145,14 +2170,14 @@ static int em28xx_usb_probe(struct usb_interface *interface,
        /* compute alternate max packet sizes */
        uif = udev->actconfig->interface[0];
 
-       dev->num_alt=uif->num_altsetting;
-       em28xx_info("Alternate settings: %i\n",dev->num_alt);
-//     dev->alt_max_pkt_size = kmalloc(sizeof(*dev->alt_max_pkt_size)*
-       dev->alt_max_pkt_size = kmalloc(32*
-                                               dev->num_alt,GFP_KERNEL);
+       dev->num_alt = uif->num_altsetting;
+       em28xx_info("Alternate settings: %i\n", dev->num_alt);
+/*     dev->alt_max_pkt_size = kmalloc(sizeof(*dev->alt_max_pkt_size)* */
+       dev->alt_max_pkt_size = kmalloc(32 * dev->num_alt, GFP_KERNEL);
+
        if (dev->alt_max_pkt_size == NULL) {
                em28xx_errdev("out of memory!\n");
-               em28xx_devused&=~(1<<nr);
+               em28xx_devused &= ~(1<<nr);
                kfree(dev);
                return -ENOMEM;
        }
@@ -2162,11 +2187,11 @@ static int em28xx_usb_probe(struct usb_interface *interface,
                                                        wMaxPacketSize);
                dev->alt_max_pkt_size[i] =
                    (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
-               em28xx_info("Alternate setting %i, max size= %i\n",i,
-                                                       dev->alt_max_pkt_size[i]);
+               em28xx_info("Alternate setting %i, max size= %i\n", i,
+                                               dev->alt_max_pkt_size[i]);
        }
 
-       if ((card[nr]>=0)&&(card[nr]<em28xx_bcount))
+       if ((card[nr] >= 0) && (card[nr] < em28xx_bcount))
                dev->model = card[nr];
 
        /* allocate device struct */
@@ -2202,7 +2227,8 @@ static void em28xx_usb_disconnect(struct usb_interface *interface)
 
        em28xx_info("disconnecting %s\n", dev->vdev->name);
 
-       /* wait until all current v4l2 io is finished then deallocate resources */
+       /* wait until all current v4l2 io is finished then deallocate
+          resources */
        mutex_lock(&dev->lock);
 
        wake_up_interruptible_all(&dev->open);
index 04e0e48ecabe54b36a6e92a70aae50623e2a8498..002f170b211a34416cdf9e414b8d7d5a7023f7f3 100644 (file)
 #define _EM28XX_H
 
 #include <linux/videodev2.h>
+#include <media/videobuf-vmalloc.h>
+
 #include <linux/i2c.h>
 #include <linux/mutex.h>
 #include <media/ir-kbd-i2c.h>
-
-#define UNSET -1
+#if defined(CONFIG_VIDEO_EM28XX_DVB) || defined(CONFIG_VIDEO_EM28XX_DVB_MODULE)
+#include <media/videobuf-dvb.h>
+#endif
+#include "tuner-xc2028.h"
+#include "em28xx-reg.h"
+
+/* Boards supported by driver */
+#define EM2800_BOARD_UNKNOWN                   0
+#define EM2820_BOARD_UNKNOWN                   1
+#define EM2820_BOARD_TERRATEC_CINERGY_250      2
+#define EM2820_BOARD_PINNACLE_USB_2            3
+#define EM2820_BOARD_HAUPPAUGE_WINTV_USB_2      4
+#define EM2820_BOARD_MSI_VOX_USB_2              5
+#define EM2800_BOARD_TERRATEC_CINERGY_200       6
+#define EM2800_BOARD_LEADTEK_WINFAST_USBII      7
+#define EM2800_BOARD_KWORLD_USB2800             8
+#define EM2820_BOARD_PINNACLE_DVC_90           9
+#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900   10
+#define EM2880_BOARD_TERRATEC_HYBRID_XS                11
+#define EM2820_BOARD_KWORLD_PVRTV2800RF                12
+#define EM2880_BOARD_TERRATEC_PRODIGY_XS       13
+#define EM2820_BOARD_PROLINK_PLAYTV_USB2       14
+#define EM2800_BOARD_VGEAR_POCKETTV             15
+#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950   16
+
+/* Limits minimum and default number of buffers */
+#define EM28XX_MIN_BUF 4
+#define EM28XX_DEF_BUF 8
 
 /* maximum number of em28xx boards */
 #define EM28XX_MAXBOARDS 4 /*FIXME: should be bigger */
 /* time in msecs to wait for i2c writes to finish */
 #define EM2800_I2C_WRITE_TIMEOUT 20
 
-/* the various frame states */
-enum em28xx_frame_state {
-       F_UNUSED = 0,
-       F_QUEUED,
-       F_GRABBING,
-       F_DONE,
-       F_ERROR,
+enum em28xx_mode {
+       EM28XX_MODE_UNDEFINED,
+       EM28XX_ANALOG_MODE,
+       EM28XX_DIGITAL_MODE,
 };
 
-/* stream states */
 enum em28xx_stream_state {
        STREAM_OFF,
        STREAM_INTERRUPT,
        STREAM_ON,
 };
 
-/* frames */
-struct em28xx_frame_t {
-       void *bufmem;
-       struct v4l2_buffer buf;
-       enum em28xx_frame_state state;
+struct em28xx;
+
+struct em28xx_usb_isoc_ctl {
+               /* max packet size of isoc transaction */
+       int                             max_pkt_size;
+
+               /* number of allocated urbs */
+       int                             num_bufs;
+
+               /* urb for isoc transfers */
+       struct urb                      **urb;
+
+               /* transfer buffers for isoc transfer */
+       char                            **transfer_buffer;
+
+               /* Last buffer command and region */
+       u8                              cmd;
+       int                             pos, size, pktsize;
+
+               /* Last field: ODD or EVEN? */
+       int                             field;
+
+               /* Stores incomplete commands */
+       u32                             tmp_buf;
+       int                             tmp_buf_len;
+
+               /* Stores already requested buffers */
+       struct em28xx_buffer            *buf;
+
+               /* Stores the number of received fields */
+       int                             nfields;
+
+               /* isoc urb callback */
+       int (*isoc_copy) (struct em28xx *dev, struct urb *urb);
+
+};
+
+struct em28xx_fmt {
+       char  *name;
+       u32   fourcc;          /* v4l2 format id */
+};
+
+/* buffer for one video frame */
+struct em28xx_buffer {
+       /* common v4l buffer stuff -- must be first */
+       struct videobuf_buffer vb;
+
        struct list_head frame;
-       unsigned long vma_use_count;
        int top_field;
-       int fieldbytesused;
+       int receiving;
+};
+
+struct em28xx_dmaqueue {
+       struct list_head       active;
+       struct list_head       queued;
+
+       wait_queue_head_t          wq;
+
+       /* Counters to control buffer fill */
+       int                        pos;
 };
 
 /* io methods */
@@ -152,6 +227,12 @@ enum em28xx_decoder {
        EM28XX_SAA7114
 };
 
+struct em28xx_reg_seq {
+       int reg;
+       unsigned char val, mask;
+       int sleep;
+};
+
 struct em28xx_board {
        char *name;
        int vchannels;
@@ -165,8 +246,7 @@ struct em28xx_board {
        unsigned int mts_firmware:1;
        unsigned int has_12mhz_i2s:1;
        unsigned int max_range_640_480:1;
-
-       unsigned int analog_gpio;
+       unsigned int has_dvb:1;
 
        enum em28xx_decoder decoder;
 
@@ -199,7 +279,10 @@ enum em28xx_dev_state {
 #define EM28XX_NUM_AUDIO_PACKETS 64
 #define EM28XX_AUDIO_MAX_PACKET_SIZE 196 /* static value */
 #define EM28XX_CAPTURE_STREAM_EN 1
+
+/* em28xx extensions */
 #define EM28XX_AUDIO   0x10
+#define EM28XX_DVB     0x20
 
 struct em28xx_audio {
        char name[50];
@@ -217,13 +300,24 @@ struct em28xx_audio {
        spinlock_t slock;
 };
 
+struct em28xx;
+
+struct em28xx_fh {
+       struct em28xx *dev;
+       unsigned int  stream_on:1;      /* Locks streams */
+       int           radio;
+
+       struct videobuf_queue        vb_vidq;
+
+       enum v4l2_buf_type           type;
+};
+
 /* main device struct */
 struct em28xx {
        /* generic device properties */
        char name[30];          /* name (including minor) of the device */
        int model;              /* index in the device_data struct */
        int devno;              /* marks the number of this device */
-       unsigned int analog_gpio;
        unsigned int is_em2800:1;
        unsigned int has_msp34xx:1;
        unsigned int has_tda9887:1;
@@ -231,6 +325,16 @@ struct em28xx {
        unsigned int has_audio_class:1;
        unsigned int has_12mhz_i2s:1;
        unsigned int max_range_640_480:1;
+       unsigned int has_dvb:1;
+
+       /* Some older em28xx chips needs a waiting time after writing */
+       unsigned int wait_after_write;
+
+       /* GPIO sequences for analog and digital mode */
+       struct em28xx_reg_seq *analog_gpio, *digital_gpio;
+
+       /* GPIO sequences for tuner callbacks */
+       struct em28xx_reg_seq *tun_analog_gpio, *tun_digital_gpio;
 
        int video_inputs;       /* number of video inputs */
        struct list_head        devlist;
@@ -255,36 +359,28 @@ struct em28xx {
        int mute;
        int volume;
        /* frame properties */
-       struct em28xx_frame_t frame[EM28XX_NUM_FRAMES]; /* list of frames */
-       int num_frames;         /* number of frames currently in use */
-       unsigned int frame_count;       /* total number of transfered frames */
-       struct em28xx_frame_t *frame_current;   /* the frame that is being filled */
        int width;              /* current frame width */
        int height;             /* current frame height */
-       int frame_size;         /* current frame size */
-       int field_size;         /* current field size */
-       int bytesperline;
        int hscale;             /* horizontal scale factor (see datasheet) */
        int vscale;             /* vertical scale factor (see datasheet) */
        int interlaced;         /* 1=interlace fileds, 0=just top fileds */
-       int type;
        unsigned int video_bytesread;   /* Number of bytes read */
 
        unsigned long hash;     /* eeprom hash - for boards with generic ID */
-       unsigned long i2c_hash; /* i2c devicelist hash - for boards with generic ID */
+       unsigned long i2c_hash; /* i2c devicelist hash -
+                                  for boards with generic ID */
 
        struct em28xx_audio *adev;
 
        /* states */
        enum em28xx_dev_state state;
-       enum em28xx_stream_state stream;
        enum em28xx_io_method io;
 
        struct work_struct         request_module_wk;
 
        /* locks */
        struct mutex lock;
-       spinlock_t queue_lock;
+       /* spinlock_t queue_lock; */
        struct list_head inqueue, outqueue;
        wait_queue_head_t open, wait_frame, wait_stream;
        struct video_device *vbi_dev;
@@ -292,6 +388,11 @@ struct em28xx {
 
        unsigned char eedata[256];
 
+       /* Isoc control struct */
+       struct em28xx_dmaqueue vidq;
+       struct em28xx_usb_isoc_ctl isoc_ctl;
+       spinlock_t slock;
+
        /* usb transfer */
        struct usb_device *udev;        /* the usb device */
        int alt;                /* alternate */
@@ -301,20 +402,21 @@ struct em28xx {
        struct urb *urb[EM28XX_NUM_BUFS];       /* urb for isoc transfers */
        char *transfer_buffer[EM28XX_NUM_BUFS]; /* transfer buffers for isoc transfer */
        /* helper funcs that call usb_control_msg */
-       int (*em28xx_write_regs) (struct em28xx * dev, u16 reg, char *buf,
-                                 int len);
-       int (*em28xx_read_reg) (struct em28xx * dev, u16 reg);
-       int (*em28xx_read_reg_req_len) (struct em28xx * dev, u8 req, u16 reg,
+       int (*em28xx_write_regs) (struct em28xx *dev, u16 reg,
                                        char *buf, int len);
-       int (*em28xx_write_regs_req) (struct em28xx * dev, u8 req, u16 reg,
+       int (*em28xx_read_reg) (struct em28xx *dev, u16 reg);
+       int (*em28xx_read_reg_req_len) (struct em28xx *dev, u8 req, u16 reg,
+                                       char *buf, int len);
+       int (*em28xx_write_regs_req) (struct em28xx *dev, u8 req, u16 reg,
                                      char *buf, int len);
-       int (*em28xx_read_reg_req) (struct em28xx * dev, u8 req, u16 reg);
-};
+       int (*em28xx_read_reg_req) (struct em28xx *dev, u8 req, u16 reg);
 
-struct em28xx_fh {
-       struct em28xx *dev;
-       unsigned int  stream_on:1;      /* Locks streams */
-       int           radio;
+       enum em28xx_mode mode;
+
+       /* Caches GPO and GPIO registers */
+       unsigned char   reg_gpo, reg_gpio;
+
+       struct em28xx_dvb *dvb;
 };
 
 struct em28xx_ops {
@@ -351,22 +453,27 @@ int em28xx_colorlevels_set_default(struct em28xx *dev);
 int em28xx_capture_start(struct em28xx *dev, int start);
 int em28xx_outfmt_set_yuv422(struct em28xx *dev);
 int em28xx_resolution_set(struct em28xx *dev);
-int em28xx_init_isoc(struct em28xx *dev);
-void em28xx_uninit_isoc(struct em28xx *dev);
 int em28xx_set_alternate(struct em28xx *dev);
+int em28xx_init_isoc(struct em28xx *dev, int max_packets,
+                    int num_bufs, int max_pkt_size,
+                    int (*isoc_copy) (struct em28xx *dev, struct urb *urb));
+void em28xx_uninit_isoc(struct em28xx *dev);
+int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode);
+int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio);
 
 /* Provided by em28xx-video.c */
 int em28xx_register_extension(struct em28xx_ops *dev);
 void em28xx_unregister_extension(struct em28xx_ops *dev);
 
 /* Provided by em28xx-cards.c */
-extern int em2800_variant_detect(struct usb_device* udev,int model);
+extern int em2800_variant_detect(struct usb_device *udev, int model);
 extern void em28xx_pre_card_setup(struct em28xx *dev);
 extern void em28xx_card_setup(struct em28xx *dev);
 extern struct em28xx_board em28xx_boards[];
 extern struct usb_device_id em28xx_id_table[];
 extern const unsigned int em28xx_bcount;
 void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir);
+int em28xx_tuner_callback(void *ptr, int command, int arg);
 
 /* Provided by em28xx-input.c */
 /* TODO: Check if the standard get_key handlers on ir-common can be used */
@@ -375,71 +482,6 @@ int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw);
 int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key,
                                     u32 *ir_raw);
 
-/* em2800 registers */
-#define EM2800_AUDIOSRC_REG 0x08
-
-/* em28xx registers */
-#define I2C_CLK_REG    0x06
-#define CHIPID_REG     0x0a
-#define USBSUSP_REG    0x0c    /* */
-
-#define AUDIOSRC_REG   0x0e
-#define XCLK_REG       0x0f
-
-#define VINMODE_REG    0x10
-#define VINCTRL_REG    0x11
-#define VINENABLE_REG  0x12    /* */
-
-#define GAMMA_REG      0x14
-#define RGAIN_REG      0x15
-#define GGAIN_REG      0x16
-#define BGAIN_REG      0x17
-#define ROFFSET_REG    0x18
-#define GOFFSET_REG    0x19
-#define BOFFSET_REG    0x1a
-
-#define OFLOW_REG      0x1b
-#define HSTART_REG     0x1c
-#define VSTART_REG     0x1d
-#define CWIDTH_REG     0x1e
-#define CHEIGHT_REG    0x1f
-
-#define YGAIN_REG      0x20
-#define YOFFSET_REG    0x21
-#define UVGAIN_REG     0x22
-#define UOFFSET_REG    0x23
-#define VOFFSET_REG    0x24
-#define SHARPNESS_REG  0x25
-
-#define COMPR_REG      0x26
-#define OUTFMT_REG     0x27
-
-#define XMIN_REG       0x28
-#define XMAX_REG       0x29
-#define YMIN_REG       0x2a
-#define YMAX_REG       0x2b
-
-#define HSCALELOW_REG  0x30
-#define HSCALEHIGH_REG 0x31
-#define VSCALELOW_REG  0x32
-#define VSCALEHIGH_REG 0x33
-
-#define AC97LSB_REG    0x40
-#define AC97MSB_REG    0x41
-#define AC97ADDR_REG   0x42
-#define AC97BUSY_REG   0x43
-
-/* em202 registers */
-#define MASTER_AC97    0x02
-#define LINE_IN_AC97    0x10
-#define VIDEO_AC97     0x14
-
-/* register settings */
-#define EM2800_AUDIO_SRC_TUNER  0x0d
-#define EM2800_AUDIO_SRC_LINE   0x0c
-#define EM28XX_AUDIO_SRC_TUNER 0xc0
-#define EM28XX_AUDIO_SRC_LINE  0x80
-
 /* printk macros */
 
 #define em28xx_err(fmt, arg...) do {\
@@ -456,80 +498,80 @@ int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key,
        printk(KERN_WARNING "%s: "fmt,\
                        dev->name , ##arg); } while (0)
 
-inline static int em28xx_compression_disable(struct em28xx *dev)
+static inline int em28xx_compression_disable(struct em28xx *dev)
 {
        /* side effect of disabling scaler and mixer */
-       return em28xx_write_regs(dev, COMPR_REG, "\x00", 1);
+       return em28xx_write_regs(dev, EM28XX_R26_COMPR, "\x00", 1);
 }
 
-inline static int em28xx_contrast_get(struct em28xx *dev)
+static inline int em28xx_contrast_get(struct em28xx *dev)
 {
-       return em28xx_read_reg(dev, YGAIN_REG) & 0x1f;
+       return em28xx_read_reg(dev, EM28XX_R20_YGAIN) & 0x1f;
 }
 
-inline static int em28xx_brightness_get(struct em28xx *dev)
+static inline int em28xx_brightness_get(struct em28xx *dev)
 {
-       return em28xx_read_reg(dev, YOFFSET_REG);
+       return em28xx_read_reg(dev, EM28XX_R21_YOFFSET);
 }
 
-inline static int em28xx_saturation_get(struct em28xx *dev)
+static inline int em28xx_saturation_get(struct em28xx *dev)
 {
-       return em28xx_read_reg(dev, UVGAIN_REG) & 0x1f;
+       return em28xx_read_reg(dev, EM28XX_R22_UVGAIN) & 0x1f;
 }
 
-inline static int em28xx_u_balance_get(struct em28xx *dev)
+static inline int em28xx_u_balance_get(struct em28xx *dev)
 {
-       return em28xx_read_reg(dev, UOFFSET_REG);
+       return em28xx_read_reg(dev, EM28XX_R23_UOFFSET);
 }
 
-inline static int em28xx_v_balance_get(struct em28xx *dev)
+static inline int em28xx_v_balance_get(struct em28xx *dev)
 {
-       return em28xx_read_reg(dev, VOFFSET_REG);
+       return em28xx_read_reg(dev, EM28XX_R24_VOFFSET);
 }
 
-inline static int em28xx_gamma_get(struct em28xx *dev)
+static inline int em28xx_gamma_get(struct em28xx *dev)
 {
-       return em28xx_read_reg(dev, GAMMA_REG) & 0x3f;
+       return em28xx_read_reg(dev, EM28XX_R14_GAMMA) & 0x3f;
 }
 
-inline static int em28xx_contrast_set(struct em28xx *dev, s32 val)
+static inline int em28xx_contrast_set(struct em28xx *dev, s32 val)
 {
        u8 tmp = (u8) val;
-       return em28xx_write_regs(dev, YGAIN_REG, &tmp, 1);
+       return em28xx_write_regs(dev, EM28XX_R20_YGAIN, &tmp, 1);
 }
 
-inline static int em28xx_brightness_set(struct em28xx *dev, s32 val)
+static inline int em28xx_brightness_set(struct em28xx *dev, s32 val)
 {
        u8 tmp = (u8) val;
-       return em28xx_write_regs(dev, YOFFSET_REG, &tmp, 1);
+       return em28xx_write_regs(dev, EM28XX_R21_YOFFSET, &tmp, 1);
 }
 
-inline static int em28xx_saturation_set(struct em28xx *dev, s32 val)
+static inline int em28xx_saturation_set(struct em28xx *dev, s32 val)
 {
        u8 tmp = (u8) val;
-       return em28xx_write_regs(dev, UVGAIN_REG, &tmp, 1);
+       return em28xx_write_regs(dev, EM28XX_R22_UVGAIN, &tmp, 1);
 }
 
-inline static int em28xx_u_balance_set(struct em28xx *dev, s32 val)
+static inline int em28xx_u_balance_set(struct em28xx *dev, s32 val)
 {
        u8 tmp = (u8) val;
-       return em28xx_write_regs(dev, UOFFSET_REG, &tmp, 1);
+       return em28xx_write_regs(dev, EM28XX_R23_UOFFSET, &tmp, 1);
 }
 
-inline static int em28xx_v_balance_set(struct em28xx *dev, s32 val)
+static inline int em28xx_v_balance_set(struct em28xx *dev, s32 val)
 {
        u8 tmp = (u8) val;
-       return em28xx_write_regs(dev, VOFFSET_REG, &tmp, 1);
+       return em28xx_write_regs(dev, EM28XX_R24_VOFFSET, &tmp, 1);
 }
 
-inline static int em28xx_gamma_set(struct em28xx *dev, s32 val)
+static inline int em28xx_gamma_set(struct em28xx *dev, s32 val)
 {
        u8 tmp = (u8) val;
-       return em28xx_write_regs(dev, GAMMA_REG, &tmp, 1);
+       return em28xx_write_regs(dev, EM28XX_R14_GAMMA, &tmp, 1);
 }
 
 /*FIXME: maxw should be dependent of alt mode */
-inline static unsigned int norm_maxw(struct em28xx *dev)
+static inline unsigned int norm_maxw(struct em28xx *dev)
 {
        if (dev->max_range_640_480)
                return 640;
@@ -537,7 +579,7 @@ inline static unsigned int norm_maxw(struct em28xx *dev)
                return 720;
 }
 
-inline static unsigned int norm_maxh(struct em28xx *dev)
+static inline unsigned int norm_maxh(struct em28xx *dev)
 {
        if (dev->max_range_640_480)
                return 480;
index 02c741d8f85a55a7e2b965922610c7b4ae09733c..cc77d144df3cc4bc68f77c9fc7a07a150db7b2ac 100644 (file)
@@ -199,7 +199,7 @@ do {                                                                          \
                        dev_info(&cam->usbdev->dev, fmt "\n", ## args);       \
                else if ((level) >= 3)                                        \
                        dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n",   \
-                                __FILE__, __FUNCTION__, __LINE__ , ## args); \
+                                __FILE__, __func__, __LINE__ , ## args); \
        }                                                                     \
 } while (0)
 #      define KDBG(level, fmt, args...)                                      \
@@ -209,7 +209,7 @@ do {                                                                          \
                        pr_info("et61x251: " fmt "\n", ## args);              \
                else if ((level) == 3)                                        \
                        pr_debug("sn9c102: [%s:%s:%d] " fmt "\n", __FILE__,   \
-                                __FUNCTION__, __LINE__ , ## args);           \
+                                __func__, __LINE__ , ## args);           \
        }                                                                     \
 } while (0)
 #      define V4LDBG(level, name, cmd)                                       \
@@ -225,7 +225,7 @@ do {                                                                          \
 
 #undef PDBG
 #define PDBG(fmt, args...)                                                    \
-dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __FUNCTION__,   \
+dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __func__,   \
         __LINE__ , ## args)
 
 #undef PDBGG
index 06b6a3ae06c4c151bb8d54c04299920e11449e7a..5e749c528a624e7ea6babc290ede9dc041726e88 100644 (file)
@@ -2523,7 +2523,9 @@ static const struct file_operations et61x251_fops = {
        .open =    et61x251_open,
        .release = et61x251_release,
        .ioctl =   et61x251_ioctl,
+#ifdef CONFIG_COMPAT
        .compat_ioctl = v4l_compat_ioctl32,
+#endif
        .read =    et61x251_read,
        .poll =    et61x251_poll,
        .mmap =    et61x251_mmap,
@@ -2538,7 +2540,7 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
 {
        struct usb_device *udev = interface_to_usbdev(intf);
        struct et61x251_device* cam;
-       static unsigned int dev_nr = 0;
+       static unsigned int dev_nr;
        unsigned int i;
        int err = 0;
 
index c7fed340565524d8ad13553e7fce99ed84c56c37..352f84d440fb64272e6818fc2439122fa0c43230 100644 (file)
 
 #include <media/saa7146_vv.h>
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "debug verbosity");
 
 /* global variables */
-static int hexium_num = 0;
+static int hexium_num;
 
 #define HEXIUM_GEMINI                  4
 #define HEXIUM_GEMINI_DUAL             5
index 137c4736da04085ccf8d3df188d905ea97ceda43..8d3c1482e7ea376b5ae9919f7107b7eded09e185 100644 (file)
 
 #include <media/saa7146_vv.h>
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "debug verbosity");
 
 /* global variables */
-static int hexium_num = 0;
+static int hexium_num;
 
 #define HEXIUM_HV_PCI6_ORION           1
 #define HEXIUM_ORION_1SVHS_3BNC                2
index dabafdf71e609ca2860b55ac449d3989154f8bd3..11c5fdedc23bc341fb82ab4459d42b53bcab9a5f 100644 (file)
@@ -50,7 +50,7 @@
 static int debug;
 module_param(debug, int, 0644);    /* debug level (0,1,2) */
 
-static int hauppauge = 0;
+static int hauppauge;
 module_param(hauppauge, int, 0644);    /* Choose Hauppauge remote */
 MODULE_PARM_DESC(hauppauge, "Specify Hauppauge remote: 0=black, 1=grey (defaults to 0)");
 
@@ -153,7 +153,7 @@ static int get_key_fusionhdtv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
        }
 
        if(buf[0] !=0 || buf[1] !=0 || buf[2] !=0 || buf[3] != 0)
-               dprintk(2, "%s: 0x%2x 0x%2x 0x%2x 0x%2x\n", __FUNCTION__,
+               dprintk(2, "%s: 0x%2x 0x%2x 0x%2x 0x%2x\n", __func__,
                        buf[0], buf[1], buf[2], buf[3]);
 
        /* no key pressed or signal from other ir remote */
@@ -508,10 +508,10 @@ static int ir_probe(struct i2c_adapter *adap)
        static const int probe_em28XX[] = { 0x30, 0x47, -1 };
        static const int probe_cx88[] = { 0x18, 0x6b, 0x71, -1 };
        static const int probe_cx23885[] = { 0x6b, -1 };
-       const int *probe = NULL;
-       struct i2c_client c;
+       const int *probe;
+       struct i2c_client *c;
        unsigned char buf;
-       int i,rc;
+       int i, rc;
 
        switch (adap->id) {
        case I2C_HW_B_BT848:
@@ -532,23 +532,27 @@ static int ir_probe(struct i2c_adapter *adap)
        case I2C_HW_B_CX23885:
                probe = probe_cx23885;
                break;
-       }
-       if (NULL == probe)
+       default:
                return 0;
+       }
+
+       c = kzalloc(sizeof(*c), GFP_KERNEL);
+       if (!c)
+               return -ENOMEM;
 
-       memset(&c,0,sizeof(c));
-       c.adapter = adap;
+       c->adapter = adap;
        for (i = 0; -1 != probe[i]; i++) {
-               c.addr = probe[i];
-               rc = i2c_master_recv(&c,&buf,0);
+               c->addr = probe[i];
+               rc = i2c_master_recv(c, &buf, 0);
                dprintk(1,"probe 0x%02x @ %s: %s\n",
                        probe[i], adap->name,
                        (0 == rc) ? "yes" : "no");
                if (0 == rc) {
-                       ir_attach(adap,probe[i],0,0);
+                       ir_attach(adap, probe[i], 0, 0);
                        break;
                }
        }
+       kfree(c);
        return 0;
 }
 
index 270906fc314600107e161dde9575308c85385f1e..b6171702c4d051824c5215f5b93b9ca8f339cbc2 100644 (file)
@@ -10,6 +10,7 @@ config VIDEO_IVTV
        select VIDEO_CX25840
        select VIDEO_MSP3400
        select VIDEO_SAA711X
+       select VIDEO_SAA717X
        select VIDEO_SAA7127
        select VIDEO_TVAUDIO
        select VIDEO_CS53L32A
index f23c6b8d6911dee0f360c60e5c745b869df95e6e..e908649ea37cc738fc2611fb4cb14cbfe3a90ea0 100644 (file)
@@ -416,11 +416,10 @@ static const struct ivtv_card ivtv_card_avc2410 = {
           on the country/region setting of the user to decide which tuner
           is available. */
        .tuners = {
-               /* This tuner has been verified for the AVC2410 */
                { .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
-               /* This is a good guess, but I'm not totally sure this is
-                  the correct tuner for NTSC. */
-               { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FM1236_MK3 },
+               { .std = V4L2_STD_ALL - V4L2_STD_NTSC_M_JP,
+                       .tuner = TUNER_PHILIPS_FM1236_MK3 },
+               { .std = V4L2_STD_NTSC_M_JP, .tuner = TUNER_PHILIPS_FQ1286 },
        },
        .pci_list = ivtv_pci_avc2410,
        .i2c = &ivtv_i2c_std,
index 191aafdd9968fd008fbc405a2b566a03cf1ab452..9186fa2ee5fc01bff46a451df77569cbe593eba6 100644 (file)
 
 #define IVTV_CARD_MAX_VIDEO_INPUTS 6
 #define IVTV_CARD_MAX_AUDIO_INPUTS 3
-#define IVTV_CARD_MAX_TUNERS      2
+#define IVTV_CARD_MAX_TUNERS      3
 
 /* SAA71XX HW inputs */
 #define IVTV_SAA71XX_COMPOSITE0 0
index 948ca35e7ee897469eafd905c0ffb4432dd4fc76..065df53f80fdcbf543486a9c1fb5ce739e440841 100644 (file)
@@ -101,7 +101,7 @@ static int radio[IVTV_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1,
 static unsigned int cardtype_c = 1;
 static unsigned int tuner_c = 1;
 static unsigned int radio_c = 1;
-static char pal[] = "--";
+static char pal[] = "---";
 static char secam[] = "--";
 static char ntsc[] = "-";
 
@@ -126,12 +126,13 @@ static int dec_mpg_buffers = IVTV_DEFAULT_DEC_MPG_BUFFERS;
 static int dec_yuv_buffers = IVTV_DEFAULT_DEC_YUV_BUFFERS;
 static int dec_vbi_buffers = IVTV_DEFAULT_DEC_VBI_BUFFERS;
 
-static int ivtv_yuv_mode = 0;
-static int ivtv_yuv_threshold=-1;
+static int ivtv_yuv_mode;
+static int ivtv_yuv_threshold = -1;
 static int ivtv_pci_latency = 1;
 
-int ivtv_debug = 0;
+int ivtv_debug;
 
+static int tunertype = -1;
 static int newi2c = -1;
 
 module_param_array(tuner, int, &tuner_c, 0644);
@@ -154,6 +155,7 @@ module_param(dec_mpg_buffers, int, 0644);
 module_param(dec_yuv_buffers, int, 0644);
 module_param(dec_vbi_buffers, int, 0644);
 
+module_param(tunertype, int, 0644);
 module_param(newi2c, int, 0644);
 
 MODULE_PARM_DESC(tuner, "Tuner type selection,\n"
@@ -190,9 +192,14 @@ MODULE_PARM_DESC(cardtype,
                 "\t\t\t24 = AverMedia EZMaker PCI Deluxe\n"
                 "\t\t\t 0 = Autodetect (default)\n"
                 "\t\t\t-1 = Ignore this card\n\t\t");
-MODULE_PARM_DESC(pal, "Set PAL standard: B, G, H, D, K, I, M, N, Nc, 60");
-MODULE_PARM_DESC(secam, "Set SECAM standard: B, G, H, D, K, L, LC");
-MODULE_PARM_DESC(ntsc, "Set NTSC standard: M, J, K");
+MODULE_PARM_DESC(pal, "Set PAL standard: BGH, DK, I, M, N, Nc, 60");
+MODULE_PARM_DESC(secam, "Set SECAM standard: BGH, DK, L, LC");
+MODULE_PARM_DESC(ntsc, "Set NTSC standard: M, J (Japan), K (South Korea)");
+MODULE_PARM_DESC(tunertype,
+               "Specify tuner type:\n"
+               "\t\t\t 0 = tuner for PAL-B/G/H/D/K/I, SECAM-B/G/H/D/K/L/Lc\n"
+               "\t\t\t 1 = tuner for NTSC-M/J/K, PAL-M/N/Nc\n"
+               "\t\t\t-1 = Autodetect (default)\n");
 MODULE_PARM_DESC(debug,
                 "Debug level (bitmask). Default: 0\n"
                 "\t\t\t   1/0x0001: warning\n"
@@ -490,30 +497,35 @@ static v4l2_std_id ivtv_parse_std(struct ivtv *itv)
 {
        switch (pal[0]) {
                case '6':
+                       tunertype = 0;
                        return V4L2_STD_PAL_60;
                case 'b':
                case 'B':
                case 'g':
                case 'G':
-                       return V4L2_STD_PAL_BG;
                case 'h':
                case 'H':
-                       return V4L2_STD_PAL_H;
+                       tunertype = 0;
+                       return V4L2_STD_PAL_BG | V4L2_STD_PAL_H;
                case 'n':
                case 'N':
+                       tunertype = 1;
                        if (pal[1] == 'c' || pal[1] == 'C')
                                return V4L2_STD_PAL_Nc;
                        return V4L2_STD_PAL_N;
                case 'i':
                case 'I':
+                       tunertype = 0;
                        return V4L2_STD_PAL_I;
                case 'd':
                case 'D':
                case 'k':
                case 'K':
+                       tunertype = 0;
                        return V4L2_STD_PAL_DK;
                case 'M':
                case 'm':
+                       tunertype = 1;
                        return V4L2_STD_PAL_M;
                case '-':
                        break;
@@ -529,14 +541,17 @@ static v4l2_std_id ivtv_parse_std(struct ivtv *itv)
                case 'G':
                case 'h':
                case 'H':
+                       tunertype = 0;
                        return V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H;
                case 'd':
                case 'D':
                case 'k':
                case 'K':
+                       tunertype = 0;
                        return V4L2_STD_SECAM_DK;
                case 'l':
                case 'L':
+                       tunertype = 0;
                        if (secam[1] == 'C' || secam[1] == 'c')
                                return V4L2_STD_SECAM_LC;
                        return V4L2_STD_SECAM_L;
@@ -550,12 +565,15 @@ static v4l2_std_id ivtv_parse_std(struct ivtv *itv)
        switch (ntsc[0]) {
                case 'm':
                case 'M':
+                       tunertype = 1;
                        return V4L2_STD_NTSC_M;
                case 'j':
                case 'J':
+                       tunertype = 1;
                        return V4L2_STD_NTSC_M_JP;
                case 'k':
                case 'K':
+                       tunertype = 1;
                        return V4L2_STD_NTSC_M_KR;
                case '-':
                        break;
@@ -584,8 +602,13 @@ static void ivtv_process_options(struct ivtv *itv)
        itv->options.tuner = tuner[itv->num];
        itv->options.radio = radio[itv->num];
        itv->options.newi2c = newi2c;
-
+       if (tunertype < -1 || tunertype > 1) {
+               IVTV_WARN("Invalid tunertype argument, will autodetect instead\n");
+               tunertype = -1;
+       }
        itv->std = ivtv_parse_std(itv);
+       if (itv->std == 0 && tunertype >= 0)
+               itv->std = tunertype ? V4L2_STD_MN : (V4L2_STD_ALL & ~V4L2_STD_MN);
        itv->has_cx23415 = (itv->dev->device == PCI_DEVICE_ID_IVTV15);
        chipname = itv->has_cx23415 ? "cx23415" : "cx23416";
        if (itv->options.cardtype == -1) {
@@ -711,6 +734,7 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv)
        itv->yuv_info.lace_mode = ivtv_yuv_mode;
        itv->yuv_info.lace_threshold = ivtv_yuv_threshold;
        itv->yuv_info.max_frames_buffered = 3;
+       itv->yuv_info.track_osd = 1;
        return 0;
 }
 
@@ -859,7 +883,9 @@ static void ivtv_load_and_init_modules(struct ivtv *itv)
 #ifndef CONFIG_VIDEO_SAA7127
        hw = ivtv_request_module(itv, hw, "saa7127", IVTV_HW_SAA7127);
 #endif
+#ifndef CONFIG_VIDEO_SAA717X
        hw = ivtv_request_module(itv, hw, "saa717x", IVTV_HW_SAA717X);
+#endif
 #ifndef CONFIG_VIDEO_UPD64031A
        hw = ivtv_request_module(itv, hw, "upd64031a", IVTV_HW_UPD64031A);
 #endif
index 536140f0c19efb6eabd9f8673857c742a3a7a600..ba06e813c58c3d789222aca798e5bc6811c6caa4 100644 (file)
@@ -456,6 +456,8 @@ struct yuv_playback_info
        int v_filter_2;
        int h_filter;
 
+       u8 track_osd; /* Should yuv output track the OSD size & position */
+
        u32 osd_x_offset;
        u32 osd_y_offset;
 
index 6fb96f19a8661dfe369f7303e6ed4e11301d3ad9..a7640c49f1d84aa6f89e8f81e67b291d62a67350 100644 (file)
@@ -219,7 +219,9 @@ static struct ivtv_buffer *ivtv_get_buffer(struct ivtv_stream *s, int non_block,
                        /* Process pending program info updates and pending VBI data */
                        ivtv_update_pgm_info(itv);
 
-                       if (jiffies - itv->dualwatch_jiffies > msecs_to_jiffies(1000)) {
+                       if (time_after(jiffies,
+                                      itv->dualwatch_jiffies +
+                                      msecs_to_jiffies(1000))) {
                                itv->dualwatch_jiffies = jiffies;
                                ivtv_dualwatch(itv);
                        }
@@ -753,7 +755,7 @@ unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table * wait)
        IVTV_DEBUG_HI_FILE("Encoder poll\n");
        poll_wait(filp, &s->waitq, wait);
 
-       if (eof || s->q_full.length)
+       if (eof || s->q_full.length || s->q_io.length)
                return POLLIN | POLLRDNORM;
        return 0;
 }
index fa5ab1eb180005049db0412df19b8279303b7aec..9824eafee02131eb88b67045de9ce32de8f0e93e 100644 (file)
@@ -177,10 +177,16 @@ int ivtv_i2c_register(struct ivtv *itv, unsigned idx)
        }
 
        if (id != I2C_DRIVERID_TUNER) {
-               c = i2c_new_device(&itv->i2c_adap, &info);
-               if (c->driver == NULL)
+               if (id == I2C_DRIVERID_UPD64031A ||
+                   id == I2C_DRIVERID_UPD64083) {
+                       unsigned short addrs[2] = { info.addr, I2C_CLIENT_END };
+
+                       c = i2c_new_probed_device(&itv->i2c_adap, &info, addrs);
+               } else
+                       c = i2c_new_device(&itv->i2c_adap, &info);
+               if (c && c->driver == NULL)
                        i2c_unregister_device(c);
-               else
+               else if (c)
                        itv->i2c_clients[i] = c;
                return itv->i2c_clients[i] ? 0 : -ENODEV;
        }
index edef2a579617e722c5357b93775f88620faff327..15cac1812122e22c11805e3fe006c5111f2581ae 100644 (file)
@@ -712,6 +712,7 @@ static int ivtv_debug_ioctls(struct file *filp, unsigned int cmd, void *arg)
 int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void *arg)
 {
        struct ivtv_open_id *id = NULL;
+       struct yuv_playback_info *yi = &itv->yuv_info;
        u32 data[CX2341X_MBOX_MAX_DATA];
        int streamtype = 0;
 
@@ -741,7 +742,8 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
 
                memset(vcap, 0, sizeof(*vcap));
                strcpy(vcap->driver, IVTV_DRIVER_NAME);     /* driver name */
-               strcpy(vcap->card, itv->card_name);         /* card type */
+               strncpy(vcap->card, itv->card_name,
+                               sizeof(vcap->card)-1);      /* card type */
                strcpy(vcap->bus_info, pci_name(itv->dev)); /* bus info... */
                vcap->version = IVTV_DRIVER_VERSION;        /* version */
                vcap->capabilities = itv->v4l2_cap;         /* capabilities */
@@ -827,8 +829,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
        case VIDIOC_CROPCAP: {
                struct v4l2_cropcap *cropcap = arg;
 
-               if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
-                   cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
+               if (cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
                        return -EINVAL;
                cropcap->bounds.top = cropcap->bounds.left = 0;
                cropcap->bounds.width = 720;
@@ -837,8 +838,14 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
                        cropcap->pixelaspect.numerator = itv->is_50hz ? 59 : 10;
                        cropcap->pixelaspect.denominator = itv->is_50hz ? 54 : 11;
                } else if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
-                       cropcap->bounds.width = itv->yuv_info.osd_full_w;
-                       cropcap->bounds.height = itv->yuv_info.osd_full_h;
+                       if (yi->track_osd) {
+                               cropcap->bounds.width = yi->osd_full_w;
+                               cropcap->bounds.height = yi->osd_full_h;
+                       } else {
+                               cropcap->bounds.width = 720;
+                               cropcap->bounds.height =
+                                               itv->is_out_50hz ? 576 : 480;
+                       }
                        cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10;
                        cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11;
                } else {
@@ -856,7 +863,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
                if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
                    (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
                        if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
-                               itv->yuv_info.main_rect = crop->c;
+                               yi->main_rect = crop->c;
                                return 0;
                        } else {
                                if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
@@ -867,9 +874,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
                        }
                        return -EINVAL;
                }
-               if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-                       return -EINVAL;
-               return itv->video_dec_func(itv, VIDIOC_S_CROP, arg);
+               return -EINVAL;
        }
 
        case VIDIOC_G_CROP: {
@@ -878,14 +883,12 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
                if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
                    (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
                        if (streamtype == IVTV_DEC_STREAM_TYPE_YUV)
-                               crop->c = itv->yuv_info.main_rect;
+                               crop->c = yi->main_rect;
                        else
                                crop->c = itv->main_rect;
                        return 0;
                }
-               if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-                       return -EINVAL;
-               return itv->video_dec_func(itv, VIDIOC_G_CROP, arg);
+               return -EINVAL;
        }
 
        case VIDIOC_ENUM_FMT: {
@@ -1070,11 +1073,10 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
                        itv->main_rect.height = itv->params.height;
                        ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
                                720, itv->main_rect.height, 0, 0);
-                       itv->yuv_info.main_rect = itv->main_rect;
+                       yi->main_rect = itv->main_rect;
                        if (!itv->osd_info) {
-                               itv->yuv_info.osd_full_w = 720;
-                               itv->yuv_info.osd_full_h =
-                                               itv->is_out_50hz ? 576 : 480;
+                               yi->osd_full_w = 720;
+                               yi->osd_full_h = itv->is_out_50hz ? 576 : 480;
                        }
                }
                break;
@@ -1272,6 +1274,8 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
                        else
                                fb->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
                }
+               if (yi->track_osd)
+                       fb->flags |= V4L2_FBUF_FLAG_OVERLAY;
                break;
        }
 
@@ -1285,6 +1289,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
                        (fb->flags & (V4L2_FBUF_FLAG_LOCAL_ALPHA|V4L2_FBUF_FLAG_LOCAL_INV_ALPHA)) != 0;
                itv->osd_chroma_key_state = (fb->flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0;
                ivtv_set_osd_alpha(itv);
+               yi->track_osd = (fb->flags & V4L2_FBUF_FLAG_OVERLAY) != 0;
                break;
        }
 
@@ -1628,6 +1633,7 @@ static int ivtv_v4l2_do_ioctl(struct inode *inode, struct file *filp,
                if (ivtv_debug & IVTV_DBGFLG_IOCTL) {
                        printk(KERN_INFO "ivtv%d ioctl: ", itv->num);
                        v4l_printk_ioctl(cmd);
+                       printk("\n");
                }
                return ivtv_debug_ioctls(filp, cmd, arg);
 
@@ -1671,6 +1677,7 @@ static int ivtv_v4l2_do_ioctl(struct inode *inode, struct file *filp,
                if (ivtv_debug & IVTV_DBGFLG_IOCTL) {
                        printk(KERN_INFO "ivtv%d ioctl: ", itv->num);
                        v4l_printk_ioctl(cmd);
+                       printk("\n");
                }
                return ivtv_v4l2_ioctls(itv, filp, cmd, arg);
 
@@ -1684,6 +1691,7 @@ static int ivtv_v4l2_do_ioctl(struct inode *inode, struct file *filp,
                if (ivtv_debug & IVTV_DBGFLG_IOCTL) {
                        printk(KERN_INFO "ivtv%d ioctl: ", itv->num);
                        v4l_printk_ioctl(cmd);
+                       printk("\n");
                }
                return ivtv_control_ioctls(itv, cmd, arg);
 
index 65604dde972614cfb9c1926c3dcd89649cacc2cf..a329c4689dbf71de5b56a307c3256b6d8979aa76 100644 (file)
@@ -384,6 +384,8 @@ static void ivtv_dma_enc_start_xfer(struct ivtv_stream *s)
        ivtv_stream_sync_for_device(s);
        write_reg(s->sg_handle, IVTV_REG_ENCDMAADDR);
        write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x02, IVTV_REG_DMAXFER);
+       itv->dma_timer.expires = jiffies + msecs_to_jiffies(100);
+       add_timer(&itv->dma_timer);
 }
 
 static void ivtv_dma_dec_start_xfer(struct ivtv_stream *s)
@@ -398,6 +400,8 @@ static void ivtv_dma_dec_start_xfer(struct ivtv_stream *s)
        ivtv_stream_sync_for_device(s);
        write_reg(s->sg_handle, IVTV_REG_DECDMAADDR);
        write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x01, IVTV_REG_DMAXFER);
+       itv->dma_timer.expires = jiffies + msecs_to_jiffies(100);
+       add_timer(&itv->dma_timer);
 }
 
 /* start the encoder DMA */
@@ -459,8 +463,6 @@ static void ivtv_dma_enc_start(struct ivtv_stream *s)
                ivtv_dma_enc_start_xfer(s);
                set_bit(IVTV_F_I_DMA, &itv->i_flags);
                itv->cur_dma_stream = s->type;
-               itv->dma_timer.expires = jiffies + msecs_to_jiffies(100);
-               add_timer(&itv->dma_timer);
        }
 }
 
@@ -481,8 +483,6 @@ static void ivtv_dma_dec_start(struct ivtv_stream *s)
        ivtv_dma_dec_start_xfer(s);
        set_bit(IVTV_F_I_DMA, &itv->i_flags);
        itv->cur_dma_stream = s->type;
-       itv->dma_timer.expires = jiffies + msecs_to_jiffies(100);
-       add_timer(&itv->dma_timer);
 }
 
 static void ivtv_irq_dma_read(struct ivtv *itv)
@@ -492,10 +492,11 @@ static void ivtv_irq_dma_read(struct ivtv *itv)
        int hw_stream_type = 0;
 
        IVTV_DEBUG_HI_IRQ("DEC DMA READ\n");
-       if (!test_bit(IVTV_F_I_UDMA, &itv->i_flags) && itv->cur_dma_stream < 0) {
-               del_timer(&itv->dma_timer);
+
+       del_timer(&itv->dma_timer);
+
+       if (!test_bit(IVTV_F_I_UDMA, &itv->i_flags) && itv->cur_dma_stream < 0)
                return;
-       }
 
        if (!test_bit(IVTV_F_I_UDMA, &itv->i_flags)) {
                s = &itv->streams[itv->cur_dma_stream];
@@ -543,7 +544,6 @@ static void ivtv_irq_dma_read(struct ivtv *itv)
                }
                wake_up(&s->waitq);
        }
-       del_timer(&itv->dma_timer);
        clear_bit(IVTV_F_I_UDMA, &itv->i_flags);
        clear_bit(IVTV_F_I_DMA, &itv->i_flags);
        itv->cur_dma_stream = -1;
@@ -557,10 +557,12 @@ static void ivtv_irq_enc_dma_complete(struct ivtv *itv)
 
        ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA_END, data);
        IVTV_DEBUG_HI_IRQ("ENC DMA COMPLETE %x %d (%d)\n", data[0], data[1], itv->cur_dma_stream);
-       if (itv->cur_dma_stream < 0) {
-               del_timer(&itv->dma_timer);
+
+       del_timer(&itv->dma_timer);
+
+       if (itv->cur_dma_stream < 0)
                return;
-       }
+
        s = &itv->streams[itv->cur_dma_stream];
        ivtv_stream_sync_for_cpu(s);
 
@@ -585,7 +587,6 @@ static void ivtv_irq_enc_dma_complete(struct ivtv *itv)
                ivtv_dma_enc_start_xfer(s);
                return;
        }
-       del_timer(&itv->dma_timer);
        clear_bit(IVTV_F_I_DMA, &itv->i_flags);
        itv->cur_dma_stream = -1;
        dma_post(s);
index 13a6c374d2dbf0833108ff3e0367cbcca7e40f8e..1b5c0ac09a8552cb0c71db7a31fed5cb2a4124ef 100644 (file)
@@ -177,7 +177,8 @@ static int get_mailbox(struct ivtv *itv, struct ivtv_mailbox_data *mbdata, int f
 
                /* Sleep before a retry, if not atomic */
                if (!(flags & API_NO_WAIT_MB)) {
-                       if (jiffies - then > msecs_to_jiffies(10*retries))
+                       if (time_after(jiffies,
+                                      then + msecs_to_jiffies(10*retries)))
                               break;
                        ivtv_msleep_timeout(10, 0);
                }
@@ -244,7 +245,9 @@ static int ivtv_api_call(struct ivtv *itv, int cmd, int args, u32 data[])
           data, then just return 0 as there is no need to issue this command again.
           Just an optimization to prevent unnecessary use of mailboxes. */
        if (itv->api_cache[cmd].last_jiffies &&
-           jiffies - itv->api_cache[cmd].last_jiffies < msecs_to_jiffies(1800000) &&
+           time_before(jiffies,
+                       itv->api_cache[cmd].last_jiffies +
+                       msecs_to_jiffies(1800000)) &&
            !memcmp(data, itv->api_cache[cmd].data, sizeof(itv->api_cache[cmd].data))) {
                itv->api_cache[cmd].last_jiffies = jiffies;
                return 0;
@@ -299,7 +302,7 @@ static int ivtv_api_call(struct ivtv *itv, int cmd, int args, u32 data[])
                }
        }
        while (!(readl(&mbox->flags) & IVTV_MBOX_FIRMWARE_DONE)) {
-               if (jiffies - then > api_timeout) {
+               if (time_after(jiffies, then + api_timeout)) {
                        IVTV_DEBUG_WARN("Could not get result (%s)\n", api_info[cmd].name);
                        /* reset the mailbox, but it is likely too late already */
                        write_sync(0, &mbox->flags);
@@ -311,7 +314,7 @@ static int ivtv_api_call(struct ivtv *itv, int cmd, int args, u32 data[])
                else
                        ivtv_msleep_timeout(1, 0);
        }
-       if (jiffies - then > msecs_to_jiffies(100))
+       if (time_after(jiffies, then + msecs_to_jiffies(100)))
                IVTV_DEBUG_WARN("%s took %u jiffies\n",
                                api_info[cmd].name,
                                jiffies_to_msecs(jiffies - then));
index 39a216713244eecd6481d75d307e0ec38f9d74b1..3e1deec67a5e33d8f12ba141546946eec6db4436 100644 (file)
@@ -51,7 +51,7 @@ void ivtv_queue_init(struct ivtv_queue *q)
 
 void ivtv_enqueue(struct ivtv_stream *s, struct ivtv_buffer *buf, struct ivtv_queue *q)
 {
-       unsigned long flags = 0;
+       unsigned long flags;
 
        /* clear the buffer if it is going to be enqueued to the free queue */
        if (q == &s->q_free) {
@@ -71,7 +71,7 @@ void ivtv_enqueue(struct ivtv_stream *s, struct ivtv_buffer *buf, struct ivtv_qu
 struct ivtv_buffer *ivtv_dequeue(struct ivtv_stream *s, struct ivtv_queue *q)
 {
        struct ivtv_buffer *buf = NULL;
-       unsigned long flags = 0;
+       unsigned long flags;
 
        spin_lock_irqsave(&s->qlock, flags);
        if (!list_empty(&q->list)) {
index 24d98ecf35ad13de77f4d2457de6c8ba09c9c584..4ab8d36831ba427e477e984b457d967824493443 100644 (file)
@@ -768,7 +768,8 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end)
 
                        /* wait 2s for EOS interrupt */
                        while (!test_bit(IVTV_F_I_EOS, &itv->i_flags) &&
-                               jiffies < then + msecs_to_jiffies (2000)) {
+                               time_before(jiffies,
+                                           then + msecs_to_jiffies(2000))) {
                                schedule_timeout(msecs_to_jiffies(10));
                        }
 
index 85183480a2259e610aaad59e4341dd4d91d4d5c4..393d917cd67265367aa0280395bf521b4a57902e 100644 (file)
@@ -718,9 +718,11 @@ static u32 ivtv_yuv_window_setup(struct ivtv *itv, struct yuv_frame_info *f)
                f->src_w -= (osd_scale * osd_crop) >> 16;
        }
 
-       /* The OSD can be moved. Track to it */
-       f->dst_x += itv->yuv_info.osd_x_offset;
-       f->dst_y += itv->yuv_info.osd_y_offset;
+       if (itv->yuv_info.track_osd) {
+               /* The OSD can be moved. Track to it */
+               f->dst_x += itv->yuv_info.osd_x_offset;
+               f->dst_y += itv->yuv_info.osd_y_offset;
+       }
 
        /* Width & height for both src & dst must be even.
           Same for coordinates. */
@@ -792,11 +794,19 @@ void ivtv_yuv_work_handler(struct ivtv *itv)
        IVTV_DEBUG_YUV("Update yuv registers for frame %d\n", frame);
        f = yi->new_frame_info[frame];
 
-       /* Update the osd pan info */
-       f.pan_x = yi->osd_x_pan;
-       f.pan_y = yi->osd_y_pan;
-       f.vis_w = yi->osd_vis_w;
-       f.vis_h = yi->osd_vis_h;
+       if (yi->track_osd) {
+               /* Snapshot the osd pan info */
+               f.pan_x = yi->osd_x_pan;
+               f.pan_y = yi->osd_y_pan;
+               f.vis_w = yi->osd_vis_w;
+               f.vis_h = yi->osd_vis_h;
+       } else {
+               /* Not tracking the osd, so assume full screen */
+               f.pan_x = 0;
+               f.pan_y = 0;
+               f.vis_w = 720;
+               f.vis_h = yi->decode_height;
+       }
 
        /* Calculate the display window coordinates. Exit if nothing left */
        if (!(yuv_update = ivtv_yuv_window_setup(itv, &f)))
@@ -914,7 +924,7 @@ static void ivtv_yuv_init(struct ivtv *itv)
 }
 
 /* Get next available yuv buffer on PVR350 */
-void ivtv_yuv_next_free(struct ivtv *itv)
+static void ivtv_yuv_next_free(struct ivtv *itv)
 {
        int draw, display;
        struct yuv_playback_info *yi = &itv->yuv_info;
@@ -937,7 +947,7 @@ void ivtv_yuv_next_free(struct ivtv *itv)
 }
 
 /* Set up frame according to ivtv_dma_frame parameters */
-void ivtv_yuv_setup_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
+static void ivtv_yuv_setup_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
 {
        struct yuv_playback_info *yi = &itv->yuv_info;
        u8 frame = yi->draw_frame;
@@ -965,12 +975,6 @@ void ivtv_yuv_setup_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
        /* Are we going to offset the Y plane */
        nf->offset_y = (nf->tru_h + nf->src_x < 512 - 16) ? 1 : 0;
 
-       /* Snapshot the osd pan info */
-       nf->pan_x = yi->osd_x_pan;
-       nf->pan_y = yi->osd_y_pan;
-       nf->vis_w = yi->osd_vis_w;
-       nf->vis_h = yi->osd_vis_h;
-
        nf->update = 0;
        nf->interlaced_y = 0;
        nf->interlaced_uv = 0;
@@ -1042,7 +1046,7 @@ void ivtv_yuv_frame_complete(struct ivtv *itv)
                        (itv->yuv_info.draw_frame + 1) % IVTV_YUV_BUFFERS);
 }
 
-int ivtv_yuv_udma_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
+static int ivtv_yuv_udma_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
 {
        DEFINE_WAIT(wait);
        int rc = 0;
index 3d51fa0a52b6132c6b09859c691c466e97e0964e..e7ccbc895d7abe4fc37b84ae805d6d504d37dbde 100644 (file)
 #include <linux/meye.h>
 
 MODULE_AUTHOR("Stelian Pop <stelian@popies.net>");
-MODULE_DESCRIPTION("v4l/v4l2 driver for the MotionEye camera");
+MODULE_DESCRIPTION("v4l2 driver for the MotionEye camera");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(MEYE_DRIVER_VERSION);
 
-/* force usage of V4L1 API */
-static int forcev4l1; /* = 0 */
-module_param(forcev4l1, int, 0644);
-MODULE_PARM_DESC(forcev4l1, "force use of V4L1 instead of V4L2");
-
 /* number of grab buffers */
 static unsigned int gbuffers = 2;
 module_param(gbuffers, int, 0444);
@@ -789,7 +784,7 @@ static irqreturn_t meye_irq(int irq, void *dev_id)
 {
        u32 v;
        int reqnr;
-       static int sequence = 0;
+       static int sequence;
 
        v = mchip_read(MCHIP_MM_INTA);
 
@@ -876,795 +871,735 @@ static int meye_release(struct inode *inode, struct file *file)
        return 0;
 }
 
-static int meye_do_ioctl(struct inode *inode, struct file *file,
-                        unsigned int cmd, void *arg)
+static int meyeioc_g_params(struct meye_params *p)
 {
-       switch (cmd) {
+       *p = meye.params;
+       return 0;
+}
 
-       case VIDIOCGCAP: {
-               struct video_capability *b = arg;
-               strcpy(b->name,meye.video_dev->name);
-               b->type = VID_TYPE_CAPTURE;
-               b->channels = 1;
-               b->audios = 0;
-               b->maxwidth = 640;
-               b->maxheight = 480;
-               b->minwidth = 320;
-               b->minheight = 240;
-               break;
-       }
+static int meyeioc_s_params(struct meye_params *jp)
+{
+       if (jp->subsample > 1)
+               return -EINVAL;
 
-       case VIDIOCGCHAN: {
-               struct video_channel *v = arg;
-               v->flags = 0;
-               v->tuners = 0;
-               v->type = VIDEO_TYPE_CAMERA;
-               if (v->channel != 0)
-                       return -EINVAL;
-               strcpy(v->name,"Camera");
-               break;
-       }
+       if (jp->quality > 10)
+               return -EINVAL;
 
-       case VIDIOCSCHAN: {
-               struct video_channel *v = arg;
-               if (v->channel != 0)
-                       return -EINVAL;
-               break;
-       }
+       if (jp->sharpness > 63 || jp->agc > 63 || jp->picture > 63)
+               return -EINVAL;
 
-       case VIDIOCGPICT: {
-               struct video_picture *p = arg;
-               *p = meye.picture;
-               break;
-       }
+       if (jp->framerate > 31)
+               return -EINVAL;
 
-       case VIDIOCSPICT: {
-               struct video_picture *p = arg;
-               if (p->depth != 16)
-                       return -EINVAL;
-               if (p->palette != VIDEO_PALETTE_YUV422 && p->palette != VIDEO_PALETTE_YUYV)
-                       return -EINVAL;
-               mutex_lock(&meye.lock);
-               sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERABRIGHTNESS,
-                                     p->brightness >> 10);
-               sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAHUE,
-                                     p->hue >> 10);
-               sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERACOLOR,
-                                     p->colour >> 10);
-               sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERACONTRAST,
-                                     p->contrast >> 10);
-               meye.picture = *p;
-               mutex_unlock(&meye.lock);
-               break;
-       }
+       mutex_lock(&meye.lock);
 
-       case VIDIOCSYNC: {
-               int *i = arg;
-               int unused;
+       if (meye.params.subsample != jp->subsample ||
+           meye.params.quality != jp->quality)
+               mchip_hic_stop();       /* need restart */
+
+       meye.params = *jp;
+       sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERASHARPNESS,
+                             meye.params.sharpness);
+       sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAAGC,
+                             meye.params.agc);
+       sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAPICTURE,
+                             meye.params.picture);
+       mutex_unlock(&meye.lock);
 
-               if (*i < 0 || *i >= gbuffers)
-                       return -EINVAL;
+       return 0;
+}
 
-               mutex_lock(&meye.lock);
+static int meyeioc_qbuf_capt(int *nb)
+{
+       if (!meye.grab_fbuffer)
+               return -EINVAL;
 
-               switch (meye.grab_buffer[*i].state) {
+       if (*nb >= gbuffers)
+               return -EINVAL;
 
-               case MEYE_BUF_UNUSED:
-                       mutex_unlock(&meye.lock);
-                       return -EINVAL;
-               case MEYE_BUF_USING:
-                       if (file->f_flags & O_NONBLOCK) {
-                               mutex_unlock(&meye.lock);
-                               return -EAGAIN;
-                       }
-                       if (wait_event_interruptible(meye.proc_list,
-                                                    (meye.grab_buffer[*i].state != MEYE_BUF_USING))) {
-                               mutex_unlock(&meye.lock);
-                               return -EINTR;
-                       }
-                       /* fall through */
-               case MEYE_BUF_DONE:
-                       meye.grab_buffer[*i].state = MEYE_BUF_UNUSED;
-                       kfifo_get(meye.doneq, (unsigned char *)&unused, sizeof(int));
-               }
-               mutex_unlock(&meye.lock);
-               break;
+       if (*nb < 0) {
+               /* stop capture */
+               mchip_hic_stop();
+               return 0;
        }
 
-       case VIDIOCMCAPTURE: {
-               struct video_mmap *vm = arg;
-               int restart = 0;
-
-               if (vm->frame >= gbuffers || vm->frame < 0)
-                       return -EINVAL;
-               if (vm->format != VIDEO_PALETTE_YUV422 && vm->format != VIDEO_PALETTE_YUYV)
-                       return -EINVAL;
-               if (vm->height * vm->width * 2 > gbufsize)
-                       return -EINVAL;
-               if (!meye.grab_fbuffer)
-                       return -EINVAL;
-               if (meye.grab_buffer[vm->frame].state != MEYE_BUF_UNUSED)
-                       return -EBUSY;
-
-               mutex_lock(&meye.lock);
-               if (vm->width == 640 && vm->height == 480) {
-                       if (meye.params.subsample) {
-                               meye.params.subsample = 0;
-                               restart = 1;
-                       }
-               } else if (vm->width == 320 && vm->height == 240) {
-                       if (!meye.params.subsample) {
-                               meye.params.subsample = 1;
-                               restart = 1;
-                       }
-               } else {
-                       mutex_unlock(&meye.lock);
-                       return -EINVAL;
-               }
+       if (meye.grab_buffer[*nb].state != MEYE_BUF_UNUSED)
+               return -EBUSY;
 
-               if (restart || meye.mchip_mode != MCHIP_HIC_MODE_CONT_OUT)
-                       mchip_continuous_start();
-               meye.grab_buffer[vm->frame].state = MEYE_BUF_USING;
-               kfifo_put(meye.grabq, (unsigned char *)&vm->frame, sizeof(int));
-               mutex_unlock(&meye.lock);
-               break;
-       }
+       mutex_lock(&meye.lock);
 
-       case VIDIOCGMBUF: {
-               struct video_mbuf *vm = arg;
-               int i;
+       if (meye.mchip_mode != MCHIP_HIC_MODE_CONT_COMP)
+               mchip_cont_compression_start();
 
-               memset(vm, 0 , sizeof(*vm));
-               vm->size = gbufsize * gbuffers;
-               vm->frames = gbuffers;
-               for (i = 0; i < gbuffers; i++)
-                       vm->offsets[i] = i * gbufsize;
-               break;
-       }
+       meye.grab_buffer[*nb].state = MEYE_BUF_USING;
+       kfifo_put(meye.grabq, (unsigned char *)nb, sizeof(int));
+       mutex_unlock(&meye.lock);
 
-       case MEYEIOC_G_PARAMS: {
-               struct meye_params *p = arg;
-               *p = meye.params;
-               break;
-       }
+       return 0;
+}
 
-       case MEYEIOC_S_PARAMS: {
-               struct meye_params *jp = arg;
-               if (jp->subsample > 1)
-                       return -EINVAL;
-               if (jp->quality > 10)
-                       return -EINVAL;
-               if (jp->sharpness > 63 || jp->agc > 63 || jp->picture > 63)
-                       return -EINVAL;
-               if (jp->framerate > 31)
-                       return -EINVAL;
-               mutex_lock(&meye.lock);
-               if (meye.params.subsample != jp->subsample ||
-                   meye.params.quality != jp->quality)
-                       mchip_hic_stop();       /* need restart */
-               meye.params = *jp;
-               sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERASHARPNESS,
-                                     meye.params.sharpness);
-               sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAAGC,
-                                     meye.params.agc);
-               sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAPICTURE,
-                                     meye.params.picture);
-               mutex_unlock(&meye.lock);
-               break;
-       }
+static int meyeioc_sync(struct file *file, void *fh, int *i)
+{
+       int unused;
 
-       case MEYEIOC_QBUF_CAPT: {
-               int *nb = arg;
-
-               if (!meye.grab_fbuffer)
-                       return -EINVAL;
-               if (*nb >= gbuffers)
-                       return -EINVAL;
-               if (*nb < 0) {
-                       /* stop capture */
-                       mchip_hic_stop();
-                       return 0;
-               }
-               if (meye.grab_buffer[*nb].state != MEYE_BUF_UNUSED)
-                       return -EBUSY;
-               mutex_lock(&meye.lock);
-               if (meye.mchip_mode != MCHIP_HIC_MODE_CONT_COMP)
-                       mchip_cont_compression_start();
-               meye.grab_buffer[*nb].state = MEYE_BUF_USING;
-               kfifo_put(meye.grabq, (unsigned char *)nb, sizeof(int));
+       if (*i < 0 || *i >= gbuffers)
+               return -EINVAL;
+
+       mutex_lock(&meye.lock);
+       switch (meye.grab_buffer[*i].state) {
+
+       case MEYE_BUF_UNUSED:
                mutex_unlock(&meye.lock);
-               break;
+               return -EINVAL;
+       case MEYE_BUF_USING:
+               if (file->f_flags & O_NONBLOCK) {
+                       mutex_unlock(&meye.lock);
+                       return -EAGAIN;
+               }
+               if (wait_event_interruptible(meye.proc_list,
+                       (meye.grab_buffer[*i].state != MEYE_BUF_USING))) {
+                       mutex_unlock(&meye.lock);
+                       return -EINTR;
+               }
+               /* fall through */
+       case MEYE_BUF_DONE:
+               meye.grab_buffer[*i].state = MEYE_BUF_UNUSED;
+               kfifo_get(meye.doneq, (unsigned char *)&unused, sizeof(int));
        }
+       *i = meye.grab_buffer[*i].size;
+       mutex_unlock(&meye.lock);
+       return 0;
+}
 
-       case MEYEIOC_SYNC: {
-               int *i = arg;
-               int unused;
+static int meyeioc_stillcapt(void)
+{
+       if (!meye.grab_fbuffer)
+               return -EINVAL;
 
-               if (*i < 0 || *i >= gbuffers)
-                       return -EINVAL;
+       if (meye.grab_buffer[0].state != MEYE_BUF_UNUSED)
+               return -EBUSY;
 
-               mutex_lock(&meye.lock);
-               switch (meye.grab_buffer[*i].state) {
+       mutex_lock(&meye.lock);
+       meye.grab_buffer[0].state = MEYE_BUF_USING;
+       mchip_take_picture();
 
-               case MEYE_BUF_UNUSED:
-                       mutex_unlock(&meye.lock);
-                       return -EINVAL;
-               case MEYE_BUF_USING:
-                       if (file->f_flags & O_NONBLOCK) {
-                               mutex_unlock(&meye.lock);
-                               return -EAGAIN;
-                       }
-                       if (wait_event_interruptible(meye.proc_list,
-                                                    (meye.grab_buffer[*i].state != MEYE_BUF_USING))) {
-                               mutex_unlock(&meye.lock);
-                               return -EINTR;
-                       }
-                       /* fall through */
-               case MEYE_BUF_DONE:
-                       meye.grab_buffer[*i].state = MEYE_BUF_UNUSED;
-                       kfifo_get(meye.doneq, (unsigned char *)&unused, sizeof(int));
-               }
-               *i = meye.grab_buffer[*i].size;
-               mutex_unlock(&meye.lock);
-               break;
-       }
+       mchip_get_picture(meye.grab_fbuffer,
+                       mchip_hsize() * mchip_vsize() * 2);
 
-       case MEYEIOC_STILLCAPT: {
+       meye.grab_buffer[0].state = MEYE_BUF_DONE;
+       mutex_unlock(&meye.lock);
 
-               if (!meye.grab_fbuffer)
-                       return -EINVAL;
-               if (meye.grab_buffer[0].state != MEYE_BUF_UNUSED)
-                       return -EBUSY;
-               mutex_lock(&meye.lock);
-               meye.grab_buffer[0].state = MEYE_BUF_USING;
+       return 0;
+}
+
+static int meyeioc_stilljcapt(int *len)
+{
+       if (!meye.grab_fbuffer)
+               return -EINVAL;
+
+       if (meye.grab_buffer[0].state != MEYE_BUF_UNUSED)
+               return -EBUSY;
+
+       mutex_lock(&meye.lock);
+       meye.grab_buffer[0].state = MEYE_BUF_USING;
+       *len = -1;
+
+       while (*len == -1) {
                mchip_take_picture();
-               mchip_get_picture(
-                       meye.grab_fbuffer,
-                       mchip_hsize() * mchip_vsize() * 2);
-               meye.grab_buffer[0].state = MEYE_BUF_DONE;
-               mutex_unlock(&meye.lock);
-               break;
+               *len = mchip_compress_frame(meye.grab_fbuffer, gbufsize);
        }
 
-       case MEYEIOC_STILLJCAPT: {
-               int *len = arg;
-
-               if (!meye.grab_fbuffer)
-                       return -EINVAL;
-               if (meye.grab_buffer[0].state != MEYE_BUF_UNUSED)
-                       return -EBUSY;
-               mutex_lock(&meye.lock);
-               meye.grab_buffer[0].state = MEYE_BUF_USING;
-               *len = -1;
-               while (*len == -1) {
-                       mchip_take_picture();
-                       *len = mchip_compress_frame(meye.grab_fbuffer, gbufsize);
-               }
-               meye.grab_buffer[0].state = MEYE_BUF_DONE;
-               mutex_unlock(&meye.lock);
-               break;
-       }
+       meye.grab_buffer[0].state = MEYE_BUF_DONE;
+       mutex_unlock(&meye.lock);
+       return 0;
+}
 
-       case VIDIOC_QUERYCAP: {
-               struct v4l2_capability *cap = arg;
+static int vidioc_querycap(struct file *file, void *fh,
+                               struct v4l2_capability *cap)
+{
+       memset(cap, 0, sizeof(*cap));
+       strcpy(cap->driver, "meye");
+       strcpy(cap->card, "meye");
+       sprintf(cap->bus_info, "PCI:%s", pci_name(meye.mchip_dev));
 
-               if (forcev4l1)
-                       return -EINVAL;
+       cap->version = (MEYE_DRIVER_MAJORVERSION << 8) +
+                      MEYE_DRIVER_MINORVERSION;
 
-               memset(cap, 0, sizeof(*cap));
-               strcpy(cap->driver, "meye");
-               strcpy(cap->card, "meye");
-               sprintf(cap->bus_info, "PCI:%s", pci_name(meye.mchip_dev));
-               cap->version = (MEYE_DRIVER_MAJORVERSION << 8) +
-                              MEYE_DRIVER_MINORVERSION;
-               cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
-                                   V4L2_CAP_STREAMING;
-               break;
-       }
+       cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
+                           V4L2_CAP_STREAMING;
+
+       return 0;
+}
+
+static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
+{
+       if (i->index != 0)
+               return -EINVAL;
 
-       case VIDIOC_ENUMINPUT: {
-               struct v4l2_input *i = arg;
+       memset(i, 0, sizeof(*i));
+       i->index = 0;
+       strcpy(i->name, "Camera");
+       i->type = V4L2_INPUT_TYPE_CAMERA;
 
-               if (i->index != 0)
-                       return -EINVAL;
-               memset(i, 0, sizeof(*i));
-               i->index = 0;
-               strcpy(i->name, "Camera");
-               i->type = V4L2_INPUT_TYPE_CAMERA;
+       return 0;
+}
+
+static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
+{
+       *i = 0;
+       return 0;
+}
+
+static int vidioc_s_input(struct file *file, void *fh, unsigned int i)
+{
+       if (i != 0)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int vidioc_queryctrl(struct file *file, void *fh,
+                               struct v4l2_queryctrl *c)
+{
+       switch (c->id) {
+
+       case V4L2_CID_BRIGHTNESS:
+               c->type = V4L2_CTRL_TYPE_INTEGER;
+               strcpy(c->name, "Brightness");
+               c->minimum = 0;
+               c->maximum = 63;
+               c->step = 1;
+               c->default_value = 32;
+               c->flags = 0;
+               break;
+       case V4L2_CID_HUE:
+               c->type = V4L2_CTRL_TYPE_INTEGER;
+               strcpy(c->name, "Hue");
+               c->minimum = 0;
+               c->maximum = 63;
+               c->step = 1;
+               c->default_value = 32;
+               c->flags = 0;
+               break;
+       case V4L2_CID_CONTRAST:
+               c->type = V4L2_CTRL_TYPE_INTEGER;
+               strcpy(c->name, "Contrast");
+               c->minimum = 0;
+               c->maximum = 63;
+               c->step = 1;
+               c->default_value = 32;
+               c->flags = 0;
+               break;
+       case V4L2_CID_SATURATION:
+               c->type = V4L2_CTRL_TYPE_INTEGER;
+               strcpy(c->name, "Saturation");
+               c->minimum = 0;
+               c->maximum = 63;
+               c->step = 1;
+               c->default_value = 32;
+               c->flags = 0;
+               break;
+       case V4L2_CID_AGC:
+               c->type = V4L2_CTRL_TYPE_INTEGER;
+               strcpy(c->name, "Agc");
+               c->minimum = 0;
+               c->maximum = 63;
+               c->step = 1;
+               c->default_value = 48;
+               c->flags = 0;
                break;
+       case V4L2_CID_MEYE_SHARPNESS:
+       case V4L2_CID_SHARPNESS:
+               c->type = V4L2_CTRL_TYPE_INTEGER;
+               strcpy(c->name, "Sharpness");
+               c->minimum = 0;
+               c->maximum = 63;
+               c->step = 1;
+               c->default_value = 32;
+
+               /* Continue to report legacy private SHARPNESS ctrl but
+                * say it is disabled in preference to ctrl in the spec
+                */
+               c->flags = (c->id == V4L2_CID_SHARPNESS) ? 0 :
+                                               V4L2_CTRL_FLAG_DISABLED;
+               break;
+       case V4L2_CID_PICTURE:
+               c->type = V4L2_CTRL_TYPE_INTEGER;
+               strcpy(c->name, "Picture");
+               c->minimum = 0;
+               c->maximum = 63;
+               c->step = 1;
+               c->default_value = 0;
+               c->flags = 0;
+               break;
+       case V4L2_CID_JPEGQUAL:
+               c->type = V4L2_CTRL_TYPE_INTEGER;
+               strcpy(c->name, "JPEG quality");
+               c->minimum = 0;
+               c->maximum = 10;
+               c->step = 1;
+               c->default_value = 8;
+               c->flags = 0;
+               break;
+       case V4L2_CID_FRAMERATE:
+               c->type = V4L2_CTRL_TYPE_INTEGER;
+               strcpy(c->name, "Framerate");
+               c->minimum = 0;
+               c->maximum = 31;
+               c->step = 1;
+               c->default_value = 0;
+               c->flags = 0;
+               break;
+       default:
+               return -EINVAL;
        }
 
-       case VIDIOC_G_INPUT: {
-               int *i = arg;
+       return 0;
+}
 
-               *i = 0;
+static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *c)
+{
+       mutex_lock(&meye.lock);
+       switch (c->id) {
+       case V4L2_CID_BRIGHTNESS:
+               sony_pic_camera_command(
+                       SONY_PIC_COMMAND_SETCAMERABRIGHTNESS, c->value);
+               meye.picture.brightness = c->value << 10;
+               break;
+       case V4L2_CID_HUE:
+               sony_pic_camera_command(
+                       SONY_PIC_COMMAND_SETCAMERAHUE, c->value);
+               meye.picture.hue = c->value << 10;
+               break;
+       case V4L2_CID_CONTRAST:
+               sony_pic_camera_command(
+                       SONY_PIC_COMMAND_SETCAMERACONTRAST, c->value);
+               meye.picture.contrast = c->value << 10;
+               break;
+       case V4L2_CID_SATURATION:
+               sony_pic_camera_command(
+                       SONY_PIC_COMMAND_SETCAMERACOLOR, c->value);
+               meye.picture.colour = c->value << 10;
+               break;
+       case V4L2_CID_AGC:
+               sony_pic_camera_command(
+                       SONY_PIC_COMMAND_SETCAMERAAGC, c->value);
+               meye.params.agc = c->value;
+               break;
+       case V4L2_CID_SHARPNESS:
+       case V4L2_CID_MEYE_SHARPNESS:
+               sony_pic_camera_command(
+                       SONY_PIC_COMMAND_SETCAMERASHARPNESS, c->value);
+               meye.params.sharpness = c->value;
+               break;
+       case V4L2_CID_PICTURE:
+               sony_pic_camera_command(
+                       SONY_PIC_COMMAND_SETCAMERAPICTURE, c->value);
+               meye.params.picture = c->value;
+               break;
+       case V4L2_CID_JPEGQUAL:
+               meye.params.quality = c->value;
+               break;
+       case V4L2_CID_FRAMERATE:
+               meye.params.framerate = c->value;
                break;
+       default:
+               mutex_unlock(&meye.lock);
+               return -EINVAL;
        }
+       mutex_unlock(&meye.lock);
 
-       case VIDIOC_S_INPUT: {
-               int *i = arg;
+       return 0;
+}
 
-               if (*i != 0)
-                       return -EINVAL;
+static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *c)
+{
+       mutex_lock(&meye.lock);
+       switch (c->id) {
+       case V4L2_CID_BRIGHTNESS:
+               c->value = meye.picture.brightness >> 10;
+               break;
+       case V4L2_CID_HUE:
+               c->value = meye.picture.hue >> 10;
+               break;
+       case V4L2_CID_CONTRAST:
+               c->value = meye.picture.contrast >> 10;
+               break;
+       case V4L2_CID_SATURATION:
+               c->value = meye.picture.colour >> 10;
+               break;
+       case V4L2_CID_AGC:
+               c->value = meye.params.agc;
+               break;
+       case V4L2_CID_SHARPNESS:
+       case V4L2_CID_MEYE_SHARPNESS:
+               c->value = meye.params.sharpness;
                break;
+       case V4L2_CID_PICTURE:
+               c->value = meye.params.picture;
+               break;
+       case V4L2_CID_JPEGQUAL:
+               c->value = meye.params.quality;
+               break;
+       case V4L2_CID_FRAMERATE:
+               c->value = meye.params.framerate;
+               break;
+       default:
+               mutex_unlock(&meye.lock);
+               return -EINVAL;
        }
+       mutex_unlock(&meye.lock);
 
-       case VIDIOC_QUERYCTRL: {
-               struct v4l2_queryctrl *c = arg;
+       return 0;
+}
 
-               switch (c->id) {
+static int vidioc_enum_fmt_cap(struct file *file, void *fh,
+                               struct v4l2_fmtdesc *f)
+{
+       if (f->index > 1)
+               return -EINVAL;
 
-               case V4L2_CID_BRIGHTNESS:
-                       c->type = V4L2_CTRL_TYPE_INTEGER;
-                       strcpy(c->name, "Brightness");
-                       c->minimum = 0;
-                       c->maximum = 63;
-                       c->step = 1;
-                       c->default_value = 32;
-                       c->flags = 0;
-                       break;
-               case V4L2_CID_HUE:
-                       c->type = V4L2_CTRL_TYPE_INTEGER;
-                       strcpy(c->name, "Hue");
-                       c->minimum = 0;
-                       c->maximum = 63;
-                       c->step = 1;
-                       c->default_value = 32;
-                       c->flags = 0;
-                       break;
-               case V4L2_CID_CONTRAST:
-                       c->type = V4L2_CTRL_TYPE_INTEGER;
-                       strcpy(c->name, "Contrast");
-                       c->minimum = 0;
-                       c->maximum = 63;
-                       c->step = 1;
-                       c->default_value = 32;
-                       c->flags = 0;
-                       break;
-               case V4L2_CID_SATURATION:
-                       c->type = V4L2_CTRL_TYPE_INTEGER;
-                       strcpy(c->name, "Saturation");
-                       c->minimum = 0;
-                       c->maximum = 63;
-                       c->step = 1;
-                       c->default_value = 32;
-                       c->flags = 0;
-                       break;
-               case V4L2_CID_AGC:
-                       c->type = V4L2_CTRL_TYPE_INTEGER;
-                       strcpy(c->name, "Agc");
-                       c->minimum = 0;
-                       c->maximum = 63;
-                       c->step = 1;
-                       c->default_value = 48;
-                       c->flags = 0;
-                       break;
-               case V4L2_CID_SHARPNESS:
-                       c->type = V4L2_CTRL_TYPE_INTEGER;
-                       strcpy(c->name, "Sharpness");
-                       c->minimum = 0;
-                       c->maximum = 63;
-                       c->step = 1;
-                       c->default_value = 32;
-                       c->flags = 0;
-                       break;
-               case V4L2_CID_PICTURE:
-                       c->type = V4L2_CTRL_TYPE_INTEGER;
-                       strcpy(c->name, "Picture");
-                       c->minimum = 0;
-                       c->maximum = 63;
-                       c->step = 1;
-                       c->default_value = 0;
-                       c->flags = 0;
-                       break;
-               case V4L2_CID_JPEGQUAL:
-                       c->type = V4L2_CTRL_TYPE_INTEGER;
-                       strcpy(c->name, "JPEG quality");
-                       c->minimum = 0;
-                       c->maximum = 10;
-                       c->step = 1;
-                       c->default_value = 8;
-                       c->flags = 0;
-                       break;
-               case V4L2_CID_FRAMERATE:
-                       c->type = V4L2_CTRL_TYPE_INTEGER;
-                       strcpy(c->name, "Framerate");
-                       c->minimum = 0;
-                       c->maximum = 31;
-                       c->step = 1;
-                       c->default_value = 0;
-                       c->flags = 0;
-                       break;
-               default:
-                       return -EINVAL;
-               }
-               break;
+       if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       if (f->index == 0) {
+               /* standard YUV 422 capture */
+               memset(f, 0, sizeof(*f));
+               f->index = 0;
+               f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               f->flags = 0;
+               strcpy(f->description, "YUV422");
+               f->pixelformat = V4L2_PIX_FMT_YUYV;
+       } else {
+               /* compressed MJPEG capture */
+               memset(f, 0, sizeof(*f));
+               f->index = 1;
+               f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               f->flags = V4L2_FMT_FLAG_COMPRESSED;
+               strcpy(f->description, "MJPEG");
+               f->pixelformat = V4L2_PIX_FMT_MJPEG;
        }
 
-       case VIDIOC_S_CTRL: {
-               struct v4l2_control *c = arg;
+       return 0;
+}
 
-               mutex_lock(&meye.lock);
-               switch (c->id) {
-               case V4L2_CID_BRIGHTNESS:
-                       sony_pic_camera_command(
-                               SONY_PIC_COMMAND_SETCAMERABRIGHTNESS, c->value);
-                       meye.picture.brightness = c->value << 10;
-                       break;
-               case V4L2_CID_HUE:
-                       sony_pic_camera_command(
-                               SONY_PIC_COMMAND_SETCAMERAHUE, c->value);
-                       meye.picture.hue = c->value << 10;
-                       break;
-               case V4L2_CID_CONTRAST:
-                       sony_pic_camera_command(
-                               SONY_PIC_COMMAND_SETCAMERACONTRAST, c->value);
-                       meye.picture.contrast = c->value << 10;
-                       break;
-               case V4L2_CID_SATURATION:
-                       sony_pic_camera_command(
-                               SONY_PIC_COMMAND_SETCAMERACOLOR, c->value);
-                       meye.picture.colour = c->value << 10;
-                       break;
-               case V4L2_CID_AGC:
-                       sony_pic_camera_command(
-                               SONY_PIC_COMMAND_SETCAMERAAGC, c->value);
-                       meye.params.agc = c->value;
-                       break;
-               case V4L2_CID_SHARPNESS:
-                       sony_pic_camera_command(
-                               SONY_PIC_COMMAND_SETCAMERASHARPNESS, c->value);
-                       meye.params.sharpness = c->value;
-                       break;
-               case V4L2_CID_PICTURE:
-                       sony_pic_camera_command(
-                               SONY_PIC_COMMAND_SETCAMERAPICTURE, c->value);
-                       meye.params.picture = c->value;
-                       break;
-               case V4L2_CID_JPEGQUAL:
-                       meye.params.quality = c->value;
-                       break;
-               case V4L2_CID_FRAMERATE:
-                       meye.params.framerate = c->value;
-                       break;
-               default:
-                       mutex_unlock(&meye.lock);
-                       return -EINVAL;
-               }
-               mutex_unlock(&meye.lock);
-               break;
+static int vidioc_try_fmt_cap(struct file *file, void *fh,
+                               struct v4l2_format *f)
+{
+       if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV &&
+           f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG)
+               return -EINVAL;
+
+       if (f->fmt.pix.field != V4L2_FIELD_ANY &&
+           f->fmt.pix.field != V4L2_FIELD_NONE)
+               return -EINVAL;
+
+       f->fmt.pix.field = V4L2_FIELD_NONE;
+
+       if (f->fmt.pix.width <= 320) {
+               f->fmt.pix.width = 320;
+               f->fmt.pix.height = 240;
+       } else {
+               f->fmt.pix.width = 640;
+               f->fmt.pix.height = 480;
        }
 
-       case VIDIOC_G_CTRL: {
-               struct v4l2_control *c = arg;
+       f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
+       f->fmt.pix.sizeimage = f->fmt.pix.height *
+                              f->fmt.pix.bytesperline;
+       f->fmt.pix.colorspace = 0;
+       f->fmt.pix.priv = 0;
 
-               mutex_lock(&meye.lock);
-               switch (c->id) {
-               case V4L2_CID_BRIGHTNESS:
-                       c->value = meye.picture.brightness >> 10;
-                       break;
-               case V4L2_CID_HUE:
-                       c->value = meye.picture.hue >> 10;
-                       break;
-               case V4L2_CID_CONTRAST:
-                       c->value = meye.picture.contrast >> 10;
-                       break;
-               case V4L2_CID_SATURATION:
-                       c->value = meye.picture.colour >> 10;
-                       break;
-               case V4L2_CID_AGC:
-                       c->value = meye.params.agc;
-                       break;
-               case V4L2_CID_SHARPNESS:
-                       c->value = meye.params.sharpness;
-                       break;
-               case V4L2_CID_PICTURE:
-                       c->value = meye.params.picture;
-                       break;
-               case V4L2_CID_JPEGQUAL:
-                       c->value = meye.params.quality;
-                       break;
-               case V4L2_CID_FRAMERATE:
-                       c->value = meye.params.framerate;
-                       break;
-               default:
-                       mutex_unlock(&meye.lock);
-                       return -EINVAL;
-               }
-               mutex_unlock(&meye.lock);
+       return 0;
+}
+
+static int vidioc_g_fmt_cap(struct file *file, void *fh, struct v4l2_format *f)
+{
+       if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format));
+       f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+       switch (meye.mchip_mode) {
+       case MCHIP_HIC_MODE_CONT_OUT:
+       default:
+               f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
+               break;
+       case MCHIP_HIC_MODE_CONT_COMP:
+               f->fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
                break;
        }
 
-       case VIDIOC_ENUM_FMT: {
-               struct v4l2_fmtdesc *f = arg;
-
-               if (f->index > 1)
-                       return -EINVAL;
-               if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-                       return -EINVAL;
-               if (f->index == 0) {
-                       /* standard YUV 422 capture */
-                       memset(f, 0, sizeof(*f));
-                       f->index = 0;
-                       f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-                       f->flags = 0;
-                       strcpy(f->description, "YUV422");
-                       f->pixelformat = V4L2_PIX_FMT_YUYV;
-               } else {
-                       /* compressed MJPEG capture */
-                       memset(f, 0, sizeof(*f));
-                       f->index = 1;
-                       f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-                       f->flags = V4L2_FMT_FLAG_COMPRESSED;
-                       strcpy(f->description, "MJPEG");
-                       f->pixelformat = V4L2_PIX_FMT_MJPEG;
-               }
-               break;
+       f->fmt.pix.field = V4L2_FIELD_NONE;
+       f->fmt.pix.width = mchip_hsize();
+       f->fmt.pix.height = mchip_vsize();
+       f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
+       f->fmt.pix.sizeimage = f->fmt.pix.height *
+                              f->fmt.pix.bytesperline;
+       f->fmt.pix.colorspace = 0;
+       f->fmt.pix.priv = 0;
+
+       return 0;
+}
+
+static int vidioc_s_fmt_cap(struct file *file, void *fh, struct v4l2_format *f)
+{
+       if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV &&
+           f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG)
+               return -EINVAL;
+
+       if (f->fmt.pix.field != V4L2_FIELD_ANY &&
+           f->fmt.pix.field != V4L2_FIELD_NONE)
+               return -EINVAL;
+
+       f->fmt.pix.field = V4L2_FIELD_NONE;
+       mutex_lock(&meye.lock);
+
+       if (f->fmt.pix.width <= 320) {
+               f->fmt.pix.width = 320;
+               f->fmt.pix.height = 240;
+               meye.params.subsample = 1;
+       } else {
+               f->fmt.pix.width = 640;
+               f->fmt.pix.height = 480;
+               meye.params.subsample = 0;
        }
 
-       case VIDIOC_TRY_FMT: {
-               struct v4l2_format *f = arg;
-
-               if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-                       return -EINVAL;
-               if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV &&
-                   f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG)
-                       return -EINVAL;
-               if (f->fmt.pix.field != V4L2_FIELD_ANY &&
-                   f->fmt.pix.field != V4L2_FIELD_NONE)
-                       return -EINVAL;
-               f->fmt.pix.field = V4L2_FIELD_NONE;
-               if (f->fmt.pix.width <= 320) {
-                       f->fmt.pix.width = 320;
-                       f->fmt.pix.height = 240;
-               } else {
-                       f->fmt.pix.width = 640;
-                       f->fmt.pix.height = 480;
-               }
-               f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
-               f->fmt.pix.sizeimage = f->fmt.pix.height *
-                                      f->fmt.pix.bytesperline;
-               f->fmt.pix.colorspace = 0;
-               f->fmt.pix.priv = 0;
+       switch (f->fmt.pix.pixelformat) {
+       case V4L2_PIX_FMT_YUYV:
+               meye.mchip_mode = MCHIP_HIC_MODE_CONT_OUT;
+               break;
+       case V4L2_PIX_FMT_MJPEG:
+               meye.mchip_mode = MCHIP_HIC_MODE_CONT_COMP;
                break;
        }
 
-       case VIDIOC_G_FMT: {
-               struct v4l2_format *f = arg;
+       mutex_unlock(&meye.lock);
+       f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
+       f->fmt.pix.sizeimage = f->fmt.pix.height *
+                              f->fmt.pix.bytesperline;
+       f->fmt.pix.colorspace = 0;
+       f->fmt.pix.priv = 0;
 
-               if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-                       return -EINVAL;
-               memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format));
-               f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               switch (meye.mchip_mode) {
-               case MCHIP_HIC_MODE_CONT_OUT:
-               default:
-                       f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
-                       break;
-               case MCHIP_HIC_MODE_CONT_COMP:
-                       f->fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
-                       break;
-               }
-               f->fmt.pix.field = V4L2_FIELD_NONE;
-               f->fmt.pix.width = mchip_hsize();
-               f->fmt.pix.height = mchip_vsize();
-               f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
-               f->fmt.pix.sizeimage = f->fmt.pix.height *
-                                      f->fmt.pix.bytesperline;
-               f->fmt.pix.colorspace = 0;
-               f->fmt.pix.priv = 0;
-               break;
-       }
+       return 0;
+}
 
-       case VIDIOC_S_FMT: {
-               struct v4l2_format *f = arg;
-
-               if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-                       return -EINVAL;
-               if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV &&
-                   f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG)
-                       return -EINVAL;
-               if (f->fmt.pix.field != V4L2_FIELD_ANY &&
-                   f->fmt.pix.field != V4L2_FIELD_NONE)
-                       return -EINVAL;
-               f->fmt.pix.field = V4L2_FIELD_NONE;
-               mutex_lock(&meye.lock);
-               if (f->fmt.pix.width <= 320) {
-                       f->fmt.pix.width = 320;
-                       f->fmt.pix.height = 240;
-                       meye.params.subsample = 1;
-               } else {
-                       f->fmt.pix.width = 640;
-                       f->fmt.pix.height = 480;
-                       meye.params.subsample = 0;
-               }
-               switch (f->fmt.pix.pixelformat) {
-               case V4L2_PIX_FMT_YUYV:
-                       meye.mchip_mode = MCHIP_HIC_MODE_CONT_OUT;
-                       break;
-               case V4L2_PIX_FMT_MJPEG:
-                       meye.mchip_mode = MCHIP_HIC_MODE_CONT_COMP;
-                       break;
-               }
-               mutex_unlock(&meye.lock);
-               f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
-               f->fmt.pix.sizeimage = f->fmt.pix.height *
-                                      f->fmt.pix.bytesperline;
-               f->fmt.pix.colorspace = 0;
-               f->fmt.pix.priv = 0;
+static int vidioc_reqbufs(struct file *file, void *fh,
+                               struct v4l2_requestbuffers *req)
+{
+       int i;
 
-               break;
-       }
+       if (req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
 
-       case VIDIOC_REQBUFS: {
-               struct v4l2_requestbuffers *req = arg;
-               int i;
+       if (req->memory != V4L2_MEMORY_MMAP)
+               return -EINVAL;
 
-               if (req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-                       return -EINVAL;
-               if (req->memory != V4L2_MEMORY_MMAP)
-                       return -EINVAL;
-               if (meye.grab_fbuffer && req->count == gbuffers) {
-                       /* already allocated, no modifications */
-                       break;
-               }
-               mutex_lock(&meye.lock);
-               if (meye.grab_fbuffer) {
-                       for (i = 0; i < gbuffers; i++)
-                               if (meye.vma_use_count[i]) {
-                                       mutex_unlock(&meye.lock);
-                                       return -EINVAL;
-                               }
-                       rvfree(meye.grab_fbuffer, gbuffers * gbufsize);
-                       meye.grab_fbuffer = NULL;
-               }
-               gbuffers = max(2, min((int)req->count, MEYE_MAX_BUFNBRS));
-               req->count = gbuffers;
-               meye.grab_fbuffer = rvmalloc(gbuffers * gbufsize);
-               if (!meye.grab_fbuffer) {
-                       printk(KERN_ERR "meye: v4l framebuffer allocation"
-                                       " failed\n");
-                       mutex_unlock(&meye.lock);
-                       return -ENOMEM;
-               }
-               for (i = 0; i < gbuffers; i++)
-                       meye.vma_use_count[i] = 0;
-               mutex_unlock(&meye.lock);
-               break;
+       if (meye.grab_fbuffer && req->count == gbuffers) {
+               /* already allocated, no modifications */
+               return 0;
        }
 
-       case VIDIOC_QUERYBUF: {
-               struct v4l2_buffer *buf = arg;
-               int index = buf->index;
-
-               if (index < 0 || index >= gbuffers)
-                       return -EINVAL;
-               memset(buf, 0, sizeof(*buf));
-               buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               buf->index = index;
-               buf->bytesused = meye.grab_buffer[index].size;
-               buf->flags = V4L2_BUF_FLAG_MAPPED;
-               if (meye.grab_buffer[index].state == MEYE_BUF_USING)
-                       buf->flags |= V4L2_BUF_FLAG_QUEUED;
-               if (meye.grab_buffer[index].state == MEYE_BUF_DONE)
-                       buf->flags |= V4L2_BUF_FLAG_DONE;
-               buf->field = V4L2_FIELD_NONE;
-               buf->timestamp = meye.grab_buffer[index].timestamp;
-               buf->sequence = meye.grab_buffer[index].sequence;
-               buf->memory = V4L2_MEMORY_MMAP;
-               buf->m.offset = index * gbufsize;
-               buf->length = gbufsize;
-               break;
+       mutex_lock(&meye.lock);
+       if (meye.grab_fbuffer) {
+               for (i = 0; i < gbuffers; i++)
+                       if (meye.vma_use_count[i]) {
+                               mutex_unlock(&meye.lock);
+                               return -EINVAL;
+                       }
+               rvfree(meye.grab_fbuffer, gbuffers * gbufsize);
+               meye.grab_fbuffer = NULL;
        }
 
-       case VIDIOC_QBUF: {
-               struct v4l2_buffer *buf = arg;
-
-               if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-                       return -EINVAL;
-               if (buf->memory != V4L2_MEMORY_MMAP)
-                       return -EINVAL;
-               if (buf->index < 0 || buf->index >= gbuffers)
-                       return -EINVAL;
-               if (meye.grab_buffer[buf->index].state != MEYE_BUF_UNUSED)
-                       return -EINVAL;
-               mutex_lock(&meye.lock);
-               buf->flags |= V4L2_BUF_FLAG_QUEUED;
-               buf->flags &= ~V4L2_BUF_FLAG_DONE;
-               meye.grab_buffer[buf->index].state = MEYE_BUF_USING;
-               kfifo_put(meye.grabq, (unsigned char *)&buf->index, sizeof(int));
+       gbuffers = max(2, min((int)req->count, MEYE_MAX_BUFNBRS));
+       req->count = gbuffers;
+       meye.grab_fbuffer = rvmalloc(gbuffers * gbufsize);
+
+       if (!meye.grab_fbuffer) {
+               printk(KERN_ERR "meye: v4l framebuffer allocation"
+                               " failed\n");
                mutex_unlock(&meye.lock);
-               break;
+               return -ENOMEM;
        }
 
-       case VIDIOC_DQBUF: {
-               struct v4l2_buffer *buf = arg;
-               int reqnr;
+       for (i = 0; i < gbuffers; i++)
+               meye.vma_use_count[i] = 0;
 
-               if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-                       return -EINVAL;
-               if (buf->memory != V4L2_MEMORY_MMAP)
-                       return -EINVAL;
+       mutex_unlock(&meye.lock);
 
-               mutex_lock(&meye.lock);
-               if (kfifo_len(meye.doneq) == 0 && file->f_flags & O_NONBLOCK) {
-                       mutex_unlock(&meye.lock);
-                       return -EAGAIN;
-               }
-               if (wait_event_interruptible(meye.proc_list,
-                                            kfifo_len(meye.doneq) != 0) < 0) {
-                       mutex_unlock(&meye.lock);
-                       return -EINTR;
-               }
-               if (!kfifo_get(meye.doneq, (unsigned char *)&reqnr,
-                              sizeof(int))) {
-                       mutex_unlock(&meye.lock);
-                       return -EBUSY;
-               }
-               if (meye.grab_buffer[reqnr].state != MEYE_BUF_DONE) {
-                       mutex_unlock(&meye.lock);
-                       return -EINVAL;
-               }
-               buf->index = reqnr;
-               buf->bytesused = meye.grab_buffer[reqnr].size;
-               buf->flags = V4L2_BUF_FLAG_MAPPED;
-               buf->field = V4L2_FIELD_NONE;
-               buf->timestamp = meye.grab_buffer[reqnr].timestamp;
-               buf->sequence = meye.grab_buffer[reqnr].sequence;
-               buf->memory = V4L2_MEMORY_MMAP;
-               buf->m.offset = reqnr * gbufsize;
-               buf->length = gbufsize;
-               meye.grab_buffer[reqnr].state = MEYE_BUF_UNUSED;
+       return 0;
+}
+
+static int vidioc_querybuf(struct file *file, void *fh, struct v4l2_buffer *buf)
+{
+       int index = buf->index;
+
+       if (index < 0 || index >= gbuffers)
+               return -EINVAL;
+
+       memset(buf, 0, sizeof(*buf));
+
+       buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       buf->index = index;
+       buf->bytesused = meye.grab_buffer[index].size;
+       buf->flags = V4L2_BUF_FLAG_MAPPED;
+
+       if (meye.grab_buffer[index].state == MEYE_BUF_USING)
+               buf->flags |= V4L2_BUF_FLAG_QUEUED;
+
+       if (meye.grab_buffer[index].state == MEYE_BUF_DONE)
+               buf->flags |= V4L2_BUF_FLAG_DONE;
+
+       buf->field = V4L2_FIELD_NONE;
+       buf->timestamp = meye.grab_buffer[index].timestamp;
+       buf->sequence = meye.grab_buffer[index].sequence;
+       buf->memory = V4L2_MEMORY_MMAP;
+       buf->m.offset = index * gbufsize;
+       buf->length = gbufsize;
+
+       return 0;
+}
+
+static int vidioc_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
+{
+       if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       if (buf->memory != V4L2_MEMORY_MMAP)
+               return -EINVAL;
+
+       if (buf->index < 0 || buf->index >= gbuffers)
+               return -EINVAL;
+
+       if (meye.grab_buffer[buf->index].state != MEYE_BUF_UNUSED)
+               return -EINVAL;
+
+       mutex_lock(&meye.lock);
+       buf->flags |= V4L2_BUF_FLAG_QUEUED;
+       buf->flags &= ~V4L2_BUF_FLAG_DONE;
+       meye.grab_buffer[buf->index].state = MEYE_BUF_USING;
+       kfifo_put(meye.grabq, (unsigned char *)&buf->index, sizeof(int));
+       mutex_unlock(&meye.lock);
+
+       return 0;
+}
+
+static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
+{
+       int reqnr;
+
+       if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       if (buf->memory != V4L2_MEMORY_MMAP)
+               return -EINVAL;
+
+       mutex_lock(&meye.lock);
+
+       if (kfifo_len(meye.doneq) == 0 && file->f_flags & O_NONBLOCK) {
                mutex_unlock(&meye.lock);
-               break;
+               return -EAGAIN;
        }
 
-       case VIDIOC_STREAMON: {
-               mutex_lock(&meye.lock);
-               switch (meye.mchip_mode) {
-               case MCHIP_HIC_MODE_CONT_OUT:
-                       mchip_continuous_start();
-                       break;
-               case MCHIP_HIC_MODE_CONT_COMP:
-                       mchip_cont_compression_start();
-                       break;
-               default:
-                       mutex_unlock(&meye.lock);
-                       return -EINVAL;
-               }
+       if (wait_event_interruptible(meye.proc_list,
+                                    kfifo_len(meye.doneq) != 0) < 0) {
                mutex_unlock(&meye.lock);
-               break;
+               return -EINTR;
        }
 
-       case VIDIOC_STREAMOFF: {
-               int i;
+       if (!kfifo_get(meye.doneq, (unsigned char *)&reqnr,
+                      sizeof(int))) {
+               mutex_unlock(&meye.lock);
+               return -EBUSY;
+       }
 
-               mutex_lock(&meye.lock);
-               mchip_hic_stop();
-               kfifo_reset(meye.grabq);
-               kfifo_reset(meye.doneq);
-               for (i = 0; i < MEYE_MAX_BUFNBRS; i++)
-                       meye.grab_buffer[i].state = MEYE_BUF_UNUSED;
+       if (meye.grab_buffer[reqnr].state != MEYE_BUF_DONE) {
                mutex_unlock(&meye.lock);
-               break;
+               return -EINVAL;
        }
 
-       /*
-        * XXX what about private snapshot ioctls ?
-        * Do they need to be converted to V4L2 ?
-       */
+       buf->index = reqnr;
+       buf->bytesused = meye.grab_buffer[reqnr].size;
+       buf->flags = V4L2_BUF_FLAG_MAPPED;
+       buf->field = V4L2_FIELD_NONE;
+       buf->timestamp = meye.grab_buffer[reqnr].timestamp;
+       buf->sequence = meye.grab_buffer[reqnr].sequence;
+       buf->memory = V4L2_MEMORY_MMAP;
+       buf->m.offset = reqnr * gbufsize;
+       buf->length = gbufsize;
+       meye.grab_buffer[reqnr].state = MEYE_BUF_UNUSED;
+       mutex_unlock(&meye.lock);
+
+       return 0;
+}
 
+static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)
+{
+       mutex_lock(&meye.lock);
+
+       switch (meye.mchip_mode) {
+       case MCHIP_HIC_MODE_CONT_OUT:
+               mchip_continuous_start();
+               break;
+       case MCHIP_HIC_MODE_CONT_COMP:
+               mchip_cont_compression_start();
+               break;
        default:
-               return -ENOIOCTLCMD;
+               mutex_unlock(&meye.lock);
+               return -EINVAL;
        }
 
+       mutex_unlock(&meye.lock);
+
        return 0;
 }
 
-static int meye_ioctl(struct inode *inode, struct file *file,
-                    unsigned int cmd, unsigned long arg)
+static int vidioc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i)
 {
-       return video_usercopy(inode, file, cmd, arg, meye_do_ioctl);
+       mutex_lock(&meye.lock);
+       mchip_hic_stop();
+       kfifo_reset(meye.grabq);
+       kfifo_reset(meye.doneq);
+
+       for (i = 0; i < MEYE_MAX_BUFNBRS; i++)
+               meye.grab_buffer[i].state = MEYE_BUF_UNUSED;
+
+       mutex_unlock(&meye.lock);
+       return 0;
+}
+
+static int vidioc_default(struct file *file, void *fh, int cmd, void *arg)
+{
+       switch (cmd) {
+       case MEYEIOC_G_PARAMS:
+               return meyeioc_g_params((struct meye_params *) arg);
+
+       case MEYEIOC_S_PARAMS:
+               return meyeioc_s_params((struct meye_params *) arg);
+
+       case MEYEIOC_QBUF_CAPT:
+               return meyeioc_qbuf_capt((int *) arg);
+
+       case MEYEIOC_SYNC:
+               return meyeioc_sync(file, fh, (int *) arg);
+
+       case MEYEIOC_STILLCAPT:
+               return meyeioc_stillcapt();
+
+       case MEYEIOC_STILLJCAPT:
+               return meyeioc_stilljcapt((int *) arg);
+
+       default:
+               return -EINVAL;
+       }
+
 }
 
 static unsigned int meye_poll(struct file *file, poll_table *wait)
@@ -1752,8 +1687,10 @@ static const struct file_operations meye_fops = {
        .open           = meye_open,
        .release        = meye_release,
        .mmap           = meye_mmap,
-       .ioctl          = meye_ioctl,
+       .ioctl          = video_ioctl2,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .poll           = meye_poll,
        .llseek         = no_llseek,
 };
@@ -1765,6 +1702,24 @@ static struct video_device meye_template = {
        .fops           = &meye_fops,
        .release        = video_device_release,
        .minor          = -1,
+       .vidioc_querycap        = vidioc_querycap,
+       .vidioc_enum_input      = vidioc_enum_input,
+       .vidioc_g_input         = vidioc_g_input,
+       .vidioc_s_input         = vidioc_s_input,
+       .vidioc_queryctrl       = vidioc_queryctrl,
+       .vidioc_s_ctrl          = vidioc_s_ctrl,
+       .vidioc_g_ctrl          = vidioc_g_ctrl,
+       .vidioc_enum_fmt_cap    = vidioc_enum_fmt_cap,
+       .vidioc_try_fmt_cap     = vidioc_try_fmt_cap,
+       .vidioc_g_fmt_cap       = vidioc_g_fmt_cap,
+       .vidioc_s_fmt_cap       = vidioc_s_fmt_cap,
+       .vidioc_reqbufs         = vidioc_reqbufs,
+       .vidioc_querybuf        = vidioc_querybuf,
+       .vidioc_qbuf            = vidioc_qbuf,
+       .vidioc_dqbuf           = vidioc_dqbuf,
+       .vidioc_streamon        = vidioc_streamon,
+       .vidioc_streamoff       = vidioc_streamoff,
+       .vidioc_default         = vidioc_default,
 };
 
 #ifdef CONFIG_PM
index 7a11f3159e32b755a3a435b6872590b35f0dc845..b73c740f7fb2697a5e128feee6de2f49abeec192 100644 (file)
@@ -366,7 +366,7 @@ int msp_sleep(struct msp_state *state, int timeout)
 }
 
 /* ------------------------------------------------------------------------ */
-#ifdef CONFIG_VIDEO_V4L1
+#ifdef CONFIG_VIDEO_ALLOW_V4L1
 static int msp_mode_v4l2_to_v4l1(int rxsubchans, int audmode)
 {
        if (rxsubchans == V4L2_TUNER_SUB_MONO)
@@ -514,7 +514,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
        /* --- v4l ioctls --- */
        /* take care: bttv does userspace copying, we'll get a
           kernel pointer here... */
-#ifdef CONFIG_VIDEO_V4L1
+#ifdef CONFIG_VIDEO_ALLOW_V4L1
        case VIDIOCGAUDIO:
        {
                struct video_audio *va = arg;
index 61ec794a737e2f438072a06e9e0272bb274e2a3f..7f5568592793c836f8a71d78181f83c6dcf2c648 100644 (file)
@@ -833,11 +833,6 @@ static int msp34xxg_modus(struct i2c_client *client)
                v4l_dbg(1, msp_debug, client, "selected radio modus\n");
                return 0x0001;
        }
-
-       if (state->v4l2_std & V4L2_STD_PAL) {
-               v4l_dbg(1, msp_debug, client, "selected PAL modus\n");
-               return 0x7001;
-       }
        if (state->v4l2_std == V4L2_STD_NTSC_M_JP) {
                v4l_dbg(1, msp_debug, client, "selected M (EIA-J) modus\n");
                return 0x4001;
@@ -846,15 +841,15 @@ static int msp34xxg_modus(struct i2c_client *client)
                v4l_dbg(1, msp_debug, client, "selected M (A2) modus\n");
                return 0x0001;
        }
+       if (state->v4l2_std == V4L2_STD_SECAM_L) {
+               v4l_dbg(1, msp_debug, client, "selected SECAM-L modus\n");
+               return 0x6001;
+       }
        if (state->v4l2_std & V4L2_STD_MN) {
                v4l_dbg(1, msp_debug, client, "selected M (BTSC) modus\n");
                return 0x2001;
        }
-       if (state->v4l2_std & V4L2_STD_SECAM) {
-               v4l_dbg(1, msp_debug, client, "selected SECAM modus\n");
-               return 0x6001;
-       }
-       return 0x0001;
+       return 0x7001;
 }
 
 static void msp34xxg_set_source(struct i2c_client *client, u16 reg, int in)
index 74fd6a01d4c4060b05037f93d7069715b0b41433..fbcb28233737c86182b89b73c133a428083547cd 100644 (file)
 #include "tuner-i2c.h"
 #include "mt20xx.h"
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "enable verbose debug messages");
 
-#define PREFIX "mt20xx"
-
 /* ---------------------------------------------------------------------- */
 
 static unsigned int optimize_vco  = 1;
@@ -24,7 +22,7 @@ module_param(optimize_vco,      int, 0644);
 static unsigned int tv_antenna    = 1;
 module_param(tv_antenna,        int, 0644);
 
-static unsigned int radio_antenna = 0;
+static unsigned int radio_antenna;
 module_param(radio_antenna,     int, 0644);
 
 /* ---------------------------------------------------------------------- */
@@ -611,6 +609,7 @@ struct dvb_frontend *microtune_attach(struct dvb_frontend *fe,
 
        priv->i2c_props.addr = i2c_addr;
        priv->i2c_props.adap = i2c_adap;
+       priv->i2c_props.name = "mt20xx";
 
        //priv->radio_if2 = 10700 * 1000;       /* 10.7MHz - FM radio */
 
index 5e9c825d2e91bb392d283d04a776c6aa7dc1de11..aa848e14ce5e75bbf43b8edecc057fdc209af33b 100644 (file)
@@ -29,7 +29,7 @@ static inline struct dvb_frontend *microtune_attach(struct dvb_frontend *fe,
                                             struct i2c_adapter* i2c_adap,
                                             u8 i2c_addr)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif
diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c
new file mode 100644 (file)
index 0000000..3fb5f63
--- /dev/null
@@ -0,0 +1,722 @@
+/*
+ * Driver for MT9M001 CMOS Image Sensor from Micron
+ *
+ * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
+ *
+ * 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/videodev2.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/log2.h>
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/soc_camera.h>
+
+#ifdef CONFIG_MT9M001_PCA9536_SWITCH
+#include <asm/gpio.h>
+#endif
+
+/* mt9m001 i2c address 0x5d
+ * The platform has to define i2c_board_info
+ * and call i2c_register_board_info() */
+
+/* mt9m001 selected register addresses */
+#define MT9M001_CHIP_VERSION           0x00
+#define MT9M001_ROW_START              0x01
+#define MT9M001_COLUMN_START           0x02
+#define MT9M001_WINDOW_HEIGHT          0x03
+#define MT9M001_WINDOW_WIDTH           0x04
+#define MT9M001_HORIZONTAL_BLANKING    0x05
+#define MT9M001_VERTICAL_BLANKING      0x06
+#define MT9M001_OUTPUT_CONTROL         0x07
+#define MT9M001_SHUTTER_WIDTH          0x09
+#define MT9M001_FRAME_RESTART          0x0b
+#define MT9M001_SHUTTER_DELAY          0x0c
+#define MT9M001_RESET                  0x0d
+#define MT9M001_READ_OPTIONS1          0x1e
+#define MT9M001_READ_OPTIONS2          0x20
+#define MT9M001_GLOBAL_GAIN            0x35
+#define MT9M001_CHIP_ENABLE            0xF1
+
+static const struct soc_camera_data_format mt9m001_colour_formats[] = {
+       /* Order important: first natively supported,
+        * second supported with a GPIO extender */
+       {
+               .name           = "Bayer (sRGB) 10 bit",
+               .depth          = 10,
+               .fourcc         = V4L2_PIX_FMT_SBGGR16,
+               .colorspace     = V4L2_COLORSPACE_SRGB,
+       }, {
+               .name           = "Bayer (sRGB) 8 bit",
+               .depth          = 8,
+               .fourcc         = V4L2_PIX_FMT_SBGGR8,
+               .colorspace     = V4L2_COLORSPACE_SRGB,
+       }
+};
+
+static const struct soc_camera_data_format mt9m001_monochrome_formats[] = {
+       /* Order important - see above */
+       {
+               .name           = "Monochrome 10 bit",
+               .depth          = 10,
+               .fourcc         = V4L2_PIX_FMT_Y16,
+       }, {
+               .name           = "Monochrome 8 bit",
+               .depth          = 8,
+               .fourcc         = V4L2_PIX_FMT_GREY,
+       },
+};
+
+struct mt9m001 {
+       struct i2c_client *client;
+       struct soc_camera_device icd;
+       int model;      /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */
+       int switch_gpio;
+       unsigned char autoexposure;
+       unsigned char datawidth;
+};
+
+static int reg_read(struct soc_camera_device *icd, const u8 reg)
+{
+       struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
+       struct i2c_client *client = mt9m001->client;
+       s32 data = i2c_smbus_read_word_data(client, reg);
+       return data < 0 ? data : swab16(data);
+}
+
+static int reg_write(struct soc_camera_device *icd, const u8 reg,
+                    const u16 data)
+{
+       struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
+       return i2c_smbus_write_word_data(mt9m001->client, reg, swab16(data));
+}
+
+static int reg_set(struct soc_camera_device *icd, const u8 reg,
+                  const u16 data)
+{
+       int ret;
+
+       ret = reg_read(icd, reg);
+       if (ret < 0)
+               return ret;
+       return reg_write(icd, reg, ret | data);
+}
+
+static int reg_clear(struct soc_camera_device *icd, const u8 reg,
+                    const u16 data)
+{
+       int ret;
+
+       ret = reg_read(icd, reg);
+       if (ret < 0)
+               return ret;
+       return reg_write(icd, reg, ret & ~data);
+}
+
+static int mt9m001_init(struct soc_camera_device *icd)
+{
+       int ret;
+
+       /* Disable chip, synchronous option update */
+       dev_dbg(icd->vdev->dev, "%s\n", __func__);
+
+       ret = reg_write(icd, MT9M001_RESET, 1);
+       if (ret >= 0)
+               ret = reg_write(icd, MT9M001_RESET, 0);
+       if (ret >= 0)
+               ret = reg_write(icd, MT9M001_OUTPUT_CONTROL, 0);
+
+       return ret >= 0 ? 0 : -EIO;
+}
+
+static int mt9m001_release(struct soc_camera_device *icd)
+{
+       /* Disable the chip */
+       reg_write(icd, MT9M001_OUTPUT_CONTROL, 0);
+       return 0;
+}
+
+static int mt9m001_start_capture(struct soc_camera_device *icd)
+{
+       /* Switch to master "normal" mode */
+       if (reg_write(icd, MT9M001_OUTPUT_CONTROL, 2) < 0)
+               return -EIO;
+       return 0;
+}
+
+static int mt9m001_stop_capture(struct soc_camera_device *icd)
+{
+       /* Stop sensor readout */
+       if (reg_write(icd, MT9M001_OUTPUT_CONTROL, 0) < 0)
+               return -EIO;
+       return 0;
+}
+
+static int bus_switch_request(struct mt9m001 *mt9m001,
+                             struct soc_camera_link *icl)
+{
+#ifdef CONFIG_MT9M001_PCA9536_SWITCH
+       int ret;
+       unsigned int gpio = icl->gpio;
+
+       if (gpio_is_valid(gpio)) {
+               /* We have a data bus switch. */
+               ret = gpio_request(gpio, "mt9m001");
+               if (ret < 0) {
+                       dev_err(&mt9m001->client->dev, "Cannot get GPIO %u\n",
+                               gpio);
+                       return ret;
+               }
+
+               ret = gpio_direction_output(gpio, 0);
+               if (ret < 0) {
+                       dev_err(&mt9m001->client->dev,
+                               "Cannot set GPIO %u to output\n", gpio);
+                       gpio_free(gpio);
+                       return ret;
+               }
+       }
+
+       mt9m001->switch_gpio = gpio;
+#else
+       mt9m001->switch_gpio = -EINVAL;
+#endif
+       return 0;
+}
+
+static void bus_switch_release(struct mt9m001 *mt9m001)
+{
+#ifdef CONFIG_MT9M001_PCA9536_SWITCH
+       if (gpio_is_valid(mt9m001->switch_gpio))
+               gpio_free(mt9m001->switch_gpio);
+#endif
+}
+
+static int bus_switch_act(struct mt9m001 *mt9m001, int go8bit)
+{
+#ifdef CONFIG_MT9M001_PCA9536_SWITCH
+       if (!gpio_is_valid(mt9m001->switch_gpio))
+               return -ENODEV;
+
+       gpio_set_value_cansleep(mt9m001->switch_gpio, go8bit);
+       return 0;
+#else
+       return -ENODEV;
+#endif
+}
+
+static int bus_switch_possible(struct mt9m001 *mt9m001)
+{
+#ifdef CONFIG_MT9M001_PCA9536_SWITCH
+       return gpio_is_valid(mt9m001->switch_gpio);
+#else
+       return 0;
+#endif
+}
+
+static int mt9m001_set_bus_param(struct soc_camera_device *icd,
+                                unsigned long flags)
+{
+       struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
+       unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK;
+       int ret;
+
+       /* Flags validity verified in test_bus_param */
+
+       if ((mt9m001->datawidth != 10 && (width_flag == SOCAM_DATAWIDTH_10)) ||
+           (mt9m001->datawidth != 9  && (width_flag == SOCAM_DATAWIDTH_9)) ||
+           (mt9m001->datawidth != 8  && (width_flag == SOCAM_DATAWIDTH_8))) {
+               /* Well, we actually only can do 10 or 8 bits... */
+               if (width_flag == SOCAM_DATAWIDTH_9)
+                       return -EINVAL;
+               ret = bus_switch_act(mt9m001,
+                                    width_flag == SOCAM_DATAWIDTH_8);
+               if (ret < 0)
+                       return ret;
+
+               mt9m001->datawidth = width_flag == SOCAM_DATAWIDTH_8 ? 8 : 10;
+       }
+
+       return 0;
+}
+
+static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd)
+{
+       struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
+       unsigned int width_flag = SOCAM_DATAWIDTH_10;
+
+       if (bus_switch_possible(mt9m001))
+               width_flag |= SOCAM_DATAWIDTH_8;
+
+       /* MT9M001 has all capture_format parameters fixed */
+       return SOCAM_PCLK_SAMPLE_RISING |
+               SOCAM_HSYNC_ACTIVE_HIGH |
+               SOCAM_VSYNC_ACTIVE_HIGH |
+               SOCAM_MASTER |
+               width_flag;
+}
+
+static int mt9m001_set_fmt_cap(struct soc_camera_device *icd,
+               __u32 pixfmt, struct v4l2_rect *rect)
+{
+       struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
+       int ret;
+       const u16 hblank = 9, vblank = 25;
+
+       /* Blanking and start values - default... */
+       ret = reg_write(icd, MT9M001_HORIZONTAL_BLANKING, hblank);
+       if (ret >= 0)
+               ret = reg_write(icd, MT9M001_VERTICAL_BLANKING, vblank);
+
+       /* The caller provides a supported format, as verified per
+        * call to icd->try_fmt_cap() */
+       if (ret >= 0)
+               ret = reg_write(icd, MT9M001_COLUMN_START, rect->left);
+       if (ret >= 0)
+               ret = reg_write(icd, MT9M001_ROW_START, rect->top);
+       if (ret >= 0)
+               ret = reg_write(icd, MT9M001_WINDOW_WIDTH, rect->width - 1);
+       if (ret >= 0)
+               ret = reg_write(icd, MT9M001_WINDOW_HEIGHT,
+                               rect->height + icd->y_skip_top - 1);
+       if (ret >= 0 && mt9m001->autoexposure) {
+               ret = reg_write(icd, MT9M001_SHUTTER_WIDTH,
+                               rect->height + icd->y_skip_top + vblank);
+               if (ret >= 0) {
+                       const struct v4l2_queryctrl *qctrl =
+                               soc_camera_find_qctrl(icd->ops,
+                                                     V4L2_CID_EXPOSURE);
+                       icd->exposure = (524 + (rect->height + icd->y_skip_top +
+                                               vblank - 1) *
+                                        (qctrl->maximum - qctrl->minimum)) /
+                               1048 + qctrl->minimum;
+               }
+       }
+
+       return ret < 0 ? ret : 0;
+}
+
+static int mt9m001_try_fmt_cap(struct soc_camera_device *icd,
+                              struct v4l2_format *f)
+{
+       if (f->fmt.pix.height < 32 + icd->y_skip_top)
+               f->fmt.pix.height = 32 + icd->y_skip_top;
+       if (f->fmt.pix.height > 1024 + icd->y_skip_top)
+               f->fmt.pix.height = 1024 + icd->y_skip_top;
+       if (f->fmt.pix.width < 48)
+               f->fmt.pix.width = 48;
+       if (f->fmt.pix.width > 1280)
+               f->fmt.pix.width = 1280;
+       f->fmt.pix.width &= ~0x01; /* has to be even, unsure why was ~3 */
+
+       return 0;
+}
+
+static int mt9m001_get_chip_id(struct soc_camera_device *icd,
+                              struct v4l2_chip_ident *id)
+{
+       struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
+
+       if (id->match_type != V4L2_CHIP_MATCH_I2C_ADDR)
+               return -EINVAL;
+
+       if (id->match_chip != mt9m001->client->addr)
+               return -ENODEV;
+
+       id->ident       = mt9m001->model;
+       id->revision    = 0;
+
+       return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int mt9m001_get_register(struct soc_camera_device *icd,
+                               struct v4l2_register *reg)
+{
+       struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
+
+       if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
+               return -EINVAL;
+
+       if (reg->match_chip != mt9m001->client->addr)
+               return -ENODEV;
+
+       reg->val = reg_read(icd, reg->reg);
+
+       if (reg->val > 0xffff)
+               return -EIO;
+
+       return 0;
+}
+
+static int mt9m001_set_register(struct soc_camera_device *icd,
+                               struct v4l2_register *reg)
+{
+       struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
+
+       if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
+               return -EINVAL;
+
+       if (reg->match_chip != mt9m001->client->addr)
+               return -ENODEV;
+
+       if (reg_write(icd, reg->reg, reg->val) < 0)
+               return -EIO;
+
+       return 0;
+}
+#endif
+
+const struct v4l2_queryctrl mt9m001_controls[] = {
+       {
+               .id             = V4L2_CID_VFLIP,
+               .type           = V4L2_CTRL_TYPE_BOOLEAN,
+               .name           = "Flip Vertically",
+               .minimum        = 0,
+               .maximum        = 1,
+               .step           = 1,
+               .default_value  = 0,
+       }, {
+               .id             = V4L2_CID_GAIN,
+               .type           = V4L2_CTRL_TYPE_INTEGER,
+               .name           = "Gain",
+               .minimum        = 0,
+               .maximum        = 127,
+               .step           = 1,
+               .default_value  = 64,
+               .flags          = V4L2_CTRL_FLAG_SLIDER,
+       }, {
+               .id             = V4L2_CID_EXPOSURE,
+               .type           = V4L2_CTRL_TYPE_INTEGER,
+               .name           = "Exposure",
+               .minimum        = 1,
+               .maximum        = 255,
+               .step           = 1,
+               .default_value  = 255,
+               .flags          = V4L2_CTRL_FLAG_SLIDER,
+       }, {
+               .id             = V4L2_CID_EXPOSURE_AUTO,
+               .type           = V4L2_CTRL_TYPE_BOOLEAN,
+               .name           = "Automatic Exposure",
+               .minimum        = 0,
+               .maximum        = 1,
+               .step           = 1,
+               .default_value  = 1,
+       }
+};
+
+static int mt9m001_video_probe(struct soc_camera_device *);
+static void mt9m001_video_remove(struct soc_camera_device *);
+static int mt9m001_get_control(struct soc_camera_device *, struct v4l2_control *);
+static int mt9m001_set_control(struct soc_camera_device *, struct v4l2_control *);
+
+static struct soc_camera_ops mt9m001_ops = {
+       .owner                  = THIS_MODULE,
+       .probe                  = mt9m001_video_probe,
+       .remove                 = mt9m001_video_remove,
+       .init                   = mt9m001_init,
+       .release                = mt9m001_release,
+       .start_capture          = mt9m001_start_capture,
+       .stop_capture           = mt9m001_stop_capture,
+       .set_fmt_cap            = mt9m001_set_fmt_cap,
+       .try_fmt_cap            = mt9m001_try_fmt_cap,
+       .set_bus_param          = mt9m001_set_bus_param,
+       .query_bus_param        = mt9m001_query_bus_param,
+       .controls               = mt9m001_controls,
+       .num_controls           = ARRAY_SIZE(mt9m001_controls),
+       .get_control            = mt9m001_get_control,
+       .set_control            = mt9m001_set_control,
+       .get_chip_id            = mt9m001_get_chip_id,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       .get_register           = mt9m001_get_register,
+       .set_register           = mt9m001_set_register,
+#endif
+};
+
+static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl)
+{
+       struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
+       int data;
+
+       switch (ctrl->id) {
+       case V4L2_CID_VFLIP:
+               data = reg_read(icd, MT9M001_READ_OPTIONS2);
+               if (data < 0)
+                       return -EIO;
+               ctrl->value = !!(data & 0x8000);
+               break;
+       case V4L2_CID_EXPOSURE_AUTO:
+               ctrl->value = mt9m001->autoexposure;
+               break;
+       }
+       return 0;
+}
+
+static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl)
+{
+       struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
+       const struct v4l2_queryctrl *qctrl;
+       int data;
+
+       qctrl = soc_camera_find_qctrl(&mt9m001_ops, ctrl->id);
+
+       if (!qctrl)
+               return -EINVAL;
+
+       switch (ctrl->id) {
+       case V4L2_CID_VFLIP:
+               if (ctrl->value)
+                       data = reg_set(icd, MT9M001_READ_OPTIONS2, 0x8000);
+               else
+                       data = reg_clear(icd, MT9M001_READ_OPTIONS2, 0x8000);
+               if (data < 0)
+                       return -EIO;
+               break;
+       case V4L2_CID_GAIN:
+               if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum)
+                       return -EINVAL;
+               /* See Datasheet Table 7, Gain settings. */
+               if (ctrl->value <= qctrl->default_value) {
+                       /* Pack it into 0..1 step 0.125, register values 0..8 */
+                       unsigned long range = qctrl->default_value - qctrl->minimum;
+                       data = ((ctrl->value - qctrl->minimum) * 8 + range / 2) / range;
+
+                       dev_dbg(&icd->dev, "Setting gain %d\n", data);
+                       data = reg_write(icd, MT9M001_GLOBAL_GAIN, data);
+                       if (data < 0)
+                               return -EIO;
+               } else {
+                       /* Pack it into 1.125..15 variable step, register values 9..67 */
+                       /* We assume qctrl->maximum - qctrl->default_value - 1 > 0 */
+                       unsigned long range = qctrl->maximum - qctrl->default_value - 1;
+                       unsigned long gain = ((ctrl->value - qctrl->default_value - 1) *
+                                              111 + range / 2) / range + 9;
+
+                       if (gain <= 32)
+                               data = gain;
+                       else if (gain <= 64)
+                               data = ((gain - 32) * 16 + 16) / 32 + 80;
+                       else
+                               data = ((gain - 64) * 7 + 28) / 56 + 96;
+
+                       dev_dbg(&icd->dev, "Setting gain from %d to %d\n",
+                                reg_read(icd, MT9M001_GLOBAL_GAIN), data);
+                       data = reg_write(icd, MT9M001_GLOBAL_GAIN, data);
+                       if (data < 0)
+                               return -EIO;
+               }
+
+               /* Success */
+               icd->gain = ctrl->value;
+               break;
+       case V4L2_CID_EXPOSURE:
+               /* mt9m001 has maximum == default */
+               if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum)
+                       return -EINVAL;
+               else {
+                       unsigned long range = qctrl->maximum - qctrl->minimum;
+                       unsigned long shutter = ((ctrl->value - qctrl->minimum) * 1048 +
+                                                range / 2) / range + 1;
+
+                       dev_dbg(&icd->dev, "Setting shutter width from %d to %lu\n",
+                                reg_read(icd, MT9M001_SHUTTER_WIDTH), shutter);
+                       if (reg_write(icd, MT9M001_SHUTTER_WIDTH, shutter) < 0)
+                               return -EIO;
+                       icd->exposure = ctrl->value;
+                       mt9m001->autoexposure = 0;
+               }
+               break;
+       case V4L2_CID_EXPOSURE_AUTO:
+               if (ctrl->value) {
+                       const u16 vblank = 25;
+                       if (reg_write(icd, MT9M001_SHUTTER_WIDTH, icd->height +
+                                     icd->y_skip_top + vblank) < 0)
+                               return -EIO;
+                       qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE);
+                       icd->exposure = (524 + (icd->height + icd->y_skip_top + vblank - 1) *
+                                        (qctrl->maximum - qctrl->minimum)) /
+                               1048 + qctrl->minimum;
+                       mt9m001->autoexposure = 1;
+               } else
+                       mt9m001->autoexposure = 0;
+               break;
+       }
+       return 0;
+}
+
+/* Interface active, can use i2c. If it fails, it can indeed mean, that
+ * this wasn't our capture interface, so, we wait for the right one */
+static int mt9m001_video_probe(struct soc_camera_device *icd)
+{
+       struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
+       s32 data;
+       int ret;
+
+       /* We must have a parent by now. And it cannot be a wrong one.
+        * So this entire test is completely redundant. */
+       if (!icd->dev.parent ||
+           to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
+               return -ENODEV;
+
+       /* Enable the chip */
+       data = reg_write(&mt9m001->icd, MT9M001_CHIP_ENABLE, 1);
+       dev_dbg(&icd->dev, "write: %d\n", data);
+
+       /* Read out the chip version register */
+       data = reg_read(icd, MT9M001_CHIP_VERSION);
+
+       /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */
+       switch (data) {
+       case 0x8411:
+       case 0x8421:
+               mt9m001->model = V4L2_IDENT_MT9M001C12ST;
+               icd->formats = mt9m001_colour_formats;
+               if (mt9m001->client->dev.platform_data)
+                       icd->num_formats = ARRAY_SIZE(mt9m001_colour_formats);
+               else
+                       icd->num_formats = 1;
+               break;
+       case 0x8431:
+               mt9m001->model = V4L2_IDENT_MT9M001C12STM;
+               icd->formats = mt9m001_monochrome_formats;
+               if (mt9m001->client->dev.platform_data)
+                       icd->num_formats = ARRAY_SIZE(mt9m001_monochrome_formats);
+               else
+                       icd->num_formats = 1;
+               break;
+       default:
+               ret = -ENODEV;
+               dev_err(&icd->dev,
+                       "No MT9M001 chip detected, register read %x\n", data);
+               goto ei2c;
+       }
+
+       dev_info(&icd->dev, "Detected a MT9M001 chip ID %x (%s)\n", data,
+                data == 0x8431 ? "C12STM" : "C12ST");
+
+       /* Now that we know the model, we can start video */
+       ret = soc_camera_video_start(icd);
+       if (ret)
+               goto eisis;
+
+       return 0;
+
+eisis:
+ei2c:
+       return ret;
+}
+
+static void mt9m001_video_remove(struct soc_camera_device *icd)
+{
+       struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
+
+       dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9m001->client->addr,
+               mt9m001->icd.dev.parent, mt9m001->icd.vdev);
+       soc_camera_video_stop(&mt9m001->icd);
+}
+
+static int mt9m001_probe(struct i2c_client *client)
+{
+       struct mt9m001 *mt9m001;
+       struct soc_camera_device *icd;
+       struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+       struct soc_camera_link *icl = client->dev.platform_data;
+       int ret;
+
+       if (!icl) {
+               dev_err(&client->dev, "MT9M001 driver needs platform data\n");
+               return -EINVAL;
+       }
+
+       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) {
+               dev_warn(&adapter->dev,
+                        "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
+               return -EIO;
+       }
+
+       mt9m001 = kzalloc(sizeof(struct mt9m001), GFP_KERNEL);
+       if (!mt9m001)
+               return -ENOMEM;
+
+       mt9m001->client = client;
+       i2c_set_clientdata(client, mt9m001);
+
+       /* Second stage probe - when a capture adapter is there */
+       icd = &mt9m001->icd;
+       icd->ops        = &mt9m001_ops;
+       icd->control    = &client->dev;
+       icd->x_min      = 20;
+       icd->y_min      = 12;
+       icd->x_current  = 20;
+       icd->y_current  = 12;
+       icd->width_min  = 48;
+       icd->width_max  = 1280;
+       icd->height_min = 32;
+       icd->height_max = 1024;
+       icd->y_skip_top = 1;
+       icd->iface      = icl->bus_id;
+       /* Default datawidth - this is the only width this camera (normally)
+        * supports. It is only with extra logic that it can support
+        * other widths. Therefore it seems to be a sensible default. */
+       mt9m001->datawidth = 10;
+       /* Simulated autoexposure. If enabled, we calculate shutter width
+        * ourselves in the driver based on vertical blanking and frame width */
+       mt9m001->autoexposure = 1;
+
+       ret = bus_switch_request(mt9m001, icl);
+       if (ret)
+               goto eswinit;
+
+       ret = soc_camera_device_register(icd);
+       if (ret)
+               goto eisdr;
+
+       return 0;
+
+eisdr:
+       bus_switch_release(mt9m001);
+eswinit:
+       kfree(mt9m001);
+       return ret;
+}
+
+static int mt9m001_remove(struct i2c_client *client)
+{
+       struct mt9m001 *mt9m001 = i2c_get_clientdata(client);
+
+       soc_camera_device_unregister(&mt9m001->icd);
+       bus_switch_release(mt9m001);
+       kfree(mt9m001);
+
+       return 0;
+}
+
+static struct i2c_driver mt9m001_i2c_driver = {
+       .driver = {
+               .name = "mt9m001",
+       },
+       .probe          = mt9m001_probe,
+       .remove         = mt9m001_remove,
+};
+
+static int __init mt9m001_mod_init(void)
+{
+       return i2c_add_driver(&mt9m001_i2c_driver);
+}
+
+static void __exit mt9m001_mod_exit(void)
+{
+       i2c_del_driver(&mt9m001_i2c_driver);
+}
+
+module_init(mt9m001_mod_init);
+module_exit(mt9m001_mod_exit);
+
+MODULE_DESCRIPTION("Micron MT9M001 Camera driver");
+MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c
new file mode 100644 (file)
index 0000000..d4b9e27
--- /dev/null
@@ -0,0 +1,844 @@
+/*
+ * Driver for MT9V022 CMOS Image Sensor from Micron
+ *
+ * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
+ *
+ * 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/videodev2.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/log2.h>
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/soc_camera.h>
+
+#ifdef CONFIG_MT9M001_PCA9536_SWITCH
+#include <asm/gpio.h>
+#endif
+
+/* mt9v022 i2c address 0x48, 0x4c, 0x58, 0x5c
+ * The platform has to define i2c_board_info
+ * and call i2c_register_board_info() */
+
+static char *sensor_type;
+module_param(sensor_type, charp, S_IRUGO);
+MODULE_PARM_DESC(sensor_type, "Sensor type: \"colour\" or \"monochrome\"\n");
+
+/* mt9v022 selected register addresses */
+#define MT9V022_CHIP_VERSION           0x00
+#define MT9V022_COLUMN_START           0x01
+#define MT9V022_ROW_START              0x02
+#define MT9V022_WINDOW_HEIGHT          0x03
+#define MT9V022_WINDOW_WIDTH           0x04
+#define MT9V022_HORIZONTAL_BLANKING    0x05
+#define MT9V022_VERTICAL_BLANKING      0x06
+#define MT9V022_CHIP_CONTROL           0x07
+#define MT9V022_SHUTTER_WIDTH1         0x08
+#define MT9V022_SHUTTER_WIDTH2         0x09
+#define MT9V022_SHUTTER_WIDTH_CTRL     0x0a
+#define MT9V022_TOTAL_SHUTTER_WIDTH    0x0b
+#define MT9V022_RESET                  0x0c
+#define MT9V022_READ_MODE              0x0d
+#define MT9V022_MONITOR_MODE           0x0e
+#define MT9V022_PIXEL_OPERATION_MODE   0x0f
+#define MT9V022_LED_OUT_CONTROL                0x1b
+#define MT9V022_ADC_MODE_CONTROL       0x1c
+#define MT9V022_ANALOG_GAIN            0x34
+#define MT9V022_BLACK_LEVEL_CALIB_CTRL 0x47
+#define MT9V022_PIXCLK_FV_LV           0x74
+#define MT9V022_DIGITAL_TEST_PATTERN   0x7f
+#define MT9V022_AEC_AGC_ENABLE         0xAF
+#define MT9V022_MAX_TOTAL_SHUTTER_WIDTH        0xBD
+
+/* Progressive scan, master, defaults */
+#define MT9V022_CHIP_CONTROL_DEFAULT   0x188
+
+static const struct soc_camera_data_format mt9v022_colour_formats[] = {
+       /* Order important: first natively supported,
+        * second supported with a GPIO extender */
+       {
+               .name           = "Bayer (sRGB) 10 bit",
+               .depth          = 10,
+               .fourcc         = V4L2_PIX_FMT_SBGGR16,
+               .colorspace     = V4L2_COLORSPACE_SRGB,
+       }, {
+               .name           = "Bayer (sRGB) 8 bit",
+               .depth          = 8,
+               .fourcc         = V4L2_PIX_FMT_SBGGR8,
+               .colorspace     = V4L2_COLORSPACE_SRGB,
+       }
+};
+
+static const struct soc_camera_data_format mt9v022_monochrome_formats[] = {
+       /* Order important - see above */
+       {
+               .name           = "Monochrome 10 bit",
+               .depth          = 10,
+               .fourcc         = V4L2_PIX_FMT_Y16,
+       }, {
+               .name           = "Monochrome 8 bit",
+               .depth          = 8,
+               .fourcc         = V4L2_PIX_FMT_GREY,
+       },
+};
+
+struct mt9v022 {
+       struct i2c_client *client;
+       struct soc_camera_device icd;
+       int model;      /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */
+       int switch_gpio;
+       u16 chip_control;
+       unsigned char datawidth;
+};
+
+static int reg_read(struct soc_camera_device *icd, const u8 reg)
+{
+       struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
+       struct i2c_client *client = mt9v022->client;
+       s32 data = i2c_smbus_read_word_data(client, reg);
+       return data < 0 ? data : swab16(data);
+}
+
+static int reg_write(struct soc_camera_device *icd, const u8 reg,
+                    const u16 data)
+{
+       struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
+       return i2c_smbus_write_word_data(mt9v022->client, reg, swab16(data));
+}
+
+static int reg_set(struct soc_camera_device *icd, const u8 reg,
+                  const u16 data)
+{
+       int ret;
+
+       ret = reg_read(icd, reg);
+       if (ret < 0)
+               return ret;
+       return reg_write(icd, reg, ret | data);
+}
+
+static int reg_clear(struct soc_camera_device *icd, const u8 reg,
+                    const u16 data)
+{
+       int ret;
+
+       ret = reg_read(icd, reg);
+       if (ret < 0)
+               return ret;
+       return reg_write(icd, reg, ret & ~data);
+}
+
+static int mt9v022_init(struct soc_camera_device *icd)
+{
+       struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
+       int ret;
+
+       /* Almost the default mode: master, parallel, simultaneous, and an
+        * undocumented bit 0x200, which is present in table 7, but not in 8,
+        * plus snapshot mode to disable scan for now */
+       mt9v022->chip_control |= 0x10;
+       ret = reg_write(icd, MT9V022_CHIP_CONTROL, mt9v022->chip_control);
+       if (ret >= 0)
+               reg_write(icd, MT9V022_READ_MODE, 0x300);
+
+       /* All defaults */
+       if (ret >= 0)
+               /* AEC, AGC on */
+               ret = reg_set(icd, MT9V022_AEC_AGC_ENABLE, 0x3);
+       if (ret >= 0)
+               ret = reg_write(icd, MT9V022_MAX_TOTAL_SHUTTER_WIDTH, 480);
+       if (ret >= 0)
+               /* default - auto */
+               ret = reg_clear(icd, MT9V022_BLACK_LEVEL_CALIB_CTRL, 1);
+       if (ret >= 0)
+               ret = reg_write(icd, MT9V022_DIGITAL_TEST_PATTERN, 0);
+
+       return ret >= 0 ? 0 : -EIO;
+}
+
+static int mt9v022_release(struct soc_camera_device *icd)
+{
+       /* Nothing? */
+       return 0;
+}
+
+static int mt9v022_start_capture(struct soc_camera_device *icd)
+{
+       struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
+       /* Switch to master "normal" mode */
+       mt9v022->chip_control &= ~0x10;
+       if (reg_write(icd, MT9V022_CHIP_CONTROL,
+                     mt9v022->chip_control) < 0)
+               return -EIO;
+       return 0;
+}
+
+static int mt9v022_stop_capture(struct soc_camera_device *icd)
+{
+       struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
+       /* Switch to snapshot mode */
+       mt9v022->chip_control |= 0x10;
+       if (reg_write(icd, MT9V022_CHIP_CONTROL,
+                     mt9v022->chip_control) < 0)
+               return -EIO;
+       return 0;
+}
+
+static int bus_switch_request(struct mt9v022 *mt9v022, struct soc_camera_link *icl)
+{
+#ifdef CONFIG_MT9V022_PCA9536_SWITCH
+       int ret;
+       unsigned int gpio = icl->gpio;
+
+       if (gpio_is_valid(gpio)) {
+               /* We have a data bus switch. */
+               ret = gpio_request(gpio, "mt9v022");
+               if (ret < 0) {
+                       dev_err(&mt9v022->client->dev, "Cannot get GPIO %u\n", gpio);
+                       return ret;
+               }
+
+               ret = gpio_direction_output(gpio, 0);
+               if (ret < 0) {
+                       dev_err(&mt9v022->client->dev,
+                               "Cannot set GPIO %u to output\n", gpio);
+                       gpio_free(gpio);
+                       return ret;
+               }
+       }
+
+       mt9v022->switch_gpio = gpio;
+#else
+       mt9v022->switch_gpio = -EINVAL;
+#endif
+       return 0;
+}
+
+static void bus_switch_release(struct mt9v022 *mt9v022)
+{
+#ifdef CONFIG_MT9V022_PCA9536_SWITCH
+       if (gpio_is_valid(mt9v022->switch_gpio))
+               gpio_free(mt9v022->switch_gpio);
+#endif
+}
+
+static int bus_switch_act(struct mt9v022 *mt9v022, int go8bit)
+{
+#ifdef CONFIG_MT9V022_PCA9536_SWITCH
+       if (!gpio_is_valid(mt9v022->switch_gpio))
+               return -ENODEV;
+
+       gpio_set_value_cansleep(mt9v022->switch_gpio, go8bit);
+       return 0;
+#else
+       return -ENODEV;
+#endif
+}
+
+static int bus_switch_possible(struct mt9v022 *mt9v022)
+{
+#ifdef CONFIG_MT9V022_PCA9536_SWITCH
+       return gpio_is_valid(mt9v022->switch_gpio);
+#else
+       return 0;
+#endif
+}
+
+static int mt9v022_set_bus_param(struct soc_camera_device *icd,
+                                unsigned long flags)
+{
+       struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
+       unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK;
+       int ret;
+       u16 pixclk = 0;
+
+       /* Only one width bit may be set */
+       if (!is_power_of_2(width_flag))
+               return -EINVAL;
+
+       if ((mt9v022->datawidth != 10 && (width_flag == SOCAM_DATAWIDTH_10)) ||
+           (mt9v022->datawidth != 9  && (width_flag == SOCAM_DATAWIDTH_9)) ||
+           (mt9v022->datawidth != 8  && (width_flag == SOCAM_DATAWIDTH_8))) {
+               /* Well, we actually only can do 10 or 8 bits... */
+               if (width_flag == SOCAM_DATAWIDTH_9)
+                       return -EINVAL;
+
+               ret = bus_switch_act(mt9v022,
+                                    width_flag == SOCAM_DATAWIDTH_8);
+               if (ret < 0)
+                       return ret;
+
+               mt9v022->datawidth = width_flag == SOCAM_DATAWIDTH_8 ? 8 : 10;
+       }
+
+       if (flags & SOCAM_PCLK_SAMPLE_RISING)
+               pixclk |= 0x10;
+
+       if (!(flags & SOCAM_HSYNC_ACTIVE_HIGH))
+               pixclk |= 0x1;
+
+       if (!(flags & SOCAM_VSYNC_ACTIVE_HIGH))
+               pixclk |= 0x2;
+
+       ret = reg_write(icd, MT9V022_PIXCLK_FV_LV, pixclk);
+       if (ret < 0)
+               return ret;
+
+       if (!(flags & SOCAM_MASTER))
+               mt9v022->chip_control &= ~0x8;
+
+       ret = reg_write(icd, MT9V022_CHIP_CONTROL, mt9v022->chip_control);
+       if (ret < 0)
+               return ret;
+
+       dev_dbg(&icd->dev, "Calculated pixclk 0x%x, chip control 0x%x\n",
+               pixclk, mt9v022->chip_control);
+
+       return 0;
+}
+
+static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd)
+{
+       struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
+       unsigned int width_flag = SOCAM_DATAWIDTH_10;
+
+       if (bus_switch_possible(mt9v022))
+               width_flag |= SOCAM_DATAWIDTH_8;
+
+       return SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING |
+               SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW |
+               SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW |
+               SOCAM_MASTER | SOCAM_SLAVE |
+               width_flag;
+}
+
+static int mt9v022_set_fmt_cap(struct soc_camera_device *icd,
+               __u32 pixfmt, struct v4l2_rect *rect)
+{
+       struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
+       int ret;
+
+       /* The caller provides a supported format, as verified per call to
+        * icd->try_fmt_cap(), datawidth is from our supported format list */
+       switch (pixfmt) {
+       case V4L2_PIX_FMT_GREY:
+       case V4L2_PIX_FMT_Y16:
+               if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATM)
+                       return -EINVAL;
+               break;
+       case V4L2_PIX_FMT_SBGGR8:
+       case V4L2_PIX_FMT_SBGGR16:
+               if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATC)
+                       return -EINVAL;
+               break;
+       case 0:
+               /* No format change, only geometry */
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* Like in example app. Contradicts the datasheet though */
+       ret = reg_read(icd, MT9V022_AEC_AGC_ENABLE);
+       if (ret >= 0) {
+               if (ret & 1) /* Autoexposure */
+                       ret = reg_write(icd, MT9V022_MAX_TOTAL_SHUTTER_WIDTH,
+                                       rect->height + icd->y_skip_top + 43);
+               else
+                       ret = reg_write(icd, MT9V022_TOTAL_SHUTTER_WIDTH,
+                                       rect->height + icd->y_skip_top + 43);
+       }
+       /* Setup frame format: defaults apart from width and height */
+       if (ret >= 0)
+               ret = reg_write(icd, MT9V022_COLUMN_START, rect->left);
+       if (ret >= 0)
+               ret = reg_write(icd, MT9V022_ROW_START, rect->top);
+       if (ret >= 0)
+               /* Default 94, Phytec driver says:
+                * "width + horizontal blank >= 660" */
+               ret = reg_write(icd, MT9V022_HORIZONTAL_BLANKING,
+                               rect->width > 660 - 43 ? 43 :
+                               660 - rect->width);
+       if (ret >= 0)
+               ret = reg_write(icd, MT9V022_VERTICAL_BLANKING, 45);
+       if (ret >= 0)
+               ret = reg_write(icd, MT9V022_WINDOW_WIDTH, rect->width);
+       if (ret >= 0)
+               ret = reg_write(icd, MT9V022_WINDOW_HEIGHT,
+                               rect->height + icd->y_skip_top);
+
+       if (ret < 0)
+               return ret;
+
+       dev_dbg(&icd->dev, "Frame %ux%u pixel\n", rect->width, rect->height);
+
+       return 0;
+}
+
+static int mt9v022_try_fmt_cap(struct soc_camera_device *icd,
+                              struct v4l2_format *f)
+{
+       if (f->fmt.pix.height < 32 + icd->y_skip_top)
+               f->fmt.pix.height = 32 + icd->y_skip_top;
+       if (f->fmt.pix.height > 480 + icd->y_skip_top)
+               f->fmt.pix.height = 480 + icd->y_skip_top;
+       if (f->fmt.pix.width < 48)
+               f->fmt.pix.width = 48;
+       if (f->fmt.pix.width > 752)
+               f->fmt.pix.width = 752;
+       f->fmt.pix.width &= ~0x03; /* ? */
+
+       return 0;
+}
+
+static int mt9v022_get_chip_id(struct soc_camera_device *icd,
+                              struct v4l2_chip_ident *id)
+{
+       struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
+
+       if (id->match_type != V4L2_CHIP_MATCH_I2C_ADDR)
+               return -EINVAL;
+
+       if (id->match_chip != mt9v022->client->addr)
+               return -ENODEV;
+
+       id->ident       = mt9v022->model;
+       id->revision    = 0;
+
+       return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int mt9v022_get_register(struct soc_camera_device *icd,
+                               struct v4l2_register *reg)
+{
+       struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
+
+       if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
+               return -EINVAL;
+
+       if (reg->match_chip != mt9v022->client->addr)
+               return -ENODEV;
+
+       reg->val = reg_read(icd, reg->reg);
+
+       if (reg->val > 0xffff)
+               return -EIO;
+
+       return 0;
+}
+
+static int mt9v022_set_register(struct soc_camera_device *icd,
+                               struct v4l2_register *reg)
+{
+       struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
+
+       if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
+               return -EINVAL;
+
+       if (reg->match_chip != mt9v022->client->addr)
+               return -ENODEV;
+
+       if (reg_write(icd, reg->reg, reg->val) < 0)
+               return -EIO;
+
+       return 0;
+}
+#endif
+
+const struct v4l2_queryctrl mt9v022_controls[] = {
+       {
+               .id             = V4L2_CID_VFLIP,
+               .type           = V4L2_CTRL_TYPE_BOOLEAN,
+               .name           = "Flip Vertically",
+               .minimum        = 0,
+               .maximum        = 1,
+               .step           = 1,
+               .default_value  = 0,
+       }, {
+               .id             = V4L2_CID_HFLIP,
+               .type           = V4L2_CTRL_TYPE_BOOLEAN,
+               .name           = "Flip Horizontally",
+               .minimum        = 0,
+               .maximum        = 1,
+               .step           = 1,
+               .default_value  = 0,
+       }, {
+               .id             = V4L2_CID_GAIN,
+               .type           = V4L2_CTRL_TYPE_INTEGER,
+               .name           = "Analog Gain",
+               .minimum        = 64,
+               .maximum        = 127,
+               .step           = 1,
+               .default_value  = 64,
+               .flags          = V4L2_CTRL_FLAG_SLIDER,
+       }, {
+               .id             = V4L2_CID_EXPOSURE,
+               .type           = V4L2_CTRL_TYPE_INTEGER,
+               .name           = "Exposure",
+               .minimum        = 1,
+               .maximum        = 255,
+               .step           = 1,
+               .default_value  = 255,
+               .flags          = V4L2_CTRL_FLAG_SLIDER,
+       }, {
+               .id             = V4L2_CID_AUTOGAIN,
+               .type           = V4L2_CTRL_TYPE_BOOLEAN,
+               .name           = "Automatic Gain",
+               .minimum        = 0,
+               .maximum        = 1,
+               .step           = 1,
+               .default_value  = 1,
+       }, {
+               .id             = V4L2_CID_EXPOSURE_AUTO,
+               .type           = V4L2_CTRL_TYPE_BOOLEAN,
+               .name           = "Automatic Exposure",
+               .minimum        = 0,
+               .maximum        = 1,
+               .step           = 1,
+               .default_value  = 1,
+       }
+};
+
+static int mt9v022_video_probe(struct soc_camera_device *);
+static void mt9v022_video_remove(struct soc_camera_device *);
+static int mt9v022_get_control(struct soc_camera_device *, struct v4l2_control *);
+static int mt9v022_set_control(struct soc_camera_device *, struct v4l2_control *);
+
+static struct soc_camera_ops mt9v022_ops = {
+       .owner                  = THIS_MODULE,
+       .probe                  = mt9v022_video_probe,
+       .remove                 = mt9v022_video_remove,
+       .init                   = mt9v022_init,
+       .release                = mt9v022_release,
+       .start_capture          = mt9v022_start_capture,
+       .stop_capture           = mt9v022_stop_capture,
+       .set_fmt_cap            = mt9v022_set_fmt_cap,
+       .try_fmt_cap            = mt9v022_try_fmt_cap,
+       .set_bus_param          = mt9v022_set_bus_param,
+       .query_bus_param        = mt9v022_query_bus_param,
+       .controls               = mt9v022_controls,
+       .num_controls           = ARRAY_SIZE(mt9v022_controls),
+       .get_control            = mt9v022_get_control,
+       .set_control            = mt9v022_set_control,
+       .get_chip_id            = mt9v022_get_chip_id,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       .get_register           = mt9v022_get_register,
+       .set_register           = mt9v022_set_register,
+#endif
+};
+
+static int mt9v022_get_control(struct soc_camera_device *icd,
+                              struct v4l2_control *ctrl)
+{
+       int data;
+
+       switch (ctrl->id) {
+       case V4L2_CID_VFLIP:
+               data = reg_read(icd, MT9V022_READ_MODE);
+               if (data < 0)
+                       return -EIO;
+               ctrl->value = !!(data & 0x10);
+               break;
+       case V4L2_CID_HFLIP:
+               data = reg_read(icd, MT9V022_READ_MODE);
+               if (data < 0)
+                       return -EIO;
+               ctrl->value = !!(data & 0x20);
+               break;
+       case V4L2_CID_EXPOSURE_AUTO:
+               data = reg_read(icd, MT9V022_AEC_AGC_ENABLE);
+               if (data < 0)
+                       return -EIO;
+               ctrl->value = !!(data & 0x1);
+               break;
+       case V4L2_CID_AUTOGAIN:
+               data = reg_read(icd, MT9V022_AEC_AGC_ENABLE);
+               if (data < 0)
+                       return -EIO;
+               ctrl->value = !!(data & 0x2);
+               break;
+       }
+       return 0;
+}
+
+static int mt9v022_set_control(struct soc_camera_device *icd,
+                              struct v4l2_control *ctrl)
+{
+       int data;
+       const struct v4l2_queryctrl *qctrl;
+
+       qctrl = soc_camera_find_qctrl(&mt9v022_ops, ctrl->id);
+
+       if (!qctrl)
+               return -EINVAL;
+
+       switch (ctrl->id) {
+       case V4L2_CID_VFLIP:
+               if (ctrl->value)
+                       data = reg_set(icd, MT9V022_READ_MODE, 0x10);
+               else
+                       data = reg_clear(icd, MT9V022_READ_MODE, 0x10);
+               if (data < 0)
+                       return -EIO;
+               break;
+       case V4L2_CID_HFLIP:
+               if (ctrl->value)
+                       data = reg_set(icd, MT9V022_READ_MODE, 0x20);
+               else
+                       data = reg_clear(icd, MT9V022_READ_MODE, 0x20);
+               if (data < 0)
+                       return -EIO;
+               break;
+       case V4L2_CID_GAIN:
+               /* mt9v022 has minimum == default */
+               if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum)
+                       return -EINVAL;
+               else {
+                       unsigned long range = qctrl->maximum - qctrl->minimum;
+                       /* Datasheet says 16 to 64. autogain only works properly
+                        * after setting gain to maximum 14. Larger values
+                        * produce "white fly" noise effect. On the whole,
+                        * manually setting analog gain does no good. */
+                       unsigned long gain = ((ctrl->value - qctrl->minimum) *
+                                             10 + range / 2) / range + 4;
+                       if (gain >= 32)
+                               gain &= ~1;
+                       /* The user wants to set gain manually, hope, she
+                        * knows, what she's doing... Switch AGC off. */
+
+                       if (reg_clear(icd, MT9V022_AEC_AGC_ENABLE, 0x2) < 0)
+                               return -EIO;
+
+                       dev_info(&icd->dev, "Setting gain from %d to %lu\n",
+                                reg_read(icd, MT9V022_ANALOG_GAIN), gain);
+                       if (reg_write(icd, MT9V022_ANALOG_GAIN, gain) < 0)
+                               return -EIO;
+                       icd->gain = ctrl->value;
+               }
+               break;
+       case V4L2_CID_EXPOSURE:
+               /* mt9v022 has maximum == default */
+               if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum)
+                       return -EINVAL;
+               else {
+                       unsigned long range = qctrl->maximum - qctrl->minimum;
+                       unsigned long shutter = ((ctrl->value - qctrl->minimum) *
+                                                479 + range / 2) / range + 1;
+                       /* The user wants to set shutter width manually, hope,
+                        * she knows, what she's doing... Switch AEC off. */
+
+                       if (reg_clear(icd, MT9V022_AEC_AGC_ENABLE, 0x1) < 0)
+                               return -EIO;
+
+                       dev_dbg(&icd->dev, "Shutter width from %d to %lu\n",
+                               reg_read(icd, MT9V022_TOTAL_SHUTTER_WIDTH),
+                               shutter);
+                       if (reg_write(icd, MT9V022_TOTAL_SHUTTER_WIDTH,
+                                     shutter) < 0)
+                               return -EIO;
+                       icd->exposure = ctrl->value;
+               }
+               break;
+       case V4L2_CID_AUTOGAIN:
+               if (ctrl->value)
+                       data = reg_set(icd, MT9V022_AEC_AGC_ENABLE, 0x2);
+               else
+                       data = reg_clear(icd, MT9V022_AEC_AGC_ENABLE, 0x2);
+               if (data < 0)
+                       return -EIO;
+               break;
+       case V4L2_CID_EXPOSURE_AUTO:
+               if (ctrl->value)
+                       data = reg_set(icd, MT9V022_AEC_AGC_ENABLE, 0x1);
+               else
+                       data = reg_clear(icd, MT9V022_AEC_AGC_ENABLE, 0x1);
+               if (data < 0)
+                       return -EIO;
+               break;
+       }
+       return 0;
+}
+
+/* Interface active, can use i2c. If it fails, it can indeed mean, that
+ * this wasn't our capture interface, so, we wait for the right one */
+static int mt9v022_video_probe(struct soc_camera_device *icd)
+{
+       struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
+       s32 data;
+       int ret;
+
+       if (!icd->dev.parent ||
+           to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
+               return -ENODEV;
+
+       /* Read out the chip version register */
+       data = reg_read(icd, MT9V022_CHIP_VERSION);
+
+       /* must be 0x1311 or 0x1313 */
+       if (data != 0x1311 && data != 0x1313) {
+               ret = -ENODEV;
+               dev_info(&icd->dev, "No MT9V022 detected, ID register 0x%x\n",
+                        data);
+               goto ei2c;
+       }
+
+       /* Soft reset */
+       ret = reg_write(icd, MT9V022_RESET, 1);
+       if (ret < 0)
+               goto ei2c;
+       /* 15 clock cycles */
+       udelay(200);
+       if (reg_read(icd, MT9V022_RESET)) {
+               dev_err(&icd->dev, "Resetting MT9V022 failed!\n");
+               goto ei2c;
+       }
+
+       /* Set monochrome or colour sensor type */
+       if (sensor_type && (!strcmp("colour", sensor_type) ||
+                           !strcmp("color", sensor_type))) {
+               ret = reg_write(icd, MT9V022_PIXEL_OPERATION_MODE, 4 | 0x11);
+               mt9v022->model = V4L2_IDENT_MT9V022IX7ATC;
+               icd->formats = mt9v022_colour_formats;
+               if (mt9v022->client->dev.platform_data)
+                       icd->num_formats = ARRAY_SIZE(mt9v022_colour_formats);
+               else
+                       icd->num_formats = 1;
+       } else {
+               ret = reg_write(icd, MT9V022_PIXEL_OPERATION_MODE, 0x11);
+               mt9v022->model = V4L2_IDENT_MT9V022IX7ATM;
+               icd->formats = mt9v022_monochrome_formats;
+               if (mt9v022->client->dev.platform_data)
+                       icd->num_formats = ARRAY_SIZE(mt9v022_monochrome_formats);
+               else
+                       icd->num_formats = 1;
+       }
+
+       if (ret >= 0)
+               ret = soc_camera_video_start(icd);
+       if (ret < 0)
+               goto eisis;
+
+       dev_info(&icd->dev, "Detected a MT9V022 chip ID %x, %s sensor\n",
+                data, mt9v022->model == V4L2_IDENT_MT9V022IX7ATM ?
+                "monochrome" : "colour");
+
+       return 0;
+
+eisis:
+ei2c:
+       return ret;
+}
+
+static void mt9v022_video_remove(struct soc_camera_device *icd)
+{
+       struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
+
+       dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9v022->client->addr,
+               mt9v022->icd.dev.parent, mt9v022->icd.vdev);
+       soc_camera_video_stop(&mt9v022->icd);
+}
+
+static int mt9v022_probe(struct i2c_client *client)
+{
+       struct mt9v022 *mt9v022;
+       struct soc_camera_device *icd;
+       struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+       struct soc_camera_link *icl = client->dev.platform_data;
+       int ret;
+
+       if (!icl) {
+               dev_err(&client->dev, "MT9V022 driver needs platform data\n");
+               return -EINVAL;
+       }
+
+       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) {
+               dev_warn(&adapter->dev,
+                        "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
+               return -EIO;
+       }
+
+       mt9v022 = kzalloc(sizeof(struct mt9v022), GFP_KERNEL);
+       if (!mt9v022)
+               return -ENOMEM;
+
+       mt9v022->chip_control = MT9V022_CHIP_CONTROL_DEFAULT;
+       mt9v022->client = client;
+       i2c_set_clientdata(client, mt9v022);
+
+       icd = &mt9v022->icd;
+       icd->ops        = &mt9v022_ops;
+       icd->control    = &client->dev;
+       icd->x_min      = 1;
+       icd->y_min      = 4;
+       icd->x_current  = 1;
+       icd->y_current  = 4;
+       icd->width_min  = 48;
+       icd->width_max  = 752;
+       icd->height_min = 32;
+       icd->height_max = 480;
+       icd->y_skip_top = 1;
+       icd->iface      = icl->bus_id;
+       /* Default datawidth - this is the only width this camera (normally)
+        * supports. It is only with extra logic that it can support
+        * other widths. Therefore it seems to be a sensible default. */
+       mt9v022->datawidth = 10;
+
+       ret = bus_switch_request(mt9v022, icl);
+       if (ret)
+               goto eswinit;
+
+       ret = soc_camera_device_register(icd);
+       if (ret)
+               goto eisdr;
+
+       return 0;
+
+eisdr:
+       bus_switch_release(mt9v022);
+eswinit:
+       kfree(mt9v022);
+       return ret;
+}
+
+static int mt9v022_remove(struct i2c_client *client)
+{
+       struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
+
+       soc_camera_device_unregister(&mt9v022->icd);
+       bus_switch_release(mt9v022);
+       kfree(mt9v022);
+
+       return 0;
+}
+
+static struct i2c_driver mt9v022_i2c_driver = {
+       .driver = {
+               .name = "mt9v022",
+       },
+       .probe          = mt9v022_probe,
+       .remove         = mt9v022_remove,
+};
+
+static int __init mt9v022_mod_init(void)
+{
+       return i2c_add_driver(&mt9v022_i2c_driver);
+}
+
+static void __exit mt9v022_mod_exit(void)
+{
+       i2c_del_driver(&mt9v022_i2c_driver);
+}
+
+module_init(mt9v022_mod_init);
+module_exit(mt9v022_mod_exit);
+
+MODULE_DESCRIPTION("Micron MT9V022 Camera driver");
+MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>");
+MODULE_LICENSE("GPL");
index cb5a510f9251b49f5e1a9ccfecf0d386b7e80c0b..f68e91fbe7fbcbe7d6e28705a00100eb4c57c06f 100644 (file)
@@ -38,7 +38,7 @@
 #define MXB_BOARD_CAN_DO_VBI(dev)   (dev->revision != 0)
 
 /* global variable */
-static int mxb_num = 0;
+static int mxb_num;
 
 /* initial frequence the tuner will be tuned to.
    in verden (lower saxony, germany) 4148 is a
@@ -47,7 +47,7 @@ static int freq = 4148;
 module_param(freq, int, 0644);
 MODULE_PARM_DESC(freq, "initial frequency the tuner will be tuned to while setup");
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
 
index 6590058e8ff00ee8ce4acf1028538e2e3e79572b..eafb0c7736e630bff974b002db478702aeee5100 100644 (file)
@@ -4659,7 +4659,9 @@ static const struct file_operations ov511_fops = {
        .read =         ov51x_v4l1_read,
        .mmap =         ov51x_v4l1_mmap,
        .ioctl =        ov51x_v4l1_ioctl,
+#ifdef CONFIG_COMPAT
        .compat_ioctl = v4l_compat_ioctl32,
+#endif
        .llseek =       no_llseek,
 };
 
@@ -5831,7 +5833,7 @@ ov51x_probe(struct usb_interface *intf, const struct usb_device_id *id)
                goto error;
 
        memcpy(ov->vdev, &vdev_template, sizeof(*ov->vdev));
-       ov->vdev->dev = &dev->dev;
+       ov->vdev->dev = &intf->dev;
        video_set_drvdata(ov->vdev, ov);
 
        for (i = 0; i < OV511_MAX_UNIT_VIDEO; i++) {
index 18c64222dd11f7f4a38bab979165085e2863bf2f..1010e51189b77bd3f6d2970bd69111659e84e51a 100644 (file)
@@ -12,7 +12,7 @@
 #ifdef OV511_DEBUG
        #define PDEBUG(level, fmt, args...) \
                if (debug >= (level)) info("[%s:%d] " fmt, \
-               __FUNCTION__, __LINE__ , ## args)
+               __func__, __LINE__ , ## args)
 #else
        #define PDEBUG(level, fmt, args...) do {} while(0)
 #endif
index 50c7763d44b3cad08799299a9f46c2f3839be43c..9afa4fe47726011f4e78edb87fd97095d3410c35 100644 (file)
@@ -24,11 +24,11 @@ extern int ovcamchip_debug;
 
 #define PDEBUG(level, fmt, args...) \
        if (ovcamchip_debug >= (level)) pr_debug("[%s:%d] " fmt "\n", \
-               __FUNCTION__, __LINE__ , ## args)
+               __func__, __LINE__ , ## args)
 
 #define DDEBUG(level, dev, fmt, args...) \
        if (ovcamchip_debug >= (level)) dev_dbg(dev, "[%s:%d] " fmt "\n", \
-               __FUNCTION__, __LINE__ , ## args)
+               __func__, __LINE__ , ## args)
 
 /* Number of times to retry chip detection. Increase this if you are getting
  * "Failed to init camera chip" */
index 6820c2aabd303affccde30951bd018bc7f1d5673..51b1461d8fb62707f48482a59ee34cef55d85a50 100644 (file)
@@ -57,11 +57,11 @@ struct i2c_info
        u8 hits;
 };
 
-static int i2c_count           = 0;
+static int i2c_count;
 static struct i2c_info i2cinfo[64];
 
 static int decoder             = PHILIPS2;
-static int standard            = 0;    /* 0 - auto 1 - ntsc 2 - pal 3 - secam */
+static int standard;   /* 0 - auto 1 - ntsc 2 - pal 3 - secam */
 
 /*
  *     I/O ports and Shared Memory
@@ -885,7 +885,9 @@ static const struct file_operations pms_fops = {
        .open           = video_exclusive_open,
        .release        = video_exclusive_release,
        .ioctl          = pms_ioctl,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .read           = pms_read,
        .llseek         = no_llseek,
 };
index 6fc1b8be1a1ff7811e458d2c4128876ddc974ad7..a8da90f69dd91eba11285efcf2d706839a40791b 100644 (file)
@@ -58,6 +58,30 @@ config VIDEO_PVRUSB2_SYSFS
 
          Note: This feature is experimental and subject to change.
 
+config VIDEO_PVRUSB2_DVB
+       bool "pvrusb2 DVB support (EXPERIMENTAL)"
+       default n
+       depends on VIDEO_PVRUSB2 && DVB_CORE && EXPERIMENTAL
+       select DVB_LGDT330X if !DVB_FE_CUSTOMISE
+       select DVB_S5H1409 if !DVB_FE_CUSTOMISE
+       select DVB_TDA10048 if !DVB_FE_CUSTOMIZE
+       select DVB_TDA18271 if !DVB_FE_CUSTOMIZE
+       select TUNER_SIMPLE if !DVB_FE_CUSTOMISE
+       select TUNER_TDA8290 if !DVB_FE_CUSTOMIZE
+       ---help---
+
+         This option enables compilation of a DVB interface for the
+         pvrusb2 driver.  Currently this is very very experimental.
+         It is also limiting - the DVB interface can only access the
+         digital side of hybrid devices, and there are going to be
+         issues if you attempt to mess with the V4L side at the same
+         time.  Don't turn this on unless you know what you are
+         doing.
+
+         If you are in doubt, say N.
+
+         Note: This feature is very experimental and might break
+
 config VIDEO_PVRUSB2_DEBUGIFC
        bool "pvrusb2 debug interface"
        depends on VIDEO_PVRUSB2_SYSFS
index 47284e55864808a12be78b854b99cf7946c3a577..5b3083c89aa9bcd1841c41d76c029d3ae682d4dc 100644 (file)
@@ -1,5 +1,6 @@
 obj-pvrusb2-sysfs-$(CONFIG_VIDEO_PVRUSB2_SYSFS) := pvrusb2-sysfs.o
 obj-pvrusb2-debugifc-$(CONFIG_VIDEO_PVRUSB2_DEBUGIFC) := pvrusb2-debugifc.o
+obj-pvrusb2-dvb-$(CONFIG_VIDEO_PVRUSB2_DVB) := pvrusb2-dvb.o
 
 pvrusb2-objs   := pvrusb2-i2c-core.o pvrusb2-i2c-cmd-v4l2.o \
                   pvrusb2-audio.o pvrusb2-i2c-chips-v4l2.o \
@@ -9,6 +10,11 @@ pvrusb2-objs  := pvrusb2-i2c-core.o pvrusb2-i2c-cmd-v4l2.o \
                   pvrusb2-ctrl.o pvrusb2-std.o pvrusb2-devattr.o \
                   pvrusb2-context.o pvrusb2-io.o pvrusb2-ioread.o \
                   pvrusb2-cx2584x-v4l.o pvrusb2-wm8775.o \
+                  $(obj-pvrusb2-dvb-y) \
                   $(obj-pvrusb2-sysfs-y) $(obj-pvrusb2-debugifc-y)
 
 obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2.o
+
+EXTRA_CFLAGS += -Idrivers/media/video
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
+EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
index 160437b21e6d3457490f2bd30dc9fdeed82d01b7..b5db6a5bab31e94b5338feb1b788ee14b129eb6e 100644 (file)
 #include "pvrusb2-ioread.h"
 #include "pvrusb2-hdw.h"
 #include "pvrusb2-debug.h"
+#include <linux/wait.h>
+#include <linux/kthread.h>
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/slab.h>
 
+static struct pvr2_context *pvr2_context_exist_first;
+static struct pvr2_context *pvr2_context_exist_last;
+static struct pvr2_context *pvr2_context_notify_first;
+static struct pvr2_context *pvr2_context_notify_last;
+static DEFINE_MUTEX(pvr2_context_mutex);
+static DECLARE_WAIT_QUEUE_HEAD(pvr2_context_sync_data);
+static DECLARE_WAIT_QUEUE_HEAD(pvr2_context_cleanup_data);
+static int pvr2_context_cleanup_flag;
+static int pvr2_context_cleaned_flag;
+static struct task_struct *pvr2_context_thread_ptr;
+
+
+static void pvr2_context_set_notify(struct pvr2_context *mp, int fl)
+{
+       int signal_flag = 0;
+       mutex_lock(&pvr2_context_mutex);
+       if (fl) {
+               if (!mp->notify_flag) {
+                       signal_flag = (pvr2_context_notify_first == NULL);
+                       mp->notify_prev = pvr2_context_notify_last;
+                       mp->notify_next = NULL;
+                       pvr2_context_notify_last = mp;
+                       if (mp->notify_prev) {
+                               mp->notify_prev->notify_next = mp;
+                       } else {
+                               pvr2_context_notify_first = mp;
+                       }
+                       mp->notify_flag = !0;
+               }
+       } else {
+               if (mp->notify_flag) {
+                       mp->notify_flag = 0;
+                       if (mp->notify_next) {
+                               mp->notify_next->notify_prev = mp->notify_prev;
+                       } else {
+                               pvr2_context_notify_last = mp->notify_prev;
+                       }
+                       if (mp->notify_prev) {
+                               mp->notify_prev->notify_next = mp->notify_next;
+                       } else {
+                               pvr2_context_notify_first = mp->notify_next;
+                       }
+               }
+       }
+       mutex_unlock(&pvr2_context_mutex);
+       if (signal_flag) wake_up(&pvr2_context_sync_data);
+}
+
 
 static void pvr2_context_destroy(struct pvr2_context *mp)
 {
-       pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr_main id=%p",mp);
+       pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context %p (destroy)",mp);
        if (mp->hdw) pvr2_hdw_destroy(mp->hdw);
+       pvr2_context_set_notify(mp, 0);
+       mutex_lock(&pvr2_context_mutex);
+       if (mp->exist_next) {
+               mp->exist_next->exist_prev = mp->exist_prev;
+       } else {
+               pvr2_context_exist_last = mp->exist_prev;
+       }
+       if (mp->exist_prev) {
+               mp->exist_prev->exist_next = mp->exist_next;
+       } else {
+               pvr2_context_exist_first = mp->exist_next;
+       }
+       if (!pvr2_context_exist_first) {
+               /* Trigger wakeup on control thread in case it is waiting
+                  for an exit condition. */
+               wake_up(&pvr2_context_sync_data);
+       }
+       mutex_unlock(&pvr2_context_mutex);
        kfree(mp);
 }
 
 
-static void pvr2_context_state_check(struct pvr2_context *mp)
+static void pvr2_context_notify(struct pvr2_context *mp)
 {
-       if (mp->init_flag) return;
+       pvr2_context_set_notify(mp,!0);
+}
+
 
-       switch (pvr2_hdw_get_state(mp->hdw)) {
-       case PVR2_STATE_WARM: break;
-       case PVR2_STATE_ERROR: break;
-       case PVR2_STATE_READY: break;
-       case PVR2_STATE_RUN: break;
-       default: return;
+static void pvr2_context_check(struct pvr2_context *mp)
+{
+       struct pvr2_channel *ch1, *ch2;
+       pvr2_trace(PVR2_TRACE_CTXT,
+                  "pvr2_context %p (notify)", mp);
+       if (!mp->initialized_flag && !mp->disconnect_flag) {
+               mp->initialized_flag = !0;
+               pvr2_trace(PVR2_TRACE_CTXT,
+                          "pvr2_context %p (initialize)", mp);
+               /* Finish hardware initialization */
+               if (pvr2_hdw_initialize(mp->hdw,
+                                       (void (*)(void *))pvr2_context_notify,
+                                       mp)) {
+                       mp->video_stream.stream =
+                               pvr2_hdw_get_video_stream(mp->hdw);
+                       /* Trigger interface initialization.  By doing this
+                          here initialization runs in our own safe and
+                          cozy thread context. */
+                       if (mp->setup_func) mp->setup_func(mp);
+               } else {
+                       pvr2_trace(PVR2_TRACE_CTXT,
+                                  "pvr2_context %p (thread skipping setup)",
+                                  mp);
+                       /* Even though initialization did not succeed,
+                          we're still going to continue anyway.  We need
+                          to do this in order to await the expected
+                          disconnect (which we will detect in the normal
+                          course of operation). */
+               }
        }
 
-       pvr2_context_enter(mp); do {
-               mp->init_flag = !0;
-               mp->video_stream.stream = pvr2_hdw_get_video_stream(mp->hdw);
-               if (mp->setup_func) {
-                       mp->setup_func(mp);
+       for (ch1 = mp->mc_first; ch1; ch1 = ch2) {
+               ch2 = ch1->mc_next;
+               if (ch1->check_func) ch1->check_func(ch1);
+       }
+
+       if (mp->disconnect_flag && !mp->mc_first) {
+               /* Go away... */
+               pvr2_context_destroy(mp);
+               return;
+       }
+}
+
+
+static int pvr2_context_shutok(void)
+{
+       return pvr2_context_cleanup_flag && (pvr2_context_exist_first == NULL);
+}
+
+
+static int pvr2_context_thread_func(void *foo)
+{
+       struct pvr2_context *mp;
+
+       pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context thread start");
+
+       do {
+               while ((mp = pvr2_context_notify_first) != NULL) {
+                       pvr2_context_set_notify(mp, 0);
+                       pvr2_context_check(mp);
                }
-       } while (0); pvr2_context_exit(mp);
- }
+               wait_event_interruptible(
+                       pvr2_context_sync_data,
+                       ((pvr2_context_notify_first != NULL) ||
+                        pvr2_context_shutok()));
+       } while (!pvr2_context_shutok());
+
+       pvr2_context_cleaned_flag = !0;
+       wake_up(&pvr2_context_cleanup_data);
+
+       pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context thread cleaned up");
+
+       wait_event_interruptible(
+               pvr2_context_sync_data,
+               kthread_should_stop());
+
+       pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context thread end");
+
+       return 0;
+}
+
+
+int pvr2_context_global_init(void)
+{
+       pvr2_context_thread_ptr = kthread_run(pvr2_context_thread_func,
+                                             0,
+                                             "pvrusb2-context");
+       return (pvr2_context_thread_ptr ? 0 : -ENOMEM);
+}
+
+
+void pvr2_context_global_done(void)
+{
+       pvr2_context_cleanup_flag = !0;
+       wake_up(&pvr2_context_sync_data);
+       wait_event_interruptible(
+               pvr2_context_cleanup_data,
+               pvr2_context_cleaned_flag);
+       kthread_stop(pvr2_context_thread_ptr);
+}
 
 
 struct pvr2_context *pvr2_context_create(
@@ -66,67 +220,75 @@ struct pvr2_context *pvr2_context_create(
        struct pvr2_context *mp = NULL;
        mp = kzalloc(sizeof(*mp),GFP_KERNEL);
        if (!mp) goto done;
-       pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_main id=%p",mp);
+       pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context %p (create)",mp);
        mp->setup_func = setup_func;
        mutex_init(&mp->mutex);
+       mutex_lock(&pvr2_context_mutex);
+       mp->exist_prev = pvr2_context_exist_last;
+       mp->exist_next = NULL;
+       pvr2_context_exist_last = mp;
+       if (mp->exist_prev) {
+               mp->exist_prev->exist_next = mp;
+       } else {
+               pvr2_context_exist_first = mp;
+       }
+       mutex_unlock(&pvr2_context_mutex);
        mp->hdw = pvr2_hdw_create(intf,devid);
        if (!mp->hdw) {
                pvr2_context_destroy(mp);
                mp = NULL;
                goto done;
        }
-       pvr2_hdw_set_state_callback(mp->hdw,
-                                   (void (*)(void *))pvr2_context_state_check,
-                                   mp);
-       pvr2_context_state_check(mp);
+       pvr2_context_set_notify(mp, !0);
  done:
        return mp;
 }
 
 
-void pvr2_context_enter(struct pvr2_context *mp)
+static void pvr2_context_reset_input_limits(struct pvr2_context *mp)
+{
+       unsigned int tmsk,mmsk;
+       struct pvr2_channel *cp;
+       struct pvr2_hdw *hdw = mp->hdw;
+       mmsk = pvr2_hdw_get_input_available(hdw);
+       tmsk = mmsk;
+       for (cp = mp->mc_first; cp; cp = cp->mc_next) {
+               if (!cp->input_mask) continue;
+               tmsk &= cp->input_mask;
+       }
+       pvr2_hdw_set_input_allowed(hdw,mmsk,tmsk);
+       pvr2_hdw_commit_ctl(hdw);
+}
+
+
+static void pvr2_context_enter(struct pvr2_context *mp)
 {
        mutex_lock(&mp->mutex);
-       pvr2_trace(PVR2_TRACE_CREG,"pvr2_context_enter(id=%p)",mp);
 }
 
 
-void pvr2_context_exit(struct pvr2_context *mp)
+static void pvr2_context_exit(struct pvr2_context *mp)
 {
        int destroy_flag = 0;
        if (!(mp->mc_first || !mp->disconnect_flag)) {
                destroy_flag = !0;
        }
-       pvr2_trace(PVR2_TRACE_CREG,"pvr2_context_exit(id=%p) outside",mp);
        mutex_unlock(&mp->mutex);
-       if (destroy_flag) pvr2_context_destroy(mp);
-}
-
-
-static void pvr2_context_run_checks(struct pvr2_context *mp)
-{
-       struct pvr2_channel *ch1,*ch2;
-       for (ch1 = mp->mc_first; ch1; ch1 = ch2) {
-               ch2 = ch1->mc_next;
-               if (ch1->check_func) {
-                       ch1->check_func(ch1);
-               }
-       }
+       if (destroy_flag) pvr2_context_notify(mp);
 }
 
 
 void pvr2_context_disconnect(struct pvr2_context *mp)
 {
-       pvr2_context_enter(mp); do {
-               pvr2_hdw_disconnect(mp->hdw);
-               mp->disconnect_flag = !0;
-               pvr2_context_run_checks(mp);
-       } while (0); pvr2_context_exit(mp);
+       pvr2_hdw_disconnect(mp->hdw);
+       mp->disconnect_flag = !0;
+       pvr2_context_notify(mp);
 }
 
 
 void pvr2_channel_init(struct pvr2_channel *cp,struct pvr2_context *mp)
 {
+       pvr2_context_enter(mp);
        cp->hdw = mp->hdw;
        cp->mc_head = mp;
        cp->mc_next = NULL;
@@ -137,6 +299,7 @@ void pvr2_channel_init(struct pvr2_channel *cp,struct pvr2_context *mp)
                mp->mc_first = cp;
        }
        mp->mc_last = cp;
+       pvr2_context_exit(mp);
 }
 
 
@@ -152,7 +315,10 @@ static void pvr2_channel_disclaim_stream(struct pvr2_channel *cp)
 void pvr2_channel_done(struct pvr2_channel *cp)
 {
        struct pvr2_context *mp = cp->mc_head;
+       pvr2_context_enter(mp);
+       cp->input_mask = 0;
        pvr2_channel_disclaim_stream(cp);
+       pvr2_context_reset_input_limits(mp);
        if (cp->mc_next) {
                cp->mc_next->mc_prev = cp->mc_prev;
        } else {
@@ -164,6 +330,58 @@ void pvr2_channel_done(struct pvr2_channel *cp)
                mp->mc_first = cp->mc_next;
        }
        cp->hdw = NULL;
+       pvr2_context_exit(mp);
+}
+
+
+int pvr2_channel_limit_inputs(struct pvr2_channel *cp,unsigned int cmsk)
+{
+       unsigned int tmsk,mmsk;
+       int ret = 0;
+       struct pvr2_channel *p2;
+       struct pvr2_hdw *hdw = cp->hdw;
+
+       mmsk = pvr2_hdw_get_input_available(hdw);
+       cmsk &= mmsk;
+       if (cmsk == cp->input_mask) {
+               /* No change; nothing to do */
+               return 0;
+       }
+
+       pvr2_context_enter(cp->mc_head);
+       do {
+               if (!cmsk) {
+                       cp->input_mask = 0;
+                       pvr2_context_reset_input_limits(cp->mc_head);
+                       break;
+               }
+               tmsk = mmsk;
+               for (p2 = cp->mc_head->mc_first; p2; p2 = p2->mc_next) {
+                       if (p2 == cp) continue;
+                       if (!p2->input_mask) continue;
+                       tmsk &= p2->input_mask;
+               }
+               if (!(tmsk & cmsk)) {
+                       ret = -EPERM;
+                       break;
+               }
+               tmsk &= cmsk;
+               if ((ret = pvr2_hdw_set_input_allowed(hdw,mmsk,tmsk)) != 0) {
+                       /* Internal failure changing allowed list; probably
+                          should not happen, but react if it does. */
+                       break;
+               }
+               cp->input_mask = cmsk;
+               pvr2_hdw_commit_ctl(hdw);
+       } while (0);
+       pvr2_context_exit(cp->mc_head);
+       return ret;
+}
+
+
+unsigned int pvr2_channel_get_limited_inputs(struct pvr2_channel *cp)
+{
+       return cp->input_mask;
 }
 
 
@@ -173,7 +391,7 @@ int pvr2_channel_claim_stream(struct pvr2_channel *cp,
        int code = 0;
        pvr2_context_enter(cp->mc_head); do {
                if (sp == cp->stream) break;
-               if (sp->user) {
+               if (sp && sp->user) {
                        code = -EBUSY;
                        break;
                }
index a04187a932251dd86b11020916f55c31c3da51c5..745e270233c26572f2c8f647ae64b43b24908268 100644 (file)
@@ -30,7 +30,6 @@ struct pvr2_stream;  /* stream interface - defined elsewhere */
 struct pvr2_context;        /* All central state */
 struct pvr2_channel;        /* One I/O pathway to a user */
 struct pvr2_context_stream; /* Wrapper for a stream */
-struct pvr2_crit_reg;       /* Critical region pointer */
 struct pvr2_ioread;         /* Low level stream structure */
 
 struct pvr2_context_stream {
@@ -41,11 +40,16 @@ struct pvr2_context_stream {
 struct pvr2_context {
        struct pvr2_channel *mc_first;
        struct pvr2_channel *mc_last;
+       struct pvr2_context *exist_next;
+       struct pvr2_context *exist_prev;
+       struct pvr2_context *notify_next;
+       struct pvr2_context *notify_prev;
        struct pvr2_hdw *hdw;
        struct pvr2_context_stream video_stream;
        struct mutex mutex;
+       int notify_flag;
+       int initialized_flag;
        int disconnect_flag;
-       int init_flag;
 
        /* Called after pvr2_context initialization is complete */
        void (*setup_func)(struct pvr2_context *);
@@ -58,12 +62,10 @@ struct pvr2_channel {
        struct pvr2_channel *mc_prev;
        struct pvr2_context_stream *stream;
        struct pvr2_hdw *hdw;
+       unsigned int input_mask;
        void (*check_func)(struct pvr2_channel *);
 };
 
-void pvr2_context_enter(struct pvr2_context *);
-void pvr2_context_exit(struct pvr2_context *);
-
 struct pvr2_context *pvr2_context_create(struct usb_interface *intf,
                                         const struct usb_device_id *devid,
                                         void (*setup_func)(struct pvr2_context *));
@@ -71,11 +73,15 @@ void pvr2_context_disconnect(struct pvr2_context *);
 
 void pvr2_channel_init(struct pvr2_channel *,struct pvr2_context *);
 void pvr2_channel_done(struct pvr2_channel *);
+int pvr2_channel_limit_inputs(struct pvr2_channel *,unsigned int);
+unsigned int pvr2_channel_get_limited_inputs(struct pvr2_channel *);
 int pvr2_channel_claim_stream(struct pvr2_channel *,
                              struct pvr2_context_stream *);
 struct pvr2_ioread *pvr2_channel_create_mpeg_stream(
        struct pvr2_context_stream *);
 
+int pvr2_context_global_init(void);
+void pvr2_context_global_done(void);
 
 #endif /* __PVRUSB2_CONTEXT_H */
 /*
index 5a3e8d21a38ae7e95b58cd4940a4b905186928d5..91a42f2473a7ff7718d163233c38e39b3efd3b5f 100644 (file)
@@ -30,6 +30,9 @@ static int pvr2_ctrl_range_check(struct pvr2_ctrl *cptr,int val)
 {
        if (cptr->info->check_value) {
                if (!cptr->info->check_value(cptr,val)) return -ERANGE;
+       } else if (cptr->info->type == pvr2_ctl_enum) {
+               if (val < 0) return -ERANGE;
+               if (val >= cptr->info->def.type_enum.count) return -ERANGE;
        } else {
                int lim;
                lim = cptr->info->def.type_int.min_value;
@@ -63,13 +66,10 @@ int pvr2_ctrl_set_mask_value(struct pvr2_ctrl *cptr,int mask,int val)
                if (cptr->info->set_value) {
                        if (cptr->info->type == pvr2_ctl_bitmask) {
                                mask &= cptr->info->def.type_bitmask.valid_bits;
-                       } else if (cptr->info->type == pvr2_ctl_int) {
+                       } else if ((cptr->info->type == pvr2_ctl_int)||
+                                  (cptr->info->type == pvr2_ctl_enum)) {
                                ret = pvr2_ctrl_range_check(cptr,val);
                                if (ret < 0) break;
-                       } else if (cptr->info->type == pvr2_ctl_enum) {
-                               if (val >= cptr->info->def.type_enum.count) {
-                                       break;
-                               }
                        } else if (cptr->info->type != pvr2_ctl_bool) {
                                break;
                        }
@@ -204,8 +204,7 @@ int pvr2_ctrl_get_valname(struct pvr2_ctrl *cptr,int val,
                if (cptr->info->type == pvr2_ctl_enum) {
                        const char **names;
                        names = cptr->info->def.type_enum.value_names;
-                       if ((val >= 0) &&
-                           (val < cptr->info->def.type_enum.count)) {
+                       if (pvr2_ctrl_range_check(cptr,val) == 0) {
                                if (names[val]) {
                                        *blen = scnprintf(
                                                bptr,bmax,"%s",
@@ -528,10 +527,8 @@ int pvr2_ctrl_sym_to_value(struct pvr2_ctrl *cptr,
                                ptr,len,valptr,
                                cptr->info->def.type_enum.value_names,
                                cptr->info->def.type_enum.count);
-                       if ((ret >= 0) &&
-                           ((*valptr < 0) ||
-                            (*valptr >= cptr->info->def.type_enum.count))) {
-                               ret = -ERANGE;
+                       if (ret >= 0) {
+                               ret = pvr2_ctrl_range_check(cptr,*valptr);
                        }
                        if (maskptr) *maskptr = ~0;
                } else if (cptr->info->type == pvr2_ctl_bitmask) {
index ffdc45c324e5d24936de4557da279af46314ee8d..97350b048b8deeb394fba59265467215f3930b45 100644 (file)
@@ -84,7 +84,9 @@ static const struct routing_scheme_item routing_schemegv[] = {
                .vid = CX25840_COMPOSITE2,
                .aud = CX25840_AUDIO5,
        },
-       [PVR2_CVAL_INPUT_RADIO] = { /* Treat the same as composite */
+       [PVR2_CVAL_INPUT_RADIO] = {
+               /* line-in is used for radio and composite.  A GPIO is
+                  used to switch between the two choices. */
                .vid = CX25840_COMPOSITE1,
                .aud = CX25840_AUDIO_SERIAL,
        },
index fca49d8a9311e70544e89b5cd713fc677d91cf05..11537ddf8aa3b0d6b81a44f069b83fb1feec220c 100644 (file)
@@ -39,7 +39,7 @@ extern int pvrusb2_debug;
 #define PVR2_TRACE_EEPROM     (1 << 10) /* eeprom parsing / report */
 #define PVR2_TRACE_STRUCT     (1 << 11) /* internal struct creation */
 #define PVR2_TRACE_OPEN_CLOSE (1 << 12) /* application open / close */
-#define PVR2_TRACE_CREG       (1 << 13) /* Main critical region entry / exit */
+#define PVR2_TRACE_CTXT       (1 << 13) /* Main context tracking */
 #define PVR2_TRACE_SYSFS      (1 << 14) /* Sysfs driven I/O */
 #define PVR2_TRACE_FIRMWARE   (1 << 15) /* firmware upload actions */
 #define PVR2_TRACE_CHIPS      (1 << 16) /* chip broadcast operation */
index b0687430fdd421fc8798ecb4bde590512b42f2d5..b53121c78ff992e9b249e3a1c3afeb8526823ee6 100644 (file)
@@ -164,6 +164,8 @@ int pvr2_debugifc_print_status(struct pvr2_hdw *hdw,
        int ccnt;
        int ret;
        u32 gpio_dir,gpio_in,gpio_out;
+       struct pvr2_stream_stats stats;
+       struct pvr2_stream *sp;
 
        ret = pvr2_hdw_is_hsm(hdw);
        ccnt = scnprintf(buf,acnt,"USB link speed: %s\n",
@@ -182,6 +184,24 @@ int pvr2_debugifc_print_status(struct pvr2_hdw *hdw,
                         pvr2_hdw_get_streaming(hdw) ? "on" : "off");
        bcnt += ccnt; acnt -= ccnt; buf += ccnt;
 
+
+       sp = pvr2_hdw_get_video_stream(hdw);
+       if (sp) {
+               pvr2_stream_get_stats(sp, &stats, 0);
+               ccnt = scnprintf(
+                       buf,acnt,
+                       "Bytes streamed=%u"
+                       " URBs: queued=%u idle=%u ready=%u"
+                       " processed=%u failed=%u\n",
+                       stats.bytes_processed,
+                       stats.buffers_in_queue,
+                       stats.buffers_in_idle,
+                       stats.buffers_in_ready,
+                       stats.buffers_processed,
+                       stats.buffers_failed);
+               bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+       }
+
        return bcnt;
 }
 
@@ -220,6 +240,10 @@ static int pvr2_debugifc_do1cmd(struct pvr2_hdw *hdw,const char *buf,
                        return pvr2_hdw_cmd_decoder_reset(hdw);
                } else if (debugifc_match_keyword(wptr,wlen,"worker")) {
                        return pvr2_hdw_untrip(hdw);
+               } else if (debugifc_match_keyword(wptr,wlen,"usbstats")) {
+                       pvr2_stream_get_stats(pvr2_hdw_get_video_stream(hdw),
+                                             NULL, !0);
+                       return 0;
                }
                return -EINVAL;
        } else if (debugifc_match_keyword(wptr,wlen,"cpufw")) {
index fe9991c10cf4c5b577d9d610360bad84271d11c4..2dd06a90adce435869226611f0864d77ee2f3d65 100644 (file)
@@ -32,7 +32,15 @@ pvr2_device_desc structures.
 /* This is needed in order to pull in tuner type ids... */
 #include <linux/i2c.h>
 #include <media/tuner.h>
-
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+#include "pvrusb2-hdw-internal.h"
+#include "lgdt330x.h"
+#include "s5h1409.h"
+#include "tda10048.h"
+#include "tda18271.h"
+#include "tda8290.h"
+#include "tuner-simple.h"
+#endif
 
 
 /*------------------------------------------------------------------------*/
@@ -49,14 +57,19 @@ static const char *pvr2_fw1_names_29xxx[] = {
 };
 
 static const struct pvr2_device_desc pvr2_device_29xxx = {
-               .description = "WinTV PVR USB2 Model Category 29xxxx",
+               .description = "WinTV PVR USB2 Model Category 29xxx",
                .shortname = "29xxx",
                .client_modules.lst = pvr2_client_29xxx,
                .client_modules.cnt = ARRAY_SIZE(pvr2_client_29xxx),
                .fx2_firmware.lst = pvr2_fw1_names_29xxx,
                .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_29xxx),
                .flag_has_hauppauge_rom = !0,
+               .flag_has_analogtuner = !0,
+               .flag_has_fmradio = !0,
+               .flag_has_composite = !0,
+               .flag_has_svideo = !0,
                .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
+               .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE,
 };
 
 
@@ -75,7 +88,7 @@ static const char *pvr2_fw1_names_24xxx[] = {
 };
 
 static const struct pvr2_device_desc pvr2_device_24xxx = {
-               .description = "WinTV PVR USB2 Model Category 24xxxx",
+               .description = "WinTV PVR USB2 Model Category 24xxx",
                .shortname = "24xxx",
                .client_modules.lst = pvr2_client_24xxx,
                .client_modules.cnt = ARRAY_SIZE(pvr2_client_24xxx),
@@ -85,7 +98,12 @@ static const struct pvr2_device_desc pvr2_device_24xxx = {
                .flag_has_wm8775 = !0,
                .flag_has_hauppauge_rom = !0,
                .flag_has_hauppauge_custom_ir = !0,
+               .flag_has_analogtuner = !0,
+               .flag_has_fmradio = !0,
+               .flag_has_composite = !0,
+               .flag_has_svideo = !0,
                .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
+               .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE,
 };
 
 
@@ -105,6 +123,30 @@ static const struct pvr2_device_desc pvr2_device_gotview_2 = {
                .client_modules.cnt = ARRAY_SIZE(pvr2_client_gotview_2),
                .flag_has_cx25840 = !0,
                .default_tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
+               .flag_has_analogtuner = !0,
+               .flag_has_fmradio = !0,
+               .flag_has_composite = !0,
+               .flag_has_svideo = !0,
+               .signal_routing_scheme = PVR2_ROUTING_SCHEME_GOTVIEW,
+};
+
+
+
+/*------------------------------------------------------------------------*/
+/* GOTVIEW USB2.0 DVD Deluxe */
+
+/* (same module list as gotview_2) */
+
+static const struct pvr2_device_desc pvr2_device_gotview_2d = {
+               .description = "Gotview USB 2.0 DVD Deluxe",
+               .shortname = "gv2d",
+               .client_modules.lst = pvr2_client_gotview_2,
+               .client_modules.cnt = ARRAY_SIZE(pvr2_client_gotview_2),
+               .flag_has_cx25840 = !0,
+               .default_tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
+               .flag_has_analogtuner = !0,
+               .flag_has_composite = !0,
+               .flag_has_svideo = !0,
                .signal_routing_scheme = PVR2_ROUTING_SCHEME_GOTVIEW,
 };
 
@@ -114,6 +156,38 @@ static const struct pvr2_device_desc pvr2_device_gotview_2 = {
 /*------------------------------------------------------------------------*/
 /* OnAir Creator */
 
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+static struct lgdt330x_config pvr2_lgdt3303_config = {
+       .demod_address       = 0x0e,
+       .demod_chip          = LGDT3303,
+       .clock_polarity_flip = 1,
+};
+
+static int pvr2_lgdt3303_attach(struct pvr2_dvb_adapter *adap)
+{
+       adap->fe = dvb_attach(lgdt330x_attach, &pvr2_lgdt3303_config,
+                             &adap->channel.hdw->i2c_adap);
+       if (adap->fe)
+               return 0;
+
+       return -EIO;
+}
+
+static int pvr2_lgh06xf_attach(struct pvr2_dvb_adapter *adap)
+{
+       dvb_attach(simple_tuner_attach, adap->fe,
+                  &adap->channel.hdw->i2c_adap, 0x61,
+                  TUNER_LG_TDVS_H06XF);
+
+       return 0;
+}
+
+struct pvr2_dvb_props pvr2_onair_creator_fe_props = {
+       .frontend_attach = pvr2_lgdt3303_attach,
+       .tuner_attach    = pvr2_lgh06xf_attach,
+};
+#endif
+
 static const char *pvr2_client_onair_creator[] = {
        "saa7115",
        "tuner",
@@ -126,7 +200,16 @@ static const struct pvr2_device_desc pvr2_device_onair_creator = {
                .client_modules.lst = pvr2_client_onair_creator,
                .client_modules.cnt = ARRAY_SIZE(pvr2_client_onair_creator),
                .default_tuner_type = TUNER_LG_TDVS_H06XF,
+               .flag_has_analogtuner = !0,
+               .flag_has_composite = !0,
+               .flag_has_svideo = !0,
+               .flag_digital_requires_cx23416 = !0,
                .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
+               .digital_control_scheme = PVR2_DIGITAL_SCHEME_ONAIR,
+               .default_std_mask = V4L2_STD_NTSC_M,
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+               .dvb_props = &pvr2_onair_creator_fe_props,
+#endif
 };
 #endif
 
@@ -136,6 +219,37 @@ static const struct pvr2_device_desc pvr2_device_onair_creator = {
 /*------------------------------------------------------------------------*/
 /* OnAir USB 2.0 */
 
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+static struct lgdt330x_config pvr2_lgdt3302_config = {
+       .demod_address       = 0x0e,
+       .demod_chip          = LGDT3302,
+};
+
+static int pvr2_lgdt3302_attach(struct pvr2_dvb_adapter *adap)
+{
+       adap->fe = dvb_attach(lgdt330x_attach, &pvr2_lgdt3302_config,
+                             &adap->channel.hdw->i2c_adap);
+       if (adap->fe)
+               return 0;
+
+       return -EIO;
+}
+
+static int pvr2_fcv1236d_attach(struct pvr2_dvb_adapter *adap)
+{
+       dvb_attach(simple_tuner_attach, adap->fe,
+                  &adap->channel.hdw->i2c_adap, 0x61,
+                  TUNER_PHILIPS_FCV1236D);
+
+       return 0;
+}
+
+struct pvr2_dvb_props pvr2_onair_usb2_fe_props = {
+       .frontend_attach = pvr2_lgdt3302_attach,
+       .tuner_attach    = pvr2_fcv1236d_attach,
+};
+#endif
+
 static const char *pvr2_client_onair_usb2[] = {
        "saa7115",
        "tuner",
@@ -147,8 +261,17 @@ static const struct pvr2_device_desc pvr2_device_onair_usb2 = {
                .shortname = "oa2",
                .client_modules.lst = pvr2_client_onair_usb2,
                .client_modules.cnt = ARRAY_SIZE(pvr2_client_onair_usb2),
-               .default_tuner_type = TUNER_PHILIPS_ATSC,
+               .default_tuner_type = TUNER_PHILIPS_FCV1236D,
+               .flag_has_analogtuner = !0,
+               .flag_has_composite = !0,
+               .flag_has_svideo = !0,
+               .flag_digital_requires_cx23416 = !0,
                .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
+               .digital_control_scheme = PVR2_DIGITAL_SCHEME_ONAIR,
+               .default_std_mask = V4L2_STD_NTSC_M,
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+               .dvb_props = &pvr2_onair_usb2_fe_props,
+#endif
 };
 #endif
 
@@ -157,6 +280,50 @@ static const struct pvr2_device_desc pvr2_device_onair_usb2 = {
 /*------------------------------------------------------------------------*/
 /* Hauppauge PVR-USB2 Model 73xxx */
 
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+static struct tda10048_config hauppauge_tda10048_config = {
+       .demod_address  = 0x10 >> 1,
+       .output_mode    = TDA10048_PARALLEL_OUTPUT,
+       .fwbulkwritelen = TDA10048_BULKWRITE_50,
+       .inversion      = TDA10048_INVERSION_ON,
+};
+
+static struct tda829x_config tda829x_no_probe = {
+       .probe_tuner = TDA829X_DONT_PROBE,
+};
+
+static struct tda18271_config hauppauge_tda18271_dvb_config = {
+       .gate    = TDA18271_GATE_ANALOG,
+};
+
+static int pvr2_tda10048_attach(struct pvr2_dvb_adapter *adap)
+{
+       adap->fe = dvb_attach(tda10048_attach, &hauppauge_tda10048_config,
+                             &adap->channel.hdw->i2c_adap);
+       if (adap->fe)
+               return 0;
+
+       return -EIO;
+}
+
+static int pvr2_73xxx_tda18271_8295_attach(struct pvr2_dvb_adapter *adap)
+{
+       dvb_attach(tda829x_attach, adap->fe,
+                  &adap->channel.hdw->i2c_adap, 0x42,
+                  &tda829x_no_probe);
+       dvb_attach(tda18271_attach, adap->fe, 0x60,
+                  &adap->channel.hdw->i2c_adap,
+                  &hauppauge_tda18271_dvb_config);
+
+       return 0;
+}
+
+struct pvr2_dvb_props pvr2_73xxx_dvb_props = {
+       .frontend_attach = pvr2_tda10048_attach,
+       .tuner_attach    = pvr2_73xxx_tda18271_8295_attach,
+};
+#endif
+
 static const char *pvr2_client_73xxx[] = {
        "cx25840",
        "tuner",
@@ -167,7 +334,7 @@ static const char *pvr2_fw1_names_73xxx[] = {
 };
 
 static const struct pvr2_device_desc pvr2_device_73xxx = {
-               .description = "WinTV PVR USB2 Model Category 73xxxx",
+               .description = "WinTV PVR USB2 Model Category 73xxx",
                .shortname = "73xxx",
                .client_modules.lst = pvr2_client_73xxx,
                .client_modules.cnt = ARRAY_SIZE(pvr2_client_73xxx),
@@ -175,15 +342,14 @@ static const struct pvr2_device_desc pvr2_device_73xxx = {
                .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_73xxx),
                .flag_has_cx25840 = !0,
                .flag_has_hauppauge_rom = !0,
-#if 0
                .flag_has_analogtuner = !0,
                .flag_has_composite = !0,
                .flag_has_svideo = !0,
                .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
                .digital_control_scheme = PVR2_DIGITAL_SCHEME_HAUPPAUGE,
                .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE,
-#else
-               .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+               .dvb_props = &pvr2_73xxx_dvb_props,
 #endif
 };
 
@@ -192,6 +358,56 @@ static const struct pvr2_device_desc pvr2_device_73xxx = {
 /*------------------------------------------------------------------------*/
 /* Hauppauge PVR-USB2 Model 75xxx */
 
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+static struct s5h1409_config pvr2_s5h1409_config = {
+       .demod_address = 0x32 >> 1,
+       .output_mode   = S5H1409_PARALLEL_OUTPUT,
+       .gpio          = S5H1409_GPIO_OFF,
+       .qam_if        = 4000,
+       .inversion     = S5H1409_INVERSION_ON,
+       .status_mode   = S5H1409_DEMODLOCKING,
+};
+
+static struct tda18271_std_map hauppauge_tda18271_std_map = {
+       .atsc_6   = { .if_freq = 5380, .agc_mode = 3, .std = 3,
+                     .if_lvl = 6, .rfagc_top = 0x37, },
+       .qam_6    = { .if_freq = 4000, .agc_mode = 3, .std = 0,
+                     .if_lvl = 6, .rfagc_top = 0x37, },
+};
+
+static struct tda18271_config hauppauge_tda18271_config = {
+       .std_map = &hauppauge_tda18271_std_map,
+       .gate    = TDA18271_GATE_ANALOG,
+};
+
+static int pvr2_s5h1409_attach(struct pvr2_dvb_adapter *adap)
+{
+       adap->fe = dvb_attach(s5h1409_attach, &pvr2_s5h1409_config,
+                             &adap->channel.hdw->i2c_adap);
+       if (adap->fe)
+               return 0;
+
+       return -EIO;
+}
+
+static int pvr2_tda18271_8295_attach(struct pvr2_dvb_adapter *adap)
+{
+       dvb_attach(tda829x_attach, adap->fe,
+                  &adap->channel.hdw->i2c_adap, 0x42,
+                  &tda829x_no_probe);
+       dvb_attach(tda18271_attach, adap->fe, 0x60,
+                  &adap->channel.hdw->i2c_adap,
+                  &hauppauge_tda18271_config);
+
+       return 0;
+}
+
+struct pvr2_dvb_props pvr2_750xx_dvb_props = {
+       .frontend_attach = pvr2_s5h1409_attach,
+       .tuner_attach    = pvr2_tda18271_8295_attach,
+};
+#endif
+
 static const char *pvr2_client_75xxx[] = {
        "cx25840",
        "tuner",
@@ -201,17 +417,43 @@ static const char *pvr2_fw1_names_75xxx[] = {
                "v4l-pvrusb2-73xxx-01.fw",
 };
 
-static const struct pvr2_device_desc pvr2_device_75xxx = {
-               .description = "WinTV PVR USB2 Model Category 75xxxx",
-               .shortname = "75xxx",
+static const struct pvr2_device_desc pvr2_device_750xx = {
+               .description = "WinTV PVR USB2 Model Category 750xx",
+               .shortname = "750xx",
+               .client_modules.lst = pvr2_client_75xxx,
+               .client_modules.cnt = ARRAY_SIZE(pvr2_client_75xxx),
+               .fx2_firmware.lst = pvr2_fw1_names_75xxx,
+               .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_75xxx),
+               .flag_has_cx25840 = !0,
+               .flag_has_hauppauge_rom = !0,
+               .flag_has_analogtuner = !0,
+               .flag_has_composite = !0,
+               .flag_has_svideo = !0,
+               .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
+               .digital_control_scheme = PVR2_DIGITAL_SCHEME_HAUPPAUGE,
+               .default_std_mask = V4L2_STD_NTSC_M,
+               .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE,
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+               .dvb_props = &pvr2_750xx_dvb_props,
+#endif
+};
+
+static const struct pvr2_device_desc pvr2_device_751xx = {
+               .description = "WinTV PVR USB2 Model Category 751xx",
+               .shortname = "751xx",
                .client_modules.lst = pvr2_client_75xxx,
                .client_modules.cnt = ARRAY_SIZE(pvr2_client_75xxx),
                .fx2_firmware.lst = pvr2_fw1_names_75xxx,
                .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_75xxx),
                .flag_has_cx25840 = !0,
                .flag_has_hauppauge_rom = !0,
+               .flag_has_analogtuner = !0,
+               .flag_has_composite = !0,
+               .flag_has_svideo = !0,
                .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
+               .digital_control_scheme = PVR2_DIGITAL_SCHEME_HAUPPAUGE,
                .default_std_mask = V4L2_STD_NTSC_M,
+               .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE,
 };
 
 
@@ -225,6 +467,8 @@ struct usb_device_id pvr2_device_table[] = {
          .driver_info = (kernel_ulong_t)&pvr2_device_24xxx},
        { USB_DEVICE(0x1164, 0x0622),
          .driver_info = (kernel_ulong_t)&pvr2_device_gotview_2},
+       { USB_DEVICE(0x1164, 0x0602),
+         .driver_info = (kernel_ulong_t)&pvr2_device_gotview_2d},
 #ifdef CONFIG_VIDEO_PVRUSB2_ONAIR_CREATOR
        { USB_DEVICE(0x11ba, 0x1003),
          .driver_info = (kernel_ulong_t)&pvr2_device_onair_creator},
@@ -236,9 +480,9 @@ struct usb_device_id pvr2_device_table[] = {
        { USB_DEVICE(0x2040, 0x7300),
          .driver_info = (kernel_ulong_t)&pvr2_device_73xxx},
        { USB_DEVICE(0x2040, 0x7500),
-         .driver_info = (kernel_ulong_t)&pvr2_device_75xxx},
+         .driver_info = (kernel_ulong_t)&pvr2_device_750xx},
        { USB_DEVICE(0x2040, 0x7501),
-         .driver_info = (kernel_ulong_t)&pvr2_device_75xxx},
+         .driver_info = (kernel_ulong_t)&pvr2_device_751xx},
        { }
 };
 
index 64b467f0637f121e1ea4eb6b9eb9fe8a6be2ef01..c2e2b06fe2e0bbeb80d791309495591e4d75e9da 100644 (file)
@@ -23,6 +23,9 @@
 
 #include <linux/mod_devicetable.h>
 #include <linux/videodev2.h>
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+#include "pvrusb2-dvb.h"
+#endif
 
 /*
 
@@ -39,6 +42,13 @@ struct pvr2_string_table {
 #define PVR2_ROUTING_SCHEME_HAUPPAUGE 0
 #define PVR2_ROUTING_SCHEME_GOTVIEW 1
 
+#define PVR2_DIGITAL_SCHEME_NONE 0
+#define PVR2_DIGITAL_SCHEME_HAUPPAUGE 1
+#define PVR2_DIGITAL_SCHEME_ONAIR 2
+
+#define PVR2_LED_SCHEME_NONE 0
+#define PVR2_LED_SCHEME_HAUPPAUGE 1
+
 /* This describes a particular hardware type (except for the USB device ID
    which must live in a separate structure due to environmental
    constraints).  See the top of pvrusb2-hdw.c for where this is
@@ -58,40 +68,64 @@ struct pvr2_device_desc {
           was initialized from internal ROM. */
        struct pvr2_string_table fx2_firmware;
 
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+       /* callback functions to handle attachment of digital tuner & demod */
+       struct pvr2_dvb_props *dvb_props;
+
+#endif
+       /* Initial standard bits to use for this device, if not zero.
+          Anything set here is also implied as an available standard.
+          Note: This is ignored if overridden on the module load line via
+          the video_std module option. */
+       v4l2_std_id default_std_mask;
+
+       /* V4L tuner type ID to use with this device (only used if the
+          driver could not discover the type any other way). */
+       int default_tuner_type;
+
        /* Signal routing scheme used by device, contains one of
           PVR2_ROUTING_SCHEME_XXX.  Schemes have to be defined as we
           encounter them.  This is an arbitrary integer scheme id; its
           meaning is contained entirely within the driver and is
           interpreted by logic which must send commands to the chip-level
           drivers (search for things which touch this field). */
-       unsigned int signal_routing_scheme;
+       unsigned char signal_routing_scheme;
 
-       /* V4L tuner type ID to use with this device (only used if the
-          driver could not discover the type any other way). */
-       int default_tuner_type;
+       /* Indicates scheme for controlling device's LED (if any).  The
+          driver will turn on the LED when streaming is underway.  This
+          contains one of PVR2_LED_SCHEME_XXX. */
+       unsigned char led_scheme;
 
-       /* Initial standard bits to use for this device, if not zero.
-          Anything set here is also implied as an available standard.
-          Note: This is ignored if overridden on the module load line via
-          the video_std module option. */
-       v4l2_std_id default_std_mask;
+       /* Control scheme to use if there is a digital tuner.  This
+          contains one of PVR2_DIGITAL_SCHEME_XXX.  This is an arbitrary
+          integer scheme id; its meaning is contained entirely within the
+          driver and is interpreted by logic which must control the
+          streaming pathway (search for things which touch this field). */
+       unsigned char digital_control_scheme;
 
        /* If set, we don't bother trying to load cx23416 firmware. */
-       char flag_skip_cx23416_firmware;
+       int flag_skip_cx23416_firmware:1;
+
+       /* If set, the encoder must be healthy in order for digital mode to
+          work (otherwise we assume that digital streaming will work even
+          if we fail to locate firmware for the encoder).  If the device
+          doesn't support digital streaming then this flag has no
+          effect. */
+       int flag_digital_requires_cx23416:1;
 
        /* Device has a hauppauge eeprom which we can interrogate. */
-       char flag_has_hauppauge_rom;
+       int flag_has_hauppauge_rom:1;
 
        /* Device does not require a powerup command to be issued. */
-       char flag_no_powerup;
+       int flag_no_powerup:1;
 
        /* Device has a cx25840 - this enables special additional logic to
           handle it. */
-       char flag_has_cx25840;
+       int flag_has_cx25840:1;
 
        /* Device has a wm8775 - this enables special additional logic to
           ensure that it is found. */
-       char flag_has_wm8775;
+       int flag_has_wm8775:1;
 
        /* Device has IR hardware that can be faked into looking like a
           normal Hauppauge i2c IR receiver.  This is currently very
@@ -101,7 +135,15 @@ struct pvr2_device_desc {
           to virtualize the presence of the non-existant IR receiver chip and
           implement the virtual receiver in terms of appropriate FX2
           commands. */
-       char flag_has_hauppauge_custom_ir;
+       int flag_has_hauppauge_custom_ir:1;
+
+       /* These bits define which kinds of sources the device can handle.
+          Note: Digital tuner presence is inferred by the
+          digital_control_scheme enumeration. */
+       int flag_has_fmradio:1;       /* Has FM radio receiver */
+       int flag_has_analogtuner:1;   /* Has analog tuner */
+       int flag_has_composite:1;     /* Has composite input */
+       int flag_has_svideo:1;        /* Has s-video input */
 };
 
 extern struct usb_device_id pvr2_device_table[];
diff --git a/drivers/media/video/pvrusb2/pvrusb2-dvb.c b/drivers/media/video/pvrusb2/pvrusb2-dvb.c
new file mode 100644 (file)
index 0000000..2e64f98
--- /dev/null
@@ -0,0 +1,425 @@
+/*
+ *  pvrusb2-dvb.c - linux-dvb api interface to the pvrusb2 driver.
+ *
+ *  Copyright (C) 2007, 2008 Michael Krufky <mkrufky@linuxtv.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
+ *
+ *  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/kthread.h>
+#include <linux/freezer.h>
+#include "dvbdev.h"
+#include "pvrusb2-hdw-internal.h"
+#include "pvrusb2-hdw.h"
+#include "pvrusb2-io.h"
+#include "pvrusb2-dvb.h"
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+static int pvr2_dvb_feed_func(struct pvr2_dvb_adapter *adap)
+{
+       int ret;
+       unsigned int count;
+       struct pvr2_buffer *bp;
+       struct pvr2_stream *stream;
+
+       printk(KERN_DEBUG "dvb thread started\n");
+       set_freezable();
+
+       stream = adap->channel.stream->stream;
+
+       for (;;) {
+               if (kthread_should_stop()) break;
+
+               /* Not sure about this... */
+               try_to_freeze();
+
+               bp = pvr2_stream_get_ready_buffer(stream);
+               if (bp != NULL) {
+                       count = pvr2_buffer_get_count(bp);
+                       if (count) {
+                               dvb_dmx_swfilter(
+                                       &adap->demux,
+                                       adap->buffer_storage[
+                                           pvr2_buffer_get_id(bp)],
+                                       count);
+                       } else {
+                               ret = pvr2_buffer_get_status(bp);
+                               if (ret < 0) break;
+                       }
+                       ret = pvr2_buffer_queue(bp);
+                       if (ret < 0) break;
+
+                       /* Since we know we did something to a buffer,
+                          just go back and try again.  No point in
+                          blocking unless we really ran out of
+                          buffers to process. */
+                       continue;
+               }
+
+
+               /* Wait until more buffers become available or we're
+                  told not to wait any longer. */
+               ret = wait_event_interruptible(
+                   adap->buffer_wait_data,
+                   (pvr2_stream_get_ready_count(stream) > 0) ||
+                   kthread_should_stop());
+               if (ret < 0) break;
+       }
+
+       /* If we get here and ret is < 0, then an error has occurred.
+          Probably would be a good idea to communicate that to DVB core... */
+
+       printk(KERN_DEBUG "dvb thread stopped\n");
+
+       return 0;
+}
+
+static int pvr2_dvb_feed_thread(void *data)
+{
+       int stat = pvr2_dvb_feed_func(data);
+       /* from videobuf-dvb.c: */
+       while (!kthread_should_stop()) {
+               set_current_state(TASK_INTERRUPTIBLE);
+               schedule();
+       }
+       return stat;
+}
+
+static void pvr2_dvb_notify(struct pvr2_dvb_adapter *adap)
+{
+       wake_up(&adap->buffer_wait_data);
+}
+
+static void pvr2_dvb_stream_end(struct pvr2_dvb_adapter *adap)
+{
+       unsigned int idx;
+       struct pvr2_stream *stream;
+
+       if (adap->thread) {
+               kthread_stop(adap->thread);
+               adap->thread = NULL;
+       }
+
+       if (adap->channel.stream) {
+               stream = adap->channel.stream->stream;
+       } else {
+               stream = NULL;
+       }
+       if (stream) {
+               pvr2_hdw_set_streaming(adap->channel.hdw, 0);
+               pvr2_stream_set_callback(stream, NULL, NULL);
+               pvr2_stream_kill(stream);
+               pvr2_stream_set_buffer_count(stream, 0);
+               pvr2_channel_claim_stream(&adap->channel, NULL);
+       }
+
+       if (adap->stream_run) {
+               for (idx = 0; idx < PVR2_DVB_BUFFER_COUNT; idx++) {
+                       if (!(adap->buffer_storage[idx])) continue;
+                       kfree(adap->buffer_storage[idx]);
+                       adap->buffer_storage[idx] = 0;
+               }
+               adap->stream_run = 0;
+       }
+}
+
+static int pvr2_dvb_stream_do_start(struct pvr2_dvb_adapter *adap)
+{
+       struct pvr2_context *pvr = adap->channel.mc_head;
+       unsigned int idx;
+       int ret;
+       struct pvr2_buffer *bp;
+       struct pvr2_stream *stream = 0;
+
+       if (adap->stream_run) return -EIO;
+
+       ret = pvr2_channel_claim_stream(&adap->channel, &pvr->video_stream);
+       /* somebody else already has the stream */
+       if (ret < 0) return ret;
+
+       stream = adap->channel.stream->stream;
+
+       for (idx = 0; idx < PVR2_DVB_BUFFER_COUNT; idx++) {
+               adap->buffer_storage[idx] = kmalloc(PVR2_DVB_BUFFER_SIZE,
+                                                   GFP_KERNEL);
+               if (!(adap->buffer_storage[idx])) return -ENOMEM;
+       }
+
+       pvr2_stream_set_callback(pvr->video_stream.stream,
+                                (pvr2_stream_callback) pvr2_dvb_notify, adap);
+
+       ret = pvr2_stream_set_buffer_count(stream, PVR2_DVB_BUFFER_COUNT);
+       if (ret < 0) return ret;
+
+       for (idx = 0; idx < PVR2_DVB_BUFFER_COUNT; idx++) {
+               bp = pvr2_stream_get_buffer(stream, idx);
+               pvr2_buffer_set_buffer(bp,
+                                      adap->buffer_storage[idx],
+                                      PVR2_DVB_BUFFER_SIZE);
+       }
+
+       ret = pvr2_hdw_set_streaming(adap->channel.hdw, 1);
+       if (ret < 0) return ret;
+
+       while ((bp = pvr2_stream_get_idle_buffer(stream)) != 0) {
+               ret = pvr2_buffer_queue(bp);
+               if (ret < 0) return ret;
+       }
+
+       adap->thread = kthread_run(pvr2_dvb_feed_thread, adap, "pvrusb2-dvb");
+
+       if (IS_ERR(adap->thread)) {
+               ret = PTR_ERR(adap->thread);
+               adap->thread = NULL;
+               return ret;
+       }
+
+       adap->stream_run = !0;
+
+       return 0;
+}
+
+static int pvr2_dvb_stream_start(struct pvr2_dvb_adapter *adap)
+{
+       int ret = pvr2_dvb_stream_do_start(adap);
+       if (ret < 0) pvr2_dvb_stream_end(adap);
+       return ret;
+}
+
+static int pvr2_dvb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
+{
+       struct pvr2_dvb_adapter *adap = dvbdmxfeed->demux->priv;
+       int ret = 0;
+
+       if (adap == NULL) return -ENODEV;
+
+       mutex_lock(&adap->lock);
+       do {
+               if (onoff) {
+                       if (!adap->feedcount) {
+                               printk(KERN_DEBUG "start feeding\n");
+                               ret = pvr2_dvb_stream_start(adap);
+                               if (ret < 0) break;
+                       }
+                       (adap->feedcount)++;
+               } else if (adap->feedcount > 0) {
+                       (adap->feedcount)--;
+                       if (!adap->feedcount) {
+                               printk(KERN_DEBUG "stop feeding\n");
+                               pvr2_dvb_stream_end(adap);
+                       }
+               }
+       } while (0);
+       mutex_unlock(&adap->lock);
+
+       return ret;
+}
+
+static int pvr2_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+       printk(KERN_DEBUG "start pid: 0x%04x, feedtype: %d\n",
+              dvbdmxfeed->pid, dvbdmxfeed->type);
+       return pvr2_dvb_ctrl_feed(dvbdmxfeed, 1);
+}
+
+static int pvr2_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+       printk(KERN_DEBUG "stop pid: 0x%04x, feedtype: %d\n",
+              dvbdmxfeed->pid, dvbdmxfeed->type);
+       return pvr2_dvb_ctrl_feed(dvbdmxfeed, 0);
+}
+
+static int pvr2_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire)
+{
+       struct pvr2_dvb_adapter *adap = fe->dvb->priv;
+       return pvr2_channel_limit_inputs(
+           &adap->channel,
+           (acquire ? (1 << PVR2_CVAL_INPUT_DTV) : 0));
+}
+
+static int pvr2_dvb_adapter_init(struct pvr2_dvb_adapter *adap)
+{
+       int ret;
+
+       ret = dvb_register_adapter(&adap->dvb_adap, "pvrusb2-dvb",
+                                  THIS_MODULE/*&hdw->usb_dev->owner*/,
+                                  &adap->channel.hdw->usb_dev->dev,
+                                  adapter_nr);
+       if (ret < 0) {
+               err("dvb_register_adapter failed: error %d", ret);
+               goto err;
+       }
+       adap->dvb_adap.priv = adap;
+
+       adap->demux.dmx.capabilities = DMX_TS_FILTERING |
+                                      DMX_SECTION_FILTERING |
+                                      DMX_MEMORY_BASED_FILTERING;
+       adap->demux.priv             = adap;
+       adap->demux.filternum        = 256;
+       adap->demux.feednum          = 256;
+       adap->demux.start_feed       = pvr2_dvb_start_feed;
+       adap->demux.stop_feed        = pvr2_dvb_stop_feed;
+       adap->demux.write_to_decoder = NULL;
+
+       ret = dvb_dmx_init(&adap->demux);
+       if (ret < 0) {
+               err("dvb_dmx_init failed: error %d", ret);
+               goto err_dmx;
+       }
+
+       adap->dmxdev.filternum       = adap->demux.filternum;
+       adap->dmxdev.demux           = &adap->demux.dmx;
+       adap->dmxdev.capabilities    = 0;
+
+       ret = dvb_dmxdev_init(&adap->dmxdev, &adap->dvb_adap);
+       if (ret < 0) {
+               err("dvb_dmxdev_init failed: error %d", ret);
+               goto err_dmx_dev;
+       }
+
+       dvb_net_init(&adap->dvb_adap, &adap->dvb_net, &adap->demux.dmx);
+
+       return 0;
+
+err_dmx_dev:
+       dvb_dmx_release(&adap->demux);
+err_dmx:
+       dvb_unregister_adapter(&adap->dvb_adap);
+err:
+       return ret;
+}
+
+static int pvr2_dvb_adapter_exit(struct pvr2_dvb_adapter *adap)
+{
+       printk(KERN_DEBUG "unregistering DVB devices\n");
+       dvb_net_release(&adap->dvb_net);
+       adap->demux.dmx.close(&adap->demux.dmx);
+       dvb_dmxdev_release(&adap->dmxdev);
+       dvb_dmx_release(&adap->demux);
+       dvb_unregister_adapter(&adap->dvb_adap);
+       return 0;
+}
+
+static int pvr2_dvb_frontend_init(struct pvr2_dvb_adapter *adap)
+{
+       struct pvr2_hdw *hdw = adap->channel.hdw;
+       struct pvr2_dvb_props *dvb_props = hdw->hdw_desc->dvb_props;
+       int ret = 0;
+
+       if (dvb_props == NULL) {
+               err("fe_props not defined!");
+               return -EINVAL;
+       }
+
+       ret = pvr2_channel_limit_inputs(
+           &adap->channel,
+           (1 << PVR2_CVAL_INPUT_DTV));
+       if (ret) {
+               err("failed to grab control of dtv input (code=%d)",
+                   ret);
+               return ret;
+       }
+
+       if (dvb_props->frontend_attach == NULL) {
+               err("frontend_attach not defined!");
+               ret = -EINVAL;
+               goto done;
+       }
+
+       if ((dvb_props->frontend_attach(adap) == 0) && (adap->fe)) {
+
+               if (dvb_register_frontend(&adap->dvb_adap, adap->fe)) {
+                       err("frontend registration failed!");
+                       dvb_frontend_detach(adap->fe);
+                       adap->fe = NULL;
+                       ret = -ENODEV;
+                       goto done;
+               }
+
+               if (dvb_props->tuner_attach)
+                       dvb_props->tuner_attach(adap);
+
+               if (adap->fe->ops.analog_ops.standby)
+                       adap->fe->ops.analog_ops.standby(adap->fe);
+
+               /* Ensure all frontends negotiate bus access */
+               adap->fe->ops.ts_bus_ctrl = pvr2_dvb_bus_ctrl;
+
+       } else {
+               err("no frontend was attached!");
+               ret = -ENODEV;
+               return ret;
+       }
+
+ done:
+       pvr2_channel_limit_inputs(&adap->channel, 0);
+       return ret;
+}
+
+static int pvr2_dvb_frontend_exit(struct pvr2_dvb_adapter *adap)
+{
+       if (adap->fe != NULL) {
+               dvb_unregister_frontend(adap->fe);
+               dvb_frontend_detach(adap->fe);
+       }
+       return 0;
+}
+
+static void pvr2_dvb_destroy(struct pvr2_dvb_adapter *adap)
+{
+       pvr2_dvb_stream_end(adap);
+       pvr2_dvb_frontend_exit(adap);
+       pvr2_dvb_adapter_exit(adap);
+       pvr2_channel_done(&adap->channel);
+       kfree(adap);
+}
+
+static void pvr2_dvb_internal_check(struct pvr2_channel *chp)
+{
+       struct pvr2_dvb_adapter *adap;
+       adap = container_of(chp, struct pvr2_dvb_adapter, channel);
+       if (!adap->channel.mc_head->disconnect_flag) return;
+       pvr2_dvb_destroy(adap);
+}
+
+struct pvr2_dvb_adapter *pvr2_dvb_create(struct pvr2_context *pvr)
+{
+       int ret = 0;
+       struct pvr2_dvb_adapter *adap;
+       if (!pvr->hdw->hdw_desc->dvb_props) {
+               /* Device lacks a digital interface so don't set up
+                  the DVB side of the driver either.  For now. */
+               return NULL;
+       }
+       adap = kzalloc(sizeof(*adap), GFP_KERNEL);
+       if (!adap) return adap;
+       pvr2_channel_init(&adap->channel, pvr);
+       adap->channel.check_func = pvr2_dvb_internal_check;
+       init_waitqueue_head(&adap->buffer_wait_data);
+       mutex_init(&adap->lock);
+       ret = pvr2_dvb_adapter_init(adap);
+       if (ret < 0) goto fail1;
+       ret = pvr2_dvb_frontend_init(adap);
+       if (ret < 0) goto fail2;
+       return adap;
+
+fail2:
+       pvr2_dvb_adapter_exit(adap);
+fail1:
+       pvr2_channel_done(&adap->channel);
+       return NULL;
+}
+
diff --git a/drivers/media/video/pvrusb2/pvrusb2-dvb.h b/drivers/media/video/pvrusb2/pvrusb2-dvb.h
new file mode 100644 (file)
index 0000000..884ff91
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef __PVRUSB2_DVB_H__
+#define __PVRUSB2_DVB_H__
+
+#include "dvb_frontend.h"
+#include "dvb_demux.h"
+#include "dvb_net.h"
+#include "dmxdev.h"
+#include "pvrusb2-context.h"
+
+#define PVR2_DVB_BUFFER_COUNT 32
+#define PVR2_DVB_BUFFER_SIZE PAGE_ALIGN(0x4000)
+
+struct pvr2_dvb_adapter {
+       struct pvr2_channel     channel;
+
+       struct dvb_adapter      dvb_adap;
+       struct dmxdev           dmxdev;
+       struct dvb_demux        demux;
+       struct dvb_net          dvb_net;
+       struct dvb_frontend     *fe;
+
+       int                     feedcount;
+       int                     max_feed_count;
+
+       struct task_struct      *thread;
+       struct mutex            lock;
+
+       unsigned int            stream_run:1;
+
+       wait_queue_head_t       buffer_wait_data;
+       char                    *buffer_storage[PVR2_DVB_BUFFER_COUNT];
+};
+
+struct pvr2_dvb_props {
+       int (*frontend_attach) (struct pvr2_dvb_adapter *);
+       int (*tuner_attach) (struct pvr2_dvb_adapter *);
+};
+
+struct pvr2_dvb_adapter *pvr2_dvb_create(struct pvr2_context *pvr);
+
+#endif /* __PVRUSB2_DVB_H__ */
index 64062879981e4297db9f8386c68306c15e61c616..c46d367f7472599ca8b57aeeddd52e2956c372a6 100644 (file)
@@ -278,11 +278,20 @@ static int pvr2_encoder_cmd(void *ctxt,
                        ret = -EBUSY;
                }
                if (ret) {
+                       del_timer_sync(&hdw->encoder_run_timer);
                        hdw->state_encoder_ok = 0;
                        pvr2_trace(PVR2_TRACE_STBITS,
                                   "State bit %s <-- %s",
                                   "state_encoder_ok",
                                   (hdw->state_encoder_ok ? "true" : "false"));
+                       if (hdw->state_encoder_runok) {
+                               hdw->state_encoder_runok = 0;
+                               pvr2_trace(PVR2_TRACE_STBITS,
+                                  "State bit %s <-- %s",
+                                          "state_encoder_runok",
+                                          (hdw->state_encoder_runok ?
+                                           "true" : "false"));
+                       }
                        pvr2_trace(
                                PVR2_TRACE_ERROR_LEGS,
                                "Giving up on command."
@@ -480,10 +489,6 @@ int pvr2_encoder_start(struct pvr2_hdw *hdw)
        /* unmask some interrupts */
        pvr2_write_register(hdw, 0x0048, 0xbfffffff);
 
-       /* change some GPIO data */
-       pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000481);
-       pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000000);
-
        pvr2_encoder_vcmd(hdw,CX2341X_ENC_MUTE_VIDEO,1,
                          hdw->input_val == PVR2_CVAL_INPUT_RADIO ? 1 : 0);
 
@@ -526,12 +531,6 @@ int pvr2_encoder_stop(struct pvr2_hdw *hdw)
                break;
        }
 
-       /* change some GPIO data */
-       /* Note: Bit d7 of dir appears to control the LED.  So we shut it
-          off here. */
-       pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000401);
-       pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000000);
-
        return status;
 }
 
index ffbc6d09610880535fc04120f3461bc78b112308..abaada31e66ebe06c26bb9ba34a2df0006c58ab2 100644 (file)
 #ifndef _PVRUSB2_FX2_CMD_H_
 #define _PVRUSB2_FX2_CMD_H_
 
-#define FX2CMD_MEM_WRITE_DWORD  0x01
-#define FX2CMD_MEM_READ_DWORD   0x02
+#define FX2CMD_MEM_WRITE_DWORD  0x01u
+#define FX2CMD_MEM_READ_DWORD   0x02u
 
-#define FX2CMD_MEM_READ_64BYTES 0x28
+#define FX2CMD_MEM_READ_64BYTES 0x28u
 
-#define FX2CMD_REG_WRITE        0x04
-#define FX2CMD_REG_READ         0x05
-#define FX2CMD_MEMSEL           0x06
+#define FX2CMD_REG_WRITE        0x04u
+#define FX2CMD_REG_READ         0x05u
+#define FX2CMD_MEMSEL           0x06u
 
-#define FX2CMD_I2C_WRITE        0x08
-#define FX2CMD_I2C_READ         0x09
+#define FX2CMD_I2C_WRITE        0x08u
+#define FX2CMD_I2C_READ         0x09u
 
-#define FX2CMD_GET_USB_SPEED    0x0b
+#define FX2CMD_GET_USB_SPEED    0x0bu
 
-#define FX2CMD_STREAMING_ON     0x36
-#define FX2CMD_STREAMING_OFF    0x37
+#define FX2CMD_STREAMING_ON     0x36u
+#define FX2CMD_STREAMING_OFF    0x37u
 
-#define FX2CMD_FWPOST1          0x52
+#define FX2CMD_FWPOST1          0x52u
 
-#define FX2CMD_POWER_OFF        0xdc
-#define FX2CMD_POWER_ON         0xde
+#define FX2CMD_POWER_OFF        0xdcu
+#define FX2CMD_POWER_ON         0xdeu
 
-#define FX2CMD_DEEP_RESET       0xdd
+#define FX2CMD_DEEP_RESET       0xddu
 
-#define FX2CMD_GET_EEPROM_ADDR  0xeb
-#define FX2CMD_GET_IR_CODE      0xec
+#define FX2CMD_GET_EEPROM_ADDR  0xebu
+#define FX2CMD_GET_IR_CODE      0xecu
+
+#define FX2CMD_HCW_DEMOD_RESETIN       0xf0u
+#define FX2CMD_HCW_DTV_STREAMING_ON    0xf1u
+#define FX2CMD_HCW_DTV_STREAMING_OFF   0xf2u
+
+#define FX2CMD_ONAIR_DTV_STREAMING_ON  0xa0u
+#define FX2CMD_ONAIR_DTV_STREAMING_OFF 0xa1u
+#define FX2CMD_ONAIR_DTV_POWER_ON      0xa2u
+#define FX2CMD_ONAIR_DTV_POWER_OFF     0xa3u
 
 #endif /* _PVRUSB2_FX2_CMD_H_ */
 
index d7a216b41b7235b14bcd364ef82dc3c946a2b97b..a3fe251d6fd912eeaefc9f07157b702074d67abd 100644 (file)
@@ -163,6 +163,11 @@ struct pvr2_decoder_ctrl {
 #define FW1_STATE_RELOAD 3
 #define FW1_STATE_OK 4
 
+/* What state the device is in if it is a hybrid */
+#define PVR2_PATHWAY_UNKNOWN 0
+#define PVR2_PATHWAY_ANALOG 1
+#define PVR2_PATHWAY_DIGITAL 2
+
 typedef int (*pvr2_i2c_func)(struct pvr2_hdw *,u8,u8 *,u16,u8 *, u16);
 #define PVR2_I2C_FUNC_CNT 128
 
@@ -182,7 +187,6 @@ struct pvr2_hdw {
        struct workqueue_struct *workqueue;
        struct work_struct workpoll;     /* Update driver state */
        struct work_struct worki2csync;  /* Update i2c clients */
-       struct work_struct workinit;     /* Driver initialization sequence */
 
        /* Video spigot */
        struct pvr2_stream *vid_stream;
@@ -229,17 +233,19 @@ struct pvr2_hdw {
 
        /* Bits of state that describe what is going on with various parts
           of the driver. */
+       int state_pathway_ok;         /* Pathway config is ok */
        int state_encoder_ok;         /* Encoder is operational */
        int state_encoder_run;        /* Encoder is running */
        int state_encoder_config;     /* Encoder is configured */
        int state_encoder_waitok;     /* Encoder pre-wait done */
+       int state_encoder_runok;      /* Encoder has run for >= .25 sec */
        int state_decoder_run;        /* Decoder is running */
        int state_usbstream_run;      /* FX2 is streaming */
        int state_decoder_quiescent;  /* Decoder idle for > 50msec */
        int state_pipeline_config;    /* Pipeline is configured */
-       int state_pipeline_req;                /* Somebody wants to stream */
-       int state_pipeline_pause;              /* Pipeline must be paused */
-       int state_pipeline_idle;               /* Pipeline not running */
+       int state_pipeline_req;       /* Somebody wants to stream */
+       int state_pipeline_pause;     /* Pipeline must be paused */
+       int state_pipeline_idle;      /* Pipeline not running */
 
        /* This is the master state of the driver.  It is the combined
           result of other bits of state.  Examining this will indicate the
@@ -247,6 +253,9 @@ struct pvr2_hdw {
           PVR2_STATE_xxxx */
        unsigned int master_state;
 
+       /* True if device led is currently on */
+       int led_on;
+
        /* True if states must be re-evaluated */
        int state_stale;
 
@@ -259,6 +268,9 @@ struct pvr2_hdw {
        /* Timer for measuring encoder pre-wait time */
        struct timer_list encoder_wait_timer;
 
+       /* Timer for measuring encoder minimum run time */
+       struct timer_list encoder_run_timer;
+
        /* Place to block while waiting for state changes */
        wait_queue_head_t state_wait_data;
 
@@ -267,6 +279,7 @@ struct pvr2_hdw {
        int flag_disconnected;  /* flag_ok == 0 due to disconnect */
        int flag_init_ok;       /* true if structure is fully initialized */
        int fw1_state;          /* current situation with fw1 */
+       int pathway_state;      /* one of PVR2_PATHWAY_xxx */
        int flag_decoder_missed;/* We've noticed missing decoder */
        int flag_tripped;       /* Indicates overall failure to start */
 
@@ -323,6 +336,11 @@ struct pvr2_hdw {
        int v4l_minor_number_vbi;
        int v4l_minor_number_radio;
 
+       /* Bit mask of PVR2_CVAL_INPUT choices which are valid for the hardware */
+       unsigned int input_avail_mask;
+       /* Bit mask of PVR2_CVAL_INPUT choices which are currenly allowed */
+       unsigned int input_allowed_mask;
+
        /* Location of eeprom or a negative number if none */
        int eeprom_addr;
 
index 2404053a4d8585b5eda3f4822d9ad816e3c3f90a..0a868888f389d2e74004051558511b90a8dd2b88 100644 (file)
 static struct pvr2_hdw *unit_pointers[PVR_NUM] = {[ 0 ... PVR_NUM-1 ] = NULL};
 static DEFINE_MUTEX(pvr2_unit_mtx);
 
-static int ctlchg = 0;
+static int ctlchg;
 static int initusbreset = 1;
-static int procreload = 0;
+static int procreload;
 static int tuner[PVR_NUM] = { [0 ... PVR_NUM-1] = -1 };
 static int tolerance[PVR_NUM] = { [0 ... PVR_NUM-1] = 0 };
 static int video_std[PVR_NUM] = { [0 ... PVR_NUM-1] = 0 };
-static int init_pause_msec = 0;
+static int init_pause_msec;
 
 module_param(ctlchg, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(ctlchg, "0=optimize ctl change 1=always accept new ctl value");
@@ -182,6 +182,7 @@ static const char *control_values_srate[] = {
 
 static const char *control_values_input[] = {
        [PVR2_CVAL_INPUT_TV]        = "television",  /*xawtv needs this name*/
+       [PVR2_CVAL_INPUT_DTV]       = "dtv",
        [PVR2_CVAL_INPUT_RADIO]     = "radio",
        [PVR2_CVAL_INPUT_SVIDEO]    = "s-video",
        [PVR2_CVAL_INPUT_COMPOSITE] = "composite",
@@ -215,12 +216,45 @@ static const char *pvr2_state_names[] = {
 };
 
 
+struct pvr2_fx2cmd_descdef {
+       unsigned char id;
+       unsigned char *desc;
+};
+
+static const struct pvr2_fx2cmd_descdef pvr2_fx2cmd_desc[] = {
+       {FX2CMD_MEM_WRITE_DWORD, "write encoder dword"},
+       {FX2CMD_MEM_READ_DWORD, "read encoder dword"},
+       {FX2CMD_MEM_READ_64BYTES, "read encoder 64bytes"},
+       {FX2CMD_REG_WRITE, "write encoder register"},
+       {FX2CMD_REG_READ, "read encoder register"},
+       {FX2CMD_MEMSEL, "encoder memsel"},
+       {FX2CMD_I2C_WRITE, "i2c write"},
+       {FX2CMD_I2C_READ, "i2c read"},
+       {FX2CMD_GET_USB_SPEED, "get USB speed"},
+       {FX2CMD_STREAMING_ON, "stream on"},
+       {FX2CMD_STREAMING_OFF, "stream off"},
+       {FX2CMD_FWPOST1, "fwpost1"},
+       {FX2CMD_POWER_OFF, "power off"},
+       {FX2CMD_POWER_ON, "power on"},
+       {FX2CMD_DEEP_RESET, "deep reset"},
+       {FX2CMD_GET_EEPROM_ADDR, "get rom addr"},
+       {FX2CMD_GET_IR_CODE, "get IR code"},
+       {FX2CMD_HCW_DEMOD_RESETIN, "hcw demod resetin"},
+       {FX2CMD_HCW_DTV_STREAMING_ON, "hcw dtv stream on"},
+       {FX2CMD_HCW_DTV_STREAMING_OFF, "hcw dtv stream off"},
+       {FX2CMD_ONAIR_DTV_STREAMING_ON, "onair dtv stream on"},
+       {FX2CMD_ONAIR_DTV_STREAMING_OFF, "onair dtv stream off"},
+       {FX2CMD_ONAIR_DTV_POWER_ON, "onair dtv power on"},
+       {FX2CMD_ONAIR_DTV_POWER_OFF, "onair dtv power off"},
+};
+
+
+static int pvr2_hdw_set_input(struct pvr2_hdw *hdw,int v);
 static void pvr2_hdw_state_sched(struct pvr2_hdw *);
 static int pvr2_hdw_state_eval(struct pvr2_hdw *);
 static void pvr2_hdw_set_cur_freq(struct pvr2_hdw *,unsigned long);
 static void pvr2_hdw_worker_i2c(struct work_struct *work);
 static void pvr2_hdw_worker_poll(struct work_struct *work);
-static void pvr2_hdw_worker_init(struct work_struct *work);
 static int pvr2_hdw_wait(struct pvr2_hdw *,int state);
 static int pvr2_hdw_untrip_unlocked(struct pvr2_hdw *);
 static void pvr2_hdw_state_log_state(struct pvr2_hdw *);
@@ -231,6 +265,8 @@ static void pvr2_hdw_internal_find_stdenum(struct pvr2_hdw *hdw);
 static void pvr2_hdw_internal_set_std_avail(struct pvr2_hdw *hdw);
 static void pvr2_hdw_quiescent_timeout(unsigned long);
 static void pvr2_hdw_encoder_wait_timeout(unsigned long);
+static void pvr2_hdw_encoder_run_timeout(unsigned long);
+static int pvr2_issue_simple_cmd(struct pvr2_hdw *,u32);
 static int pvr2_send_request_ex(struct pvr2_hdw *hdw,
                                unsigned int timeout,int probe_fl,
                                void *write_data,unsigned int write_len,
@@ -367,26 +403,14 @@ static int ctrl_get_input(struct pvr2_ctrl *cptr,int *vp)
        return 0;
 }
 
-static int ctrl_set_input(struct pvr2_ctrl *cptr,int m,int v)
+static int ctrl_check_input(struct pvr2_ctrl *cptr,int v)
 {
-       struct pvr2_hdw *hdw = cptr->hdw;
-
-       if (hdw->input_val != v) {
-               hdw->input_val = v;
-               hdw->input_dirty = !0;
-       }
+       return ((1 << v) & cptr->hdw->input_allowed_mask) != 0;
+}
 
-       /* Handle side effects - if we switch to a mode that needs the RF
-          tuner, then select the right frequency choice as well and mark
-          it dirty. */
-       if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
-               hdw->freqSelector = 0;
-               hdw->freqDirty = !0;
-       } else if (hdw->input_val == PVR2_CVAL_INPUT_TV) {
-               hdw->freqSelector = 1;
-               hdw->freqDirty = !0;
-       }
-       return 0;
+static int ctrl_set_input(struct pvr2_ctrl *cptr,int m,int v)
+{
+       return pvr2_hdw_set_input(cptr->hdw,v);
 }
 
 static int ctrl_isdirty_input(struct pvr2_ctrl *cptr)
@@ -803,6 +827,7 @@ static const struct pvr2_ctl_info control_defs[] = {
                .name = "input",
                .internal_id = PVR2_CID_INPUT,
                .default_value = PVR2_CVAL_INPUT_TV,
+               .check_value = ctrl_check_input,
                DEFREF(input),
                DEFENUM(control_values_input),
        },{
@@ -982,7 +1007,7 @@ unsigned long pvr2_hdw_get_cur_freq(struct pvr2_hdw *hdw)
 
 /* Set the currently tuned frequency and account for all possible
    driver-core side effects of this action. */
-void pvr2_hdw_set_cur_freq(struct pvr2_hdw *hdw,unsigned long val)
+static void pvr2_hdw_set_cur_freq(struct pvr2_hdw *hdw,unsigned long val)
 {
        if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
                if (hdw->freqSelector) {
@@ -1195,6 +1220,14 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
           time we configure the encoder, then we'll fully configure it. */
        hdw->enc_cur_valid = 0;
 
+       /* Encoder is about to be reset so note that as far as we're
+          concerned now, the encoder has never been run. */
+       del_timer_sync(&hdw->encoder_run_timer);
+       if (hdw->state_encoder_runok) {
+               hdw->state_encoder_runok = 0;
+               trace_stbit("state_encoder_runok",hdw->state_encoder_runok);
+       }
+
        /* First prepare firmware loading */
        ret |= pvr2_write_register(hdw, 0x0048, 0xffffffff); /*interrupt mask*/
        ret |= pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000088); /*gpio dir*/
@@ -1212,19 +1245,14 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
        ret |= pvr2_write_register(hdw, 0xaa04, 0x00057810); /*unknown*/
        ret |= pvr2_write_register(hdw, 0xaa10, 0x00148500); /*unknown*/
        ret |= pvr2_write_register(hdw, 0xaa18, 0x00840000); /*unknown*/
-       LOCK_TAKE(hdw->ctl_lock); do {
-               hdw->cmd_buffer[0] = FX2CMD_FWPOST1;
-               ret |= pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0);
-               hdw->cmd_buffer[0] = FX2CMD_MEMSEL;
-               hdw->cmd_buffer[1] = 0;
-               ret |= pvr2_send_request(hdw,hdw->cmd_buffer,2,NULL,0);
-       } while (0); LOCK_GIVE(hdw->ctl_lock);
+       ret |= pvr2_issue_simple_cmd(hdw,FX2CMD_FWPOST1);
+       ret |= pvr2_issue_simple_cmd(hdw,FX2CMD_MEMSEL | (1 << 8) | (0 << 16));
 
        if (ret) {
                pvr2_trace(PVR2_TRACE_ERROR_LEGS,
                           "firmware2 upload prep failed, ret=%d",ret);
                release_firmware(fw_entry);
-               return ret;
+               goto done;
        }
 
        /* Now send firmware */
@@ -1237,7 +1265,8 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
                           " must be a multiple of %zu bytes",
                           fw_files[fwidx],sizeof(u32));
                release_firmware(fw_entry);
-               return -1;
+               ret = -EINVAL;
+               goto done;
        }
 
        fw_ptr = kmalloc(FIRMWARE_CHUNK_SIZE, GFP_KERNEL);
@@ -1245,7 +1274,8 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
                release_firmware(fw_entry);
                pvr2_trace(PVR2_TRACE_ERROR_LEGS,
                           "failed to allocate memory for firmware2 upload");
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto done;
        }
 
        pipe = usb_sndbulkpipe(hdw->usb_dev, PVR2_FIRMWARE_ENDPOINT);
@@ -1276,23 +1306,27 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
        if (ret) {
                pvr2_trace(PVR2_TRACE_ERROR_LEGS,
                           "firmware2 upload transfer failure");
-               return ret;
+               goto done;
        }
 
        /* Finish upload */
 
        ret |= pvr2_write_register(hdw, 0x9054, 0xffffffff); /*reset hw blocks*/
        ret |= pvr2_write_register(hdw, 0x9058, 0xffffffe8); /*VPU ctrl*/
-       LOCK_TAKE(hdw->ctl_lock); do {
-               hdw->cmd_buffer[0] = FX2CMD_MEMSEL;
-               hdw->cmd_buffer[1] = 0;
-               ret |= pvr2_send_request(hdw,hdw->cmd_buffer,2,NULL,0);
-       } while (0); LOCK_GIVE(hdw->ctl_lock);
+       ret |= pvr2_issue_simple_cmd(hdw,FX2CMD_MEMSEL | (1 << 8) | (0 << 16));
 
        if (ret) {
                pvr2_trace(PVR2_TRACE_ERROR_LEGS,
                           "firmware2 upload post-proc failure");
        }
+
+ done:
+       if (hdw->hdw_desc->signal_routing_scheme ==
+           PVR2_ROUTING_SCHEME_GOTVIEW) {
+               /* Ensure that GPIO 11 is set to output for GOTVIEW
+                  hardware. */
+               pvr2_hdw_gpio_chg_dir(hdw,(1 << 11),~0);
+       }
        return ret;
 }
 
@@ -1364,11 +1398,6 @@ int pvr2_hdw_untrip(struct pvr2_hdw *hdw)
 }
 
 
-const char *pvr2_hdw_get_state_name(unsigned int id)
-{
-       if (id >= ARRAY_SIZE(pvr2_state_names)) return NULL;
-       return pvr2_state_names[id];
-}
 
 
 int pvr2_hdw_get_streaming(struct pvr2_hdw *hdw)
@@ -1495,7 +1524,7 @@ struct pvr2_std_hack {
    default - which can always be overridden explicitly - and if the user
    has otherwise named a default then that default will always be used in
    place of this table. */
-const static struct pvr2_std_hack std_eeprom_maps[] = {
+static const struct pvr2_std_hack std_eeprom_maps[] = {
        {       /* PAL(B/G) */
                .pat = V4L2_STD_B|V4L2_STD_GH,
                .std = V4L2_STD_PAL_B|V4L2_STD_PAL_B1|V4L2_STD_PAL_G,
@@ -1712,6 +1741,13 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw)
 
        if (!pvr2_hdw_dev_ok(hdw)) return;
 
+       if (hdw->hdw_desc->signal_routing_scheme ==
+           PVR2_ROUTING_SCHEME_GOTVIEW) {
+               /* Ensure that GPIO 11 is set to output for GOTVIEW
+                  hardware. */
+               pvr2_hdw_gpio_chg_dir(hdw,(1 << 11),~0);
+       }
+
        pvr2_hdw_commit_setup(hdw);
 
        hdw->vid_stream = pvr2_stream_create();
@@ -1805,12 +1841,37 @@ static void pvr2_hdw_setup(struct pvr2_hdw *hdw)
 }
 
 
-/* Create and return a structure for interacting with the underlying
-   hardware */
+/* Perform second stage initialization.  Set callback pointer first so that
+   we can avoid a possible initialization race (if the kernel thread runs
+   before the callback has been set). */
+int pvr2_hdw_initialize(struct pvr2_hdw *hdw,
+                       void (*callback_func)(void *),
+                       void *callback_data)
+{
+       LOCK_TAKE(hdw->big_lock); do {
+               if (hdw->flag_disconnected) {
+                       /* Handle a race here: If we're already
+                          disconnected by this point, then give up.  If we
+                          get past this then we'll remain connected for
+                          the duration of initialization since the entire
+                          initialization sequence is now protected by the
+                          big_lock. */
+                       break;
+               }
+               hdw->state_data = callback_data;
+               hdw->state_func = callback_func;
+               pvr2_hdw_setup(hdw);
+       } while (0); LOCK_GIVE(hdw->big_lock);
+       return hdw->flag_init_ok;
+}
+
+
+/* Create, set up, and return a structure for interacting with the
+   underlying hardware.  */
 struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
                                 const struct usb_device_id *devid)
 {
-       unsigned int idx,cnt1,cnt2;
+       unsigned int idx,cnt1,cnt2,m;
        struct pvr2_hdw *hdw;
        int valid_std_mask;
        struct pvr2_ctrl *cptr;
@@ -1834,6 +1895,10 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
        hdw->encoder_wait_timer.data = (unsigned long)hdw;
        hdw->encoder_wait_timer.function = pvr2_hdw_encoder_wait_timeout;
 
+       init_timer(&hdw->encoder_run_timer);
+       hdw->encoder_run_timer.data = (unsigned long)hdw;
+       hdw->encoder_run_timer.function = pvr2_hdw_encoder_run_timeout;
+
        hdw->master_state = PVR2_STATE_DEAD;
 
        init_waitqueue_head(&hdw->state_wait_data);
@@ -1841,6 +1906,26 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
        hdw->tuner_signal_stale = !0;
        cx2341x_fill_defaults(&hdw->enc_ctl_state);
 
+       /* Calculate which inputs are OK */
+       m = 0;
+       if (hdw_desc->flag_has_analogtuner) m |= 1 << PVR2_CVAL_INPUT_TV;
+       if (hdw_desc->digital_control_scheme != PVR2_DIGITAL_SCHEME_NONE) {
+               m |= 1 << PVR2_CVAL_INPUT_DTV;
+       }
+       if (hdw_desc->flag_has_svideo) m |= 1 << PVR2_CVAL_INPUT_SVIDEO;
+       if (hdw_desc->flag_has_composite) m |= 1 << PVR2_CVAL_INPUT_COMPOSITE;
+       if (hdw_desc->flag_has_fmradio) m |= 1 << PVR2_CVAL_INPUT_RADIO;
+       hdw->input_avail_mask = m;
+       hdw->input_allowed_mask = hdw->input_avail_mask;
+
+       /* If not a hybrid device, pathway_state never changes.  So
+          initialize it here to what it should forever be. */
+       if (!(hdw->input_avail_mask & (1 << PVR2_CVAL_INPUT_DTV))) {
+               hdw->pathway_state = PVR2_PATHWAY_ANALOG;
+       } else if (!(hdw->input_avail_mask & (1 << PVR2_CVAL_INPUT_TV))) {
+               hdw->pathway_state = PVR2_PATHWAY_DIGITAL;
+       }
+
        hdw->control_cnt = CTRLDEF_COUNT;
        hdw->control_cnt += MPEGDEF_COUNT;
        hdw->controls = kzalloc(sizeof(struct pvr2_ctrl) * hdw->control_cnt,
@@ -1858,6 +1943,15 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
                cptr = hdw->controls + idx;
                cptr->info = control_defs+idx;
        }
+
+       /* Ensure that default input choice is a valid one. */
+       m = hdw->input_avail_mask;
+       if (m) for (idx = 0; idx < (sizeof(m) << 3); idx++) {
+               if (!((1 << idx) & m)) continue;
+               hdw->input_val = idx;
+               break;
+       }
+
        /* Define and configure additional controls from cx2341x module. */
        hdw->mpeg_ctrl_info = kzalloc(
                sizeof(*(hdw->mpeg_ctrl_info)) * MPEGDEF_COUNT, GFP_KERNEL);
@@ -1981,7 +2075,6 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
        hdw->workqueue = create_singlethread_workqueue(hdw->name);
        INIT_WORK(&hdw->workpoll,pvr2_hdw_worker_poll);
        INIT_WORK(&hdw->worki2csync,pvr2_hdw_worker_i2c);
-       INIT_WORK(&hdw->workinit,pvr2_hdw_worker_init);
 
        pvr2_trace(PVR2_TRACE_INIT,"Driver unit number is %d, name is %s",
                   hdw->unit_number,hdw->name);
@@ -2003,11 +2096,11 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
        mutex_init(&hdw->ctl_lock_mutex);
        mutex_init(&hdw->big_lock_mutex);
 
-       queue_work(hdw->workqueue,&hdw->workinit);
        return hdw;
  fail:
        if (hdw) {
                del_timer_sync(&hdw->quiescent_timer);
+               del_timer_sync(&hdw->encoder_run_timer);
                del_timer_sync(&hdw->encoder_wait_timer);
                if (hdw->workqueue) {
                        flush_workqueue(hdw->workqueue);
@@ -2064,13 +2157,14 @@ void pvr2_hdw_destroy(struct pvr2_hdw *hdw)
 {
        if (!hdw) return;
        pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_destroy: hdw=%p",hdw);
-       del_timer_sync(&hdw->quiescent_timer);
-       del_timer_sync(&hdw->encoder_wait_timer);
        if (hdw->workqueue) {
                flush_workqueue(hdw->workqueue);
                destroy_workqueue(hdw->workqueue);
                hdw->workqueue = NULL;
        }
+       del_timer_sync(&hdw->quiescent_timer);
+       del_timer_sync(&hdw->encoder_run_timer);
+       del_timer_sync(&hdw->encoder_wait_timer);
        if (hdw->fw_buffer) {
                kfree(hdw->fw_buffer);
                hdw->fw_buffer = NULL;
@@ -2352,6 +2446,18 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw)
                }
        }
 
+       if (hdw->input_dirty && hdw->state_pathway_ok &&
+           (((hdw->input_val == PVR2_CVAL_INPUT_DTV) ?
+             PVR2_PATHWAY_DIGITAL : PVR2_PATHWAY_ANALOG) !=
+            hdw->pathway_state)) {
+               /* Change of mode being asked for... */
+               hdw->state_pathway_ok = 0;
+               trace_stbit("state_pathway_ok",hdw->state_pathway_ok);
+       }
+       if (!hdw->state_pathway_ok) {
+               /* Can't commit anything until pathway is ok. */
+               return 0;
+       }
        /* If any of the below has changed, then we can't do the update
           while the pipeline is running.  Pipeline must be paused first
           and decoder -> encoder connection be made quiescent before we
@@ -2405,12 +2511,28 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw)
                hdw->active_stream_type = hdw->desired_stream_type;
        }
 
+       if (hdw->hdw_desc->signal_routing_scheme ==
+           PVR2_ROUTING_SCHEME_GOTVIEW) {
+               u32 b;
+               /* Handle GOTVIEW audio switching */
+               pvr2_hdw_gpio_get_out(hdw,&b);
+               if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
+                       /* Set GPIO 11 */
+                       pvr2_hdw_gpio_chg_out(hdw,(1 << 11),~0);
+               } else {
+                       /* Clear GPIO 11 */
+                       pvr2_hdw_gpio_chg_out(hdw,(1 << 11),0);
+               }
+       }
+
        /* Now execute i2c core update */
        pvr2_i2c_core_sync(hdw);
 
-       if (hdw->state_encoder_run) {
-               /* If encoder isn't running, then this will get worked out
-                  later when we start the encoder. */
+       if ((hdw->pathway_state == PVR2_PATHWAY_ANALOG) &&
+           hdw->state_encoder_run) {
+               /* If encoder isn't running or it can't be touched, then
+                  this will get worked out later when we start the
+                  encoder. */
                if (pvr2_encoder_adjust(hdw) < 0) return !0;
        }
 
@@ -2453,15 +2575,6 @@ static void pvr2_hdw_worker_poll(struct work_struct *work)
 }
 
 
-static void pvr2_hdw_worker_init(struct work_struct *work)
-{
-       struct pvr2_hdw *hdw = container_of(work,struct pvr2_hdw,workinit);
-       LOCK_TAKE(hdw->big_lock); do {
-               pvr2_hdw_setup(hdw);
-       } while (0); LOCK_GIVE(hdw->big_lock);
-}
-
-
 static int pvr2_hdw_wait(struct pvr2_hdw *hdw,int state)
 {
        return wait_event_interruptible(
@@ -2471,17 +2584,6 @@ static int pvr2_hdw_wait(struct pvr2_hdw *hdw,int state)
 }
 
 
-void pvr2_hdw_set_state_callback(struct pvr2_hdw *hdw,
-                                void (*callback_func)(void *),
-                                void *callback_data)
-{
-       LOCK_TAKE(hdw->big_lock); do {
-               hdw->state_data = callback_data;
-               hdw->state_func = callback_func;
-       } while (0); LOCK_GIVE(hdw->big_lock);
-}
-
-
 /* Return name for this driver instance */
 const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *hdw)
 {
@@ -3050,6 +3152,67 @@ int pvr2_send_request(struct pvr2_hdw *hdw,
                                    read_data,read_len);
 }
 
+
+static int pvr2_issue_simple_cmd(struct pvr2_hdw *hdw,u32 cmdcode)
+{
+       int ret;
+       unsigned int cnt = 1;
+       unsigned int args = 0;
+       LOCK_TAKE(hdw->ctl_lock);
+       hdw->cmd_buffer[0] = cmdcode & 0xffu;
+       args = (cmdcode >> 8) & 0xffu;
+       args = (args > 2) ? 2 : args;
+       if (args) {
+               cnt += args;
+               hdw->cmd_buffer[1] = (cmdcode >> 16) & 0xffu;
+               if (args > 1) {
+                       hdw->cmd_buffer[2] = (cmdcode >> 24) & 0xffu;
+               }
+       }
+       if (pvrusb2_debug & PVR2_TRACE_INIT) {
+               unsigned int idx;
+               unsigned int ccnt,bcnt;
+               char tbuf[50];
+               cmdcode &= 0xffu;
+               bcnt = 0;
+               ccnt = scnprintf(tbuf+bcnt,
+                                sizeof(tbuf)-bcnt,
+                                "Sending FX2 command 0x%x",cmdcode);
+               bcnt += ccnt;
+               for (idx = 0; idx < ARRAY_SIZE(pvr2_fx2cmd_desc); idx++) {
+                       if (pvr2_fx2cmd_desc[idx].id == cmdcode) {
+                               ccnt = scnprintf(tbuf+bcnt,
+                                                sizeof(tbuf)-bcnt,
+                                                " \"%s\"",
+                                                pvr2_fx2cmd_desc[idx].desc);
+                               bcnt += ccnt;
+                               break;
+                       }
+               }
+               if (args) {
+                       ccnt = scnprintf(tbuf+bcnt,
+                                        sizeof(tbuf)-bcnt,
+                                        " (%u",hdw->cmd_buffer[1]);
+                       bcnt += ccnt;
+                       if (args > 1) {
+                               ccnt = scnprintf(tbuf+bcnt,
+                                                sizeof(tbuf)-bcnt,
+                                                ",%u",hdw->cmd_buffer[2]);
+                               bcnt += ccnt;
+                       }
+                       ccnt = scnprintf(tbuf+bcnt,
+                                        sizeof(tbuf)-bcnt,
+                                        ")");
+                       bcnt += ccnt;
+               }
+               pvr2_trace(PVR2_TRACE_INIT,"%.*s",bcnt,tbuf);
+       }
+       ret = pvr2_send_request(hdw,hdw->cmd_buffer,cnt,NULL,0);
+       LOCK_GIVE(hdw->ctl_lock);
+       return ret;
+}
+
+
 int pvr2_write_register(struct pvr2_hdw *hdw, u16 reg, u32 data)
 {
        int ret;
@@ -3157,25 +3320,19 @@ void pvr2_hdw_cpureset_assert(struct pvr2_hdw *hdw,int val)
 
 int pvr2_hdw_cmd_deep_reset(struct pvr2_hdw *hdw)
 {
-       int status;
-       LOCK_TAKE(hdw->ctl_lock); do {
-               pvr2_trace(PVR2_TRACE_INIT,"Requesting uproc hard reset");
-               hdw->cmd_buffer[0] = FX2CMD_DEEP_RESET;
-               status = pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0);
-       } while (0); LOCK_GIVE(hdw->ctl_lock);
-       return status;
+       return pvr2_issue_simple_cmd(hdw,FX2CMD_DEEP_RESET);
 }
 
 
 int pvr2_hdw_cmd_powerup(struct pvr2_hdw *hdw)
 {
-       int status;
-       LOCK_TAKE(hdw->ctl_lock); do {
-               pvr2_trace(PVR2_TRACE_INIT,"Requesting powerup");
-               hdw->cmd_buffer[0] = FX2CMD_POWER_ON;
-               status = pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0);
-       } while (0); LOCK_GIVE(hdw->ctl_lock);
-       return status;
+       return pvr2_issue_simple_cmd(hdw,FX2CMD_POWER_ON);
+}
+
+
+int pvr2_hdw_cmd_powerdown(struct pvr2_hdw *hdw)
+{
+       return pvr2_issue_simple_cmd(hdw,FX2CMD_POWER_OFF);
 }
 
 
@@ -3200,16 +3357,173 @@ int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *hdw)
 }
 
 
+static int pvr2_hdw_cmd_hcw_demod_reset(struct pvr2_hdw *hdw, int onoff)
+{
+       hdw->flag_ok = !0;
+       return pvr2_issue_simple_cmd(hdw,
+                                    FX2CMD_HCW_DEMOD_RESETIN |
+                                    (1 << 8) |
+                                    ((onoff ? 1 : 0) << 16));
+}
+
+
+static int pvr2_hdw_cmd_onair_fe_power_ctrl(struct pvr2_hdw *hdw, int onoff)
+{
+       hdw->flag_ok = !0;
+       return pvr2_issue_simple_cmd(hdw,(onoff ?
+                                         FX2CMD_ONAIR_DTV_POWER_ON :
+                                         FX2CMD_ONAIR_DTV_POWER_OFF));
+}
+
+
+static int pvr2_hdw_cmd_onair_digital_path_ctrl(struct pvr2_hdw *hdw,
+                                               int onoff)
+{
+       return pvr2_issue_simple_cmd(hdw,(onoff ?
+                                         FX2CMD_ONAIR_DTV_STREAMING_ON :
+                                         FX2CMD_ONAIR_DTV_STREAMING_OFF));
+}
+
+
+static void pvr2_hdw_cmd_modeswitch(struct pvr2_hdw *hdw,int digitalFl)
+{
+       int cmode;
+       /* Compare digital/analog desired setting with current setting.  If
+          they don't match, fix it... */
+       cmode = (digitalFl ? PVR2_PATHWAY_DIGITAL : PVR2_PATHWAY_ANALOG);
+       if (cmode == hdw->pathway_state) {
+               /* They match; nothing to do */
+               return;
+       }
+
+       switch (hdw->hdw_desc->digital_control_scheme) {
+       case PVR2_DIGITAL_SCHEME_HAUPPAUGE:
+               pvr2_hdw_cmd_hcw_demod_reset(hdw,digitalFl);
+               if (cmode == PVR2_PATHWAY_ANALOG) {
+                       /* If moving to analog mode, also force the decoder
+                          to reset.  If no decoder is attached, then it's
+                          ok to ignore this because if/when the decoder
+                          attaches, it will reset itself at that time. */
+                       pvr2_hdw_cmd_decoder_reset(hdw);
+               }
+               break;
+       case PVR2_DIGITAL_SCHEME_ONAIR:
+               /* Supposedly we should always have the power on whether in
+                  digital or analog mode.  But for now do what appears to
+                  work... */
+               pvr2_hdw_cmd_onair_fe_power_ctrl(hdw,digitalFl);
+               break;
+       default: break;
+       }
+
+       pvr2_hdw_untrip_unlocked(hdw);
+       hdw->pathway_state = cmode;
+}
+
+
+void pvr2_led_ctrl_hauppauge(struct pvr2_hdw *hdw, int onoff)
+{
+       /* change some GPIO data
+        *
+        * note: bit d7 of dir appears to control the LED,
+        * so we shut it off here.
+        *
+        */
+       if (onoff) {
+               pvr2_hdw_gpio_chg_dir(hdw, 0xffffffff, 0x00000481);
+       } else {
+               pvr2_hdw_gpio_chg_dir(hdw, 0xffffffff, 0x00000401);
+       }
+       pvr2_hdw_gpio_chg_out(hdw, 0xffffffff, 0x00000000);
+}
+
+
+typedef void (*led_method_func)(struct pvr2_hdw *,int);
+
+static led_method_func led_methods[] = {
+       [PVR2_LED_SCHEME_HAUPPAUGE] = pvr2_led_ctrl_hauppauge,
+};
+
+
+/* Toggle LED */
+static void pvr2_led_ctrl(struct pvr2_hdw *hdw,int onoff)
+{
+       unsigned int scheme_id;
+       led_method_func fp;
+
+       if ((!onoff) == (!hdw->led_on)) return;
+
+       hdw->led_on = onoff != 0;
+
+       scheme_id = hdw->hdw_desc->led_scheme;
+       if (scheme_id < ARRAY_SIZE(led_methods)) {
+               fp = led_methods[scheme_id];
+       } else {
+               fp = NULL;
+       }
+
+       if (fp) (*fp)(hdw,onoff);
+}
+
+
 /* Stop / start video stream transport */
 static int pvr2_hdw_cmd_usbstream(struct pvr2_hdw *hdw,int runFl)
 {
-       int status;
-       LOCK_TAKE(hdw->ctl_lock); do {
-               hdw->cmd_buffer[0] =
-                       (runFl ? FX2CMD_STREAMING_ON : FX2CMD_STREAMING_OFF);
-               status = pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0);
-       } while (0); LOCK_GIVE(hdw->ctl_lock);
-       return status;
+       int ret;
+
+       /* If we're in analog mode, then just issue the usual analog
+          command. */
+       if (hdw->pathway_state == PVR2_PATHWAY_ANALOG) {
+               return pvr2_issue_simple_cmd(hdw,
+                                            (runFl ?
+                                             FX2CMD_STREAMING_ON :
+                                             FX2CMD_STREAMING_OFF));
+               /*Note: Not reached */
+       }
+
+       if (hdw->pathway_state != PVR2_PATHWAY_DIGITAL) {
+               /* Whoops, we don't know what mode we're in... */
+               return -EINVAL;
+       }
+
+       /* To get here we have to be in digital mode.  The mechanism here
+          is unfortunately different for different vendors.  So we switch
+          on the device's digital scheme attribute in order to figure out
+          what to do. */
+       switch (hdw->hdw_desc->digital_control_scheme) {
+       case PVR2_DIGITAL_SCHEME_HAUPPAUGE:
+               return pvr2_issue_simple_cmd(hdw,
+                                            (runFl ?
+                                             FX2CMD_HCW_DTV_STREAMING_ON :
+                                             FX2CMD_HCW_DTV_STREAMING_OFF));
+       case PVR2_DIGITAL_SCHEME_ONAIR:
+               ret = pvr2_issue_simple_cmd(hdw,
+                                           (runFl ?
+                                            FX2CMD_STREAMING_ON :
+                                            FX2CMD_STREAMING_OFF));
+               if (ret) return ret;
+               return pvr2_hdw_cmd_onair_digital_path_ctrl(hdw,runFl);
+       default:
+               return -EINVAL;
+       }
+}
+
+
+/* Evaluate whether or not state_pathway_ok can change */
+static int state_eval_pathway_ok(struct pvr2_hdw *hdw)
+{
+       if (hdw->state_pathway_ok) {
+               /* Nothing to do if pathway is already ok */
+               return 0;
+       }
+       if (!hdw->state_pipeline_idle) {
+               /* Not allowed to change anything if pipeline is not idle */
+               return 0;
+       }
+       pvr2_hdw_cmd_modeswitch(hdw,hdw->input_val == PVR2_CVAL_INPUT_DTV);
+       hdw->state_pathway_ok = !0;
+       trace_stbit("state_pathway_ok",hdw->state_pathway_ok);
+       return !0;
 }
 
 
@@ -3222,6 +3536,12 @@ static int state_eval_encoder_ok(struct pvr2_hdw *hdw)
        if (hdw->state_encoder_config) return 0;
        if (hdw->state_decoder_run) return 0;
        if (hdw->state_usbstream_run) return 0;
+       if (hdw->pathway_state == PVR2_PATHWAY_DIGITAL) {
+               if (!hdw->hdw_desc->flag_digital_requires_cx23416) return 0;
+       } else if (hdw->pathway_state != PVR2_PATHWAY_ANALOG) {
+               return 0;
+       }
+
        if (pvr2_upload_firmware2(hdw) < 0) {
                hdw->flag_tripped = !0;
                trace_stbit("flag_tripped",hdw->flag_tripped);
@@ -3247,7 +3567,9 @@ static int state_eval_encoder_config(struct pvr2_hdw *hdw)
                /* paranoia - solve race if timer just completed */
                del_timer_sync(&hdw->encoder_wait_timer);
        } else {
-               if (!hdw->state_encoder_ok ||
+               if (!hdw->state_pathway_ok ||
+                   (hdw->pathway_state != PVR2_PATHWAY_ANALOG) ||
+                   !hdw->state_encoder_ok ||
                    !hdw->state_pipeline_idle ||
                    hdw->state_pipeline_pause ||
                    !hdw->state_pipeline_req ||
@@ -3296,20 +3618,116 @@ static int state_eval_encoder_config(struct pvr2_hdw *hdw)
 }
 
 
+/* Return true if the encoder should not be running. */
+static int state_check_disable_encoder_run(struct pvr2_hdw *hdw)
+{
+       if (!hdw->state_encoder_ok) {
+               /* Encoder isn't healthy at the moment, so stop it. */
+               return !0;
+       }
+       if (!hdw->state_pathway_ok) {
+               /* Mode is not understood at the moment (i.e. it wants to
+                  change), so encoder must be stopped. */
+               return !0;
+       }
+
+       switch (hdw->pathway_state) {
+       case PVR2_PATHWAY_ANALOG:
+               if (!hdw->state_decoder_run) {
+                       /* We're in analog mode and the decoder is not
+                          running; thus the encoder should be stopped as
+                          well. */
+                       return !0;
+               }
+               break;
+       case PVR2_PATHWAY_DIGITAL:
+               if (hdw->state_encoder_runok) {
+                       /* This is a funny case.  We're in digital mode so
+                          really the encoder should be stopped.  However
+                          if it really is running, only kill it after
+                          runok has been set.  This gives a chance for the
+                          onair quirk to function (encoder must run
+                          briefly first, at least once, before onair
+                          digital streaming can work). */
+                       return !0;
+               }
+               break;
+       default:
+               /* Unknown mode; so encoder should be stopped. */
+               return !0;
+       }
+
+       /* If we get here, we haven't found a reason to stop the
+          encoder. */
+       return 0;
+}
+
+
+/* Return true if the encoder should be running. */
+static int state_check_enable_encoder_run(struct pvr2_hdw *hdw)
+{
+       if (!hdw->state_encoder_ok) {
+               /* Don't run the encoder if it isn't healthy... */
+               return 0;
+       }
+       if (!hdw->state_pathway_ok) {
+               /* Don't run the encoder if we don't (yet) know what mode
+                  we need to be in... */
+               return 0;
+       }
+
+       switch (hdw->pathway_state) {
+       case PVR2_PATHWAY_ANALOG:
+               if (hdw->state_decoder_run) {
+                       /* In analog mode, if the decoder is running, then
+                          run the encoder. */
+                       return !0;
+               }
+               break;
+       case PVR2_PATHWAY_DIGITAL:
+               if ((hdw->hdw_desc->digital_control_scheme ==
+                    PVR2_DIGITAL_SCHEME_ONAIR) &&
+                   !hdw->state_encoder_runok) {
+                       /* This is a quirk.  OnAir hardware won't stream
+                          digital until the encoder has been run at least
+                          once, for a minimal period of time (empiricially
+                          measured to be 1/4 second).  So if we're on
+                          OnAir hardware and the encoder has never been
+                          run at all, then start the encoder.  Normal
+                          state machine logic in the driver will
+                          automatically handle the remaining bits. */
+                       return !0;
+               }
+               break;
+       default:
+               /* For completeness (unknown mode; encoder won't run ever) */
+               break;
+       }
+       /* If we get here, then we haven't found any reason to run the
+          encoder, so don't run it. */
+       return 0;
+}
+
+
 /* Evaluate whether or not state_encoder_run can change */
 static int state_eval_encoder_run(struct pvr2_hdw *hdw)
 {
        if (hdw->state_encoder_run) {
+               if (!state_check_disable_encoder_run(hdw)) return 0;
                if (hdw->state_encoder_ok) {
-                       if (hdw->state_decoder_run) return 0;
+                       del_timer_sync(&hdw->encoder_run_timer);
                        if (pvr2_encoder_stop(hdw) < 0) return !0;
                }
                hdw->state_encoder_run = 0;
        } else {
-               if (!hdw->state_encoder_ok) return 0;
-               if (!hdw->state_decoder_run) return 0;
+               if (!state_check_enable_encoder_run(hdw)) return 0;
                if (pvr2_encoder_start(hdw) < 0) return !0;
                hdw->state_encoder_run = !0;
+               if (!hdw->state_encoder_runok) {
+                       hdw->encoder_run_timer.expires =
+                               jiffies + (HZ*250/1000);
+                       add_timer(&hdw->encoder_run_timer);
+               }
        }
        trace_stbit("state_encoder_run",hdw->state_encoder_run);
        return !0;
@@ -3338,13 +3756,27 @@ static void pvr2_hdw_encoder_wait_timeout(unsigned long data)
 }
 
 
+/* Timeout function for encoder run timer. */
+static void pvr2_hdw_encoder_run_timeout(unsigned long data)
+{
+       struct pvr2_hdw *hdw = (struct pvr2_hdw *)data;
+       if (!hdw->state_encoder_runok) {
+               hdw->state_encoder_runok = !0;
+               trace_stbit("state_encoder_runok",hdw->state_encoder_runok);
+               hdw->state_stale = !0;
+               queue_work(hdw->workqueue,&hdw->workpoll);
+       }
+}
+
+
 /* Evaluate whether or not state_decoder_run can change */
 static int state_eval_decoder_run(struct pvr2_hdw *hdw)
 {
        if (hdw->state_decoder_run) {
                if (hdw->state_encoder_ok) {
                        if (hdw->state_pipeline_req &&
-                           !hdw->state_pipeline_pause) return 0;
+                           !hdw->state_pipeline_pause &&
+                           hdw->state_pathway_ok) return 0;
                }
                if (!hdw->flag_decoder_missed) {
                        pvr2_decoder_enable(hdw,0);
@@ -3377,7 +3809,9 @@ static int state_eval_decoder_run(struct pvr2_hdw *hdw)
                           hopefully further stabilize the encoder. */
                        return 0;
                }
-               if (!hdw->state_pipeline_req ||
+               if (!hdw->state_pathway_ok ||
+                   (hdw->pathway_state != PVR2_PATHWAY_ANALOG) ||
+                   !hdw->state_pipeline_req ||
                    hdw->state_pipeline_pause ||
                    !hdw->state_pipeline_config ||
                    !hdw->state_encoder_config ||
@@ -3398,16 +3832,43 @@ static int state_eval_decoder_run(struct pvr2_hdw *hdw)
 static int state_eval_usbstream_run(struct pvr2_hdw *hdw)
 {
        if (hdw->state_usbstream_run) {
-               if (hdw->state_encoder_ok) {
-                       if (hdw->state_encoder_run) return 0;
+               int fl = !0;
+               if (hdw->pathway_state == PVR2_PATHWAY_ANALOG) {
+                       fl = (hdw->state_encoder_ok &&
+                             hdw->state_encoder_run);
+               } else if ((hdw->pathway_state == PVR2_PATHWAY_DIGITAL) &&
+                          (hdw->hdw_desc->flag_digital_requires_cx23416)) {
+                       fl = hdw->state_encoder_ok;
+               }
+               if (fl &&
+                   hdw->state_pipeline_req &&
+                   !hdw->state_pipeline_pause &&
+                   hdw->state_pathway_ok) {
+                       return 0;
                }
                pvr2_hdw_cmd_usbstream(hdw,0);
                hdw->state_usbstream_run = 0;
        } else {
-               if (!hdw->state_encoder_ok ||
-                   !hdw->state_encoder_run ||
-                   !hdw->state_pipeline_req ||
-                   hdw->state_pipeline_pause) return 0;
+               if (!hdw->state_pipeline_req ||
+                   hdw->state_pipeline_pause ||
+                   !hdw->state_pathway_ok) return 0;
+               if (hdw->pathway_state == PVR2_PATHWAY_ANALOG) {
+                       if (!hdw->state_encoder_ok ||
+                           !hdw->state_encoder_run) return 0;
+               } else if ((hdw->pathway_state == PVR2_PATHWAY_DIGITAL) &&
+                          (hdw->hdw_desc->flag_digital_requires_cx23416)) {
+                       if (!hdw->state_encoder_ok) return 0;
+                       if (hdw->state_encoder_run) return 0;
+                       if (hdw->hdw_desc->digital_control_scheme ==
+                           PVR2_DIGITAL_SCHEME_ONAIR) {
+                               /* OnAir digital receivers won't stream
+                                  unless the analog encoder has run first.
+                                  Why?  I have no idea.  But don't even
+                                  try until we know the analog side is
+                                  known to have run. */
+                               if (!hdw->state_encoder_runok) return 0;
+                       }
+               }
                if (pvr2_hdw_cmd_usbstream(hdw,!0) < 0) return 0;
                hdw->state_usbstream_run = !0;
        }
@@ -3453,7 +3914,8 @@ static int state_update_pipeline_state(struct pvr2_hdw *hdw)
 typedef int (*state_eval_func)(struct pvr2_hdw *);
 
 /* Set of functions to be run to evaluate various states in the driver. */
-const static state_eval_func eval_funcs[] = {
+static const state_eval_func eval_funcs[] = {
+       state_eval_pathway_ok,
        state_eval_pipeline_config,
        state_eval_encoder_ok,
        state_eval_encoder_config,
@@ -3501,6 +3963,34 @@ static int pvr2_hdw_state_update(struct pvr2_hdw *hdw)
 }
 
 
+static unsigned int print_input_mask(unsigned int msk,
+                                    char *buf,unsigned int acnt)
+{
+       unsigned int idx,ccnt;
+       unsigned int tcnt = 0;
+       for (idx = 0; idx < ARRAY_SIZE(control_values_input); idx++) {
+               if (!((1 << idx) & msk)) continue;
+               ccnt = scnprintf(buf+tcnt,
+                                acnt-tcnt,
+                                "%s%s",
+                                (tcnt ? ", " : ""),
+                                control_values_input[idx]);
+               tcnt += ccnt;
+       }
+       return tcnt;
+}
+
+
+static const char *pvr2_pathway_state_name(int id)
+{
+       switch (id) {
+       case PVR2_PATHWAY_ANALOG: return "analog";
+       case PVR2_PATHWAY_DIGITAL: return "digital";
+       default: return "unknown";
+       }
+}
+
+
 static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which,
                                             char *buf,unsigned int acnt)
 {
@@ -3508,13 +3998,15 @@ static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which,
        case 0:
                return scnprintf(
                        buf,acnt,
-                       "driver:%s%s%s%s%s",
+                       "driver:%s%s%s%s%s <mode=%s>",
                        (hdw->flag_ok ? " <ok>" : " <fail>"),
                        (hdw->flag_init_ok ? " <init>" : " <uninitialized>"),
                        (hdw->flag_disconnected ? " <disconnected>" :
                         " <connected>"),
                        (hdw->flag_tripped ? " <tripped>" : ""),
-                       (hdw->flag_decoder_missed ? " <no decoder>" : ""));
+                       (hdw->flag_decoder_missed ? " <no decoder>" : ""),
+                       pvr2_pathway_state_name(hdw->pathway_state));
+
        case 1:
                return scnprintf(
                        buf,acnt,
@@ -3527,7 +4019,7 @@ static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which,
        case 2:
                return scnprintf(
                        buf,acnt,
-                       "worker:%s%s%s%s%s%s",
+                       "worker:%s%s%s%s%s%s%s",
                        (hdw->state_decoder_run ?
                         " <decode:run>" :
                         (hdw->state_decoder_quiescent ?
@@ -3537,20 +4029,65 @@ static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which,
                        (hdw->state_encoder_ok ?
                         "" : " <encode:init>"),
                        (hdw->state_encoder_run ?
-                        " <encode:run>" : " <encode:stop>"),
+                        (hdw->state_encoder_runok ?
+                         " <encode:run>" :
+                         " <encode:firstrun>") :
+                        (hdw->state_encoder_runok ?
+                         " <encode:stop>" :
+                         " <encode:virgin>")),
                        (hdw->state_encoder_config ?
                         " <encode:configok>" :
                         (hdw->state_encoder_waitok ?
-                         "" : " <encode:wait>")),
+                         "" : " <encode:waitok>")),
                        (hdw->state_usbstream_run ?
-                        " <usb:run>" : " <usb:stop>"));
-               break;
+                        " <usb:run>" : " <usb:stop>"),
+                       (hdw->state_pathway_ok ?
+                        " <pathway:ok>" : ""));
        case 3:
                return scnprintf(
                        buf,acnt,
                        "state: %s",
                        pvr2_get_state_name(hdw->master_state));
-               break;
+       case 4: {
+               unsigned int tcnt = 0;
+               unsigned int ccnt;
+
+               ccnt = scnprintf(buf,
+                                acnt,
+                                "Hardware supported inputs: ");
+               tcnt += ccnt;
+               tcnt += print_input_mask(hdw->input_avail_mask,
+                                        buf+tcnt,
+                                        acnt-tcnt);
+               if (hdw->input_avail_mask != hdw->input_allowed_mask) {
+                       ccnt = scnprintf(buf+tcnt,
+                                        acnt-tcnt,
+                                        "; allowed inputs: ");
+                       tcnt += ccnt;
+                       tcnt += print_input_mask(hdw->input_allowed_mask,
+                                                buf+tcnt,
+                                                acnt-tcnt);
+               }
+               return tcnt;
+       }
+       case 5: {
+               struct pvr2_stream_stats stats;
+               if (!hdw->vid_stream) break;
+               pvr2_stream_get_stats(hdw->vid_stream,
+                                     &stats,
+                                     0);
+               return scnprintf(
+                       buf,acnt,
+                       "Bytes streamed=%u"
+                       " URBs: queued=%u idle=%u ready=%u"
+                       " processed=%u failed=%u",
+                       stats.bytes_processed,
+                       stats.buffers_in_queue,
+                       stats.buffers_in_idle,
+                       stats.buffers_in_ready,
+                       stats.buffers_processed,
+                       stats.buffers_failed);
+       }
        default: break;
        }
        return 0;
@@ -3596,6 +4133,7 @@ static int pvr2_hdw_state_eval(struct pvr2_hdw *hdw)
        unsigned int st;
        int state_updated = 0;
        int callback_flag = 0;
+       int analog_mode;
 
        pvr2_trace(PVR2_TRACE_STBITS,
                   "Drive state check START");
@@ -3606,18 +4144,23 @@ static int pvr2_hdw_state_eval(struct pvr2_hdw *hdw)
        /* Process all state and get back over disposition */
        state_updated = pvr2_hdw_state_update(hdw);
 
+       analog_mode = (hdw->pathway_state != PVR2_PATHWAY_DIGITAL);
+
        /* Update master state based upon all other states. */
        if (!hdw->flag_ok) {
                st = PVR2_STATE_DEAD;
        } else if (hdw->fw1_state != FW1_STATE_OK) {
                st = PVR2_STATE_COLD;
-       } else if (!hdw->state_encoder_ok) {
+       } else if ((analog_mode ||
+                   hdw->hdw_desc->flag_digital_requires_cx23416) &&
+                  !hdw->state_encoder_ok) {
                st = PVR2_STATE_WARM;
-       } else if (hdw->flag_tripped || hdw->flag_decoder_missed) {
+       } else if (hdw->flag_tripped ||
+                  (analog_mode && hdw->flag_decoder_missed)) {
                st = PVR2_STATE_ERROR;
-       } else if (hdw->state_encoder_run &&
-                  hdw->state_decoder_run &&
-                  hdw->state_usbstream_run) {
+       } else if (hdw->state_usbstream_run &&
+                  (!analog_mode ||
+                   (hdw->state_encoder_run && hdw->state_decoder_run))) {
                st = PVR2_STATE_RUN;
        } else {
                st = PVR2_STATE_READY;
@@ -3627,6 +4170,7 @@ static int pvr2_hdw_state_eval(struct pvr2_hdw *hdw)
                           "Device state change from %s to %s",
                           pvr2_get_state_name(hdw->master_state),
                           pvr2_get_state_name(st));
+               pvr2_led_ctrl(hdw,st == PVR2_STATE_RUN);
                hdw->master_state = st;
                state_updated = !0;
                callback_flag = !0;
@@ -3656,47 +4200,6 @@ static void pvr2_hdw_state_sched(struct pvr2_hdw *hdw)
 }
 
 
-void pvr2_hdw_get_debug_info_unlocked(const struct pvr2_hdw *hdw,
-                                     struct pvr2_hdw_debug_info *ptr)
-{
-       ptr->big_lock_held = hdw->big_lock_held;
-       ptr->ctl_lock_held = hdw->ctl_lock_held;
-       ptr->flag_disconnected = hdw->flag_disconnected;
-       ptr->flag_init_ok = hdw->flag_init_ok;
-       ptr->flag_ok = hdw->flag_ok;
-       ptr->fw1_state = hdw->fw1_state;
-       ptr->flag_decoder_missed = hdw->flag_decoder_missed;
-       ptr->flag_tripped = hdw->flag_tripped;
-       ptr->state_encoder_ok = hdw->state_encoder_ok;
-       ptr->state_encoder_run = hdw->state_encoder_run;
-       ptr->state_decoder_run = hdw->state_decoder_run;
-       ptr->state_usbstream_run = hdw->state_usbstream_run;
-       ptr->state_decoder_quiescent = hdw->state_decoder_quiescent;
-       ptr->state_pipeline_config = hdw->state_pipeline_config;
-       ptr->state_pipeline_req = hdw->state_pipeline_req;
-       ptr->state_pipeline_pause = hdw->state_pipeline_pause;
-       ptr->state_pipeline_idle = hdw->state_pipeline_idle;
-       ptr->cmd_debug_state = hdw->cmd_debug_state;
-       ptr->cmd_code = hdw->cmd_debug_code;
-       ptr->cmd_debug_write_len = hdw->cmd_debug_write_len;
-       ptr->cmd_debug_read_len = hdw->cmd_debug_read_len;
-       ptr->cmd_debug_timeout = hdw->ctl_timeout_flag;
-       ptr->cmd_debug_write_pend = hdw->ctl_write_pend_flag;
-       ptr->cmd_debug_read_pend = hdw->ctl_read_pend_flag;
-       ptr->cmd_debug_rstatus = hdw->ctl_read_urb->status;
-       ptr->cmd_debug_wstatus = hdw->ctl_read_urb->status;
-}
-
-
-void pvr2_hdw_get_debug_info_locked(struct pvr2_hdw *hdw,
-                                   struct pvr2_hdw_debug_info *ptr)
-{
-       LOCK_TAKE(hdw->ctl_lock); do {
-               pvr2_hdw_get_debug_info_unlocked(hdw,ptr);
-       } while(0); LOCK_GIVE(hdw->ctl_lock);
-}
-
-
 int pvr2_hdw_gpio_get_dir(struct pvr2_hdw *hdw,u32 *dp)
 {
        return pvr2_read_register(hdw,PVR2_GPIO_DIR,dp);
@@ -3756,6 +4259,80 @@ int pvr2_hdw_gpio_chg_out(struct pvr2_hdw *hdw,u32 msk,u32 val)
 }
 
 
+unsigned int pvr2_hdw_get_input_available(struct pvr2_hdw *hdw)
+{
+       return hdw->input_avail_mask;
+}
+
+
+unsigned int pvr2_hdw_get_input_allowed(struct pvr2_hdw *hdw)
+{
+       return hdw->input_allowed_mask;
+}
+
+
+static int pvr2_hdw_set_input(struct pvr2_hdw *hdw,int v)
+{
+       if (hdw->input_val != v) {
+               hdw->input_val = v;
+               hdw->input_dirty = !0;
+       }
+
+       /* Handle side effects - if we switch to a mode that needs the RF
+          tuner, then select the right frequency choice as well and mark
+          it dirty. */
+       if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
+               hdw->freqSelector = 0;
+               hdw->freqDirty = !0;
+       } else if ((hdw->input_val == PVR2_CVAL_INPUT_TV) ||
+                  (hdw->input_val == PVR2_CVAL_INPUT_DTV)) {
+               hdw->freqSelector = 1;
+               hdw->freqDirty = !0;
+       }
+       return 0;
+}
+
+
+int pvr2_hdw_set_input_allowed(struct pvr2_hdw *hdw,
+                              unsigned int change_mask,
+                              unsigned int change_val)
+{
+       int ret = 0;
+       unsigned int nv,m,idx;
+       LOCK_TAKE(hdw->big_lock);
+       do {
+               nv = hdw->input_allowed_mask & ~change_mask;
+               nv |= (change_val & change_mask);
+               nv &= hdw->input_avail_mask;
+               if (!nv) {
+                       /* No legal modes left; return error instead. */
+                       ret = -EPERM;
+                       break;
+               }
+               hdw->input_allowed_mask = nv;
+               if ((1 << hdw->input_val) & hdw->input_allowed_mask) {
+                       /* Current mode is still in the allowed mask, so
+                          we're done. */
+                       break;
+               }
+               /* Select and switch to a mode that is still in the allowed
+                  mask */
+               if (!hdw->input_allowed_mask) {
+                       /* Nothing legal; give up */
+                       break;
+               }
+               m = hdw->input_allowed_mask;
+               for (idx = 0; idx < (sizeof(m) << 3); idx++) {
+                       if (!((1 << idx) & m)) continue;
+                       pvr2_hdw_set_input(hdw,idx);
+                       break;
+               }
+       } while (0);
+       LOCK_GIVE(hdw->big_lock);
+       return ret;
+}
+
+
 /* Find I2C address of eeprom */
 static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw)
 {
index 3ad7a13d6c391839a3135e117ae1102c20a888b1..20295e0c19954efe6e3784a781aa0c6c445551ac 100644 (file)
 
 /* Legal values for the INPUT state variable */
 #define PVR2_CVAL_INPUT_TV 0
-#define PVR2_CVAL_INPUT_SVIDEO 1
+#define PVR2_CVAL_INPUT_DTV 1
 #define PVR2_CVAL_INPUT_COMPOSITE 2
-#define PVR2_CVAL_INPUT_RADIO 3
+#define PVR2_CVAL_INPUT_SVIDEO 3
+#define PVR2_CVAL_INPUT_RADIO 4
 
 enum pvr2_config {
        pvr2_config_empty,    /* No configuration */
@@ -90,9 +91,6 @@ enum pvr2_v4l_type {
 /* Translate configuration enum to a string label */
 const char *pvr2_config_get_name(enum pvr2_config);
 
-/* Translate a master state enum to a string label */
-const char *pvr2_hdw_get_state_name(unsigned int);
-
 struct pvr2_hdw;
 
 /* Create and return a structure for interacting with the underlying
@@ -100,14 +98,15 @@ struct pvr2_hdw;
 struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
                                 const struct usb_device_id *devid);
 
+/* Perform second stage initialization, passing in a notification callback
+   for when the master state changes. */
+int pvr2_hdw_initialize(struct pvr2_hdw *,
+                       void (*callback_func)(void *),
+                       void *callback_data);
+
 /* Destroy hardware interaction structure */
 void pvr2_hdw_destroy(struct pvr2_hdw *);
 
-/* Register a function to be called whenever the master state changes. */
-void pvr2_hdw_set_state_callback(struct pvr2_hdw *,
-                                void (*callback_func)(void *),
-                                void *callback_data);
-
 /* Return true if in the ready (normal) state */
 int pvr2_hdw_dev_ok(struct pvr2_hdw *);
 
@@ -146,6 +145,23 @@ struct pvr2_ctrl *pvr2_hdw_get_ctrl_nextv4l(struct pvr2_hdw *,
 /* Commit all control changes made up to this point */
 int pvr2_hdw_commit_ctl(struct pvr2_hdw *);
 
+/* Return a bit mask of valid input selections for this device.  Mask bits
+ * will be according to PVR_CVAL_INPUT_xxxx definitions. */
+unsigned int pvr2_hdw_get_input_available(struct pvr2_hdw *);
+
+/* Return a bit mask of allowed input selections for this device.  Mask bits
+ * will be according to PVR_CVAL_INPUT_xxxx definitions. */
+unsigned int pvr2_hdw_get_input_allowed(struct pvr2_hdw *);
+
+/* Change the set of allowed input selections for this device.  Both
+   change_mask and change_valu are mask bits according to
+   PVR_CVAL_INPUT_xxxx definitions.  The change_mask parameter indicate
+   which settings are being changed and the change_val parameter indicates
+   whether corresponding settings are being set or cleared. */
+int pvr2_hdw_set_input_allowed(struct pvr2_hdw *,
+                              unsigned int change_mask,
+                              unsigned int change_val);
+
 /* Return name for this driver instance */
 const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *);
 
@@ -250,6 +266,9 @@ int pvr2_hdw_cmd_deep_reset(struct pvr2_hdw *);
 /* Execute simple reset command */
 int pvr2_hdw_cmd_powerup(struct pvr2_hdw *);
 
+/* suspend */
+int pvr2_hdw_cmd_powerdown(struct pvr2_hdw *);
+
 /* Order decoder to reset */
 int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *);
 
index 62867fa3517ae4cd201b2971372aa180ccf716d8..793c89a8d672c513c2ea72fb54732008e9c7dd48 100644 (file)
@@ -35,7 +35,7 @@
 
 */
 
-static unsigned int i2c_scan = 0;
+static unsigned int i2c_scan;
 module_param(i2c_scan, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time");
 
index a9889ff96ecc945b1f344c9fd4ab7e8eced695e0..7aff8b720064c864226ed0502d4ba60365c95f1e 100644 (file)
@@ -80,6 +80,10 @@ struct pvr2_stream {
        /* Tracking state for tolerating errors */
        unsigned int fail_count;
        unsigned int fail_tolerance;
+
+       unsigned int buffers_processed;
+       unsigned int buffers_failed;
+       unsigned int bytes_processed;
 };
 
 struct pvr2_buffer {
@@ -446,6 +450,8 @@ static void buffer_complete(struct urb *urb)
            (urb->status == -ENOENT) ||
            (urb->status == -ECONNRESET) ||
            (urb->status == -ESHUTDOWN)) {
+               (sp->buffers_processed)++;
+               sp->bytes_processed += urb->actual_length;
                bp->used_count = urb->actual_length;
                if (sp->fail_count) {
                        pvr2_trace(PVR2_TRACE_TOLERANCE,
@@ -457,11 +463,13 @@ static void buffer_complete(struct urb *urb)
                // We can tolerate this error, because we're below the
                // threshold...
                (sp->fail_count)++;
+               (sp->buffers_failed)++;
                pvr2_trace(PVR2_TRACE_TOLERANCE,
                           "stream %p ignoring error %d"
                           " - fail count increased to %u",
                           sp,urb->status,sp->fail_count);
        } else {
+               (sp->buffers_failed)++;
                bp->status = urb->status;
        }
        spin_unlock_irqrestore(&sp->list_lock,irq_flags);
@@ -515,6 +523,28 @@ void pvr2_stream_set_callback(struct pvr2_stream *sp,
        } while(0); mutex_unlock(&sp->mutex);
 }
 
+void pvr2_stream_get_stats(struct pvr2_stream *sp,
+                          struct pvr2_stream_stats *stats,
+                          int zero_counts)
+{
+       unsigned long irq_flags;
+       spin_lock_irqsave(&sp->list_lock,irq_flags);
+       if (stats) {
+               stats->buffers_in_queue = sp->q_count;
+               stats->buffers_in_idle = sp->i_count;
+               stats->buffers_in_ready = sp->r_count;
+               stats->buffers_processed = sp->buffers_processed;
+               stats->buffers_failed = sp->buffers_failed;
+               stats->bytes_processed = sp->bytes_processed;
+       }
+       if (zero_counts) {
+               sp->buffers_processed = 0;
+               sp->buffers_failed = 0;
+               sp->bytes_processed = 0;
+       }
+       spin_unlock_irqrestore(&sp->list_lock,irq_flags);
+}
+
 /* Query / set the nominal buffer count */
 int pvr2_stream_get_buffer_count(struct pvr2_stream *sp)
 {
index 93279cc2a35e7e29785b8fd4346b32e5f1d0c2f7..42fcf8281a879c10624157043bb7681bcac29ddc 100644 (file)
@@ -36,6 +36,15 @@ enum pvr2_buffer_state {
 struct pvr2_stream;
 struct pvr2_buffer;
 
+struct pvr2_stream_stats {
+       unsigned int buffers_in_queue;
+       unsigned int buffers_in_idle;
+       unsigned int buffers_in_ready;
+       unsigned int buffers_processed;
+       unsigned int buffers_failed;
+       unsigned int bytes_processed;
+};
+
 /* Initialize / tear down stream structure */
 struct pvr2_stream *pvr2_stream_create(void);
 void pvr2_stream_destroy(struct pvr2_stream *);
@@ -45,6 +54,9 @@ void pvr2_stream_setup(struct pvr2_stream *,
 void pvr2_stream_set_callback(struct pvr2_stream *,
                              pvr2_stream_callback func,
                              void *data);
+void pvr2_stream_get_stats(struct pvr2_stream *,
+                          struct pvr2_stream_stats *,
+                          int zero_counts);
 
 /* Query / set the nominal buffer count */
 int pvr2_stream_get_buffer_count(struct pvr2_stream *);
index b63b2265503ac174a335e1ca23c5a560e8d1c31c..332aced8a5a1f04d182c19acbe600f474900ff4c 100644 (file)
@@ -60,6 +60,10 @@ static void pvr_setup_attach(struct pvr2_context *pvr)
 {
        /* Create association with v4l layer */
        pvr2_v4l2_create(pvr);
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+       /* Create association with dvb layer */
+       pvr2_dvb_create(pvr);
+#endif
 #ifdef CONFIG_VIDEO_PVRUSB2_SYSFS
        pvr2_sysfs_create(pvr,class_ptr);
 #endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */
@@ -121,6 +125,12 @@ static int __init pvr_init(void)
 
        pvr2_trace(PVR2_TRACE_INIT,"pvr_init");
 
+       ret = pvr2_context_global_init();
+       if (ret != 0) {
+               pvr2_trace(PVR2_TRACE_INIT,"pvr_init failure code=%d",ret);
+               return ret;
+       }
+
 #ifdef CONFIG_VIDEO_PVRUSB2_SYSFS
        class_ptr = pvr2_sysfs_class_create();
 #endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */
@@ -132,6 +142,8 @@ static int __init pvr_init(void)
        if (pvrusb2_debug) info("Debug mask is %d (0x%x)",
                                pvrusb2_debug,pvrusb2_debug);
 
+       pvr2_trace(PVR2_TRACE_INIT,"pvr_init complete");
+
        return ret;
 }
 
@@ -144,6 +156,10 @@ static void __exit pvr_exit(void)
 #ifdef CONFIG_VIDEO_PVRUSB2_SYSFS
        pvr2_sysfs_class_destroy(class_ptr);
 #endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */
+
+       pvr2_context_global_done();
+
+       pvr2_trace(PVR2_TRACE_INIT,"pvr_exit complete");
 }
 
 module_init(pvr_init);
index da309288daa4c603fd92b6dbd33e3eca5a6a6508..fdc5a2b49ca8568cf73adb1b3f5fe6d69859a814 100644 (file)
@@ -79,7 +79,7 @@ struct std_name {
 #define TSTD_Nc  (V4L2_STD_PAL_Nc)
 #define TSTD_60  (V4L2_STD_PAL_60)
 
-#define CSTD_ALL (CSTD_PAL|CSTD_NTSC|CSTD_SECAM)
+#define CSTD_ALL (CSTD_PAL|CSTD_NTSC|CSTD_ATSC|CSTD_SECAM)
 
 /* Mapping of standard bits to color system */
 static const struct std_name std_groups[] = {
@@ -328,7 +328,7 @@ struct v4l2_standard *pvr2_std_create_enum(unsigned int *countptr,
        struct v4l2_standard *stddefs;
 
        if (pvrusb2_debug & PVR2_TRACE_STD) {
-               char buf[50];
+               char buf[100];
                bcnt = pvr2_std_id_to_str(buf,sizeof(buf),id);
                pvr2_trace(
                        PVR2_TRACE_STD,"Mapping standards mask=0x%x (%.*s)",
@@ -352,8 +352,11 @@ struct v4l2_standard *pvr2_std_create_enum(unsigned int *countptr,
                if ((id & std_mixes[idx2]) == std_mixes[idx2]) std_cnt++;
        }
 
+       /* Don't complain about ATSC standard values */
+       fmsk &= ~CSTD_ATSC;
+
        if (fmsk) {
-               char buf[50];
+               char buf[100];
                bcnt = pvr2_std_id_to_str(buf,sizeof(buf),fmsk);
                pvr2_trace(
                        PVR2_TRACE_ERROR_LEGS,
index 07f4eae184330a6a91796a3d53e07e24a7c3204a..0ff7a836a8a2493e926ad102664a7814333d026a 100644 (file)
@@ -287,6 +287,8 @@ static ssize_t store_val_norm(int id,struct device *class_dev,
        struct pvr2_sysfs *sfp;
        int ret;
        sfp = (struct pvr2_sysfs *)class_dev->driver_data;
+       pvr2_sysfs_trace("pvr2_sysfs(%p) store_val_norm(cid=%d) \"%.*s\"",
+                        sfp,id,(int)count,buf);
        ret = store_val_any(id,0,sfp,buf,count);
        if (!ret) ret = count;
        return ret;
@@ -298,6 +300,8 @@ static ssize_t store_val_custom(int id,struct device *class_dev,
        struct pvr2_sysfs *sfp;
        int ret;
        sfp = (struct pvr2_sysfs *)class_dev->driver_data;
+       pvr2_sysfs_trace("pvr2_sysfs(%p) store_val_custom(cid=%d) \"%.*s\"",
+                        sfp,id,(int)count,buf);
        ret = store_val_any(id,1,sfp,buf,count);
        if (!ret) ret = count;
        return ret;
@@ -604,8 +608,9 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
 
        ret = sysfs_create_group(&sfp->class_dev->kobj,&cip->grp);
        if (ret) {
-               printk(KERN_WARNING "%s: sysfs_create_group error: %d\n",
-                      __FUNCTION__, ret);
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "sysfs_create_group error: %d",
+                          ret);
                return;
        }
        cip->created_ok = !0;
@@ -636,15 +641,17 @@ static void pvr2_sysfs_add_debugifc(struct pvr2_sysfs *sfp)
        sfp->debugifc = dip;
        ret = device_create_file(sfp->class_dev,&dip->attr_debugcmd);
        if (ret < 0) {
-               printk(KERN_WARNING "%s: device_create_file error: %d\n",
-                      __FUNCTION__, ret);
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "device_create_file error: %d",
+                          ret);
        } else {
                dip->debugcmd_created_ok = !0;
        }
        ret = device_create_file(sfp->class_dev,&dip->attr_debuginfo);
        if (ret < 0) {
-               printk(KERN_WARNING "%s: device_create_file error: %d\n",
-                      __FUNCTION__, ret);
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "device_create_file error: %d",
+                          ret);
        } else {
                dip->debuginfo_created_ok = !0;
        }
@@ -847,8 +854,8 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
        class_dev->driver_data = sfp;
        ret = device_register(class_dev);
        if (ret) {
-               printk(KERN_ERR "%s: device_register failed\n",
-                      __FUNCTION__);
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "device_register failed");
                kfree(class_dev);
                return;
        }
@@ -860,8 +867,9 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
        ret = device_create_file(sfp->class_dev,
                                       &sfp->attr_v4l_minor_number);
        if (ret < 0) {
-               printk(KERN_WARNING "%s: device_create_file error: %d\n",
-                      __FUNCTION__, ret);
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "device_create_file error: %d",
+                          ret);
        } else {
                sfp->v4l_minor_number_created_ok = !0;
        }
@@ -873,8 +881,9 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
        ret = device_create_file(sfp->class_dev,
                                       &sfp->attr_v4l_radio_minor_number);
        if (ret < 0) {
-               printk(KERN_WARNING "%s: device_create_file error: %d\n",
-                      __FUNCTION__, ret);
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "device_create_file error: %d",
+                          ret);
        } else {
                sfp->v4l_radio_minor_number_created_ok = !0;
        }
@@ -885,8 +894,9 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
        sfp->attr_unit_number.store = NULL;
        ret = device_create_file(sfp->class_dev,&sfp->attr_unit_number);
        if (ret < 0) {
-               printk(KERN_WARNING "%s: device_create_file error: %d\n",
-                      __FUNCTION__, ret);
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "device_create_file error: %d",
+                          ret);
        } else {
                sfp->unit_number_created_ok = !0;
        }
@@ -898,8 +908,9 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
        ret = device_create_file(sfp->class_dev,
                                       &sfp->attr_bus_info);
        if (ret < 0) {
-               printk(KERN_WARNING "%s: device_create_file error: %d\n",
-                      __FUNCTION__, ret);
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "device_create_file error: %d",
+                          ret);
        } else {
                sfp->bus_info_created_ok = !0;
        }
@@ -911,8 +922,9 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
        ret = device_create_file(sfp->class_dev,
                                 &sfp->attr_hdw_name);
        if (ret < 0) {
-               printk(KERN_WARNING "%s: device_create_file error: %d\n",
-                      __FUNCTION__, ret);
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "device_create_file error: %d",
+                          ret);
        } else {
                sfp->hdw_name_created_ok = !0;
        }
@@ -924,8 +936,9 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
        ret = device_create_file(sfp->class_dev,
                                 &sfp->attr_hdw_desc);
        if (ret < 0) {
-               printk(KERN_WARNING "%s: device_create_file error: %d\n",
-                      __FUNCTION__, ret);
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "device_create_file error: %d",
+                          ret);
        } else {
                sfp->hdw_desc_created_ok = !0;
        }
index 8f0587ebd4bd8609b4e97f785f3641f176b01344..087a18245560f467fb059590a91531c4840a4d0d 100644 (file)
@@ -57,7 +57,9 @@ struct pvr2_v4l2_fh {
        struct pvr2_v4l2_fh *vprev;
        wait_queue_head_t wait_data;
        int fw_mode_flag;
-       int prev_input_val;
+       /* Map contiguous ordinal value to input id */
+       unsigned char *input_map;
+       unsigned int input_cnt;
 };
 
 struct pvr2_v4l2 {
@@ -259,14 +261,21 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
                struct v4l2_input *vi = (struct v4l2_input *)arg;
                struct v4l2_input tmp;
                unsigned int cnt;
+               int val;
 
                cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
 
                memset(&tmp,0,sizeof(tmp));
                tmp.index = vi->index;
                ret = 0;
-               switch (vi->index) {
+               if ((vi->index < 0) || (vi->index >= fh->input_cnt)) {
+                       ret = -EINVAL;
+                       break;
+               }
+               val = fh->input_map[vi->index];
+               switch (val) {
                case PVR2_CVAL_INPUT_TV:
+               case PVR2_CVAL_INPUT_DTV:
                case PVR2_CVAL_INPUT_RADIO:
                        tmp.type = V4L2_INPUT_TYPE_TUNER;
                        break;
@@ -281,7 +290,7 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
                if (ret < 0) break;
 
                cnt = 0;
-               pvr2_ctrl_get_valname(cptr,vi->index,
+               pvr2_ctrl_get_valname(cptr,val,
                                      tmp.name,sizeof(tmp.name)-1,&cnt);
                tmp.name[cnt] = 0;
 
@@ -303,22 +312,33 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
 
        case VIDIOC_G_INPUT:
        {
+               unsigned int idx;
                struct pvr2_ctrl *cptr;
                struct v4l2_input *vi = (struct v4l2_input *)arg;
                int val;
                cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
                val = 0;
                ret = pvr2_ctrl_get_value(cptr,&val);
-               vi->index = val;
+               vi->index = 0;
+               for (idx = 0; idx < fh->input_cnt; idx++) {
+                       if (fh->input_map[idx] == val) {
+                               vi->index = idx;
+                               break;
+                       }
+               }
                break;
        }
 
        case VIDIOC_S_INPUT:
        {
                struct v4l2_input *vi = (struct v4l2_input *)arg;
+               if ((vi->index < 0) || (vi->index >= fh->input_cnt)) {
+                       ret = -ERANGE;
+                       break;
+               }
                ret = pvr2_ctrl_set_value(
                        pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
-                       vi->index);
+                       fh->input_map[vi->index]);
                break;
        }
 
@@ -858,7 +878,6 @@ static int pvr2_v4l2_release(struct inode *inode, struct file *file)
 {
        struct pvr2_v4l2_fh *fhp = file->private_data;
        struct pvr2_v4l2 *vp = fhp->vhead;
-       struct pvr2_context *mp = fhp->vhead->channel.mc_head;
        struct pvr2_hdw *hdw = fhp->channel.mc_head->hdw;
 
        pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_release");
@@ -875,42 +894,30 @@ static int pvr2_v4l2_release(struct inode *inode, struct file *file)
        v4l2_prio_close(&vp->prio, &fhp->prio);
        file->private_data = NULL;
 
-       pvr2_context_enter(mp); do {
-               /* Restore the previous input selection, if it makes sense
-                  to do so. */
-               if (fhp->dev_info->v4l_type == VFL_TYPE_RADIO) {
-                       struct pvr2_ctrl *cp;
-                       int pval;
-                       cp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
-                       pvr2_ctrl_get_value(cp,&pval);
-                       /* Only restore if we're still selecting the radio */
-                       if (pval == PVR2_CVAL_INPUT_RADIO) {
-                               pvr2_ctrl_set_value(cp,fhp->prev_input_val);
-                               pvr2_hdw_commit_ctl(hdw);
-                       }
-               }
-
-               if (fhp->vnext) {
-                       fhp->vnext->vprev = fhp->vprev;
-               } else {
-                       vp->vlast = fhp->vprev;
-               }
-               if (fhp->vprev) {
-                       fhp->vprev->vnext = fhp->vnext;
-               } else {
-                       vp->vfirst = fhp->vnext;
-               }
-               fhp->vnext = NULL;
-               fhp->vprev = NULL;
-               fhp->vhead = NULL;
-               pvr2_channel_done(&fhp->channel);
-               pvr2_trace(PVR2_TRACE_STRUCT,
-                          "Destroying pvr_v4l2_fh id=%p",fhp);
-               kfree(fhp);
-               if (vp->channel.mc_head->disconnect_flag && !vp->vfirst) {
-                       pvr2_v4l2_destroy_no_lock(vp);
-               }
-       } while (0); pvr2_context_exit(mp);
+       if (fhp->vnext) {
+               fhp->vnext->vprev = fhp->vprev;
+       } else {
+               vp->vlast = fhp->vprev;
+       }
+       if (fhp->vprev) {
+               fhp->vprev->vnext = fhp->vnext;
+       } else {
+               vp->vfirst = fhp->vnext;
+       }
+       fhp->vnext = NULL;
+       fhp->vprev = NULL;
+       fhp->vhead = NULL;
+       pvr2_channel_done(&fhp->channel);
+       pvr2_trace(PVR2_TRACE_STRUCT,
+                  "Destroying pvr_v4l2_fh id=%p",fhp);
+       if (fhp->input_map) {
+               kfree(fhp->input_map);
+               fhp->input_map = NULL;
+       }
+       kfree(fhp);
+       if (vp->channel.mc_head->disconnect_flag && !vp->vfirst) {
+               pvr2_v4l2_destroy_no_lock(vp);
+       }
        return 0;
 }
 
@@ -921,6 +928,9 @@ static int pvr2_v4l2_open(struct inode *inode, struct file *file)
        struct pvr2_v4l2_fh *fhp;
        struct pvr2_v4l2 *vp;
        struct pvr2_hdw *hdw;
+       unsigned int input_mask = 0;
+       unsigned int input_cnt,idx;
+       int ret = 0;
 
        dip = container_of(video_devdata(file),struct pvr2_v4l2_dev,devbase);
 
@@ -943,32 +953,62 @@ static int pvr2_v4l2_open(struct inode *inode, struct file *file)
        init_waitqueue_head(&fhp->wait_data);
        fhp->dev_info = dip;
 
-       pvr2_context_enter(vp->channel.mc_head); do {
-               pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp);
-               pvr2_channel_init(&fhp->channel,vp->channel.mc_head);
+       pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp);
+       pvr2_channel_init(&fhp->channel,vp->channel.mc_head);
 
-               fhp->vnext = NULL;
-               fhp->vprev = vp->vlast;
-               if (vp->vlast) {
-                       vp->vlast->vnext = fhp;
-               } else {
-                       vp->vfirst = fhp;
-               }
-               vp->vlast = fhp;
-               fhp->vhead = vp;
-
-               /* Opening the /dev/radioX device implies a mode switch.
-                  So execute that here.  Note that you can get the
-                  IDENTICAL effect merely by opening the normal video
-                  device and setting the input appropriately. */
-               if (dip->v4l_type == VFL_TYPE_RADIO) {
-                       struct pvr2_ctrl *cp;
-                       cp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
-                       pvr2_ctrl_get_value(cp,&fhp->prev_input_val);
-                       pvr2_ctrl_set_value(cp,PVR2_CVAL_INPUT_RADIO);
-                       pvr2_hdw_commit_ctl(hdw);
-               }
-       } while (0); pvr2_context_exit(vp->channel.mc_head);
+       if (dip->v4l_type == VFL_TYPE_RADIO) {
+               /* Opening device as a radio, legal input selection subset
+                  is just the radio. */
+               input_mask = (1 << PVR2_CVAL_INPUT_RADIO);
+       } else {
+               /* Opening the main V4L device, legal input selection
+                  subset includes all analog inputs. */
+               input_mask = ((1 << PVR2_CVAL_INPUT_RADIO) |
+                             (1 << PVR2_CVAL_INPUT_TV) |
+                             (1 << PVR2_CVAL_INPUT_COMPOSITE) |
+                             (1 << PVR2_CVAL_INPUT_SVIDEO));
+       }
+       ret = pvr2_channel_limit_inputs(&fhp->channel,input_mask);
+       if (ret) {
+               pvr2_channel_done(&fhp->channel);
+               pvr2_trace(PVR2_TRACE_STRUCT,
+                          "Destroying pvr_v4l2_fh id=%p (input mask error)",
+                          fhp);
+
+               kfree(fhp);
+               return ret;
+       }
+
+       input_mask &= pvr2_hdw_get_input_available(hdw);
+       input_cnt = 0;
+       for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
+               if (input_mask & (1 << idx)) input_cnt++;
+       }
+       fhp->input_cnt = input_cnt;
+       fhp->input_map = kzalloc(input_cnt,GFP_KERNEL);
+       if (!fhp->input_map) {
+               pvr2_channel_done(&fhp->channel);
+               pvr2_trace(PVR2_TRACE_STRUCT,
+                          "Destroying pvr_v4l2_fh id=%p (input map failure)",
+                          fhp);
+               kfree(fhp);
+               return -ENOMEM;
+       }
+       input_cnt = 0;
+       for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
+               if (!(input_mask & (1 << idx))) continue;
+               fhp->input_map[input_cnt++] = idx;
+       }
+
+       fhp->vnext = NULL;
+       fhp->vprev = vp->vlast;
+       if (vp->vlast) {
+               vp->vlast->vnext = fhp;
+       } else {
+               vp->vfirst = fhp;
+       }
+       vp->vlast = fhp;
+       fhp->vhead = vp;
 
        fhp->file = file;
        file->private_data = fhp;
@@ -1201,24 +1241,27 @@ struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp)
 
        vp = kzalloc(sizeof(*vp),GFP_KERNEL);
        if (!vp) return vp;
-       vp->dev_video = kzalloc(sizeof(*vp->dev_video),GFP_KERNEL);
-       vp->dev_radio = kzalloc(sizeof(*vp->dev_radio),GFP_KERNEL);
-       if (!(vp->dev_video && vp->dev_radio)) {
-               kfree(vp->dev_video);
-               kfree(vp->dev_radio);
-               kfree(vp);
-               return NULL;
-       }
        pvr2_channel_init(&vp->channel,mnp);
        pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp);
 
        vp->channel.check_func = pvr2_v4l2_internal_check;
 
        /* register streams */
+       vp->dev_video = kzalloc(sizeof(*vp->dev_video),GFP_KERNEL);
+       if (!vp->dev_video) goto fail;
        pvr2_v4l2_dev_init(vp->dev_video,vp,VFL_TYPE_GRABBER);
-       pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO);
+       if (pvr2_hdw_get_input_available(vp->channel.mc_head->hdw) &
+           (1 << PVR2_CVAL_INPUT_RADIO)) {
+               vp->dev_radio = kzalloc(sizeof(*vp->dev_radio),GFP_KERNEL);
+               if (!vp->dev_radio) goto fail;
+               pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO);
+       }
 
        return vp;
+ fail:
+       pvr2_trace(PVR2_TRACE_STRUCT,"Failure creating pvr2_v4l2 id=%p",vp);
+       pvr2_v4l2_destroy_no_lock(vp);
+       return 0;
 }
 
 /*
index e0a453a6543d2526c2ba3ef39e1dd86901c8c89e..423fa7c2d0c9b465fa54f0a6cb761ea06e1cd420 100644 (file)
@@ -130,8 +130,8 @@ static int default_fbufs = 3;   /* Default number of frame buffers */
 #ifdef CONFIG_USB_PWC_DEBUG
        int pwc_trace = PWC_DEBUG_LEVEL;
 #endif
-static int power_save = 0;
-static int led_on = 100, led_off = 0; /* defaults to LED that is on while in use */
+static int power_save;
+static int led_on = 100, led_off; /* defaults to LED that is on while in use */
 static int pwc_preferred_compression = 1; /* 0..3 = uncompressed..high */
 static struct {
        int type;
@@ -159,7 +159,9 @@ static const struct file_operations pwc_fops = {
        .poll =         pwc_video_poll,
        .mmap =         pwc_video_mmap,
        .ioctl =        pwc_video_ioctl,
+#ifdef CONFIG_COMPAT
        .compat_ioctl = v4l_compat_ioctl32,
+#endif
        .llseek =       no_llseek,
 };
 static struct video_device pwc_template = {
@@ -487,7 +489,7 @@ static void pwc_reset_buffers(struct pwc_device *pdev)
        int i;
        unsigned long flags;
 
-       PWC_DEBUG_MEMORY(">> %s __enter__\n", __FUNCTION__);
+       PWC_DEBUG_MEMORY(">> %s __enter__\n", __func__);
 
        spin_lock_irqsave(&pdev->ptrlock, flags);
        pdev->full_frames = NULL;
@@ -509,7 +511,7 @@ static void pwc_reset_buffers(struct pwc_device *pdev)
        pdev->fill_image = 0;
        spin_unlock_irqrestore(&pdev->ptrlock, flags);
 
-       PWC_DEBUG_MEMORY("<< %s __leaving__\n", __FUNCTION__);
+       PWC_DEBUG_MEMORY("<< %s __leaving__\n", __func__);
 }
 
 
@@ -786,8 +788,8 @@ static void pwc_isoc_handler(struct urb *urb)
                } /* ..status == 0 */
                else {
                        /* This is normally not interesting to the user, unless
-                        * you are really debugging something */
-                       static int iso_error = 0;
+                        * you are really debugging something, default = 0 */
+                       static int iso_error;
                        iso_error++;
                        if (iso_error < 20)
                                PWC_DEBUG_FLOW("Iso frame %d of USB has error %d\n", i, fst);
@@ -1426,7 +1428,7 @@ static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma)
        unsigned long page, pos = 0;
        int index;
 
-       PWC_DEBUG_MEMORY(">> %s\n", __FUNCTION__);
+       PWC_DEBUG_MEMORY(">> %s\n", __func__);
        pdev = vdev->priv;
        size = vma->vm_end - vma->vm_start;
        start = vma->vm_start;
index 32fbe1ae62519c30d595b545c53e3320a8621f44..1742889874df08c6f944b4b066fa1111fcff2e4a 100644 (file)
@@ -351,8 +351,10 @@ int pwc_video_do_ioctl(struct inode *inode, struct file *file,
                return -EFAULT;
 
 #ifdef CONFIG_USB_PWC_DEBUG
-       if (PWC_DEBUG_LEVEL_IOCTL & pwc_trace)
+       if (PWC_DEBUG_LEVEL_IOCTL & pwc_trace) {
                v4l_printk_ioctl(cmd);
+               printk("\n");
+       }
 #endif
 
 
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c
new file mode 100644 (file)
index 0000000..7cc8e9b
--- /dev/null
@@ -0,0 +1,1206 @@
+/*
+ * V4L2 Driver for PXA camera host
+ *
+ * Copyright (C) 2006, Sascha Hauer, Pengutronix
+ * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
+ *
+ * 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/io.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/moduleparam.h>
+#include <linux/time.h>
+#include <linux/version.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/clk.h>
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-dev.h>
+#include <media/soc_camera.h>
+
+#include <linux/videodev2.h>
+
+#include <asm/dma.h>
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/camera.h>
+
+#define PXA_CAM_VERSION_CODE KERNEL_VERSION(0, 0, 5)
+#define PXA_CAM_DRV_NAME "pxa27x-camera"
+
+#define CICR0_SIM_MP   (0 << 24)
+#define CICR0_SIM_SP   (1 << 24)
+#define CICR0_SIM_MS   (2 << 24)
+#define CICR0_SIM_EP   (3 << 24)
+#define CICR0_SIM_ES   (4 << 24)
+
+#define CICR1_DW_VAL(x)   ((x) & CICR1_DW)         /* Data bus width */
+#define CICR1_PPL_VAL(x)  (((x) << 15) & CICR1_PPL) /* Pixels per line */
+#define CICR1_COLOR_SP_VAL(x)  (((x) << 3) & CICR1_COLOR_SP)   /* color space */
+#define CICR1_RGB_BPP_VAL(x)   (((x) << 7) & CICR1_RGB_BPP)    /* bpp for rgb */
+#define CICR1_RGBT_CONV_VAL(x) (((x) << 29) & CICR1_RGBT_CONV) /* rgbt conv */
+
+#define CICR2_BLW_VAL(x)  (((x) << 24) & CICR2_BLW) /* Beginning-of-line pixel clock wait count */
+#define CICR2_ELW_VAL(x)  (((x) << 16) & CICR2_ELW) /* End-of-line pixel clock wait count */
+#define CICR2_HSW_VAL(x)  (((x) << 10) & CICR2_HSW) /* Horizontal sync pulse width */
+#define CICR2_BFPW_VAL(x) (((x) << 3) & CICR2_BFPW) /* Beginning-of-frame pixel clock wait count */
+#define CICR2_FSW_VAL(x)  (((x) << 0) & CICR2_FSW)  /* Frame stabilization wait count */
+
+#define CICR3_BFW_VAL(x)  (((x) << 24) & CICR3_BFW) /* Beginning-of-frame line clock wait count  */
+#define CICR3_EFW_VAL(x)  (((x) << 16) & CICR3_EFW) /* End-of-frame line clock wait count */
+#define CICR3_VSW_VAL(x)  (((x) << 11) & CICR3_VSW) /* Vertical sync pulse width */
+#define CICR3_LPF_VAL(x)  (((x) << 0) & CICR3_LPF)  /* Lines per frame */
+
+#define CICR0_IRQ_MASK (CICR0_TOM | CICR0_RDAVM | CICR0_FEM | CICR0_EOLM | \
+                       CICR0_PERRM | CICR0_QDM | CICR0_CDM | CICR0_SOFM | \
+                       CICR0_EOFM | CICR0_FOM)
+
+static DEFINE_MUTEX(camera_lock);
+
+/*
+ * Structures
+ */
+enum pxa_camera_active_dma {
+       DMA_Y = 0x1,
+       DMA_U = 0x2,
+       DMA_V = 0x4,
+};
+
+/* descriptor needed for the PXA DMA engine */
+struct pxa_cam_dma {
+       dma_addr_t              sg_dma;
+       struct pxa_dma_desc     *sg_cpu;
+       size_t                  sg_size;
+       int                     sglen;
+};
+
+/* buffer for one video frame */
+struct pxa_buffer {
+       /* common v4l buffer stuff -- must be first */
+       struct videobuf_buffer vb;
+
+       const struct soc_camera_data_format        *fmt;
+
+       /* our descriptor lists for Y, U and V channels */
+       struct pxa_cam_dma dmas[3];
+
+       int                     inwork;
+
+       enum pxa_camera_active_dma active_dma;
+};
+
+struct pxa_camera_dev {
+       struct device           *dev;
+       /* PXA27x is only supposed to handle one camera on its Quick Capture
+        * interface. If anyone ever builds hardware to enable more than
+        * one camera, they will have to modify this driver too */
+       struct soc_camera_device *icd;
+       struct clk              *clk;
+
+       unsigned int            irq;
+       void __iomem            *base;
+
+       int                     channels;
+       unsigned int            dma_chans[3];
+
+       struct pxacamera_platform_data *pdata;
+       struct resource         *res;
+       unsigned long           platform_flags;
+       unsigned long           platform_mclk_10khz;
+
+       struct list_head        capture;
+
+       spinlock_t              lock;
+
+       struct pxa_buffer       *active;
+       struct pxa_dma_desc     *sg_tail[3];
+};
+
+static const char *pxa_cam_driver_description = "PXA_Camera";
+
+static unsigned int vid_limit = 16;    /* Video memory limit, in Mb */
+
+/*
+ *  Videobuf operations
+ */
+static int pxa_videobuf_setup(struct videobuf_queue *vq, unsigned int *count,
+                             unsigned int *size)
+{
+       struct soc_camera_device *icd = vq->priv_data;
+       struct soc_camera_host *ici =
+               to_soc_camera_host(icd->dev.parent);
+       struct pxa_camera_dev *pcdev = ici->priv;
+
+       dev_dbg(&icd->dev, "count=%d, size=%d\n", *count, *size);
+
+       /* planar capture requires Y, U and V buffers to be page aligned */
+       if (pcdev->channels == 3) {
+               *size = PAGE_ALIGN(icd->width * icd->height); /* Y pages */
+               *size += PAGE_ALIGN(icd->width * icd->height / 2); /* U pages */
+               *size += PAGE_ALIGN(icd->width * icd->height / 2); /* V pages */
+       } else {
+               *size = icd->width * icd->height *
+                       ((icd->current_fmt->depth + 7) >> 3);
+       }
+
+       if (0 == *count)
+               *count = 32;
+       while (*size * *count > vid_limit * 1024 * 1024)
+               (*count)--;
+
+       return 0;
+}
+
+static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf)
+{
+       struct soc_camera_device *icd = vq->priv_data;
+       struct soc_camera_host *ici =
+               to_soc_camera_host(icd->dev.parent);
+       struct pxa_camera_dev *pcdev = ici->priv;
+       struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb);
+       int i;
+
+       BUG_ON(in_interrupt());
+
+       dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
+               &buf->vb, buf->vb.baddr, buf->vb.bsize);
+
+       /* This waits until this buffer is out of danger, i.e., until it is no
+        * longer in STATE_QUEUED or STATE_ACTIVE */
+       videobuf_waiton(&buf->vb, 0, 0);
+       videobuf_dma_unmap(vq, dma);
+       videobuf_dma_free(dma);
+
+       for (i = 0; i < ARRAY_SIZE(buf->dmas); i++) {
+               if (buf->dmas[i].sg_cpu)
+                       dma_free_coherent(pcdev->dev, buf->dmas[i].sg_size,
+                                         buf->dmas[i].sg_cpu,
+                                         buf->dmas[i].sg_dma);
+               buf->dmas[i].sg_cpu = NULL;
+       }
+
+       buf->vb.state = VIDEOBUF_NEEDS_INIT;
+}
+
+static int pxa_init_dma_channel(struct pxa_camera_dev *pcdev,
+                               struct pxa_buffer *buf,
+                               struct videobuf_dmabuf *dma, int channel,
+                               int sglen, int sg_start, int cibr,
+                               unsigned int size)
+{
+       struct pxa_cam_dma *pxa_dma = &buf->dmas[channel];
+       int i;
+
+       if (pxa_dma->sg_cpu)
+               dma_free_coherent(pcdev->dev, pxa_dma->sg_size,
+                                 pxa_dma->sg_cpu, pxa_dma->sg_dma);
+
+       pxa_dma->sg_size = (sglen + 1) * sizeof(struct pxa_dma_desc);
+       pxa_dma->sg_cpu = dma_alloc_coherent(pcdev->dev, pxa_dma->sg_size,
+                                            &pxa_dma->sg_dma, GFP_KERNEL);
+       if (!pxa_dma->sg_cpu)
+               return -ENOMEM;
+
+       pxa_dma->sglen = sglen;
+
+       for (i = 0; i < sglen; i++) {
+               int sg_i = sg_start + i;
+               struct scatterlist *sg = dma->sglist;
+               unsigned int dma_len = sg_dma_len(&sg[sg_i]), xfer_len;
+
+               pxa_dma->sg_cpu[i].dsadr = pcdev->res->start + cibr;
+               pxa_dma->sg_cpu[i].dtadr = sg_dma_address(&sg[sg_i]);
+
+               /* PXA27x Developer's Manual 27.4.4.1: round up to 8 bytes */
+               xfer_len = (min(dma_len, size) + 7) & ~7;
+
+               pxa_dma->sg_cpu[i].dcmd =
+                       DCMD_FLOWSRC | DCMD_BURST8 | DCMD_INCTRGADDR | xfer_len;
+               size -= dma_len;
+               pxa_dma->sg_cpu[i].ddadr =
+                       pxa_dma->sg_dma + (i + 1) * sizeof(struct pxa_dma_desc);
+       }
+
+       pxa_dma->sg_cpu[sglen - 1].ddadr = DDADR_STOP;
+       pxa_dma->sg_cpu[sglen - 1].dcmd |= DCMD_ENDIRQEN;
+
+       return 0;
+}
+
+static int pxa_videobuf_prepare(struct videobuf_queue *vq,
+               struct videobuf_buffer *vb, enum v4l2_field field)
+{
+       struct soc_camera_device *icd = vq->priv_data;
+       struct soc_camera_host *ici =
+               to_soc_camera_host(icd->dev.parent);
+       struct pxa_camera_dev *pcdev = ici->priv;
+       struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb);
+       int ret;
+       int sglen_y,  sglen_yu = 0, sglen_u = 0, sglen_v = 0;
+       int size_y, size_u = 0, size_v = 0;
+
+       dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
+               vb, vb->baddr, vb->bsize);
+
+       /* Added list head initialization on alloc */
+       WARN_ON(!list_empty(&vb->queue));
+
+#ifdef DEBUG
+       /* This can be useful if you want to see if we actually fill
+        * the buffer with something */
+       memset((void *)vb->baddr, 0xaa, vb->bsize);
+#endif
+
+       BUG_ON(NULL == icd->current_fmt);
+
+       /* I think, in buf_prepare you only have to protect global data,
+        * the actual buffer is yours */
+       buf->inwork = 1;
+
+       if (buf->fmt    != icd->current_fmt ||
+           vb->width   != icd->width ||
+           vb->height  != icd->height ||
+           vb->field   != field) {
+               buf->fmt        = icd->current_fmt;
+               vb->width       = icd->width;
+               vb->height      = icd->height;
+               vb->field       = field;
+               vb->state       = VIDEOBUF_NEEDS_INIT;
+       }
+
+       vb->size = vb->width * vb->height * ((buf->fmt->depth + 7) >> 3);
+       if (0 != vb->baddr && vb->bsize < vb->size) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       if (vb->state == VIDEOBUF_NEEDS_INIT) {
+               unsigned int size = vb->size;
+               struct videobuf_dmabuf *dma = videobuf_to_dma(vb);
+
+               ret = videobuf_iolock(vq, vb, NULL);
+               if (ret)
+                       goto fail;
+
+               if (pcdev->channels == 3) {
+                       /* FIXME the calculations should be more precise */
+                       sglen_y = dma->sglen / 2;
+                       sglen_u = sglen_v = dma->sglen / 4 + 1;
+                       sglen_yu = sglen_y + sglen_u;
+                       size_y = size / 2;
+                       size_u = size_v = size / 4;
+               } else {
+                       sglen_y = dma->sglen;
+                       size_y = size;
+               }
+
+               /* init DMA for Y channel */
+               ret = pxa_init_dma_channel(pcdev, buf, dma, 0, sglen_y,
+                                          0, 0x28, size_y);
+
+               if (ret) {
+                       dev_err(pcdev->dev,
+                               "DMA initialization for Y/RGB failed\n");
+                       goto fail;
+               }
+
+               if (pcdev->channels == 3) {
+                       /* init DMA for U channel */
+                       ret = pxa_init_dma_channel(pcdev, buf, dma, 1, sglen_u,
+                                                  sglen_y, 0x30, size_u);
+                       if (ret) {
+                               dev_err(pcdev->dev,
+                                       "DMA initialization for U failed\n");
+                               goto fail_u;
+                       }
+
+                       /* init DMA for V channel */
+                       ret = pxa_init_dma_channel(pcdev, buf, dma, 2, sglen_v,
+                                                  sglen_yu, 0x38, size_v);
+                       if (ret) {
+                               dev_err(pcdev->dev,
+                                       "DMA initialization for V failed\n");
+                               goto fail_v;
+                       }
+               }
+
+               vb->state = VIDEOBUF_PREPARED;
+       }
+
+       buf->inwork = 0;
+       buf->active_dma = DMA_Y;
+       if (pcdev->channels == 3)
+               buf->active_dma |= DMA_U | DMA_V;
+
+       return 0;
+
+fail_v:
+       dma_free_coherent(pcdev->dev, buf->dmas[1].sg_size,
+                         buf->dmas[1].sg_cpu, buf->dmas[1].sg_dma);
+fail_u:
+       dma_free_coherent(pcdev->dev, buf->dmas[0].sg_size,
+                         buf->dmas[0].sg_cpu, buf->dmas[0].sg_dma);
+fail:
+       free_buffer(vq, buf);
+out:
+       buf->inwork = 0;
+       return ret;
+}
+
+static void pxa_videobuf_queue(struct videobuf_queue *vq,
+                              struct videobuf_buffer *vb)
+{
+       struct soc_camera_device *icd = vq->priv_data;
+       struct soc_camera_host *ici =
+               to_soc_camera_host(icd->dev.parent);
+       struct pxa_camera_dev *pcdev = ici->priv;
+       struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb);
+       struct pxa_buffer *active;
+       unsigned long flags;
+       int i;
+
+       dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
+               vb, vb->baddr, vb->bsize);
+       spin_lock_irqsave(&pcdev->lock, flags);
+
+       list_add_tail(&vb->queue, &pcdev->capture);
+
+       vb->state = VIDEOBUF_ACTIVE;
+       active = pcdev->active;
+
+       if (!active) {
+               CIFR |= CIFR_RESET_F;
+
+               for (i = 0; i < pcdev->channels; i++) {
+                       DDADR(pcdev->dma_chans[i]) = buf->dmas[i].sg_dma;
+                       DCSR(pcdev->dma_chans[i]) = DCSR_RUN;
+                       pcdev->sg_tail[i] = buf->dmas[i].sg_cpu + buf->dmas[i].sglen - 1;
+               }
+
+               pcdev->active = buf;
+               CICR0 |= CICR0_ENB;
+       } else {
+               struct pxa_cam_dma *buf_dma;
+               struct pxa_cam_dma *act_dma;
+               int nents;
+
+               for (i = 0; i < pcdev->channels; i++) {
+                       buf_dma = &buf->dmas[i];
+                       act_dma = &active->dmas[i];
+                       nents = buf_dma->sglen;
+
+                       /* Stop DMA engine */
+                       DCSR(pcdev->dma_chans[i]) = 0;
+
+                       /* Add the descriptors we just initialized to
+                          the currently running chain */
+                       pcdev->sg_tail[i]->ddadr = buf_dma->sg_dma;
+                       pcdev->sg_tail[i] = buf_dma->sg_cpu + buf_dma->sglen - 1;
+
+                       /* Setup a dummy descriptor with the DMA engines current
+                        * state
+                        */
+                       buf_dma->sg_cpu[nents].dsadr =
+                               pcdev->res->start + 0x28 + i*8; /* CIBRx */
+                       buf_dma->sg_cpu[nents].dtadr =
+                               DTADR(pcdev->dma_chans[i]);
+                       buf_dma->sg_cpu[nents].dcmd =
+                               DCMD(pcdev->dma_chans[i]);
+
+                       if (DDADR(pcdev->dma_chans[i]) == DDADR_STOP) {
+                               /* The DMA engine is on the last
+                                  descriptor, set the next descriptors
+                                  address to the descriptors we just
+                                  initialized */
+                               buf_dma->sg_cpu[nents].ddadr = buf_dma->sg_dma;
+                       } else {
+                               buf_dma->sg_cpu[nents].ddadr =
+                                       DDADR(pcdev->dma_chans[i]);
+                       }
+
+                       /* The next descriptor is the dummy descriptor */
+                       DDADR(pcdev->dma_chans[i]) = buf_dma->sg_dma + nents *
+                               sizeof(struct pxa_dma_desc);
+
+                       DCSR(pcdev->dma_chans[i]) = DCSR_RUN;
+               }
+       }
+
+       spin_unlock_irqrestore(&pcdev->lock, flags);
+}
+
+static void pxa_videobuf_release(struct videobuf_queue *vq,
+                                struct videobuf_buffer *vb)
+{
+       struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb);
+#ifdef DEBUG
+       struct soc_camera_device *icd = vq->priv_data;
+
+       dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
+               vb, vb->baddr, vb->bsize);
+
+       switch (vb->state) {
+       case VIDEOBUF_ACTIVE:
+               dev_dbg(&icd->dev, "%s (active)\n", __func__);
+               break;
+       case VIDEOBUF_QUEUED:
+               dev_dbg(&icd->dev, "%s (queued)\n", __func__);
+               break;
+       case VIDEOBUF_PREPARED:
+               dev_dbg(&icd->dev, "%s (prepared)\n", __func__);
+               break;
+       default:
+               dev_dbg(&icd->dev, "%s (unknown)\n", __func__);
+               break;
+       }
+#endif
+
+       free_buffer(vq, buf);
+}
+
+static void pxa_camera_wakeup(struct pxa_camera_dev *pcdev,
+                             struct videobuf_buffer *vb,
+                             struct pxa_buffer *buf)
+{
+       /* _init is used to debug races, see comment in pxa_camera_reqbufs() */
+       list_del_init(&vb->queue);
+       vb->state = VIDEOBUF_DONE;
+       do_gettimeofday(&vb->ts);
+       vb->field_count++;
+       wake_up(&vb->done);
+
+       if (list_empty(&pcdev->capture)) {
+               pcdev->active = NULL;
+               DCSR(pcdev->dma_chans[0]) = 0;
+               DCSR(pcdev->dma_chans[1]) = 0;
+               DCSR(pcdev->dma_chans[2]) = 0;
+               CICR0 &= ~CICR0_ENB;
+               return;
+       }
+
+       pcdev->active = list_entry(pcdev->capture.next,
+                                  struct pxa_buffer, vb.queue);
+}
+
+static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev,
+                              enum pxa_camera_active_dma act_dma)
+{
+       struct pxa_buffer *buf;
+       unsigned long flags;
+       u32 status, camera_status, overrun;
+       struct videobuf_buffer *vb;
+
+       spin_lock_irqsave(&pcdev->lock, flags);
+
+       status = DCSR(channel);
+       DCSR(channel) = status | DCSR_ENDINTR;
+
+       if (status & DCSR_BUSERR) {
+               dev_err(pcdev->dev, "DMA Bus Error IRQ!\n");
+               goto out;
+       }
+
+       if (!(status & DCSR_ENDINTR)) {
+               dev_err(pcdev->dev, "Unknown DMA IRQ source, "
+                       "status: 0x%08x\n", status);
+               goto out;
+       }
+
+       if (!pcdev->active) {
+               dev_err(pcdev->dev, "DMA End IRQ with no active buffer!\n");
+               goto out;
+       }
+
+       camera_status = CISR;
+       overrun = CISR_IFO_0;
+       if (pcdev->channels == 3)
+               overrun |= CISR_IFO_1 | CISR_IFO_2;
+       if (camera_status & overrun) {
+               dev_dbg(pcdev->dev, "FIFO overrun! CISR: %x\n", camera_status);
+               /* Stop the Capture Interface */
+               CICR0 &= ~CICR0_ENB;
+               /* Stop DMA */
+               DCSR(channel) = 0;
+               /* Reset the FIFOs */
+               CIFR |= CIFR_RESET_F;
+               /* Enable End-Of-Frame Interrupt */
+               CICR0 &= ~CICR0_EOFM;
+               /* Restart the Capture Interface */
+               CICR0 |= CICR0_ENB;
+               goto out;
+       }
+
+       vb = &pcdev->active->vb;
+       buf = container_of(vb, struct pxa_buffer, vb);
+       WARN_ON(buf->inwork || list_empty(&vb->queue));
+       dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
+               vb, vb->baddr, vb->bsize);
+
+       buf->active_dma &= ~act_dma;
+       if (!buf->active_dma)
+               pxa_camera_wakeup(pcdev, vb, buf);
+
+out:
+       spin_unlock_irqrestore(&pcdev->lock, flags);
+}
+
+static void pxa_camera_dma_irq_y(int channel, void *data)
+{
+       struct pxa_camera_dev *pcdev = data;
+       pxa_camera_dma_irq(channel, pcdev, DMA_Y);
+}
+
+static void pxa_camera_dma_irq_u(int channel, void *data)
+{
+       struct pxa_camera_dev *pcdev = data;
+       pxa_camera_dma_irq(channel, pcdev, DMA_U);
+}
+
+static void pxa_camera_dma_irq_v(int channel, void *data)
+{
+       struct pxa_camera_dev *pcdev = data;
+       pxa_camera_dma_irq(channel, pcdev, DMA_V);
+}
+
+static struct videobuf_queue_ops pxa_videobuf_ops = {
+       .buf_setup      = pxa_videobuf_setup,
+       .buf_prepare    = pxa_videobuf_prepare,
+       .buf_queue      = pxa_videobuf_queue,
+       .buf_release    = pxa_videobuf_release,
+};
+
+static int mclk_get_divisor(struct pxa_camera_dev *pcdev)
+{
+       unsigned int mclk_10khz = pcdev->platform_mclk_10khz;
+       unsigned long div;
+       unsigned long lcdclk;
+
+       lcdclk = clk_get_rate(pcdev->clk) / 10000;
+
+       /* We verify platform_mclk_10khz != 0, so if anyone breaks it, here
+        * they get a nice Oops */
+       div = (lcdclk + 2 * mclk_10khz - 1) / (2 * mclk_10khz) - 1;
+
+       dev_dbg(pcdev->dev, "LCD clock %lukHz, target freq %dkHz, "
+               "divisor %lu\n", lcdclk * 10, mclk_10khz * 10, div);
+
+       return div;
+}
+
+static void pxa_camera_activate(struct pxa_camera_dev *pcdev)
+{
+       struct pxacamera_platform_data *pdata = pcdev->pdata;
+       u32 cicr4 = 0;
+
+       dev_dbg(pcdev->dev, "Registered platform device at %p data %p\n",
+               pcdev, pdata);
+
+       if (pdata && pdata->init) {
+               dev_dbg(pcdev->dev, "%s: Init gpios\n", __func__);
+               pdata->init(pcdev->dev);
+       }
+
+       if (pdata && pdata->power) {
+               dev_dbg(pcdev->dev, "%s: Power on camera\n", __func__);
+               pdata->power(pcdev->dev, 1);
+       }
+
+       if (pdata && pdata->reset) {
+               dev_dbg(pcdev->dev, "%s: Releasing camera reset\n",
+                       __func__);
+               pdata->reset(pcdev->dev, 1);
+       }
+
+       CICR0 = 0x3FF;   /* disable all interrupts */
+
+       if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN)
+               cicr4 |= CICR4_PCLK_EN;
+       if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN)
+               cicr4 |= CICR4_MCLK_EN;
+       if (pcdev->platform_flags & PXA_CAMERA_PCP)
+               cicr4 |= CICR4_PCP;
+       if (pcdev->platform_flags & PXA_CAMERA_HSP)
+               cicr4 |= CICR4_HSP;
+       if (pcdev->platform_flags & PXA_CAMERA_VSP)
+               cicr4 |= CICR4_VSP;
+
+       CICR4 = mclk_get_divisor(pcdev) | cicr4;
+
+       clk_enable(pcdev->clk);
+}
+
+static void pxa_camera_deactivate(struct pxa_camera_dev *pcdev)
+{
+       struct pxacamera_platform_data *board = pcdev->pdata;
+
+       clk_disable(pcdev->clk);
+
+       if (board && board->reset) {
+               dev_dbg(pcdev->dev, "%s: Asserting camera reset\n",
+                       __func__);
+               board->reset(pcdev->dev, 0);
+       }
+
+       if (board && board->power) {
+               dev_dbg(pcdev->dev, "%s: Power off camera\n", __func__);
+               board->power(pcdev->dev, 0);
+       }
+}
+
+static irqreturn_t pxa_camera_irq(int irq, void *data)
+{
+       struct pxa_camera_dev *pcdev = data;
+       unsigned int status = CISR;
+
+       dev_dbg(pcdev->dev, "Camera interrupt status 0x%x\n", status);
+
+       if (!status)
+               return IRQ_NONE;
+
+       CISR = status;
+
+       if (status & CISR_EOF) {
+               int i;
+               for (i = 0; i < pcdev->channels; i++) {
+                       DDADR(pcdev->dma_chans[i]) =
+                               pcdev->active->dmas[i].sg_dma;
+                       DCSR(pcdev->dma_chans[i]) = DCSR_RUN;
+               }
+               CICR0 |= CICR0_EOFM;
+       }
+
+       return IRQ_HANDLED;
+}
+
+/* The following two functions absolutely depend on the fact, that
+ * there can be only one camera on PXA quick capture interface */
+static int pxa_camera_add_device(struct soc_camera_device *icd)
+{
+       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct pxa_camera_dev *pcdev = ici->priv;
+       int ret;
+
+       mutex_lock(&camera_lock);
+
+       if (pcdev->icd) {
+               ret = -EBUSY;
+               goto ebusy;
+       }
+
+       dev_info(&icd->dev, "PXA Camera driver attached to camera %d\n",
+                icd->devnum);
+
+       pxa_camera_activate(pcdev);
+       ret = icd->ops->init(icd);
+
+       if (!ret)
+               pcdev->icd = icd;
+
+ebusy:
+       mutex_unlock(&camera_lock);
+
+       return ret;
+}
+
+static void pxa_camera_remove_device(struct soc_camera_device *icd)
+{
+       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct pxa_camera_dev *pcdev = ici->priv;
+
+       BUG_ON(icd != pcdev->icd);
+
+       dev_info(&icd->dev, "PXA Camera driver detached from camera %d\n",
+                icd->devnum);
+
+       /* disable capture, disable interrupts */
+       CICR0 = 0x3ff;
+
+       /* Stop DMA engine */
+       DCSR(pcdev->dma_chans[0]) = 0;
+       DCSR(pcdev->dma_chans[1]) = 0;
+       DCSR(pcdev->dma_chans[2]) = 0;
+
+       icd->ops->release(icd);
+
+       pxa_camera_deactivate(pcdev);
+
+       pcdev->icd = NULL;
+}
+
+static int test_platform_param(struct pxa_camera_dev *pcdev,
+                              unsigned char buswidth, unsigned long *flags)
+{
+       /*
+        * Platform specified synchronization and pixel clock polarities are
+        * only a recommendation and are only used during probing. The PXA270
+        * quick capture interface supports both.
+        */
+       *flags = (pcdev->platform_flags & PXA_CAMERA_MASTER ?
+                 SOCAM_MASTER : SOCAM_SLAVE) |
+               SOCAM_HSYNC_ACTIVE_HIGH |
+               SOCAM_HSYNC_ACTIVE_LOW |
+               SOCAM_VSYNC_ACTIVE_HIGH |
+               SOCAM_VSYNC_ACTIVE_LOW |
+               SOCAM_PCLK_SAMPLE_RISING |
+               SOCAM_PCLK_SAMPLE_FALLING;
+
+       /* If requested data width is supported by the platform, use it */
+       switch (buswidth) {
+       case 10:
+               if (!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_10))
+                       return -EINVAL;
+               *flags |= SOCAM_DATAWIDTH_10;
+               break;
+       case 9:
+               if (!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_9))
+                       return -EINVAL;
+               *flags |= SOCAM_DATAWIDTH_9;
+               break;
+       case 8:
+               if (!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_8))
+                       return -EINVAL;
+               *flags |= SOCAM_DATAWIDTH_8;
+       }
+
+       return 0;
+}
+
+static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
+{
+       struct soc_camera_host *ici =
+               to_soc_camera_host(icd->dev.parent);
+       struct pxa_camera_dev *pcdev = ici->priv;
+       unsigned long dw, bpp, bus_flags, camera_flags, common_flags;
+       u32 cicr0, cicr1, cicr4 = 0;
+       int ret = test_platform_param(pcdev, icd->buswidth, &bus_flags);
+
+       if (ret < 0)
+               return ret;
+
+       camera_flags = icd->ops->query_bus_param(icd);
+
+       common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags);
+       if (!common_flags)
+               return -EINVAL;
+
+       pcdev->channels = 1;
+
+       /* Make choises, based on platform preferences */
+       if ((common_flags & SOCAM_HSYNC_ACTIVE_HIGH) &&
+           (common_flags & SOCAM_HSYNC_ACTIVE_LOW)) {
+               if (pcdev->platform_flags & PXA_CAMERA_HSP)
+                       common_flags &= ~SOCAM_HSYNC_ACTIVE_HIGH;
+               else
+                       common_flags &= ~SOCAM_HSYNC_ACTIVE_LOW;
+       }
+
+       if ((common_flags & SOCAM_VSYNC_ACTIVE_HIGH) &&
+           (common_flags & SOCAM_VSYNC_ACTIVE_LOW)) {
+               if (pcdev->platform_flags & PXA_CAMERA_VSP)
+                       common_flags &= ~SOCAM_VSYNC_ACTIVE_HIGH;
+               else
+                       common_flags &= ~SOCAM_VSYNC_ACTIVE_LOW;
+       }
+
+       if ((common_flags & SOCAM_PCLK_SAMPLE_RISING) &&
+           (common_flags & SOCAM_PCLK_SAMPLE_FALLING)) {
+               if (pcdev->platform_flags & PXA_CAMERA_PCP)
+                       common_flags &= ~SOCAM_PCLK_SAMPLE_RISING;
+               else
+                       common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING;
+       }
+
+       ret = icd->ops->set_bus_param(icd, common_flags);
+       if (ret < 0)
+               return ret;
+
+       /* Datawidth is now guaranteed to be equal to one of the three values.
+        * We fix bit-per-pixel equal to data-width... */
+       switch (common_flags & SOCAM_DATAWIDTH_MASK) {
+       case SOCAM_DATAWIDTH_10:
+               icd->buswidth = 10;
+               dw = 4;
+               bpp = 0x40;
+               break;
+       case SOCAM_DATAWIDTH_9:
+               icd->buswidth = 9;
+               dw = 3;
+               bpp = 0x20;
+               break;
+       default:
+               /* Actually it can only be 8 now,
+                * default is just to silence compiler warnings */
+       case SOCAM_DATAWIDTH_8:
+               icd->buswidth = 8;
+               dw = 2;
+               bpp = 0;
+       }
+
+       if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN)
+               cicr4 |= CICR4_PCLK_EN;
+       if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN)
+               cicr4 |= CICR4_MCLK_EN;
+       if (common_flags & SOCAM_PCLK_SAMPLE_FALLING)
+               cicr4 |= CICR4_PCP;
+       if (common_flags & SOCAM_HSYNC_ACTIVE_LOW)
+               cicr4 |= CICR4_HSP;
+       if (common_flags & SOCAM_VSYNC_ACTIVE_LOW)
+               cicr4 |= CICR4_VSP;
+
+       cicr0 = CICR0;
+       if (cicr0 & CICR0_ENB)
+               CICR0 = cicr0 & ~CICR0_ENB;
+
+       cicr1 = CICR1_PPL_VAL(icd->width - 1) | bpp | dw;
+
+       switch (pixfmt) {
+       case V4L2_PIX_FMT_YUV422P:
+               pcdev->channels = 3;
+               cicr1 |= CICR1_YCBCR_F;
+       case V4L2_PIX_FMT_YUYV:
+               cicr1 |= CICR1_COLOR_SP_VAL(2);
+               break;
+       case V4L2_PIX_FMT_RGB555:
+               cicr1 |= CICR1_RGB_BPP_VAL(1) | CICR1_RGBT_CONV_VAL(2) |
+                       CICR1_TBIT | CICR1_COLOR_SP_VAL(1);
+               break;
+       case V4L2_PIX_FMT_RGB565:
+               cicr1 |= CICR1_COLOR_SP_VAL(1) | CICR1_RGB_BPP_VAL(2);
+               break;
+       }
+
+       CICR1 = cicr1;
+       CICR2 = 0;
+       CICR3 = CICR3_LPF_VAL(icd->height - 1) |
+               CICR3_BFW_VAL(min((unsigned short)255, icd->y_skip_top));
+       CICR4 = mclk_get_divisor(pcdev) | cicr4;
+
+       /* CIF interrupts are not used, only DMA */
+       CICR0 = (pcdev->platform_flags & PXA_CAMERA_MASTER ?
+                CICR0_SIM_MP : (CICR0_SL_CAP_EN | CICR0_SIM_SP)) |
+               CICR0_DMAEN | CICR0_IRQ_MASK | (cicr0 & CICR0_ENB);
+
+       return 0;
+}
+
+static int pxa_camera_try_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
+{
+       struct soc_camera_host *ici =
+               to_soc_camera_host(icd->dev.parent);
+       struct pxa_camera_dev *pcdev = ici->priv;
+       unsigned long bus_flags, camera_flags;
+       int ret = test_platform_param(pcdev, icd->buswidth, &bus_flags);
+
+       if (ret < 0)
+               return ret;
+
+       camera_flags = icd->ops->query_bus_param(icd);
+
+       return soc_camera_bus_param_compatible(camera_flags, bus_flags) ? 0 : -EINVAL;
+}
+
+static int pxa_camera_set_fmt_cap(struct soc_camera_device *icd,
+                                 __u32 pixfmt, struct v4l2_rect *rect)
+{
+       return icd->ops->set_fmt_cap(icd, pixfmt, rect);
+}
+
+static int pxa_camera_try_fmt_cap(struct soc_camera_device *icd,
+                                 struct v4l2_format *f)
+{
+       /* limit to pxa hardware capabilities */
+       if (f->fmt.pix.height < 32)
+               f->fmt.pix.height = 32;
+       if (f->fmt.pix.height > 2048)
+               f->fmt.pix.height = 2048;
+       if (f->fmt.pix.width < 48)
+               f->fmt.pix.width = 48;
+       if (f->fmt.pix.width > 2048)
+               f->fmt.pix.width = 2048;
+       f->fmt.pix.width &= ~0x01;
+
+       /* limit to sensor capabilities */
+       return icd->ops->try_fmt_cap(icd, f);
+}
+
+static int pxa_camera_reqbufs(struct soc_camera_file *icf,
+                             struct v4l2_requestbuffers *p)
+{
+       int i;
+
+       /* This is for locking debugging only. I removed spinlocks and now I
+        * check whether .prepare is ever called on a linked buffer, or whether
+        * a dma IRQ can occur for an in-work or unlinked buffer. Until now
+        * it hadn't triggered */
+       for (i = 0; i < p->count; i++) {
+               struct pxa_buffer *buf = container_of(icf->vb_vidq.bufs[i],
+                                                     struct pxa_buffer, vb);
+               buf->inwork = 0;
+               INIT_LIST_HEAD(&buf->vb.queue);
+       }
+
+       return 0;
+}
+
+static unsigned int pxa_camera_poll(struct file *file, poll_table *pt)
+{
+       struct soc_camera_file *icf = file->private_data;
+       struct pxa_buffer *buf;
+
+       buf = list_entry(icf->vb_vidq.stream.next, struct pxa_buffer,
+                        vb.stream);
+
+       poll_wait(file, &buf->vb.done, pt);
+
+       if (buf->vb.state == VIDEOBUF_DONE ||
+           buf->vb.state == VIDEOBUF_ERROR)
+               return POLLIN|POLLRDNORM;
+
+       return 0;
+}
+
+static int pxa_camera_querycap(struct soc_camera_host *ici,
+                              struct v4l2_capability *cap)
+{
+       /* cap->name is set by the firendly caller:-> */
+       strlcpy(cap->card, pxa_cam_driver_description, sizeof(cap->card));
+       cap->version = PXA_CAM_VERSION_CODE;
+       cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
+
+       return 0;
+}
+
+static spinlock_t *pxa_camera_spinlock_alloc(struct soc_camera_file *icf)
+{
+       struct soc_camera_host *ici =
+               to_soc_camera_host(icf->icd->dev.parent);
+       struct pxa_camera_dev *pcdev = ici->priv;
+
+       return &pcdev->lock;
+}
+
+static struct soc_camera_host_ops pxa_soc_camera_host_ops = {
+       .owner          = THIS_MODULE,
+       .add            = pxa_camera_add_device,
+       .remove         = pxa_camera_remove_device,
+       .set_fmt_cap    = pxa_camera_set_fmt_cap,
+       .try_fmt_cap    = pxa_camera_try_fmt_cap,
+       .reqbufs        = pxa_camera_reqbufs,
+       .poll           = pxa_camera_poll,
+       .querycap       = pxa_camera_querycap,
+       .try_bus_param  = pxa_camera_try_bus_param,
+       .set_bus_param  = pxa_camera_set_bus_param,
+       .spinlock_alloc = pxa_camera_spinlock_alloc,
+};
+
+/* Should be allocated dynamically too, but we have only one. */
+static struct soc_camera_host pxa_soc_camera_host = {
+       .drv_name               = PXA_CAM_DRV_NAME,
+       .vbq_ops                = &pxa_videobuf_ops,
+       .msize                  = sizeof(struct pxa_buffer),
+       .ops                    = &pxa_soc_camera_host_ops,
+};
+
+static int pxa_camera_probe(struct platform_device *pdev)
+{
+       struct pxa_camera_dev *pcdev;
+       struct resource *res;
+       void __iomem *base;
+       unsigned int irq;
+       int err = 0;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       irq = platform_get_irq(pdev, 0);
+       if (!res || !irq) {
+               err = -ENODEV;
+               goto exit;
+       }
+
+       pcdev = kzalloc(sizeof(*pcdev), GFP_KERNEL);
+       if (!pcdev) {
+               dev_err(&pdev->dev, "Could not allocate pcdev\n");
+               err = -ENOMEM;
+               goto exit;
+       }
+
+       pcdev->clk = clk_get(&pdev->dev, "CAMCLK");
+       if (IS_ERR(pcdev->clk)) {
+               err = PTR_ERR(pcdev->clk);
+               goto exit_kfree;
+       }
+
+       dev_set_drvdata(&pdev->dev, pcdev);
+       pcdev->res = res;
+
+       pcdev->pdata = pdev->dev.platform_data;
+       pcdev->platform_flags = pcdev->pdata->flags;
+       if (!(pcdev->platform_flags & (PXA_CAMERA_DATAWIDTH_8 |
+                       PXA_CAMERA_DATAWIDTH_9 | PXA_CAMERA_DATAWIDTH_10))) {
+               /* Platform hasn't set available data widths. This is bad.
+                * Warn and use a default. */
+               dev_warn(&pdev->dev, "WARNING! Platform hasn't set available "
+                        "data widths, using default 10 bit\n");
+               pcdev->platform_flags |= PXA_CAMERA_DATAWIDTH_10;
+       }
+       pcdev->platform_mclk_10khz = pcdev->pdata->mclk_10khz;
+       if (!pcdev->platform_mclk_10khz) {
+               dev_warn(&pdev->dev,
+                        "mclk_10khz == 0! Please, fix your platform data. "
+                        "Using default 20MHz\n");
+               pcdev->platform_mclk_10khz = 2000;
+       }
+
+       INIT_LIST_HEAD(&pcdev->capture);
+       spin_lock_init(&pcdev->lock);
+
+       /*
+        * Request the regions.
+        */
+       if (!request_mem_region(res->start, res->end - res->start + 1,
+                               PXA_CAM_DRV_NAME)) {
+               err = -EBUSY;
+               goto exit_clk;
+       }
+
+       base = ioremap(res->start, res->end - res->start + 1);
+       if (!base) {
+               err = -ENOMEM;
+               goto exit_release;
+       }
+       pcdev->irq = irq;
+       pcdev->base = base;
+       pcdev->dev = &pdev->dev;
+
+       /* request dma */
+       pcdev->dma_chans[0] = pxa_request_dma("CI_Y", DMA_PRIO_HIGH,
+                                             pxa_camera_dma_irq_y, pcdev);
+       if (pcdev->dma_chans[0] < 0) {
+               dev_err(pcdev->dev, "Can't request DMA for Y\n");
+               err = -ENOMEM;
+               goto exit_iounmap;
+       }
+       dev_dbg(pcdev->dev, "got DMA channel %d\n", pcdev->dma_chans[0]);
+
+       pcdev->dma_chans[1] = pxa_request_dma("CI_U", DMA_PRIO_HIGH,
+                                             pxa_camera_dma_irq_u, pcdev);
+       if (pcdev->dma_chans[1] < 0) {
+               dev_err(pcdev->dev, "Can't request DMA for U\n");
+               err = -ENOMEM;
+               goto exit_free_dma_y;
+       }
+       dev_dbg(pcdev->dev, "got DMA channel (U) %d\n", pcdev->dma_chans[1]);
+
+       pcdev->dma_chans[2] = pxa_request_dma("CI_V", DMA_PRIO_HIGH,
+                                             pxa_camera_dma_irq_v, pcdev);
+       if (pcdev->dma_chans[0] < 0) {
+               dev_err(pcdev->dev, "Can't request DMA for V\n");
+               err = -ENOMEM;
+               goto exit_free_dma_u;
+       }
+       dev_dbg(pcdev->dev, "got DMA channel (V) %d\n", pcdev->dma_chans[2]);
+
+       DRCMR68 = pcdev->dma_chans[0] | DRCMR_MAPVLD;
+       DRCMR69 = pcdev->dma_chans[1] | DRCMR_MAPVLD;
+       DRCMR70 = pcdev->dma_chans[2] | DRCMR_MAPVLD;
+
+       /* request irq */
+       err = request_irq(pcdev->irq, pxa_camera_irq, 0, PXA_CAM_DRV_NAME,
+                         pcdev);
+       if (err) {
+               dev_err(pcdev->dev, "Camera interrupt register failed \n");
+               goto exit_free_dma;
+       }
+
+       pxa_soc_camera_host.priv        = pcdev;
+       pxa_soc_camera_host.dev.parent  = &pdev->dev;
+       pxa_soc_camera_host.nr          = pdev->id;
+       err = soc_camera_host_register(&pxa_soc_camera_host);
+       if (err)
+               goto exit_free_irq;
+
+       return 0;
+
+exit_free_irq:
+       free_irq(pcdev->irq, pcdev);
+exit_free_dma:
+       pxa_free_dma(pcdev->dma_chans[2]);
+exit_free_dma_u:
+       pxa_free_dma(pcdev->dma_chans[1]);
+exit_free_dma_y:
+       pxa_free_dma(pcdev->dma_chans[0]);
+exit_iounmap:
+       iounmap(base);
+exit_release:
+       release_mem_region(res->start, res->end - res->start + 1);
+exit_clk:
+       clk_put(pcdev->clk);
+exit_kfree:
+       kfree(pcdev);
+exit:
+       return err;
+}
+
+static int __devexit pxa_camera_remove(struct platform_device *pdev)
+{
+       struct pxa_camera_dev *pcdev = platform_get_drvdata(pdev);
+       struct resource *res;
+
+       clk_put(pcdev->clk);
+
+       pxa_free_dma(pcdev->dma_chans[0]);
+       pxa_free_dma(pcdev->dma_chans[1]);
+       pxa_free_dma(pcdev->dma_chans[2]);
+       free_irq(pcdev->irq, pcdev);
+
+       soc_camera_host_unregister(&pxa_soc_camera_host);
+
+       iounmap(pcdev->base);
+
+       res = pcdev->res;
+       release_mem_region(res->start, res->end - res->start + 1);
+
+       kfree(pcdev);
+
+       dev_info(&pdev->dev, "PXA Camera driver unloaded\n");
+
+       return 0;
+}
+
+static struct platform_driver pxa_camera_driver = {
+       .driver         = {
+               .name   = PXA_CAM_DRV_NAME,
+       },
+       .probe          = pxa_camera_probe,
+       .remove         = __exit_p(pxa_camera_remove),
+};
+
+
+static int __devinit pxa_camera_init(void)
+{
+       return platform_driver_register(&pxa_camera_driver);
+}
+
+static void __exit pxa_camera_exit(void)
+{
+       return platform_driver_unregister(&pxa_camera_driver);
+}
+
+module_init(pxa_camera_init);
+module_exit(pxa_camera_exit);
+
+MODULE_DESCRIPTION("PXA27x SoC Camera Host driver");
+MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>");
+MODULE_LICENSE("GPL");
index f55d6e85f20f34c59d93e4ae9a5f70c59ecd0a32..ec8c65dc8408506ae02786a4dc7e2e982f63f21f 100644 (file)
@@ -701,7 +701,9 @@ static const struct file_operations saa_fops = {
        .open           = saa5249_open,
        .release        = saa5249_release,
        .ioctl          = saa5249_ioctl,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .llseek         = no_llseek,
 };
 
index 72e344a12c798e86a5ca06db54c4c7a8059e423b..716ee7f64df3c017deffdd15dbf899e48fb8840c 100644 (file)
@@ -44,10 +44,10 @@ static unsigned short normal_i2c[] = {
 I2C_CLIENT_INSMOD;
 
 /* insmod options */
-static unsigned int debug = 0;
-static unsigned int xtal = 0;
-static unsigned int rbds = 0;
-static unsigned int plvl = 0;
+static unsigned int debug;
+static unsigned int xtal;
+static unsigned int rbds;
+static unsigned int plvl;
 static unsigned int bufblocks = 100;
 
 module_param(debug, int, 0644);
index 1df2602cd1842c40d0ed1a9ca56d2793221e8a0c..4aa82b310708c768140e50b698e81932d21e94a0 100644 (file)
@@ -46,7 +46,7 @@ MODULE_LICENSE("GPL");
 #include <media/v4l2-common.h>
 #include <linux/video_decoder.h>
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0-1)");
 
index a0772c53bb1f5e78c8dd2a00b5dd529664805683..96c3d4357722fb32d279a8f63aae8a7318c6b7d5 100644 (file)
@@ -55,7 +55,7 @@ MODULE_LICENSE("GPL");
 #define I2C_NAME(s) (s)->name
 
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Debug level (0-1)");
 
index bf91a4faa706f154903b9be9f7069fb9e55ded2a..e79075533beb2bcc9ffc90825d8777e5cf0c033f 100644 (file)
@@ -56,7 +56,7 @@ MODULE_LICENSE("GPL");
 #define I2C_NAME(x) (x)->name
 
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0-1)");
 
index 41e5e518a47e21926245fc8deca0d115f2edf8dc..416d05d4a969088d02d2f1c5a319de4fb215fe68 100644 (file)
@@ -57,7 +57,7 @@ MODULE_AUTHOR(  "Maxim Yevtyushkin, Kevin Thayer, Chris Kennedy, "
                "Hans Verkuil, Mauro Carvalho Chehab");
 MODULE_LICENSE("GPL");
 
-static int debug = 0;
+static int debug;
 module_param(debug, bool, 0644);
 
 MODULE_PARM_DESC(debug, "Debug level (0-1)");
@@ -957,7 +957,7 @@ static void saa711x_set_v4lstd(struct i2c_client *client, v4l2_std_id std)
 
                if (std == V4L2_STD_PAL_M) {
                        reg |= 0x30;
-               } else if (std == V4L2_STD_PAL_N) {
+               } else if (std == V4L2_STD_PAL_Nc) {
                        reg |= 0x20;
                } else if (std == V4L2_STD_PAL_60) {
                        reg |= 0x10;
index 80bf9118785624bdbdbbc68e8c46545f47a6b608..cedb988574bdbcf65023d2ddc777c046ff64fd17 100644 (file)
@@ -48,7 +48,7 @@ MODULE_LICENSE("GPL");
 
 #include <linux/video_decoder.h>
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, " Set the default Debug level.  Default: 0 (Off) - (0-1)");
 
index 96bc3b1298a2564389b262e843b49622da4fde44..e086f14d56639ef458e1c69be6dd83eaa7d50f57 100644 (file)
@@ -37,6 +37,7 @@ config VIDEO_SAA7134_DVB
        select DVB_TDA826X if !DVB_FE_CUSTOMISE
        select DVB_TDA827X if !DVB_FE_CUSTOMISE
        select DVB_ISL6421 if !DVB_FE_CUSTOMISE
+       select TUNER_SIMPLE if !DVB_FE_CUSTOMISE
        ---help---
          This adds support for DVB cards based on the
          Philips saa7134 chip.
index 047add8f3010efae75fd7128e2d293b75206e1e4..ba3082422a01915dce20bce15832c495e9555d89 100644 (file)
@@ -31,7 +31,7 @@
 #include "saa7134.h"
 #include "saa7134-reg.h"
 
-static unsigned int debug  = 0;
+static unsigned int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug,"enable debug messages [alsa]");
 
@@ -503,7 +503,7 @@ static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream,
        /* release the old buffer */
        if (substream->runtime->dma_area) {
                saa7134_pgtable_free(dev->pci, &dev->dmasound.pt);
-               videobuf_pci_dma_unmap(dev->pci, &dev->dmasound.dma);
+               videobuf_sg_dma_unmap(&dev->pci->dev, &dev->dmasound.dma);
                dsp_buffer_free(dev);
                substream->runtime->dma_area = NULL;
        }
@@ -519,12 +519,12 @@ static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream,
                return err;
        }
 
-       if (0 != (err = videobuf_pci_dma_map(dev->pci, &dev->dmasound.dma))) {
+       if (0 != (err = videobuf_sg_dma_map(&dev->pci->dev, &dev->dmasound.dma))) {
                dsp_buffer_free(dev);
                return err;
        }
        if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->dmasound.pt))) {
-               videobuf_pci_dma_unmap(dev->pci, &dev->dmasound.dma);
+               videobuf_sg_dma_unmap(&dev->pci->dev, &dev->dmasound.dma);
                dsp_buffer_free(dev);
                return err;
        }
@@ -533,7 +533,7 @@ static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream,
                                                dev->dmasound.dma.sglen,
                                                0))) {
                saa7134_pgtable_free(dev->pci, &dev->dmasound.pt);
-               videobuf_pci_dma_unmap(dev->pci, &dev->dmasound.dma);
+               videobuf_sg_dma_unmap(&dev->pci->dev, &dev->dmasound.dma);
                dsp_buffer_free(dev);
                return err;
        }
@@ -569,7 +569,7 @@ static int snd_card_saa7134_hw_free(struct snd_pcm_substream * substream)
 
        if (substream->runtime->dma_area) {
                saa7134_pgtable_free(dev->pci, &dev->dmasound.pt);
-               videobuf_pci_dma_unmap(dev->pci, &dev->dmasound.dma);
+               videobuf_sg_dma_unmap(&dev->pci->dev, &dev->dmasound.dma);
                dsp_buffer_free(dev);
                substream->runtime->dma_area = NULL;
        }
@@ -954,10 +954,8 @@ static void snd_saa7134_free(struct snd_card * card)
        if (chip->dev->dmasound.priv_data == NULL)
                return;
 
-       if (chip->irq >= 0) {
-               synchronize_irq(chip->irq);
+       if (chip->irq >= 0)
                free_irq(chip->irq, &chip->dev->dmasound);
-       }
 
        chip->dev->dmasound.priv_data = NULL;
 
index 6f5744286e8c2044aece263c1e4d65ff66a5c629..98375955a84b7c42e62b34a83cf76dc358d0c52f 100644 (file)
 
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
 
 #include "saa7134-reg.h"
 #include "saa7134.h"
+#include "tuner-xc2028.h"
 #include <media/v4l2-common.h>
 #include <media/tveeprom.h>
+#include "tea5767.h"
 
 /* commly used strings */
 static char name_mute[]    = "mute";
@@ -1046,7 +1050,7 @@ struct saa7134_board saa7134_boards[] = {
        },
        [SAA7134_BOARD_MANLI_MTV002] = {
                /* Ognjen Nastic <ognjen@logosoft.ba> */
-               .name           = "Manli MuchTV M-TV002/Behold TV 403 FM",
+               .name           = "Manli MuchTV M-TV002",
                .audio_clock    = 0x00200000,
                .tuner_type     = TUNER_PHILIPS_PAL,
                .radio_type     = UNSET,
@@ -1073,7 +1077,7 @@ struct saa7134_board saa7134_boards[] = {
        },
        [SAA7134_BOARD_MANLI_MTV001] = {
                /* Ognjen Nastic <ognjen@logosoft.ba> UNTESTED */
-               .name           = "Manli MuchTV M-TV001/Behold TV 401",
+               .name           = "Manli MuchTV M-TV001",
                .audio_clock    = 0x00200000,
                .tuner_type     = TUNER_PHILIPS_PAL,
                .radio_type     = UNSET,
@@ -2195,6 +2199,8 @@ struct saa7134_board saa7134_boards[] = {
        },
        [SAA7134_BOARD_BEHOLD_409FM] = {
                /* <http://tuner.beholder.ru>, Sergey <skiv@orel.ru> */
+               /*       Beholder Intl. Ltd. 2008      */
+               /*Dmitry Belimov <d.belimov@gmail.com> */
                .name           = "Beholder BeholdTV 409 FM",
                .audio_clock    = 0x00187de7,
                .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
@@ -2202,6 +2208,7 @@ struct saa7134_board saa7134_boards[] = {
                .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
                .tda9887_conf   = TDA9887_PRESENT,
+               .gpiomask       = 0x00008000,
                .inputs         = {{
                          .name = name_tv,
                          .vmux = 3,
@@ -2908,15 +2915,13 @@ struct saa7134_board saa7134_boards[] = {
                }},
        },
        [SAA7134_BOARD_MD7134_BRIDGE_2] = {
-               /* This card has two saa7134 chips on it,
-                  but only one of them is currently working.
-                  The programming for the primary decoder is
-                  in SAA7134_BOARD_MD7134 */
+               /* The second saa7134 on this card only serves as DVB-S host bridge */
                .name           = "Medion 7134 Bridge #2",
                .audio_clock    = 0x00187de7,
                .radio_type     = UNSET,
                .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
+               .mpeg           = SAA7134_MPEG_DVB,
        },
        [SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS] = {
                .name           = "LifeView FlyDVB-T Hybrid Cardbus/MSI TV @nywhere A/D NB",
@@ -3330,7 +3335,7 @@ struct saa7134_board saa7134_boards[] = {
   /*   Juan Pablo Sormani <sorman@gmail.com> */
                .name           = "Encore ENLTV-FM",
                .audio_clock    = 0x00200000,
-               .tuner_type     = TUNER_PHILIPS_ATSC,
+               .tuner_type     = TUNER_PHILIPS_FCV1236D,
                .radio_type     = UNSET,
                .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
@@ -3575,12 +3580,15 @@ struct saa7134_board saa7134_boards[] = {
                }},
        },
        [SAA7134_BOARD_BEHOLD_401] = {
+               /*       Beholder Intl. Ltd. 2008      */
+               /*Dmitry Belimov <d.belimov@gmail.com> */
                .name           = "Beholder BeholdTV 401",
                .audio_clock    = 0x00187de7,
                .tuner_type     = TUNER_PHILIPS_FQ1216ME,
                .radio_type     = UNSET,
                .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
+               .gpiomask       = 0x00008000,
                .inputs         = {{
                        .name = name_svideo,
                        .vmux = 8,
@@ -3601,12 +3609,15 @@ struct saa7134_board saa7134_boards[] = {
                },
        },
        [SAA7134_BOARD_BEHOLD_403] = {
+               /*       Beholder Intl. Ltd. 2008      */
+               /*Dmitry Belimov <d.belimov@gmail.com> */
                .name           = "Beholder BeholdTV 403",
                .audio_clock    = 0x00187de7,
                .tuner_type     = TUNER_PHILIPS_FQ1216ME,
                .radio_type     = UNSET,
                .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
+               .gpiomask       = 0x00008000,
                .inputs         = {{
                        .name = name_svideo,
                        .vmux = 8,
@@ -3623,12 +3634,15 @@ struct saa7134_board saa7134_boards[] = {
                }},
        },
        [SAA7134_BOARD_BEHOLD_403FM] = {
+               /*       Beholder Intl. Ltd. 2008      */
+               /*Dmitry Belimov <d.belimov@gmail.com> */
                .name           = "Beholder BeholdTV 403 FM",
                .audio_clock    = 0x00187de7,
                .tuner_type     = TUNER_PHILIPS_FQ1216ME,
                .radio_type     = UNSET,
                .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
+               .gpiomask       = 0x00008000,
                .inputs         = {{
                        .name = name_svideo,
                        .vmux = 8,
@@ -3649,6 +3663,8 @@ struct saa7134_board saa7134_boards[] = {
                },
        },
        [SAA7134_BOARD_BEHOLD_405] = {
+               /*       Beholder Intl. Ltd. 2008      */
+               /*Dmitry Belimov <d.belimov@gmail.com> */
                .name           = "Beholder BeholdTV 405",
                .audio_clock    = 0x00187de7,
                .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
@@ -3656,6 +3672,7 @@ struct saa7134_board saa7134_boards[] = {
                .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
                .tda9887_conf   = TDA9887_PRESENT,
+               .gpiomask       = 0x00008000,
                .inputs         = {{
                        .name = name_svideo,
                        .vmux = 8,
@@ -3673,6 +3690,8 @@ struct saa7134_board saa7134_boards[] = {
        },
        [SAA7134_BOARD_BEHOLD_405FM] = {
                /* Sergey <skiv@orel.ru> */
+               /*       Beholder Intl. Ltd. 2008      */
+               /*Dmitry Belimov <d.belimov@gmail.com> */
                .name           = "Beholder BeholdTV 405 FM",
                .audio_clock    = 0x00187de7,
                .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
@@ -3680,6 +3699,7 @@ struct saa7134_board saa7134_boards[] = {
                .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
                .tda9887_conf   = TDA9887_PRESENT,
+               .gpiomask       = 0x00008000,
                .inputs         = {{
                        .name = name_svideo,
                        .vmux = 8,
@@ -3700,6 +3720,8 @@ struct saa7134_board saa7134_boards[] = {
                },
        },
        [SAA7134_BOARD_BEHOLD_407] = {
+               /*       Beholder Intl. Ltd. 2008      */
+               /*Dmitry Belimov <d.belimov@gmail.com> */
                .name           = "Beholder BeholdTV 407",
                .audio_clock    = 0x00187de7,
                .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
@@ -3707,7 +3729,7 @@ struct saa7134_board saa7134_boards[] = {
                .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
                .tda9887_conf   = TDA9887_PRESENT,
-               .gpiomask = 0xc0c000,
+               .gpiomask       = 0x00008000,
                .inputs = {{
                        .name = name_svideo,
                        .vmux = 8,
@@ -3727,6 +3749,8 @@ struct saa7134_board saa7134_boards[] = {
                }},
        },
        [SAA7134_BOARD_BEHOLD_407FM] = {
+               /*       Beholder Intl. Ltd. 2008      */
+               /*Dmitry Belimov <d.belimov@gmail.com> */
                .name           = "Beholder BeholdTV 407 FM",
                .audio_clock    = 0x00187de7,
                .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
@@ -3734,7 +3758,7 @@ struct saa7134_board saa7134_boards[] = {
                .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
                .tda9887_conf   = TDA9887_PRESENT,
-               .gpiomask = 0xc0c000,
+               .gpiomask       = 0x00008000,
                .inputs = {{
                        .name = name_svideo,
                        .vmux = 8,
@@ -3759,6 +3783,8 @@ struct saa7134_board saa7134_boards[] = {
                },
        },
        [SAA7134_BOARD_BEHOLD_409] = {
+               /*       Beholder Intl. Ltd. 2008      */
+               /*Dmitry Belimov <d.belimov@gmail.com> */
                .name           = "Beholder BeholdTV 409",
                .audio_clock    = 0x00187de7,
                .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
@@ -3766,6 +3792,7 @@ struct saa7134_board saa7134_boards[] = {
                .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
                .tda9887_conf   = TDA9887_PRESENT,
+               .gpiomask       = 0x00008000,
                .inputs         = {{
                        .name = name_tv,
                        .vmux = 3,
@@ -3782,6 +3809,8 @@ struct saa7134_board saa7134_boards[] = {
                }},
        },
        [SAA7134_BOARD_BEHOLD_505FM] = {
+               /*       Beholder Intl. Ltd. 2008      */
+               /*Dmitry Belimov <d.belimov@gmail.com> */
                .name           = "Beholder BeholdTV 505 FM/RDS",
                .audio_clock    = 0x00200000,
                .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
@@ -3789,6 +3818,7 @@ struct saa7134_board saa7134_boards[] = {
                .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
                .tda9887_conf   = TDA9887_PRESENT,
+               .gpiomask       = 0x00008000,
                .inputs         = {{
                        .name = name_tv,
                        .vmux = 3,
@@ -3813,6 +3843,8 @@ struct saa7134_board saa7134_boards[] = {
                },
        },
        [SAA7134_BOARD_BEHOLD_507_9FM] = {
+               /*       Beholder Intl. Ltd. 2008      */
+               /*Dmitry Belimov <d.belimov@gmail.com> */
                .name           = "Beholder BeholdTV 507 FM/RDS / BeholdTV 509 FM",
                .audio_clock    = 0x00187de7,
                .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
@@ -3820,6 +3852,7 @@ struct saa7134_board saa7134_boards[] = {
                .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
                .tda9887_conf   = TDA9887_PRESENT,
+               .gpiomask       = 0x00008000,
                .inputs         = {{
                        .name = name_tv,
                        .vmux = 3,
@@ -3840,6 +3873,8 @@ struct saa7134_board saa7134_boards[] = {
                },
        },
        [SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM] = {
+               /*       Beholder Intl. Ltd. 2008      */
+               /*Dmitry Belimov <d.belimov@gmail.com> */
                .name           = "Beholder BeholdTV Columbus TVFM",
                .audio_clock    = 0x00187de7,
                .tuner_type     = TUNER_ALPS_TSBE5_PAL,
@@ -3847,23 +3882,28 @@ struct saa7134_board saa7134_boards[] = {
                .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
                .tda9887_conf   = TDA9887_PRESENT,
+               .gpiomask       = 0x000A8004,
                .inputs         = {{
                        .name = name_tv,
                        .vmux = 3,
                        .amux = TV,
                        .tv   = 1,
-               },{
+                       .gpio = 0x000A8004,
+               }, {
                        .name = name_comp1,
                        .vmux = 1,
                        .amux = LINE1,
-               },{
+                       .gpio = 0x000A8000,
+               }, {
                        .name = name_svideo,
                        .vmux = 8,
                        .amux = LINE1,
-               }},
+                       .gpio = 0x000A8000,
+               } },
                .radio = {
                        .name = name_radio,
                        .amux = LINE2,
+                       .gpio = 0x000A8000,
                },
        },
        [SAA7134_BOARD_BEHOLD_607_9FM] = {
@@ -3992,6 +4032,221 @@ struct saa7134_board saa7134_boards[] = {
                        .gpio = 0x6000,
                },
        },
+       [SAA7134_BOARD_PHILIPS_SNAKE] = {
+               .name           = "NXP Snake DVB-S reference design",
+               .audio_clock    = 0x00200000,
+               .tuner_type     = TUNER_ABSENT,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .inputs = {{
+                       .name   = name_comp1,
+                       .vmux   = 3,
+                       .amux   = LINE1,
+               }, {
+                       .name   = name_svideo,
+                       .vmux   = 8,
+                       .amux   = LINE1,
+               } },
+       },
+       [SAA7134_BOARD_CREATIX_CTX953] = {
+               .name         = "Medion/Creatix CTX953 Hybrid",
+               .audio_clock  = 0x00187de7,
+               .tuner_type   = TUNER_PHILIPS_TDA8290,
+               .radio_type   = UNSET,
+               .tuner_addr   = ADDR_UNSET,
+               .radio_addr   = ADDR_UNSET,
+               .tuner_config = 0,
+               .mpeg         = SAA7134_MPEG_DVB,
+               .inputs       = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+               }, {
+                       .name = name_comp1,
+                       .vmux = 0,
+                       .amux = LINE1,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               } },
+       },
+       [SAA7134_BOARD_MSI_TVANYWHERE_AD11] = {
+               .name           = "MSI TV@nywhere A/D v1.1",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tuner_config   = 2,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .gpiomask       = 0x0200000,
+               .inputs = { {
+                       .name   = name_tv,
+                       .vmux   = 1,
+                       .amux   = TV,
+                       .tv     = 1,
+               }, {
+                       .name   = name_comp1,
+                       .vmux   = 3,
+                       .amux   = LINE1,
+               }, {
+                       .name   = name_svideo,
+                       .vmux   = 8,
+                       .amux   = LINE1,
+               } },
+               .radio = {
+                       .name   = name_radio,
+                       .amux   = TV,
+                       .gpio   = 0x0200000,
+               },
+       },
+       [SAA7134_BOARD_AVERMEDIA_CARDBUS_506] = {
+               .name           = "AVerMedia Cardbus TV/Radio (E506R)",
+               .audio_clock    = 0x187de7,
+               .tuner_type     = TUNER_XC2028,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+                /*
+                   TODO:
+                .mpeg           = SAA7134_MPEG_DVB,
+                */
+
+                .inputs         = {{
+                        .name = name_tv,
+                        .vmux = 1,
+                        .amux = TV,
+                        .tv   = 1,
+                }, {
+                        .name = name_comp1,
+                        .vmux = 3,
+                        .amux = LINE2,
+                }, {
+                        .name = name_svideo,
+                        .vmux = 8,
+                        .amux = LINE1,
+                } },
+                .radio = {
+                        .name = name_radio,
+                        .amux = TV,
+                },
+       },
+       [SAA7134_BOARD_AVERMEDIA_A16D] = {
+               .name           = "AVerMedia Hybrid TV/Radio (A16D)",
+               .audio_clock    = 0x187de7,
+               .tuner_type     = TUNER_XC2028,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               } },
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE1,
+               },
+       },
+       [SAA7134_BOARD_AVERMEDIA_M115] = {
+               .name           = "Avermedia M115",
+               .audio_clock    = 0x187de7,
+               .tuner_type     = TUNER_XC2028,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+               }, {
+                       .name = name_comp1,
+                       .vmux = 3,
+                       .amux = LINE1,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE2,
+               } },
+       },
+       [SAA7134_BOARD_VIDEOMATE_T750] = {
+               /* John Newbigin <jn@it.swin.edu.au> */
+               .name           = "Compro VideoMate T750",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_XC2028,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .inputs = {{
+                       .name   = name_tv,
+                       .vmux   = 3,
+                       .amux   = TV,
+                       .tv     = 1,
+               }, {
+                       .name   = name_comp1,
+                       .vmux   = 1,
+                       .amux   = LINE2,
+               }, {
+                       .name   = name_svideo,
+                       .vmux   = 8,
+                       .amux   = LINE2,
+               } },
+               .radio = {
+                       .name = name_radio,
+                       .amux = TV,
+               }
+       },
+       [SAA7134_BOARD_AVERMEDIA_A700_PRO] = {
+               /* Matthias Schwarzott <zzam@gentoo.org> */
+               .name           = "Avermedia DVB-S Pro A700",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_ABSENT,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               /* no DVB support for now */
+               /* .mpeg           = SAA7134_MPEG_DVB, */
+               .inputs         = { {
+                       .name = name_comp,
+                       .vmux = 1,
+                       .amux = LINE1,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 6,
+                       .amux = LINE1,
+               } },
+       },
+       [SAA7134_BOARD_AVERMEDIA_A700_HYBRID] = {
+               /* Matthias Schwarzott <zzam@gentoo.org> */
+               .name           = "Avermedia DVB-S Hybrid+FM A700",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_ABSENT, /* TUNER_XC2028 */
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               /* no DVB support for now */
+               /* .mpeg           = SAA7134_MPEG_DVB, */
+               .inputs         = { {
+                       .name = name_comp,
+                       .vmux = 1,
+                       .amux = LINE1,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 6,
+                       .amux = LINE1,
+               } },
+       },
 };
 
 const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards);
@@ -4223,6 +4478,18 @@ struct pci_device_id saa7134_pci_tbl[] = {
                .subdevice    = 0xa70b,
                .driver_data  = SAA7134_BOARD_MD2819,
        },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
+               .subdevice    = 0xa7a1,
+               .driver_data  = SAA7134_BOARD_AVERMEDIA_A700_PRO,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
+               .subdevice    = 0xa7a2,
+               .driver_data  = SAA7134_BOARD_AVERMEDIA_A700_HYBRID,
+       }, {
                .vendor       = PCI_VENDOR_ID_PHILIPS,
                .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
                .subvendor    = 0x1461, /* Avermedia Technologies Inc */
@@ -4942,7 +5209,43 @@ struct pci_device_id saa7134_pci_tbl[] = {
                .subvendor    = 0x1822, /*Twinhan Technology Co. Ltd*/
                .subdevice    = 0x0022,
                .driver_data  = SAA7134_BOARD_TWINHAN_DTV_DVB_3056,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x16be,
+               .subdevice    = 0x0010, /* Medion version CTX953_V.1.4.3 */
+               .driver_data  = SAA7134_BOARD_CREATIX_CTX953,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1462, /* MSI */
+               .subdevice    = 0x8625, /* TV@nywhere A/D v1.1 */
+               .driver_data  = SAA7134_BOARD_MSI_TVANYWHERE_AD11,
        },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
+               .subdevice    = 0xf436,
+               .driver_data  = SAA7134_BOARD_AVERMEDIA_CARDBUS_506,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
+               .subdevice    = 0xf936,
+               .driver_data  = SAA7134_BOARD_AVERMEDIA_A16D,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
+               .subdevice    = 0xa836,
+               .driver_data  = SAA7134_BOARD_AVERMEDIA_M115,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x185b,
+               .subdevice    = 0xc900,
+               .driver_data  = SAA7134_BOARD_VIDEOMATE_T750,
+       }, {
                /* --- boards without eeprom + subsystem ID --- */
                .vendor       = PCI_VENDOR_ID_PHILIPS,
                .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
@@ -4998,6 +5301,77 @@ static void board_flyvideo(struct saa7134_dev *dev)
               dev->name, dev->name, dev->name);
 }
 
+static int saa7134_xc2028_callback(struct saa7134_dev *dev,
+                                  int command, int arg)
+{
+       switch (command) {
+       case XC2028_TUNER_RESET:
+               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x06e20000, 0x06e20000);
+               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x06a20000, 0x06a20000);
+               mdelay(250);
+               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x06e20000, 0);
+               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x06a20000, 0);
+               mdelay(250);
+               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x06e20000, 0x06e20000);
+               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x06a20000, 0x06a20000);
+               mdelay(250);
+               saa_andorl(SAA7133_ANALOG_IO_SELECT >> 2, 0x02, 0x02);
+               saa_andorl(SAA7134_ANALOG_IN_CTRL1 >> 2, 0x81, 0x81);
+               saa_andorl(SAA7134_AUDIO_CLOCK0 >> 2, 0x03187de7, 0x03187de7);
+               saa_andorl(SAA7134_AUDIO_PLL_CTRL >> 2, 0x03, 0x03);
+               saa_andorl(SAA7134_AUDIO_CLOCKS_PER_FIELD0 >> 2,
+                          0x0001e000, 0x0001e000);
+               return 0;
+       }
+       return -EINVAL;
+}
+
+
+static int saa7134_tda8290_callback(struct saa7134_dev *dev,
+                                   int command, int arg)
+{
+       u8 sync_control;
+
+       switch (command) {
+       case 0: /* switch LNA gain through GPIO 22*/
+               saa7134_set_gpio(dev, 22, arg) ;
+               break;
+       case 1: /* vsync output at GPIO22. 50 / 60Hz */
+               saa_andorb(SAA7134_VIDEO_PORT_CTRL3, 0x80, 0x80);
+               saa_andorb(SAA7134_VIDEO_PORT_CTRL6, 0x0f, 0x03);
+               if (arg == 1)
+                       sync_control = 11;
+               else
+                       sync_control = 17;
+               saa_writeb(SAA7134_VGATE_START, sync_control);
+               saa_writeb(SAA7134_VGATE_STOP, sync_control + 1);
+               saa_andorb(SAA7134_MISC_VGATE_MSB, 0x03, 0x00);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+int saa7134_tuner_callback(void *priv, int command, int arg)
+{
+       struct saa7134_dev *dev = priv;
+       if (dev != NULL) {
+               switch (dev->tuner_type) {
+               case TUNER_PHILIPS_TDA8290:
+                       return saa7134_tda8290_callback(dev, command, arg);
+               case TUNER_XC2028:
+                       return saa7134_xc2028_callback(dev, command, arg);
+               }
+       } else {
+               printk(KERN_ERR "saa7134: Error - device struct undefined.\n");
+               return -EINVAL;
+       }
+       return -EINVAL;
+}
+EXPORT_SYMBOL(saa7134_tuner_callback);
+
 /* ----------------------------------------------------------- */
 
 static void hauppauge_eeprom(struct saa7134_dev *dev, u8 *eeprom_data)
@@ -5067,6 +5441,7 @@ int saa7134_board_init1(struct saa7134_dev *dev)
        case SAA7134_BOARD_VIDEOMATE_DVBT_300:
        case SAA7134_BOARD_VIDEOMATE_DVBT_200:
        case SAA7134_BOARD_VIDEOMATE_DVBT_200A:
+       case SAA7134_BOARD_VIDEOMATE_T750:
        case SAA7134_BOARD_MANLI_MTV001:
        case SAA7134_BOARD_MANLI_MTV002:
        case SAA7134_BOARD_BEHOLD_409FM:
@@ -5133,11 +5508,29 @@ int saa7134_board_init1(struct saa7134_dev *dev)
                saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x08000000, 0x00000000);
                break;
        case SAA7134_BOARD_AVERMEDIA_CARDBUS:
-       case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM:
+       case SAA7134_BOARD_AVERMEDIA_CARDBUS_506:
+       case SAA7134_BOARD_AVERMEDIA_M115:
+       case SAA7134_BOARD_AVERMEDIA_A16D:
+               /* power-down tuner chip */
+               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0xffffffff, 0);
+               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0xffffffff, 0);
+               msleep(10);
                /* power-up tuner chip */
                saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0xffffffff, 0xffffffff);
                saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0xffffffff, 0xffffffff);
-               msleep(1);
+               msleep(10);
+               break;
+       case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM:
+               /* power-down tuner chip */
+               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x000A8004, 0x000A8004);
+               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x000A8004, 0);
+               msleep(10);
+               /* power-up tuner chip */
+               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x000A8004, 0x000A8004);
+               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x000A8004, 0x000A8004);
+               msleep(10);
+               /* remote via GPIO */
+               dev->has_remote = SAA7134_REMOTE_GPIO;
                break;
        case SAA7134_BOARD_RTD_VFG7350:
 
@@ -5160,7 +5553,6 @@ int saa7134_board_init1(struct saa7134_dev *dev)
                dev->has_remote = SAA7134_REMOTE_I2C;
                break;
        case SAA7134_BOARD_AVERMEDIA_A169_B:
-       case SAA7134_BOARD_MD7134_BRIDGE_2:
                printk("%s: %s: dual saa713x broadcast decoders\n"
                       "%s: Sorry, none of the inputs to this chip are supported yet.\n"
                       "%s: Dual decoder functionality is disabled for now, use the other chip.\n",
@@ -5172,6 +5564,15 @@ int saa7134_board_init1(struct saa7134_dev *dev)
                saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x8c040007, 0x8c040007);
                saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x0c0007cd, 0x0c0007cd);
                break;
+       case SAA7134_BOARD_AVERMEDIA_A700_PRO:
+       case SAA7134_BOARD_AVERMEDIA_A700_HYBRID:
+               /* write windows gpio values */
+               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x80040100, 0x80040100);
+               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x80040100, 0x00040100);
+               printk("%s: %s: hybrid analog/dvb card\n"
+                      "%s: Sorry, only the analog inputs are supported for now.\n",
+                       dev->name, card(dev).name, dev->name);
+               break;
        }
        return 0;
 }
@@ -5200,11 +5601,16 @@ int saa7134_board_init2(struct saa7134_dev *dev)
                dev->tuner_type = saa7134_boards[dev->board].tuner_type;
 
                if (TUNER_ABSENT != dev->tuner_type) {
-                               tun_setup.mode_mask = T_RADIO | T_ANALOG_TV | T_DIGITAL_TV;
-                               tun_setup.type = dev->tuner_type;
-                               tun_setup.addr = ADDR_UNSET;
+                       tun_setup.mode_mask = T_RADIO     |
+                                             T_ANALOG_TV |
+                                             T_DIGITAL_TV;
+                       tun_setup.type = dev->tuner_type;
+                       tun_setup.addr = ADDR_UNSET;
+                       tun_setup.tuner_callback = saa7134_tuner_callback;
 
-                               saa7134_i2c_call_clients (dev, TUNER_SET_TYPE_ADDR, &tun_setup);
+                       saa7134_i2c_call_clients(dev,
+                                                TUNER_SET_TYPE_ADDR,
+                                                &tun_setup);
                }
                break;
        case SAA7134_BOARD_MD7134:
@@ -5275,14 +5681,25 @@ int saa7134_board_init2(struct saa7134_dev *dev)
                                                 &tda9887_cfg);
                }
 
-               tun_setup.mode_mask = T_RADIO | T_ANALOG_TV | T_DIGITAL_TV;
+               tun_setup.mode_mask = T_RADIO     |
+                                     T_ANALOG_TV |
+                                     T_DIGITAL_TV;
                tun_setup.type = dev->tuner_type;
                tun_setup.addr = ADDR_UNSET;
 
-               saa7134_i2c_call_clients (dev, TUNER_SET_TYPE_ADDR,&tun_setup);
+               saa7134_i2c_call_clients(dev,
+                                        TUNER_SET_TYPE_ADDR, &tun_setup);
                }
                break;
        case SAA7134_BOARD_PHILIPS_EUROPA:
+               if (dev->autodetected && (dev->eedata[0x41] == 0x1c)) {
+                       /* Reconfigure board as Snake reference design */
+                       dev->board = SAA7134_BOARD_PHILIPS_SNAKE;
+                       dev->tuner_type = saa7134_boards[dev->board].tuner_type;
+                       printk(KERN_INFO "%s: Reconfigured board as %s\n",
+                               dev->name, saa7134_boards[dev->board].name);
+                       break;
+               }
        case SAA7134_BOARD_VIDEOMATE_DVBT_300:
        case SAA7134_BOARD_ASUS_EUROPA2_HYBRID:
                /* The Philips EUROPA based hybrid boards have the tuner connected through
@@ -5333,6 +5750,7 @@ int saa7134_board_init2(struct saa7134_dev *dev)
        case SAA7134_BOARD_MEDION_MD8800_QUADRO:
        case SAA7134_BOARD_AVERMEDIA_SUPER_007:
        case SAA7134_BOARD_TWINHAN_DTV_DVB_3056:
+       case SAA7134_BOARD_CREATIX_CTX953:
                /* this is a hybrid board, initialize to analog mode
                 * and configure firmware eeprom address
                 */
@@ -5402,13 +5820,46 @@ int saa7134_board_init2(struct saa7134_dev *dev)
                        break;
                }
                break;
+       case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM:
+               {
+               struct v4l2_priv_tun_config tea5767_cfg;
+               struct tea5767_ctrl ctl;
+
+               dev->i2c_client.addr = 0xC0;
+               /* set TEA5767(analog FM) defines */
+               memset(&ctl, 0, sizeof(ctl));
+               ctl.xtal_freq = TEA5767_HIGH_LO_13MHz;
+               tea5767_cfg.tuner = TUNER_TEA5767;
+               tea5767_cfg.priv  = &ctl;
+               saa7134_i2c_call_clients(dev, TUNER_SET_CONFIG, &tea5767_cfg);
+               }
+               break;
        }
+
+       if (dev->tuner_type == TUNER_XC2028) {
+               struct v4l2_priv_tun_config  xc2028_cfg;
+               struct xc2028_ctrl           ctl;
+
+               memset(&xc2028_cfg, 0, sizeof(ctl));
+               memset(&ctl, 0, sizeof(ctl));
+
+               ctl.fname   = XC2028_DEFAULT_FIRMWARE;
+               ctl.max_len = 64;
+
+               switch (dev->board) {
+               case SAA7134_BOARD_AVERMEDIA_A16D:
+                       ctl.demod = XC3028_FE_ZARLINK456;
+                       break;
+               default:
+                       ctl.demod = XC3028_FE_OREN538;
+                       ctl.mts = 1;
+               }
+
+               xc2028_cfg.tuner = TUNER_XC2028;
+               xc2028_cfg.priv  = &ctl;
+
+               saa7134_i2c_call_clients(dev, TUNER_SET_CONFIG, &xc2028_cfg);
+       }
+
        return 0;
 }
-
-/* ----------------------------------------------------------- */
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
index 58ab163fdbd74e628e60655ea05c5d3bea611599..eec127864fe3e710832a34275c337b51819cf53b 100644 (file)
@@ -42,23 +42,23 @@ MODULE_LICENSE("GPL");
 
 /* ------------------------------------------------------------------ */
 
-static unsigned int irq_debug = 0;
+static unsigned int irq_debug;
 module_param(irq_debug, int, 0644);
 MODULE_PARM_DESC(irq_debug,"enable debug messages [IRQ handler]");
 
-static unsigned int core_debug = 0;
+static unsigned int core_debug;
 module_param(core_debug, int, 0644);
 MODULE_PARM_DESC(core_debug,"enable debug messages [core]");
 
-static unsigned int gpio_tracking = 0;
+static unsigned int gpio_tracking;
 module_param(gpio_tracking, int, 0644);
 MODULE_PARM_DESC(gpio_tracking,"enable debug messages [gpio]");
 
-static unsigned int alsa = 0;
+static unsigned int alsa;
 module_param(alsa, int, 0644);
 MODULE_PARM_DESC(alsa,"enable ALSA DMA sound [dmasound]");
 
-static unsigned int oss = 0;
+static unsigned int oss;
 module_param(oss, int, 0644);
 MODULE_PARM_DESC(oss,"enable OSS DMA sound [dmasound]");
 
@@ -142,39 +142,6 @@ void saa7134_set_gpio(struct saa7134_dev *dev, int bit_no, int value)
        }
 }
 
-int saa7134_tuner_callback(void *ptr, int command, int arg)
-{
-       u8 sync_control;
-       struct saa7134_dev *dev = ptr;
-
-       switch (dev->tuner_type) {
-       case TUNER_PHILIPS_TDA8290:
-               switch (command) {
-               case 0: /* switch LNA gain through GPIO 22*/
-                       saa7134_set_gpio(dev, 22, arg) ;
-                       break;
-               case 1: /* vsync output at GPIO22. 50 / 60Hz */
-                       dprintk("setting GPIO22 to vsync %d\n", arg);
-                       saa_andorb(SAA7134_VIDEO_PORT_CTRL3, 0x80, 0x80);
-                       saa_andorb(SAA7134_VIDEO_PORT_CTRL6, 0x0f, 0x03);
-                       if (arg == 1)
-                               sync_control = 11;
-                       else
-                               sync_control = 17;
-                       saa_writeb(SAA7134_VGATE_START, sync_control);
-                       saa_writeb(SAA7134_VGATE_STOP, sync_control + 1);
-                       saa_andorb(SAA7134_MISC_VGATE_MSB, 0x03, 0x00);
-                       break;
-               default:
-                       return -EINVAL;
-               }
-               break;
-       default:
-               return -ENODEV;
-       }
-       return 0;
-}
-
 /* ------------------------------------------------------------------ */
 
 
@@ -897,6 +864,10 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
        struct saa7134_dev *dev;
        struct saa7134_mpeg_ops *mops;
        int err;
+       int mask;
+
+       if (saa7134_devcount == SAA7134_MAXBOARDS)
+               return -ENOMEM;
 
        dev = kzalloc(sizeof(*dev),GFP_KERNEL);
        if (NULL == dev)
@@ -1094,6 +1065,11 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
        if (TUNER_ABSENT != dev->tuner_type)
                saa7134_i2c_call_clients(dev, TUNER_SET_STANDBY, NULL);
 
+       if (card(dev).gpiomask != 0) {
+               mask = card(dev).gpiomask;
+               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   mask, mask);
+               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, mask, 0);
+       }
        return 0;
 
  fail4:
index ea2be9eceeb8bf90ad36ae2334a5c3b6e2cd2084..2d16be2259dbb6182b10d84b54585bfc66e81ed5 100644 (file)
 #include "saa7134.h"
 #include <media/v4l2-common.h>
 #include "dvb-pll.h"
+#include <dvb_frontend.h>
 
 #include "mt352.h"
 #include "mt352_priv.h" /* FIXME */
 #include "tda1004x.h"
 #include "nxt200x.h"
+#include "tuner-xc2028.h"
 
 #include "tda10086.h"
 #include "tda826x.h"
 #include "tda827x.h"
 #include "isl6421.h"
+#include "isl6405.h"
+#include "lnbp21.h"
+#include "tuner-simple.h"
 
 MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
 MODULE_LICENSE("GPL");
 
-static unsigned int antenna_pwr = 0;
+static unsigned int antenna_pwr;
 
 module_param(antenna_pwr, int, 0444);
 MODULE_PARM_DESC(antenna_pwr,"enable antenna power (Pinnacle 300i)");
 
-static int use_frontend = 0;
+static int use_frontend;
 module_param(use_frontend, int, 0644);
 MODULE_PARM_DESC(use_frontend,"for cards with multiple frontends (0: terrestrial, 1: satellite)");
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off module debugging (default:off).");
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 #define dprintk(fmt, arg...)   do { if (debug) \
        printk(KERN_DEBUG "%s/dvb: " fmt, dev->name , ## arg); } while(0)
 
@@ -91,7 +98,7 @@ static int pinnacle_antenna_pwr(struct saa7134_dev *dev, int on)
        saa_setl(SAA7134_GPIO_GPSTATUS0 >> 2,   (1 << 28));
        udelay(10);
        ok = saa_readl(SAA7134_GPIO_GPSTATUS0) & (1 << 27);
-       dprintk("%s %s\n", __FUNCTION__, ok ? "on" : "off");
+       dprintk("%s %s\n", __func__, ok ? "on" : "off");
 
        if (!ok)
                saa_clearl(SAA7134_GPIO_GPSTATUS0 >> 2,   (1 << 26));
@@ -111,7 +118,7 @@ static int mt352_pinnacle_init(struct dvb_frontend* fe)
        static u8 irq_cfg []       = { INTERRUPT_EN_0, 0x00, 0x00, 0x00, 0x00 };
        struct saa7134_dev *dev= fe->dvb->priv;
 
-       dprintk("%s called\n", __FUNCTION__);
+       dprintk("%s called\n", __func__);
 
        mt352_write(fe, clock_config,   sizeof(clock_config));
        udelay(200);
@@ -146,6 +153,26 @@ static int mt352_aver777_init(struct dvb_frontend* fe)
        return 0;
 }
 
+static int mt352_aver_a16d_init(struct dvb_frontend *fe)
+{
+       static u8 clock_config []  = { CLOCK_CTL,  0x38, 0x2d };
+       static u8 reset []         = { RESET,      0x80 };
+       static u8 adc_ctl_1_cfg [] = { ADC_CTL_1,  0x40 };
+       static u8 agc_cfg []       = { AGC_TARGET, 0x28, 0xa0 };
+       static u8 capt_range_cfg[] = { CAPT_RANGE, 0x33 };
+
+       mt352_write(fe, clock_config,   sizeof(clock_config));
+       udelay(200);
+       mt352_write(fe, reset,          sizeof(reset));
+       mt352_write(fe, adc_ctl_1_cfg,  sizeof(adc_ctl_1_cfg));
+       mt352_write(fe, agc_cfg,        sizeof(agc_cfg));
+       mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
+
+       return 0;
+}
+
+
+
 static int mt352_pinnacle_tuner_set_params(struct dvb_frontend* fe,
                                           struct dvb_frontend_parameters* params)
 {
@@ -188,6 +215,16 @@ static struct mt352_config avermedia_777 = {
        .demod_init    = mt352_aver777_init,
 };
 
+static struct mt352_config avermedia_16d = {
+       .demod_address = 0xf,
+       .demod_init    = mt352_aver_a16d_init,
+};
+
+static struct mt352_config avermedia_e506r_mt352_dev = {
+       .demod_address   = (0x1e >> 1),
+       .no_tuner        = 1,
+};
+
 /* ==================================================================
  * tda1004x based DVB-T cards, helper functions
  */
@@ -430,8 +467,6 @@ static struct tda1004x_config philips_europa_config = {
        .request_firmware = philips_tda1004x_request_firmware
 };
 
-/* ------------------------------------------------------------------ */
-
 static struct tda1004x_config medion_cardbus = {
        .demod_address = 0x08,
        .invert        = 1,
@@ -447,47 +482,6 @@ static struct tda1004x_config medion_cardbus = {
  * tda 1004x based cards with philips silicon tuner
  */
 
-static void philips_tda827x_lna_gain(struct dvb_frontend *fe, int high)
-{
-       struct saa7134_dev *dev = fe->dvb->priv;
-       struct tda1004x_state *state = fe->demodulator_priv;
-       u8 addr = state->config->i2c_gate;
-       u8 config = state->config->tuner_config;
-       u8 GP00_CF[] = {0x20, 0x01};
-       u8 GP00_LEV[] = {0x22, 0x00};
-
-       struct i2c_msg msg = {.addr = addr,.flags = 0,.buf = GP00_CF, .len = 2};
-       if (config) {
-               if (high) {
-                       dprintk("setting LNA to high gain\n");
-               } else {
-                       dprintk("setting LNA to low gain\n");
-               }
-       }
-       switch (config) {
-       case 0: /* no LNA */
-               break;
-       case 1: /* switch is GPIO 0 of tda8290 */
-       case 2:
-               /* turn Vsync off */
-               saa7134_set_gpio(dev, 22, 0);
-               GP00_LEV[1] = high ? 0 : 1;
-               if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1) {
-                       wprintk("could not access tda8290 at addr: 0x%02x\n",
-                               addr << 1);
-                       return;
-               }
-               msg.buf = GP00_LEV;
-               if (config == 2)
-                       GP00_LEV[1] = high ? 1 : 0;
-               i2c_transfer(&dev->i2c_adap, &msg, 1);
-               break;
-       case 3: /* switch with GPIO of saa713x */
-               saa7134_set_gpio(dev, 22, high);
-               break;
-       }
-}
-
 static int tda8290_i2c_gate_ctrl( struct dvb_frontend* fe, int enable)
 {
        struct tda1004x_state *state = fe->demodulator_priv;
@@ -510,8 +504,6 @@ static int tda8290_i2c_gate_ctrl( struct dvb_frontend* fe, int enable)
        return 0;
 }
 
-/* ------------------------------------------------------------------ */
-
 static int philips_tda827x_tuner_init(struct dvb_frontend *fe)
 {
        struct saa7134_dev *dev = fe->dvb->priv;
@@ -546,28 +538,57 @@ static int philips_tda827x_tuner_sleep(struct dvb_frontend *fe)
        return 0;
 }
 
-static struct tda827x_config tda827x_cfg = {
-       .lna_gain = philips_tda827x_lna_gain,
-       .init = philips_tda827x_tuner_init,
-       .sleep = philips_tda827x_tuner_sleep
-};
-
-static void configure_tda827x_fe(struct saa7134_dev *dev, struct tda1004x_config *tda_conf)
+static void configure_tda827x_fe(struct saa7134_dev *dev, struct tda1004x_config *cdec_conf,
+                                                         struct tda827x_config *tuner_conf)
 {
-       dev->dvb.frontend = dvb_attach(tda10046_attach, tda_conf, &dev->i2c_adap);
+       dev->dvb.frontend = dvb_attach(tda10046_attach, cdec_conf, &dev->i2c_adap);
        if (dev->dvb.frontend) {
-               if (tda_conf->i2c_gate)
+               if (cdec_conf->i2c_gate)
                        dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl;
-               if (dvb_attach(tda827x_attach, dev->dvb.frontend, tda_conf->tuner_address,
-                                               &dev->i2c_adap,&tda827x_cfg) == NULL) {
+               if (dvb_attach(tda827x_attach, dev->dvb.frontend, cdec_conf->tuner_address,
+                                                       &dev->i2c_adap, tuner_conf) == NULL) {
                        wprintk("no tda827x tuner found at addr: %02x\n",
-                               tda_conf->tuner_address);
+                               cdec_conf->tuner_address);
                }
        }
 }
 
 /* ------------------------------------------------------------------ */
 
+static struct tda827x_config tda827x_cfg_0 = {
+       .tuner_callback = saa7134_tuner_callback,
+       .init = philips_tda827x_tuner_init,
+       .sleep = philips_tda827x_tuner_sleep,
+       .config = 0,
+       .switch_addr = 0
+};
+
+static struct tda827x_config tda827x_cfg_1 = {
+       .tuner_callback = saa7134_tuner_callback,
+       .init = philips_tda827x_tuner_init,
+       .sleep = philips_tda827x_tuner_sleep,
+       .config = 1,
+       .switch_addr = 0x4b
+};
+
+static struct tda827x_config tda827x_cfg_2 = {
+       .tuner_callback = saa7134_tuner_callback,
+       .init = philips_tda827x_tuner_init,
+       .sleep = philips_tda827x_tuner_sleep,
+       .config = 2,
+       .switch_addr = 0x4b
+};
+
+static struct tda827x_config tda827x_cfg_2_sw42 = {
+       .tuner_callback = saa7134_tuner_callback,
+       .init = philips_tda827x_tuner_init,
+       .sleep = philips_tda827x_tuner_sleep,
+       .config = 2,
+       .switch_addr = 0x42
+};
+
+/* ------------------------------------------------------------------ */
+
 static struct tda1004x_config tda827x_lifeview_config = {
        .demod_address = 0x08,
        .invert        = 1,
@@ -590,7 +611,6 @@ static struct tda1004x_config philips_tiger_config = {
        .if_freq       = TDA10046_FREQ_045,
        .i2c_gate      = 0x4b,
        .tuner_address = 0x61,
-       .tuner_config  = 0,
        .antenna_switch= 1,
        .request_firmware = philips_tda1004x_request_firmware
 };
@@ -605,7 +625,6 @@ static struct tda1004x_config cinergy_ht_config = {
        .if_freq       = TDA10046_FREQ_045,
        .i2c_gate      = 0x4b,
        .tuner_address = 0x61,
-       .tuner_config  = 0,
        .request_firmware = philips_tda1004x_request_firmware
 };
 
@@ -619,7 +638,6 @@ static struct tda1004x_config cinergy_ht_pci_config = {
        .if_freq       = TDA10046_FREQ_045,
        .i2c_gate      = 0x4b,
        .tuner_address = 0x60,
-       .tuner_config  = 0,
        .request_firmware = philips_tda1004x_request_firmware
 };
 
@@ -633,7 +651,6 @@ static struct tda1004x_config philips_tiger_s_config = {
        .if_freq       = TDA10046_FREQ_045,
        .i2c_gate      = 0x4b,
        .tuner_address = 0x61,
-       .tuner_config  = 2,
        .antenna_switch= 1,
        .request_firmware = philips_tda1004x_request_firmware
 };
@@ -648,7 +665,6 @@ static struct tda1004x_config pinnacle_pctv_310i_config = {
        .if_freq       = TDA10046_FREQ_045,
        .i2c_gate      = 0x4b,
        .tuner_address = 0x61,
-       .tuner_config  = 1,
        .request_firmware = philips_tda1004x_request_firmware
 };
 
@@ -662,7 +678,6 @@ static struct tda1004x_config hauppauge_hvr_1110_config = {
        .if_freq       = TDA10046_FREQ_045,
        .i2c_gate      = 0x4b,
        .tuner_address = 0x61,
-       .tuner_config  = 1,
        .request_firmware = philips_tda1004x_request_firmware
 };
 
@@ -676,7 +691,6 @@ static struct tda1004x_config asus_p7131_dual_config = {
        .if_freq       = TDA10046_FREQ_045,
        .i2c_gate      = 0x4b,
        .tuner_address = 0x61,
-       .tuner_config  = 0,
        .antenna_switch= 2,
        .request_firmware = philips_tda1004x_request_firmware
 };
@@ -715,7 +729,6 @@ static struct tda1004x_config md8800_dvbt_config = {
        .if_freq       = TDA10046_FREQ_045,
        .i2c_gate      = 0x4b,
        .tuner_address = 0x60,
-       .tuner_config  = 0,
        .request_firmware = philips_tda1004x_request_firmware
 };
 
@@ -729,7 +742,6 @@ static struct tda1004x_config asus_p7131_4871_config = {
        .if_freq       = TDA10046_FREQ_045,
        .i2c_gate      = 0x4b,
        .tuner_address = 0x61,
-       .tuner_config  = 2,
        .antenna_switch= 2,
        .request_firmware = philips_tda1004x_request_firmware
 };
@@ -744,7 +756,6 @@ static struct tda1004x_config asus_p7131_hybrid_lna_config = {
        .if_freq       = TDA10046_FREQ_045,
        .i2c_gate      = 0x4b,
        .tuner_address = 0x61,
-       .tuner_config  = 2,
        .antenna_switch= 2,
        .request_firmware = philips_tda1004x_request_firmware
 };
@@ -759,7 +770,6 @@ static struct tda1004x_config kworld_dvb_t_210_config = {
        .if_freq       = TDA10046_FREQ_045,
        .i2c_gate      = 0x4b,
        .tuner_address = 0x61,
-       .tuner_config  = 2,
        .antenna_switch= 1,
        .request_firmware = philips_tda1004x_request_firmware
 };
@@ -774,7 +784,6 @@ static struct tda1004x_config avermedia_super_007_config = {
        .if_freq       = TDA10046_FREQ_045,
        .i2c_gate      = 0x4b,
        .tuner_address = 0x60,
-       .tuner_config  = 0,
        .antenna_switch= 1,
        .request_firmware = philips_tda1004x_request_firmware
 };
@@ -789,7 +798,6 @@ static struct tda1004x_config twinhan_dtv_dvb_3056_config = {
        .if_freq       = TDA10046_FREQ_045,
        .i2c_gate      = 0x42,
        .tuner_address = 0x61,
-       .tuner_config  = 2,
        .antenna_switch = 1,
        .request_firmware = philips_tda1004x_request_firmware
 };
@@ -817,9 +825,10 @@ static int ads_duo_tuner_sleep(struct dvb_frontend *fe)
 }
 
 static struct tda827x_config ads_duo_cfg = {
-       .lna_gain = philips_tda827x_lna_gain,
+       .tuner_callback = saa7134_tuner_callback,
        .init = ads_duo_tuner_init,
-       .sleep = ads_duo_tuner_sleep
+       .sleep = ads_duo_tuner_sleep,
+       .config = 0
 };
 
 static struct tda1004x_config ads_tech_duo_config = {
@@ -842,8 +851,73 @@ static struct tda10086_config flydvbs = {
        .demod_address = 0x0e,
        .invert = 0,
        .diseqc_tone = 0,
+       .xtal_freq = TDA10086_XTAL_16M,
 };
 
+static struct tda10086_config sd1878_4m = {
+       .demod_address = 0x0e,
+       .invert = 0,
+       .diseqc_tone = 0,
+       .xtal_freq = TDA10086_XTAL_4M,
+};
+
+/* ------------------------------------------------------------------
+ * special case: lnb supply is connected to the gated i2c
+ */
+
+static int md8800_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+       int res = -EIO;
+       struct saa7134_dev *dev = fe->dvb->priv;
+       if (fe->ops.i2c_gate_ctrl) {
+               fe->ops.i2c_gate_ctrl(fe, 1);
+               if (dev->original_set_voltage)
+                       res = dev->original_set_voltage(fe, voltage);
+               fe->ops.i2c_gate_ctrl(fe, 0);
+       }
+       return res;
+};
+
+static int md8800_set_high_voltage(struct dvb_frontend *fe, long arg)
+{
+       int res = -EIO;
+       struct saa7134_dev *dev = fe->dvb->priv;
+       if (fe->ops.i2c_gate_ctrl) {
+               fe->ops.i2c_gate_ctrl(fe, 1);
+               if (dev->original_set_high_voltage)
+                       res = dev->original_set_high_voltage(fe, arg);
+               fe->ops.i2c_gate_ctrl(fe, 0);
+       }
+       return res;
+};
+
+static int md8800_set_voltage2(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+       struct saa7134_dev *dev = fe->dvb->priv;
+       u8 wbuf[2] = { 0x1f, 00 };
+       u8 rbuf;
+       struct i2c_msg msg[] = { { .addr = 0x08, .flags = 0, .buf = wbuf, .len = 1 },
+                                { .addr = 0x08, .flags = I2C_M_RD, .buf = &rbuf, .len = 1 } };
+
+       if (i2c_transfer(&dev->i2c_adap, msg, 2) != 2)
+               return -EIO;
+       /* NOTE: this assumes that gpo1 is used, it might be bit 5 (gpo2) */
+       if (voltage == SEC_VOLTAGE_18)
+               wbuf[1] = rbuf | 0x10;
+       else
+               wbuf[1] = rbuf & 0xef;
+       msg[0].len = 2;
+       i2c_transfer(&dev->i2c_adap, msg, 1);
+       return 0;
+}
+
+static int md8800_set_high_voltage2(struct dvb_frontend *fe, long arg)
+{
+       struct saa7134_dev *dev = fe->dvb->priv;
+       wprintk("%s: sorry can't set high LNB supply voltage from here\n", __func__);
+       return -EIO;
+}
+
 /* ==================================================================
  * nxt200x based ATSC cards, helper functions
  */
@@ -863,12 +937,14 @@ static struct nxt200x_config kworldatsc110 = {
 static int dvb_init(struct saa7134_dev *dev)
 {
        int ret;
+       int attach_xc3028 = 0;
+
        /* init struct videobuf_dvb */
        dev->ts.nr_bufs    = 32;
        dev->ts.nr_packets = 32*4;
        dev->dvb.name = dev->name;
-       videobuf_queue_pci_init(&dev->dvb.dvbq, &saa7134_ts_qops,
-                           dev->pci, &dev->slock,
+       videobuf_queue_sg_init(&dev->dvb.dvbq, &saa7134_ts_qops,
+                           &dev->pci->dev, &dev->slock,
                            V4L2_BUF_TYPE_VIDEO_CAPTURE,
                            V4L2_FIELD_ALTERNATE,
                            sizeof(struct saa7134_buf),
@@ -889,17 +965,25 @@ static int dvb_init(struct saa7134_dev *dev)
                dev->dvb.frontend = dvb_attach(mt352_attach, &avermedia_777,
                                               &dev->i2c_adap);
                if (dev->dvb.frontend) {
-                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
-                                  NULL, DVB_PLL_PHILIPS_TD1316);
+                       dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+                                  &dev->i2c_adap, 0x61,
+                                  TUNER_PHILIPS_TD1316);
                }
                break;
+       case SAA7134_BOARD_AVERMEDIA_A16D:
+               dprintk("avertv A16D dvb setup\n");
+               dev->dvb.frontend = dvb_attach(mt352_attach, &avermedia_16d,
+                                              &dev->i2c_adap);
+               attach_xc3028 = 1;
+               break;
        case SAA7134_BOARD_MD7134:
                dev->dvb.frontend = dvb_attach(tda10046_attach,
                                               &medion_cardbus,
                                               &dev->i2c_adap);
                if (dev->dvb.frontend) {
-                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, medion_cardbus.tuner_address,
-                                  &dev->i2c_adap, DVB_PLL_FMD1216ME);
+                       dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+                                  &dev->i2c_adap, medion_cardbus.tuner_address,
+                                  TUNER_PHILIPS_FMD1216ME_MK3);
                }
                break;
        case SAA7134_BOARD_PHILIPS_TOUGH:
@@ -913,7 +997,7 @@ static int dvb_init(struct saa7134_dev *dev)
                break;
        case SAA7134_BOARD_FLYDVBTDUO:
        case SAA7134_BOARD_FLYDVBT_DUO_CARDBUS:
-               configure_tda827x_fe(dev, &tda827x_lifeview_config);
+               configure_tda827x_fe(dev, &tda827x_lifeview_config, &tda827x_cfg_0);
                break;
        case SAA7134_BOARD_PHILIPS_EUROPA:
        case SAA7134_BOARD_VIDEOMATE_DVBT_300:
@@ -938,36 +1022,36 @@ static int dvb_init(struct saa7134_dev *dev)
                }
                break;
        case SAA7134_BOARD_KWORLD_DVBT_210:
-               configure_tda827x_fe(dev, &kworld_dvb_t_210_config);
+               configure_tda827x_fe(dev, &kworld_dvb_t_210_config, &tda827x_cfg_2);
                break;
        case SAA7134_BOARD_PHILIPS_TIGER:
-               configure_tda827x_fe(dev, &philips_tiger_config);
+               configure_tda827x_fe(dev, &philips_tiger_config, &tda827x_cfg_0);
                break;
        case SAA7134_BOARD_PINNACLE_PCTV_310i:
-               configure_tda827x_fe(dev, &pinnacle_pctv_310i_config);
+               configure_tda827x_fe(dev, &pinnacle_pctv_310i_config, &tda827x_cfg_1);
                break;
        case SAA7134_BOARD_HAUPPAUGE_HVR1110:
-               configure_tda827x_fe(dev, &hauppauge_hvr_1110_config);
+               configure_tda827x_fe(dev, &hauppauge_hvr_1110_config, &tda827x_cfg_1);
                break;
        case SAA7134_BOARD_ASUSTeK_P7131_DUAL:
-               configure_tda827x_fe(dev, &asus_p7131_dual_config);
+               configure_tda827x_fe(dev, &asus_p7131_dual_config, &tda827x_cfg_0);
                break;
        case SAA7134_BOARD_FLYDVBT_LR301:
-               configure_tda827x_fe(dev, &tda827x_lifeview_config);
+               configure_tda827x_fe(dev, &tda827x_lifeview_config, &tda827x_cfg_0);
                break;
        case SAA7134_BOARD_FLYDVB_TRIO:
                if(! use_frontend) {    /* terrestrial */
-                       configure_tda827x_fe(dev, &lifeview_trio_config);
-               } else {                /* satellite */
+                       configure_tda827x_fe(dev, &lifeview_trio_config, &tda827x_cfg_0);
+               } else {                /* satellite */
                        dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, &dev->i2c_adap);
                        if (dev->dvb.frontend) {
                                if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x63,
                                                                        &dev->i2c_adap, 0) == NULL) {
-                                       wprintk("%s: Lifeview Trio, No tda826x found!\n", __FUNCTION__);
+                                       wprintk("%s: Lifeview Trio, No tda826x found!\n", __func__);
                                }
                                if (dvb_attach(isl6421_attach, dev->dvb.frontend, &dev->i2c_adap,
                                                                                0x08, 0, 0) == NULL) {
-                                       wprintk("%s: Lifeview Trio, No ISL6421 found!\n", __FUNCTION__);
+                                       wprintk("%s: Lifeview Trio, No ISL6421 found!\n", __func__);
                                }
                        }
                }
@@ -979,18 +1063,56 @@ static int dvb_init(struct saa7134_dev *dev)
                                               &dev->i2c_adap);
                if (dev->dvb.frontend) {
                        if (dvb_attach(tda827x_attach,dev->dvb.frontend,
-                                  ads_tech_duo_config.tuner_address,
-                                  &dev->i2c_adap,&ads_duo_cfg) == NULL) {
+                                  ads_tech_duo_config.tuner_address, &dev->i2c_adap,
+                                                               &ads_duo_cfg) == NULL) {
                                wprintk("no tda827x tuner found at addr: %02x\n",
                                        ads_tech_duo_config.tuner_address);
                        }
                }
                break;
        case SAA7134_BOARD_TEVION_DVBT_220RF:
-               configure_tda827x_fe(dev, &tevion_dvbt220rf_config);
+               configure_tda827x_fe(dev, &tevion_dvbt220rf_config, &tda827x_cfg_0);
                break;
        case SAA7134_BOARD_MEDION_MD8800_QUADRO:
-               configure_tda827x_fe(dev, &md8800_dvbt_config);
+               if (!use_frontend) {     /* terrestrial */
+                       configure_tda827x_fe(dev, &md8800_dvbt_config, &tda827x_cfg_0);
+               } else {        /* satellite */
+                       dev->dvb.frontend = dvb_attach(tda10086_attach,
+                                                       &flydvbs, &dev->i2c_adap);
+                       if (dev->dvb.frontend) {
+                               struct dvb_frontend *fe = dev->dvb.frontend;
+                               u8 dev_id = dev->eedata[2];
+                               u8 data = 0xc4;
+                               struct i2c_msg msg = {.addr = 0x08, .flags = 0, .len = 1};
+
+                               if (dvb_attach(tda826x_attach, dev->dvb.frontend,
+                                               0x60, &dev->i2c_adap, 0) == NULL)
+                                       wprintk("%s: Medion Quadro, no tda826x "
+                                               "found !\n", __func__);
+                               if (dev_id != 0x08) {
+                                       /* we need to open the i2c gate (we know it exists) */
+                                       fe->ops.i2c_gate_ctrl(fe, 1);
+                                       if (dvb_attach(isl6405_attach, fe,
+                                                       &dev->i2c_adap, 0x08, 0, 0) == NULL)
+                                               wprintk("%s: Medion Quadro, no ISL6405 "
+                                                       "found !\n", __func__);
+                                       if (dev_id == 0x07) {
+                                               /* fire up the 2nd section of the LNB supply since
+                                                  we can't do this from the other section */
+                                               msg.buf = &data;
+                                               i2c_transfer(&dev->i2c_adap, &msg, 1);
+                                       }
+                                       fe->ops.i2c_gate_ctrl(fe, 0);
+                                       dev->original_set_voltage = fe->ops.set_voltage;
+                                       fe->ops.set_voltage = md8800_set_voltage;
+                                       dev->original_set_high_voltage = fe->ops.enable_high_lnb_voltage;
+                                       fe->ops.enable_high_lnb_voltage = md8800_set_high_voltage;
+                               } else {
+                                       fe->ops.set_voltage = md8800_set_voltage2;
+                                       fe->ops.enable_high_lnb_voltage = md8800_set_high_voltage2;
+                               }
+                       }
+               }
                break;
        case SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180:
                dev->dvb.frontend = dvb_attach(nxt200x_attach, &avertvhda180,
@@ -1004,8 +1126,9 @@ static int dvb_init(struct saa7134_dev *dev)
                dev->dvb.frontend = dvb_attach(nxt200x_attach, &kworldatsc110,
                                               &dev->i2c_adap);
                if (dev->dvb.frontend) {
-                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
-                                  NULL, DVB_PLL_TUV1236D);
+                       dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+                                  &dev->i2c_adap, 0x61,
+                                  TUNER_PHILIPS_TUV1236D);
                }
                break;
        case SAA7134_BOARD_FLYDVBS_LR300:
@@ -1014,11 +1137,11 @@ static int dvb_init(struct saa7134_dev *dev)
                if (dev->dvb.frontend) {
                        if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x60,
                                       &dev->i2c_adap, 0) == NULL) {
-                               wprintk("%s: No tda826x found!\n", __FUNCTION__);
+                               wprintk("%s: No tda826x found!\n", __func__);
                        }
                        if (dvb_attach(isl6421_attach, dev->dvb.frontend,
                                       &dev->i2c_adap, 0x08, 0, 0) == NULL) {
-                               wprintk("%s: No ISL6421 found!\n", __FUNCTION__);
+                               wprintk("%s: No ISL6421 found!\n", __func__);
                        }
                }
                break;
@@ -1030,8 +1153,9 @@ static int dvb_init(struct saa7134_dev *dev)
                        dev->original_demod_sleep = dev->dvb.frontend->ops.sleep;
                        dev->dvb.frontend->ops.sleep = philips_europa_demod_sleep;
 
-                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, medion_cardbus.tuner_address,
-                                  &dev->i2c_adap, DVB_PLL_FMD1216ME);
+                       dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+                                  &dev->i2c_adap, medion_cardbus.tuner_address,
+                                  TUNER_PHILIPS_FMD1216ME_MK3);
                }
                break;
        case SAA7134_BOARD_VIDEOMATE_DVBT_200A:
@@ -1044,38 +1168,107 @@ static int dvb_init(struct saa7134_dev *dev)
                }
                break;
        case SAA7134_BOARD_CINERGY_HT_PCMCIA:
-               configure_tda827x_fe(dev, &cinergy_ht_config);
+               configure_tda827x_fe(dev, &cinergy_ht_config, &tda827x_cfg_0);
                break;
        case SAA7134_BOARD_CINERGY_HT_PCI:
-               configure_tda827x_fe(dev, &cinergy_ht_pci_config);
+               configure_tda827x_fe(dev, &cinergy_ht_pci_config, &tda827x_cfg_0);
                break;
        case SAA7134_BOARD_PHILIPS_TIGER_S:
-               configure_tda827x_fe(dev, &philips_tiger_s_config);
+               configure_tda827x_fe(dev, &philips_tiger_s_config, &tda827x_cfg_2);
                break;
        case SAA7134_BOARD_ASUS_P7131_4871:
-               configure_tda827x_fe(dev, &asus_p7131_4871_config);
+               configure_tda827x_fe(dev, &asus_p7131_4871_config, &tda827x_cfg_2);
                break;
        case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA:
-               configure_tda827x_fe(dev, &asus_p7131_hybrid_lna_config);
+               configure_tda827x_fe(dev, &asus_p7131_hybrid_lna_config, &tda827x_cfg_2);
                break;
        case SAA7134_BOARD_AVERMEDIA_SUPER_007:
-               configure_tda827x_fe(dev, &avermedia_super_007_config);
+               configure_tda827x_fe(dev, &avermedia_super_007_config, &tda827x_cfg_0);
                break;
        case SAA7134_BOARD_TWINHAN_DTV_DVB_3056:
-               configure_tda827x_fe(dev, &twinhan_dtv_dvb_3056_config);
+               configure_tda827x_fe(dev, &twinhan_dtv_dvb_3056_config, &tda827x_cfg_2_sw42);
+               break;
+       case SAA7134_BOARD_PHILIPS_SNAKE:
+               dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs,
+                                               &dev->i2c_adap);
+               if (dev->dvb.frontend) {
+                       if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x60,
+                                       &dev->i2c_adap, 0) == NULL)
+                               wprintk("%s: No tda826x found!\n", __func__);
+                       if (dvb_attach(lnbp21_attach, dev->dvb.frontend,
+                                       &dev->i2c_adap, 0, 0) == NULL)
+                               wprintk("%s: No lnbp21 found!\n", __func__);
+               }
+               break;
+       case SAA7134_BOARD_CREATIX_CTX953:
+               configure_tda827x_fe(dev, &md8800_dvbt_config, &tda827x_cfg_0);
+               break;
+       case SAA7134_BOARD_MSI_TVANYWHERE_AD11:
+               configure_tda827x_fe(dev, &philips_tiger_s_config, &tda827x_cfg_2);
+               break;
+       case SAA7134_BOARD_AVERMEDIA_CARDBUS_506:
+               dev->dvb.frontend = dvb_attach(mt352_attach,
+                                              &avermedia_e506r_mt352_dev,
+                                              &dev->i2c_adap);
+               attach_xc3028 = 1;
+               break;
+       case SAA7134_BOARD_MD7134_BRIDGE_2:
+               dev->dvb.frontend = dvb_attach(tda10086_attach,
+                                               &sd1878_4m, &dev->i2c_adap);
+               if (dev->dvb.frontend) {
+                       struct dvb_frontend *fe;
+                       if (dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60,
+                                 &dev->i2c_adap, DVB_PLL_PHILIPS_SD1878_TDA8261) == NULL)
+                               wprintk("%s: MD7134 DVB-S, no SD1878 "
+                                       "found !\n", __func__);
+                       /* we need to open the i2c gate (we know it exists) */
+                       fe = dev->dvb.frontend;
+                       fe->ops.i2c_gate_ctrl(fe, 1);
+                       if (dvb_attach(isl6405_attach, fe,
+                                       &dev->i2c_adap, 0x08, 0, 0) == NULL)
+                               wprintk("%s: MD7134 DVB-S, no ISL6405 "
+                                       "found !\n", __func__);
+                       fe->ops.i2c_gate_ctrl(fe, 0);
+                       dev->original_set_voltage = fe->ops.set_voltage;
+                       fe->ops.set_voltage = md8800_set_voltage;
+                       dev->original_set_high_voltage = fe->ops.enable_high_lnb_voltage;
+                       fe->ops.enable_high_lnb_voltage = md8800_set_high_voltage;
+               }
                break;
        default:
                wprintk("Huh? unknown DVB card?\n");
                break;
        }
 
+       if (attach_xc3028) {
+               struct dvb_frontend *fe;
+               struct xc2028_config cfg = {
+                       .i2c_adap  = &dev->i2c_adap,
+                       .i2c_addr  = 0x61,
+               };
+
+               if (!dev->dvb.frontend)
+                       return -1;
+
+               fe = dvb_attach(xc2028_attach, dev->dvb.frontend, &cfg);
+               if (!fe) {
+                       printk(KERN_ERR "%s/2: xc3028 attach failed\n",
+                              dev->name);
+                       dvb_frontend_detach(dev->dvb.frontend);
+                       dvb_unregister_frontend(dev->dvb.frontend);
+                       dev->dvb.frontend = NULL;
+                       return -1;
+               }
+       }
+
        if (NULL == dev->dvb.frontend) {
                printk(KERN_ERR "%s/dvb: frontend initialization failed\n", dev->name);
                return -1;
        }
 
        /* register everything else */
-       ret = videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, &dev->pci->dev);
+       ret = videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, &dev->pci->dev,
+                                   adapter_nr);
 
        /* this sequence is necessary to make the tda1004x load its firmware
         * and to enter analog mode of hybrid boards
@@ -1106,9 +1299,22 @@ static int dvb_fini(struct saa7134_dev *dev)
 
                /* otherwise we don't detect the tuner on next insmod */
                saa7134_i2c_call_clients(dev, TUNER_SET_CONFIG, &tda9887_cfg);
+       } else if (dev->board == SAA7134_BOARD_MEDION_MD8800_QUADRO) {
+               if ((dev->eedata[2] == 0x07) && use_frontend) {
+                       /* turn off the 2nd lnb supply */
+                       u8 data = 0x80;
+                       struct i2c_msg msg = {.addr = 0x08, .buf = &data, .flags = 0, .len = 1};
+                       struct dvb_frontend *fe;
+                       fe = dev->dvb.frontend;
+                       if (fe->ops.i2c_gate_ctrl) {
+                               fe->ops.i2c_gate_ctrl(fe, 1);
+                               i2c_transfer(&dev->i2c_adap, &msg, 1);
+                               fe->ops.i2c_gate_ctrl(fe, 0);
+                       }
+               }
        }
-
-       videobuf_dvb_unregister(&dev->dvb);
+       if (dev->dvb.frontend)
+               videobuf_dvb_unregister(&dev->dvb);
        return 0;
 }
 
index 3d2ec30de22799fc129bc80be208ef1c05c30146..1314522a8130784432147a5f8ad8e3ef35743a6f 100644 (file)
@@ -40,7 +40,7 @@ static unsigned int empress_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
 module_param_array(empress_nr, int, NULL, 0444);
 MODULE_PARM_DESC(empress_nr,"ts device number");
 
-static unsigned int debug = 0;
+static unsigned int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug,"enable debug messages");
 
@@ -402,7 +402,7 @@ static int empress_init(struct saa7134_dev *dev)
 {
        int err;
 
-       dprintk("%s: %s\n",dev->name,__FUNCTION__);
+       dprintk("%s: %s\n",dev->name,__func__);
        dev->empress_dev = video_device_alloc();
        if (NULL == dev->empress_dev)
                return -ENOMEM;
@@ -427,8 +427,8 @@ static int empress_init(struct saa7134_dev *dev)
        printk(KERN_INFO "%s: registered device video%d [mpeg]\n",
               dev->name,dev->empress_dev->minor & 0x1f);
 
-       videobuf_queue_pci_init(&dev->empress_tsq, &saa7134_ts_qops,
-                           dev->pci, &dev->slock,
+       videobuf_queue_sg_init(&dev->empress_tsq, &saa7134_ts_qops,
+                           &dev->pci->dev, &dev->slock,
                            V4L2_BUF_TYPE_VIDEO_CAPTURE,
                            V4L2_FIELD_ALTERNATE,
                            sizeof(struct saa7134_buf),
@@ -440,7 +440,7 @@ static int empress_init(struct saa7134_dev *dev)
 
 static int empress_fini(struct saa7134_dev *dev)
 {
-       dprintk("%s: %s\n",dev->name,__FUNCTION__);
+       dprintk("%s: %s\n",dev->name,__func__);
 
        if (NULL == dev->empress_dev)
                return 0;
index d3322c3018f2d6a7887584926005c025778f5b3d..2ccfaba0c490bfc6d42da43722a8ab6f665d42c9 100644 (file)
 
 /* ----------------------------------------------------------- */
 
-static unsigned int i2c_debug = 0;
+static unsigned int i2c_debug;
 module_param(i2c_debug, int, 0644);
 MODULE_PARM_DESC(i2c_debug,"enable debug messages [i2c]");
 
-static unsigned int i2c_scan = 0;
+static unsigned int i2c_scan;
 module_param(i2c_scan, int, 0444);
 MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time");
 
@@ -140,6 +140,8 @@ static inline int i2c_is_busy(enum i2c_status status)
 {
        switch (status) {
        case BUSY:
+       case TO_SCL:
+       case TO_ARB:
                return true;
        default:
                return false;
index b4188819782f2c6a0ae180565ede8b87765f8292..767ff30832f27d9e613ca3883c9f174438a59064 100644 (file)
 #include "saa7134-reg.h"
 #include "saa7134.h"
 
-static unsigned int disable_ir = 0;
+static unsigned int disable_ir;
 module_param(disable_ir, int, 0444);
 MODULE_PARM_DESC(disable_ir,"disable infrared remote support");
 
-static unsigned int ir_debug = 0;
+static unsigned int ir_debug;
 module_param(ir_debug, int, 0644);
 MODULE_PARM_DESC(ir_debug,"enable debug messages [IR]");
 
-static int pinnacle_remote = 0;
+static int pinnacle_remote;
 module_param(pinnacle_remote, int, 0644);    /* Choose Pinnacle PCTV remote */
 MODULE_PARM_DESC(pinnacle_remote, "Specify Pinnacle PCTV remote: 0=coloured, 1=grey (defaults to 0)");
 
@@ -331,6 +331,11 @@ int saa7134_input_init1(struct saa7134_dev *dev)
                break;
        case SAA7134_BOARD_MANLI_MTV001:
        case SAA7134_BOARD_MANLI_MTV002:
+               ir_codes     = ir_codes_manli;
+               mask_keycode = 0x001f00;
+               mask_keyup   = 0x004000;
+               polling      = 50; /* ms */
+               break;
        case SAA7134_BOARD_BEHOLD_409FM:
        case SAA7134_BOARD_BEHOLD_401:
        case SAA7134_BOARD_BEHOLD_403:
@@ -343,7 +348,13 @@ int saa7134_input_init1(struct saa7134_dev *dev)
        case SAA7134_BOARD_BEHOLD_505FM:
        case SAA7134_BOARD_BEHOLD_507_9FM:
                ir_codes     = ir_codes_manli;
-               mask_keycode = 0x001f00;
+               mask_keycode = 0x003f00;
+               mask_keyup   = 0x004000;
+               polling      = 50; /* ms */
+               break;
+       case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM:
+               ir_codes     = ir_codes_behold_columbus;
+               mask_keycode = 0x003f00;
                mask_keyup   = 0x004000;
                polling      = 50; // ms
                break;
index ac6431ba4fc37e9467b1c43b3ebb76582ff424f1..86f5eefdb0f6d94f5f245e4ded082688e91f975c 100644 (file)
 #define SAA7135_DSP_RWSTATE_RDB                 (1 << 1)
 #define SAA7135_DSP_RWSTATE_WRR                 (1 << 0)
 
+#define SAA7135_DSP_RWCLEAR                    0x586
+#define SAA7135_DSP_RWCLEAR_RERR                   1
+
 /* ------------------------------------------------------------------ */
 /*
  * Local variables:
index f1b8fcaeb43acc6ecddf2ae62c25aefafb117a76..eae72fd60cec6f6b3aa888d4bb380cb62cc10209 100644 (file)
@@ -32,7 +32,7 @@
 
 /* ------------------------------------------------------------------ */
 
-static unsigned int ts_debug  = 0;
+static unsigned int ts_debug;
 module_param(ts_debug, int, 0644);
 MODULE_PARM_DESC(ts_debug,"enable debug messages [ts]");
 
index 4e9810469ae309c0ac41917c2764a7977301658e..232af598d94709a9d66ef0bd898f13efca3cffeb 100644 (file)
 
 /* ------------------------------------------------------------------ */
 
-static unsigned int audio_debug = 0;
+static unsigned int audio_debug;
 module_param(audio_debug, int, 0644);
 MODULE_PARM_DESC(audio_debug,"enable debug messages [tv audio]");
 
-static unsigned int audio_ddep = 0;
+static unsigned int audio_ddep;
 module_param(audio_ddep, int, 0644);
 MODULE_PARM_DESC(audio_ddep,"audio ddep overwrite");
 
 static int audio_clock_override = UNSET;
 module_param(audio_clock_override, int, 0644);
 
-static int audio_clock_tweak = 0;
+static int audio_clock_tweak;
 module_param(audio_clock_tweak, int, 0644);
 MODULE_PARM_DESC(audio_clock_tweak, "Audio clock tick fine tuning for cards with audio crystal that's slightly off (range [-1024 .. 1024])");
 
@@ -653,6 +653,17 @@ static char *stdres[0x20] = {
 
 #define DSP_RETRY 32
 #define DSP_DELAY 16
+#define SAA7135_DSP_RWCLEAR_RERR 1
+
+static inline int saa_dsp_reset_error_bit(struct saa7134_dev *dev)
+{
+       int state = saa_readb(SAA7135_DSP_RWSTATE);
+       if (unlikely(state & SAA7135_DSP_RWSTATE_ERR)) {
+               d2printk("%s: resetting error bit\n", dev->name);
+               saa_writeb(SAA7135_DSP_RWCLEAR, SAA7135_DSP_RWCLEAR_RERR);
+       }
+       return 0;
+}
 
 static inline int saa_dsp_wait_bit(struct saa7134_dev *dev, int bit)
 {
@@ -660,8 +671,8 @@ static inline int saa_dsp_wait_bit(struct saa7134_dev *dev, int bit)
 
        state = saa_readb(SAA7135_DSP_RWSTATE);
        if (unlikely(state & SAA7135_DSP_RWSTATE_ERR)) {
-               printk("%s: dsp access error\n",dev->name);
-               /* FIXME: send ack ... */
+               printk(KERN_WARNING "%s: dsp access error\n", dev->name);
+               saa_dsp_reset_error_bit(dev);
                return -EIO;
        }
        while (0 == (state & bit)) {
index f0d5ed9c2b0666e1152611f3325f89a6d8914182..cb0304298a96ec27419ba219259012ab021037b4 100644 (file)
@@ -31,7 +31,7 @@
 
 /* ------------------------------------------------------------------ */
 
-static unsigned int vbi_debug  = 0;
+static unsigned int vbi_debug;
 module_param(vbi_debug, int, 0644);
 MODULE_PARM_DESC(vbi_debug,"enable debug messages [vbi]");
 
index 39c41ad97d0ecfb3bafcec5fcc2a9ace517afe68..a0baf2d0ba7f307bade2c320716ce08b9b143d18 100644 (file)
@@ -40,7 +40,7 @@
 
 unsigned int video_debug;
 static unsigned int gbuffers      = 8;
-static unsigned int noninterlaced = 0;
+static unsigned int noninterlaced; /* 0 */
 static unsigned int gbufsize      = 720*576*4;
 static unsigned int gbufsize_max  = 720*576*4;
 static char secam[] = "--";
@@ -626,13 +626,8 @@ void saa7134_set_tvnorm_hw(struct saa7134_dev *dev)
 {
        saa7134_set_decoder(dev);
 
-       if (card_in(dev, dev->ctl_input).tv) {
-               if ((card(dev).tuner_type == TUNER_PHILIPS_TDA8290)
-                               && ((card(dev).tuner_config == 1)
-                               ||  (card(dev).tuner_config == 2)))
-                       saa7134_set_gpio(dev, 22, 5);
+       if (card_in(dev, dev->ctl_input).tv)
                saa7134_i2c_call_clients(dev, VIDIOC_S_STD, &dev->tvnorm->id);
-       }
 }
 
 static void set_h_prescale(struct saa7134_dev *dev, int task, int prescale)
@@ -1350,14 +1345,14 @@ static int video_open(struct inode *inode, struct file *file)
        fh->height   = 576;
        v4l2_prio_open(&dev->prio,&fh->prio);
 
-       videobuf_queue_pci_init(&fh->cap, &video_qops,
-                           dev->pci, &dev->slock,
+       videobuf_queue_sg_init(&fh->cap, &video_qops,
+                           &dev->pci->dev, &dev->slock,
                            V4L2_BUF_TYPE_VIDEO_CAPTURE,
                            V4L2_FIELD_INTERLACED,
                            sizeof(struct saa7134_buf),
                            fh);
-       videobuf_queue_pci_init(&fh->vbi, &saa7134_vbi_qops,
-                           dev->pci, &dev->slock,
+       videobuf_queue_sg_init(&fh->vbi, &saa7134_vbi_qops,
+                           &dev->pci->dev, &dev->slock,
                            V4L2_BUF_TYPE_VBI_CAPTURE,
                            V4L2_FIELD_SEQ_TB,
                            sizeof(struct saa7134_buf),
index f940d0254798a6eb6ae7da25e986be7998fa8bd6..924ffd13637ead8b5e66d058b037ae7b9cbb9bd1 100644 (file)
@@ -253,7 +253,17 @@ struct saa7134_format {
 #define SAA7134_BOARD_BEHOLD_607_9FM   129
 #define SAA7134_BOARD_BEHOLD_M6                130
 #define SAA7134_BOARD_TWINHAN_DTV_DVB_3056 131
-#define SAA7134_BOARD_GENIUS_TVGO_A11MCE 132
+#define SAA7134_BOARD_GENIUS_TVGO_A11MCE   132
+#define SAA7134_BOARD_PHILIPS_SNAKE        133
+#define SAA7134_BOARD_CREATIX_CTX953       134
+#define SAA7134_BOARD_MSI_TVANYWHERE_AD11  135
+#define SAA7134_BOARD_AVERMEDIA_CARDBUS_506 136
+#define SAA7134_BOARD_AVERMEDIA_A16D       137
+#define SAA7134_BOARD_AVERMEDIA_M115       138
+#define SAA7134_BOARD_VIDEOMATE_T750       139
+#define SAA7134_BOARD_AVERMEDIA_A700_PRO    140
+#define SAA7134_BOARD_AVERMEDIA_A700_HYBRID 141
+
 
 #define SAA7134_MAXBOARDS 8
 #define SAA7134_INPUT_MAX 8
@@ -380,9 +390,7 @@ struct saa7134_fh {
        unsigned int               radio;
        enum v4l2_buf_type         type;
        unsigned int               resources;
-#ifdef VIDIOC_G_PRIORITY
        enum v4l2_priority         prio;
-#endif
 
        /* video overlay */
        struct v4l2_window         win;
@@ -454,9 +462,7 @@ struct saa7134_dev {
        struct list_head           devlist;
        struct mutex               lock;
        spinlock_t                 slock;
-#ifdef VIDIOC_G_PRIORITY
        struct v4l2_prio_state     prio;
-#endif
        /* workstruct for loading modules */
        struct work_struct request_module_wk;
 
@@ -556,7 +562,9 @@ struct saa7134_dev {
 #if defined(CONFIG_VIDEO_SAA7134_DVB) || defined(CONFIG_VIDEO_SAA7134_DVB_MODULE)
        /* SAA7134_MPEG_DVB only */
        struct videobuf_dvb        dvb;
-       int (*original_demod_sleep)(struct dvb_frontend* fe);
+       int (*original_demod_sleep)(struct dvb_frontend *fe);
+       int (*original_set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage);
+       int (*original_set_high_voltage)(struct dvb_frontend *fe, long arg);
 #endif
 };
 
@@ -594,7 +602,6 @@ extern int saa7134_no_overlay;
 
 void saa7134_track_gpio(struct saa7134_dev *dev, char *msg);
 void saa7134_set_gpio(struct saa7134_dev *dev, int bit_no, int value);
-int saa7134_tuner_callback(void *ptr, int command, int arg);
 
 #define SAA7134_PGTABLE_SIZE 4096
 
@@ -631,6 +638,7 @@ extern struct pci_device_id __devinitdata saa7134_pci_tbl[];
 
 extern int saa7134_board_init1(struct saa7134_dev *dev);
 extern int saa7134_board_init2(struct saa7134_dev *dev);
+int saa7134_tuner_callback(void *priv, int command, int arg);
 
 
 /* ----------------------------------------------------------- */
diff --git a/drivers/media/video/saa717x.c b/drivers/media/video/saa717x.c
new file mode 100644 (file)
index 0000000..53c5edb
--- /dev/null
@@ -0,0 +1,1516 @@
+/*
+ * saa717x - Philips SAA717xHL video decoder driver
+ *
+ * Based on the saa7115 driver
+ *
+ * Changes by Ohta Kyuma <alpha292@bremen.or.jp>
+ *    - Apply to SAA717x,NEC uPD64031,uPD64083. (1/31/2004)
+ *
+ * Changes by T.Adachi (tadachi@tadachi-net.com)
+ *    - support audio, video scaler etc, and checked the initialize sequence.
+ *
+ * Cleaned up by Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * Note: this is a reversed engineered driver based on captures from
+ * the I2C bus under Windows. This chip is very similar to the saa7134,
+ * though. Unfortunately, this driver is currently only working for NTSC.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+#include <linux/videodev.h>
+#include <linux/videodev2.h>
+#include <linux/i2c.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-i2c-drv.h>
+
+MODULE_DESCRIPTION("Philips SAA717x audio/video decoder driver");
+MODULE_AUTHOR("K. Ohta, T. Adachi, Hans Verkuil");
+MODULE_LICENSE("GPL");
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Debug level (0-1)");
+
+/*
+ * Generic i2c probe
+ * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
+ */
+
+struct saa717x_state {
+       v4l2_std_id std;
+       int input;
+       int enable;
+       int radio;
+       int bright;
+       int contrast;
+       int hue;
+       int sat;
+       int playback;
+       int audio;
+       int tuner_audio_mode;
+       int audio_main_mute;
+       int audio_main_vol_r;
+       int audio_main_vol_l;
+       u16 audio_main_bass;
+       u16 audio_main_treble;
+       u16 audio_main_volume;
+       u16 audio_main_balance;
+       int audio_input;
+};
+
+/* ----------------------------------------------------------------------- */
+
+/* for audio mode */
+#define TUNER_AUDIO_MONO       0  /* LL */
+#define TUNER_AUDIO_STEREO     1  /* LR */
+#define TUNER_AUDIO_LANG1      2  /* LL */
+#define TUNER_AUDIO_LANG2      3  /* RR */
+
+#define SAA717X_NTSC_WIDTH     (704)
+#define SAA717X_NTSC_HEIGHT    (480)
+
+/* ----------------------------------------------------------------------- */
+
+static int saa717x_write(struct i2c_client *client, u32 reg, u32 value)
+{
+       struct i2c_adapter *adap = client->adapter;
+       int fw_addr = reg == 0x454 || (reg >= 0x464 && reg <= 0x478) || reg == 0x480 || reg == 0x488;
+       unsigned char mm1[6];
+       struct i2c_msg msg;
+
+       msg.flags = 0;
+       msg.addr = client->addr;
+       mm1[0] = (reg >> 8) & 0xff;
+       mm1[1] = reg & 0xff;
+
+       if (fw_addr) {
+               mm1[4] = (value >> 16) & 0xff;
+               mm1[3] = (value >> 8) & 0xff;
+               mm1[2] = value & 0xff;
+       } else {
+               mm1[2] = value & 0xff;
+       }
+       msg.len = fw_addr ? 5 : 3; /* Long Registers have *only* three bytes! */
+       msg.buf = mm1;
+       v4l_dbg(2, debug, client, "wrote:  reg 0x%03x=%08x\n", reg, value);
+       return i2c_transfer(adap, &msg, 1) == 1;
+}
+
+static void saa717x_write_regs(struct i2c_client *client, u32 *data)
+{
+       while (data[0] || data[1]) {
+               saa717x_write(client, data[0], data[1]);
+               data += 2;
+       }
+}
+
+static u32 saa717x_read(struct i2c_client *client, u32 reg)
+{
+       struct i2c_adapter *adap = client->adapter;
+       int fw_addr = (reg >= 0x404 && reg <= 0x4b8) || reg == 0x528;
+       unsigned char mm1[2];
+       unsigned char mm2[4] = { 0, 0, 0, 0 };
+       struct i2c_msg msgs[2];
+       u32 value;
+
+       msgs[0].flags = 0;
+       msgs[1].flags = I2C_M_RD;
+       msgs[0].addr = msgs[1].addr = client->addr;
+       mm1[0] = (reg >> 8) & 0xff;
+       mm1[1] = reg & 0xff;
+       msgs[0].len = 2;
+       msgs[0].buf = mm1;
+       msgs[1].len = fw_addr ? 3 : 1; /* Multibyte Registers contains *only* 3 bytes */
+       msgs[1].buf = mm2;
+       i2c_transfer(adap, msgs, 2);
+
+       if (fw_addr)
+               value = (mm2[2] & 0xff)  | ((mm2[1] & 0xff) >> 8) | ((mm2[0] & 0xff) >> 16);
+       else
+               value = mm2[0] & 0xff;
+
+       v4l_dbg(2, debug, client, "read:  reg 0x%03x=0x%08x\n", reg, value);
+       return value;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static u32 reg_init_initialize[] =
+{
+       /* from linux driver */
+       0x101, 0x008, /* Increment delay */
+
+       0x103, 0x000, /* Analog input control 2 */
+       0x104, 0x090, /* Analog input control 3 */
+       0x105, 0x090, /* Analog input control 4 */
+       0x106, 0x0eb, /* Horizontal sync start */
+       0x107, 0x0e0, /* Horizontal sync stop */
+       0x109, 0x055, /* Luminance control */
+
+       0x10f, 0x02a, /* Chroma gain control */
+       0x110, 0x000, /* Chroma control 2 */
+
+       0x114, 0x045, /* analog/ADC */
+
+       0x118, 0x040, /* RAW data gain */
+       0x119, 0x080, /* RAW data offset */
+
+       0x044, 0x000, /* VBI horizontal input window start (L) TASK A */
+       0x045, 0x000, /* VBI horizontal input window start (H) TASK A */
+       0x046, 0x0cf, /* VBI horizontal input window stop (L) TASK A */
+       0x047, 0x002, /* VBI horizontal input window stop (H) TASK A */
+
+       0x049, 0x000, /* VBI vertical input window start (H) TASK A */
+
+       0x04c, 0x0d0, /* VBI horizontal output length (L) TASK A */
+       0x04d, 0x002, /* VBI horizontal output length (H) TASK A */
+
+       0x064, 0x080, /* Lumina brightness TASK A */
+       0x065, 0x040, /* Luminance contrast TASK A */
+       0x066, 0x040, /* Chroma saturation TASK A */
+       /* 067H: Reserved */
+       0x068, 0x000, /* VBI horizontal scaling increment (L) TASK A */
+       0x069, 0x004, /* VBI horizontal scaling increment (H) TASK A */
+       0x06a, 0x000, /* VBI phase offset TASK A */
+
+       0x06e, 0x000, /* Horizontal phase offset Luma TASK A */
+       0x06f, 0x000, /* Horizontal phase offset Chroma TASK A */
+
+       0x072, 0x000, /* Vertical filter mode TASK A */
+
+       0x084, 0x000, /* VBI horizontal input window start (L) TAKS B */
+       0x085, 0x000, /* VBI horizontal input window start (H) TAKS B */
+       0x086, 0x0cf, /* VBI horizontal input window stop (L) TAKS B */
+       0x087, 0x002, /* VBI horizontal input window stop (H) TAKS B */
+
+       0x089, 0x000, /* VBI vertical input window start (H) TAKS B */
+
+       0x08c, 0x0d0, /* VBI horizontal output length (L) TASK B */
+       0x08d, 0x002, /* VBI horizontal output length (H) TASK B */
+
+       0x0a4, 0x080, /* Lumina brightness TASK B */
+       0x0a5, 0x040, /* Luminance contrast TASK B */
+       0x0a6, 0x040, /* Chroma saturation TASK B */
+       /* 0A7H reserved */
+       0x0a8, 0x000, /* VBI horizontal scaling increment (L) TASK B */
+       0x0a9, 0x004, /* VBI horizontal scaling increment (H) TASK B */
+       0x0aa, 0x000, /* VBI phase offset TASK B */
+
+       0x0ae, 0x000, /* Horizontal phase offset Luma TASK B */
+       0x0af, 0x000, /*Horizontal phase offset Chroma TASK B */
+
+       0x0b2, 0x000, /* Vertical filter mode TASK B */
+
+       0x00c, 0x000, /* Start point GREEN path */
+       0x00d, 0x000, /* Start point BLUE path */
+       0x00e, 0x000, /* Start point RED path */
+
+       0x010, 0x010, /* GREEN path gamma curve --- */
+       0x011, 0x020,
+       0x012, 0x030,
+       0x013, 0x040,
+       0x014, 0x050,
+       0x015, 0x060,
+       0x016, 0x070,
+       0x017, 0x080,
+       0x018, 0x090,
+       0x019, 0x0a0,
+       0x01a, 0x0b0,
+       0x01b, 0x0c0,
+       0x01c, 0x0d0,
+       0x01d, 0x0e0,
+       0x01e, 0x0f0,
+       0x01f, 0x0ff, /* --- GREEN path gamma curve */
+
+       0x020, 0x010, /* BLUE path gamma curve --- */
+       0x021, 0x020,
+       0x022, 0x030,
+       0x023, 0x040,
+       0x024, 0x050,
+       0x025, 0x060,
+       0x026, 0x070,
+       0x027, 0x080,
+       0x028, 0x090,
+       0x029, 0x0a0,
+       0x02a, 0x0b0,
+       0x02b, 0x0c0,
+       0x02c, 0x0d0,
+       0x02d, 0x0e0,
+       0x02e, 0x0f0,
+       0x02f, 0x0ff, /* --- BLUE path gamma curve */
+
+       0x030, 0x010, /* RED path gamma curve --- */
+       0x031, 0x020,
+       0x032, 0x030,
+       0x033, 0x040,
+       0x034, 0x050,
+       0x035, 0x060,
+       0x036, 0x070,
+       0x037, 0x080,
+       0x038, 0x090,
+       0x039, 0x0a0,
+       0x03a, 0x0b0,
+       0x03b, 0x0c0,
+       0x03c, 0x0d0,
+       0x03d, 0x0e0,
+       0x03e, 0x0f0,
+       0x03f, 0x0ff, /* --- RED path gamma curve */
+
+       0x109, 0x085, /* Luminance control  */
+
+       /**** from app start ****/
+       0x584, 0x000, /* AGC gain control */
+       0x585, 0x000, /* Program count */
+       0x586, 0x003, /* Status reset */
+       0x588, 0x0ff, /* Number of audio samples (L) */
+       0x589, 0x00f, /* Number of audio samples (M) */
+       0x58a, 0x000, /* Number of audio samples (H) */
+       0x58b, 0x000, /* Audio select */
+       0x58c, 0x010, /* Audio channel assign1 */
+       0x58d, 0x032, /* Audio channel assign2 */
+       0x58e, 0x054, /* Audio channel assign3 */
+       0x58f, 0x023, /* Audio format */
+       0x590, 0x000, /* SIF control */
+
+       0x595, 0x000, /* ?? */
+       0x596, 0x000, /* ?? */
+       0x597, 0x000, /* ?? */
+
+       0x464, 0x00, /* Digital input crossbar1 */
+
+       0x46c, 0xbbbb10, /* Digital output selection1-3 */
+       0x470, 0x101010, /* Digital output selection4-6 */
+
+       0x478, 0x00, /* Sound feature control */
+
+       0x474, 0x18, /* Softmute control */
+
+       0x454, 0x0425b9, /* Sound Easy programming(reset) */
+       0x454, 0x042539, /* Sound Easy programming(reset) */
+
+
+       /**** common setting( of DVD play, including scaler commands) ****/
+       0x042, 0x003, /* Data path configuration for VBI (TASK A) */
+
+       0x082, 0x003, /* Data path configuration for VBI (TASK B) */
+
+       0x108, 0x0f8, /* Sync control */
+       0x2a9, 0x0fd, /* ??? */
+       0x102, 0x089, /* select video input "mode 9" */
+       0x111, 0x000, /* Mode/delay control */
+
+       0x10e, 0x00a, /* Chroma control 1 */
+
+       0x594, 0x002, /* SIF, analog I/O select */
+
+       0x454, 0x0425b9, /* Sound  */
+       0x454, 0x042539,
+
+       0x111, 0x000,
+       0x10e, 0x00a,
+       0x464, 0x000,
+       0x300, 0x000,
+       0x301, 0x006,
+       0x302, 0x000,
+       0x303, 0x006,
+       0x308, 0x040,
+       0x309, 0x000,
+       0x30a, 0x000,
+       0x30b, 0x000,
+       0x000, 0x002,
+       0x001, 0x000,
+       0x002, 0x000,
+       0x003, 0x000,
+       0x004, 0x033,
+       0x040, 0x01d,
+       0x041, 0x001,
+       0x042, 0x004,
+       0x043, 0x000,
+       0x080, 0x01e,
+       0x081, 0x001,
+       0x082, 0x004,
+       0x083, 0x000,
+       0x190, 0x018,
+       0x115, 0x000,
+       0x116, 0x012,
+       0x117, 0x018,
+       0x04a, 0x011,
+       0x08a, 0x011,
+       0x04b, 0x000,
+       0x08b, 0x000,
+       0x048, 0x000,
+       0x088, 0x000,
+       0x04e, 0x012,
+       0x08e, 0x012,
+       0x058, 0x012,
+       0x098, 0x012,
+       0x059, 0x000,
+       0x099, 0x000,
+       0x05a, 0x003,
+       0x09a, 0x003,
+       0x05b, 0x001,
+       0x09b, 0x001,
+       0x054, 0x008,
+       0x094, 0x008,
+       0x055, 0x000,
+       0x095, 0x000,
+       0x056, 0x0c7,
+       0x096, 0x0c7,
+       0x057, 0x002,
+       0x097, 0x002,
+       0x0ff, 0x0ff,
+       0x060, 0x001,
+       0x0a0, 0x001,
+       0x061, 0x000,
+       0x0a1, 0x000,
+       0x062, 0x000,
+       0x0a2, 0x000,
+       0x063, 0x000,
+       0x0a3, 0x000,
+       0x070, 0x000,
+       0x0b0, 0x000,
+       0x071, 0x004,
+       0x0b1, 0x004,
+       0x06c, 0x0e9,
+       0x0ac, 0x0e9,
+       0x06d, 0x003,
+       0x0ad, 0x003,
+       0x05c, 0x0d0,
+       0x09c, 0x0d0,
+       0x05d, 0x002,
+       0x09d, 0x002,
+       0x05e, 0x0f2,
+       0x09e, 0x0f2,
+       0x05f, 0x000,
+       0x09f, 0x000,
+       0x074, 0x000,
+       0x0b4, 0x000,
+       0x075, 0x000,
+       0x0b5, 0x000,
+       0x076, 0x000,
+       0x0b6, 0x000,
+       0x077, 0x000,
+       0x0b7, 0x000,
+       0x195, 0x008,
+       0x0ff, 0x0ff,
+       0x108, 0x0f8,
+       0x111, 0x000,
+       0x10e, 0x00a,
+       0x2a9, 0x0fd,
+       0x464, 0x001,
+       0x454, 0x042135,
+       0x598, 0x0e7,
+       0x599, 0x07d,
+       0x59a, 0x018,
+       0x59c, 0x066,
+       0x59d, 0x090,
+       0x59e, 0x001,
+       0x584, 0x000,
+       0x585, 0x000,
+       0x586, 0x003,
+       0x588, 0x0ff,
+       0x589, 0x00f,
+       0x58a, 0x000,
+       0x58b, 0x000,
+       0x58c, 0x010,
+       0x58d, 0x032,
+       0x58e, 0x054,
+       0x58f, 0x023,
+       0x590, 0x000,
+       0x595, 0x000,
+       0x596, 0x000,
+       0x597, 0x000,
+       0x464, 0x000,
+       0x46c, 0xbbbb10,
+       0x470, 0x101010,
+
+
+       0x478, 0x000,
+       0x474, 0x018,
+       0x454, 0x042135,
+       0x598, 0x0e7,
+       0x599, 0x07d,
+       0x59a, 0x018,
+       0x59c, 0x066,
+       0x59d, 0x090,
+       0x59e, 0x001,
+       0x584, 0x000,
+       0x585, 0x000,
+       0x586, 0x003,
+       0x588, 0x0ff,
+       0x589, 0x00f,
+       0x58a, 0x000,
+       0x58b, 0x000,
+       0x58c, 0x010,
+       0x58d, 0x032,
+       0x58e, 0x054,
+       0x58f, 0x023,
+       0x590, 0x000,
+       0x595, 0x000,
+       0x596, 0x000,
+       0x597, 0x000,
+       0x464, 0x000,
+       0x46c, 0xbbbb10,
+       0x470, 0x101010,
+
+       0x478, 0x000,
+       0x474, 0x018,
+       0x454, 0x042135,
+       0x598, 0x0e7,
+       0x599, 0x07d,
+       0x59a, 0x018,
+       0x59c, 0x066,
+       0x59d, 0x090,
+       0x59e, 0x001,
+       0x584, 0x000,
+       0x585, 0x000,
+       0x586, 0x003,
+       0x588, 0x0ff,
+       0x589, 0x00f,
+       0x58a, 0x000,
+       0x58b, 0x000,
+       0x58c, 0x010,
+       0x58d, 0x032,
+       0x58e, 0x054,
+       0x58f, 0x023,
+       0x590, 0x000,
+       0x595, 0x000,
+       0x596, 0x000,
+       0x597, 0x000,
+       0x464, 0x000,
+       0x46c, 0xbbbb10,
+       0x470, 0x101010,
+       0x478, 0x000,
+       0x474, 0x018,
+       0x454, 0x042135,
+       0x193, 0x000,
+       0x300, 0x000,
+       0x301, 0x006,
+       0x302, 0x000,
+       0x303, 0x006,
+       0x308, 0x040,
+       0x309, 0x000,
+       0x30a, 0x000,
+       0x30b, 0x000,
+       0x000, 0x002,
+       0x001, 0x000,
+       0x002, 0x000,
+       0x003, 0x000,
+       0x004, 0x033,
+       0x040, 0x01d,
+       0x041, 0x001,
+       0x042, 0x004,
+       0x043, 0x000,
+       0x080, 0x01e,
+       0x081, 0x001,
+       0x082, 0x004,
+       0x083, 0x000,
+       0x190, 0x018,
+       0x115, 0x000,
+       0x116, 0x012,
+       0x117, 0x018,
+       0x04a, 0x011,
+       0x08a, 0x011,
+       0x04b, 0x000,
+       0x08b, 0x000,
+       0x048, 0x000,
+       0x088, 0x000,
+       0x04e, 0x012,
+       0x08e, 0x012,
+       0x058, 0x012,
+       0x098, 0x012,
+       0x059, 0x000,
+       0x099, 0x000,
+       0x05a, 0x003,
+       0x09a, 0x003,
+       0x05b, 0x001,
+       0x09b, 0x001,
+       0x054, 0x008,
+       0x094, 0x008,
+       0x055, 0x000,
+       0x095, 0x000,
+       0x056, 0x0c7,
+       0x096, 0x0c7,
+       0x057, 0x002,
+       0x097, 0x002,
+       0x060, 0x001,
+       0x0a0, 0x001,
+       0x061, 0x000,
+       0x0a1, 0x000,
+       0x062, 0x000,
+       0x0a2, 0x000,
+       0x063, 0x000,
+       0x0a3, 0x000,
+       0x070, 0x000,
+       0x0b0, 0x000,
+       0x071, 0x004,
+       0x0b1, 0x004,
+       0x06c, 0x0e9,
+       0x0ac, 0x0e9,
+       0x06d, 0x003,
+       0x0ad, 0x003,
+       0x05c, 0x0d0,
+       0x09c, 0x0d0,
+       0x05d, 0x002,
+       0x09d, 0x002,
+       0x05e, 0x0f2,
+       0x09e, 0x0f2,
+       0x05f, 0x000,
+       0x09f, 0x000,
+       0x074, 0x000,
+       0x0b4, 0x000,
+       0x075, 0x000,
+       0x0b5, 0x000,
+       0x076, 0x000,
+       0x0b6, 0x000,
+       0x077, 0x000,
+       0x0b7, 0x000,
+       0x195, 0x008,
+       0x598, 0x0e7,
+       0x599, 0x07d,
+       0x59a, 0x018,
+       0x59c, 0x066,
+       0x59d, 0x090,
+       0x59e, 0x001,
+       0x584, 0x000,
+       0x585, 0x000,
+       0x586, 0x003,
+       0x588, 0x0ff,
+       0x589, 0x00f,
+       0x58a, 0x000,
+       0x58b, 0x000,
+       0x58c, 0x010,
+       0x58d, 0x032,
+       0x58e, 0x054,
+       0x58f, 0x023,
+       0x590, 0x000,
+       0x595, 0x000,
+       0x596, 0x000,
+       0x597, 0x000,
+       0x464, 0x000,
+       0x46c, 0xbbbb10,
+       0x470, 0x101010,
+       0x478, 0x000,
+       0x474, 0x018,
+       0x454, 0x042135,
+       0x193, 0x0a6,
+       0x108, 0x0f8,
+       0x042, 0x003,
+       0x082, 0x003,
+       0x454, 0x0425b9,
+       0x454, 0x042539,
+       0x193, 0x000,
+       0x193, 0x0a6,
+       0x464, 0x000,
+
+       0, 0
+};
+
+/* Tuner */
+static u32 reg_init_tuner_input[] = {
+       0x108, 0x0f8, /* Sync control */
+       0x111, 0x000, /* Mode/delay control */
+       0x10e, 0x00a, /* Chroma control 1 */
+       0, 0
+};
+
+/* Composite */
+static u32 reg_init_composite_input[] = {
+       0x108, 0x0e8, /* Sync control */
+       0x111, 0x000, /* Mode/delay control */
+       0x10e, 0x04a, /* Chroma control 1 */
+       0, 0
+};
+
+/* S-Video */
+static u32 reg_init_svideo_input[] = {
+       0x108, 0x0e8, /* Sync control */
+       0x111, 0x000, /* Mode/delay control */
+       0x10e, 0x04a, /* Chroma control 1 */
+       0, 0
+};
+
+static u32 reg_set_audio_template[4][2] =
+{
+       { /* for MONO
+               tadachi 6/29 DMA audio output select?
+               Register 0x46c
+               7-4: DMA2, 3-0: DMA1 ch. DMA4, DMA3 DMA2, DMA1
+               0: MAIN left,  1: MAIN right
+               2: AUX1 left,  3: AUX1 right
+               4: AUX2 left,  5: AUX2 right
+               6: DPL left,   7: DPL  right
+               8: DPL center, 9: DPL surround
+               A: monitor output, B: digital sense */
+               0xbbbb00,
+
+               /* tadachi 6/29 DAC and I2S output select?
+                  Register 0x470
+                  7-4:DAC right ch. 3-0:DAC left ch.
+                  I2S1 right,left  I2S2 right,left */
+               0x00,
+       },
+       { /* for STEREO */
+               0xbbbb10, 0x101010,
+       },
+       { /* for LANG1 */
+               0xbbbb00, 0x00,
+       },
+       { /* for LANG2/SAP */
+               0xbbbb11, 0x111111,
+       }
+};
+
+
+/* Get detected audio flags (from saa7134 driver) */
+static void get_inf_dev_status(struct i2c_client *client,
+               int *dual_flag, int *stereo_flag)
+{
+       u32 reg_data3;
+
+       static char *stdres[0x20] = {
+               [0x00] = "no standard detected",
+               [0x01] = "B/G (in progress)",
+               [0x02] = "D/K (in progress)",
+               [0x03] = "M (in progress)",
+
+               [0x04] = "B/G A2",
+               [0x05] = "B/G NICAM",
+               [0x06] = "D/K A2 (1)",
+               [0x07] = "D/K A2 (2)",
+               [0x08] = "D/K A2 (3)",
+               [0x09] = "D/K NICAM",
+               [0x0a] = "L NICAM",
+               [0x0b] = "I NICAM",
+
+               [0x0c] = "M Korea",
+               [0x0d] = "M BTSC ",
+               [0x0e] = "M EIAJ",
+
+               [0x0f] = "FM radio / IF 10.7 / 50 deemp",
+               [0x10] = "FM radio / IF 10.7 / 75 deemp",
+               [0x11] = "FM radio / IF sel / 50 deemp",
+               [0x12] = "FM radio / IF sel / 75 deemp",
+
+               [0x13 ... 0x1e] = "unknown",
+               [0x1f] = "??? [in progress]",
+       };
+
+
+       *dual_flag = *stereo_flag = 0;
+
+       /* (demdec status: 0x528) */
+
+       /* read current status */
+       reg_data3 = saa717x_read(client, 0x0528);
+
+       v4l_dbg(1, debug, client, "tvaudio thread status: 0x%x [%s%s%s]\n",
+               reg_data3, stdres[reg_data3 & 0x1f],
+               (reg_data3 & 0x000020) ? ",stereo" : "",
+               (reg_data3 & 0x000040) ? ",dual"   : "");
+       v4l_dbg(1, debug, client, "detailed status: "
+               "%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s\n",
+               (reg_data3 & 0x000080) ? " A2/EIAJ pilot tone "     : "",
+               (reg_data3 & 0x000100) ? " A2/EIAJ dual "           : "",
+               (reg_data3 & 0x000200) ? " A2/EIAJ stereo "         : "",
+               (reg_data3 & 0x000400) ? " A2/EIAJ noise mute "     : "",
+
+               (reg_data3 & 0x000800) ? " BTSC/FM radio pilot "    : "",
+               (reg_data3 & 0x001000) ? " SAP carrier "            : "",
+               (reg_data3 & 0x002000) ? " BTSC stereo noise mute " : "",
+               (reg_data3 & 0x004000) ? " SAP noise mute "         : "",
+               (reg_data3 & 0x008000) ? " VDSP "                   : "",
+
+               (reg_data3 & 0x010000) ? " NICST "                  : "",
+               (reg_data3 & 0x020000) ? " NICDU "                  : "",
+               (reg_data3 & 0x040000) ? " NICAM muted "            : "",
+               (reg_data3 & 0x080000) ? " NICAM reserve sound "    : "",
+
+               (reg_data3 & 0x100000) ? " init done "              : "");
+
+       if (reg_data3 & 0x000220) {
+               v4l_dbg(1, debug, client, "ST!!!\n");
+               *stereo_flag = 1;
+       }
+
+       if (reg_data3 & 0x000140) {
+               v4l_dbg(1, debug, client, "DUAL!!!\n");
+               *dual_flag = 1;
+       }
+}
+
+/* regs write to set audio mode */
+static void set_audio_mode(struct i2c_client *client, int audio_mode)
+{
+       v4l_dbg(1, debug, client, "writing registers to set audio mode by set %d\n",
+                       audio_mode);
+
+       saa717x_write(client, 0x46c, reg_set_audio_template[audio_mode][0]);
+       saa717x_write(client, 0x470, reg_set_audio_template[audio_mode][1]);
+}
+
+/* write regs to video output level (bright,contrast,hue,sat) */
+static void set_video_output_level_regs(struct i2c_client *client,
+               struct saa717x_state *decoder)
+{
+       /* brightness ffh (bright) - 80h (ITU level) - 00h (dark) */
+       saa717x_write(client, 0x10a, decoder->bright);
+
+       /* contrast 7fh (max: 1.984) - 44h (ITU) - 40h (1.0) -
+          0h (luminance off) 40: i2c dump
+          c0h (-1.0 inverse chrominance)
+          80h (-2.0 inverse chrominance) */
+       saa717x_write(client, 0x10b, decoder->contrast);
+
+       /* saturation? 7fh(max)-40h(ITU)-0h(color off)
+          c0h (-1.0 inverse chrominance)
+          80h (-2.0 inverse chrominance) */
+       saa717x_write(client, 0x10c, decoder->sat);
+
+       /* color hue (phase) control
+          7fh (+178.6) - 0h (0 normal) - 80h (-180.0) */
+       saa717x_write(client, 0x10d, decoder->hue);
+}
+
+/* write regs to set audio volume, bass and treble */
+static int set_audio_regs(struct i2c_client *client,
+               struct saa717x_state *decoder)
+{
+       u8 mute = 0xac; /* -84 dB */
+       u32 val;
+       unsigned int work_l, work_r;
+
+       /* set SIF analog I/O select */
+       saa717x_write(client, 0x0594, decoder->audio_input);
+       v4l_dbg(1, debug, client, "set audio input %d\n",
+                       decoder->audio_input);
+
+       /* normalize ( 65535 to 0 -> 24 to -40 (not -84)) */
+       work_l = (min(65536 - decoder->audio_main_balance, 32768) * decoder->audio_main_volume) / 32768;
+       work_r = (min(decoder->audio_main_balance, (u16)32768) * decoder->audio_main_volume) / 32768;
+       decoder->audio_main_vol_l = (long)work_l * (24 - (-40)) / 65535 - 40;
+       decoder->audio_main_vol_r = (long)work_r * (24 - (-40)) / 65535 - 40;
+
+       /* set main volume */
+       /* main volume L[7-0],R[7-0],0x00  24=24dB,-83dB, -84(mute) */
+       /*    def:0dB->6dB(MPG600GR) */
+       /* if mute is on, set mute */
+       if (decoder->audio_main_mute) {
+               val = mute | (mute << 8);
+       } else {
+               val = (u8)decoder->audio_main_vol_l |
+                       ((u8)decoder->audio_main_vol_r << 8);
+       }
+
+       saa717x_write(client, 0x480, val);
+
+       /* bass and treble; go to another function */
+       /* set bass and treble */
+       val = decoder->audio_main_bass | (decoder->audio_main_treble << 8);
+       saa717x_write(client, 0x488, val);
+       return 0;
+}
+
+/********** scaling staff ***********/
+static void set_h_prescale(struct i2c_client *client,
+               int task, int prescale)
+{
+       static const struct {
+               int xpsc;
+               int xacl;
+               int xc2_1;
+               int xdcg;
+               int vpfy;
+       } vals[] = {
+               /* XPSC XACL XC2_1 XDCG VPFY */
+               {    1,   0,    0,    0,   0 },
+               {    2,   2,    1,    2,   2 },
+               {    3,   4,    1,    3,   2 },
+               {    4,   8,    1,    4,   2 },
+               {    5,   8,    1,    4,   2 },
+               {    6,   8,    1,    4,   3 },
+               {    7,   8,    1,    4,   3 },
+               {    8,  15,    0,    4,   3 },
+               {    9,  15,    0,    4,   3 },
+               {   10,  16,    1,    5,   3 },
+       };
+       static const int count = ARRAY_SIZE(vals);
+       int i, task_shift;
+
+       task_shift = task * 0x40;
+       for (i = 0; i < count; i++)
+               if (vals[i].xpsc == prescale)
+                       break;
+       if (i == count)
+               return;
+
+       /* horizonal prescaling */
+       saa717x_write(client, 0x60 + task_shift, vals[i].xpsc);
+       /* accumulation length */
+       saa717x_write(client, 0x61 + task_shift, vals[i].xacl);
+       /* level control */
+       saa717x_write(client, 0x62 + task_shift,
+                       (vals[i].xc2_1 << 3) | vals[i].xdcg);
+       /*FIR prefilter control */
+       saa717x_write(client, 0x63 + task_shift,
+                       (vals[i].vpfy << 2) | vals[i].vpfy);
+}
+
+/********** scaling staff ***********/
+static void set_v_scale(struct i2c_client *client, int task, int yscale)
+{
+       int task_shift;
+
+       task_shift = task * 0x40;
+       /* Vertical scaling ratio (LOW) */
+       saa717x_write(client, 0x70 + task_shift, yscale & 0xff);
+       /* Vertical scaling ratio (HI) */
+       saa717x_write(client, 0x71 + task_shift, yscale >> 8);
+}
+
+static int saa717x_set_audio_clock_freq(struct i2c_client *client, u32 freq)
+{
+       /* not yet implament, so saa717x_cfg_??hz_??_audio is not defined. */
+       return 0;
+}
+
+static int saa717x_set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
+{
+       struct saa717x_state *state = i2c_get_clientdata(client);
+
+       switch (ctrl->id) {
+       case V4L2_CID_BRIGHTNESS:
+               if (ctrl->value < 0 || ctrl->value > 255) {
+                       v4l_err(client, "invalid brightness setting %d\n", ctrl->value);
+                       return -ERANGE;
+               }
+
+               state->bright = ctrl->value;
+               v4l_dbg(1, debug, client, "bright:%d\n", state->bright);
+               saa717x_write(client, 0x10a, state->bright);
+               break;
+
+       case V4L2_CID_CONTRAST:
+               if (ctrl->value < 0 || ctrl->value > 127) {
+                       v4l_err(client, "invalid contrast setting %d\n", ctrl->value);
+                       return -ERANGE;
+               }
+
+               state->contrast = ctrl->value;
+               v4l_dbg(1, debug, client, "contrast:%d\n", state->contrast);
+               saa717x_write(client, 0x10b, state->contrast);
+               break;
+
+       case V4L2_CID_SATURATION:
+               if (ctrl->value < 0 || ctrl->value > 127) {
+                       v4l_err(client, "invalid saturation setting %d\n", ctrl->value);
+                       return -ERANGE;
+               }
+
+               state->sat = ctrl->value;
+               v4l_dbg(1, debug, client, "sat:%d\n", state->sat);
+               saa717x_write(client, 0x10c, state->sat);
+               break;
+
+       case V4L2_CID_HUE:
+               if (ctrl->value < -127 || ctrl->value > 127) {
+                       v4l_err(client, "invalid hue setting %d\n", ctrl->value);
+                       return -ERANGE;
+               }
+
+               state->hue = ctrl->value;
+               v4l_dbg(1, debug, client, "hue:%d\n", state->hue);
+               saa717x_write(client, 0x10d, state->hue);
+               break;
+
+       case V4L2_CID_AUDIO_MUTE:
+               state->audio_main_mute = ctrl->value;
+               set_audio_regs(client, state);
+               break;
+
+       case V4L2_CID_AUDIO_VOLUME:
+               state->audio_main_volume = ctrl->value;
+               set_audio_regs(client, state);
+               break;
+
+       case V4L2_CID_AUDIO_BALANCE:
+               state->audio_main_balance = ctrl->value;
+               set_audio_regs(client, state);
+               break;
+
+       case V4L2_CID_AUDIO_TREBLE:
+               state->audio_main_treble = ctrl->value;
+               set_audio_regs(client, state);
+               break;
+
+       case V4L2_CID_AUDIO_BASS:
+               state->audio_main_bass = ctrl->value;
+               set_audio_regs(client, state);
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int saa717x_get_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
+{
+       struct saa717x_state *state = i2c_get_clientdata(client);
+
+       switch (ctrl->id) {
+       case V4L2_CID_BRIGHTNESS:
+               ctrl->value = state->bright;
+               break;
+
+       case V4L2_CID_CONTRAST:
+               ctrl->value = state->contrast;
+               break;
+
+       case V4L2_CID_SATURATION:
+               ctrl->value = state->sat;
+               break;
+
+       case V4L2_CID_HUE:
+               ctrl->value = state->hue;
+               break;
+
+       case V4L2_CID_AUDIO_MUTE:
+               ctrl->value = state->audio_main_mute;
+               break;
+
+       case V4L2_CID_AUDIO_VOLUME:
+               ctrl->value = state->audio_main_volume;
+               break;
+
+       case V4L2_CID_AUDIO_BALANCE:
+               ctrl->value = state->audio_main_balance;
+               break;
+
+       case V4L2_CID_AUDIO_TREBLE:
+               ctrl->value = state->audio_main_treble;
+               break;
+
+       case V4L2_CID_AUDIO_BASS:
+               ctrl->value = state->audio_main_bass;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static struct v4l2_queryctrl saa717x_qctrl[] = {
+       {
+               .id            = V4L2_CID_BRIGHTNESS,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+               .name          = "Brightness",
+               .minimum       = 0,
+               .maximum       = 255,
+               .step          = 1,
+               .default_value = 128,
+               .flags         = 0,
+       }, {
+               .id            = V4L2_CID_CONTRAST,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+               .name          = "Contrast",
+               .minimum       = 0,
+               .maximum       = 255,
+               .step          = 1,
+               .default_value = 64,
+               .flags         = 0,
+       }, {
+               .id            = V4L2_CID_SATURATION,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+               .name          = "Saturation",
+               .minimum       = 0,
+               .maximum       = 255,
+               .step          = 1,
+               .default_value = 64,
+               .flags         = 0,
+       }, {
+               .id            = V4L2_CID_HUE,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+               .name          = "Hue",
+               .minimum       = -128,
+               .maximum       = 127,
+               .step          = 1,
+               .default_value = 0,
+               .flags         = 0,
+       }, {
+               .id            = V4L2_CID_AUDIO_VOLUME,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+               .name          = "Volume",
+               .minimum       = 0,
+               .maximum       = 65535,
+               .step          = 65535 / 100,
+               .default_value = 58880,
+               .flags         = 0,
+       }, {
+               .id            = V4L2_CID_AUDIO_BALANCE,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+               .name          = "Balance",
+               .minimum       = 0,
+               .maximum       = 65535,
+               .step          = 65535 / 100,
+               .default_value = 32768,
+               .flags         = 0,
+       }, {
+               .id            = V4L2_CID_AUDIO_MUTE,
+               .type          = V4L2_CTRL_TYPE_BOOLEAN,
+               .name          = "Mute",
+               .minimum       = 0,
+               .maximum       = 1,
+               .step          = 1,
+               .default_value = 1,
+               .flags         = 0,
+       }, {
+               .id            = V4L2_CID_AUDIO_BASS,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+               .name          = "Bass",
+               .minimum       = 0,
+               .maximum       = 65535,
+               .step          = 65535 / 100,
+               .default_value = 32768,
+       }, {
+               .id            = V4L2_CID_AUDIO_TREBLE,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+               .name          = "Treble",
+               .minimum       = 0,
+               .maximum       = 65535,
+               .step          = 65535 / 100,
+               .default_value = 32768,
+       },
+};
+
+static int saa717x_set_video_input(struct i2c_client *client, struct saa717x_state *decoder, int inp)
+{
+       int is_tuner = inp & 0x80;  /* tuner input flag */
+
+       inp &= 0x7f;
+
+       v4l_dbg(1, debug, client, "decoder set input (%d)\n", inp);
+       /* inputs from 0-9 are available*/
+       /* saa717x have mode0-mode9 but mode5 is reserved. */
+       if (inp < 0 || inp > 9 || inp == 5)
+               return -EINVAL;
+
+       if (decoder->input != inp) {
+               int input_line = inp;
+
+               decoder->input = input_line;
+               v4l_dbg(1, debug, client,  "now setting %s input %d\n",
+                               input_line >= 6 ? "S-Video" : "Composite",
+                               input_line);
+
+               /* select mode */
+               saa717x_write(client, 0x102,
+                               (saa717x_read(client, 0x102) & 0xf0) |
+                               input_line);
+
+               /* bypass chrominance trap for modes 6..9 */
+               saa717x_write(client, 0x109,
+                               (saa717x_read(client, 0x109) & 0x7f) |
+                               (input_line < 6 ? 0x0 : 0x80));
+
+               /* change audio_mode */
+               if (is_tuner) {
+                       /* tuner */
+                       set_audio_mode(client, decoder->tuner_audio_mode);
+               } else {
+                       /* Force to STEREO mode if Composite or
+                        * S-Video were chosen */
+                       set_audio_mode(client, TUNER_AUDIO_STEREO);
+               }
+               /* change initialize procedure (Composite/S-Video) */
+               if (is_tuner)
+                       saa717x_write_regs(client, reg_init_tuner_input);
+               else if (input_line >= 6)
+                       saa717x_write_regs(client, reg_init_svideo_input);
+               else
+                       saa717x_write_regs(client, reg_init_composite_input);
+       }
+
+       return 0;
+}
+
+static int saa717x_command(struct i2c_client *client, unsigned cmd, void *arg)
+{
+       struct saa717x_state *decoder = i2c_get_clientdata(client);
+
+       v4l_dbg(1, debug, client, "IOCTL: %08x\n", cmd);
+
+       switch (cmd) {
+       case VIDIOC_INT_AUDIO_CLOCK_FREQ:
+               return saa717x_set_audio_clock_freq(client, *(u32 *)arg);
+
+       case VIDIOC_G_CTRL:
+               return saa717x_get_v4lctrl(client, (struct v4l2_control *)arg);
+
+       case VIDIOC_S_CTRL:
+               return saa717x_set_v4lctrl(client, (struct v4l2_control *)arg);
+
+       case VIDIOC_QUERYCTRL: {
+               struct v4l2_queryctrl *qc = arg;
+               int i;
+
+               for (i = 0; i < ARRAY_SIZE(saa717x_qctrl); i++)
+                       if (qc->id && qc->id == saa717x_qctrl[i].id) {
+                               memcpy(qc, &saa717x_qctrl[i], sizeof(*qc));
+                               return 0;
+                       }
+               return -EINVAL;
+       }
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       case VIDIOC_DBG_G_REGISTER: {
+               struct v4l2_register *reg = arg;
+
+               if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip))
+                       return -EINVAL;
+               if (!capable(CAP_SYS_ADMIN))
+                       return -EPERM;
+               reg->val = saa717x_read(client, reg->reg);
+               break;
+       }
+
+       case VIDIOC_DBG_S_REGISTER: {
+               struct v4l2_register *reg = arg;
+               u16 addr = reg->reg & 0xffff;
+               u8 val = reg->val & 0xff;
+
+               if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip))
+                       return -EINVAL;
+               if (!capable(CAP_SYS_ADMIN))
+                       return -EPERM;
+               saa717x_write(client, addr, val);
+               break;
+       }
+#endif
+
+       case VIDIOC_S_FMT: {
+               struct v4l2_format *fmt = (struct v4l2_format *)arg;
+               struct v4l2_pix_format *pix;
+               int prescale, h_scale, v_scale;
+
+               pix = &fmt->fmt.pix;
+               v4l_dbg(1, debug, client, "decoder set size\n");
+
+               /* FIXME need better bounds checking here */
+               if (pix->width < 1 || pix->width > 1440)
+                       return -EINVAL;
+               if (pix->height < 1 || pix->height > 960)
+                       return -EINVAL;
+
+               /* scaling setting */
+               /* NTSC and interlace only */
+               prescale = SAA717X_NTSC_WIDTH / pix->width;
+               if (prescale == 0)
+                       prescale = 1;
+               h_scale = 1024 * SAA717X_NTSC_WIDTH / prescale / pix->width;
+               /* interlace */
+               v_scale = 512 * 2 * SAA717X_NTSC_HEIGHT / pix->height;
+
+               /* Horizontal prescaling etc */
+               set_h_prescale(client, 0, prescale);
+               set_h_prescale(client, 1, prescale);
+
+               /* Horizontal scaling increment */
+               /* TASK A */
+               saa717x_write(client, 0x6C, (u8)(h_scale & 0xFF));
+               saa717x_write(client, 0x6D, (u8)((h_scale >> 8) & 0xFF));
+               /* TASK B */
+               saa717x_write(client, 0xAC, (u8)(h_scale & 0xFF));
+               saa717x_write(client, 0xAD, (u8)((h_scale >> 8) & 0xFF));
+
+               /* Vertical prescaling etc */
+               set_v_scale(client, 0, v_scale);
+               set_v_scale(client, 1, v_scale);
+
+               /* set video output size */
+               /* video number of pixels at output */
+               /* TASK A */
+               saa717x_write(client, 0x5C, (u8)(pix->width & 0xFF));
+               saa717x_write(client, 0x5D, (u8)((pix->width >> 8) & 0xFF));
+               /* TASK B */
+               saa717x_write(client, 0x9C, (u8)(pix->width & 0xFF));
+               saa717x_write(client, 0x9D, (u8)((pix->width >> 8) & 0xFF));
+
+               /* video number of lines at output */
+               /* TASK A */
+               saa717x_write(client, 0x5E, (u8)(pix->height & 0xFF));
+               saa717x_write(client, 0x5F, (u8)((pix->height >> 8) & 0xFF));
+               /* TASK B */
+               saa717x_write(client, 0x9E, (u8)(pix->height & 0xFF));
+               saa717x_write(client, 0x9F, (u8)((pix->height >> 8) & 0xFF));
+               break;
+       }
+
+       case AUDC_SET_RADIO:
+               decoder->radio = 1;
+               break;
+
+       case VIDIOC_S_STD: {
+               v4l2_std_id std = *(v4l2_std_id *) arg;
+
+               v4l_dbg(1, debug, client, "decoder set norm ");
+               v4l_dbg(1, debug, client, "(not yet implementd)\n");
+
+               decoder->radio = 0;
+               decoder->std = std;
+               break;
+       }
+
+       case VIDIOC_INT_G_AUDIO_ROUTING: {
+               struct v4l2_routing *route = arg;
+
+               route->input = decoder->audio_input;
+               route->output = 0;
+               break;
+       }
+
+       case VIDIOC_INT_S_AUDIO_ROUTING: {
+               struct v4l2_routing *route = arg;
+
+               if (route->input < 3) { /* FIXME! --tadachi */
+                       decoder->audio_input = route->input;
+                       v4l_dbg(1, debug, client,
+                               "set decoder audio input to %d\n",
+                               decoder->audio_input);
+                       set_audio_regs(client, decoder);
+                       break;
+               }
+               return -ERANGE;
+       }
+
+       case VIDIOC_INT_S_VIDEO_ROUTING: {
+               struct v4l2_routing *route = arg;
+               int inp = route->input;
+
+               return saa717x_set_video_input(client, decoder, inp);
+       }
+
+       case VIDIOC_STREAMON: {
+               v4l_dbg(1, debug, client, "decoder enable output\n");
+               decoder->enable = 1;
+               saa717x_write(client, 0x193, 0xa6);
+               break;
+       }
+
+       case VIDIOC_STREAMOFF: {
+               v4l_dbg(1, debug, client, "decoder disable output\n");
+               decoder->enable = 0;
+               saa717x_write(client, 0x193, 0x26); /* right? FIXME!--tadachi */
+               break;
+       }
+
+               /* change audio mode */
+       case VIDIOC_S_TUNER: {
+               struct v4l2_tuner *vt = (struct v4l2_tuner *)arg;
+               int audio_mode;
+               char *mes[4] = {
+                       "MONO", "STEREO", "LANG1", "LANG2/SAP"
+               };
+
+               audio_mode = V4L2_TUNER_MODE_STEREO;
+
+               switch (vt->audmode) {
+               case V4L2_TUNER_MODE_MONO:
+                       audio_mode = TUNER_AUDIO_MONO;
+                       break;
+               case V4L2_TUNER_MODE_STEREO:
+                       audio_mode = TUNER_AUDIO_STEREO;
+                       break;
+               case V4L2_TUNER_MODE_LANG2:
+                       audio_mode = TUNER_AUDIO_LANG2;
+                       break;
+               case V4L2_TUNER_MODE_LANG1:
+                       audio_mode = TUNER_AUDIO_LANG1;
+                       break;
+               }
+
+               v4l_dbg(1, debug, client, "change audio mode to %s\n",
+                               mes[audio_mode]);
+               decoder->tuner_audio_mode = audio_mode;
+               /* The registers are not changed here. */
+               /* See DECODER_ENABLE_OUTPUT section. */
+               set_audio_mode(client, decoder->tuner_audio_mode);
+               break;
+       }
+
+       case VIDIOC_G_TUNER: {
+               struct v4l2_tuner *vt = (struct v4l2_tuner *)arg;
+               int dual_f, stereo_f;
+
+               if (decoder->radio)
+                       break;
+               get_inf_dev_status(client, &dual_f, &stereo_f);
+
+               v4l_dbg(1, debug, client, "DETECT==st:%d dual:%d\n",
+                               stereo_f, dual_f);
+
+               /* mono */
+               if ((dual_f == 0) && (stereo_f == 0)) {
+                       vt->rxsubchans = V4L2_TUNER_SUB_MONO;
+                       v4l_dbg(1, debug, client, "DETECT==MONO\n");
+               }
+
+               /* stereo */
+               if (stereo_f == 1) {
+                       if (vt->audmode == V4L2_TUNER_MODE_STEREO ||
+                           vt->audmode == V4L2_TUNER_MODE_LANG1) {
+                               vt->rxsubchans = V4L2_TUNER_SUB_STEREO;
+                               v4l_dbg(1, debug, client, "DETECT==ST(ST)\n");
+                       } else {
+                               vt->rxsubchans = V4L2_TUNER_SUB_MONO;
+                               v4l_dbg(1, debug, client, "DETECT==ST(MONO)\n");
+                       }
+               }
+
+               /* dual */
+               if (dual_f == 1) {
+                       if (vt->audmode == V4L2_TUNER_MODE_LANG2) {
+                               vt->rxsubchans = V4L2_TUNER_SUB_LANG2 | V4L2_TUNER_SUB_MONO;
+                               v4l_dbg(1, debug, client, "DETECT==DUAL1\n");
+                       } else {
+                               vt->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_MONO;
+                               v4l_dbg(1, debug, client, "DETECT==DUAL2\n");
+                       }
+               }
+               break;
+       }
+
+       case VIDIOC_LOG_STATUS:
+               /* not yet implemented */
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+
+/* i2c implementation */
+
+/* ----------------------------------------------------------------------- */
+static int saa717x_probe(struct i2c_client *client)
+{
+       struct saa717x_state *decoder;
+       u8 id = 0;
+       char *p = "";
+
+       /* Check if the adapter supports the needed features */
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+               return -EIO;
+
+       snprintf(client->name, sizeof(client->name) - 1, "saa717x");
+
+       if (saa717x_write(client, 0x5a4, 0xfe) &&
+                       saa717x_write(client, 0x5a5, 0x0f) &&
+                       saa717x_write(client, 0x5a6, 0x00) &&
+                       saa717x_write(client, 0x5a7, 0x01))
+               id = saa717x_read(client, 0x5a0);
+       if (id != 0xc2 && id != 0x32 && id != 0xf2 && id != 0x6c) {
+               v4l_dbg(1, debug, client, "saa717x not found (id=%02x)\n", id);
+               return -ENODEV;
+       }
+       if (id == 0xc2)
+               p = "saa7173";
+       else if (id == 0x32)
+               p = "saa7174A";
+       else if (id == 0x6c)
+               p = "saa7174HL";
+       else
+               p = "saa7171";
+       v4l_info(client, "%s found @ 0x%x (%s)\n", p,
+                       client->addr << 1, client->adapter->name);
+
+       decoder = kzalloc(sizeof(struct saa717x_state), GFP_KERNEL);
+       i2c_set_clientdata(client, decoder);
+
+       if (decoder == NULL)
+               return -ENOMEM;
+       decoder->std = V4L2_STD_NTSC;
+       decoder->input = -1;
+       decoder->enable = 1;
+
+       /* tune these parameters */
+       decoder->bright = 0x80;
+       decoder->contrast = 0x44;
+       decoder->sat = 0x40;
+       decoder->hue = 0x00;
+
+       /* FIXME!! */
+       decoder->playback = 0;  /* initially capture mode used */
+       decoder->audio = 1; /* DECODER_AUDIO_48_KHZ */
+
+       decoder->audio_input = 2; /* FIXME!! */
+
+       decoder->tuner_audio_mode = TUNER_AUDIO_STEREO;
+       /* set volume, bass and treble */
+       decoder->audio_main_vol_l = 6;
+       decoder->audio_main_vol_r = 6;
+       decoder->audio_main_bass = 0;
+       decoder->audio_main_treble = 0;
+       decoder->audio_main_mute = 0;
+       decoder->audio_main_balance = 32768;
+       /* normalize (24 to -40 (not -84) -> 65535 to 0) */
+       decoder->audio_main_volume =
+               (decoder->audio_main_vol_r + 41) * 65535 / (24 - (-40));
+
+       v4l_dbg(1, debug, client, "writing init values\n");
+
+       /* FIXME!! */
+       saa717x_write_regs(client, reg_init_initialize);
+       set_video_output_level_regs(client, decoder);
+       /* set bass,treble to 0db 20041101 K.Ohta */
+       decoder->audio_main_bass = 0;
+       decoder->audio_main_treble = 0;
+       set_audio_regs(client, decoder);
+
+       set_current_state(TASK_INTERRUPTIBLE);
+       schedule_timeout(2*HZ);
+       return 0;
+}
+
+static int saa717x_remove(struct i2c_client *client)
+{
+       kfree(i2c_get_clientdata(client));
+       return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
+       .name = "saa717x",
+       .driverid = I2C_DRIVERID_SAA717X,
+       .command = saa717x_command,
+       .probe = saa717x_probe,
+       .remove = saa717x_remove,
+       .legacy_class = I2C_CLASS_TV_ANALOG | I2C_CLASS_TV_DIGITAL,
+};
index 41f70440fd3bcb2b842720680d4d42a3b97476a9..02fda4eecea3269080eb14c5cd36d20d22df5803 100644 (file)
@@ -52,7 +52,7 @@ MODULE_LICENSE("GPL");
 #define I2C_NAME(s) (s)->name
 
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0-1)");
 
index d5d7d6cf734aba40ca0c224051a206bd52fd1b4a..1cd629380f7183c94882fca69c1f4a4e85c67784 100644 (file)
@@ -35,7 +35,7 @@ static const char version[] = "0.24";
 #include <linux/usb.h>
 #include "se401.h"
 
-static int flickerless=0;
+static int flickerless;
 static int video_nr = -1;
 
 static struct usb_device_id device_table [] = {
@@ -300,10 +300,10 @@ static void se401_button_irq(struct urb *urb)
        case -ENOENT:
        case -ESHUTDOWN:
                /* this urb is terminated, clean up */
-               dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+               dbg("%s - urb shutting down with status: %d", __func__, urb->status);
                return;
        default:
-               dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+               dbg("%s - nonzero urb status received: %d", __func__, urb->status);
                goto exit;
        }
 
@@ -315,7 +315,7 @@ exit:
        status = usb_submit_urb (urb, GFP_ATOMIC);
        if (status)
                err ("%s - usb_submit_urb failed with result %d",
-                    __FUNCTION__, status);
+                    __func__, status);
 }
 
 static void se401_video_irq(struct urb *urb)
@@ -1224,7 +1224,9 @@ static const struct file_operations se401_fops = {
        .read =         se401_read,
        .mmap =         se401_mmap,
        .ioctl =        se401_ioctl,
+#ifdef CONFIG_COMPAT
        .compat_ioctl = v4l_compat_ioctl32,
+#endif
        .llseek =       no_llseek,
 };
 static struct video_device se401_template = {
@@ -1279,7 +1281,7 @@ static int se401_init(struct usb_se401 *se401, int button)
        rc=se401_sndctrl(0, se401, SE401_REQ_GET_HEIGHT, 0, cp, sizeof(cp));
        se401->cheight=cp[0]+cp[1]*256;
 
-       if (!cp[2] && SE401_FORMAT_BAYER) {
+       if (!(cp[2] & SE401_FORMAT_BAYER)) {
                err("Bayer format not supported!");
                return 1;
        }
index 2e3c3de793a72a2161a2bf1c0ca69fd8c3b91b7c..0c8d87d8d18dd0b7e3b60b1b530942f944bfef96 100644 (file)
@@ -176,7 +176,7 @@ do {                                                                          \
                        dev_info(&cam->usbdev->dev, fmt "\n", ## args);       \
                else if ((level) >= 3)                                        \
                        dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n",      \
-                                __FUNCTION__, __LINE__ , ## args);           \
+                                __func__, __LINE__ , ## args);           \
        }                                                                     \
 } while (0)
 #      define V4LDBG(level, name, cmd)                                       \
@@ -191,7 +191,7 @@ do {                                                                          \
                        pr_info("sn9c102: " fmt "\n", ## args);               \
                else if ((level) == 3)                                        \
                        pr_debug("sn9c102: [%s:%d] " fmt "\n",                \
-                                __FUNCTION__, __LINE__ , ## args);           \
+                                __func__, __LINE__ , ## args);           \
        }                                                                     \
 } while (0)
 #else
@@ -202,7 +202,7 @@ do {                                                                          \
 
 #undef PDBG
 #define PDBG(fmt, args...)                                                    \
-dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __FUNCTION__,   \
+dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __func__,   \
         __LINE__ , ## args)
 
 #undef PDBGG
index c40ba3adab21ccc24ff8ab27a3f6ffeef1bb04a1..5748b1e1a128aacdff1abfbdc756d1c6048963a3 100644 (file)
@@ -464,9 +464,9 @@ sn9c102_i2c_try_read(struct sn9c102_device* cam,
 }
 
 
-int
-sn9c102_i2c_try_write(struct sn9c102_device* cam,
-                     const struct sn9c102_sensor* sensor, u8 address, u8 value)
+static int sn9c102_i2c_try_write(struct sn9c102_device* cam,
+                                const struct sn9c102_sensor* sensor,
+                                u8 address, u8 value)
 {
        return sn9c102_i2c_try_raw_write(cam, sensor, 3,
                                         sensor->i2c_slave_id, address,
@@ -528,7 +528,7 @@ sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len)
 
                /* Search for the SOF marker (fixed part) in the header */
                for (j = 0, b=cam->sof.bytesread; j+b < sizeof(marker); j++) {
-                       if (unlikely(i+j) == len)
+                       if (unlikely(i+j == len))
                                return NULL;
                        if (*(m+i+j) == marker[cam->sof.bytesread]) {
                                cam->sof.header[cam->sof.bytesread] = *(m+i+j);
@@ -3224,7 +3224,9 @@ static const struct file_operations sn9c102_fops = {
        .open = sn9c102_open,
        .release = sn9c102_release,
        .ioctl = sn9c102_ioctl,
+#ifdef CONFIG_COMPAT
        .compat_ioctl = v4l_compat_ioctl32,
+#endif
        .read = sn9c102_read,
        .poll = sn9c102_poll,
        .mmap = sn9c102_mmap,
@@ -3239,7 +3241,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
 {
        struct usb_device *udev = interface_to_usbdev(intf);
        struct sn9c102_device* cam;
-       static unsigned int dev_nr = 0;
+       static unsigned int dev_nr;
        unsigned int i;
        int err = 0, r;
 
index 2dc7c68694840cb006cd99a39c60d54e989a8e51..4af7382da5c523d93ab61dcb57868ffbb7098daf 100644 (file)
@@ -85,9 +85,6 @@ sn9c102_attach_sensor(struct sn9c102_device* cam,
 */
 
 /* The "try" I2C I/O versions are used when probing the sensor */
-extern int sn9c102_i2c_try_write(struct sn9c102_device*,
-                                const struct sn9c102_sensor*, u8 address,
-                                u8 value);
 extern int sn9c102_i2c_try_read(struct sn9c102_device*,
                                const struct sn9c102_sensor*, u8 address);
 
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c
new file mode 100644 (file)
index 0000000..a1b9244
--- /dev/null
@@ -0,0 +1,1031 @@
+/*
+ * camera image capture (abstract) bus driver
+ *
+ * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
+ *
+ * This driver provides an interface between platform-specific camera
+ * busses and camera devices. It should be used if the camera is
+ * connected not over a "proper" bus like PCI or USB, but over a
+ * special bus, like, for example, the Quick Capture interface on PXA270
+ * SoCs. Later it should also be used for i.MX31 SoCs from Freescale.
+ * It can handle multiple cameras and / or multiple busses, which can
+ * be used, e.g., in stereo-vision applications.
+ *
+ * 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/list.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/vmalloc.h>
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-dev.h>
+#include <media/soc_camera.h>
+
+static LIST_HEAD(hosts);
+static LIST_HEAD(devices);
+static DEFINE_MUTEX(list_lock);
+static DEFINE_MUTEX(video_lock);
+
+const static struct soc_camera_data_format*
+format_by_fourcc(struct soc_camera_device *icd, unsigned int fourcc)
+{
+       unsigned int i;
+
+       for (i = 0; i < icd->num_formats; i++)
+               if (icd->formats[i].fourcc == fourcc)
+                       return icd->formats + i;
+       return NULL;
+}
+
+static int soc_camera_try_fmt_cap(struct file *file, void *priv,
+                                 struct v4l2_format *f)
+{
+       struct soc_camera_file *icf = file->private_data;
+       struct soc_camera_device *icd = icf->icd;
+       struct soc_camera_host *ici =
+               to_soc_camera_host(icd->dev.parent);
+       enum v4l2_field field;
+       const struct soc_camera_data_format *fmt;
+       int ret;
+
+       WARN_ON(priv != file->private_data);
+
+       fmt = format_by_fourcc(icd, f->fmt.pix.pixelformat);
+       if (!fmt) {
+               dev_dbg(&icd->dev, "invalid format 0x%08x\n",
+                       f->fmt.pix.pixelformat);
+               return -EINVAL;
+       }
+
+       dev_dbg(&icd->dev, "fmt: 0x%08x\n", fmt->fourcc);
+
+       field = f->fmt.pix.field;
+
+       if (field == V4L2_FIELD_ANY) {
+               field = V4L2_FIELD_NONE;
+       } else if (V4L2_FIELD_NONE != field) {
+               dev_err(&icd->dev, "Field type invalid.\n");
+               return -EINVAL;
+       }
+
+       /* test physical bus parameters */
+       ret = ici->ops->try_bus_param(icd, f->fmt.pix.pixelformat);
+       if (ret)
+               return ret;
+
+       /* limit format to hardware capabilities */
+       ret = ici->ops->try_fmt_cap(icd, f);
+
+       /* calculate missing fields */
+       f->fmt.pix.field = field;
+       f->fmt.pix.bytesperline =
+               (f->fmt.pix.width * fmt->depth) >> 3;
+       f->fmt.pix.sizeimage =
+               f->fmt.pix.height * f->fmt.pix.bytesperline;
+
+       return ret;
+}
+
+static int soc_camera_enum_input(struct file *file, void *priv,
+                                struct v4l2_input *inp)
+{
+       if (inp->index != 0)
+               return -EINVAL;
+
+       inp->type = V4L2_INPUT_TYPE_CAMERA;
+       inp->std = V4L2_STD_UNKNOWN;
+       strcpy(inp->name, "Camera");
+
+       return 0;
+}
+
+static int soc_camera_g_input(struct file *file, void *priv, unsigned int *i)
+{
+       *i = 0;
+
+       return 0;
+}
+
+static int soc_camera_s_input(struct file *file, void *priv, unsigned int i)
+{
+       if (i > 0)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int soc_camera_s_std(struct file *file, void *priv, v4l2_std_id *a)
+{
+       return 0;
+}
+
+static int soc_camera_reqbufs(struct file *file, void *priv,
+                             struct v4l2_requestbuffers *p)
+{
+       int ret;
+       struct soc_camera_file *icf = file->private_data;
+       struct soc_camera_device *icd = icf->icd;
+       struct soc_camera_host *ici =
+               to_soc_camera_host(icd->dev.parent);
+
+       WARN_ON(priv != file->private_data);
+
+       dev_dbg(&icd->dev, "%s: %d\n", __func__, p->memory);
+
+       ret = videobuf_reqbufs(&icf->vb_vidq, p);
+       if (ret < 0)
+               return ret;
+
+       return ici->ops->reqbufs(icf, p);
+}
+
+static int soc_camera_querybuf(struct file *file, void *priv,
+                              struct v4l2_buffer *p)
+{
+       struct soc_camera_file *icf = file->private_data;
+
+       WARN_ON(priv != file->private_data);
+
+       return videobuf_querybuf(&icf->vb_vidq, p);
+}
+
+static int soc_camera_qbuf(struct file *file, void *priv,
+                          struct v4l2_buffer *p)
+{
+       struct soc_camera_file *icf = file->private_data;
+
+       WARN_ON(priv != file->private_data);
+
+       return videobuf_qbuf(&icf->vb_vidq, p);
+}
+
+static int soc_camera_dqbuf(struct file *file, void *priv,
+                           struct v4l2_buffer *p)
+{
+       struct soc_camera_file *icf = file->private_data;
+
+       WARN_ON(priv != file->private_data);
+
+       return videobuf_dqbuf(&icf->vb_vidq, p, file->f_flags & O_NONBLOCK);
+}
+
+static int soc_camera_open(struct inode *inode, struct file *file)
+{
+       struct video_device *vdev;
+       struct soc_camera_device *icd;
+       struct soc_camera_host *ici;
+       struct soc_camera_file *icf;
+       spinlock_t *lock;
+       int ret;
+
+       icf = vmalloc(sizeof(*icf));
+       if (!icf)
+               return -ENOMEM;
+
+       /* Protect against icd->remove() until we module_get() both drivers. */
+       mutex_lock(&video_lock);
+
+       vdev = video_devdata(file);
+       icd = container_of(vdev->dev, struct soc_camera_device, dev);
+       ici = to_soc_camera_host(icd->dev.parent);
+
+       if (!try_module_get(icd->ops->owner)) {
+               dev_err(&icd->dev, "Couldn't lock sensor driver.\n");
+               ret = -EINVAL;
+               goto emgd;
+       }
+
+       if (!try_module_get(ici->ops->owner)) {
+               dev_err(&icd->dev, "Couldn't lock capture bus driver.\n");
+               ret = -EINVAL;
+               goto emgi;
+       }
+
+       icf->icd = icd;
+
+       icf->lock = ici->ops->spinlock_alloc(icf);
+       if (!icf->lock) {
+               ret = -ENOMEM;
+               goto esla;
+       }
+
+       icd->use_count++;
+
+       /* Now we really have to activate the camera */
+       if (icd->use_count == 1) {
+               ret = ici->ops->add(icd);
+               if (ret < 0) {
+                       dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret);
+                       icd->use_count--;
+                       goto eiciadd;
+               }
+       }
+
+       mutex_unlock(&video_lock);
+
+       file->private_data = icf;
+       dev_dbg(&icd->dev, "camera device open\n");
+
+       /* We must pass NULL as dev pointer, then all pci_* dma operations
+        * transform to normal dma_* ones. */
+       videobuf_queue_sg_init(&icf->vb_vidq, ici->vbq_ops, NULL, icf->lock,
+                               V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE,
+                               ici->msize, icd);
+
+       return 0;
+
+       /* All errors are entered with the video_lock held */
+eiciadd:
+       lock = icf->lock;
+       icf->lock = NULL;
+       if (ici->ops->spinlock_free)
+               ici->ops->spinlock_free(lock);
+esla:
+       module_put(ici->ops->owner);
+emgi:
+       module_put(icd->ops->owner);
+emgd:
+       mutex_unlock(&video_lock);
+       vfree(icf);
+       return ret;
+}
+
+static int soc_camera_close(struct inode *inode, struct file *file)
+{
+       struct soc_camera_file *icf = file->private_data;
+       struct soc_camera_device *icd = icf->icd;
+       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct video_device *vdev = icd->vdev;
+       spinlock_t *lock = icf->lock;
+
+       mutex_lock(&video_lock);
+       icd->use_count--;
+       if (!icd->use_count)
+               ici->ops->remove(icd);
+       icf->lock = NULL;
+       if (ici->ops->spinlock_free)
+               ici->ops->spinlock_free(lock);
+       module_put(icd->ops->owner);
+       module_put(ici->ops->owner);
+       mutex_unlock(&video_lock);
+
+       vfree(icf);
+
+       dev_dbg(vdev->dev, "camera device close\n");
+
+       return 0;
+}
+
+static ssize_t soc_camera_read(struct file *file, char __user *buf,
+                          size_t count, loff_t *ppos)
+{
+       struct soc_camera_file *icf = file->private_data;
+       struct soc_camera_device *icd = icf->icd;
+       struct video_device *vdev = icd->vdev;
+       int err = -EINVAL;
+
+       dev_err(vdev->dev, "camera device read not implemented\n");
+
+       return err;
+}
+
+static int soc_camera_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct soc_camera_file *icf = file->private_data;
+       struct soc_camera_device *icd = icf->icd;
+       int err;
+
+       dev_dbg(&icd->dev, "mmap called, vma=0x%08lx\n", (unsigned long)vma);
+
+       err = videobuf_mmap_mapper(&icf->vb_vidq, vma);
+
+       dev_dbg(&icd->dev, "vma start=0x%08lx, size=%ld, ret=%d\n",
+               (unsigned long)vma->vm_start,
+               (unsigned long)vma->vm_end - (unsigned long)vma->vm_start,
+               err);
+
+       return err;
+}
+
+static unsigned int soc_camera_poll(struct file *file, poll_table *pt)
+{
+       struct soc_camera_file *icf = file->private_data;
+       struct soc_camera_device *icd = icf->icd;
+       struct soc_camera_host *ici =
+               to_soc_camera_host(icd->dev.parent);
+
+       if (list_empty(&icf->vb_vidq.stream)) {
+               dev_err(&icd->dev, "Trying to poll with no queued buffers!\n");
+               return POLLERR;
+       }
+
+       return ici->ops->poll(file, pt);
+}
+
+
+static struct file_operations soc_camera_fops = {
+       .owner          = THIS_MODULE,
+       .open           = soc_camera_open,
+       .release        = soc_camera_close,
+       .ioctl          = video_ioctl2,
+       .read           = soc_camera_read,
+       .mmap           = soc_camera_mmap,
+       .poll           = soc_camera_poll,
+       .llseek         = no_llseek,
+};
+
+
+static int soc_camera_s_fmt_cap(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       struct soc_camera_file *icf = file->private_data;
+       struct soc_camera_device *icd = icf->icd;
+       struct soc_camera_host *ici =
+               to_soc_camera_host(icd->dev.parent);
+       int ret;
+       struct v4l2_rect rect;
+       const static struct soc_camera_data_format *data_fmt;
+
+       WARN_ON(priv != file->private_data);
+
+       data_fmt = format_by_fourcc(icd, f->fmt.pix.pixelformat);
+       if (!data_fmt)
+               return -EINVAL;
+
+       /* buswidth may be further adjusted by the ici */
+       icd->buswidth = data_fmt->depth;
+
+       ret = soc_camera_try_fmt_cap(file, icf, f);
+       if (ret < 0)
+               return ret;
+
+       rect.left       = icd->x_current;
+       rect.top        = icd->y_current;
+       rect.width      = f->fmt.pix.width;
+       rect.height     = f->fmt.pix.height;
+       ret = ici->ops->set_fmt_cap(icd, f->fmt.pix.pixelformat, &rect);
+       if (ret < 0)
+               return ret;
+
+       icd->current_fmt        = data_fmt;
+       icd->width              = rect.width;
+       icd->height             = rect.height;
+       icf->vb_vidq.field      = f->fmt.pix.field;
+       if (V4L2_BUF_TYPE_VIDEO_CAPTURE != f->type)
+               dev_warn(&icd->dev, "Attention! Wrong buf-type %d\n",
+                        f->type);
+
+       dev_dbg(&icd->dev, "set width: %d height: %d\n",
+               icd->width, icd->height);
+
+       /* set physical bus parameters */
+       return ici->ops->set_bus_param(icd, f->fmt.pix.pixelformat);
+}
+
+static int soc_camera_enum_fmt_cap(struct file *file, void  *priv,
+                                  struct v4l2_fmtdesc *f)
+{
+       struct soc_camera_file *icf = file->private_data;
+       struct soc_camera_device *icd = icf->icd;
+       const struct soc_camera_data_format *format;
+
+       WARN_ON(priv != file->private_data);
+
+       if (f->index >= icd->num_formats)
+               return -EINVAL;
+
+       format = &icd->formats[f->index];
+
+       strlcpy(f->description, format->name, sizeof(f->description));
+       f->pixelformat = format->fourcc;
+       return 0;
+}
+
+static int soc_camera_g_fmt_cap(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       struct soc_camera_file *icf = file->private_data;
+       struct soc_camera_device *icd = icf->icd;
+
+       WARN_ON(priv != file->private_data);
+
+       f->fmt.pix.width        = icd->width;
+       f->fmt.pix.height       = icd->height;
+       f->fmt.pix.field        = icf->vb_vidq.field;
+       f->fmt.pix.pixelformat  = icd->current_fmt->fourcc;
+       f->fmt.pix.bytesperline =
+               (f->fmt.pix.width * icd->current_fmt->depth) >> 3;
+       f->fmt.pix.sizeimage    =
+               f->fmt.pix.height * f->fmt.pix.bytesperline;
+       dev_dbg(&icd->dev, "current_fmt->fourcc: 0x%08x\n",
+               icd->current_fmt->fourcc);
+       return 0;
+}
+
+static int soc_camera_querycap(struct file *file, void  *priv,
+                              struct v4l2_capability *cap)
+{
+       struct soc_camera_file *icf = file->private_data;
+       struct soc_camera_device *icd = icf->icd;
+       struct soc_camera_host *ici =
+               to_soc_camera_host(icd->dev.parent);
+
+       WARN_ON(priv != file->private_data);
+
+       strlcpy(cap->driver, ici->drv_name, sizeof(cap->driver));
+       return ici->ops->querycap(ici, cap);
+}
+
+static int soc_camera_streamon(struct file *file, void *priv,
+                              enum v4l2_buf_type i)
+{
+       struct soc_camera_file *icf = file->private_data;
+       struct soc_camera_device *icd = icf->icd;
+
+       WARN_ON(priv != file->private_data);
+
+       dev_dbg(&icd->dev, "%s\n", __func__);
+
+       if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       icd->ops->start_capture(icd);
+
+       /* This calls buf_queue from host driver's videobuf_queue_ops */
+       return videobuf_streamon(&icf->vb_vidq);
+}
+
+static int soc_camera_streamoff(struct file *file, void *priv,
+                               enum v4l2_buf_type i)
+{
+       struct soc_camera_file *icf = file->private_data;
+       struct soc_camera_device *icd = icf->icd;
+
+       WARN_ON(priv != file->private_data);
+
+       dev_dbg(&icd->dev, "%s\n", __func__);
+
+       if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       /* This calls buf_release from host driver's videobuf_queue_ops for all
+        * remaining buffers. When the last buffer is freed, stop capture */
+       videobuf_streamoff(&icf->vb_vidq);
+
+       icd->ops->stop_capture(icd);
+
+       return 0;
+}
+
+static int soc_camera_queryctrl(struct file *file, void *priv,
+                               struct v4l2_queryctrl *qc)
+{
+       struct soc_camera_file *icf = file->private_data;
+       struct soc_camera_device *icd = icf->icd;
+       int i;
+
+       WARN_ON(priv != file->private_data);
+
+       if (!qc->id)
+               return -EINVAL;
+
+       for (i = 0; i < icd->ops->num_controls; i++)
+               if (qc->id == icd->ops->controls[i].id) {
+                       memcpy(qc, &(icd->ops->controls[i]),
+                               sizeof(*qc));
+                       return 0;
+               }
+
+       return -EINVAL;
+}
+
+static int soc_camera_g_ctrl(struct file *file, void *priv,
+                            struct v4l2_control *ctrl)
+{
+       struct soc_camera_file *icf = file->private_data;
+       struct soc_camera_device *icd = icf->icd;
+
+       WARN_ON(priv != file->private_data);
+
+       switch (ctrl->id) {
+       case V4L2_CID_GAIN:
+               if (icd->gain == (unsigned short)~0)
+                       return -EINVAL;
+               ctrl->value = icd->gain;
+               return 0;
+       case V4L2_CID_EXPOSURE:
+               if (icd->exposure == (unsigned short)~0)
+                       return -EINVAL;
+               ctrl->value = icd->exposure;
+               return 0;
+       }
+
+       if (icd->ops->get_control)
+               return icd->ops->get_control(icd, ctrl);
+       return -EINVAL;
+}
+
+static int soc_camera_s_ctrl(struct file *file, void *priv,
+                            struct v4l2_control *ctrl)
+{
+       struct soc_camera_file *icf = file->private_data;
+       struct soc_camera_device *icd = icf->icd;
+
+       WARN_ON(priv != file->private_data);
+
+       if (icd->ops->set_control)
+               return icd->ops->set_control(icd, ctrl);
+       return -EINVAL;
+}
+
+static int soc_camera_cropcap(struct file *file, void *fh,
+                             struct v4l2_cropcap *a)
+{
+       struct soc_camera_file *icf = file->private_data;
+       struct soc_camera_device *icd = icf->icd;
+
+       a->type                         = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       a->bounds.left                  = icd->x_min;
+       a->bounds.top                   = icd->y_min;
+       a->bounds.width                 = icd->width_max;
+       a->bounds.height                = icd->height_max;
+       a->defrect.left                 = icd->x_min;
+       a->defrect.top                  = icd->y_min;
+       a->defrect.width                = 640;
+       a->defrect.height               = 480;
+       a->pixelaspect.numerator        = 1;
+       a->pixelaspect.denominator      = 1;
+
+       return 0;
+}
+
+static int soc_camera_g_crop(struct file *file, void *fh,
+                            struct v4l2_crop *a)
+{
+       struct soc_camera_file *icf = file->private_data;
+       struct soc_camera_device *icd = icf->icd;
+
+       a->type         = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       a->c.left       = icd->x_current;
+       a->c.top        = icd->y_current;
+       a->c.width      = icd->width;
+       a->c.height     = icd->height;
+
+       return 0;
+}
+
+static int soc_camera_s_crop(struct file *file, void *fh,
+                            struct v4l2_crop *a)
+{
+       struct soc_camera_file *icf = file->private_data;
+       struct soc_camera_device *icd = icf->icd;
+       struct soc_camera_host *ici =
+               to_soc_camera_host(icd->dev.parent);
+       int ret;
+
+       if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       ret = ici->ops->set_fmt_cap(icd, 0, &a->c);
+       if (!ret) {
+               icd->width      = a->c.width;
+               icd->height     = a->c.height;
+               icd->x_current  = a->c.left;
+               icd->y_current  = a->c.top;
+       }
+
+       return ret;
+}
+
+static int soc_camera_g_chip_ident(struct file *file, void *fh,
+                                  struct v4l2_chip_ident *id)
+{
+       struct soc_camera_file *icf = file->private_data;
+       struct soc_camera_device *icd = icf->icd;
+
+       if (!icd->ops->get_chip_id)
+               return -EINVAL;
+
+       return icd->ops->get_chip_id(icd, id);
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int soc_camera_g_register(struct file *file, void *fh,
+                                struct v4l2_register *reg)
+{
+       struct soc_camera_file *icf = file->private_data;
+       struct soc_camera_device *icd = icf->icd;
+
+       if (!icd->ops->get_register)
+               return -EINVAL;
+
+       return icd->ops->get_register(icd, reg);
+}
+
+static int soc_camera_s_register(struct file *file, void *fh,
+                                struct v4l2_register *reg)
+{
+       struct soc_camera_file *icf = file->private_data;
+       struct soc_camera_device *icd = icf->icd;
+
+       if (!icd->ops->set_register)
+               return -EINVAL;
+
+       return icd->ops->set_register(icd, reg);
+}
+#endif
+
+static int device_register_link(struct soc_camera_device *icd)
+{
+       int ret = device_register(&icd->dev);
+
+       if (ret < 0) {
+               /* Prevent calling device_unregister() */
+               icd->dev.parent = NULL;
+               dev_err(&icd->dev, "Cannot register device: %d\n", ret);
+       /* Even if probe() was unsuccessful for all registered drivers,
+        * device_register() returns 0, and we add the link, just to
+        * document this camera's control device */
+       } else if (icd->control)
+               /* Have to sysfs_remove_link() before device_unregister()? */
+               if (sysfs_create_link(&icd->dev.kobj, &icd->control->kobj,
+                                     "control"))
+                       dev_warn(&icd->dev,
+                                "Failed creating the control symlink\n");
+       return ret;
+}
+
+/* So far this function cannot fail */
+static void scan_add_host(struct soc_camera_host *ici)
+{
+       struct soc_camera_device *icd;
+
+       mutex_lock(&list_lock);
+
+       list_for_each_entry(icd, &devices, list) {
+               if (icd->iface == ici->nr) {
+                       icd->dev.parent = &ici->dev;
+                       device_register_link(icd);
+               }
+       }
+
+       mutex_unlock(&list_lock);
+}
+
+/* return: 0 if no match found or a match found and
+ * device_register() successful, error code otherwise */
+static int scan_add_device(struct soc_camera_device *icd)
+{
+       struct soc_camera_host *ici;
+       int ret = 0;
+
+       mutex_lock(&list_lock);
+
+       list_add_tail(&icd->list, &devices);
+
+       /* Watch out for class_for_each_device / class_find_device API by
+        * Dave Young <hidave.darkstar@gmail.com> */
+       list_for_each_entry(ici, &hosts, list) {
+               if (icd->iface == ici->nr) {
+                       ret = 1;
+                       icd->dev.parent = &ici->dev;
+                       break;
+               }
+       }
+
+       mutex_unlock(&list_lock);
+
+       if (ret)
+               ret = device_register_link(icd);
+
+       return ret;
+}
+
+static int soc_camera_probe(struct device *dev)
+{
+       struct soc_camera_device *icd = to_soc_camera_dev(dev);
+       struct soc_camera_host *ici =
+               to_soc_camera_host(icd->dev.parent);
+       int ret;
+
+       if (!icd->ops->probe)
+               return -ENODEV;
+
+       /* We only call ->add() here to activate and probe the camera.
+        * We shall ->remove() and deactivate it immediately afterwards. */
+       ret = ici->ops->add(icd);
+       if (ret < 0)
+               return ret;
+
+       ret = icd->ops->probe(icd);
+       if (ret >= 0) {
+               const struct v4l2_queryctrl *qctrl;
+
+               qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_GAIN);
+               icd->gain = qctrl ? qctrl->default_value : (unsigned short)~0;
+               qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE);
+               icd->exposure = qctrl ? qctrl->default_value :
+                       (unsigned short)~0;
+       }
+       ici->ops->remove(icd);
+
+       return ret;
+}
+
+/* This is called on device_unregister, which only means we have to disconnect
+ * from the host, but not remove ourselves from the device list */
+static int soc_camera_remove(struct device *dev)
+{
+       struct soc_camera_device *icd = to_soc_camera_dev(dev);
+
+       if (icd->ops->remove)
+               icd->ops->remove(icd);
+
+       return 0;
+}
+
+static struct bus_type soc_camera_bus_type = {
+       .name           = "soc-camera",
+       .probe          = soc_camera_probe,
+       .remove         = soc_camera_remove,
+};
+
+static struct device_driver ic_drv = {
+       .name   = "camera",
+       .bus    = &soc_camera_bus_type,
+       .owner  = THIS_MODULE,
+};
+
+/*
+ * Image capture host - this is a host device, not a bus device, so,
+ * no bus reference, no probing.
+ */
+static struct class soc_camera_host_class = {
+       .owner          = THIS_MODULE,
+       .name           = "camera_host",
+};
+
+static void dummy_release(struct device *dev)
+{
+}
+
+static spinlock_t *spinlock_alloc(struct soc_camera_file *icf)
+{
+       spinlock_t *lock = kmalloc(sizeof(spinlock_t), GFP_KERNEL);
+
+       if (lock)
+               spin_lock_init(lock);
+
+       return lock;
+}
+
+static void spinlock_free(spinlock_t *lock)
+{
+       kfree(lock);
+}
+
+int soc_camera_host_register(struct soc_camera_host *ici)
+{
+       int ret;
+       struct soc_camera_host *ix;
+
+       if (!ici->vbq_ops || !ici->ops->add || !ici->ops->remove)
+               return -EINVAL;
+
+       /* Number might be equal to the platform device ID */
+       sprintf(ici->dev.bus_id, "camera_host%d", ici->nr);
+       ici->dev.class = &soc_camera_host_class;
+
+       mutex_lock(&list_lock);
+       list_for_each_entry(ix, &hosts, list) {
+               if (ix->nr == ici->nr) {
+                       mutex_unlock(&list_lock);
+                       return -EBUSY;
+               }
+       }
+
+       list_add_tail(&ici->list, &hosts);
+       mutex_unlock(&list_lock);
+
+       ici->dev.release = dummy_release;
+
+       ret = device_register(&ici->dev);
+
+       if (ret)
+               goto edevr;
+
+       if (!ici->ops->spinlock_alloc) {
+               ici->ops->spinlock_alloc = spinlock_alloc;
+               ici->ops->spinlock_free = spinlock_free;
+       }
+
+       scan_add_host(ici);
+
+       return 0;
+
+edevr:
+       mutex_lock(&list_lock);
+       list_del(&ici->list);
+       mutex_unlock(&list_lock);
+
+       return ret;
+}
+EXPORT_SYMBOL(soc_camera_host_register);
+
+/* Unregister all clients! */
+void soc_camera_host_unregister(struct soc_camera_host *ici)
+{
+       struct soc_camera_device *icd;
+
+       mutex_lock(&list_lock);
+
+       list_del(&ici->list);
+
+       list_for_each_entry(icd, &devices, list) {
+               if (icd->dev.parent == &ici->dev) {
+                       device_unregister(&icd->dev);
+                       /* Not before device_unregister(), .remove
+                        * needs parent to call ici->ops->remove() */
+                       icd->dev.parent = NULL;
+                       memset(&icd->dev.kobj, 0, sizeof(icd->dev.kobj));
+               }
+       }
+
+       mutex_unlock(&list_lock);
+
+       device_unregister(&ici->dev);
+}
+EXPORT_SYMBOL(soc_camera_host_unregister);
+
+/* Image capture device */
+int soc_camera_device_register(struct soc_camera_device *icd)
+{
+       struct soc_camera_device *ix;
+       int num = -1, i;
+
+       if (!icd)
+               return -EINVAL;
+
+       for (i = 0; i < 256 && num < 0; i++) {
+               num = i;
+               list_for_each_entry(ix, &devices, list) {
+                       if (ix->iface == icd->iface && ix->devnum == i) {
+                               num = -1;
+                               break;
+                       }
+               }
+       }
+
+       if (num < 0)
+               /* ok, we have 256 cameras on this host...
+                * man, stay reasonable... */
+               return -ENOMEM;
+
+       icd->devnum = num;
+       icd->dev.bus = &soc_camera_bus_type;
+       snprintf(icd->dev.bus_id, sizeof(icd->dev.bus_id),
+                "%u-%u", icd->iface, icd->devnum);
+
+       icd->dev.release = dummy_release;
+
+       return scan_add_device(icd);
+}
+EXPORT_SYMBOL(soc_camera_device_register);
+
+void soc_camera_device_unregister(struct soc_camera_device *icd)
+{
+       mutex_lock(&list_lock);
+       list_del(&icd->list);
+
+       /* The bus->remove will be eventually called */
+       if (icd->dev.parent)
+               device_unregister(&icd->dev);
+       mutex_unlock(&list_lock);
+}
+EXPORT_SYMBOL(soc_camera_device_unregister);
+
+int soc_camera_video_start(struct soc_camera_device *icd)
+{
+       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       int err = -ENOMEM;
+       struct video_device *vdev;
+
+       if (!icd->dev.parent)
+               return -ENODEV;
+
+       vdev = video_device_alloc();
+       if (!vdev)
+               goto evidallocd;
+       dev_dbg(&ici->dev, "Allocated video_device %p\n", vdev);
+
+       strlcpy(vdev->name, ici->drv_name, sizeof(vdev->name));
+       /* Maybe better &ici->dev */
+       vdev->dev               = &icd->dev;
+       vdev->type              = VID_TYPE_CAPTURE;
+       vdev->current_norm      = V4L2_STD_UNKNOWN;
+       vdev->fops              = &soc_camera_fops;
+       vdev->release           = video_device_release;
+       vdev->minor             = -1;
+       vdev->tvnorms           = V4L2_STD_UNKNOWN,
+       vdev->vidioc_querycap   = soc_camera_querycap;
+       vdev->vidioc_g_fmt_cap  = soc_camera_g_fmt_cap;
+       vdev->vidioc_enum_fmt_cap = soc_camera_enum_fmt_cap;
+       vdev->vidioc_s_fmt_cap  = soc_camera_s_fmt_cap;
+       vdev->vidioc_enum_input = soc_camera_enum_input;
+       vdev->vidioc_g_input    = soc_camera_g_input;
+       vdev->vidioc_s_input    = soc_camera_s_input;
+       vdev->vidioc_s_std      = soc_camera_s_std;
+       vdev->vidioc_reqbufs    = soc_camera_reqbufs;
+       vdev->vidioc_try_fmt_cap = soc_camera_try_fmt_cap;
+       vdev->vidioc_querybuf   = soc_camera_querybuf;
+       vdev->vidioc_qbuf       = soc_camera_qbuf;
+       vdev->vidioc_dqbuf      = soc_camera_dqbuf;
+       vdev->vidioc_streamon   = soc_camera_streamon;
+       vdev->vidioc_streamoff  = soc_camera_streamoff;
+       vdev->vidioc_queryctrl  = soc_camera_queryctrl;
+       vdev->vidioc_g_ctrl     = soc_camera_g_ctrl;
+       vdev->vidioc_s_ctrl     = soc_camera_s_ctrl;
+       vdev->vidioc_cropcap    = soc_camera_cropcap;
+       vdev->vidioc_g_crop     = soc_camera_g_crop;
+       vdev->vidioc_s_crop     = soc_camera_s_crop;
+       vdev->vidioc_g_chip_ident = soc_camera_g_chip_ident;
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       vdev->vidioc_g_register = soc_camera_g_register;
+       vdev->vidioc_s_register = soc_camera_s_register;
+#endif
+
+       icd->current_fmt = &icd->formats[0];
+
+       err = video_register_device(vdev, VFL_TYPE_GRABBER, vdev->minor);
+       if (err < 0) {
+               dev_err(vdev->dev, "video_register_device failed\n");
+               goto evidregd;
+       }
+       icd->vdev = vdev;
+
+       return 0;
+
+evidregd:
+       video_device_release(vdev);
+evidallocd:
+       return err;
+}
+EXPORT_SYMBOL(soc_camera_video_start);
+
+void soc_camera_video_stop(struct soc_camera_device *icd)
+{
+       struct video_device *vdev = icd->vdev;
+
+       dev_dbg(&icd->dev, "%s\n", __func__);
+
+       if (!icd->dev.parent || !vdev)
+               return;
+
+       mutex_lock(&video_lock);
+       video_unregister_device(vdev);
+       icd->vdev = NULL;
+       mutex_unlock(&video_lock);
+}
+EXPORT_SYMBOL(soc_camera_video_stop);
+
+static int __init soc_camera_init(void)
+{
+       int ret = bus_register(&soc_camera_bus_type);
+       if (ret)
+               return ret;
+       ret = driver_register(&ic_drv);
+       if (ret)
+               goto edrvr;
+       ret = class_register(&soc_camera_host_class);
+       if (ret)
+               goto eclr;
+
+       return 0;
+
+eclr:
+       driver_unregister(&ic_drv);
+edrvr:
+       bus_unregister(&soc_camera_bus_type);
+       return ret;
+}
+
+static void __exit soc_camera_exit(void)
+{
+       class_unregister(&soc_camera_host_class);
+       driver_unregister(&ic_drv);
+       bus_unregister(&soc_camera_bus_type);
+}
+
+module_init(soc_camera_init);
+module_exit(soc_camera_exit);
+
+MODULE_DESCRIPTION("Image capture bus driver");
+MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>");
+MODULE_LICENSE("GPL");
index ceba45ad02942622edd1c67f8aecb9d65306c1e7..9276ed99738839075615554ff384e5afd285815b 100644 (file)
@@ -1100,7 +1100,7 @@ static int stk_setup_format(struct stk_camera *dev)
                        && i < ARRAY_SIZE(stk_sizes))
                i++;
        if (i == ARRAY_SIZE(stk_sizes)) {
-               STK_ERROR("Something is broken in %s\n", __FUNCTION__);
+               STK_ERROR("Something is broken in %s\n", __func__);
                return -EFAULT;
        }
        /* This registers controls some timings, not sure of what. */
@@ -1465,7 +1465,7 @@ static void stk_camera_disconnect(struct usb_interface *interface)
 }
 
 #ifdef CONFIG_PM
-int stk_camera_suspend(struct usb_interface *intf, pm_message_t message)
+static int stk_camera_suspend(struct usb_interface *intf, pm_message_t message)
 {
        struct stk_camera *dev = usb_get_intfdata(intf);
        if (is_streaming(dev)) {
@@ -1476,7 +1476,7 @@ int stk_camera_suspend(struct usb_interface *intf, pm_message_t message)
        return 0;
 }
 
-int stk_camera_resume(struct usb_interface *intf)
+static int stk_camera_resume(struct usb_interface *intf)
 {
        struct stk_camera *dev = usb_get_intfdata(intf);
        if (!is_initialised(dev))
index 3fb85af5d1f2b8ab45140661298a53062c920fb3..c109511f21ea8a92b307d4ce1596748567c0348f 100644 (file)
@@ -58,7 +58,7 @@
 
 static struct saa7146 saa7146s[SAA7146_MAX];
 
-static int saa_num = 0;                /* number of SAA7146s in use */
+static int saa_num;            /* number of SAA7146s in use */
 
 static int video_nr = -1;
 module_param(video_nr, int, 0);
@@ -248,7 +248,7 @@ static void I2CBusScan(struct saa7146 *saa)
                        attach_inform(saa, i);
 }
 
-static int debiwait_maxwait = 0;
+static int debiwait_maxwait;
 
 static int wait_for_debi_done(struct saa7146 *saa)
 {
@@ -1906,7 +1906,9 @@ static const struct file_operations saa_fops = {
        .open = saa_open,
        .release = saa_release,
        .ioctl = saa_ioctl,
+#ifdef CONFIG_COMPAT
        .compat_ioctl = v4l_compat_ioctl32,
+#endif
        .read = saa_read,
        .llseek = no_llseek,
        .write = saa_write,
index afc32aa56fde2eb3952cb69dd214cdd9cd52701b..d7f130bedb5f47a05f6eddff87634e6af54d25c4 100644 (file)
 #include "stv680.h"
 
 static int video_nr = -1;
-static int swapRGB = 0;   /* default for auto sleect */
-static int swapRGB_on = 0; /* default to allow auto select; -1=swap never, +1= swap always */
 
-static unsigned int debug = 0;
+static int swapRGB;    /* 0 = default for auto select */
+
+/* 0 = default to allow auto select; -1 = swap never, +1 = swap always */
+static int swapRGB_on;
+
+static unsigned int debug;
 
 #define PDEBUG(level, fmt, args...) \
        do { \
        if (debug >= level)     \
-               info("[%s:%d] " fmt, __FUNCTION__, __LINE__ , ## args); \
+               info("[%s:%d] " fmt, __func__, __LINE__ , ## args);     \
        } while (0)
 
 
@@ -1391,7 +1394,9 @@ static const struct file_operations stv680_fops = {
        .read =         stv680_read,
        .mmap =         stv680_mmap,
        .ioctl =        stv680_ioctl,
+#ifdef CONFIG_COMPAT
        .compat_ioctl = v4l_compat_ioctl32,
+#endif
        .llseek =       no_llseek,
 };
 static struct video_device stv680_template = {
index fb895f6684a3cf31851323afa4ef5db03e84c762..6943b447a1bd7f4067e4a6f97a92c9e6d67ef83e 100644 (file)
@@ -906,7 +906,7 @@ static int __init tcm825x_init(void)
        rval = i2c_add_driver(&tcm825x_i2c_driver);
        if (rval)
                printk(KERN_INFO "%s: failed registering " TCM825X_NAME "\n",
-                      __FUNCTION__);
+                      __func__);
 
        return rval;
 }
index 55bc89a6f0694c7f3d8e35e6804f4fb8d01eda5f..0ebb5b525e576da86f021b74b669f5493e4886db 100644 (file)
@@ -32,8 +32,6 @@ static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "enable verbose debug messages");
 
-#define PREFIX "tda8290"
-
 /* ---------------------------------------------------------------------- */
 
 struct tda8290_priv {
@@ -174,7 +172,7 @@ static void tda8290_set_params(struct dvb_frontend *fe,
        set_audio(fe, params);
 
        if (priv->cfg.config)
-               tuner_dbg("tda827xa config is 0x%02x\n", *priv->cfg.config);
+               tuner_dbg("tda827xa config is 0x%02x\n", priv->cfg.config);
        tuner_i2c_xfer_send(&priv->i2c_props, easy_mode, 2);
        tuner_i2c_xfer_send(&priv->i2c_props, agc_out_on, 2);
        tuner_i2c_xfer_send(&priv->i2c_props, soft_reset, 2);
@@ -365,7 +363,7 @@ static void tda8295_set_params(struct dvb_frontend *fe,
 
        set_audio(fe, params);
 
-       tuner_dbg("%s: freq = %d\n", __FUNCTION__, params->frequency);
+       tuner_dbg("%s: freq = %d\n", __func__, params->frequency);
 
        tda8295_power(fe, 1);
        tda8295_agc1_out(fe, 1);
@@ -444,8 +442,7 @@ static void tda8290_init_if(struct dvb_frontend *fe)
        unsigned char set_GP00_CF[] = { 0x20, 0x01 };
        unsigned char set_GP01_CF[] = { 0x20, 0x0B };
 
-       if ((priv->cfg.config) &&
-           ((*priv->cfg.config == 1) || (*priv->cfg.config == 2)))
+       if ((priv->cfg.config == 1) || (priv->cfg.config == 2))
                tuner_i2c_xfer_send(&priv->i2c_props, set_GP00_CF, 2);
        else
                tuner_i2c_xfer_send(&priv->i2c_props, set_GP01_CF, 2);
@@ -590,8 +587,8 @@ static int tda829x_find_tuner(struct dvb_frontend *fe)
                else
                        priv->ver |= TDA8275A;
 
-               tda827x_attach(fe, priv->tda827x_addr,
-                              priv->i2c_props.adap, &priv->cfg);
+               tda827x_attach(fe, priv->tda827x_addr, priv->i2c_props.adap, &priv->cfg);
+               priv->cfg.switch_addr = priv->i2c_props.addr;
        }
        if (fe->ops.tuner_ops.init)
                fe->ops.tuner_ops.init(fe);
@@ -616,7 +613,7 @@ static int tda8290_probe(struct tuner_i2c_props *i2c_props)
        if (tda8290_id[1] == TDA8290_ID) {
                if (debug)
                        printk(KERN_DEBUG "%s: tda8290 detected @ %d-%04x\n",
-                              __FUNCTION__, i2c_adapter_id(i2c_props->adap),
+                              __func__, i2c_adapter_id(i2c_props->adap),
                               i2c_props->addr);
                return 0;
        }
@@ -636,7 +633,7 @@ static int tda8295_probe(struct tuner_i2c_props *i2c_props)
        if (tda8295_id[1] == TDA8295_ID) {
                if (debug)
                        printk(KERN_DEBUG "%s: tda8295 detected @ %d-%04x\n",
-                              __FUNCTION__, i2c_adapter_id(i2c_props->adap),
+                              __func__, i2c_adapter_id(i2c_props->adap),
                               i2c_props->addr);
                return 0;
        }
@@ -674,6 +671,7 @@ struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe,
 
        priv->i2c_props.addr     = i2c_addr;
        priv->i2c_props.adap     = i2c_adap;
+       priv->i2c_props.name     = "tda829x";
        if (cfg) {
                priv->cfg.config         = cfg->lna_cfg;
                priv->cfg.tuner_callback = cfg->tuner_callback;
index dc8ef310b7b26b1fbccc6e24d321eb70d63caba2..d3bbf276a469165354e82770764feec9d619bec6 100644 (file)
@@ -21,7 +21,7 @@
 #include "dvb_frontend.h"
 
 struct tda829x_config {
-       unsigned int *lna_cfg;
+       unsigned int lna_cfg;
        int (*tuner_callback) (void *dev, int command, int arg);
 
        unsigned int probe_tuner:1;
@@ -39,7 +39,7 @@ extern struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe,
 #else
 static inline int tda829x_probe(struct i2c_adapter *i2c_adap, u8 i2c_addr)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return -EINVAL;
 }
 
@@ -49,7 +49,7 @@ static inline struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe,
                                                  struct tda829x_config *cfg)
 {
        printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n",
-              __FUNCTION__);
+              __func__);
        return NULL;
 }
 #endif
index bdca5d278978374b7a65e7e55bd65aa06a010ee2..0cee00242782bb0ec16a0736b822d43370cd9624 100644 (file)
 
 #include "tda9840.h"
 
-static int debug = 0;          /* insmod parameter */
+static int debug;              /* insmod parameter */
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
 #define dprintk(args...) \
-           do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __FUNCTION__, __LINE__); printk(args); } } while (0)
+           do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __func__, __LINE__); printk(args); } } while (0)
 
 #define        SWITCH          0x00
 #define        LEVEL_ADJUST    0x02
index 106c93b8203fea587562240b37b8d0564cbb21a3..a0545ba957b05c5be756016ebb041d792088006d 100644 (file)
@@ -25,10 +25,12 @@ static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "enable verbose debug messages");
 
-#define PREFIX "tda9887"
+static DEFINE_MUTEX(tda9887_list_mutex);
+static LIST_HEAD(hybrid_tuner_instance_list);
 
 struct tda9887_priv {
        struct tuner_i2c_props i2c_props;
+       struct list_head hybrid_tuner_instance_list;
 
        unsigned char      data[4];
        unsigned int       config;
@@ -644,7 +646,15 @@ static int tda9887_set_config(struct dvb_frontend *fe, void *priv_cfg)
 
 static void tda9887_release(struct dvb_frontend *fe)
 {
-       kfree(fe->analog_demod_priv);
+       struct tda9887_priv *priv = fe->analog_demod_priv;
+
+       mutex_lock(&tda9887_list_mutex);
+
+       if (priv)
+               hybrid_tuner_release_state(priv);
+
+       mutex_unlock(&tda9887_list_mutex);
+
        fe->analog_demod_priv = NULL;
 }
 
@@ -665,17 +675,29 @@ struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe,
                                    u8 i2c_addr)
 {
        struct tda9887_priv *priv = NULL;
+       int instance;
 
-       priv = kzalloc(sizeof(struct tda9887_priv), GFP_KERNEL);
-       if (priv == NULL)
-               return NULL;
-       fe->analog_demod_priv = priv;
+       mutex_lock(&tda9887_list_mutex);
 
-       priv->i2c_props.addr = i2c_addr;
-       priv->i2c_props.adap = i2c_adap;
-       priv->mode = T_STANDBY;
+       instance = hybrid_tuner_request_state(struct tda9887_priv, priv,
+                                             hybrid_tuner_instance_list,
+                                             i2c_adap, i2c_addr, "tda9887");
+       switch (instance) {
+       case 0:
+               mutex_unlock(&tda9887_list_mutex);
+               return NULL;
+               break;
+       case 1:
+               fe->analog_demod_priv = priv;
+               priv->mode = T_STANDBY;
+               tuner_info("tda988[5/6/7] found\n");
+               break;
+       default:
+               fe->analog_demod_priv = priv;
+               break;
+       }
 
-       tuner_info("tda988[5/6/7] found\n");
+       mutex_unlock(&tda9887_list_mutex);
 
        memcpy(&fe->ops.analog_ops, &tda9887_ops,
               sizeof(struct analog_demod_ops));
index 8f873a8e6ed20ef80b16ff2dfe4bdf4809be33ab..be49dcbfc70e1473056823b24e7a7f0d7bec56d2 100644 (file)
@@ -30,7 +30,7 @@ static inline struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe,
                                                  struct i2c_adapter *i2c_adap,
                                                  u8 i2c_addr)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif
index 5326eeceaacdabb0bdce32825182924fd8d65f35..b93cdef9ac73e48b04f5a369da3767e6d46c42d7 100644 (file)
 #include "tuner-i2c.h"
 #include "tea5761.h"
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "enable verbose debug messages");
 
-#define PREFIX "tea5761"
-
 struct tea5761_priv {
        struct tuner_i2c_props i2c_props;
 
@@ -131,7 +129,7 @@ static void tea5761_status_dump(unsigned char *buffer)
 
        frq = 1000 * (div * 32768 / 1000 + FREQ_OFFSET + 225) / 4;      /* Freq in KHz */
 
-       printk(PREFIX "Frequency %d.%03d KHz (divider = 0x%04x)\n",
+       printk(KERN_INFO "tea5761: Frequency %d.%03d KHz (divider = 0x%04x)\n",
               frq / 1000, frq % 1000, div);
 }
 
@@ -249,14 +247,19 @@ int tea5761_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr)
 
        if (16 != (rc = tuner_i2c_xfer_recv(&i2c, buffer, 16))) {
                printk(KERN_WARNING "it is not a TEA5761. Received %i chars.\n", rc);
-               return EINVAL;
+               return -EINVAL;
        }
 
-       if (!((buffer[13] != 0x2b) || (buffer[14] != 0x57) || (buffer[15] != 0x061))) {
-               printk(KERN_WARNING "Manufacturer ID= 0x%02x, Chip ID = %02x%02x. It is not a TEA5761\n",buffer[13],buffer[14],buffer[15]);
-               return EINVAL;
+       if ((buffer[13] != 0x2b) || (buffer[14] != 0x57) || (buffer[15] != 0x061)) {
+               printk(KERN_WARNING "Manufacturer ID= 0x%02x, Chip ID = %02x%02x."
+                                   " It is not a TEA5761\n",
+                                   buffer[13], buffer[14], buffer[15]);
+               return -EINVAL;
        }
-       printk(KERN_WARNING "TEA5761 detected.\n");
+       printk(KERN_WARNING "tea5761: TEA%02x%02x detected. "
+                           "Manufacturer ID= 0x%02x\n",
+                           buffer[14], buffer[15], buffer[13]);
+
        return 0;
 }
 
@@ -302,6 +305,7 @@ struct dvb_frontend *tea5761_attach(struct dvb_frontend *fe,
 
        priv->i2c_props.addr = i2c_addr;
        priv->i2c_props.adap = i2c_adap;
+       priv->i2c_props.name = "tea5761";
 
        memcpy(&fe->ops.tuner_ops, &tea5761_tuner_ops,
               sizeof(struct dvb_tuner_ops));
index 73a03b427843f4466a3043c68eb6dc14a36a1b2b..8eb62722b9885f7d4253200a128401b416736c65 100644 (file)
@@ -31,7 +31,7 @@ static inline int tea5761_autodetection(struct i2c_adapter* i2c_adap,
                                        u8 i2c_addr)
 {
        printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n",
-              __FUNCTION__);
+              __func__);
        return -EINVAL;
 }
 
@@ -39,7 +39,7 @@ static inline struct dvb_frontend *tea5761_attach(struct dvb_frontend *fe,
                                                   struct i2c_adapter* i2c_adap,
                                                   u8 i2c_addr)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif
index e1b48d87e7b74fba277b9796e074bf13b514bd86..f6e7d7ad842416ad5ac9b82bde9532125a3ddd80 100644 (file)
 #include "tuner-i2c.h"
 #include "tea5767.h"
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "enable verbose debug messages");
 
-#define PREFIX "tea5767"
-
 /*****************************************************************************/
 
 struct tea5767_priv {
@@ -137,14 +135,14 @@ static void tea5767_status_dump(struct tea5767_priv *priv,
        unsigned int div, frq;
 
        if (TEA5767_READY_FLAG_MASK & buffer[0])
-               printk(PREFIX "Ready Flag ON\n");
+               tuner_info("Ready Flag ON\n");
        else
-               printk(PREFIX "Ready Flag OFF\n");
+               tuner_info("Ready Flag OFF\n");
 
        if (TEA5767_BAND_LIMIT_MASK & buffer[0])
-               printk(PREFIX "Tuner at band limit\n");
+               tuner_info("Tuner at band limit\n");
        else
-               printk(PREFIX "Tuner not at band limit\n");
+               tuner_info("Tuner not at band limit\n");
 
        div = ((buffer[0] & 0x3f) << 8) | buffer[1];
 
@@ -166,23 +164,23 @@ static void tea5767_status_dump(struct tea5767_priv *priv,
        buffer[0] = (div >> 8) & 0x3f;
        buffer[1] = div & 0xff;
 
-       printk(PREFIX "Frequency %d.%03d KHz (divider = 0x%04x)\n",
-              frq / 1000, frq % 1000, div);
+       tuner_info("Frequency %d.%03d KHz (divider = 0x%04x)\n",
+                  frq / 1000, frq % 1000, div);
 
        if (TEA5767_STEREO_MASK & buffer[2])
-               printk(PREFIX "Stereo\n");
+               tuner_info("Stereo\n");
        else
-               printk(PREFIX "Mono\n");
+               tuner_info("Mono\n");
 
-       printk(PREFIX "IF Counter = %d\n", buffer[2] & TEA5767_IF_CNTR_MASK);
+       tuner_info("IF Counter = %d\n", buffer[2] & TEA5767_IF_CNTR_MASK);
 
-       printk(PREFIX "ADC Level = %d\n",
-              (buffer[3] & TEA5767_ADC_LEVEL_MASK) >> 4);
+       tuner_info("ADC Level = %d\n",
+                  (buffer[3] & TEA5767_ADC_LEVEL_MASK) >> 4);
 
-       printk(PREFIX "Chip ID = %d\n", (buffer[3] & TEA5767_CHIP_ID_MASK));
+       tuner_info("Chip ID = %d\n", (buffer[3] & TEA5767_CHIP_ID_MASK));
 
-       printk(PREFIX "Reserved = 0x%02x\n",
-              (buffer[4] & TEA5767_RESERVED_MASK));
+       tuner_info("Reserved = 0x%02x\n",
+                  (buffer[4] & TEA5767_RESERVED_MASK));
 }
 
 /* Freq should be specifyed at 62.5 Hz */
@@ -395,11 +393,6 @@ int tea5767_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr)
                return EINVAL;
        }
 
-       /* It seems that tea5767 returns 0xff after the 5th byte */
-       if ((buffer[5] != 0xff) || (buffer[6] != 0xff)) {
-               printk(KERN_WARNING "Returned more than 5 bytes. It is not a TEA5767\n");
-               return EINVAL;
-       }
 
        return 0;
 }
@@ -456,6 +449,8 @@ struct dvb_frontend *tea5767_attach(struct dvb_frontend *fe,
 
        priv->i2c_props.addr  = i2c_addr;
        priv->i2c_props.adap  = i2c_adap;
+       priv->i2c_props.name  = "tea5767";
+
        priv->ctrl.xtal_freq  = TEA5767_HIGH_LO_32768;
        priv->ctrl.port1      = 1;
        priv->ctrl.port2      = 1;
index a44451f6114544ea689afa716cae716d559f47bf..7b547c092e25215bbd81505b8635c7ec907611bc 100644 (file)
@@ -50,7 +50,7 @@ static inline int tea5767_autodetection(struct i2c_adapter* i2c_adap,
                                        u8 i2c_addr)
 {
        printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n",
-              __FUNCTION__);
+              __func__);
        return -EINVAL;
 }
 
@@ -58,7 +58,7 @@ static inline struct dvb_frontend *tea5767_attach(struct dvb_frontend *fe,
                                                   struct i2c_adapter* i2c_adap,
                                                   u8 i2c_addr)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif
index df2fad9f391eb0a2936b8c14c39c51a1273a0e0c..9513d8611e8781431db6306fb5a2c8645df19817 100644 (file)
 
 #include "tea6415c.h"
 
-static int debug = 0;          /* insmod parameter */
+static int debug;              /* insmod parameter */
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
 #define dprintk(args...) \
-           do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __FUNCTION__, __LINE__); printk(args); } } while (0)
+           do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __func__, __LINE__); printk(args); } } while (0)
 
 #define TEA6415C_NUM_INPUTS    8
 #define TEA6415C_NUM_OUTPUTS   6
index 4ff6c63f7237517a05d974fd60cfbcbb838af0cf..7fd53367c07caef877db4d21b55dbfc8d6355147 100644 (file)
 
 #include "tea6420.h"
 
-static int debug = 0;          /* insmod parameter */
+static int debug;              /* insmod parameter */
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
 #define dprintk(args...) \
-           do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __FUNCTION__, __LINE__); printk(args); } } while (0)
+           do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __func__, __LINE__); printk(args); } } while (0)
 
 /* addresses to scan, found only at 0x4c and/or 0x4d (7-Bit) */
 static unsigned short normal_i2c[] = { I2C_ADDR_TEA6420_1, I2C_ADDR_TEA6420_2, I2C_CLIENT_END };
index 78a09a2a4857b94028e7eadbbecb37dea0c91908..529e00952a8db1c0b813f8f3ae06c1d62d067e3b 100644 (file)
@@ -68,9 +68,9 @@ static unsigned short normal_i2c[] = {
 I2C_CLIENT_INSMOD;
 
 /* insmod options used at init time => read/only */
-static unsigned int addr = 0;
-static unsigned int no_autodetect = 0;
-static unsigned int show_i2c = 0;
+static unsigned int addr;
+static unsigned int no_autodetect;
+static unsigned int show_i2c;
 
 /* insmod options used at runtime => read/write */
 static int tuner_debug;
@@ -313,24 +313,14 @@ static void tuner_i2c_address_check(struct tuner *t)
        tuner_warn("output to v4l-dvb-maintainer@linuxtv.org\n");
        tuner_warn("Please use subject line: \"obsolete tuner i2c address.\"\n");
        tuner_warn("driver: %s, addr: 0x%02x, type: %d (%s)\n",
-                  t->i2c->adapter->name, t->i2c->addr, t->type,
-                  tuners[t->type].name);
+                  t->i2c->adapter->name, t->i2c->addr, t->type, t->i2c->name);
        tuner_warn("====================== WARNING! ======================\n");
 }
 
-static void attach_simple_tuner(struct tuner *t)
-{
-       struct simple_tuner_config cfg = {
-               .type = t->type,
-               .tun  = &tuners[t->type]
-       };
-       simple_tuner_attach(&t->fe, t->i2c->adapter, t->i2c->addr, &cfg);
-}
-
 static void attach_tda829x(struct tuner *t)
 {
        struct tda829x_config cfg = {
-               .lna_cfg        = &t->config,
+               .lna_cfg        = t->config,
                .tuner_callback = t->tuner_callback,
        };
        tda829x_attach(&t->fe, t->i2c->adapter, t->i2c->addr, &cfg);
@@ -352,11 +342,6 @@ static void set_type(struct i2c_client *c, unsigned int type,
                return;
        }
 
-       if (type >= tuner_count) {
-               tuner_warn ("tuner 0x%02x: Tuner count greater than %d\n",c->addr,tuner_count);
-               return;
-       }
-
        t->type = type;
        t->config = new_config;
        if (tuner_callback != NULL) {
@@ -409,7 +394,12 @@ static void set_type(struct i2c_client *c, unsigned int type,
                buffer[2] = 0x86;
                buffer[3] = 0x54;
                i2c_master_send(c, buffer, 4);
-               attach_simple_tuner(t);
+               if (simple_tuner_attach(&t->fe, t->i2c->adapter, t->i2c->addr,
+                                       t->type) == NULL) {
+                       t->type = TUNER_ABSENT;
+                       t->mode_mask = T_UNINITIALIZED;
+                       return;
+               }
                break;
        case TUNER_PHILIPS_TD1316:
                buffer[0] = 0x0b;
@@ -417,14 +407,18 @@ static void set_type(struct i2c_client *c, unsigned int type,
                buffer[2] = 0x86;
                buffer[3] = 0xa4;
                i2c_master_send(c,buffer,4);
-               attach_simple_tuner(t);
+               if (simple_tuner_attach(&t->fe, t->i2c->adapter,
+                                       t->i2c->addr, t->type) == NULL) {
+                       t->type = TUNER_ABSENT;
+                       t->mode_mask = T_UNINITIALIZED;
+                       return;
+               }
                break;
        case TUNER_XC2028:
        {
                struct xc2028_config cfg = {
                        .i2c_adap  = t->i2c->adapter,
                        .i2c_addr  = t->i2c->addr,
-                       .video_dev = c->adapter->algo_data,
                        .callback  = t->tuner_callback,
                };
                if (!xc2028_attach(&t->fe, &cfg)) {
@@ -455,7 +449,12 @@ static void set_type(struct i2c_client *c, unsigned int type,
                }
                break;
        default:
-               attach_simple_tuner(t);
+               if (simple_tuner_attach(&t->fe, t->i2c->adapter,
+                                       t->i2c->addr, t->type) == NULL) {
+                       t->type = TUNER_ABSENT;
+                       t->mode_mask = T_UNINITIALIZED;
+                       return;
+               }
                break;
        }
 
@@ -759,7 +758,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
                if (analog_ops->standby)
                        analog_ops->standby(&t->fe);
                break;
-#ifdef CONFIG_VIDEO_V4L1
+#ifdef CONFIG_VIDEO_ALLOW_V4L1
        case VIDIOCSAUDIO:
                if (check_mode(t, "VIDIOCSAUDIO") == EINVAL)
                        return 0;
@@ -1112,8 +1111,8 @@ static int tuner_probe(struct i2c_client *client)
        if (!no_autodetect) {
                switch (client->addr) {
                case 0x10:
-                       if (tea5761_autodetection(t->i2c->adapter, t->i2c->addr)
-                                       != EINVAL) {
+                       if (tea5761_autodetection(t->i2c->adapter,
+                                                 t->i2c->addr) >= 0) {
                                t->type = TUNER_TEA5761;
                                t->mode_mask = T_RADIO;
                                t->mode = T_STANDBY;
@@ -1125,7 +1124,7 @@ static int tuner_probe(struct i2c_client *client)
 
                                goto register_client;
                        }
-                       break;
+                       return -ENODEV;
                case 0x42:
                case 0x43:
                case 0x4a:
index de52e8ffd347df1dcd2060c2e6c406b0a58933c2..3ad6c8e0b04ccbd8d612ac89db2f61911b64e225 100644 (file)
 struct tuner_i2c_props {
        u8 addr;
        struct i2c_adapter *adap;
+
+       /* used for tuner instance management */
+       int count;
+       char *name;
 };
 
 static inline int tuner_i2c_xfer_send(struct tuner_i2c_props *props, char *buf, int len)
@@ -59,29 +63,111 @@ static inline int tuner_i2c_xfer_send_recv(struct tuner_i2c_props *props,
        return (ret == 2) ? ilen : ret;
 }
 
-#define tuner_warn(fmt, arg...) do {                                   \
-       printk(KERN_WARNING "%s %d-%04x: " fmt, PREFIX,                 \
-                       i2c_adapter_id(priv->i2c_props.adap),           \
-                       priv->i2c_props.addr, ##arg);                   \
+/* Callers must declare as a global for the module:
+ *
+ * static LIST_HEAD(hybrid_tuner_instance_list);
+ *
+ * hybrid_tuner_instance_list should be the third argument
+ * passed into hybrid_tuner_request_state().
+ *
+ * state structure must contain the following:
+ *
+ *     struct list_head        hybrid_tuner_instance_list;
+ *     struct tuner_i2c_props  i2c_props;
+ *
+ * hybrid_tuner_instance_list (both within state structure and globally)
+ * is only required if the driver is using hybrid_tuner_request_state
+ * and hybrid_tuner_release_state to manage state sharing between
+ * multiple instances of hybrid tuners.
+ */
+
+#define tuner_printk(kernlvl, i2cprops, fmt, arg...) do {              \
+       printk(kernlvl "%s %d-%04x: " fmt, i2cprops.name,               \
+                       i2cprops.adap ?                                 \
+                               i2c_adapter_id(i2cprops.adap) : -1,     \
+                       i2cprops.addr, ##arg);                          \
         } while (0)
 
-#define tuner_info(fmt, arg...) do {                                   \
-       printk(KERN_INFO "%s %d-%04x: " fmt, PREFIX,                    \
-                       i2c_adapter_id(priv->i2c_props.adap),           \
-                       priv->i2c_props.addr , ##arg);                  \
+/* TO DO: convert all callers of these macros to pass in
+ * struct tuner_i2c_props, then remove the macro wrappers */
+
+#define __tuner_warn(i2cprops, fmt, arg...) do {                       \
+       tuner_printk(KERN_WARNING, i2cprops, fmt, ##arg);               \
        } while (0)
 
-#define tuner_err(fmt, arg...) do {                                    \
-       printk(KERN_ERR "%s %d-%04x: " fmt, PREFIX,                     \
-                       i2c_adapter_id(priv->i2c_props.adap),           \
-                       priv->i2c_props.addr , ##arg);                  \
+#define __tuner_info(i2cprops, fmt, arg...) do {                       \
+       tuner_printk(KERN_INFO, i2cprops, fmt, ##arg);                  \
        } while (0)
 
-#define tuner_dbg(fmt, arg...) do {                                    \
+#define __tuner_err(i2cprops, fmt, arg...) do {                                \
+       tuner_printk(KERN_ERR, i2cprops, fmt, ##arg);                   \
+       } while (0)
+
+#define __tuner_dbg(i2cprops, fmt, arg...) do {                                \
        if ((debug))                                                    \
-               printk(KERN_DEBUG "%s %d-%04x: " fmt, PREFIX,           \
-                       i2c_adapter_id(priv->i2c_props.adap),           \
-                       priv->i2c_props.addr , ##arg);                  \
+               tuner_printk(KERN_DEBUG, i2cprops, fmt, ##arg);         \
        } while (0)
 
+#define tuner_warn(fmt, arg...) __tuner_warn(priv->i2c_props, fmt, ##arg)
+#define tuner_info(fmt, arg...) __tuner_info(priv->i2c_props, fmt, ##arg)
+#define tuner_err(fmt, arg...) __tuner_err(priv->i2c_props, fmt, ##arg)
+#define tuner_dbg(fmt, arg...) __tuner_dbg(priv->i2c_props, fmt, ##arg)
+
+/****************************************************************************/
+
+/* The return value of hybrid_tuner_request_state indicates the number of
+ * instances using this tuner object.
+ *
+ * 0 - no instances, indicates an error - kzalloc must have failed
+ *
+ * 1 - one instance, indicates that the tuner object was created successfully
+ *
+ * 2 (or more) instances, indicates that an existing tuner object was found
+ */
+
+#define hybrid_tuner_request_state(type, state, list, i2cadap, i2caddr, devname)\
+({                                                                     \
+       int __ret = 0;                                                  \
+       list_for_each_entry(state, &list, hybrid_tuner_instance_list) { \
+               if (((i2cadap) && (state->i2c_props.adap)) &&           \
+                   ((i2c_adapter_id(state->i2c_props.adap) ==          \
+                     i2c_adapter_id(i2cadap)) &&                       \
+                    (i2caddr == state->i2c_props.addr))) {             \
+                       __tuner_info(state->i2c_props,                  \
+                                    "attaching existing instance\n");  \
+                       state->i2c_props.count++;                       \
+                       __ret = state->i2c_props.count;                 \
+                       break;                                          \
+               }                                                       \
+       }                                                               \
+       if (0 == __ret) {                                               \
+               state = kzalloc(sizeof(type), GFP_KERNEL);              \
+               if (NULL == state)                                      \
+                       goto __fail;                                    \
+               state->i2c_props.addr = i2caddr;                        \
+               state->i2c_props.adap = i2cadap;                        \
+               state->i2c_props.name = devname;                        \
+               __tuner_info(state->i2c_props,                          \
+                            "creating new instance\n");                \
+               list_add_tail(&state->hybrid_tuner_instance_list, &list);\
+               state->i2c_props.count++;                               \
+               __ret = state->i2c_props.count;                         \
+       }                                                               \
+__fail:                                                                        \
+       __ret;                                                          \
+})
+
+#define hybrid_tuner_release_state(state)                              \
+({                                                                     \
+       int __ret;                                                      \
+       state->i2c_props.count--;                                       \
+       __ret = state->i2c_props.count;                                 \
+       if (!state->i2c_props.count) {                                  \
+               __tuner_info(state->i2c_props, "destroying instance\n");\
+               list_del(&state->hybrid_tuner_instance_list);           \
+               kfree(state);                                           \
+       }                                                               \
+       __ret;                                                          \
+})
+
 #endif /* __TUNER_I2C_H__ */
index c1db576696c6d34288e2b4cc6a596c4e730f9dc9..be8d903171b7dce5f3ace750c63177a86d107284 100644 (file)
 #include "tuner-i2c.h"
 #include "tuner-simple.h"
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "enable verbose debug messages");
 
-#define PREFIX "tuner-simple"
+#define TUNER_SIMPLE_MAX 64
+static unsigned int simple_devcount;
 
-static int offset = 0;
+static int offset;
 module_param(offset, int, 0664);
-MODULE_PARM_DESC(offset,"Allows to specify an offset for tuner");
+MODULE_PARM_DESC(offset, "Allows to specify an offset for tuner");
+
+static unsigned int atv_input[TUNER_SIMPLE_MAX] = \
+                       { [0 ... (TUNER_SIMPLE_MAX-1)] = 0 };
+static unsigned int dtv_input[TUNER_SIMPLE_MAX] = \
+                       { [0 ... (TUNER_SIMPLE_MAX-1)] = 0 };
+module_param_array(atv_input, int, NULL, 0644);
+module_param_array(dtv_input, int, NULL, 0644);
+MODULE_PARM_DESC(atv_input, "specify atv rf input, 0 for autoselect");
+MODULE_PARM_DESC(dtv_input, "specify dtv rf input, 0 for autoselect");
 
 /* ---------------------------------------------------------------------- */
 
@@ -36,8 +46,8 @@ MODULE_PARM_DESC(offset,"Allows to specify an offset for tuner");
  */
 #define TEMIC_SET_PAL_I         0x05
 #define TEMIC_SET_PAL_DK        0x09
-#define TEMIC_SET_PAL_L         0x0a // SECAM ?
-#define TEMIC_SET_PAL_L2        0x0b // change IF !
+#define TEMIC_SET_PAL_L         0x0a /* SECAM ? */
+#define TEMIC_SET_PAL_L2        0x0b /* change IF ! */
 #define TEMIC_SET_PAL_BG        0x0c
 
 /* tv tuner system standard selection for Philips FQ1216ME
@@ -90,14 +100,21 @@ MODULE_PARM_DESC(offset,"Allows to specify an offset for tuner");
 #define TUNER_PLL_LOCKED   0x40
 #define TUNER_STEREO_MK3   0x04
 
+static DEFINE_MUTEX(tuner_simple_list_mutex);
+static LIST_HEAD(hybrid_tuner_instance_list);
+
 struct tuner_simple_priv {
+       unsigned int nr;
        u16 last_div;
+
        struct tuner_i2c_props i2c_props;
+       struct list_head hybrid_tuner_instance_list;
 
        unsigned int type;
        struct tunertype *tun;
 
        u32 frequency;
+       u32 bandwidth;
 };
 
 /* ---------------------------------------------------------------------- */
@@ -107,7 +124,7 @@ static int tuner_read_status(struct dvb_frontend *fe)
        struct tuner_simple_priv *priv = fe->tuner_priv;
        unsigned char byte;
 
-       if (1 != tuner_i2c_xfer_recv(&priv->i2c_props,&byte,1))
+       if (1 != tuner_i2c_xfer_recv(&priv->i2c_props, &byte, 1))
                return 0;
 
        return byte;
@@ -121,13 +138,13 @@ static inline int tuner_signal(const int status)
 static inline int tuner_stereo(const int type, const int status)
 {
        switch (type) {
-               case TUNER_PHILIPS_FM1216ME_MK3:
-               case TUNER_PHILIPS_FM1236_MK3:
-               case TUNER_PHILIPS_FM1256_IH3:
-               case TUNER_LG_NTSC_TAPE:
-                       return ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3);
-               default:
-                       return status & TUNER_STEREO;
+       case TUNER_PHILIPS_FM1216ME_MK3:
+       case TUNER_PHILIPS_FM1236_MK3:
+       case TUNER_PHILIPS_FM1256_IH3:
+       case TUNER_LG_NTSC_TAPE:
+               return ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3);
+       default:
+               return status & TUNER_STEREO;
        }
 }
 
@@ -145,7 +162,12 @@ static inline int tuner_afcstatus(const int status)
 static int simple_get_status(struct dvb_frontend *fe, u32 *status)
 {
        struct tuner_simple_priv *priv = fe->tuner_priv;
-       int tuner_status = tuner_read_status(fe);
+       int tuner_status;
+
+       if (priv->i2c_props.adap == NULL)
+               return -EINVAL;
+
+       tuner_status = tuner_read_status(fe);
 
        *status = 0;
 
@@ -162,7 +184,12 @@ static int simple_get_status(struct dvb_frontend *fe, u32 *status)
 static int simple_get_rf_strength(struct dvb_frontend *fe, u16 *strength)
 {
        struct tuner_simple_priv *priv = fe->tuner_priv;
-       int signal = tuner_signal(tuner_read_status(fe));
+       int signal;
+
+       if (priv->i2c_props.adap == NULL)
+               return -EINVAL;
+
+       signal = tuner_signal(tuner_read_status(fe));
 
        *strength = signal;
 
@@ -173,174 +200,378 @@ static int simple_get_rf_strength(struct dvb_frontend *fe, u16 *strength)
 
 /* ---------------------------------------------------------------------- */
 
-static int simple_set_tv_freq(struct dvb_frontend *fe,
-                             struct analog_parameters *params)
+static inline char *tuner_param_name(enum param_type type)
 {
-       struct tuner_simple_priv *priv = fe->tuner_priv;
-       u8 config, cb, tuneraddr;
-       u16 div;
-       struct tunertype *tun;
-       u8 buffer[4];
-       int rc, IFPCoff, i, j;
-       enum param_type desired_type;
-       struct tuner_params *t_params;
+       char *name;
 
-       tun = priv->tun;
+       switch (type) {
+       case TUNER_PARAM_TYPE_RADIO:
+               name = "radio";
+               break;
+       case TUNER_PARAM_TYPE_PAL:
+               name = "pal";
+               break;
+       case TUNER_PARAM_TYPE_SECAM:
+               name = "secam";
+               break;
+       case TUNER_PARAM_TYPE_NTSC:
+               name = "ntsc";
+               break;
+       case TUNER_PARAM_TYPE_DIGITAL:
+               name = "digital";
+               break;
+       default:
+               name = "unknown";
+               break;
+       }
+       return name;
+}
 
-       /* IFPCoff = Video Intermediate Frequency - Vif:
-               940  =16*58.75  NTSC/J (Japan)
-               732  =16*45.75  M/N STD
-               704  =16*44     ATSC (at DVB code)
-               632  =16*39.50  I U.K.
-               622.4=16*38.90  B/G D/K I, L STD
-               592  =16*37.00  D China
-               590  =16.36.875 B Australia
-               543.2=16*33.95  L' STD
-               171.2=16*10.70  FM Radio (at set_radio_freq)
-       */
+static struct tuner_params *simple_tuner_params(struct dvb_frontend *fe,
+                                               enum param_type desired_type)
+{
+       struct tuner_simple_priv *priv = fe->tuner_priv;
+       struct tunertype *tun = priv->tun;
+       int i;
 
-       if (params->std == V4L2_STD_NTSC_M_JP) {
-               IFPCoff      = 940;
-               desired_type = TUNER_PARAM_TYPE_NTSC;
-       } else if ((params->std & V4L2_STD_MN) &&
-                 !(params->std & ~V4L2_STD_MN)) {
-               IFPCoff      = 732;
-               desired_type = TUNER_PARAM_TYPE_NTSC;
-       } else if (params->std == V4L2_STD_SECAM_LC) {
-               IFPCoff      = 543;
-               desired_type = TUNER_PARAM_TYPE_SECAM;
-       } else {
-               IFPCoff      = 623;
-               desired_type = TUNER_PARAM_TYPE_PAL;
-       }
+       for (i = 0; i < tun->count; i++)
+               if (desired_type == tun->params[i].type)
+                       break;
 
-       for (j = 0; j < tun->count-1; j++) {
-               if (desired_type != tun->params[j].type)
-                       continue;
-               break;
-       }
-       /* use default tuner_t_params if desired_type not available */
-       if (desired_type != tun->params[j].type) {
-               tuner_dbg("IFPCoff = %d: tuner_t_params undefined for tuner %d\n",
-                         IFPCoff, priv->type);
-               j = 0;
+       /* use default tuner params if desired_type not available */
+       if (i == tun->count) {
+               tuner_dbg("desired params (%s) undefined for tuner %d\n",
+                         tuner_param_name(desired_type), priv->type);
+               i = 0;
        }
-       t_params = &tun->params[j];
+
+       tuner_dbg("using tuner params #%d (%s)\n", i,
+                 tuner_param_name(tun->params[i].type));
+
+       return &tun->params[i];
+}
+
+static int simple_config_lookup(struct dvb_frontend *fe,
+                               struct tuner_params *t_params,
+                               int *frequency, u8 *config, u8 *cb)
+{
+       struct tuner_simple_priv *priv = fe->tuner_priv;
+       int i;
 
        for (i = 0; i < t_params->count; i++) {
-               if (params->frequency > t_params->ranges[i].limit)
+               if (*frequency > t_params->ranges[i].limit)
                        continue;
                break;
        }
        if (i == t_params->count) {
-               tuner_dbg("TV frequency out of range (%d > %d)",
-                               params->frequency, t_params->ranges[i - 1].limit);
-               params->frequency = t_params->ranges[--i].limit;
+               tuner_dbg("frequency out of range (%d > %d)\n",
+                         *frequency, t_params->ranges[i - 1].limit);
+               *frequency = t_params->ranges[--i].limit;
        }
-       config = t_params->ranges[i].config;
-       cb     = t_params->ranges[i].cb;
-       /*  i == 0 -> VHF_LO
-        *  i == 1 -> VHF_HI
-        *  i == 2 -> UHF     */
-       tuner_dbg("tv: param %d, range %d\n",j,i);
+       *config = t_params->ranges[i].config;
+       *cb     = t_params->ranges[i].cb;
+
+       tuner_dbg("freq = %d.%02d (%d), range = %d, "
+                 "config = 0x%02x, cb = 0x%02x\n",
+                 *frequency / 16, *frequency % 16 * 100 / 16, *frequency,
+                 i, *config, *cb);
+
+       return i;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void simple_set_rf_input(struct dvb_frontend *fe,
+                               u8 *config, u8 *cb, unsigned int rf)
+{
+       struct tuner_simple_priv *priv = fe->tuner_priv;
 
-       div=params->frequency + IFPCoff + offset;
+       switch (priv->type) {
+       case TUNER_PHILIPS_TUV1236D:
+               switch (rf) {
+               case 1:
+                       *cb |= 0x08;
+                       break;
+               default:
+                       *cb &= ~0x08;
+                       break;
+               }
+               break;
+       case TUNER_PHILIPS_FCV1236D:
+               switch (rf) {
+               case 1:
+                       *cb |= 0x01;
+                       break;
+               default:
+                       *cb &= ~0x01;
+                       break;
+               }
+               break;
+       default:
+               break;
+       }
+}
 
-       tuner_dbg("Freq= %d.%02d MHz, V_IF=%d.%02d MHz, Offset=%d.%02d MHz, div=%0d\n",
-                                       params->frequency / 16, params->frequency % 16 * 100 / 16,
-                                       IFPCoff / 16, IFPCoff % 16 * 100 / 16,
-                                       offset / 16, offset % 16 * 100 / 16,
-                                       div);
+static int simple_std_setup(struct dvb_frontend *fe,
+                           struct analog_parameters *params,
+                           u8 *config, u8 *cb)
+{
+       struct tuner_simple_priv *priv = fe->tuner_priv;
+       u8 tuneraddr;
+       int rc;
 
        /* tv norm specific stuff for multi-norm tuners */
        switch (priv->type) {
-       case TUNER_PHILIPS_SECAM: // FI1216MF
+       case TUNER_PHILIPS_SECAM: /* FI1216MF */
                /* 0x01 -> ??? no change ??? */
                /* 0x02 -> PAL BDGHI / SECAM L */
                /* 0x04 -> ??? PAL others / SECAM others ??? */
-               cb &= ~0x03;
-               if (params->std & V4L2_STD_SECAM_L) //also valid for V4L2_STD_SECAM
-                       cb |= PHILIPS_MF_SET_STD_L;
+               *cb &= ~0x03;
+               if (params->std & V4L2_STD_SECAM_L)
+                       /* also valid for V4L2_STD_SECAM */
+                       *cb |= PHILIPS_MF_SET_STD_L;
                else if (params->std & V4L2_STD_SECAM_LC)
-                       cb |= PHILIPS_MF_SET_STD_LC;
+                       *cb |= PHILIPS_MF_SET_STD_LC;
                else /* V4L2_STD_B|V4L2_STD_GH */
-                       cb |= PHILIPS_MF_SET_STD_BG;
+                       *cb |= PHILIPS_MF_SET_STD_BG;
                break;
 
        case TUNER_TEMIC_4046FM5:
-               cb &= ~0x0f;
+               *cb &= ~0x0f;
 
                if (params->std & V4L2_STD_PAL_BG) {
-                       cb |= TEMIC_SET_PAL_BG;
+                       *cb |= TEMIC_SET_PAL_BG;
 
                } else if (params->std & V4L2_STD_PAL_I) {
-                       cb |= TEMIC_SET_PAL_I;
+                       *cb |= TEMIC_SET_PAL_I;
 
                } else if (params->std & V4L2_STD_PAL_DK) {
-                       cb |= TEMIC_SET_PAL_DK;
+                       *cb |= TEMIC_SET_PAL_DK;
 
                } else if (params->std & V4L2_STD_SECAM_L) {
-                       cb |= TEMIC_SET_PAL_L;
+                       *cb |= TEMIC_SET_PAL_L;
 
                }
                break;
 
        case TUNER_PHILIPS_FQ1216ME:
-               cb &= ~0x0f;
+               *cb &= ~0x0f;
 
                if (params->std & (V4L2_STD_PAL_BG|V4L2_STD_PAL_DK)) {
-                       cb |= PHILIPS_SET_PAL_BGDK;
+                       *cb |= PHILIPS_SET_PAL_BGDK;
 
                } else if (params->std & V4L2_STD_PAL_I) {
-                       cb |= PHILIPS_SET_PAL_I;
+                       *cb |= PHILIPS_SET_PAL_I;
 
                } else if (params->std & V4L2_STD_SECAM_L) {
-                       cb |= PHILIPS_SET_PAL_L;
+                       *cb |= PHILIPS_SET_PAL_L;
 
                }
                break;
 
-       case TUNER_PHILIPS_ATSC:
+       case TUNER_PHILIPS_FCV1236D:
                /* 0x00 -> ATSC antenna input 1 */
                /* 0x01 -> ATSC antenna input 2 */
                /* 0x02 -> NTSC antenna input 1 */
                /* 0x03 -> NTSC antenna input 2 */
-               cb &= ~0x03;
+               *cb &= ~0x03;
                if (!(params->std & V4L2_STD_ATSC))
-                       cb |= 2;
-               /* FIXME: input */
+                       *cb |= 2;
                break;
 
        case TUNER_MICROTUNE_4042FI5:
                /* Set the charge pump for fast tuning */
-               config |= TUNER_CHARGE_PUMP;
+               *config |= TUNER_CHARGE_PUMP;
                break;
 
        case TUNER_PHILIPS_TUV1236D:
+       {
                /* 0x40 -> ATSC antenna input 1 */
                /* 0x48 -> ATSC antenna input 2 */
                /* 0x00 -> NTSC antenna input 1 */
                /* 0x08 -> NTSC antenna input 2 */
-               buffer[0] = 0x14;
-               buffer[1] = 0x00;
-               buffer[2] = 0x17;
-               buffer[3] = 0x00;
-               cb &= ~0x40;
+               u8 buffer[4] = { 0x14, 0x00, 0x17, 0x00};
+               *cb &= ~0x40;
                if (params->std & V4L2_STD_ATSC) {
-                       cb |= 0x40;
+                       *cb |= 0x40;
                        buffer[1] = 0x04;
                }
                /* set to the correct mode (analog or digital) */
                tuneraddr = priv->i2c_props.addr;
                priv->i2c_props.addr = 0x0a;
-               if (2 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,&buffer[0],2)))
-                       tuner_warn("i2c i/o error: rc == %d (should be 2)\n",rc);
-               if (2 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,&buffer[2],2)))
-                       tuner_warn("i2c i/o error: rc == %d (should be 2)\n",rc);
+               rc = tuner_i2c_xfer_send(&priv->i2c_props, &buffer[0], 2);
+               if (2 != rc)
+                       tuner_warn("i2c i/o error: rc == %d "
+                                  "(should be 2)\n", rc);
+               rc = tuner_i2c_xfer_send(&priv->i2c_props, &buffer[2], 2);
+               if (2 != rc)
+                       tuner_warn("i2c i/o error: rc == %d "
+                                  "(should be 2)\n", rc);
                priv->i2c_props.addr = tuneraddr;
-               /* FIXME: input */
                break;
        }
+       }
+       if (atv_input[priv->nr])
+               simple_set_rf_input(fe, config, cb, atv_input[priv->nr]);
+
+       return 0;
+}
+
+static int simple_post_tune(struct dvb_frontend *fe, u8 *buffer,
+                           u16 div, u8 config, u8 cb)
+{
+       struct tuner_simple_priv *priv = fe->tuner_priv;
+       int rc;
+
+       switch (priv->type) {
+       case TUNER_LG_TDVS_H06XF:
+               /* Set the Auxiliary Byte. */
+               buffer[0] = buffer[2];
+               buffer[0] &= ~0x20;
+               buffer[0] |= 0x18;
+               buffer[1] = 0x20;
+               tuner_dbg("tv 0x%02x 0x%02x\n", buffer[0], buffer[1]);
+
+               rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 2);
+               if (2 != rc)
+                       tuner_warn("i2c i/o error: rc == %d "
+                                  "(should be 2)\n", rc);
+               break;
+       case TUNER_MICROTUNE_4042FI5:
+       {
+               /* FIXME - this may also work for other tuners */
+               unsigned long timeout = jiffies + msecs_to_jiffies(1);
+               u8 status_byte = 0;
+
+               /* Wait until the PLL locks */
+               for (;;) {
+                       if (time_after(jiffies, timeout))
+                               return 0;
+                       rc = tuner_i2c_xfer_recv(&priv->i2c_props,
+                                                &status_byte, 1);
+                       if (1 != rc) {
+                               tuner_warn("i2c i/o read error: rc == %d "
+                                          "(should be 1)\n", rc);
+                               break;
+                       }
+                       if (status_byte & TUNER_PLL_LOCKED)
+                               break;
+                       udelay(10);
+               }
+
+               /* Set the charge pump for optimized phase noise figure */
+               config &= ~TUNER_CHARGE_PUMP;
+               buffer[0] = (div>>8) & 0x7f;
+               buffer[1] = div      & 0xff;
+               buffer[2] = config;
+               buffer[3] = cb;
+               tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n",
+                         buffer[0], buffer[1], buffer[2], buffer[3]);
+
+               rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 4);
+               if (4 != rc)
+                       tuner_warn("i2c i/o error: rc == %d "
+                                  "(should be 4)\n", rc);
+               break;
+       }
+       }
+
+       return 0;
+}
+
+static int simple_radio_bandswitch(struct dvb_frontend *fe, u8 *buffer)
+{
+       struct tuner_simple_priv *priv = fe->tuner_priv;
+
+       switch (priv->type) {
+       case TUNER_TENA_9533_DI:
+       case TUNER_YMEC_TVF_5533MF:
+               tuner_dbg("This tuner doesn't have FM. "
+                         "Most cards have a TEA5767 for FM\n");
+               return 0;
+       case TUNER_PHILIPS_FM1216ME_MK3:
+       case TUNER_PHILIPS_FM1236_MK3:
+       case TUNER_PHILIPS_FMD1216ME_MK3:
+       case TUNER_LG_NTSC_TAPE:
+       case TUNER_PHILIPS_FM1256_IH3:
+               buffer[3] = 0x19;
+               break;
+       case TUNER_TNF_5335MF:
+               buffer[3] = 0x11;
+               break;
+       case TUNER_LG_PAL_FM:
+               buffer[3] = 0xa5;
+               break;
+       case TUNER_THOMSON_DTT761X:
+               buffer[3] = 0x39;
+               break;
+       case TUNER_MICROTUNE_4049FM5:
+       default:
+               buffer[3] = 0xa4;
+               break;
+       }
+
+       return 0;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static int simple_set_tv_freq(struct dvb_frontend *fe,
+                             struct analog_parameters *params)
+{
+       struct tuner_simple_priv *priv = fe->tuner_priv;
+       u8 config, cb;
+       u16 div;
+       struct tunertype *tun;
+       u8 buffer[4];
+       int rc, IFPCoff, i;
+       enum param_type desired_type;
+       struct tuner_params *t_params;
+
+       tun = priv->tun;
+
+       /* IFPCoff = Video Intermediate Frequency - Vif:
+               940  =16*58.75  NTSC/J (Japan)
+               732  =16*45.75  M/N STD
+               704  =16*44     ATSC (at DVB code)
+               632  =16*39.50  I U.K.
+               622.4=16*38.90  B/G D/K I, L STD
+               592  =16*37.00  D China
+               590  =16.36.875 B Australia
+               543.2=16*33.95  L' STD
+               171.2=16*10.70  FM Radio (at set_radio_freq)
+       */
+
+       if (params->std == V4L2_STD_NTSC_M_JP) {
+               IFPCoff      = 940;
+               desired_type = TUNER_PARAM_TYPE_NTSC;
+       } else if ((params->std & V4L2_STD_MN) &&
+                 !(params->std & ~V4L2_STD_MN)) {
+               IFPCoff      = 732;
+               desired_type = TUNER_PARAM_TYPE_NTSC;
+       } else if (params->std == V4L2_STD_SECAM_LC) {
+               IFPCoff      = 543;
+               desired_type = TUNER_PARAM_TYPE_SECAM;
+       } else {
+               IFPCoff      = 623;
+               desired_type = TUNER_PARAM_TYPE_PAL;
+       }
+
+       t_params = simple_tuner_params(fe, desired_type);
+
+       i = simple_config_lookup(fe, t_params, &params->frequency,
+                                &config, &cb);
+
+       div = params->frequency + IFPCoff + offset;
+
+       tuner_dbg("Freq= %d.%02d MHz, V_IF=%d.%02d MHz, "
+                 "Offset=%d.%02d MHz, div=%0d\n",
+                 params->frequency / 16, params->frequency % 16 * 100 / 16,
+                 IFPCoff / 16, IFPCoff % 16 * 100 / 16,
+                 offset / 16, offset % 16 * 100 / 16, div);
+
+       /* tv norm specific stuff for multi-norm tuners */
+       simple_std_setup(fe, params, &config, &cb);
 
        if (t_params->cb_first_if_lower_freq && div < priv->last_div) {
                buffer[0] = config;
@@ -357,8 +588,10 @@ static int simple_set_tv_freq(struct dvb_frontend *fe,
        if (t_params->has_tda9887) {
                struct v4l2_priv_tun_config tda9887_cfg;
                int config = 0;
-               int is_secam_l = (params->std & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC)) &&
-                       !(params->std & ~(V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC));
+               int is_secam_l = (params->std & (V4L2_STD_SECAM_L |
+                                                V4L2_STD_SECAM_LC)) &&
+                       !(params->std & ~(V4L2_STD_SECAM_L |
+                                         V4L2_STD_SECAM_LC));
 
                tda9887_cfg.tuner = TUNER_TDA9887;
                tda9887_cfg.priv  = &config;
@@ -368,8 +601,7 @@ static int simple_set_tv_freq(struct dvb_frontend *fe,
                                config |= TDA9887_PORT1_ACTIVE;
                        if (t_params->port2_active ^ t_params->port2_invert_for_secam_lc)
                                config |= TDA9887_PORT2_ACTIVE;
-               }
-               else {
+               } else {
                        if (t_params->port1_active)
                                config |= TDA9887_PORT1_ACTIVE;
                        if (t_params->port2_active)
@@ -384,8 +616,7 @@ static int simple_set_tv_freq(struct dvb_frontend *fe,
                                config |= TDA9887_TOP(t_params->default_top_secam_mid);
                        else if (t_params->default_top_secam_high)
                                config |= TDA9887_TOP(t_params->default_top_secam_high);
-               }
-               else {
+               } else {
                        if (i == 0 && t_params->default_top_low)
                                config |= TDA9887_TOP(t_params->default_top_low);
                        else if (i == 1 && t_params->default_top_mid)
@@ -399,56 +630,14 @@ static int simple_set_tv_freq(struct dvb_frontend *fe,
                                    &tda9887_cfg);
        }
        tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n",
-                 buffer[0],buffer[1],buffer[2],buffer[3]);
-
-       if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,buffer,4)))
-               tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc);
-
-       switch (priv->type) {
-       case TUNER_LG_TDVS_H06XF:
-               /* Set the Auxiliary Byte. */
-               buffer[0] = buffer[2];
-               buffer[0] &= ~0x20;
-               buffer[0] |= 0x18;
-               buffer[1] = 0x20;
-               tuner_dbg("tv 0x%02x 0x%02x\n",buffer[0],buffer[1]);
-
-               if (2 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,buffer,2)))
-                       tuner_warn("i2c i/o error: rc == %d (should be 2)\n",rc);
-               break;
-       case TUNER_MICROTUNE_4042FI5:
-       {
-               // FIXME - this may also work for other tuners
-               unsigned long timeout = jiffies + msecs_to_jiffies(1);
-               u8 status_byte = 0;
+                 buffer[0], buffer[1], buffer[2], buffer[3]);
 
-               /* Wait until the PLL locks */
-               for (;;) {
-                       if (time_after(jiffies,timeout))
-                               return 0;
-                       if (1 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props,&status_byte,1))) {
-                               tuner_warn("i2c i/o read error: rc == %d (should be 1)\n",rc);
-                               break;
-                       }
-                       if (status_byte & TUNER_PLL_LOCKED)
-                               break;
-                       udelay(10);
-               }
+       rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 4);
+       if (4 != rc)
+               tuner_warn("i2c i/o error: rc == %d (should be 4)\n", rc);
 
-               /* Set the charge pump for optimized phase noise figure */
-               config &= ~TUNER_CHARGE_PUMP;
-               buffer[0] = (div>>8) & 0x7f;
-               buffer[1] = div      & 0xff;
-               buffer[2] = config;
-               buffer[3] = cb;
-               tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n",
-                         buffer[0],buffer[1],buffer[2],buffer[3]);
+       simple_post_tune(fe, &buffer[0], div, config, cb);
 
-               if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,buffer,4)))
-                       tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc);
-               break;
-       }
-       }
        return 0;
 }
 
@@ -483,37 +672,13 @@ static int simple_set_radio_freq(struct dvb_frontend *fe,
                freq += (unsigned int)(41.3*16000);
                break;
        default:
-               tuner_warn("Unsupported radio_if value %d\n", t_params->radio_if);
+               tuner_warn("Unsupported radio_if value %d\n",
+                          t_params->radio_if);
                return 0;
        }
 
        /* Bandswitch byte */
-       switch (priv->type) {
-       case TUNER_TENA_9533_DI:
-       case TUNER_YMEC_TVF_5533MF:
-               tuner_dbg("This tuner doesn't have FM. Most cards have a TEA5767 for FM\n");
-               return 0;
-       case TUNER_PHILIPS_FM1216ME_MK3:
-       case TUNER_PHILIPS_FM1236_MK3:
-       case TUNER_PHILIPS_FMD1216ME_MK3:
-       case TUNER_LG_NTSC_TAPE:
-       case TUNER_PHILIPS_FM1256_IH3:
-               buffer[3] = 0x19;
-               break;
-       case TUNER_TNF_5335MF:
-               buffer[3] = 0x11;
-               break;
-       case TUNER_LG_PAL_FM:
-               buffer[3] = 0xa5;
-               break;
-       case TUNER_THOMSON_DTT761X:
-               buffer[3] = 0x39;
-               break;
-       case TUNER_MICROTUNE_4049FM5:
-       default:
-               buffer[3] = 0xa4;
-               break;
-       }
+       simple_radio_bandswitch(fe, &buffer[0]);
 
        buffer[2] = (t_params->ranges[0].config & ~TUNER_RATIO_MASK) |
                    TUNER_RATIO_SELECT_50; /* 50 kHz step */
@@ -534,7 +699,7 @@ static int simple_set_radio_freq(struct dvb_frontend *fe,
        }
 
        tuner_dbg("radio 0x%02x 0x%02x 0x%02x 0x%02x\n",
-              buffer[0],buffer[1],buffer[2],buffer[3]);
+              buffer[0], buffer[1], buffer[2], buffer[3]);
        priv->last_div = div;
 
        if (t_params->has_tda9887) {
@@ -544,9 +709,11 @@ static int simple_set_radio_freq(struct dvb_frontend *fe,
                tda9887_cfg.tuner = TUNER_TDA9887;
                tda9887_cfg.priv = &config;
 
-               if (t_params->port1_active && !t_params->port1_fm_high_sensitivity)
+               if (t_params->port1_active &&
+                   !t_params->port1_fm_high_sensitivity)
                        config |= TDA9887_PORT1_ACTIVE;
-               if (t_params->port2_active && !t_params->port2_fm_high_sensitivity)
+               if (t_params->port2_active &&
+                   !t_params->port2_fm_high_sensitivity)
                        config |= TDA9887_PORT2_ACTIVE;
                if (t_params->intercarrier_mode)
                        config |= TDA9887_INTERCARRIER;
@@ -557,10 +724,11 @@ static int simple_set_radio_freq(struct dvb_frontend *fe,
                if (t_params->radio_if == 2)
                        config |= TDA9887_RIF_41_3;
                i2c_clients_command(priv->i2c_props.adap, TUNER_SET_CONFIG,
-                                       &tda9887_cfg);
+                                   &tda9887_cfg);
        }
-       if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,buffer,4)))
-               tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc);
+       rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 4);
+       if (4 != rc)
+               tuner_warn("i2c i/o error: rc == %d (should be 4)\n", rc);
 
        return 0;
 }
@@ -571,6 +739,9 @@ static int simple_set_params(struct dvb_frontend *fe,
        struct tuner_simple_priv *priv = fe->tuner_priv;
        int ret = -EINVAL;
 
+       if (priv->i2c_props.adap == NULL)
+               return -EINVAL;
+
        switch (params->mode) {
        case V4L2_TUNER_RADIO:
                ret = simple_set_radio_freq(fe, params);
@@ -582,14 +753,210 @@ static int simple_set_params(struct dvb_frontend *fe,
                priv->frequency = params->frequency * 62500;
                break;
        }
+       priv->bandwidth = 0;
 
        return ret;
 }
 
+static void simple_set_dvb(struct dvb_frontend *fe, u8 *buf,
+                          const struct dvb_frontend_parameters *params)
+{
+       struct tuner_simple_priv *priv = fe->tuner_priv;
+
+       switch (priv->type) {
+       case TUNER_PHILIPS_FMD1216ME_MK3:
+               if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ &&
+                   params->frequency >= 158870000)
+                       buf[3] |= 0x08;
+               break;
+       case TUNER_PHILIPS_TD1316:
+               /* determine band */
+               buf[3] |= (params->frequency < 161000000) ? 1 :
+                         (params->frequency < 444000000) ? 2 : 4;
+
+               /* setup PLL filter */
+               if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ)
+                       buf[3] |= 1 << 3;
+               break;
+       case TUNER_PHILIPS_TUV1236D:
+       case TUNER_PHILIPS_FCV1236D:
+       {
+               unsigned int new_rf;
+
+               if (dtv_input[priv->nr])
+                       new_rf = dtv_input[priv->nr];
+               else
+                       switch (params->u.vsb.modulation) {
+                       case QAM_64:
+                       case QAM_256:
+                               new_rf = 1;
+                               break;
+                       case VSB_8:
+                       default:
+                               new_rf = 0;
+                               break;
+                       }
+               simple_set_rf_input(fe, &buf[2], &buf[3], new_rf);
+               break;
+       }
+       default:
+               break;
+       }
+}
+
+static u32 simple_dvb_configure(struct dvb_frontend *fe, u8 *buf,
+                               const struct dvb_frontend_parameters *params)
+{
+       /* This function returns the tuned frequency on success, 0 on error */
+       struct tuner_simple_priv *priv = fe->tuner_priv;
+       struct tunertype *tun = priv->tun;
+       static struct tuner_params *t_params;
+       u8 config, cb;
+       u32 div;
+       int ret, frequency = params->frequency / 62500;
+
+       t_params = simple_tuner_params(fe, TUNER_PARAM_TYPE_DIGITAL);
+       ret = simple_config_lookup(fe, t_params, &frequency, &config, &cb);
+       if (ret < 0)
+               return 0; /* failure */
+
+       div = ((frequency + t_params->iffreq) * 62500 + offset +
+              tun->stepsize/2) / tun->stepsize;
+
+       buf[0] = div >> 8;
+       buf[1] = div & 0xff;
+       buf[2] = config;
+       buf[3] = cb;
+
+       simple_set_dvb(fe, buf, params);
+
+       tuner_dbg("%s: div=%d | buf=0x%02x,0x%02x,0x%02x,0x%02x\n",
+                 tun->name, div, buf[0], buf[1], buf[2], buf[3]);
+
+       /* calculate the frequency we set it to */
+       return (div * tun->stepsize) - t_params->iffreq;
+}
+
+static int simple_dvb_calc_regs(struct dvb_frontend *fe,
+                               struct dvb_frontend_parameters *params,
+                               u8 *buf, int buf_len)
+{
+       struct tuner_simple_priv *priv = fe->tuner_priv;
+       u32 frequency;
+
+       if (buf_len < 5)
+               return -EINVAL;
+
+       frequency = simple_dvb_configure(fe, buf+1, params);
+       if (frequency == 0)
+               return -EINVAL;
+
+       buf[0] = priv->i2c_props.addr;
+
+       priv->frequency = frequency;
+       priv->bandwidth = (fe->ops.info.type == FE_OFDM) ?
+               params->u.ofdm.bandwidth : 0;
+
+       return 5;
+}
+
+static int simple_dvb_set_params(struct dvb_frontend *fe,
+                                struct dvb_frontend_parameters *params)
+{
+       struct tuner_simple_priv *priv = fe->tuner_priv;
+       u32 prev_freq, prev_bw;
+       int ret;
+       u8 buf[5];
+
+       if (priv->i2c_props.adap == NULL)
+               return -EINVAL;
+
+       prev_freq = priv->frequency;
+       prev_bw   = priv->bandwidth;
+
+       ret = simple_dvb_calc_regs(fe, params, buf, 5);
+       if (ret != 5)
+               goto fail;
+
+       /* put analog demod in standby when tuning digital */
+       if (fe->ops.analog_ops.standby)
+               fe->ops.analog_ops.standby(fe);
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+
+       /* buf[0] contains the i2c address, but *
+        * we already have it in i2c_props.addr */
+       ret = tuner_i2c_xfer_send(&priv->i2c_props, buf+1, 4);
+       if (ret != 4)
+               goto fail;
+
+       return 0;
+fail:
+       /* calc_regs sets frequency and bandwidth. if we failed, unset them */
+       priv->frequency = prev_freq;
+       priv->bandwidth = prev_bw;
+
+       return ret;
+}
+
+static int simple_init(struct dvb_frontend *fe)
+{
+       struct tuner_simple_priv *priv = fe->tuner_priv;
+
+       if (priv->i2c_props.adap == NULL)
+               return -EINVAL;
+
+       if (priv->tun->initdata) {
+               int ret;
+
+               if (fe->ops.i2c_gate_ctrl)
+                       fe->ops.i2c_gate_ctrl(fe, 1);
+
+               ret = tuner_i2c_xfer_send(&priv->i2c_props,
+                                         priv->tun->initdata + 1,
+                                         priv->tun->initdata[0]);
+               if (ret != priv->tun->initdata[0])
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int simple_sleep(struct dvb_frontend *fe)
+{
+       struct tuner_simple_priv *priv = fe->tuner_priv;
+
+       if (priv->i2c_props.adap == NULL)
+               return -EINVAL;
+
+       if (priv->tun->sleepdata) {
+               int ret;
+
+               if (fe->ops.i2c_gate_ctrl)
+                       fe->ops.i2c_gate_ctrl(fe, 1);
+
+               ret = tuner_i2c_xfer_send(&priv->i2c_props,
+                                         priv->tun->sleepdata + 1,
+                                         priv->tun->sleepdata[0]);
+               if (ret != priv->tun->sleepdata[0])
+                       return ret;
+       }
+
+       return 0;
+}
 
 static int simple_release(struct dvb_frontend *fe)
 {
-       kfree(fe->tuner_priv);
+       struct tuner_simple_priv *priv = fe->tuner_priv;
+
+       mutex_lock(&tuner_simple_list_mutex);
+
+       if (priv)
+               hybrid_tuner_release_state(priv);
+
+       mutex_unlock(&tuner_simple_list_mutex);
+
        fe->tuner_priv = NULL;
 
        return 0;
@@ -602,10 +969,22 @@ static int simple_get_frequency(struct dvb_frontend *fe, u32 *frequency)
        return 0;
 }
 
+static int simple_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+{
+       struct tuner_simple_priv *priv = fe->tuner_priv;
+       *bandwidth = priv->bandwidth;
+       return 0;
+}
+
 static struct dvb_tuner_ops simple_tuner_ops = {
+       .init              = simple_init,
+       .sleep             = simple_sleep,
        .set_analog_params = simple_set_params,
+       .set_params        = simple_dvb_set_params,
+       .calc_regs         = simple_dvb_calc_regs,
        .release           = simple_release,
        .get_frequency     = simple_get_frequency,
+       .get_bandwidth     = simple_get_bandwidth,
        .get_status        = simple_get_status,
        .get_rf_strength   = simple_get_rf_strength,
 };
@@ -613,30 +992,92 @@ static struct dvb_tuner_ops simple_tuner_ops = {
 struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe,
                                         struct i2c_adapter *i2c_adap,
                                         u8 i2c_addr,
-                                        struct simple_tuner_config *cfg)
+                                        unsigned int type)
 {
        struct tuner_simple_priv *priv = NULL;
+       int instance;
 
-       priv = kzalloc(sizeof(struct tuner_simple_priv), GFP_KERNEL);
-       if (priv == NULL)
+       if (type >= tuner_count) {
+               printk(KERN_WARNING "%s: invalid tuner type: %d (max: %d)\n",
+                      __func__, type, tuner_count-1);
                return NULL;
-       fe->tuner_priv = priv;
+       }
 
-       priv->i2c_props.addr = i2c_addr;
-       priv->i2c_props.adap = i2c_adap;
-       priv->type = cfg->type;
-       priv->tun  = cfg->tun;
+       /* If i2c_adap is set, check that the tuner is at the correct address.
+        * Otherwise, if i2c_adap is NULL, the tuner will be programmed directly
+        * by the digital demod via calc_regs.
+        */
+       if (i2c_adap != NULL) {
+               u8 b[1];
+               struct i2c_msg msg = {
+                       .addr = i2c_addr, .flags = I2C_M_RD,
+                       .buf = b, .len = 1,
+               };
+
+               if (fe->ops.i2c_gate_ctrl)
+                       fe->ops.i2c_gate_ctrl(fe, 1);
+
+               if (1 != i2c_transfer(i2c_adap, &msg, 1))
+                       tuner_warn("unable to probe %s, proceeding anyway.",
+                                  tuners[type].name);
+
+               if (fe->ops.i2c_gate_ctrl)
+                       fe->ops.i2c_gate_ctrl(fe, 0);
+       }
 
-       memcpy(&fe->ops.tuner_ops, &simple_tuner_ops, sizeof(struct dvb_tuner_ops));
+       mutex_lock(&tuner_simple_list_mutex);
 
-       tuner_info("type set to %d (%s)\n", cfg->type, cfg->tun->name);
+       instance = hybrid_tuner_request_state(struct tuner_simple_priv, priv,
+                                             hybrid_tuner_instance_list,
+                                             i2c_adap, i2c_addr,
+                                             "tuner-simple");
+       switch (instance) {
+       case 0:
+               mutex_unlock(&tuner_simple_list_mutex);
+               return NULL;
+               break;
+       case 1:
+               fe->tuner_priv = priv;
 
-       strlcpy(fe->ops.tuner_ops.info.name, cfg->tun->name, sizeof(fe->ops.tuner_ops.info.name));
+               priv->type = type;
+               priv->tun  = &tuners[type];
+               priv->nr   = simple_devcount++;
+               break;
+       default:
+               fe->tuner_priv = priv;
+               break;
+       }
 
-       return fe;
-}
+       mutex_unlock(&tuner_simple_list_mutex);
+
+       memcpy(&fe->ops.tuner_ops, &simple_tuner_ops,
+              sizeof(struct dvb_tuner_ops));
+
+       tuner_info("type set to %d (%s)\n", type, priv->tun->name);
+
+       if ((debug) || ((atv_input[priv->nr] > 0) ||
+                       (dtv_input[priv->nr] > 0))) {
+               if (0 == atv_input[priv->nr])
+                       tuner_info("tuner %d atv rf input will be "
+                                  "autoselected\n", priv->nr);
+               else
+                       tuner_info("tuner %d atv rf input will be "
+                                  "set to input %d (insmod option)\n",
+                                  priv->nr, atv_input[priv->nr]);
+               if (0 == dtv_input[priv->nr])
+                       tuner_info("tuner %d dtv rf input will be "
+                                  "autoselected\n", priv->nr);
+               else
+                       tuner_info("tuner %d dtv rf input will be "
+                                  "set to input %d (insmod option)\n",
+                                  priv->nr, dtv_input[priv->nr]);
+       }
 
+       strlcpy(fe->ops.tuner_ops.info.name, priv->tun->name,
+               sizeof(fe->ops.tuner_ops.info.name));
 
+       return fe;
+}
 EXPORT_SYMBOL_GPL(simple_tuner_attach);
 
 MODULE_DESCRIPTION("Simple 4-control-bytes style tuner driver");
index 9089939a8c0214e9b71c177f7880936efd14edb5..e46cf0121e030a23e314190116567550f9c7ff7e 100644 (file)
 #include <linux/i2c.h>
 #include "dvb_frontend.h"
 
-struct simple_tuner_config
-{
-       /* chip type */
-       unsigned int type;
-       struct tunertype *tun;
-};
-
 #if defined(CONFIG_TUNER_SIMPLE) || (defined(CONFIG_TUNER_SIMPLE_MODULE) && defined(MODULE))
 extern struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe,
                                                struct i2c_adapter *i2c_adap,
                                                u8 i2c_addr,
-                                               struct simple_tuner_config *cfg);
+                                               unsigned int type);
 #else
 static inline struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe,
                                                       struct i2c_adapter *i2c_adap,
                                                       u8 i2c_addr,
-                                                      struct simple_tuner_config *cfg)
+                                                      unsigned int type)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif
index 883047f9c28c32f66eb7c98a5b080dcf92bc6e06..10dddca8b5d1817ede0be39bab500c2841c5ea4e 100644 (file)
  *     based on the video standard in use.
  */
 
+/* The following was taken from dvb-pll.c: */
+
+/* Set AGC TOP value to 103 dBuV:
+ *     0x80 = Control Byte
+ *     0x40 = 250 uA charge pump (irrelevant)
+ *     0x18 = Aux Byte to follow
+ *     0x06 = 64.5 kHz divider (irrelevant)
+ *     0x01 = Disable Vt (aka sleep)
+ *
+ *     0x00 = AGC Time constant 2s Iagc = 300 nA (vs 0x80 = 9 nA)
+ *     0x50 = AGC Take over point = 103 dBuV
+ */
+static u8 tua603x_agc103[] = { 2, 0x80|0x40|0x18|0x06|0x01, 0x00|0x50 };
+
+/*     0x04 = 166.67 kHz divider
+ *
+ *     0x80 = AGC Time constant 50ms Iagc = 9 uA
+ *     0x20 = AGC Take over point = 112 dBuV
+ */
+static u8 tua603x_agc112[] = { 2, 0x80|0x40|0x18|0x04|0x01, 0x80|0x20 };
+
 /* 0-9 */
 /* ------------ TUNER_TEMIC_PAL - TEMIC PAL ------------ */
 
@@ -594,19 +615,31 @@ static struct tuner_params tuner_philips_pal_mk_params[] = {
        },
 };
 
-/* ---- TUNER_PHILIPS_ATSC - Philips FCV1236D (ATSC/NTSC) ---- */
+/* ---- TUNER_PHILIPS_FCV1236D - Philips FCV1236D (ATSC/NTSC) ---- */
 
-static struct tuner_range tuner_philips_fcv1236d_ranges[] = {
-       { 16 * 157.25 /*MHz*/, 0x8e, 0xa0, },
-       { 16 * 451.25 /*MHz*/, 0x8e, 0x90, },
+static struct tuner_range tuner_philips_fcv1236d_ntsc_ranges[] = {
+       { 16 * 157.25 /*MHz*/, 0x8e, 0xa2, },
+       { 16 * 451.25 /*MHz*/, 0x8e, 0x92, },
+       { 16 * 999.99        , 0x8e, 0x32, },
+};
+
+static struct tuner_range tuner_philips_fcv1236d_atsc_ranges[] = {
+       { 16 * 159.00 /*MHz*/, 0x8e, 0xa0, },
+       { 16 * 453.00 /*MHz*/, 0x8e, 0x90, },
        { 16 * 999.99        , 0x8e, 0x30, },
 };
 
 static struct tuner_params tuner_philips_fcv1236d_params[] = {
        {
                .type   = TUNER_PARAM_TYPE_NTSC,
-               .ranges = tuner_philips_fcv1236d_ranges,
-               .count  = ARRAY_SIZE(tuner_philips_fcv1236d_ranges),
+               .ranges = tuner_philips_fcv1236d_ntsc_ranges,
+               .count  = ARRAY_SIZE(tuner_philips_fcv1236d_ntsc_ranges),
+       },
+       {
+               .type   = TUNER_PARAM_TYPE_DIGITAL,
+               .ranges = tuner_philips_fcv1236d_atsc_ranges,
+               .count  = ARRAY_SIZE(tuner_philips_fcv1236d_atsc_ranges),
+               .iffreq = 16 * 44.00,
        },
 };
 
@@ -701,12 +734,24 @@ static struct tuner_range tuner_microtune_4042fi5_ntsc_ranges[] = {
        { 16 * 999.99        , 0x8e, 0x31, },
 };
 
+static struct tuner_range tuner_microtune_4042fi5_atsc_ranges[] = {
+       { 16 * 162.00 /*MHz*/, 0x8e, 0xa1, },
+       { 16 * 457.00 /*MHz*/, 0x8e, 0x91, },
+       { 16 * 999.99        , 0x8e, 0x31, },
+};
+
 static struct tuner_params tuner_microtune_4042fi5_params[] = {
        {
                .type   = TUNER_PARAM_TYPE_NTSC,
                .ranges = tuner_microtune_4042fi5_ntsc_ranges,
                .count  = ARRAY_SIZE(tuner_microtune_4042fi5_ntsc_ranges),
        },
+       {
+               .type   = TUNER_PARAM_TYPE_DIGITAL,
+               .ranges = tuner_microtune_4042fi5_atsc_ranges,
+               .count  = ARRAY_SIZE(tuner_microtune_4042fi5_atsc_ranges),
+               .iffreq = 16 * 44.00 /*MHz*/,
+       },
 };
 
 /* 50-59 */
@@ -740,6 +785,7 @@ static struct tuner_params tuner_philips_fm1256_ih3_params[] = {
 
 /* ------------ TUNER_THOMSON_DTT7610 - THOMSON ATSC ------------ */
 
+/* single range used for both ntsc and atsc */
 static struct tuner_range tuner_thomson_dtt7610_ntsc_ranges[] = {
        { 16 * 157.25 /*MHz*/, 0x8e, 0x39, },
        { 16 * 454.00 /*MHz*/, 0x8e, 0x3a, },
@@ -752,6 +798,12 @@ static struct tuner_params tuner_thomson_dtt7610_params[] = {
                .ranges = tuner_thomson_dtt7610_ntsc_ranges,
                .count  = ARRAY_SIZE(tuner_thomson_dtt7610_ntsc_ranges),
        },
+       {
+               .type   = TUNER_PARAM_TYPE_DIGITAL,
+               .ranges = tuner_thomson_dtt7610_ntsc_ranges,
+               .count  = ARRAY_SIZE(tuner_thomson_dtt7610_ntsc_ranges),
+               .iffreq = 16 * 44.00 /*MHz*/,
+       },
 };
 
 /* ------------ TUNER_PHILIPS_FQ1286 - Philips NTSC ------------ */
@@ -855,6 +907,11 @@ static struct tuner_range tuner_thomson_dtt761x_ntsc_ranges[] = {
        { 16 * 999.99        , 0x8e, 0x3c, },
 };
 
+static struct tuner_range tuner_thomson_dtt761x_atsc_ranges[] = {
+       { 16 * 147.00 /*MHz*/, 0x8e, 0x39, },
+       { 16 * 417.00 /*MHz*/, 0x8e, 0x3a, },
+       { 16 * 999.99        , 0x8e, 0x3c, },
+};
 
 static struct tuner_params tuner_thomson_dtt761x_params[] = {
        {
@@ -865,6 +922,12 @@ static struct tuner_params tuner_thomson_dtt761x_params[] = {
                .fm_gain_normal = 1,
                .radio_if = 2, /* 41.3 MHz */
        },
+       {
+               .type   = TUNER_PARAM_TYPE_DIGITAL,
+               .ranges = tuner_thomson_dtt761x_atsc_ranges,
+               .count  = ARRAY_SIZE(tuner_thomson_dtt761x_atsc_ranges),
+               .iffreq = 16 * 44.00, /*MHz*/
+       },
 };
 
 /* ------------ TUNER_TENA_9533_DI - Philips PAL ------------ */
@@ -891,6 +954,15 @@ static struct tuner_range tuner_philips_fmd1216me_mk3_pal_ranges[] = {
        { 16 * 999.99        , 0x86, 0x54, },
 };
 
+static struct tuner_range tuner_philips_fmd1216me_mk3_dvb_ranges[] = {
+       { 16 * 143.87 /*MHz*/, 0xbc, 0x41 },
+       { 16 * 158.87 /*MHz*/, 0xf4, 0x41 },
+       { 16 * 329.87 /*MHz*/, 0xbc, 0x42 },
+       { 16 * 441.87 /*MHz*/, 0xf4, 0x42 },
+       { 16 * 625.87 /*MHz*/, 0xbc, 0x44 },
+       { 16 * 803.87 /*MHz*/, 0xf4, 0x44 },
+       { 16 * 999.99        , 0xfc, 0x44 },
+};
 
 static struct tuner_params tuner_philips_fmd1216me_mk3_params[] = {
        {
@@ -904,6 +976,12 @@ static struct tuner_params tuner_philips_fmd1216me_mk3_params[] = {
                .port2_invert_for_secam_lc = 1,
                .port1_set_for_fm_mono = 1,
        },
+       {
+               .type   = TUNER_PARAM_TYPE_DIGITAL,
+               .ranges = tuner_philips_fmd1216me_mk3_dvb_ranges,
+               .count  = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_dvb_ranges),
+               .iffreq = 16 * 36.125, /*MHz*/
+       },
 };
 
 
@@ -915,6 +993,11 @@ static struct tuner_range tuner_tua6034_ntsc_ranges[] = {
        { 16 * 999.99        , 0x8e, 0x04 },
 };
 
+static struct tuner_range tuner_tua6034_atsc_ranges[] = {
+       { 16 * 165.00 /*MHz*/, 0xce, 0x01 },
+       { 16 * 450.00 /*MHz*/, 0xce, 0x02 },
+       { 16 * 999.99        , 0xce, 0x04 },
+};
 
 static struct tuner_params tuner_lg_tdvs_h06xf_params[] = {
        {
@@ -922,6 +1005,12 @@ static struct tuner_params tuner_lg_tdvs_h06xf_params[] = {
                .ranges = tuner_tua6034_ntsc_ranges,
                .count  = ARRAY_SIZE(tuner_tua6034_ntsc_ranges),
        },
+       {
+               .type   = TUNER_PARAM_TYPE_DIGITAL,
+               .ranges = tuner_tua6034_atsc_ranges,
+               .count  = ARRAY_SIZE(tuner_tua6034_atsc_ranges),
+               .iffreq = 16 * 44.00,
+       },
 };
 
 /* ------------ TUNER_YMEC_TVF66T5_B_DFF - Philips PAL ------------ */
@@ -974,12 +1063,30 @@ static struct tuner_range tuner_philips_td1316_pal_ranges[] = {
        { 16 * 999.99        , 0xc8, 0xa4, },
 };
 
+static struct tuner_range tuner_philips_td1316_dvb_ranges[] = {
+       { 16 *  93.834 /*MHz*/, 0xca, 0x60, },
+       { 16 * 123.834 /*MHz*/, 0xca, 0xa0, },
+       { 16 * 163.834 /*MHz*/, 0xca, 0xc0, },
+       { 16 * 253.834 /*MHz*/, 0xca, 0x60, },
+       { 16 * 383.834 /*MHz*/, 0xca, 0xa0, },
+       { 16 * 443.834 /*MHz*/, 0xca, 0xc0, },
+       { 16 * 583.834 /*MHz*/, 0xca, 0x60, },
+       { 16 * 793.834 /*MHz*/, 0xca, 0xa0, },
+       { 16 * 999.999        , 0xca, 0xe0, },
+};
+
 static struct tuner_params tuner_philips_td1316_params[] = {
        {
                .type   = TUNER_PARAM_TYPE_PAL,
                .ranges = tuner_philips_td1316_pal_ranges,
                .count  = ARRAY_SIZE(tuner_philips_td1316_pal_ranges),
        },
+       {
+               .type   = TUNER_PARAM_TYPE_DIGITAL,
+               .ranges = tuner_philips_td1316_dvb_ranges,
+               .count  = ARRAY_SIZE(tuner_philips_td1316_dvb_ranges),
+               .iffreq = 16 * 36.166667 /*MHz*/,
+       },
 };
 
 /* ------------ TUNER_PHILIPS_TUV1236D - Philips ATSC ------------ */
@@ -990,6 +1097,11 @@ static struct tuner_range tuner_tuv1236d_ntsc_ranges[] = {
        { 16 * 999.99        , 0xce, 0x04, },
 };
 
+static struct tuner_range tuner_tuv1236d_atsc_ranges[] = {
+       { 16 * 157.25 /*MHz*/, 0xc6, 0x41, },
+       { 16 * 454.00 /*MHz*/, 0xc6, 0x42, },
+       { 16 * 999.99        , 0xc6, 0x44, },
+};
 
 static struct tuner_params tuner_tuv1236d_params[] = {
        {
@@ -997,6 +1109,12 @@ static struct tuner_params tuner_tuv1236d_params[] = {
                .ranges = tuner_tuv1236d_ntsc_ranges,
                .count  = ARRAY_SIZE(tuner_tuv1236d_ntsc_ranges),
        },
+       {
+               .type   = TUNER_PARAM_TYPE_DIGITAL,
+               .ranges = tuner_tuv1236d_atsc_ranges,
+               .count  = ARRAY_SIZE(tuner_tuv1236d_atsc_ranges),
+               .iffreq = 16 * 44.00,
+       },
 };
 
 /* ------------ TUNER_TNF_xxx5  - Texas Instruments--------- */
@@ -1050,17 +1168,30 @@ static struct tuner_params tuner_samsung_tcpn_2121p30a_params[] = {
 
 /* ------------ TUNER_THOMSON_FE6600 - DViCO Hybrid PAL ------------ */
 
-static struct tuner_range tuner_thomson_fe6600_ranges[] = {
+static struct tuner_range tuner_thomson_fe6600_pal_ranges[] = {
        { 16 * 160.00 /*MHz*/, 0xfe, 0x11, },
        { 16 * 442.00 /*MHz*/, 0xf6, 0x12, },
        { 16 * 999.99        , 0xf6, 0x18, },
 };
 
+static struct tuner_range tuner_thomson_fe6600_dvb_ranges[] = {
+       { 16 * 250.00 /*MHz*/, 0xb4, 0x12, },
+       { 16 * 455.00 /*MHz*/, 0xfe, 0x11, },
+       { 16 * 775.50 /*MHz*/, 0xbc, 0x18, },
+       { 16 * 999.99        , 0xf4, 0x18, },
+};
+
 static struct tuner_params tuner_thomson_fe6600_params[] = {
        {
                .type   = TUNER_PARAM_TYPE_PAL,
-               .ranges = tuner_thomson_fe6600_ranges,
-               .count  = ARRAY_SIZE(tuner_thomson_fe6600_ranges),
+               .ranges = tuner_thomson_fe6600_pal_ranges,
+               .count  = ARRAY_SIZE(tuner_thomson_fe6600_pal_ranges),
+       },
+       {
+               .type   = TUNER_PARAM_TYPE_DIGITAL,
+               .ranges = tuner_thomson_fe6600_dvb_ranges,
+               .count  = ARRAY_SIZE(tuner_thomson_fe6600_dvb_ranges),
+               .iffreq = 16 * 36.125 /*MHz*/,
        },
 };
 
@@ -1303,10 +1434,13 @@ struct tunertype tuners[] = {
                .params = tuner_philips_pal_mk_params,
                .count  = ARRAY_SIZE(tuner_philips_pal_mk_params),
        },
-       [TUNER_PHILIPS_ATSC] = { /* Philips ATSC */
+       [TUNER_PHILIPS_FCV1236D] = { /* Philips ATSC */
                .name   = "Philips FCV1236D ATSC/NTSC dual in",
                .params = tuner_philips_fcv1236d_params,
                .count  = ARRAY_SIZE(tuner_philips_fcv1236d_params),
+               .min = 16 *  53.00,
+               .max = 16 * 803.00,
+               .stepsize = 62500,
        },
        [TUNER_PHILIPS_FM1236_MK3] = { /* Philips NTSC */
                .name   = "Philips NTSC MK3 (FM1236MK3 or FM1236/F)",
@@ -1342,6 +1476,9 @@ struct tunertype tuners[] = {
                .name   = "Microtune 4042 FI5 ATSC/NTSC dual in",
                .params = tuner_microtune_4042fi5_params,
                .count  = ARRAY_SIZE(tuner_microtune_4042fi5_params),
+               .min    = 16 *  57.00,
+               .max    = 16 * 858.00,
+               .stepsize = 62500,
        },
 
        /* 50-59 */
@@ -1359,6 +1496,9 @@ struct tunertype tuners[] = {
                .name   = "Thomson DTT 7610 (ATSC/NTSC)",
                .params = tuner_thomson_dtt7610_params,
                .count  = ARRAY_SIZE(tuner_thomson_dtt7610_params),
+               .min    = 16 *  44.00,
+               .max    = 16 * 958.00,
+               .stepsize = 62500,
        },
        [TUNER_PHILIPS_FQ1286] = { /* Philips NTSC */
                .name   = "Philips FQ1286",
@@ -1400,6 +1540,10 @@ struct tunertype tuners[] = {
                .name   = "Thomson DTT 761X (ATSC/NTSC)",
                .params = tuner_thomson_dtt761x_params,
                .count  = ARRAY_SIZE(tuner_thomson_dtt761x_params),
+               .min    = 16 *  57.00,
+               .max    = 16 * 863.00,
+               .stepsize = 62500,
+               .initdata = tua603x_agc103,
        },
        [TUNER_TENA_9533_DI] = { /* Philips PAL */
                .name   = "Tena TNF9533-D/IF/TNF9533-B/DF",
@@ -1414,11 +1558,20 @@ struct tunertype tuners[] = {
                .name   = "Philips FMD1216ME MK3 Hybrid Tuner",
                .params = tuner_philips_fmd1216me_mk3_params,
                .count  = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_params),
+               .min = 16 *  50.87,
+               .max = 16 * 858.00,
+               .stepsize = 166667,
+               .initdata = tua603x_agc112,
+               .sleepdata = (u8[]){ 4, 0x9c, 0x60, 0x85, 0x54 },
        },
        [TUNER_LG_TDVS_H06XF] = { /* LGINNOTEK ATSC */
                .name   = "LG TDVS-H06xF", /* H061F, H062F & H064F */
                .params = tuner_lg_tdvs_h06xf_params,
                .count  = ARRAY_SIZE(tuner_lg_tdvs_h06xf_params),
+               .min    = 16 *  54.00,
+               .max    = 16 * 863.00,
+               .stepsize = 62500,
+               .initdata = tua603x_agc103,
        },
        [TUNER_YMEC_TVF66T5_B_DFF] = { /* Philips PAL */
                .name   = "Ymec TVF66T5-B/DFF",
@@ -1434,11 +1587,17 @@ struct tunertype tuners[] = {
                .name   = "Philips TD1316 Hybrid Tuner",
                .params = tuner_philips_td1316_params,
                .count  = ARRAY_SIZE(tuner_philips_td1316_params),
+               .min    = 16 *  87.00,
+               .max    = 16 * 895.00,
+               .stepsize = 166667,
        },
        [TUNER_PHILIPS_TUV1236D] = { /* Philips ATSC */
                .name   = "Philips TUV1236D ATSC/NTSC dual in",
                .params = tuner_tuv1236d_params,
                .count  = ARRAY_SIZE(tuner_tuv1236d_params),
+               .min    = 16 *  54.00,
+               .max    = 16 * 864.00,
+               .stepsize = 62500,
        },
        [TUNER_TNF_5335MF] = { /* Tenna PAL/NTSC */
                .name   = "Tena TNF 5335 and similar models",
@@ -1460,6 +1619,9 @@ struct tunertype tuners[] = {
                .name   = "Thomson FE6600",
                .params = tuner_thomson_fe6600_params,
                .count  = ARRAY_SIZE(tuner_thomson_fe6600_params),
+               .min    = 16 *  44.25,
+               .max    = 16 * 858.00,
+               .stepsize = 166667,
        },
        [TUNER_SAMSUNG_TCPG_6121P30A] = { /* Samsung PAL */
                .name   = "Samsung TCPG 6121P30A",
@@ -1480,5 +1642,11 @@ struct tunertype tuners[] = {
                /* see xc5000.c for details */
        },
 };
+EXPORT_SYMBOL(tuners);
 
 unsigned const int tuner_count = ARRAY_SIZE(tuners);
+EXPORT_SYMBOL(tuner_count);
+
+MODULE_DESCRIPTION("Simple tuner device type database");
+MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer");
+MODULE_LICENSE("GPL");
index d0057fbf0ec72e9569a92b30121961663e371e3a..74dc46a71f64555c07bb67be9ee09facf822ad41 100644 (file)
@@ -1,6 +1,9 @@
 /* tuner-xc2028_types
  *
- * Copyright (c) 2007 Mauro Carvalho Chehab (mchehab@infradead.org)
+ * This file includes internal tipes to be used inside tuner-xc2028.
+ * Shouldn't be included outside tuner-xc2028
+ *
+ * Copyright (c) 2007-2008 Mauro Carvalho Chehab (mchehab@infradead.org)
  * This code is placed under the terms of the GNU General Public License v2
  */
 
 /* LCD firmwares exist only for MTS STD/MN (PAL or NTSC/M)
        and for non-MTS STD/MN (PAL, NTSC/M or NTSC/Kr)
        There are variants both with and without NOGD
+       Those firmwares produce better result with LCD displays
  */
 #define LCD            (1<<12)
 
 /* NOGD firmwares exist only for MTS STD/MN (PAL or NTSC/M)
        and for non-MTS STD/MN (PAL, NTSC/M or NTSC/Kr)
+       The NOGD firmwares don't have group delay compensation filter
  */
 #define NOGD           (1<<13)
 
 /* This flag identifies that the scode table has a new format */
 #define HAS_IF         (1 << 30)
 
-#define SCODE_TYPES    (MTS|DTV6|QAM|DTV7|DTV78|DTV8|LCD|NOGD|MONO|ATSC|IF| \
-                        LG60|ATI638|OREN538|OREN36|TOYOTA388|TOYOTA794|     \
-                        DIBCOM52|ZARLINK456|CHINA|F6MHZ|SCODE)
+/* There are different scode tables for MTS and non-MTS.
+   The MTS firmwares support mono only
+  */
+#define SCODE_TYPES (SCODE | MTS)
+
 
-/* Newer types to be moved to videodev2.h */
+/* Newer types not defined on videodev2.h.
+   The original idea were to move all those types to videodev2.h, but
+   it seemed overkill, since, with the exception of SECAM/K3, the other
+   types seem to be autodetected.
+   It is not clear where secam/k3 is used, nor we have a feedback of this
+   working or being autodetected by the standard secam firmware.
+ */
 
 #define V4L2_STD_SECAM_K3      (0x04000000)
 
index 50cf876f020f40659929821f5c560fb58b5b8cbf..cc3db7d79a0d195adc386205621f617ecbb57ac4 100644 (file)
@@ -1,6 +1,6 @@
 /* tuner-xc2028
  *
- * Copyright (c) 2007 Mauro Carvalho Chehab (mchehab@infradead.org)
+ * Copyright (c) 2007-2008 Mauro Carvalho Chehab (mchehab@infradead.org)
  *
  * Copyright (c) 2007 Michel Ludwig (michel.ludwig@gmail.com)
  *       - frontend interface
@@ -23,8 +23,6 @@
 #include "dvb_frontend.h"
 
 
-#define PREFIX "xc2028"
-
 static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "enable verbose debug messages");
@@ -43,6 +41,11 @@ MODULE_PARM_DESC(audio_std,
        "NICAM/A\n"
        "NICAM/B\n");
 
+static char firmware_name[FIRMWARE_NAME_MAX];
+module_param_string(firmware_name, firmware_name, sizeof(firmware_name), 0);
+MODULE_PARM_DESC(firmware_name, "Firmware file name. Allows overriding the "
+                               "default firmware name\n");
+
 static LIST_HEAD(xc2028_list);
 static DEFINE_MUTEX(xc2028_list_mutex);
 
@@ -127,12 +130,12 @@ struct xc2028_data {
        _rc;                                                            \
 })
 
-static unsigned int xc2028_get_reg(struct xc2028_data *priv, u16 reg, u16 *val)
+static int xc2028_get_reg(struct xc2028_data *priv, u16 reg, u16 *val)
 {
        unsigned char buf[2];
        unsigned char ibuf[2];
 
-       tuner_dbg("%s %04x called\n", __FUNCTION__, reg);
+       tuner_dbg("%s %04x called\n", __func__, reg);
 
        buf[0] = reg >> 8;
        buf[1] = (unsigned char) reg;
@@ -145,7 +148,7 @@ static unsigned int xc2028_get_reg(struct xc2028_data *priv, u16 reg, u16 *val)
 }
 
 #define dump_firm_type(t)      dump_firm_type_and_int_freq(t, 0)
-void dump_firm_type_and_int_freq(unsigned int type, u16 int_freq)
+static void dump_firm_type_and_int_freq(unsigned int type, u16 int_freq)
 {
         if (type & BASE)
                printk("BASE ");
@@ -232,6 +235,7 @@ static  v4l2_std_id parse_audio_std_option(void)
 static void free_firmware(struct xc2028_data *priv)
 {
        int i;
+       tuner_dbg("%s called\n", __func__);
 
        if (!priv->firm)
                return;
@@ -255,19 +259,24 @@ static int load_all_firmwares(struct dvb_frontend *fe)
        int                   rc = 0;
        int                   n, n_array;
        char                  name[33];
+       char                  *fname;
+
+       tuner_dbg("%s called\n", __func__);
 
-       tuner_dbg("%s called\n", __FUNCTION__);
+       if (!firmware_name[0])
+               fname = priv->ctrl.fname;
+       else
+               fname = firmware_name;
 
-       tuner_dbg("Reading firmware %s\n", priv->ctrl.fname);
-       rc = request_firmware(&fw, priv->ctrl.fname,
-                             &priv->i2c_props.adap->dev);
+       tuner_dbg("Reading firmware %s\n", fname);
+       rc = request_firmware(&fw, fname, &priv->i2c_props.adap->dev);
        if (rc < 0) {
                if (rc == -ENOENT)
                        tuner_err("Error: firmware %s not found.\n",
-                                  priv->ctrl.fname);
+                                  fname);
                else
                        tuner_err("Error %d while requesting firmware %s \n",
-                                  rc, priv->ctrl.fname);
+                                  rc, fname);
 
                return rc;
        }
@@ -276,7 +285,7 @@ static int load_all_firmwares(struct dvb_frontend *fe)
 
        if (fw->size < sizeof(name) - 1 + 2 + 2) {
                tuner_err("Error: firmware file %s has invalid size!\n",
-                         priv->ctrl.fname);
+                         fname);
                goto corrupt;
        }
 
@@ -291,7 +300,7 @@ static int load_all_firmwares(struct dvb_frontend *fe)
        p += 2;
 
        tuner_info("Loading %d firmware images from %s, type: %s, ver %d.%d\n",
-                  n_array, priv->ctrl.fname, name,
+                  n_array, fname, name,
                   priv->firm_version >> 8, priv->firm_version & 0xff);
 
        priv->firm = kzalloc(sizeof(*priv->firm) * n_array, GFP_KERNEL);
@@ -395,9 +404,9 @@ static int seek_firmware(struct dvb_frontend *fe, unsigned int type,
 {
        struct xc2028_data *priv = fe->tuner_priv;
        int                 i, best_i = -1, best_nr_matches = 0;
-       unsigned int        ign_firm_type_mask = 0;
+       unsigned int        type_mask = 0;
 
-       tuner_dbg("%s called, want type=", __FUNCTION__);
+       tuner_dbg("%s called, want type=", __func__);
        if (debug) {
                dump_firm_type(type);
                printk("(%x), id %016llx.\n", type, (unsigned long long)*id);
@@ -412,18 +421,23 @@ static int seek_firmware(struct dvb_frontend *fe, unsigned int type,
                *id = V4L2_STD_PAL;
 
        if (type & BASE)
-               type &= BASE_TYPES;
+               type_mask = BASE_TYPES;
        else if (type & SCODE) {
                type &= SCODE_TYPES;
-               ign_firm_type_mask = HAS_IF;
+               type_mask = SCODE_TYPES & ~HAS_IF;
        } else if (type & DTV_TYPES)
-               type &= DTV_TYPES;
+               type_mask = DTV_TYPES;
        else if (type & STD_SPECIFIC_TYPES)
-               type &= STD_SPECIFIC_TYPES;
+               type_mask = STD_SPECIFIC_TYPES;
+
+       type &= type_mask;
+
+       if (!type & SCODE)
+               type_mask = ~0;
 
        /* Seek for exact match */
        for (i = 0; i < priv->firm_size; i++) {
-               if ((type == (priv->firm[i].type & ~ign_firm_type_mask)) &&
+               if ((type == (priv->firm[i].type & type_mask)) &&
                    (*id == priv->firm[i].id))
                        goto found;
        }
@@ -433,7 +447,7 @@ static int seek_firmware(struct dvb_frontend *fe, unsigned int type,
                v4l2_std_id match_mask;
                int nr_matches;
 
-               if (type != (priv->firm[i].type & ~ign_firm_type_mask))
+               if (type != (priv->firm[i].type & type_mask))
                        continue;
 
                match_mask = *id & priv->firm[i].id;
@@ -483,7 +497,7 @@ static int load_firmware(struct dvb_frontend *fe, unsigned int type,
        int                pos, rc;
        unsigned char      *p, *endp, buf[priv->ctrl.max_len];
 
-       tuner_dbg("%s called\n", __FUNCTION__);
+       tuner_dbg("%s called\n", __func__);
 
        pos = seek_firmware(fe, type, id);
        if (pos < 0)
@@ -586,7 +600,7 @@ static int load_scode(struct dvb_frontend *fe, unsigned int type,
        int                pos, rc;
        unsigned char      *p;
 
-       tuner_dbg("%s called\n", __FUNCTION__);
+       tuner_dbg("%s called\n", __func__);
 
        if (!int_freq) {
                pos = seek_firmware(fe, type, id);
@@ -650,7 +664,7 @@ static int check_firmware(struct dvb_frontend *fe, unsigned int type,
        u16                        version, hwmodel;
        v4l2_std_id                std0;
 
-       tuner_dbg("%s called\n", __FUNCTION__);
+       tuner_dbg("%s called\n", __func__);
 
        if (!priv->firm) {
                if (!priv->ctrl.fname) {
@@ -770,10 +784,10 @@ check_device:
                goto fail;
        }
 
-       tuner_info("Device is Xceive %d version %d.%d, "
-                  "firmware version %d.%d\n",
-                  hwmodel, (version & 0xf000) >> 12, (version & 0xf00) >> 8,
-                  (version & 0xf0) >> 4, version & 0xf);
+       tuner_dbg("Device is Xceive %d version %d.%d, "
+                 "firmware version %d.%d\n",
+                 hwmodel, (version & 0xf000) >> 12, (version & 0xf00) >> 8,
+                 (version & 0xf0) >> 4, version & 0xf);
 
        /* Check firmware version against what we downloaded. */
        if (priv->firm_version != ((version & 0xf0) << 4 | (version & 0x0f))) {
@@ -824,27 +838,34 @@ static int xc2028_signal(struct dvb_frontend *fe, u16 *strength)
        u16                 frq_lock, signal = 0;
        int                 rc;
 
-       tuner_dbg("%s called\n", __FUNCTION__);
+       tuner_dbg("%s called\n", __func__);
 
        mutex_lock(&priv->lock);
 
        /* Sync Lock Indicator */
        rc = xc2028_get_reg(priv, 0x0002, &frq_lock);
-       if (rc < 0 || frq_lock == 0)
+       if (rc < 0)
                goto ret;
 
-       /* Frequency is locked. Return signal quality */
+       /* Frequency is locked */
+       if (frq_lock == 1)
+               signal = 32768;
 
        /* Get SNR of the video signal */
        rc = xc2028_get_reg(priv, 0x0040, &signal);
        if (rc < 0)
-               signal = -frq_lock;
+               goto ret;
+
+       /* Use both frq_lock and signal to generate the result */
+       signal = signal || ((signal & 0x07) << 12);
 
 ret:
        mutex_unlock(&priv->lock);
 
        *strength = signal;
 
+       tuner_dbg("signal strength is %d\n", signal);
+
        return rc;
 }
 
@@ -861,7 +882,7 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */,
        unsigned char      buf[4];
        u32                div, offset = 0;
 
-       tuner_dbg("%s called\n", __FUNCTION__);
+       tuner_dbg("%s called\n", __func__);
 
        mutex_lock(&priv->lock);
 
@@ -906,9 +927,11 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */,
        if (rc < 0)
                goto ret;
 
-       rc = priv->tuner_callback(priv->video_dev, XC2028_RESET_CLK, 1);
-       if (rc < 0)
-               goto ret;
+       /* Return code shouldn't be checked.
+          The reset CLK is needed only with tm6000.
+          Driver should work fine even if this fails.
+        */
+       priv->tuner_callback(priv->video_dev, XC2028_RESET_CLK, 1);
 
        msleep(10);
 
@@ -942,7 +965,7 @@ static int xc2028_set_analog_freq(struct dvb_frontend *fe,
        struct xc2028_data *priv = fe->tuner_priv;
        unsigned int       type=0;
 
-       tuner_dbg("%s called\n", __FUNCTION__);
+       tuner_dbg("%s called\n", __func__);
 
        if (p->mode == V4L2_TUNER_RADIO) {
                type |= FM;
@@ -975,7 +998,7 @@ static int xc2028_set_params(struct dvb_frontend *fe,
        fe_bandwidth_t     bw = BANDWIDTH_8_MHZ;
        u16                demod = 0;
 
-       tuner_dbg("%s called\n", __FUNCTION__);
+       tuner_dbg("%s called\n", __func__);
 
        if (priv->ctrl.d2633)
                type |= D2633;
@@ -1040,33 +1063,12 @@ static int xc2028_set_params(struct dvb_frontend *fe,
                                T_DIGITAL_TV, type, 0, demod);
 }
 
-static int xc2028_sleep(struct dvb_frontend *fe)
-{
-       struct xc2028_data *priv = fe->tuner_priv;
-       int rc = 0;
-
-       tuner_dbg("%s called\n", __FUNCTION__);
-
-       mutex_lock(&priv->lock);
-
-       if (priv->firm_version < 0x0202)
-               rc = send_seq(priv, {0x00, 0x08, 0x00, 0x00});
-       else
-               rc = send_seq(priv, {0x80, 0x08, 0x00, 0x00});
-
-       priv->cur_fw.type = 0;  /* need firmware reload */
-
-       mutex_unlock(&priv->lock);
-
-       return rc;
-}
-
 
 static int xc2028_dvb_release(struct dvb_frontend *fe)
 {
        struct xc2028_data *priv = fe->tuner_priv;
 
-       tuner_dbg("%s called\n", __FUNCTION__);
+       tuner_dbg("%s called\n", __func__);
 
        mutex_lock(&xc2028_list_mutex);
 
@@ -1091,7 +1093,7 @@ static int xc2028_get_frequency(struct dvb_frontend *fe, u32 *frequency)
 {
        struct xc2028_data *priv = fe->tuner_priv;
 
-       tuner_dbg("%s called\n", __FUNCTION__);
+       tuner_dbg("%s called\n", __func__);
 
        *frequency = priv->frequency;
 
@@ -1104,25 +1106,25 @@ static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg)
        struct xc2028_ctrl *p    = priv_cfg;
        int                 rc   = 0;
 
-       tuner_dbg("%s called\n", __FUNCTION__);
+       tuner_dbg("%s called\n", __func__);
 
        mutex_lock(&priv->lock);
 
-       kfree(priv->ctrl.fname);
-       free_firmware(priv);
-
        memcpy(&priv->ctrl, p, sizeof(priv->ctrl));
-       priv->ctrl.fname = NULL;
+       if (priv->ctrl.max_len < 9)
+               priv->ctrl.max_len = 13;
 
        if (p->fname) {
+               if (priv->ctrl.fname && strcmp(p->fname, priv->ctrl.fname)) {
+                       kfree(priv->ctrl.fname);
+                       free_firmware(priv);
+               }
+
                priv->ctrl.fname = kstrdup(p->fname, GFP_KERNEL);
                if (priv->ctrl.fname == NULL)
                        rc = -ENOMEM;
        }
 
-       if (priv->ctrl.max_len < 9)
-               priv->ctrl.max_len = 13;
-
        mutex_unlock(&priv->lock);
 
        return rc;
@@ -1142,8 +1144,6 @@ static const struct dvb_tuner_ops xc2028_dvb_tuner_ops = {
        .get_frequency     = xc2028_get_frequency,
        .get_rf_strength   = xc2028_signal,
        .set_params        = xc2028_set_params,
-       .sleep             = xc2028_sleep,
-
 };
 
 struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
@@ -1153,23 +1153,29 @@ struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
        void               *video_dev;
 
        if (debug)
-               printk(KERN_DEBUG PREFIX ": Xcv2028/3028 init called!\n");
+               printk(KERN_DEBUG "xc2028: Xcv2028/3028 init called!\n");
 
-       if (NULL == cfg || NULL == cfg->video_dev)
+       if (NULL == cfg)
                return NULL;
 
        if (!fe) {
-               printk(KERN_ERR PREFIX ": No frontend!\n");
+               printk(KERN_ERR "xc2028: No frontend!\n");
                return NULL;
        }
 
-       video_dev = cfg->video_dev;
+       video_dev = cfg->i2c_adap->algo_data;
+
+       if (debug)
+               printk(KERN_DEBUG "xc2028: video_dev =%p\n", video_dev);
 
        mutex_lock(&xc2028_list_mutex);
 
        list_for_each_entry(priv, &xc2028_list, xc2028_list) {
-               if (priv->video_dev == cfg->video_dev) {
+               if (&priv->i2c_props.adap->dev == &cfg->i2c_adap->dev) {
                        video_dev = NULL;
+                       if (debug)
+                               printk(KERN_DEBUG "xc2028: reusing device\n");
+
                        break;
                }
        }
@@ -1183,6 +1189,8 @@ struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
 
                priv->i2c_props.addr = cfg->i2c_addr;
                priv->i2c_props.adap = cfg->i2c_adap;
+               priv->i2c_props.name = "xc2028";
+
                priv->video_dev = video_dev;
                priv->tuner_callback = cfg->callback;
                priv->ctrl.max_len = 13;
@@ -1195,6 +1203,9 @@ struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
        fe->tuner_priv = priv;
        priv->count++;
 
+       if (debug)
+               printk(KERN_DEBUG "xc2028: usage count is %i\n", priv->count);
+
        memcpy(&fe->ops.tuner_ops, &xc2028_dvb_tuner_ops,
               sizeof(xc2028_dvb_tuner_ops));
 
index 3eb8420379a42e29f108b65630082a7f1546366e..fc2f132a5541279e9c1b6089535dd42fd21fbb69 100644 (file)
@@ -1,6 +1,6 @@
 /* tuner-xc2028
  *
- * Copyright (c) 2007 Mauro Carvalho Chehab (mchehab@infradead.org)
+ * Copyright (c) 2007-2008 Mauro Carvalho Chehab (mchehab@infradead.org)
  * This code is placed under the terms of the GNU General Public License v2
  */
 
@@ -12,7 +12,7 @@
 #define XC2028_DEFAULT_FIRMWARE "xc3028-v27.fw"
 
 /*      Dmoduler               IF (kHz) */
-#define        XC3028_FE_DEFAULT       0
+#define        XC3028_FE_DEFAULT       0               /* Don't load SCODE */
 #define XC3028_FE_LG60         6000
 #define        XC3028_FE_ATI638        6380
 #define        XC3028_FE_OREN538       5380
@@ -55,7 +55,7 @@ static inline struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
                                                 struct xc2028_config *cfg)
 {
        printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n",
-              __FUNCTION__);
+              __func__);
        return NULL;
 }
 #endif
index 01ebcec040c4cee12cccb605085c1c3134ef3bfd..f29a2cd0f2f27c3db0afead3d5a7f65ba7f8fd56 100644 (file)
@@ -38,7 +38,7 @@
 /* ---------------------------------------------------------------------- */
 /* insmod args                                                            */
 
-static int debug = 0;  /* insmod parameter */
+static int debug;      /* insmod parameter */
 module_param(debug, int, 0644);
 
 MODULE_DESCRIPTION("device driver for various i2c TV sound decoder / audiomux chips");
@@ -1235,11 +1235,11 @@ static int tda9850  = 1;
 static int tda9855  = 1;
 static int tda9873  = 1;
 static int tda9874a = 1;
-static int tea6300  = 0;  /* address clash with msp34xx */
-static int tea6320  = 0;  /* address clash with msp34xx */
+static int tea6300;    /* default 0 - address clash with msp34xx */
+static int tea6320;    /* default 0 - address clash with msp34xx */
 static int tea6420  = 1;
 static int pic16c54 = 1;
-static int ta8874z  = 0;  /* address clash with tda9840 */
+static int ta8874z;    /* default 0 - address clash with tda9840 */
 
 module_param(tda8425, int, 0444);
 module_param(tda9840, int, 0444);
index dc0da44a5af636a1b0ae4b053b91c74bd36ea3c4..3cf8a8e801e5eb0ec2649b020e9fdc931c6f0363 100644 (file)
@@ -745,109 +745,6 @@ int tveeprom_read(struct i2c_client *c, unsigned char *eedata, int len)
 }
 EXPORT_SYMBOL(tveeprom_read);
 
-/* ----------------------------------------------------------------------- */
-/* needed for ivtv.sf.net at the moment.  Should go away in the long       */
-/* run, just call the exported tveeprom_* directly, there is no point in   */
-/* using the indirect way via i2c_driver->command()                        */
-
-static unsigned short normal_i2c[] = {
-       0xa0 >> 1,
-       I2C_CLIENT_END,
-};
-
-I2C_CLIENT_INSMOD;
-
-static struct i2c_driver i2c_driver_tveeprom;
-
-static int
-tveeprom_command(struct i2c_client *client,
-                unsigned int       cmd,
-                void              *arg)
-{
-       struct tveeprom eeprom;
-       u32 *eeprom_props = arg;
-       u8 *buf;
-
-       switch (cmd) {
-       case 0:
-               buf = kzalloc(256, GFP_KERNEL);
-               tveeprom_read(client, buf, 256);
-               tveeprom_hauppauge_analog(client, &eeprom, buf);
-               kfree(buf);
-               eeprom_props[0] = eeprom.tuner_type;
-               eeprom_props[1] = eeprom.tuner_formats;
-               eeprom_props[2] = eeprom.model;
-               eeprom_props[3] = eeprom.revision;
-               eeprom_props[4] = eeprom.has_radio;
-               break;
-       default:
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static int
-tveeprom_detect_client(struct i2c_adapter *adapter,
-                      int                 address,
-                      int                 kind)
-{
-       struct i2c_client *client;
-
-       client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
-       if (NULL == client)
-               return -ENOMEM;
-       client->addr = address;
-       client->adapter = adapter;
-       client->driver = &i2c_driver_tveeprom;
-       snprintf(client->name, sizeof(client->name), "tveeprom");
-       i2c_attach_client(client);
-
-       return 0;
-}
-
-static int
-tveeprom_attach_adapter(struct i2c_adapter *adapter)
-{
-       if (adapter->class & I2C_CLASS_TV_ANALOG)
-               return i2c_probe(adapter, &addr_data, tveeprom_detect_client);
-       return 0;
-}
-
-static int
-tveeprom_detach_client(struct i2c_client *client)
-{
-       int err;
-
-       err = i2c_detach_client(client);
-       if (err < 0)
-               return err;
-       kfree(client);
-       return 0;
-}
-
-static struct i2c_driver i2c_driver_tveeprom = {
-       .driver = {
-               .name   = "tveeprom",
-       },
-       .id             = I2C_DRIVERID_TVEEPROM,
-       .attach_adapter = tveeprom_attach_adapter,
-       .detach_client  = tveeprom_detach_client,
-       .command        = tveeprom_command,
-};
-
-static int __init tveeprom_init(void)
-{
-       return i2c_add_driver(&i2c_driver_tveeprom);
-}
-
-static void __exit tveeprom_exit(void)
-{
-       i2c_del_driver(&i2c_driver_tveeprom);
-}
-
-module_init(tveeprom_init);
-module_exit(tveeprom_exit);
-
 /*
  * Local variables:
  * c-basic-offset: 8
index b6e24e714a230c1e53e212687dd97b1140cf0f22..6a3af1005f03e365f654e826890b7c1b8524474e 100644 (file)
@@ -27,7 +27,7 @@ static unsigned short normal_i2c[] = {
 
 I2C_CLIENT_INSMOD;
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0-1)");
 
index 14db95e10cfee6d8828b9d607b94369ffbf0f449..59166b760104884b4d0573e61572fd9b40b2ebcd 100644 (file)
@@ -121,7 +121,7 @@ static int init_model2_yb = -1;
 
 /* 01.01.08 - Added for RCA video in support -LO */
 /* Settings for camera model 3 */
-static int init_model3_input = 0;
+static int init_model3_input;
 
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)");
@@ -802,6 +802,21 @@ static enum ParseState ibmcam_model2_320x240_parse_lines(
                return scan_Continue;
 }
 
+/*
+ * ibmcam_model3_parse_lines()
+ *
+ * | Even lines |     Odd Lines       |
+ * -----------------------------------|
+ * |YYY........Y|UYVYUYVY.........UYVY|
+ * |YYY........Y|UYVYUYVY.........UYVY|
+ * |............|.....................|
+ * |YYY........Y|UYVYUYVY.........UYVY|
+ * |------------+---------------------|
+ *
+ * There is one (U, V) chroma pair for every four luma (Y) values.  This
+ * function reads a pair of lines at a time and obtains missing chroma values
+ * from adjacent pixels.
+ */
 static enum ParseState ibmcam_model3_parse_lines(
        struct uvd *uvd,
        struct usbvideo_frame *frame,
@@ -816,6 +831,7 @@ static enum ParseState ibmcam_model3_parse_lines(
        const int ccm = 128; /* Color correction median - see below */
        int i, u, v, rw, data_w=0, data_h=0, color_corr;
        static unsigned char lineBuffer[640*3];
+       int line;
 
        color_corr = (uvd->vpic.colour - 0x8000) >> 8; /* -128..+127 = -ccm..+(ccm-1)*/
        RESTRICT_TO_RANGE(color_corr, -ccm, ccm+1);
@@ -869,15 +885,15 @@ static enum ParseState ibmcam_model3_parse_lines(
                return scan_NextFrame;
        }
 
-       /* Make sure there's enough data for the entire line */
-       len = 3 * data_w; /* <y-data> <uv-data> */
+       /* Make sure that lineBuffer can store two lines of data */
+       len = 3 * data_w; /* <y-data> <uyvy-data> */
        assert(len <= sizeof(lineBuffer));
 
-       /* Make sure there's enough data for the entire line */
+       /* Make sure there's enough data for two lines */
        if (RingQueue_GetLength(&uvd->dp) < len)
                return scan_Out;
 
-       /* Suck one line out of the ring queue */
+       /* Suck two lines of data out of the ring queue */
        RingQueue_Dequeue(&uvd->dp, lineBuffer, len);
 
        data = lineBuffer;
@@ -887,15 +903,23 @@ static enum ParseState ibmcam_model3_parse_lines(
        rw = (int)VIDEOSIZE_Y(frame->request) - (int)(frame->curline) - 1;
        RESTRICT_TO_RANGE(rw, 0, VIDEOSIZE_Y(frame->request)-1);
 
-       for (i = 0; i < VIDEOSIZE_X(frame->request); i++) {
-               int y, rv, gv, bv;      /* RGB components */
+       /* Iterate over two lines. */
+       for (line = 0; line < 2; line++) {
+               for (i = 0; i < VIDEOSIZE_X(frame->request); i++) {
+                       int y;
+                       int rv, gv, bv; /* RGB components */
 
-               if (i < data_w) {
-                       y = data[i];    /* Luminosity is the first line */
+                       if (i >= data_w) {
+                               RGB24_PUTPIXEL(frame, i, rw, 0, 0, 0);
+                               continue;
+                       }
+
+                       /* first line is YYY...Y; second is UYVY...UYVY */
+                       y = data[(line == 0) ? i : (i*2 + 1)];
 
                        /* Apply static color correction */
-                       u = color[i*2] + hue_corr;
-                       v = color[i*2 + 1] + hue2_corr;
+                       u = color[(i/2)*4] + hue_corr;
+                       v = color[(i/2)*4 + 2] + hue2_corr;
 
                        /* Apply color correction */
                        if (color_corr != 0) {
@@ -903,13 +927,21 @@ static enum ParseState ibmcam_model3_parse_lines(
                                u = 128 + ((ccm + color_corr) * (u - 128)) / ccm;
                                v = 128 + ((ccm + color_corr) * (v - 128)) / ccm;
                        }
-               } else
-                       y = 0, u = v = 128;
 
-               YUV_TO_RGB_BY_THE_BOOK(y, u, v, rv, gv, bv);
-               RGB24_PUTPIXEL(frame, i, rw, rv, gv, bv); /* Done by deinterlacing now */
+
+                       YUV_TO_RGB_BY_THE_BOOK(y, u, v, rv, gv, bv);
+                       RGB24_PUTPIXEL(frame, i, rw, rv, gv, bv);  /* No deinterlacing */
+               }
+
+               /* Check for the end of requested data */
+               if (rw == 0)
+                       break;
+
+               /* Prepare for the second line */
+               rw--;
+               data = lineBuffer + data_w;
        }
-       frame->deinterlace = Deinterlace_FillEvenLines;
+       frame->deinterlace = Deinterlace_None;
 
        /*
         * Account for number of bytes that we wrote into output V4L frame.
index 719b17ce83f832c87bf2ce50590af74d0a266bc0..1c180284ec6c2f35aa6fb3bd31e63ee97d562c0d 100644 (file)
@@ -57,11 +57,11 @@ static struct usbvideo *cams;
 static int debug;
 #define DEBUG(n, format, arg...) \
        if (n <= debug) {        \
-               printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __FUNCTION__ , ## arg); \
+               printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __func__ , ## arg); \
        }
 #else
 #define DEBUG(n, arg...)
-static const int debug = 0;
+static const int debug;
 #endif
 
 
index a2acba0bcc47586163bd4d82dffa91340354251b..32e536edf09d6cc594d4debb6c3f78c2082a1e42 100644 (file)
 static int debug;
 #define DEBUG(n, format, arg...) \
        if (n <= debug) {        \
-               printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __FUNCTION__ , ## arg); \
+               printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __func__ , ## arg); \
        }
 #else
 #define DEBUG(n, arg...)
-static const int debug = 0;
+static const int debug;
 #endif
 
 #define DRIVER_VERSION "v0.01"
index 95453c108d40e650de7c1ddfb14bb8e59916f59b..9544e644bf0de4bc6f01b8e22107d20809683657 100644 (file)
@@ -28,9 +28,9 @@ typedef struct {
 
 static struct usbvideo *cams = NULL;
 
-static int debug = 0;
+static int debug;
 
-static int flags = 0; /* FLAGS_DISPLAY_HINTS | FLAGS_OVERLAY_STATS; */
+static int flags; /* FLAGS_DISPLAY_HINTS | FLAGS_OVERLAY_STATS; */
 
 static const int min_canvasWidth  = 8;
 static const int min_canvasHeight = 4;
index 5d363be7bc735762475576cb9e7dc6db43f04b80..4128ee20b64e3eee52db9e720b44d2f143a63f2b 100644 (file)
@@ -522,14 +522,14 @@ void usbvideo_TestPattern(struct uvd *uvd, int fullframe, int pmode)
        struct usbvideo_frame *frame;
        int num_cell = 0;
        int scan_length = 0;
-       static int num_pass = 0;
+       static int num_pass;
 
        if (uvd == NULL) {
-               err("%s: uvd == NULL", __FUNCTION__);
+               err("%s: uvd == NULL", __func__);
                return;
        }
        if ((uvd->curframe < 0) || (uvd->curframe >= USBVIDEO_NUMFRAMES)) {
-               err("%s: uvd->curframe=%d.", __FUNCTION__, uvd->curframe);
+               err("%s: uvd->curframe=%d.", __func__, uvd->curframe);
                return;
        }
 
@@ -630,15 +630,15 @@ EXPORT_SYMBOL(usbvideo_HexDump);
 static int usbvideo_ClientIncModCount(struct uvd *uvd)
 {
        if (uvd == NULL) {
-               err("%s: uvd == NULL", __FUNCTION__);
+               err("%s: uvd == NULL", __func__);
                return -EINVAL;
        }
        if (uvd->handle == NULL) {
-               err("%s: uvd->handle == NULL", __FUNCTION__);
+               err("%s: uvd->handle == NULL", __func__);
                return -EINVAL;
        }
        if (!try_module_get(uvd->handle->md_module)) {
-               err("%s: try_module_get() == 0", __FUNCTION__);
+               err("%s: try_module_get() == 0", __func__);
                return -ENODEV;
        }
        return 0;
@@ -647,15 +647,15 @@ static int usbvideo_ClientIncModCount(struct uvd *uvd)
 static void usbvideo_ClientDecModCount(struct uvd *uvd)
 {
        if (uvd == NULL) {
-               err("%s: uvd == NULL", __FUNCTION__);
+               err("%s: uvd == NULL", __func__);
                return;
        }
        if (uvd->handle == NULL) {
-               err("%s: uvd->handle == NULL", __FUNCTION__);
+               err("%s: uvd->handle == NULL", __func__);
                return;
        }
        if (uvd->handle->md_module == NULL) {
-               err("%s: uvd->handle->md_module == NULL", __FUNCTION__);
+               err("%s: uvd->handle->md_module == NULL", __func__);
                return;
        }
        module_put(uvd->handle->md_module);
@@ -675,13 +675,13 @@ int usbvideo_register(
 
        /* Check parameters for sanity */
        if ((num_cams <= 0) || (pCams == NULL) || (cbTbl == NULL)) {
-               err("%s: Illegal call", __FUNCTION__);
+               err("%s: Illegal call", __func__);
                return -EINVAL;
        }
 
        /* Check registration callback - must be set! */
        if (cbTbl->probe == NULL) {
-               err("%s: probe() is required!", __FUNCTION__);
+               err("%s: probe() is required!", __func__);
                return -EINVAL;
        }
 
@@ -692,7 +692,7 @@ int usbvideo_register(
                return -ENOMEM;
        }
        dbg("%s: Allocated $%p (%d. bytes) for %d. cameras",
-           __FUNCTION__, cams, base_size, num_cams);
+           __func__, cams, base_size, num_cams);
 
        /* Copy callbacks, apply defaults for those that are not set */
        memmove(&cams->cb, cbTbl, sizeof(cams->cb));
@@ -721,7 +721,7 @@ int usbvideo_register(
                        up->user_data = kmalloc(up->user_size, GFP_KERNEL);
                        if (up->user_data == NULL) {
                                err("%s: Failed to allocate user_data (%d. bytes)",
-                                   __FUNCTION__, up->user_size);
+                                   __func__, up->user_size);
                                while (i) {
                                        up = &cams->cam[--i];
                                        kfree(up->user_data);
@@ -730,7 +730,7 @@ int usbvideo_register(
                                return -ENOMEM;
                        }
                        dbg("%s: Allocated cams[%d].user_data=$%p (%d. bytes)",
-                            __FUNCTION__, i, up->user_data, up->user_size);
+                            __func__, i, up->user_data, up->user_size);
                }
        }
 
@@ -776,19 +776,19 @@ void usbvideo_Deregister(struct usbvideo **pCams)
        int i;
 
        if (pCams == NULL) {
-               err("%s: pCams == NULL", __FUNCTION__);
+               err("%s: pCams == NULL", __func__);
                return;
        }
        cams = *pCams;
        if (cams == NULL) {
-               err("%s: cams == NULL", __FUNCTION__);
+               err("%s: cams == NULL", __func__);
                return;
        }
 
-       dbg("%s: Deregistering %s driver.", __FUNCTION__, cams->drvName);
+       dbg("%s: Deregistering %s driver.", __func__, cams->drvName);
        usb_deregister(&cams->usbdrv);
 
-       dbg("%s: Deallocating cams=$%p (%d. cameras)", __FUNCTION__, cams, cams->num_cameras);
+       dbg("%s: Deallocating cams=$%p (%d. cameras)", __func__, cams, cams->num_cameras);
        for (i=0; i < cams->num_cameras; i++) {
                struct uvd *up = &cams->cam[i];
                int warning = 0;
@@ -802,16 +802,16 @@ void usbvideo_Deregister(struct usbvideo **pCams)
                }
                if (warning) {
                        err("%s: Warning: user_data=$%p user_size=%d.",
-                           __FUNCTION__, up->user_data, up->user_size);
+                           __func__, up->user_data, up->user_size);
                } else {
                        dbg("%s: Freeing %d. $%p->user_data=$%p",
-                           __FUNCTION__, i, up, up->user_data);
+                           __func__, i, up, up->user_data);
                        kfree(up->user_data);
                }
        }
        /* Whole array was allocated in one chunk */
        dbg("%s: Freed %d uvd structures",
-           __FUNCTION__, cams->num_cameras);
+           __func__, cams->num_cameras);
        kfree(cams);
        *pCams = NULL;
 }
@@ -846,7 +846,7 @@ static void usbvideo_Disconnect(struct usb_interface *intf)
        int i;
 
        if (uvd == NULL) {
-               err("%s($%p): Illegal call.", __FUNCTION__, intf);
+               err("%s($%p): Illegal call.", __func__, intf);
                return;
        }
 
@@ -854,7 +854,7 @@ static void usbvideo_Disconnect(struct usb_interface *intf)
 
        usbvideo_ClientIncModCount(uvd);
        if (uvd->debug > 0)
-               info("%s(%p.)", __FUNCTION__, intf);
+               info("%s(%p.)", __func__, intf);
 
        mutex_lock(&uvd->lock);
        uvd->remove_pending = 1; /* Now all ISO data will be ignored */
@@ -870,10 +870,10 @@ static void usbvideo_Disconnect(struct usb_interface *intf)
 
        video_unregister_device(&uvd->vdev);
        if (uvd->debug > 0)
-               info("%s: Video unregistered.", __FUNCTION__);
+               info("%s: Video unregistered.", __func__);
 
        if (uvd->user)
-               info("%s: In use, disconnect pending.", __FUNCTION__);
+               info("%s: In use, disconnect pending.", __func__);
        else
                usbvideo_CameraRelease(uvd);
        mutex_unlock(&uvd->lock);
@@ -895,7 +895,7 @@ static void usbvideo_Disconnect(struct usb_interface *intf)
 static void usbvideo_CameraRelease(struct uvd *uvd)
 {
        if (uvd == NULL) {
-               err("%s: Illegal call", __FUNCTION__);
+               err("%s: Illegal call", __func__);
                return;
        }
 
@@ -946,7 +946,9 @@ static const struct file_operations usbvideo_fops = {
        .read =   usbvideo_v4l_read,
        .mmap =   usbvideo_v4l_mmap,
        .ioctl =  usbvideo_v4l_ioctl,
+#ifdef CONFIG_COMPAT
        .compat_ioctl = v4l_compat_ioctl32,
+#endif
        .llseek = no_llseek,
 };
 static const struct video_device usbvideo_template = {
@@ -1011,18 +1013,18 @@ int usbvideo_RegisterVideoDevice(struct uvd *uvd)
        char tmp1[20], tmp2[20];        /* Buffers for printing */
 
        if (uvd == NULL) {
-               err("%s: Illegal call.", __FUNCTION__);
+               err("%s: Illegal call.", __func__);
                return -EINVAL;
        }
        if (uvd->video_endp == 0) {
-               info("%s: No video endpoint specified; data pump disabled.", __FUNCTION__);
+               info("%s: No video endpoint specified; data pump disabled.", __func__);
        }
        if (uvd->paletteBits == 0) {
-               err("%s: No palettes specified!", __FUNCTION__);
+               err("%s: No palettes specified!", __func__);
                return -EINVAL;
        }
        if (uvd->defaultPalette == 0) {
-               info("%s: No default palette!", __FUNCTION__);
+               info("%s: No default palette!", __func__);
        }
 
        uvd->max_frame_size = VIDEOSIZE_X(uvd->canvas) *
@@ -1032,19 +1034,19 @@ int usbvideo_RegisterVideoDevice(struct uvd *uvd)
 
        if (uvd->debug > 0) {
                info("%s: iface=%d. endpoint=$%02x paletteBits=$%08lx",
-                    __FUNCTION__, uvd->iface, uvd->video_endp, uvd->paletteBits);
+                    __func__, uvd->iface, uvd->video_endp, uvd->paletteBits);
        }
        if (uvd->dev == NULL) {
-               err("%s: uvd->dev == NULL", __FUNCTION__);
+               err("%s: uvd->dev == NULL", __func__);
                return -EINVAL;
        }
-       uvd->vdev.dev=&(uvd->dev->dev);
+       uvd->vdev.dev = &uvd->dev->dev;
        if (video_register_device(&uvd->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
-               err("%s: video_register_device failed", __FUNCTION__);
+               err("%s: video_register_device failed", __func__);
                return -EPIPE;
        }
        if (uvd->debug > 1) {
-               info("%s: video_register_device() successful", __FUNCTION__);
+               info("%s: video_register_device() successful", __func__);
        }
 
        info("%s on /dev/video%d: canvas=%s videosize=%s",
@@ -1111,14 +1113,14 @@ static int usbvideo_v4l_open(struct inode *inode, struct file *file)
        int i, errCode = 0;
 
        if (uvd->debug > 1)
-               info("%s($%p)", __FUNCTION__, dev);
+               info("%s($%p)", __func__, dev);
 
        if (0 < usbvideo_ClientIncModCount(uvd))
                return -ENODEV;
        mutex_lock(&uvd->lock);
 
        if (uvd->user) {
-               err("%s: Someone tried to open an already opened device!", __FUNCTION__);
+               err("%s: Someone tried to open an already opened device!", __func__);
                errCode = -EBUSY;
        } else {
                /* Clear statistics */
@@ -1134,7 +1136,7 @@ static int usbvideo_v4l_open(struct inode *inode, struct file *file)
                RingQueue_Allocate(&uvd->dp, RING_QUEUE_SIZE);
                if ((uvd->fbuf == NULL) ||
                    (!RingQueue_IsAllocated(&uvd->dp))) {
-                       err("%s: Failed to allocate fbuf or dp", __FUNCTION__);
+                       err("%s: Failed to allocate fbuf or dp", __func__);
                        errCode = -ENOMEM;
                } else {
                        /* Allocate all buffers */
@@ -1178,19 +1180,19 @@ static int usbvideo_v4l_open(struct inode *inode, struct file *file)
                if (errCode == 0) {
                        if (VALID_CALLBACK(uvd, setupOnOpen)) {
                                if (uvd->debug > 1)
-                                       info("%s: setupOnOpen callback", __FUNCTION__);
+                                       info("%s: setupOnOpen callback", __func__);
                                errCode = GET_CALLBACK(uvd, setupOnOpen)(uvd);
                                if (errCode < 0) {
                                        err("%s: setupOnOpen callback failed (%d.).",
-                                           __FUNCTION__, errCode);
+                                           __func__, errCode);
                                } else if (uvd->debug > 1) {
-                                       info("%s: setupOnOpen callback successful", __FUNCTION__);
+                                       info("%s: setupOnOpen callback successful", __func__);
                                }
                        }
                        if (errCode == 0) {
                                uvd->settingsAdjusted = 0;
                                if (uvd->debug > 1)
-                                       info("%s: Open succeeded.", __FUNCTION__);
+                                       info("%s: Open succeeded.", __func__);
                                uvd->user++;
                                file->private_data = uvd;
                        }
@@ -1200,7 +1202,7 @@ static int usbvideo_v4l_open(struct inode *inode, struct file *file)
        if (errCode != 0)
                usbvideo_ClientDecModCount(uvd);
        if (uvd->debug > 0)
-               info("%s: Returning %d.", __FUNCTION__, errCode);
+               info("%s: Returning %d.", __func__, errCode);
        return errCode;
 }
 
@@ -1223,7 +1225,7 @@ static int usbvideo_v4l_close(struct inode *inode, struct file *file)
        int i;
 
        if (uvd->debug > 1)
-               info("%s($%p)", __FUNCTION__, dev);
+               info("%s($%p)", __func__, dev);
 
        mutex_lock(&uvd->lock);
        GET_CALLBACK(uvd, stopDataPump)(uvd);
@@ -1250,7 +1252,7 @@ static int usbvideo_v4l_close(struct inode *inode, struct file *file)
        usbvideo_ClientDecModCount(uvd);
 
        if (uvd->debug > 1)
-               info("%s: Completed.", __FUNCTION__);
+               info("%s: Completed.", __func__);
        file->private_data = NULL;
        return 0;
 }
@@ -1504,7 +1506,7 @@ static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf,
                return -EFAULT;
 
        if (uvd->debug >= 1)
-               info("%s: %Zd. bytes, noblock=%d.", __FUNCTION__, count, noblock);
+               info("%s: %Zd. bytes, noblock=%d.", __func__, count, noblock);
 
        mutex_lock(&uvd->lock);
 
@@ -1551,7 +1553,7 @@ static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf,
         */
        if (frmx == -1) {
                if (uvd->defaultPalette == 0) {
-                       err("%s: No default palette; don't know what to do!", __FUNCTION__);
+                       err("%s: No default palette; don't know what to do!", __func__);
                        count = -EFAULT;
                        goto read_done;
                }
@@ -1623,7 +1625,7 @@ static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf,
        frame->seqRead_Index += count;
        if (uvd->debug >= 1) {
                err("%s: {copy} count used=%Zd, new seqRead_Index=%ld",
-                       __FUNCTION__, count, frame->seqRead_Index);
+                       __func__, count, frame->seqRead_Index);
        }
 
        /* Finally check if the frame is done with and "release" it */
@@ -1634,7 +1636,7 @@ static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf,
                /* Mark it as available to be used again. */
                uvd->frame[frmx].frameState = FrameState_Unused;
                if (usbvideo_NewFrame(uvd, (frmx + 1) % USBVIDEO_NUMFRAMES)) {
-                       err("%s: usbvideo_NewFrame failed.", __FUNCTION__);
+                       err("%s: usbvideo_NewFrame failed.", __func__);
                }
        }
 read_done:
@@ -1741,10 +1743,10 @@ static int usbvideo_StartDataPump(struct uvd *uvd)
        int i, errFlag;
 
        if (uvd->debug > 1)
-               info("%s($%p)", __FUNCTION__, uvd);
+               info("%s($%p)", __func__, uvd);
 
        if (!CAMERA_IS_OPERATIONAL(uvd)) {
-               err("%s: Camera is not operational", __FUNCTION__);
+               err("%s: Camera is not operational", __func__);
                return -EFAULT;
        }
        uvd->curframe = -1;
@@ -1752,14 +1754,14 @@ static int usbvideo_StartDataPump(struct uvd *uvd)
        /* Alternate interface 1 is is the biggest frame size */
        i = usb_set_interface(dev, uvd->iface, uvd->ifaceAltActive);
        if (i < 0) {
-               err("%s: usb_set_interface error", __FUNCTION__);
+               err("%s: usb_set_interface error", __func__);
                uvd->last_error = i;
                return -EBUSY;
        }
        if (VALID_CALLBACK(uvd, videoStart))
                GET_CALLBACK(uvd, videoStart)(uvd);
        else
-               err("%s: videoStart not set", __FUNCTION__);
+               err("%s: videoStart not set", __func__);
 
        /* We double buffer the Iso lists */
        for (i=0; i < USBVIDEO_NUMSBUF; i++) {
@@ -1784,12 +1786,12 @@ static int usbvideo_StartDataPump(struct uvd *uvd)
        for (i=0; i < USBVIDEO_NUMSBUF; i++) {
                errFlag = usb_submit_urb(uvd->sbuf[i].urb, GFP_KERNEL);
                if (errFlag)
-                       err("%s: usb_submit_isoc(%d) ret %d", __FUNCTION__, i, errFlag);
+                       err("%s: usb_submit_isoc(%d) ret %d", __func__, i, errFlag);
        }
 
        uvd->streaming = 1;
        if (uvd->debug > 1)
-               info("%s: streaming=1 video_endp=$%02x", __FUNCTION__, uvd->video_endp);
+               info("%s: streaming=1 video_endp=$%02x", __func__, uvd->video_endp);
        return 0;
 }
 
@@ -1811,14 +1813,14 @@ static void usbvideo_StopDataPump(struct uvd *uvd)
                return;
 
        if (uvd->debug > 1)
-               info("%s($%p)", __FUNCTION__, uvd);
+               info("%s($%p)", __func__, uvd);
 
        /* Unschedule all of the iso td's */
        for (i=0; i < USBVIDEO_NUMSBUF; i++) {
                usb_kill_urb(uvd->sbuf[i].urb);
        }
        if (uvd->debug > 1)
-               info("%s: streaming=0", __FUNCTION__);
+               info("%s: streaming=0", __func__);
        uvd->streaming = 0;
 
        if (!uvd->remove_pending) {
@@ -1826,12 +1828,12 @@ static void usbvideo_StopDataPump(struct uvd *uvd)
                if (VALID_CALLBACK(uvd, videoStop))
                        GET_CALLBACK(uvd, videoStop)(uvd);
                else
-                       err("%s: videoStop not set", __FUNCTION__);
+                       err("%s: videoStop not set", __func__);
 
                /* Set packet size to 0 */
                j = usb_set_interface(uvd->dev, uvd->iface, uvd->ifaceAltInactive);
                if (j < 0) {
-                       err("%s: usb_set_interface() error %d.", __FUNCTION__, j);
+                       err("%s: usb_set_interface() error %d.", __func__, j);
                        uvd->last_error = j;
                }
        }
@@ -1955,12 +1957,12 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
        struct usbvideo_frame *frame = &uvd->frame[frameNum];
 
        if (uvd->debug >= 2)
-               info("%s($%p,%d.)", __FUNCTION__, uvd, frameNum);
+               info("%s($%p,%d.)", __func__, uvd, frameNum);
 
        switch (frame->frameState) {
        case FrameState_Unused:
                if (uvd->debug >= 2)
-                       info("%s: FrameState_Unused", __FUNCTION__);
+                       info("%s: FrameState_Unused", __func__);
                return -EINVAL;
        case FrameState_Ready:
        case FrameState_Grabbing:
@@ -1970,7 +1972,7 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
        redo:
                if (!CAMERA_IS_OPERATIONAL(uvd)) {
                        if (uvd->debug >= 2)
-                               info("%s: Camera is not operational (1)", __FUNCTION__);
+                               info("%s: Camera is not operational (1)", __func__);
                        return -EIO;
                }
                ntries = 0;
@@ -1979,24 +1981,24 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
                        signalPending = signal_pending(current);
                        if (!CAMERA_IS_OPERATIONAL(uvd)) {
                                if (uvd->debug >= 2)
-                                       info("%s: Camera is not operational (2)", __FUNCTION__);
+                                       info("%s: Camera is not operational (2)", __func__);
                                return -EIO;
                        }
                        assert(uvd->fbuf != NULL);
                        if (signalPending) {
                                if (uvd->debug >= 2)
-                                       info("%s: Signal=$%08x", __FUNCTION__, signalPending);
+                                       info("%s: Signal=$%08x", __func__, signalPending);
                                if (uvd->flags & FLAGS_RETRY_VIDIOCSYNC) {
                                        usbvideo_TestPattern(uvd, 1, 0);
                                        uvd->curframe = -1;
                                        uvd->stats.frame_num++;
                                        if (uvd->debug >= 2)
-                                               info("%s: Forced test pattern screen", __FUNCTION__);
+                                               info("%s: Forced test pattern screen", __func__);
                                        return 0;
                                } else {
                                        /* Standard answer: Interrupted! */
                                        if (uvd->debug >= 2)
-                                               info("%s: Interrupted!", __FUNCTION__);
+                                               info("%s: Interrupted!", __func__);
                                        return -EINTR;
                                }
                        } else {
@@ -2006,17 +2008,17 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
                                else if (VALID_CALLBACK(uvd, processData))
                                        GET_CALLBACK(uvd, processData)(uvd, frame);
                                else
-                                       err("%s: processData not set", __FUNCTION__);
+                                       err("%s: processData not set", __func__);
                        }
                } while (frame->frameState == FrameState_Grabbing);
                if (uvd->debug >= 2) {
                        info("%s: Grabbing done; state=%d. (%lu. bytes)",
-                            __FUNCTION__, frame->frameState, frame->seqRead_Length);
+                            __func__, frame->frameState, frame->seqRead_Length);
                }
                if (frame->frameState == FrameState_Error) {
                        int ret = usbvideo_NewFrame(uvd, frameNum);
                        if (ret < 0) {
-                               err("%s: usbvideo_NewFrame() failed (%d.)", __FUNCTION__, ret);
+                               err("%s: usbvideo_NewFrame() failed (%d.)", __func__, ret);
                                return ret;
                        }
                        goto redo;
@@ -2048,7 +2050,7 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
                }
                frame->frameState = FrameState_Done_Hold;
                if (uvd->debug >= 2)
-                       info("%s: Entered FrameState_Done_Hold state.", __FUNCTION__);
+                       info("%s: Entered FrameState_Done_Hold state.", __func__);
                return 0;
 
        case FrameState_Done_Hold:
@@ -2059,12 +2061,12 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
                 * it will be released back into the wild to roam freely.
                 */
                if (uvd->debug >= 2)
-                       info("%s: FrameState_Done_Hold state.", __FUNCTION__);
+                       info("%s: FrameState_Done_Hold state.", __func__);
                return 0;
        }
 
        /* Catch-all for other cases. We shall not be here. */
-       err("%s: Invalid state %d.", __FUNCTION__, frame->frameState);
+       err("%s: Invalid state %d.", __func__, frame->frameState);
        frame->frameState = FrameState_Unused;
        return 0;
 }
@@ -2160,7 +2162,7 @@ static void usbvideo_SoftwareContrastAdjustment(struct uvd *uvd,
        const int ccm = 128; /* Color correction median - see below */
 
        if ((uvd == NULL) || (frame == NULL)) {
-               err("%s: Illegal call.", __FUNCTION__);
+               err("%s: Illegal call.", __func__);
                return;
        }
        adj = (uvd->vpic.contrast - 0x8000) >> 8; /* -128..+127 = -ccm..+(ccm-1)*/
index da1ba0211108939810983cb3753588d713c257ef..64819353276a6a2f2540175625ab0bf42e4fac23 100644 (file)
@@ -48,7 +48,7 @@
 // #define VICAM_DEBUG
 
 #ifdef VICAM_DEBUG
-#define ADBG(lineno,fmt,args...) printk(fmt, jiffies, __FUNCTION__, lineno, ##args)
+#define ADBG(lineno,fmt,args...) printk(fmt, jiffies, __func__, lineno, ##args)
 #define DBG(fmt,args...) ADBG((__LINE__),KERN_DEBUG __FILE__"(%ld):%s (%d):"fmt,##args)
 #else
 #define DBG(fmn,args...) do {} while(0)
@@ -1066,7 +1066,9 @@ static const struct file_operations vicam_fops = {
        .read           = vicam_read,
        .mmap           = vicam_mmap,
        .ioctl          = vicam_ioctl,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .llseek         = no_llseek,
 };
 
index 56775ab8b75d386809183403b492dd05671d03ae..a9c5e5adba3afb704c300df72bbbdfe31a2928b8 100644 (file)
 
 #include "usbvision.h"
 
-static unsigned int core_debug = 0;
+static unsigned int core_debug;
 module_param(core_debug,int,0644);
 MODULE_PARM_DESC(core_debug,"enable debug messages [core]");
 
-static unsigned int force_testpattern = 0;
+static unsigned int force_testpattern;
 module_param(force_testpattern,int,0644);
 MODULE_PARM_DESC(force_testpattern,"enable test pattern display [core]");
 
-static int adjustCompression = 1;                      // Set the compression to be adaptive
+static int adjustCompression = 1;      /* Set the compression to be adaptive */
 module_param(adjustCompression, int, 0444);
 MODULE_PARM_DESC(adjustCompression, " Set the ADPCM compression for the device.  Default: 1 (On)");
 
-static int SwitchSVideoInput = 0;                      // To help people with Black and White output with using s-video input.  Some cables and input device are wired differently.
+/* To help people with Black and White output with using s-video input.
+ * Some cables and input device are wired differently. */
+static int SwitchSVideoInput;
 module_param(SwitchSVideoInput, int, 0444);
 MODULE_PARM_DESC(SwitchSVideoInput, " Set the S-Video input.  Some cables and input device are wired differently. Default: 0 (Off)");
 
@@ -82,8 +84,10 @@ MODULE_PARM_DESC(adjust_Y_Offset, "adjust Y offset display [core]");
 
 
 #ifdef USBVISION_DEBUG
-       #define PDEBUG(level, fmt, args...) \
-               if (core_debug & (level)) info("[%s:%d] " fmt, __PRETTY_FUNCTION__, __LINE__ , ## args)
+       #define PDEBUG(level, fmt, args...) { \
+               if (core_debug & (level)) \
+                       info("[%s:%d] " fmt, __func__, __LINE__ , ## args); \
+       }
 #else
        #define PDEBUG(level, fmt, args...) do {} while(0)
 #endif
@@ -384,7 +388,7 @@ int usbvision_scratch_alloc(struct usb_usbvision *usbvision)
        scratch_reset(usbvision);
        if(usbvision->scratch == NULL) {
                err("%s: unable to allocate %d bytes for scratch",
-                   __FUNCTION__, scratch_buf_size);
+                   __func__, scratch_buf_size);
                return -ENOMEM;
        }
        return 0;
@@ -418,7 +422,7 @@ static void usbvision_testpattern(struct usb_usbvision *usbvision,
        unsigned char *f;
        int num_cell = 0;
        int scan_length = 0;
-       static int num_pass = 0;
+       static int num_pass;
 
        if (usbvision == NULL) {
                printk(KERN_ERR "%s: usbvision == NULL\n", proc);
@@ -493,7 +497,8 @@ int usbvision_decompress_alloc(struct usb_usbvision *usbvision)
        int IFB_size = MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT * 3 / 2;
        usbvision->IntraFrameBuffer = vmalloc_32(IFB_size);
        if (usbvision->IntraFrameBuffer == NULL) {
-               err("%s: unable to allocate %d for compr. frame buffer", __FUNCTION__, IFB_size);
+               err("%s: unable to allocate %d for compr. frame buffer",
+                   __func__, IFB_size);
                return -ENOMEM;
        }
        return 0;
@@ -1430,7 +1435,7 @@ static int usbvision_compress_isochronous(struct usb_usbvision *usbvision,
        }
 #if ENABLE_HEXDUMP
        if (totlen > 0) {
-               static int foo = 0;
+               static int foo;
                if (foo < 1) {
                        printk(KERN_DEBUG "+%d.\n", usbvision->scratchlen);
                        usbvision_hexdump(data0, (totlen > 64) ? 64 : totlen);
@@ -1516,7 +1521,7 @@ static void usbvision_isocIrq(struct urb *urb)
 
        if(errCode) {
                err("%s: usb_submit_urb failed: error %d",
-                   __FUNCTION__, errCode);
+                   __func__, errCode);
        }
 
        return;
@@ -1547,7 +1552,7 @@ int usbvision_read_reg(struct usb_usbvision *usbvision, unsigned char reg)
                                0, (__u16) reg, buffer, 1, HZ);
 
        if (errCode < 0) {
-               err("%s: failed: error %d", __FUNCTION__, errCode);
+               err("%s: failed: error %d", __func__, errCode);
                return errCode;
        }
        return buffer[0];
@@ -1575,7 +1580,7 @@ int usbvision_write_reg(struct usb_usbvision *usbvision, unsigned char reg,
                                USB_RECIP_ENDPOINT, 0, (__u16) reg, &value, 1, HZ);
 
        if (errCode < 0) {
-               err("%s: failed: error %d", __FUNCTION__, errCode);
+               err("%s: failed: error %d", __func__, errCode);
        }
        return errCode;
 }
@@ -1851,7 +1856,7 @@ int usbvision_set_output(struct usb_usbvision *usbvision, int width,
                                 0, (__u16) USBVISION_LXSIZE_O, value, 4, HZ);
 
                if (errCode < 0) {
-                       err("%s failed: error %d", __FUNCTION__, errCode);
+                       err("%s failed: error %d", __func__, errCode);
                        return errCode;
                }
                usbvision->curwidth = usbvision->stretch_width * UsbWidth;
@@ -2237,7 +2242,7 @@ static int usbvision_set_dram_settings(struct usb_usbvision *usbvision)
                             (__u16) USBVISION_DRM_PRM1, value, 8, HZ);
 
        if (rc < 0) {
-               err("%sERROR=%d", __FUNCTION__, rc);
+               err("%sERROR=%d", __func__, rc);
                return rc;
        }
 
@@ -2486,7 +2491,7 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision)
 
                urb = usb_alloc_urb(USBVISION_URB_FRAMES, GFP_KERNEL);
                if (urb == NULL) {
-                       err("%s: usb_alloc_urb() failed", __FUNCTION__);
+                       err("%s: usb_alloc_urb() failed", __func__);
                        return -ENOMEM;
                }
                usbvision->sbuf[bufIdx].urb = urb;
@@ -2520,13 +2525,13 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision)
                                                 GFP_KERNEL);
                if (errCode) {
                        err("%s: usb_submit_urb(%d) failed: error %d",
-                           __FUNCTION__, bufIdx, errCode);
+                           __func__, bufIdx, errCode);
                }
        }
 
        usbvision->streaming = Stream_Idle;
        PDEBUG(DBG_ISOC, "%s: streaming=1 usbvision->video_endp=$%02x",
-              __FUNCTION__,
+              __func__,
               usbvision->video_endp);
        return 0;
 }
@@ -2560,7 +2565,7 @@ void usbvision_stop_isoc(struct usb_usbvision *usbvision)
        }
 
 
-       PDEBUG(DBG_ISOC, "%s: streaming=Stream_Off\n", __FUNCTION__);
+       PDEBUG(DBG_ISOC, "%s: streaming=Stream_Off\n", __func__);
        usbvision->streaming = Stream_Off;
 
        if (!usbvision->remove_pending) {
@@ -2571,7 +2576,7 @@ void usbvision_stop_isoc(struct usb_usbvision *usbvision)
                                            usbvision->ifaceAlt);
                if (errCode < 0) {
                        err("%s: usb_set_interface() failed: error %d",
-                           __FUNCTION__, errCode);
+                           __func__, errCode);
                        usbvision->last_error = errCode;
                }
                regValue = (16-usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F;
index aabc42cae9c7be63b38b6fa3bc9f26b6f12570ba..e2274d77ea295a532befda800eec9ab53e14eb0c 100644 (file)
 
 #define DBG_I2C                1<<0
 
-static int i2c_debug = 0;
+static int i2c_debug;
 
 module_param (i2c_debug, int, 0644);                   // debug_i2c_usb mode of the device driver
 MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
 
-#define PDEBUG(level, fmt, args...) \
-               if (i2c_debug & (level)) info("[%s:%d] " fmt, __PRETTY_FUNCTION__, __LINE__ , ## args)
+#define PDEBUG(level, fmt, args...) { \
+               if (i2c_debug & (level)) \
+                       info("[%s:%d] " fmt, __func__, __LINE__ , ## args); \
+       }
 
 static int usbvision_i2c_write(struct usb_usbvision *usbvision, unsigned char addr, char *buf,
                            short len);
index df52f8a602155c6c32e26011f6dd93f0c6c7b097..d97261ab430f9f3c772b9ef27f18558a2da5f5fe 100644 (file)
@@ -97,10 +97,10 @@ USBVISION_DRIVER_VERSION_PATCHLEVEL)
 
 
 #ifdef USBVISION_DEBUG
-       #define PDEBUG(level, fmt, args...) \
+       #define PDEBUG(level, fmt, args...) \
                if (video_debug & (level)) \
-                       info("[%s:%d] " fmt, __PRETTY_FUNCTION__, __LINE__ ,\
-                               ## args)
+                       info("[%s:%d] " fmt, __func__, __LINE__ , ## args); \
+       }
 #else
        #define PDEBUG(level, fmt, args...) do {} while(0)
 #endif
@@ -115,7 +115,7 @@ USBVISION_DRIVER_VERSION_PATCHLEVEL)
 
 
 /* sequential number of usbvision device */
-static int usbvision_nr = 0;
+static int usbvision_nr;
 
 static struct usbvision_v4l2_format_st usbvision_v4l2_format[] = {
        { 1, 1,  8, V4L2_PIX_FMT_GREY    , "GREY" },
@@ -135,7 +135,7 @@ static void usbvision_release(struct usb_usbvision *usbvision);
 /* Set the default format for ISOC endpoint */
 static int isocMode = ISOC_MODE_COMPRESS;
 /* Set the default Debug Mode of the device driver */
-static int video_debug = 0;
+static int video_debug;
 /* Set the default device to power on at startup */
 static int PowerOnAtOpen = 1;
 /* Sequential Number of Video Device */
@@ -343,7 +343,7 @@ static void usbvision_create_sysfs(struct video_device *vdev)
                        return;
        } while (0);
 
-       err("%s error: %d\n", __FUNCTION__, res);
+       err("%s error: %d\n", __func__, res);
 }
 
 static void usbvision_remove_sysfs(struct video_device *vdev)
@@ -490,7 +490,7 @@ static int usbvision_v4l2_close(struct inode *inode, struct file *file)
        mutex_unlock(&usbvision->lock);
 
        if (usbvision->remove_pending) {
-               printk(KERN_INFO "%s: Final disconnect\n", __FUNCTION__);
+               printk(KERN_INFO "%s: Final disconnect\n", __func__);
                usbvision_release(usbvision);
        }
 
@@ -522,7 +522,7 @@ static int vidioc_g_register (struct file *file, void *priv,
        errCode = usbvision_read_reg(usbvision, reg->reg&0xff);
        if (errCode < 0) {
                err("%s: VIDIOC_DBG_G_REGISTER failed: error %d",
-                   __FUNCTION__, errCode);
+                   __func__, errCode);
                return errCode;
        }
        reg->val = errCode;
@@ -543,7 +543,7 @@ static int vidioc_s_register (struct file *file, void *priv,
        errCode = usbvision_write_reg(usbvision, reg->reg&0xff, reg->val);
        if (errCode < 0) {
                err("%s: VIDIOC_DBG_S_REGISTER failed: error %d",
-                   __FUNCTION__, errCode);
+                   __func__, errCode);
                return errCode;
        }
        return 0;
@@ -1102,7 +1102,7 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf,
        int ret,i;
        struct usbvision_frame *frame;
 
-       PDEBUG(DBG_IO, "%s: %ld bytes, noblock=%d", __FUNCTION__,
+       PDEBUG(DBG_IO, "%s: %ld bytes, noblock=%d", __func__,
               (unsigned long)count, noblock);
 
        if (!USBVISION_IS_OPERATIONAL(usbvision) || (buf == NULL))
@@ -1171,7 +1171,7 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf,
        }
 
        PDEBUG(DBG_IO, "%s: frmx=%d, bytes_read=%ld, scanlength=%ld",
-              __FUNCTION__,
+              __func__,
               frame->index, frame->bytes_read, frame->scanlength);
 
        /* copy bytes to user space; we allow for partials reads */
@@ -1184,7 +1184,7 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf,
 
        frame->bytes_read += count;
        PDEBUG(DBG_IO, "%s: {copy} count used=%ld, new bytes_read=%ld",
-              __FUNCTION__,
+              __func__,
               (unsigned long)count, frame->bytes_read);
 
        /* For now, forget the frame if it has not been read in one shot. */
@@ -1269,12 +1269,12 @@ static int usbvision_radio_open(struct inode *inode, struct file *file)
                (struct usb_usbvision *) video_get_drvdata(dev);
        int errCode = 0;
 
-       PDEBUG(DBG_IO, "%s:", __FUNCTION__);
+       PDEBUG(DBG_IO, "%s:", __func__);
 
        mutex_lock(&usbvision->lock);
 
        if (usbvision->user) {
-               err("%s: Someone tried to open an already opened USBVision Radio!", __FUNCTION__);
+               err("%s: Someone tried to open an already opened USBVision Radio!", __func__);
                errCode = -EBUSY;
        }
        else {
@@ -1342,7 +1342,7 @@ static int usbvision_radio_close(struct inode *inode, struct file *file)
        mutex_unlock(&usbvision->lock);
 
        if (usbvision->remove_pending) {
-               printk(KERN_INFO "%s: Final disconnect\n", __FUNCTION__);
+               printk(KERN_INFO "%s: Final disconnect\n", __func__);
                usbvision_release(usbvision);
        }
 
@@ -1507,7 +1507,7 @@ static struct video_device *usbvision_vdev_init(struct usb_usbvision *usbvision,
        struct video_device *vdev;
 
        if (usb_dev == NULL) {
-               err("%s: usbvision->dev is not set", __FUNCTION__);
+               err("%s: usbvision->dev is not set", __func__);
                return NULL;
        }
 
@@ -1759,7 +1759,7 @@ static int __devinit usbvision_probe(struct usb_interface *intf,
                PDEBUG(DBG_PROBE, "model out of bounds %d",model);
                return -ENODEV;
        }
-       printk(KERN_INFO "%s: %s found\n", __FUNCTION__,
+       printk(KERN_INFO "%s: %s found\n", __func__,
                                usbvision_device_data[model].ModelString);
 
        if (usbvision_device_data[model].Interface >= 0) {
@@ -1771,20 +1771,20 @@ static int __devinit usbvision_probe(struct usb_interface *intf,
        if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) !=
            USB_ENDPOINT_XFER_ISOC) {
                err("%s: interface %d. has non-ISO endpoint!",
-                   __FUNCTION__, ifnum);
+                   __func__, ifnum);
                err("%s: Endpoint attributes %d",
-                   __FUNCTION__, endpoint->bmAttributes);
+                   __func__, endpoint->bmAttributes);
                return -ENODEV;
        }
        if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) ==
            USB_DIR_OUT) {
                err("%s: interface %d. has ISO OUT endpoint!",
-                   __FUNCTION__, ifnum);
+                   __func__, ifnum);
                return -ENODEV;
        }
 
        if ((usbvision = usbvision_alloc(dev)) == NULL) {
-               err("%s: couldn't allocate USBVision struct", __FUNCTION__);
+               err("%s: couldn't allocate USBVision struct", __func__);
                return -ENOMEM;
        }
 
@@ -1868,7 +1868,7 @@ static void __devexit usbvision_disconnect(struct usb_interface *intf)
        PDEBUG(DBG_PROBE, "");
 
        if (usbvision == NULL) {
-               err("%s: usb_get_intfdata() failed", __FUNCTION__);
+               err("%s: usb_get_intfdata() failed", __func__);
                return;
        }
        usb_set_intfdata (intf, NULL);
@@ -1891,7 +1891,7 @@ static void __devexit usbvision_disconnect(struct usb_interface *intf)
 
        if (usbvision->user) {
                printk(KERN_INFO "%s: In use, disconnect pending\n",
-                      __FUNCTION__);
+                      __func__);
                wake_up_interruptible(&usbvision->wait_frame);
                wake_up_interruptible(&usbvision->wait_stream);
        } else {
index e3ac5e6860758c6e6a7e1bd83ef11eadd4b9f6ad..a0f6c60279ece8cb97cc69612889e0a646beae63 100644 (file)
 #include <linux/kmod.h>
 #endif
 
-static unsigned int debug  = 0;
+static unsigned int debug;
 module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug,"enable debug messages");
+MODULE_PARM_DESC(debug, "enable debug messages");
 MODULE_AUTHOR("Bill Dirks");
 MODULE_DESCRIPTION("v4l(1) compatibility layer for v4l2 drivers.");
 MODULE_LICENSE("GPL");
 
-#define dprintk(fmt, arg...)   if (debug) \
-       printk(KERN_DEBUG "v4l1-compat: " fmt , ## arg)
+#define dprintk(fmt, arg...) \
+       do { \
+               if (debug) \
+                       printk(KERN_DEBUG "v4l1-compat: " fmt , ## arg);\
+       } while (0)
 
 /*
  *     I O C T L   T R A N S L A T I O N
@@ -69,14 +72,12 @@ get_v4l_control(struct inode            *inode,
        qctrl2.id = cid;
        err = drv(inode, file, VIDIOC_QUERYCTRL, &qctrl2);
        if (err < 0)
-               dprintk("VIDIOC_QUERYCTRL: %d\n",err);
-       if (err == 0 &&
-           !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED))
-       {
+               dprintk("VIDIOC_QUERYCTRL: %d\n", err);
+       if (err == 0 && !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED)) {
                ctrl2.id = qctrl2.id;
                err = drv(inode, file, VIDIOC_G_CTRL, &ctrl2);
                if (err < 0) {
-                       dprintk("VIDIOC_G_CTRL: %d\n",err);
+                       dprintk("VIDIOC_G_CTRL: %d\n", err);
                        return 0;
                }
                return ((ctrl2.value - qctrl2.minimum) * 65535
@@ -100,11 +101,10 @@ set_v4l_control(struct inode            *inode,
        qctrl2.id = cid;
        err = drv(inode, file, VIDIOC_QUERYCTRL, &qctrl2);
        if (err < 0)
-               dprintk("VIDIOC_QUERYCTRL: %d\n",err);
+               dprintk("VIDIOC_QUERYCTRL: %d\n", err);
        if (err == 0 &&
            !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED) &&
-           !(qctrl2.flags & V4L2_CTRL_FLAG_GRABBED))
-       {
+           !(qctrl2.flags & V4L2_CTRL_FLAG_GRABBED)) {
                if (value < 0)
                        value = 0;
                if (value > 65535)
@@ -119,7 +119,7 @@ set_v4l_control(struct inode            *inode,
                ctrl2.value += qctrl2.minimum;
                err = drv(inode, file, VIDIOC_S_CTRL, &ctrl2);
                if (err < 0)
-                       dprintk("VIDIOC_S_CTRL: %d\n",err);
+                       dprintk("VIDIOC_S_CTRL: %d\n", err);
        }
        return 0;
 }
@@ -157,8 +157,7 @@ static unsigned int __attribute_const__
 pixelformat_to_palette(unsigned int pixelformat)
 {
        int     palette = 0;
-       switch (pixelformat)
-       {
+       switch (pixelformat) {
        case V4L2_PIX_FMT_GREY:
                palette = VIDEO_PALETTE_GREY;
                break;
@@ -200,14 +199,13 @@ pixelformat_to_palette(unsigned int pixelformat)
 
 /* ----------------------------------------------------------------- */
 
-static int poll_one(struct file *file)
+static int poll_one(struct file *file, struct poll_wqueues *pwq)
 {
        int retval = 1;
        poll_table *table;
-       struct poll_wqueues pwq;
 
-       poll_initwait(&pwq);
-       table = &pwq.pt;
+       poll_initwait(pwq);
+       table = &pwq->pt;
        for (;;) {
                int mask;
                set_current_state(TASK_INTERRUPTIBLE);
@@ -222,878 +220,1073 @@ static int poll_one(struct file *file)
                schedule();
        }
        set_current_state(TASK_RUNNING);
-       poll_freewait(&pwq);
+       poll_freewait(pwq);
        return retval;
 }
 
-static int count_inputs(struct inode         *inode,
-                       struct file          *file,
-                       v4l2_kioctl          drv)
+static int count_inputs(
+                       struct inode *inode,
+                       struct file *file,
+                       v4l2_kioctl drv)
 {
        struct v4l2_input input2;
        int i;
 
        for (i = 0;; i++) {
-               memset(&input2,0,sizeof(input2));
+               memset(&input2, 0, sizeof(input2));
                input2.index = i;
-               if (0 != drv(inode,file,VIDIOC_ENUMINPUT, &input2))
+               if (0 != drv(inode, file, VIDIOC_ENUMINPUT, &input2))
                        break;
        }
        return i;
 }
 
-static int check_size(struct inode         *inode,
-                     struct file          *file,
-                     v4l2_kioctl          drv,
-                     int *maxw, int *maxh)
+static int check_size(
+               struct inode *inode,
+               struct file *file,
+               v4l2_kioctl drv,
+               int *maxw,
+               int *maxh)
 {
        struct v4l2_fmtdesc desc2;
        struct v4l2_format  fmt2;
 
-       memset(&desc2,0,sizeof(desc2));
-       memset(&fmt2,0,sizeof(fmt2));
+       memset(&desc2, 0, sizeof(desc2));
+       memset(&fmt2, 0, sizeof(fmt2));
 
        desc2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-       if (0 != drv(inode,file,VIDIOC_ENUM_FMT, &desc2))
+       if (0 != drv(inode, file, VIDIOC_ENUM_FMT, &desc2))
                goto done;
 
        fmt2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        fmt2.fmt.pix.width       = 10000;
        fmt2.fmt.pix.height      = 10000;
        fmt2.fmt.pix.pixelformat = desc2.pixelformat;
-       if (0 != drv(inode,file,VIDIOC_TRY_FMT, &fmt2))
+       if (0 != drv(inode, file, VIDIOC_TRY_FMT, &fmt2))
                goto done;
 
        *maxw = fmt2.fmt.pix.width;
        *maxh = fmt2.fmt.pix.height;
 
- done:
+done:
        return 0;
 }
 
 /* ----------------------------------------------------------------- */
 
-/*
- *     This function is exported.
- */
-int
-v4l_compat_translate_ioctl(struct inode         *inode,
-                          struct file          *file,
-                          int                  cmd,
-                          void                 *arg,
-                          v4l2_kioctl          drv)
+static noinline int v4l1_compat_get_capabilities(
+                                       struct video_capability *cap,
+                                       struct inode *inode,
+                                       struct file *file,
+                                       v4l2_kioctl drv)
 {
-       struct v4l2_capability  *cap2 = NULL;
-       struct v4l2_format      *fmt2 = NULL;
-       enum v4l2_buf_type      captype = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
-       struct v4l2_framebuffer fbuf2;
-       struct v4l2_input       input2;
-       struct v4l2_tuner       tun2;
-       struct v4l2_standard    std2;
-       struct v4l2_frequency   freq2;
-       struct v4l2_audio       aud2;
-       struct v4l2_queryctrl   qctrl2;
-       struct v4l2_buffer      buf2;
-       v4l2_std_id             sid;
-       int i, err = 0;
-
-       switch (cmd) {
-       case VIDIOCGCAP:        /* capability */
-       {
-               struct video_capability *cap = arg;
-
-               cap2 = kzalloc(sizeof(*cap2), GFP_KERNEL);
-               if (!cap2) {
-                       err = -ENOMEM;
-                       break;
-               }
-               memset(cap, 0, sizeof(*cap));
-               memset(&fbuf2, 0, sizeof(fbuf2));
+       int err;
+       struct v4l2_framebuffer fbuf;
+       struct v4l2_capability *cap2;
+
+       cap2 = kzalloc(sizeof(*cap2), GFP_KERNEL);
+       if (!cap2) {
+               err = -ENOMEM;
+               return err;
+       }
+       memset(cap, 0, sizeof(*cap));
+       memset(&fbuf, 0, sizeof(fbuf));
 
-               err = drv(inode, file, VIDIOC_QUERYCAP, cap2);
+       err = drv(inode, file, VIDIOC_QUERYCAP, cap2);
+       if (err < 0) {
+               dprintk("VIDIOCGCAP / VIDIOC_QUERYCAP: %d\n", err);
+               goto done;
+       }
+       if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY) {
+               err = drv(inode, file, VIDIOC_G_FBUF, &fbuf);
                if (err < 0) {
-                       dprintk("VIDIOCGCAP / VIDIOC_QUERYCAP: %d\n",err);
-                       break;
+                       dprintk("VIDIOCGCAP / VIDIOC_G_FBUF: %d\n", err);
+                       memset(&fbuf, 0, sizeof(fbuf));
                }
-               if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY) {
-                       err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2);
-                       if (err < 0) {
-                               dprintk("VIDIOCGCAP / VIDIOC_G_FBUF: %d\n",err);
-                               memset(&fbuf2, 0, sizeof(fbuf2));
-                       }
-                       err = 0;
-               }
-
-               memcpy(cap->name, cap2->card,
-                      min(sizeof(cap->name), sizeof(cap2->card)));
-               cap->name[sizeof(cap->name) - 1] = 0;
-               if (cap2->capabilities & V4L2_CAP_VIDEO_CAPTURE)
-                       cap->type |= VID_TYPE_CAPTURE;
-               if (cap2->capabilities & V4L2_CAP_TUNER)
-                       cap->type |= VID_TYPE_TUNER;
-               if (cap2->capabilities & V4L2_CAP_VBI_CAPTURE)
-                       cap->type |= VID_TYPE_TELETEXT;
-               if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY)
-                       cap->type |= VID_TYPE_OVERLAY;
-               if (fbuf2.capability & V4L2_FBUF_CAP_LIST_CLIPPING)
-                       cap->type |= VID_TYPE_CLIPPING;
-
-               cap->channels  = count_inputs(inode,file,drv);
-               check_size(inode,file,drv,
-                          &cap->maxwidth,&cap->maxheight);
-               cap->audios    =  0; /* FIXME */
-               cap->minwidth  = 48; /* FIXME */
-               cap->minheight = 32; /* FIXME */
-               break;
+               err = 0;
        }
-       case VIDIOCGFBUF: /*  get frame buffer  */
-       {
-               struct video_buffer     *buffer = arg;
 
-               memset(buffer, 0, sizeof(*buffer));
-               memset(&fbuf2, 0, sizeof(fbuf2));
+       memcpy(cap->name, cap2->card,
+              min(sizeof(cap->name), sizeof(cap2->card)));
+       cap->name[sizeof(cap->name) - 1] = 0;
+       if (cap2->capabilities & V4L2_CAP_VIDEO_CAPTURE)
+               cap->type |= VID_TYPE_CAPTURE;
+       if (cap2->capabilities & V4L2_CAP_TUNER)
+               cap->type |= VID_TYPE_TUNER;
+       if (cap2->capabilities & V4L2_CAP_VBI_CAPTURE)
+               cap->type |= VID_TYPE_TELETEXT;
+       if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY)
+               cap->type |= VID_TYPE_OVERLAY;
+       if (fbuf.capability & V4L2_FBUF_CAP_LIST_CLIPPING)
+               cap->type |= VID_TYPE_CLIPPING;
+
+       cap->channels  = count_inputs(inode, file, drv);
+       check_size(inode, file, drv,
+                  &cap->maxwidth, &cap->maxheight);
+       cap->audios    =  0; /* FIXME */
+       cap->minwidth  = 48; /* FIXME */
+       cap->minheight = 32; /* FIXME */
+
+done:
+       kfree(cap2);
+       return err;
+}
 
-               err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2);
-               if (err < 0) {
-                       dprintk("VIDIOCGFBUF / VIDIOC_G_FBUF: %d\n",err);
-                       break;
-               }
-               buffer->base   = fbuf2.base;
-               buffer->height = fbuf2.fmt.height;
-               buffer->width  = fbuf2.fmt.width;
+static noinline int v4l1_compat_get_frame_buffer(
+                                       struct video_buffer *buffer,
+                                       struct inode *inode,
+                                       struct file *file,
+                                       v4l2_kioctl drv)
+{
+       int err;
+       struct v4l2_framebuffer fbuf;
 
-               switch (fbuf2.fmt.pixelformat) {
-               case V4L2_PIX_FMT_RGB332:
-                       buffer->depth = 8;
-                       break;
-               case V4L2_PIX_FMT_RGB555:
-                       buffer->depth = 15;
-                       break;
-               case V4L2_PIX_FMT_RGB565:
-                       buffer->depth = 16;
-                       break;
-               case V4L2_PIX_FMT_BGR24:
-                       buffer->depth = 24;
-                       break;
-               case V4L2_PIX_FMT_BGR32:
-                       buffer->depth = 32;
-                       break;
-               default:
-                       buffer->depth = 0;
-               }
-               if (fbuf2.fmt.bytesperline) {
-                       buffer->bytesperline = fbuf2.fmt.bytesperline;
-                       if (!buffer->depth && buffer->width)
-                               buffer->depth   = ((fbuf2.fmt.bytesperline<<3)
-                                                 + (buffer->width-1) )
-                                                 /buffer->width;
-               } else {
-                       buffer->bytesperline =
-                               (buffer->width * buffer->depth + 7) & 7;
-                       buffer->bytesperline >>= 3;
-               }
+       memset(buffer, 0, sizeof(*buffer));
+       memset(&fbuf, 0, sizeof(fbuf));
+
+       err = drv(inode, file, VIDIOC_G_FBUF, &fbuf);
+       if (err < 0) {
+               dprintk("VIDIOCGFBUF / VIDIOC_G_FBUF: %d\n", err);
+               goto done;
+       }
+       buffer->base   = fbuf.base;
+       buffer->height = fbuf.fmt.height;
+       buffer->width  = fbuf.fmt.width;
+
+       switch (fbuf.fmt.pixelformat) {
+       case V4L2_PIX_FMT_RGB332:
+               buffer->depth = 8;
+               break;
+       case V4L2_PIX_FMT_RGB555:
+               buffer->depth = 15;
+               break;
+       case V4L2_PIX_FMT_RGB565:
+               buffer->depth = 16;
+               break;
+       case V4L2_PIX_FMT_BGR24:
+               buffer->depth = 24;
+               break;
+       case V4L2_PIX_FMT_BGR32:
+               buffer->depth = 32;
                break;
+       default:
+               buffer->depth = 0;
        }
-       case VIDIOCSFBUF: /*  set frame buffer  */
-       {
-               struct video_buffer     *buffer = arg;
-
-               memset(&fbuf2, 0, sizeof(fbuf2));
-               fbuf2.base       = buffer->base;
-               fbuf2.fmt.height = buffer->height;
-               fbuf2.fmt.width  = buffer->width;
-               switch (buffer->depth) {
-               case 8:
-                       fbuf2.fmt.pixelformat = V4L2_PIX_FMT_RGB332;
-                       break;
-               case 15:
-                       fbuf2.fmt.pixelformat = V4L2_PIX_FMT_RGB555;
-                       break;
-               case 16:
-                       fbuf2.fmt.pixelformat = V4L2_PIX_FMT_RGB565;
-                       break;
-               case 24:
-                       fbuf2.fmt.pixelformat = V4L2_PIX_FMT_BGR24;
-                       break;
-               case 32:
-                       fbuf2.fmt.pixelformat = V4L2_PIX_FMT_BGR32;
-                       break;
-               }
-               fbuf2.fmt.bytesperline = buffer->bytesperline;
-               err = drv(inode, file, VIDIOC_S_FBUF, &fbuf2);
-               if (err < 0)
-                       dprintk("VIDIOCSFBUF / VIDIOC_S_FBUF: %d\n",err);
+       if (fbuf.fmt.bytesperline) {
+               buffer->bytesperline = fbuf.fmt.bytesperline;
+               if (!buffer->depth && buffer->width)
+                       buffer->depth   = ((fbuf.fmt.bytesperline<<3)
+                                         + (buffer->width-1))
+                                         / buffer->width;
+       } else {
+               buffer->bytesperline =
+                       (buffer->width * buffer->depth + 7) & 7;
+               buffer->bytesperline >>= 3;
+       }
+done:
+       return err;
+}
+
+static noinline int v4l1_compat_set_frame_buffer(
+                                       struct video_buffer *buffer,
+                                       struct inode *inode,
+                                       struct file *file,
+                                       v4l2_kioctl drv)
+{
+       int err;
+       struct v4l2_framebuffer fbuf;
+
+       memset(&fbuf, 0, sizeof(fbuf));
+       fbuf.base       = buffer->base;
+       fbuf.fmt.height = buffer->height;
+       fbuf.fmt.width  = buffer->width;
+       switch (buffer->depth) {
+       case 8:
+               fbuf.fmt.pixelformat = V4L2_PIX_FMT_RGB332;
+               break;
+       case 15:
+               fbuf.fmt.pixelformat = V4L2_PIX_FMT_RGB555;
+               break;
+       case 16:
+               fbuf.fmt.pixelformat = V4L2_PIX_FMT_RGB565;
+               break;
+       case 24:
+               fbuf.fmt.pixelformat = V4L2_PIX_FMT_BGR24;
+               break;
+       case 32:
+               fbuf.fmt.pixelformat = V4L2_PIX_FMT_BGR32;
                break;
        }
-       case VIDIOCGWIN: /*  get window or capture dimensions  */
-       {
-               struct video_window     *win = arg;
+       fbuf.fmt.bytesperline = buffer->bytesperline;
+       err = drv(inode, file, VIDIOC_S_FBUF, &fbuf);
+       if (err < 0)
+               dprintk("VIDIOCSFBUF / VIDIOC_S_FBUF: %d\n", err);
+       return err;
+}
 
-               fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
-               if (!fmt2) {
-                       err = -ENOMEM;
-                       break;
-               }
-               memset(win,0,sizeof(*win));
+static noinline int v4l1_compat_get_win_cap_dimensions(
+                                       struct video_window *win,
+                                       struct inode *inode,
+                                       struct file *file,
+                                       v4l2_kioctl drv)
+{
+       int err;
+       struct v4l2_format *fmt;
 
-               fmt2->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
-               err = drv(inode, file, VIDIOC_G_FMT, fmt2);
-               if (err < 0)
-                       dprintk("VIDIOCGWIN / VIDIOC_G_WIN: %d\n",err);
-               if (err == 0) {
-                       win->x         = fmt2->fmt.win.w.left;
-                       win->y         = fmt2->fmt.win.w.top;
-                       win->width     = fmt2->fmt.win.w.width;
-                       win->height    = fmt2->fmt.win.w.height;
-                       win->chromakey = fmt2->fmt.win.chromakey;
-                       win->clips     = NULL;
-                       win->clipcount = 0;
-                       break;
-               }
+       fmt = kzalloc(sizeof(*fmt), GFP_KERNEL);
+       if (!fmt) {
+               err = -ENOMEM;
+               return err;
+       }
+       memset(win, 0, sizeof(*win));
 
-               fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               err = drv(inode, file, VIDIOC_G_FMT, fmt2);
-               if (err < 0) {
-                       dprintk("VIDIOCGWIN / VIDIOC_G_FMT: %d\n",err);
-                       break;
-               }
-               win->x         = 0;
-               win->y         = 0;
-               win->width     = fmt2->fmt.pix.width;
-               win->height    = fmt2->fmt.pix.height;
-               win->chromakey = 0;
+       fmt->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
+       err = drv(inode, file, VIDIOC_G_FMT, fmt);
+       if (err < 0)
+               dprintk("VIDIOCGWIN / VIDIOC_G_WIN: %d\n", err);
+       if (err == 0) {
+               win->x         = fmt->fmt.win.w.left;
+               win->y         = fmt->fmt.win.w.top;
+               win->width     = fmt->fmt.win.w.width;
+               win->height    = fmt->fmt.win.w.height;
+               win->chromakey = fmt->fmt.win.chromakey;
                win->clips     = NULL;
                win->clipcount = 0;
-               break;
+               goto done;
        }
-       case VIDIOCSWIN: /*  set window and/or capture dimensions  */
-       {
-               struct video_window     *win = arg;
-               int err1,err2;
 
-               fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
-               if (!fmt2) {
-                       err = -ENOMEM;
-                       break;
-               }
-               fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               drv(inode, file, VIDIOC_STREAMOFF, &fmt2->type);
-               err1 = drv(inode, file, VIDIOC_G_FMT, fmt2);
-               if (err1 < 0)
-                       dprintk("VIDIOCSWIN / VIDIOC_G_FMT: %d\n",err);
-               if (err1 == 0) {
-                       fmt2->fmt.pix.width  = win->width;
-                       fmt2->fmt.pix.height = win->height;
-                       fmt2->fmt.pix.field  = V4L2_FIELD_ANY;
-                       fmt2->fmt.pix.bytesperline = 0;
-                       err = drv(inode, file, VIDIOC_S_FMT, fmt2);
-                       if (err < 0)
-                               dprintk("VIDIOCSWIN / VIDIOC_S_FMT #1: %d\n",
-                                       err);
-                       win->width  = fmt2->fmt.pix.width;
-                       win->height = fmt2->fmt.pix.height;
-               }
+       fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       err = drv(inode, file, VIDIOC_G_FMT, fmt);
+       if (err < 0) {
+               dprintk("VIDIOCGWIN / VIDIOC_G_FMT: %d\n", err);
+               goto done;
+       }
+       win->x         = 0;
+       win->y         = 0;
+       win->width     = fmt->fmt.pix.width;
+       win->height    = fmt->fmt.pix.height;
+       win->chromakey = 0;
+       win->clips     = NULL;
+       win->clipcount = 0;
+done:
+       kfree(fmt);
+       return err;
+}
 
-               memset(fmt2,0,sizeof(*fmt2));
-               fmt2->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
-               fmt2->fmt.win.w.left    = win->x;
-               fmt2->fmt.win.w.top     = win->y;
-               fmt2->fmt.win.w.width   = win->width;
-               fmt2->fmt.win.w.height  = win->height;
-               fmt2->fmt.win.chromakey = win->chromakey;
-               fmt2->fmt.win.clips     = (void __user *)win->clips;
-               fmt2->fmt.win.clipcount = win->clipcount;
-               err2 = drv(inode, file, VIDIOC_S_FMT, fmt2);
-               if (err2 < 0)
-                       dprintk("VIDIOCSWIN / VIDIOC_S_FMT #2: %d\n",err);
-
-               if (err1 != 0 && err2 != 0)
-                       err = err1;
-               break;
+static noinline int v4l1_compat_set_win_cap_dimensions(
+                                       struct video_window *win,
+                                       struct inode *inode,
+                                       struct file *file,
+                                       v4l2_kioctl drv)
+{
+       int err, err1, err2;
+       struct v4l2_format *fmt;
+
+       fmt = kzalloc(sizeof(*fmt), GFP_KERNEL);
+       if (!fmt) {
+               err = -ENOMEM;
+               return err;
        }
-       case VIDIOCCAPTURE: /*  turn on/off preview  */
-       {
-               int *on = arg;
-
-               if (0 == *on) {
-                       /* dirty hack time.  But v4l1 has no STREAMOFF
-                        * equivalent in the API, and this one at
-                        * least comes close ... */
-                       drv(inode, file, VIDIOC_STREAMOFF, &captype);
-               }
-               err = drv(inode, file, VIDIOC_OVERLAY, arg);
+       fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       drv(inode, file, VIDIOC_STREAMOFF, &fmt->type);
+       err1 = drv(inode, file, VIDIOC_G_FMT, fmt);
+       if (err1 < 0)
+               dprintk("VIDIOCSWIN / VIDIOC_G_FMT: %d\n", err1);
+       if (err1 == 0) {
+               fmt->fmt.pix.width  = win->width;
+               fmt->fmt.pix.height = win->height;
+               fmt->fmt.pix.field  = V4L2_FIELD_ANY;
+               fmt->fmt.pix.bytesperline = 0;
+               err = drv(inode, file, VIDIOC_S_FMT, fmt);
                if (err < 0)
-                       dprintk("VIDIOCCAPTURE / VIDIOC_PREVIEW: %d\n",err);
-               break;
+                       dprintk("VIDIOCSWIN / VIDIOC_S_FMT #1: %d\n",
+                               err);
+               win->width  = fmt->fmt.pix.width;
+               win->height = fmt->fmt.pix.height;
        }
-       case VIDIOCGCHAN: /*  get input information  */
-       {
-               struct video_channel    *chan = arg;
 
-               memset(&input2,0,sizeof(input2));
-               input2.index = chan->channel;
-               err = drv(inode, file, VIDIOC_ENUMINPUT, &input2);
-               if (err < 0) {
-                       dprintk("VIDIOCGCHAN / VIDIOC_ENUMINPUT: "
-                               "channel=%d err=%d\n",chan->channel,err);
-                       break;
-               }
-               chan->channel = input2.index;
-               memcpy(chan->name, input2.name,
-                      min(sizeof(chan->name), sizeof(input2.name)));
-               chan->name[sizeof(chan->name) - 1] = 0;
-               chan->tuners = (input2.type == V4L2_INPUT_TYPE_TUNER) ? 1 : 0;
-               chan->flags = (chan->tuners) ? VIDEO_VC_TUNER : 0;
-               switch (input2.type) {
-               case V4L2_INPUT_TYPE_TUNER:
-                       chan->type = VIDEO_TYPE_TV;
-                       break;
-               default:
-               case V4L2_INPUT_TYPE_CAMERA:
-                       chan->type = VIDEO_TYPE_CAMERA;
-                       break;
-               }
-               chan->norm = 0;
-               err = drv(inode, file, VIDIOC_G_STD, &sid);
-               if (err < 0)
-                       dprintk("VIDIOCGCHAN / VIDIOC_G_STD: %d\n",err);
-               if (err == 0) {
-                       if (sid & V4L2_STD_PAL)
-                               chan->norm = VIDEO_MODE_PAL;
-                       if (sid & V4L2_STD_NTSC)
-                               chan->norm = VIDEO_MODE_NTSC;
-                       if (sid & V4L2_STD_SECAM)
-                               chan->norm = VIDEO_MODE_SECAM;
-               }
-               break;
-       }
-       case VIDIOCSCHAN: /*  set input  */
-       {
-               struct video_channel *chan = arg;
+       memset(fmt, 0, sizeof(*fmt));
+       fmt->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
+       fmt->fmt.win.w.left    = win->x;
+       fmt->fmt.win.w.top     = win->y;
+       fmt->fmt.win.w.width   = win->width;
+       fmt->fmt.win.w.height  = win->height;
+       fmt->fmt.win.chromakey = win->chromakey;
+       fmt->fmt.win.clips     = (void __user *)win->clips;
+       fmt->fmt.win.clipcount = win->clipcount;
+       err2 = drv(inode, file, VIDIOC_S_FMT, fmt);
+       if (err2 < 0)
+               dprintk("VIDIOCSWIN / VIDIOC_S_FMT #2: %d\n", err2);
+
+       if (err1 != 0 && err2 != 0)
+               err = err1;
+       else
+               err = 0;
+       kfree(fmt);
+       return err;
+}
 
-               sid = 0;
-               err = drv(inode, file, VIDIOC_S_INPUT, &chan->channel);
-               if (err < 0)
-                       dprintk("VIDIOCSCHAN / VIDIOC_S_INPUT: %d\n",err);
-               switch (chan->norm) {
-               case VIDEO_MODE_PAL:
-                       sid = V4L2_STD_PAL;
-                       break;
-               case VIDEO_MODE_NTSC:
-                       sid = V4L2_STD_NTSC;
-                       break;
-               case VIDEO_MODE_SECAM:
-                       sid = V4L2_STD_SECAM;
-                       break;
-               }
-               if (0 != sid) {
-                       err = drv(inode, file, VIDIOC_S_STD, &sid);
-                       if (err < 0)
-                               dprintk("VIDIOCSCHAN / VIDIOC_S_STD: %d\n",err);
-               }
-               break;
+static noinline int v4l1_compat_turn_preview_on_off(
+                                       int *on,
+                                       struct inode *inode,
+                                       struct file *file,
+                                       v4l2_kioctl drv)
+{
+       int err;
+       enum v4l2_buf_type captype = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+       if (0 == *on) {
+               /* dirty hack time.  But v4l1 has no STREAMOFF
+                * equivalent in the API, and this one at
+                * least comes close ... */
+               drv(inode, file, VIDIOC_STREAMOFF, &captype);
        }
-       case VIDIOCGPICT: /*  get tone controls & partial capture format  */
-       {
-               struct video_picture    *pict = arg;
-
-               fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
-               if (!fmt2) {
-                       err = -ENOMEM;
-                       break;
-               }
+       err = drv(inode, file, VIDIOC_OVERLAY, on);
+       if (err < 0)
+               dprintk("VIDIOCCAPTURE / VIDIOC_PREVIEW: %d\n", err);
+       return err;
+}
 
-               pict->brightness = get_v4l_control(inode, file,
-                                                  V4L2_CID_BRIGHTNESS,drv);
-               pict->hue = get_v4l_control(inode, file,
-                                           V4L2_CID_HUE, drv);
-               pict->contrast = get_v4l_control(inode, file,
-                                                V4L2_CID_CONTRAST, drv);
-               pict->colour = get_v4l_control(inode, file,
-                                              V4L2_CID_SATURATION, drv);
-               pict->whiteness = get_v4l_control(inode, file,
-                                                 V4L2_CID_WHITENESS, drv);
-
-               fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               err = drv(inode, file, VIDIOC_G_FMT, fmt2);
-               if (err < 0) {
-                       dprintk("VIDIOCGPICT / VIDIOC_G_FMT: %d\n",err);
-                       break;
-               }
+static noinline int v4l1_compat_get_input_info(
+                                       struct video_channel *chan,
+                                       struct inode *inode,
+                                       struct file *file,
+                                       v4l2_kioctl drv)
+{
+       int err;
+       struct v4l2_input       input2;
+       v4l2_std_id             sid;
 
-               pict->depth   = ((fmt2->fmt.pix.bytesperline<<3)
-                                + (fmt2->fmt.pix.width-1) )
-                                /fmt2->fmt.pix.width;
-               pict->palette = pixelformat_to_palette(
-                       fmt2->fmt.pix.pixelformat);
+       memset(&input2, 0, sizeof(input2));
+       input2.index = chan->channel;
+       err = drv(inode, file, VIDIOC_ENUMINPUT, &input2);
+       if (err < 0) {
+               dprintk("VIDIOCGCHAN / VIDIOC_ENUMINPUT: "
+                       "channel=%d err=%d\n", chan->channel, err);
+               goto done;
+       }
+       chan->channel = input2.index;
+       memcpy(chan->name, input2.name,
+              min(sizeof(chan->name), sizeof(input2.name)));
+       chan->name[sizeof(chan->name) - 1] = 0;
+       chan->tuners = (input2.type == V4L2_INPUT_TYPE_TUNER) ? 1 : 0;
+       chan->flags = (chan->tuners) ? VIDEO_VC_TUNER : 0;
+       switch (input2.type) {
+       case V4L2_INPUT_TYPE_TUNER:
+               chan->type = VIDEO_TYPE_TV;
+               break;
+       default:
+       case V4L2_INPUT_TYPE_CAMERA:
+               chan->type = VIDEO_TYPE_CAMERA;
                break;
        }
-       case VIDIOCSPICT: /*  set tone controls & partial capture format  */
-       {
-               struct video_picture    *pict = arg;
-               int mem_err = 0, ovl_err = 0;
+       chan->norm = 0;
+       err = drv(inode, file, VIDIOC_G_STD, &sid);
+       if (err < 0)
+               dprintk("VIDIOCGCHAN / VIDIOC_G_STD: %d\n", err);
+       if (err == 0) {
+               if (sid & V4L2_STD_PAL)
+                       chan->norm = VIDEO_MODE_PAL;
+               if (sid & V4L2_STD_NTSC)
+                       chan->norm = VIDEO_MODE_NTSC;
+               if (sid & V4L2_STD_SECAM)
+                       chan->norm = VIDEO_MODE_SECAM;
+       }
+done:
+       return err;
+}
 
-               fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
-               if (!fmt2) {
-                       err = -ENOMEM;
-                       break;
-               }
-               memset(&fbuf2, 0, sizeof(fbuf2));
-
-               set_v4l_control(inode, file,
-                               V4L2_CID_BRIGHTNESS, pict->brightness, drv);
-               set_v4l_control(inode, file,
-                               V4L2_CID_HUE, pict->hue, drv);
-               set_v4l_control(inode, file,
-                               V4L2_CID_CONTRAST, pict->contrast, drv);
-               set_v4l_control(inode, file,
-                               V4L2_CID_SATURATION, pict->colour, drv);
-               set_v4l_control(inode, file,
-                               V4L2_CID_WHITENESS, pict->whiteness, drv);
-               /*
-                * V4L1 uses this ioctl to set both memory capture and overlay
-                * pixel format, while V4L2 has two different ioctls for this.
-                * Some cards may not support one or the other, and may support
-                * different pixel formats for memory vs overlay.
-                */
-
-               fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               err = drv(inode, file, VIDIOC_G_FMT, fmt2);
-               /* If VIDIOC_G_FMT failed, then the driver likely doesn't
-                  support memory capture.  Trying to set the memory capture
-                  parameters would be pointless.  */
-               if (err < 0) {
-                       dprintk("VIDIOCSPICT / VIDIOC_G_FMT: %d\n",err);
-                       mem_err = -1000;  /* didn't even try */
-               } else if (fmt2->fmt.pix.pixelformat !=
-                        palette_to_pixelformat(pict->palette)) {
-                       fmt2->fmt.pix.pixelformat = palette_to_pixelformat(
-                               pict->palette);
-                       mem_err = drv(inode, file, VIDIOC_S_FMT, fmt2);
-                       if (mem_err < 0)
-                               dprintk("VIDIOCSPICT / VIDIOC_S_FMT: %d\n",
-                                       mem_err);
-               }
+static noinline int v4l1_compat_set_input(
+                                       struct video_channel *chan,
+                                       struct inode *inode,
+                                       struct file *file,
+                                       v4l2_kioctl drv)
+{
+       int err;
+       v4l2_std_id sid = 0;
 
-               err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2);
-               /* If VIDIOC_G_FBUF failed, then the driver likely doesn't
-                  support overlay.  Trying to set the overlay parameters
-                  would be quite pointless.  */
-               if (err < 0) {
-                       dprintk("VIDIOCSPICT / VIDIOC_G_FBUF: %d\n",err);
-                       ovl_err = -1000;  /* didn't even try */
-               } else if (fbuf2.fmt.pixelformat !=
-                        palette_to_pixelformat(pict->palette)) {
-                       fbuf2.fmt.pixelformat = palette_to_pixelformat(
-                               pict->palette);
-                       ovl_err = drv(inode, file, VIDIOC_S_FBUF, &fbuf2);
-                       if (ovl_err < 0)
-                               dprintk("VIDIOCSPICT / VIDIOC_S_FBUF: %d\n",
-                                       ovl_err);
-               }
-               if (ovl_err < 0 && mem_err < 0)
-                       /* ioctl failed, couldn't set either parameter */
-                       if (mem_err != -1000) {
-                           err = mem_err;
-                       } else if (ovl_err == -EPERM) {
-                           err = 0;
-                       } else {
-                           err = ovl_err;
-                       }
-               else
-                       err = 0;
+       err = drv(inode, file, VIDIOC_S_INPUT, &chan->channel);
+       if (err < 0)
+               dprintk("VIDIOCSCHAN / VIDIOC_S_INPUT: %d\n", err);
+       switch (chan->norm) {
+       case VIDEO_MODE_PAL:
+               sid = V4L2_STD_PAL;
+               break;
+       case VIDEO_MODE_NTSC:
+               sid = V4L2_STD_NTSC;
+               break;
+       case VIDEO_MODE_SECAM:
+               sid = V4L2_STD_SECAM;
                break;
        }
-       case VIDIOCGTUNER: /*  get tuner information  */
-       {
-               struct video_tuner      *tun = arg;
-
-               memset(&tun2,0,sizeof(tun2));
-               err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
-               if (err < 0) {
-                       dprintk("VIDIOCGTUNER / VIDIOC_G_TUNER: %d\n",err);
-                       break;
-               }
-               memcpy(tun->name, tun2.name,
-                      min(sizeof(tun->name), sizeof(tun2.name)));
-               tun->name[sizeof(tun->name) - 1] = 0;
-               tun->rangelow = tun2.rangelow;
-               tun->rangehigh = tun2.rangehigh;
-               tun->flags = 0;
-               tun->mode = VIDEO_MODE_AUTO;
-
-               for (i = 0; i < 64; i++) {
-                       memset(&std2,0,sizeof(std2));
-                       std2.index = i;
-                       if (0 != drv(inode, file, VIDIOC_ENUMSTD, &std2))
-                               break;
-                       if (std2.id & V4L2_STD_PAL)
-                               tun->flags |= VIDEO_TUNER_PAL;
-                       if (std2.id & V4L2_STD_NTSC)
-                               tun->flags |= VIDEO_TUNER_NTSC;
-                       if (std2.id & V4L2_STD_SECAM)
-                               tun->flags |= VIDEO_TUNER_SECAM;
-               }
-
-               err = drv(inode, file, VIDIOC_G_STD, &sid);
+       if (0 != sid) {
+               err = drv(inode, file, VIDIOC_S_STD, &sid);
                if (err < 0)
-                       dprintk("VIDIOCGTUNER / VIDIOC_G_STD: %d\n",err);
-               if (err == 0) {
-                       if (sid & V4L2_STD_PAL)
-                               tun->mode = VIDEO_MODE_PAL;
-                       if (sid & V4L2_STD_NTSC)
-                               tun->mode = VIDEO_MODE_NTSC;
-                       if (sid & V4L2_STD_SECAM)
-                               tun->mode = VIDEO_MODE_SECAM;
-               }
-
-               if (tun2.capability & V4L2_TUNER_CAP_LOW)
-                       tun->flags |= VIDEO_TUNER_LOW;
-               if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO)
-                       tun->flags |= VIDEO_TUNER_STEREO_ON;
-               tun->signal = tun2.signal;
-               break;
+                       dprintk("VIDIOCSCHAN / VIDIOC_S_STD: %d\n", err);
        }
-       case VIDIOCSTUNER: /*  select a tuner input  */
-       {
-               struct video_tuner      *tun = arg;
-               struct v4l2_tuner       t;
-               memset(&t,0,sizeof(t));
-
-               t.index=tun->tuner;
+       return err;
+}
 
-               err = drv(inode, file, VIDIOC_S_INPUT, &t);
-               if (err < 0)
-                       dprintk("VIDIOCSTUNER / VIDIOC_S_INPUT: %d\n",err);
+static noinline int v4l1_compat_get_picture(
+                                       struct video_picture *pict,
+                                       struct inode *inode,
+                                       struct file *file,
+                                       v4l2_kioctl drv)
+{
+       int err;
+       struct v4l2_format *fmt;
 
-               break;
+       fmt = kzalloc(sizeof(*fmt), GFP_KERNEL);
+       if (!fmt) {
+               err = -ENOMEM;
+               return err;
        }
-       case VIDIOCGFREQ: /*  get frequency  */
-       {
-               unsigned long *freq = arg;
-               memset(&freq2,0,sizeof(freq2));
 
-               freq2.tuner = 0;
-               err = drv(inode, file, VIDIOC_G_FREQUENCY, &freq2);
-               if (err < 0)
-                       dprintk("VIDIOCGFREQ / VIDIOC_G_FREQUENCY: %d\n",err);
-               if (0 == err)
-                       *freq = freq2.frequency;
-               break;
+       pict->brightness = get_v4l_control(inode, file,
+                                          V4L2_CID_BRIGHTNESS, drv);
+       pict->hue = get_v4l_control(inode, file,
+                                   V4L2_CID_HUE, drv);
+       pict->contrast = get_v4l_control(inode, file,
+                                        V4L2_CID_CONTRAST, drv);
+       pict->colour = get_v4l_control(inode, file,
+                                      V4L2_CID_SATURATION, drv);
+       pict->whiteness = get_v4l_control(inode, file,
+                                         V4L2_CID_WHITENESS, drv);
+
+       fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       err = drv(inode, file, VIDIOC_G_FMT, fmt);
+       if (err < 0) {
+               dprintk("VIDIOCGPICT / VIDIOC_G_FMT: %d\n", err);
+               goto done;
        }
-       case VIDIOCSFREQ: /*  set frequency  */
-       {
-               unsigned long *freq = arg;
-               memset(&freq2,0,sizeof(freq2));
 
-               drv(inode, file, VIDIOC_G_FREQUENCY, &freq2);
-               freq2.frequency = *freq;
-               err = drv(inode, file, VIDIOC_S_FREQUENCY, &freq2);
-               if (err < 0)
-                       dprintk("VIDIOCSFREQ / VIDIOC_S_FREQUENCY: %d\n",err);
-               break;
+       pict->depth   = ((fmt->fmt.pix.bytesperline << 3)
+                        + (fmt->fmt.pix.width - 1))
+                        / fmt->fmt.pix.width;
+       pict->palette = pixelformat_to_palette(
+               fmt->fmt.pix.pixelformat);
+done:
+       kfree(fmt);
+       return err;
+}
+
+static noinline int v4l1_compat_set_picture(
+                                       struct video_picture *pict,
+                                       struct inode *inode,
+                                       struct file *file,
+                                       v4l2_kioctl drv)
+{
+       int err;
+       struct v4l2_framebuffer fbuf;
+       int mem_err = 0, ovl_err = 0;
+       struct v4l2_format *fmt;
+
+       fmt = kzalloc(sizeof(*fmt), GFP_KERNEL);
+       if (!fmt) {
+               err = -ENOMEM;
+               return err;
+       }
+       memset(&fbuf, 0, sizeof(fbuf));
+
+       set_v4l_control(inode, file,
+                       V4L2_CID_BRIGHTNESS, pict->brightness, drv);
+       set_v4l_control(inode, file,
+                       V4L2_CID_HUE, pict->hue, drv);
+       set_v4l_control(inode, file,
+                       V4L2_CID_CONTRAST, pict->contrast, drv);
+       set_v4l_control(inode, file,
+                       V4L2_CID_SATURATION, pict->colour, drv);
+       set_v4l_control(inode, file,
+                       V4L2_CID_WHITENESS, pict->whiteness, drv);
+       /*
+        * V4L1 uses this ioctl to set both memory capture and overlay
+        * pixel format, while V4L2 has two different ioctls for this.
+        * Some cards may not support one or the other, and may support
+        * different pixel formats for memory vs overlay.
+        */
+
+       fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       err = drv(inode, file, VIDIOC_G_FMT, fmt);
+       /* If VIDIOC_G_FMT failed, then the driver likely doesn't
+          support memory capture.  Trying to set the memory capture
+          parameters would be pointless.  */
+       if (err < 0) {
+               dprintk("VIDIOCSPICT / VIDIOC_G_FMT: %d\n", err);
+               mem_err = -1000;  /* didn't even try */
+       } else if (fmt->fmt.pix.pixelformat !=
+                palette_to_pixelformat(pict->palette)) {
+               fmt->fmt.pix.pixelformat = palette_to_pixelformat(
+                       pict->palette);
+               mem_err = drv(inode, file, VIDIOC_S_FMT, fmt);
+               if (mem_err < 0)
+                       dprintk("VIDIOCSPICT / VIDIOC_S_FMT: %d\n",
+                               mem_err);
        }
-       case VIDIOCGAUDIO: /*  get audio properties/controls  */
-       {
-               struct video_audio      *aud = arg;
-               memset(&aud2,0,sizeof(aud2));
 
-               err = drv(inode, file, VIDIOC_G_AUDIO, &aud2);
-               if (err < 0) {
-                       dprintk("VIDIOCGAUDIO / VIDIOC_G_AUDIO: %d\n",err);
-                       break;
-               }
-               memcpy(aud->name, aud2.name,
-                      min(sizeof(aud->name), sizeof(aud2.name)));
-               aud->name[sizeof(aud->name) - 1] = 0;
-               aud->audio = aud2.index;
-               aud->flags = 0;
-               i = get_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME, drv);
-               if (i >= 0) {
-                       aud->volume = i;
-                       aud->flags |= VIDEO_AUDIO_VOLUME;
-               }
-               i = get_v4l_control(inode, file, V4L2_CID_AUDIO_BASS, drv);
-               if (i >= 0) {
-                       aud->bass = i;
-                       aud->flags |= VIDEO_AUDIO_BASS;
-               }
-               i = get_v4l_control(inode, file, V4L2_CID_AUDIO_TREBLE, drv);
-               if (i >= 0) {
-                       aud->treble = i;
-                       aud->flags |= VIDEO_AUDIO_TREBLE;
-               }
-               i = get_v4l_control(inode, file, V4L2_CID_AUDIO_BALANCE, drv);
-               if (i >= 0) {
-                       aud->balance = i;
-                       aud->flags |= VIDEO_AUDIO_BALANCE;
-               }
-               i = get_v4l_control(inode, file, V4L2_CID_AUDIO_MUTE, drv);
-               if (i >= 0) {
-                       if (i)
-                               aud->flags |= VIDEO_AUDIO_MUTE;
-                       aud->flags |= VIDEO_AUDIO_MUTABLE;
-               }
-               aud->step = 1;
-               qctrl2.id = V4L2_CID_AUDIO_VOLUME;
-               if (drv(inode, file, VIDIOC_QUERYCTRL, &qctrl2) == 0 &&
-                   !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED))
-                       aud->step = qctrl2.step;
-               aud->mode = 0;
-
-               memset(&tun2,0,sizeof(tun2));
-               err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
-               if (err < 0) {
-                       dprintk("VIDIOCGAUDIO / VIDIOC_G_TUNER: %d\n",err);
+       err = drv(inode, file, VIDIOC_G_FBUF, &fbuf);
+       /* If VIDIOC_G_FBUF failed, then the driver likely doesn't
+          support overlay.  Trying to set the overlay parameters
+          would be quite pointless.  */
+       if (err < 0) {
+               dprintk("VIDIOCSPICT / VIDIOC_G_FBUF: %d\n", err);
+               ovl_err = -1000;  /* didn't even try */
+       } else if (fbuf.fmt.pixelformat !=
+                palette_to_pixelformat(pict->palette)) {
+               fbuf.fmt.pixelformat = palette_to_pixelformat(
+                       pict->palette);
+               ovl_err = drv(inode, file, VIDIOC_S_FBUF, &fbuf);
+               if (ovl_err < 0)
+                       dprintk("VIDIOCSPICT / VIDIOC_S_FBUF: %d\n",
+                               ovl_err);
+       }
+       if (ovl_err < 0 && mem_err < 0) {
+               /* ioctl failed, couldn't set either parameter */
+               if (mem_err != -1000)
+                       err = mem_err;
+               else if (ovl_err == -EPERM)
                        err = 0;
+               else
+                       err = ovl_err;
+       } else
+               err = 0;
+       kfree(fmt);
+       return err;
+}
+
+static noinline int v4l1_compat_get_tuner(
+                                       struct video_tuner *tun,
+                                       struct inode *inode,
+                                       struct file *file,
+                                       v4l2_kioctl drv)
+{
+       int err, i;
+       struct v4l2_tuner       tun2;
+       struct v4l2_standard    std2;
+       v4l2_std_id             sid;
+
+       memset(&tun2, 0, sizeof(tun2));
+       err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
+       if (err < 0) {
+               dprintk("VIDIOCGTUNER / VIDIOC_G_TUNER: %d\n", err);
+               goto done;
+       }
+       memcpy(tun->name, tun2.name,
+              min(sizeof(tun->name), sizeof(tun2.name)));
+       tun->name[sizeof(tun->name) - 1] = 0;
+       tun->rangelow = tun2.rangelow;
+       tun->rangehigh = tun2.rangehigh;
+       tun->flags = 0;
+       tun->mode = VIDEO_MODE_AUTO;
+
+       for (i = 0; i < 64; i++) {
+               memset(&std2, 0, sizeof(std2));
+               std2.index = i;
+               if (0 != drv(inode, file, VIDIOC_ENUMSTD, &std2))
                        break;
-               }
+               if (std2.id & V4L2_STD_PAL)
+                       tun->flags |= VIDEO_TUNER_PAL;
+               if (std2.id & V4L2_STD_NTSC)
+                       tun->flags |= VIDEO_TUNER_NTSC;
+               if (std2.id & V4L2_STD_SECAM)
+                       tun->flags |= VIDEO_TUNER_SECAM;
+       }
 
-               if (tun2.rxsubchans & V4L2_TUNER_SUB_LANG2)
-                       aud->mode = VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
-               else if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO)
-                       aud->mode = VIDEO_SOUND_STEREO;
-               else if (tun2.rxsubchans & V4L2_TUNER_SUB_MONO)
-                       aud->mode = VIDEO_SOUND_MONO;
-               break;
+       err = drv(inode, file, VIDIOC_G_STD, &sid);
+       if (err < 0)
+               dprintk("VIDIOCGTUNER / VIDIOC_G_STD: %d\n", err);
+       if (err == 0) {
+               if (sid & V4L2_STD_PAL)
+                       tun->mode = VIDEO_MODE_PAL;
+               if (sid & V4L2_STD_NTSC)
+                       tun->mode = VIDEO_MODE_NTSC;
+               if (sid & V4L2_STD_SECAM)
+                       tun->mode = VIDEO_MODE_SECAM;
        }
-       case VIDIOCSAUDIO: /*  set audio controls  */
-       {
-               struct video_audio      *aud = arg;
 
-               memset(&aud2,0,sizeof(aud2));
-               memset(&tun2,0,sizeof(tun2));
+       if (tun2.capability & V4L2_TUNER_CAP_LOW)
+               tun->flags |= VIDEO_TUNER_LOW;
+       if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO)
+               tun->flags |= VIDEO_TUNER_STEREO_ON;
+       tun->signal = tun2.signal;
+done:
+       return err;
+}
 
-               aud2.index = aud->audio;
-               err = drv(inode, file, VIDIOC_S_AUDIO, &aud2);
-               if (err < 0) {
-                       dprintk("VIDIOCSAUDIO / VIDIOC_S_AUDIO: %d\n",err);
-                       break;
-               }
+static noinline int v4l1_compat_select_tuner(
+                                       struct video_tuner *tun,
+                                       struct inode *inode,
+                                       struct file *file,
+                                       v4l2_kioctl drv)
+{
+       int err;
+       struct v4l2_tuner       t;/*84 bytes on x86_64*/
+       memset(&t, 0, sizeof(t));
 
-               set_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME,
-                               aud->volume, drv);
-               set_v4l_control(inode, file, V4L2_CID_AUDIO_BASS,
-                               aud->bass, drv);
-               set_v4l_control(inode, file, V4L2_CID_AUDIO_TREBLE,
-                               aud->treble, drv);
-               set_v4l_control(inode, file, V4L2_CID_AUDIO_BALANCE,
-                               aud->balance, drv);
-               set_v4l_control(inode, file, V4L2_CID_AUDIO_MUTE,
-                               !!(aud->flags & VIDEO_AUDIO_MUTE), drv);
-
-               err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
-               if (err < 0)
-                       dprintk("VIDIOCSAUDIO / VIDIOC_G_TUNER: %d\n",err);
-               if (err == 0) {
-                       switch (aud->mode) {
-                       default:
-                       case VIDEO_SOUND_MONO:
-                       case VIDEO_SOUND_LANG1:
-                               tun2.audmode = V4L2_TUNER_MODE_MONO;
-                               break;
-                       case VIDEO_SOUND_STEREO:
-                               tun2.audmode = V4L2_TUNER_MODE_STEREO;
-                               break;
-                       case VIDEO_SOUND_LANG2:
-                               tun2.audmode = V4L2_TUNER_MODE_LANG2;
-                               break;
-                       }
-                       err = drv(inode, file, VIDIOC_S_TUNER, &tun2);
-                       if (err < 0)
-                               dprintk("VIDIOCSAUDIO / VIDIOC_S_TUNER: %d\n",err);
-               }
+       t.index = tun->tuner;
+
+       err = drv(inode, file, VIDIOC_S_INPUT, &t);
+       if (err < 0)
+               dprintk("VIDIOCSTUNER / VIDIOC_S_INPUT: %d\n", err);
+       return err;
+}
+
+static noinline int v4l1_compat_get_frequency(
+                                       unsigned long *freq,
+                                       struct inode *inode,
+                                       struct file *file,
+                                       v4l2_kioctl drv)
+{
+       int err;
+       struct v4l2_frequency   freq2;
+       memset(&freq2, 0, sizeof(freq2));
+
+       freq2.tuner = 0;
+       err = drv(inode, file, VIDIOC_G_FREQUENCY, &freq2);
+       if (err < 0)
+               dprintk("VIDIOCGFREQ / VIDIOC_G_FREQUENCY: %d\n", err);
+       if (0 == err)
+               *freq = freq2.frequency;
+       return err;
+}
+
+static noinline int v4l1_compat_set_frequency(
+                                       unsigned long *freq,
+                                       struct inode *inode,
+                                       struct file *file,
+                                       v4l2_kioctl drv)
+{
+       int err;
+       struct v4l2_frequency   freq2;
+       memset(&freq2, 0, sizeof(freq2));
+
+       drv(inode, file, VIDIOC_G_FREQUENCY, &freq2);
+       freq2.frequency = *freq;
+       err = drv(inode, file, VIDIOC_S_FREQUENCY, &freq2);
+       if (err < 0)
+               dprintk("VIDIOCSFREQ / VIDIOC_S_FREQUENCY: %d\n", err);
+       return err;
+}
+
+static noinline int v4l1_compat_get_audio(
+                                       struct video_audio *aud,
+                                       struct inode *inode,
+                                       struct file *file,
+                                       v4l2_kioctl drv)
+{
+       int err, i;
+       struct v4l2_queryctrl   qctrl2;
+       struct v4l2_audio       aud2;
+       struct v4l2_tuner       tun2;
+       memset(&aud2, 0, sizeof(aud2));
+
+       err = drv(inode, file, VIDIOC_G_AUDIO, &aud2);
+       if (err < 0) {
+               dprintk("VIDIOCGAUDIO / VIDIOC_G_AUDIO: %d\n", err);
+               goto done;
+       }
+       memcpy(aud->name, aud2.name,
+              min(sizeof(aud->name), sizeof(aud2.name)));
+       aud->name[sizeof(aud->name) - 1] = 0;
+       aud->audio = aud2.index;
+       aud->flags = 0;
+       i = get_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME, drv);
+       if (i >= 0) {
+               aud->volume = i;
+               aud->flags |= VIDEO_AUDIO_VOLUME;
+       }
+       i = get_v4l_control(inode, file, V4L2_CID_AUDIO_BASS, drv);
+       if (i >= 0) {
+               aud->bass = i;
+               aud->flags |= VIDEO_AUDIO_BASS;
+       }
+       i = get_v4l_control(inode, file, V4L2_CID_AUDIO_TREBLE, drv);
+       if (i >= 0) {
+               aud->treble = i;
+               aud->flags |= VIDEO_AUDIO_TREBLE;
+       }
+       i = get_v4l_control(inode, file, V4L2_CID_AUDIO_BALANCE, drv);
+       if (i >= 0) {
+               aud->balance = i;
+               aud->flags |= VIDEO_AUDIO_BALANCE;
+       }
+       i = get_v4l_control(inode, file, V4L2_CID_AUDIO_MUTE, drv);
+       if (i >= 0) {
+               if (i)
+                       aud->flags |= VIDEO_AUDIO_MUTE;
+               aud->flags |= VIDEO_AUDIO_MUTABLE;
+       }
+       aud->step = 1;
+       qctrl2.id = V4L2_CID_AUDIO_VOLUME;
+       if (drv(inode, file, VIDIOC_QUERYCTRL, &qctrl2) == 0 &&
+           !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED))
+               aud->step = qctrl2.step;
+       aud->mode = 0;
+
+       memset(&tun2, 0, sizeof(tun2));
+       err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
+       if (err < 0) {
+               dprintk("VIDIOCGAUDIO / VIDIOC_G_TUNER: %d\n", err);
                err = 0;
-               break;
+               goto done;
        }
-       case VIDIOCMCAPTURE: /*  capture a frame  */
-       {
-               struct video_mmap       *mm = arg;
 
-               fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
-               if (!fmt2) {
-                       err = -ENOMEM;
-                       break;
-               }
-               memset(&buf2,0,sizeof(buf2));
+       if (tun2.rxsubchans & V4L2_TUNER_SUB_LANG2)
+               aud->mode = VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
+       else if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO)
+               aud->mode = VIDEO_SOUND_STEREO;
+       else if (tun2.rxsubchans & V4L2_TUNER_SUB_MONO)
+               aud->mode = VIDEO_SOUND_MONO;
+done:
+       return err;
+}
 
-               fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               err = drv(inode, file, VIDIOC_G_FMT, fmt2);
-               if (err < 0) {
-                       dprintk("VIDIOCMCAPTURE / VIDIOC_G_FMT: %d\n",err);
+static noinline int v4l1_compat_set_audio(
+                                       struct video_audio *aud,
+                                       struct inode *inode,
+                                       struct file *file,
+                                       v4l2_kioctl drv)
+{
+       int err;
+       struct v4l2_audio       aud2;
+       struct v4l2_tuner       tun2;
+
+       memset(&aud2, 0, sizeof(aud2));
+       memset(&tun2, 0, sizeof(tun2));
+
+       aud2.index = aud->audio;
+       err = drv(inode, file, VIDIOC_S_AUDIO, &aud2);
+       if (err < 0) {
+               dprintk("VIDIOCSAUDIO / VIDIOC_S_AUDIO: %d\n", err);
+               goto done;
+       }
+
+       set_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME,
+                       aud->volume, drv);
+       set_v4l_control(inode, file, V4L2_CID_AUDIO_BASS,
+                       aud->bass, drv);
+       set_v4l_control(inode, file, V4L2_CID_AUDIO_TREBLE,
+                       aud->treble, drv);
+       set_v4l_control(inode, file, V4L2_CID_AUDIO_BALANCE,
+                       aud->balance, drv);
+       set_v4l_control(inode, file, V4L2_CID_AUDIO_MUTE,
+                       !!(aud->flags & VIDEO_AUDIO_MUTE), drv);
+
+       err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
+       if (err < 0)
+               dprintk("VIDIOCSAUDIO / VIDIOC_G_TUNER: %d\n", err);
+       if (err == 0) {
+               switch (aud->mode) {
+               default:
+               case VIDEO_SOUND_MONO:
+               case VIDEO_SOUND_LANG1:
+                       tun2.audmode = V4L2_TUNER_MODE_MONO;
                        break;
-               }
-               if (mm->width   != fmt2->fmt.pix.width  ||
-                   mm->height  != fmt2->fmt.pix.height ||
-                   palette_to_pixelformat(mm->format) !=
-                   fmt2->fmt.pix.pixelformat)
-               {/* New capture format...  */
-                       fmt2->fmt.pix.width = mm->width;
-                       fmt2->fmt.pix.height = mm->height;
-                       fmt2->fmt.pix.pixelformat =
-                               palette_to_pixelformat(mm->format);
-                       fmt2->fmt.pix.field = V4L2_FIELD_ANY;
-                       fmt2->fmt.pix.bytesperline = 0;
-                       err = drv(inode, file, VIDIOC_S_FMT, fmt2);
-                       if (err < 0) {
-                               dprintk("VIDIOCMCAPTURE / VIDIOC_S_FMT: %d\n",err);
-                               break;
-                       }
-               }
-               buf2.index = mm->frame;
-               buf2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               err = drv(inode, file, VIDIOC_QUERYBUF, &buf2);
-               if (err < 0) {
-                       dprintk("VIDIOCMCAPTURE / VIDIOC_QUERYBUF: %d\n",err);
+               case VIDEO_SOUND_STEREO:
+                       tun2.audmode = V4L2_TUNER_MODE_STEREO;
                        break;
-               }
-               err = drv(inode, file, VIDIOC_QBUF, &buf2);
-               if (err < 0) {
-                       dprintk("VIDIOCMCAPTURE / VIDIOC_QBUF: %d\n",err);
+               case VIDEO_SOUND_LANG2:
+                       tun2.audmode = V4L2_TUNER_MODE_LANG2;
                        break;
                }
-               err = drv(inode, file, VIDIOC_STREAMON, &captype);
+               err = drv(inode, file, VIDIOC_S_TUNER, &tun2);
                if (err < 0)
-                       dprintk("VIDIOCMCAPTURE / VIDIOC_STREAMON: %d\n",err);
-               break;
+                       dprintk("VIDIOCSAUDIO / VIDIOC_S_TUNER: %d\n", err);
        }
-       case VIDIOCSYNC: /*  wait for a frame  */
-       {
-               int                     *i = arg;
+       err = 0;
+done:
+       return err;
+}
 
-               memset(&buf2,0,sizeof(buf2));
-               buf2.index = *i;
-               buf2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               err = drv(inode, file, VIDIOC_QUERYBUF, &buf2);
-               if (err < 0) {
-                       /*  No such buffer */
-                       dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n",err);
-                       break;
-               }
-               if (!(buf2.flags & V4L2_BUF_FLAG_MAPPED)) {
-                       /* Buffer is not mapped  */
-                       err = -EINVAL;
-                       break;
-               }
+static noinline int v4l1_compat_capture_frame(
+                                       struct video_mmap *mm,
+                                       struct inode *inode,
+                                       struct file *file,
+                                       v4l2_kioctl drv)
+{
+       int err;
+       enum v4l2_buf_type      captype = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       struct v4l2_buffer      buf;
+       struct v4l2_format      *fmt;
+
+       fmt = kzalloc(sizeof(*fmt), GFP_KERNEL);
+       if (!fmt) {
+               err = -ENOMEM;
+               return err;
+       }
+       memset(&buf, 0, sizeof(buf));
 
-               /* make sure capture actually runs so we don't block forever */
-               err = drv(inode, file, VIDIOC_STREAMON, &captype);
+       fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       err = drv(inode, file, VIDIOC_G_FMT, fmt);
+       if (err < 0) {
+               dprintk("VIDIOCMCAPTURE / VIDIOC_G_FMT: %d\n", err);
+               goto done;
+       }
+       if (mm->width   != fmt->fmt.pix.width  ||
+           mm->height  != fmt->fmt.pix.height ||
+           palette_to_pixelformat(mm->format) !=
+           fmt->fmt.pix.pixelformat) {
+               /* New capture format...  */
+               fmt->fmt.pix.width = mm->width;
+               fmt->fmt.pix.height = mm->height;
+               fmt->fmt.pix.pixelformat =
+                       palette_to_pixelformat(mm->format);
+               fmt->fmt.pix.field = V4L2_FIELD_ANY;
+               fmt->fmt.pix.bytesperline = 0;
+               err = drv(inode, file, VIDIOC_S_FMT, fmt);
                if (err < 0) {
-                       dprintk("VIDIOCSYNC / VIDIOC_STREAMON: %d\n",err);
-                       break;
+                       dprintk("VIDIOCMCAPTURE / VIDIOC_S_FMT: %d\n", err);
+                       goto done;
                }
+       }
+       buf.index = mm->frame;
+       buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       err = drv(inode, file, VIDIOC_QUERYBUF, &buf);
+       if (err < 0) {
+               dprintk("VIDIOCMCAPTURE / VIDIOC_QUERYBUF: %d\n", err);
+               goto done;
+       }
+       err = drv(inode, file, VIDIOC_QBUF, &buf);
+       if (err < 0) {
+               dprintk("VIDIOCMCAPTURE / VIDIOC_QBUF: %d\n", err);
+               goto done;
+       }
+       err = drv(inode, file, VIDIOC_STREAMON, &captype);
+       if (err < 0)
+               dprintk("VIDIOCMCAPTURE / VIDIOC_STREAMON: %d\n", err);
+done:
+       kfree(fmt);
+       return err;
+}
 
-               /*  Loop as long as the buffer is queued, but not done  */
-               while ((buf2.flags &
-                       (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE))
-                      == V4L2_BUF_FLAG_QUEUED)
-               {
-                       err = poll_one(file);
-                       if (err < 0 ||  /* error or sleep was interrupted  */
-                           err == 0)   /* timeout? Shouldn't occur.  */
-                               break;
-                       err = drv(inode, file, VIDIOC_QUERYBUF, &buf2);
-                       if (err < 0)
-                               dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n",err);
-               }
-               if (!(buf2.flags & V4L2_BUF_FLAG_DONE)) /* not done */
-                       break;
-               do {
-                       err = drv(inode, file, VIDIOC_DQBUF, &buf2);
-                       if (err < 0)
-                               dprintk("VIDIOCSYNC / VIDIOC_DQBUF: %d\n",err);
-               } while (err == 0 && buf2.index != *i);
-               break;
+static noinline int v4l1_compat_sync(
+                               int *i,
+                               struct inode *inode,
+                               struct file *file,
+                               v4l2_kioctl drv)
+{
+       int err;
+       enum v4l2_buf_type captype = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       struct v4l2_buffer buf;
+       struct poll_wqueues *pwq;
+
+       memset(&buf, 0, sizeof(buf));
+       buf.index = *i;
+       buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       err = drv(inode, file, VIDIOC_QUERYBUF, &buf);
+       if (err < 0) {
+               /*  No such buffer */
+               dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n", err);
+               goto done;
+       }
+       if (!(buf.flags & V4L2_BUF_FLAG_MAPPED)) {
+               /* Buffer is not mapped  */
+               err = -EINVAL;
+               goto done;
        }
 
-       case VIDIOCGVBIFMT: /* query VBI data capture format */
-       {
-               struct vbi_format      *fmt = arg;
+       /* make sure capture actually runs so we don't block forever */
+       err = drv(inode, file, VIDIOC_STREAMON, &captype);
+       if (err < 0) {
+               dprintk("VIDIOCSYNC / VIDIOC_STREAMON: %d\n", err);
+               goto done;
+       }
 
-               fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
-               if (!fmt2) {
-                       err = -ENOMEM;
+       pwq = kmalloc(sizeof(*pwq), GFP_KERNEL);
+       /*  Loop as long as the buffer is queued, but not done  */
+       while ((buf.flags & (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE))
+                                               == V4L2_BUF_FLAG_QUEUED) {
+               err = poll_one(file, pwq);
+               if (err < 0 ||  /* error or sleep was interrupted  */
+                   err == 0)   /* timeout? Shouldn't occur.  */
                        break;
-               }
-               fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE;
+               err = drv(inode, file, VIDIOC_QUERYBUF, &buf);
+               if (err < 0)
+                       dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n", err);
+       }
+       kfree(pwq);
+       if (!(buf.flags & V4L2_BUF_FLAG_DONE)) /* not done */
+               goto done;
+       do {
+               err = drv(inode, file, VIDIOC_DQBUF, &buf);
+               if (err < 0)
+                       dprintk("VIDIOCSYNC / VIDIOC_DQBUF: %d\n", err);
+       } while (err == 0 && buf.index != *i);
+done:
+       return err;
+}
 
-               err = drv(inode, file, VIDIOC_G_FMT, fmt2);
-               if (err < 0) {
-                       dprintk("VIDIOCGVBIFMT / VIDIOC_G_FMT: %d\n", err);
-                       break;
-               }
-               if (fmt2->fmt.vbi.sample_format != V4L2_PIX_FMT_GREY) {
-                       err = -EINVAL;
-                       break;
-               }
-               memset(fmt, 0, sizeof(*fmt));
-               fmt->samples_per_line = fmt2->fmt.vbi.samples_per_line;
-               fmt->sampling_rate    = fmt2->fmt.vbi.sampling_rate;
-               fmt->sample_format    = VIDEO_PALETTE_RAW;
-               fmt->start[0]         = fmt2->fmt.vbi.start[0];
-               fmt->count[0]         = fmt2->fmt.vbi.count[0];
-               fmt->start[1]         = fmt2->fmt.vbi.start[1];
-               fmt->count[1]         = fmt2->fmt.vbi.count[1];
-               fmt->flags            = fmt2->fmt.vbi.flags & 0x03;
-               break;
+static noinline int v4l1_compat_get_vbi_format(
+                               struct vbi_format *fmt,
+                               struct inode *inode,
+                               struct file *file,
+                               v4l2_kioctl drv)
+{
+       int err;
+       struct v4l2_format *fmt2;
+
+       fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
+       if (!fmt2) {
+               err = -ENOMEM;
+               return err;
        }
-       case VIDIOCSVBIFMT:
-       {
-               struct vbi_format      *fmt = arg;
+       fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE;
 
-               if (VIDEO_PALETTE_RAW != fmt->sample_format) {
-                       err = -EINVAL;
-                       break;
-               }
+       err = drv(inode, file, VIDIOC_G_FMT, fmt2);
+       if (err < 0) {
+               dprintk("VIDIOCGVBIFMT / VIDIOC_G_FMT: %d\n", err);
+               goto done;
+       }
+       if (fmt2->fmt.vbi.sample_format != V4L2_PIX_FMT_GREY) {
+               err = -EINVAL;
+               goto done;
+       }
+       memset(fmt, 0, sizeof(*fmt));
+       fmt->samples_per_line = fmt2->fmt.vbi.samples_per_line;
+       fmt->sampling_rate    = fmt2->fmt.vbi.sampling_rate;
+       fmt->sample_format    = VIDEO_PALETTE_RAW;
+       fmt->start[0]         = fmt2->fmt.vbi.start[0];
+       fmt->count[0]         = fmt2->fmt.vbi.count[0];
+       fmt->start[1]         = fmt2->fmt.vbi.start[1];
+       fmt->count[1]         = fmt2->fmt.vbi.count[1];
+       fmt->flags            = fmt2->fmt.vbi.flags & 0x03;
+done:
+       kfree(fmt2);
+       return err;
+}
 
-               fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
-               if (!fmt2) {
-                       err = -ENOMEM;
-                       break;
-               }
-               fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE;
-               fmt2->fmt.vbi.samples_per_line = fmt->samples_per_line;
-               fmt2->fmt.vbi.sampling_rate    = fmt->sampling_rate;
-               fmt2->fmt.vbi.sample_format    = V4L2_PIX_FMT_GREY;
-               fmt2->fmt.vbi.start[0]         = fmt->start[0];
-               fmt2->fmt.vbi.count[0]         = fmt->count[0];
-               fmt2->fmt.vbi.start[1]         = fmt->start[1];
-               fmt2->fmt.vbi.count[1]         = fmt->count[1];
-               fmt2->fmt.vbi.flags            = fmt->flags;
-               err = drv(inode, file, VIDIOC_TRY_FMT, fmt2);
-               if (err < 0) {
-                       dprintk("VIDIOCSVBIFMT / VIDIOC_TRY_FMT: %d\n", err);
-                       break;
-               }
+static noinline int v4l1_compat_set_vbi_format(
+                               struct vbi_format *fmt,
+                               struct inode *inode,
+                               struct file *file,
+                               v4l2_kioctl drv)
+{
+       int err;
+       struct v4l2_format      *fmt2 = NULL;
 
-               if (fmt2->fmt.vbi.samples_per_line != fmt->samples_per_line ||
-                   fmt2->fmt.vbi.sampling_rate    != fmt->sampling_rate    ||
-                   fmt2->fmt.vbi.sample_format    != V4L2_PIX_FMT_GREY     ||
-                   fmt2->fmt.vbi.start[0]         != fmt->start[0]         ||
-                   fmt2->fmt.vbi.count[0]         != fmt->count[0]         ||
-                   fmt2->fmt.vbi.start[1]         != fmt->start[1]         ||
-                   fmt2->fmt.vbi.count[1]         != fmt->count[1]         ||
-                   fmt2->fmt.vbi.flags            != fmt->flags) {
-                       err = -EINVAL;
-                       break;
-               }
-               err = drv(inode, file, VIDIOC_S_FMT, fmt2);
-               if (err < 0)
-                       dprintk("VIDIOCSVBIFMT / VIDIOC_S_FMT: %d\n", err);
-               break;
+       if (VIDEO_PALETTE_RAW != fmt->sample_format) {
+               err = -EINVAL;
+               return err;
        }
 
+       fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
+       if (!fmt2) {
+               err = -ENOMEM;
+               return err;
+       }
+       fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE;
+       fmt2->fmt.vbi.samples_per_line = fmt->samples_per_line;
+       fmt2->fmt.vbi.sampling_rate    = fmt->sampling_rate;
+       fmt2->fmt.vbi.sample_format    = V4L2_PIX_FMT_GREY;
+       fmt2->fmt.vbi.start[0]         = fmt->start[0];
+       fmt2->fmt.vbi.count[0]         = fmt->count[0];
+       fmt2->fmt.vbi.start[1]         = fmt->start[1];
+       fmt2->fmt.vbi.count[1]         = fmt->count[1];
+       fmt2->fmt.vbi.flags            = fmt->flags;
+       err = drv(inode, file, VIDIOC_TRY_FMT, fmt2);
+       if (err < 0) {
+               dprintk("VIDIOCSVBIFMT / VIDIOC_TRY_FMT: %d\n", err);
+               goto done;
+       }
+
+       if (fmt2->fmt.vbi.samples_per_line != fmt->samples_per_line ||
+           fmt2->fmt.vbi.sampling_rate    != fmt->sampling_rate    ||
+           fmt2->fmt.vbi.sample_format    != V4L2_PIX_FMT_GREY     ||
+           fmt2->fmt.vbi.start[0]         != fmt->start[0]         ||
+           fmt2->fmt.vbi.count[0]         != fmt->count[0]         ||
+           fmt2->fmt.vbi.start[1]         != fmt->start[1]         ||
+           fmt2->fmt.vbi.count[1]         != fmt->count[1]         ||
+           fmt2->fmt.vbi.flags            != fmt->flags) {
+               err = -EINVAL;
+               goto done;
+       }
+       err = drv(inode, file, VIDIOC_S_FMT, fmt2);
+       if (err < 0)
+               dprintk("VIDIOCSVBIFMT / VIDIOC_S_FMT: %d\n", err);
+done:
+       kfree(fmt2);
+       return err;
+}
+
+/*
+ *     This function is exported.
+ */
+int
+v4l_compat_translate_ioctl(struct inode         *inode,
+                          struct file          *file,
+                          int                  cmd,
+                          void                 *arg,
+                          v4l2_kioctl          drv)
+{
+       int err;
+
+       switch (cmd) {
+       case VIDIOCGCAP:        /* capability */
+               err = v4l1_compat_get_capabilities(arg, inode, file, drv);
+               break;
+       case VIDIOCGFBUF: /*  get frame buffer  */
+               err = v4l1_compat_get_frame_buffer(arg, inode, file, drv);
+               break;
+       case VIDIOCSFBUF: /*  set frame buffer  */
+               err = v4l1_compat_set_frame_buffer(arg, inode, file, drv);
+               break;
+       case VIDIOCGWIN: /*  get window or capture dimensions  */
+               err = v4l1_compat_get_win_cap_dimensions(arg, inode, file, drv);
+               break;
+       case VIDIOCSWIN: /*  set window and/or capture dimensions  */
+               err = v4l1_compat_set_win_cap_dimensions(arg, inode, file, drv);
+               break;
+       case VIDIOCCAPTURE: /*  turn on/off preview  */
+               err = v4l1_compat_turn_preview_on_off(arg, inode, file, drv);
+               break;
+       case VIDIOCGCHAN: /*  get input information  */
+               err = v4l1_compat_get_input_info(arg, inode, file, drv);
+               break;
+       case VIDIOCSCHAN: /*  set input  */
+               err = v4l1_compat_set_input(arg, inode, file, drv);
+               break;
+       case VIDIOCGPICT: /*  get tone controls & partial capture format  */
+               err = v4l1_compat_get_picture(arg, inode, file, drv);
+               break;
+       case VIDIOCSPICT: /*  set tone controls & partial capture format  */
+               err = v4l1_compat_set_picture(arg, inode, file, drv);
+               break;
+       case VIDIOCGTUNER: /*  get tuner information  */
+               err = v4l1_compat_get_tuner(arg, inode, file, drv);
+               break;
+       case VIDIOCSTUNER: /*  select a tuner input  */
+               err = v4l1_compat_select_tuner(arg, inode, file, drv);
+               break;
+       case VIDIOCGFREQ: /*  get frequency  */
+               err = v4l1_compat_get_frequency(arg, inode, file, drv);
+               break;
+       case VIDIOCSFREQ: /*  set frequency  */
+               err = v4l1_compat_set_frequency(arg, inode, file, drv);
+               break;
+       case VIDIOCGAUDIO: /*  get audio properties/controls  */
+               err = v4l1_compat_get_audio(arg, inode, file, drv);
+               break;
+       case VIDIOCSAUDIO: /*  set audio controls  */
+               err = v4l1_compat_set_audio(arg, inode, file, drv);
+               break;
+       case VIDIOCMCAPTURE: /*  capture a frame  */
+               err = v4l1_compat_capture_frame(arg, inode, file, drv);
+               break;
+       case VIDIOCSYNC: /*  wait for a frame  */
+               err = v4l1_compat_sync(arg, inode, file, drv);
+               break;
+       case VIDIOCGVBIFMT: /* query VBI data capture format */
+               err = v4l1_compat_get_vbi_format(arg, inode, file, drv);
+               break;
+       case VIDIOCSVBIFMT:
+               err = v4l1_compat_set_vbi_format(arg, inode, file, drv);
+               break;
        default:
                err = -ENOIOCTLCMD;
                break;
        }
 
-       kfree(cap2);
-       kfree(fmt2);
        return err;
 }
-
 EXPORT_SYMBOL(v4l_compat_translate_ioctl);
 
 /*
index eab79ffdf56a882529113c0e25623d0c5941ab1c..fc51e4918bbf790d05ee8d93160a31ddd994aefb 100644 (file)
@@ -64,32 +64,25 @@ void *videobuf_alloc(struct videobuf_queue *q)
        return vb;
 }
 
+#define WAITON_CONDITION (vb->state != VIDEOBUF_ACTIVE &&\
+                               vb->state != VIDEOBUF_QUEUED)
 int videobuf_waiton(struct videobuf_buffer *vb, int non_blocking, int intr)
 {
-       int retval = 0;
-       DECLARE_WAITQUEUE(wait, current);
-
        MAGIC_CHECK(vb->magic, MAGIC_BUFFER);
-       add_wait_queue(&vb->done, &wait);
-       while (vb->state == VIDEOBUF_ACTIVE || vb->state == VIDEOBUF_QUEUED) {
-               if (non_blocking) {
-                       retval = -EAGAIN;
-                       break;
-               }
-               set_current_state(intr  ? TASK_INTERRUPTIBLE
-                                       : TASK_UNINTERRUPTIBLE);
-               if (vb->state == VIDEOBUF_ACTIVE ||
-                   vb->state == VIDEOBUF_QUEUED)
-                       schedule();
-               set_current_state(TASK_RUNNING);
-               if (intr && signal_pending(current)) {
-                       dprintk(1, "buffer waiton: -EINTR\n");
-                       retval = -EINTR;
-                       break;
-               }
+
+       if (non_blocking) {
+               if (WAITON_CONDITION)
+                       return 0;
+               else
+                       return -EAGAIN;
        }
-       remove_wait_queue(&vb->done, &wait);
-       return retval;
+
+       if (intr)
+               return wait_event_interruptible(vb->done, WAITON_CONDITION);
+       else
+               wait_event(vb->done, WAITON_CONDITION);
+
+       return 0;
 }
 
 int videobuf_iolock(struct videobuf_queue *q, struct videobuf_buffer *vb,
@@ -98,29 +91,22 @@ int videobuf_iolock(struct videobuf_queue *q, struct videobuf_buffer *vb,
        MAGIC_CHECK(vb->magic, MAGIC_BUFFER);
        MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
 
-       /* This is required to avoid OOPS on some cases,
-          since mmap_mapper() method should be called before _iolock.
-          On some cases, the mmap_mapper() is called only after scheduling.
-        */
-       if (vb->memory == V4L2_MEMORY_MMAP) {
-               wait_event_timeout(vb->done, q->is_mmapped,
-                                  msecs_to_jiffies(100));
-               if (!q->is_mmapped) {
-                       printk(KERN_ERR
-                              "Error: mmap_mapper() never called!\n");
-                       return -EINVAL;
-               }
-       }
-
        return CALL(q, iolock, q, vb, fbuf);
 }
 
+void *videobuf_queue_to_vmalloc (struct videobuf_queue *q,
+                          struct videobuf_buffer *buf)
+{
+       return CALL(q, vmalloc, buf);
+}
+EXPORT_SYMBOL_GPL(videobuf_queue_to_vmalloc);
+
 /* --------------------------------------------------------------------- */
 
 
 void videobuf_queue_core_init(struct videobuf_queue *q,
                         struct videobuf_queue_ops *ops,
-                        void *dev,
+                        struct device *dev,
                         spinlock_t *irqlock,
                         enum v4l2_buf_type type,
                         enum v4l2_field field,
@@ -144,10 +130,14 @@ void videobuf_queue_core_init(struct videobuf_queue *q,
        BUG_ON(!q->ops->buf_queue);
        BUG_ON(!q->ops->buf_release);
 
+       /* Lock is mandatory for queue_cancel to work */
+       BUG_ON(!irqlock);
+
        /* Having implementations for abstract methods are mandatory */
        BUG_ON(!q->int_ops);
 
        mutex_init(&q->vb_lock);
+       init_waitqueue_head(&q->wait);
        INIT_LIST_HEAD(&q->stream);
 }
 
@@ -195,19 +185,22 @@ void videobuf_queue_cancel(struct videobuf_queue *q)
        unsigned long flags = 0;
        int i;
 
+       q->streaming = 0;
+       q->reading  = 0;
+       wake_up_interruptible_sync(&q->wait);
+
        /* remove queued buffers from list */
-       if (q->irqlock)
-               spin_lock_irqsave(q->irqlock, flags);
+       spin_lock_irqsave(q->irqlock, flags);
        for (i = 0; i < VIDEO_MAX_FRAME; i++) {
                if (NULL == q->bufs[i])
                        continue;
                if (q->bufs[i]->state == VIDEOBUF_QUEUED) {
                        list_del(&q->bufs[i]->queue);
                        q->bufs[i]->state = VIDEOBUF_ERROR;
+                       wake_up_all(&q->bufs[i]->done);
                }
        }
-       if (q->irqlock)
-               spin_unlock_irqrestore(q->irqlock, flags);
+       spin_unlock_irqrestore(q->irqlock, flags);
 
        /* free all buffers + clear queue */
        for (i = 0; i < VIDEO_MAX_FRAME; i++) {
@@ -563,14 +556,13 @@ int videobuf_qbuf(struct videobuf_queue *q,
 
        list_add_tail(&buf->stream, &q->stream);
        if (q->streaming) {
-               if (q->irqlock)
-                       spin_lock_irqsave(q->irqlock, flags);
+               spin_lock_irqsave(q->irqlock, flags);
                q->ops->buf_queue(q, buf);
-               if (q->irqlock)
-                       spin_unlock_irqrestore(q->irqlock, flags);
+               spin_unlock_irqrestore(q->irqlock, flags);
        }
        dprintk(1, "qbuf: succeded\n");
        retval = 0;
+       wake_up_interruptible_sync(&q->wait);
 
  done:
        mutex_unlock(&q->vb_lock);
@@ -581,35 +573,88 @@ int videobuf_qbuf(struct videobuf_queue *q,
        return retval;
 }
 
-int videobuf_dqbuf(struct videobuf_queue *q,
-              struct v4l2_buffer *b, int nonblocking)
+
+/* Locking: Caller holds q->vb_lock */
+static int stream_next_buffer_check_queue(struct videobuf_queue *q, int noblock)
 {
-       struct videobuf_buffer *buf;
        int retval;
 
-       MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
-
-       mutex_lock(&q->vb_lock);
-       retval = -EBUSY;
-       if (q->reading) {
-               dprintk(1, "dqbuf: Reading running...\n");
-               goto done;
-       }
-       retval = -EINVAL;
-       if (b->type != q->type) {
-               dprintk(1, "dqbuf: Wrong type.\n");
+checks:
+       if (!q->streaming) {
+               dprintk(1, "next_buffer: Not streaming\n");
+               retval = -EINVAL;
                goto done;
        }
+
        if (list_empty(&q->stream)) {
-               dprintk(1, "dqbuf: stream running\n");
-               goto done;
+               if (noblock) {
+                       retval = -EAGAIN;
+                       dprintk(2, "next_buffer: no buffers to dequeue\n");
+                       goto done;
+               } else {
+                       dprintk(2, "next_buffer: waiting on buffer\n");
+
+                       /* Drop lock to avoid deadlock with qbuf */
+                       mutex_unlock(&q->vb_lock);
+
+                       /* Checking list_empty and streaming is safe without
+                        * locks because we goto checks to validate while
+                        * holding locks before proceeding */
+                       retval = wait_event_interruptible(q->wait,
+                               !list_empty(&q->stream) || !q->streaming);
+                       mutex_lock(&q->vb_lock);
+
+                       if (retval)
+                               goto done;
+
+                       goto checks;
+               }
        }
+
+       retval = 0;
+
+done:
+       return retval;
+}
+
+
+/* Locking: Caller holds q->vb_lock */
+static int stream_next_buffer(struct videobuf_queue *q,
+                       struct videobuf_buffer **vb, int nonblocking)
+{
+       int retval;
+       struct videobuf_buffer *buf = NULL;
+
+       retval = stream_next_buffer_check_queue(q, nonblocking);
+       if (retval)
+               goto done;
+
        buf = list_entry(q->stream.next, struct videobuf_buffer, stream);
        retval = videobuf_waiton(buf, nonblocking, 1);
+       if (retval < 0)
+               goto done;
+
+       *vb = buf;
+done:
+       return retval;
+}
+
+int videobuf_dqbuf(struct videobuf_queue *q,
+              struct v4l2_buffer *b, int nonblocking)
+{
+       struct videobuf_buffer *buf = NULL;
+       int retval;
+
+       MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
+
+       mutex_lock(&q->vb_lock);
+
+       retval = stream_next_buffer(q, &buf, nonblocking);
        if (retval < 0) {
-               dprintk(1, "dqbuf: waiton returned %d\n", retval);
+               dprintk(1, "dqbuf: next_buffer error: %i\n", retval);
                goto done;
        }
+
        switch (buf->state) {
        case VIDEOBUF_ERROR:
                dprintk(1, "dqbuf: state is error\n");
@@ -650,14 +695,13 @@ int videobuf_streamon(struct videobuf_queue *q)
        if (q->streaming)
                goto done;
        q->streaming = 1;
-       if (q->irqlock)
-               spin_lock_irqsave(q->irqlock, flags);
+       spin_lock_irqsave(q->irqlock, flags);
        list_for_each_entry(buf, &q->stream, stream)
                if (buf->state == VIDEOBUF_PREPARED)
                        q->ops->buf_queue(q, buf);
-       if (q->irqlock)
-               spin_unlock_irqrestore(q->irqlock, flags);
+       spin_unlock_irqrestore(q->irqlock, flags);
 
+       wake_up_interruptible_sync(&q->wait);
  done:
        mutex_unlock(&q->vb_lock);
        return retval;
@@ -670,7 +714,6 @@ static int __videobuf_streamoff(struct videobuf_queue *q)
                return -EINVAL;
 
        videobuf_queue_cancel(q);
-       q->streaming = 0;
 
        return 0;
 }
@@ -712,11 +755,9 @@ static ssize_t videobuf_read_zerocopy(struct videobuf_queue *q,
                goto done;
 
        /* start capture & wait */
-       if (q->irqlock)
-               spin_lock_irqsave(q->irqlock, flags);
+       spin_lock_irqsave(q->irqlock, flags);
        q->ops->buf_queue(q, q->read_buf);
-       if (q->irqlock)
-               spin_unlock_irqrestore(q->irqlock, flags);
+       spin_unlock_irqrestore(q->irqlock, flags);
        retval = videobuf_waiton(q->read_buf, 0, 0);
        if (0 == retval) {
                CALL(q, sync, q, q->read_buf);
@@ -740,14 +781,13 @@ ssize_t videobuf_read_one(struct videobuf_queue *q,
 {
        enum v4l2_field field;
        unsigned long flags = 0;
-       unsigned size, nbufs;
+       unsigned size = 0, nbufs = 1;
        int retval;
 
        MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
 
        mutex_lock(&q->vb_lock);
 
-       nbufs = 1; size = 0;
        q->ops->buf_setup(q, &nbufs, &size);
 
        if (NULL == q->read_buf  &&
@@ -778,12 +818,11 @@ ssize_t videobuf_read_one(struct videobuf_queue *q,
                        q->read_buf = NULL;
                        goto done;
                }
-               if (q->irqlock)
-                       spin_lock_irqsave(q->irqlock, flags);
 
+               spin_lock_irqsave(q->irqlock, flags);
                q->ops->buf_queue(q, q->read_buf);
-               if (q->irqlock)
-                       spin_unlock_irqrestore(q->irqlock, flags);
+               spin_unlock_irqrestore(q->irqlock, flags);
+
                q->read_off = 0;
        }
 
@@ -849,12 +888,10 @@ static int __videobuf_read_start(struct videobuf_queue *q)
                        return err;
                list_add_tail(&q->bufs[i]->stream, &q->stream);
        }
-       if (q->irqlock)
-               spin_lock_irqsave(q->irqlock, flags);
+       spin_lock_irqsave(q->irqlock, flags);
        for (i = 0; i < count; i++)
                q->ops->buf_queue(q, q->bufs[i]);
-       if (q->irqlock)
-               spin_unlock_irqrestore(q->irqlock, flags);
+       spin_unlock_irqrestore(q->irqlock, flags);
        q->reading = 1;
        return 0;
 }
@@ -863,7 +900,6 @@ static void __videobuf_read_stop(struct videobuf_queue *q)
 {
        int i;
 
-
        videobuf_queue_cancel(q);
        __videobuf_mmap_free(q);
        INIT_LIST_HEAD(&q->stream);
@@ -874,7 +910,6 @@ static void __videobuf_read_stop(struct videobuf_queue *q)
                q->bufs[i] = NULL;
        }
        q->read_buf = NULL;
-       q->reading  = 0;
 
 }
 
@@ -919,7 +954,7 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q,
 
        MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
 
-       dprintk(2, "%s\n", __FUNCTION__);
+       dprintk(2, "%s\n", __func__);
        mutex_lock(&q->vb_lock);
        retval = -EBUSY;
        if (q->streaming)
@@ -968,11 +1003,9 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q,
                if (q->read_off == q->read_buf->size) {
                        list_add_tail(&q->read_buf->stream,
                                      &q->stream);
-                       if (q->irqlock)
-                               spin_lock_irqsave(q->irqlock, flags);
+                       spin_lock_irqsave(q->irqlock, flags);
                        q->ops->buf_queue(q, q->read_buf);
-                       if (q->irqlock)
-                               spin_unlock_irqrestore(q->irqlock, flags);
+                       spin_unlock_irqrestore(q->irqlock, flags);
                        q->read_buf = NULL;
                }
                if (retval < 0)
index 53fed4b74ce966be1a43271fd4ff57ab469e92df..03a7b946bd5448b4b5e471836fd8469bdfc492c8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * helper functions for PCI DMA video4linux capture buffers
+ * helper functions for SG DMA video4linux capture buffers
  *
  * The functions expect the hardware being able to scatter gatter
  * (i.e. the buffers are not linear in physical memory, but fragmented
@@ -24,7 +24,7 @@
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 
-#include <linux/pci.h>
+#include <linux/dma-mapping.h>
 #include <linux/vmalloc.h>
 #include <linux/pagemap.h>
 #include <linux/scatterlist.h>
 #define MAGIC_CHECK(is,should) if (unlikely((is) != (should))) \
        { printk(KERN_ERR "magic mismatch: %x (expected %x)\n",is,should); BUG(); }
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0644);
 
-MODULE_DESCRIPTION("helper module to manage video4linux pci dma sg buffers");
+MODULE_DESCRIPTION("helper module to manage video4linux dma sg buffers");
 MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
 MODULE_LICENSE("GPL");
 
@@ -119,10 +119,10 @@ videobuf_pages_to_sg(struct page **pages, int nr_pages, int offset)
 
 struct videobuf_dmabuf *videobuf_to_dma (struct videobuf_buffer *buf)
 {
-       struct videbuf_pci_sg_memory *mem=buf->priv;
-       BUG_ON (!mem);
+       struct videobuf_dma_sg_memory *mem = buf->priv;
+       BUG_ON(!mem);
 
-       MAGIC_CHECK(mem->magic,MAGIC_SG_MEM);
+       MAGIC_CHECK(mem->magic, MAGIC_SG_MEM);
 
        return &mem->dma;
 }
@@ -141,9 +141,14 @@ static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma,
 
        dma->direction = direction;
        switch (dma->direction) {
-       case PCI_DMA_FROMDEVICE: rw = READ;  break;
-       case PCI_DMA_TODEVICE:   rw = WRITE; break;
-       default:                 BUG();
+       case DMA_FROM_DEVICE:
+               rw = READ;
+               break;
+       case DMA_TO_DEVICE:
+               rw = WRITE;
+               break;
+       default:
+               BUG();
        }
 
        first = (data          & PAGE_MASK) >> PAGE_SHIFT;
@@ -157,9 +162,6 @@ static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma,
        dprintk(1,"init user [0x%lx+0x%lx => %d pages]\n",
                data,size,dma->nr_pages);
 
-       dma->varea = (void *) data;
-
-
        err = get_user_pages(current,current->mm,
                             data & PAGE_MASK, dma->nr_pages,
                             rw == READ, 1, /* force */
@@ -216,10 +218,8 @@ int videobuf_dma_init_overlay(struct videobuf_dmabuf *dma, int direction,
        return 0;
 }
 
-int videobuf_dma_map(struct videobuf_queue* q,struct videobuf_dmabuf *dma)
+int videobuf_dma_map(struct videobuf_queue* q, struct videobuf_dmabuf *dma)
 {
-       void                   *dev=q->dev;
-
        MAGIC_CHECK(dma->magic,MAGIC_DMABUF);
        BUG_ON(0 == dma->nr_pages);
 
@@ -245,11 +245,11 @@ int videobuf_dma_map(struct videobuf_queue* q,struct videobuf_dmabuf *dma)
                return -ENOMEM;
        }
        if (!dma->bus_addr) {
-               dma->sglen = pci_map_sg(dev,dma->sglist,
+               dma->sglen = dma_map_sg(q->dev, dma->sglist,
                                        dma->nr_pages, dma->direction);
                if (0 == dma->sglen) {
                        printk(KERN_WARNING
-                              "%s: videobuf_map_sg failed\n",__FUNCTION__);
+                              "%s: videobuf_map_sg failed\n",__func__);
                        kfree(dma->sglist);
                        dma->sglist = NULL;
                        dma->sglen = 0;
@@ -259,26 +259,22 @@ int videobuf_dma_map(struct videobuf_queue* q,struct videobuf_dmabuf *dma)
        return 0;
 }
 
-int videobuf_dma_sync(struct videobuf_queue *q,struct videobuf_dmabuf *dma)
+int videobuf_dma_sync(struct videobuf_queue *q, struct videobuf_dmabuf *dma)
 {
-       void                   *dev=q->dev;
-
-       MAGIC_CHECK(dma->magic,MAGIC_DMABUF);
+       MAGIC_CHECK(dma->magic, MAGIC_DMABUF);
        BUG_ON(!dma->sglen);
 
-       pci_dma_sync_sg_for_cpu (dev,dma->sglist,dma->nr_pages,dma->direction);
+       dma_sync_sg_for_cpu(q->dev, dma->sglist, dma->nr_pages, dma->direction);
        return 0;
 }
 
 int videobuf_dma_unmap(struct videobuf_queue* q,struct videobuf_dmabuf *dma)
 {
-       void                   *dev=q->dev;
-
-       MAGIC_CHECK(dma->magic,MAGIC_DMABUF);
+       MAGIC_CHECK(dma->magic, MAGIC_DMABUF);
        if (!dma->sglen)
                return 0;
 
-       pci_unmap_sg (dev,dma->sglist,dma->nr_pages,dma->direction);
+       dma_unmap_sg(q->dev, dma->sglist, dma->nr_pages, dma->direction);
 
        kfree(dma->sglist);
        dma->sglist = NULL;
@@ -301,33 +297,32 @@ int videobuf_dma_free(struct videobuf_dmabuf *dma)
 
        vfree(dma->vmalloc);
        dma->vmalloc = NULL;
-       dma->varea = NULL;
 
        if (dma->bus_addr) {
                dma->bus_addr = 0;
        }
-       dma->direction = PCI_DMA_NONE;
+       dma->direction = DMA_NONE;
        return 0;
 }
 
 /* --------------------------------------------------------------------- */
 
-int videobuf_pci_dma_map(struct pci_dev *pci,struct videobuf_dmabuf *dma)
+int videobuf_sg_dma_map(struct device *dev, struct videobuf_dmabuf *dma)
 {
        struct videobuf_queue q;
 
-       q.dev=pci;
+       q.dev = dev;
 
-       return (videobuf_dma_map(&q,dma));
+       return videobuf_dma_map(&q, dma);
 }
 
-int videobuf_pci_dma_unmap(struct pci_dev *pci,struct videobuf_dmabuf *dma)
+int videobuf_sg_dma_unmap(struct device *dev, struct videobuf_dmabuf *dma)
 {
        struct videobuf_queue q;
 
-       q.dev=pci;
+       q.dev = dev;
 
-       return (videobuf_dma_unmap(&q,dma));
+       return videobuf_dma_unmap(&q, dma);
 }
 
 /* --------------------------------------------------------------------- */
@@ -347,7 +342,7 @@ videobuf_vm_close(struct vm_area_struct *vma)
 {
        struct videobuf_mapping *map = vma->vm_private_data;
        struct videobuf_queue *q = map->q;
-       struct videbuf_pci_sg_memory *mem;
+       struct videobuf_dma_sg_memory *mem;
        int i;
 
        dprintk(2,"vm_close %p [count=%d,vma=%08lx-%08lx]\n",map,
@@ -409,18 +404,18 @@ static struct vm_operations_struct videobuf_vm_ops =
 };
 
 /* ---------------------------------------------------------------------
- * PCI handlers for the generic methods
+ * SG handlers for the generic methods
  */
 
 /* Allocated area consists on 3 parts:
        struct video_buffer
        struct <driver>_buffer (cx88_buffer, saa7134_buf, ...)
-       struct videobuf_pci_sg_memory
+       struct videobuf_dma_sg_memory
  */
 
 static void *__videobuf_alloc(size_t size)
 {
-       struct videbuf_pci_sg_memory *mem;
+       struct videobuf_dma_sg_memory *mem;
        struct videobuf_buffer *vb;
 
        vb = kzalloc(size+sizeof(*mem),GFP_KERNEL);
@@ -431,22 +426,32 @@ static void *__videobuf_alloc(size_t size)
        videobuf_dma_init(&mem->dma);
 
        dprintk(1,"%s: allocated at %p(%ld+%ld) & %p(%ld)\n",
-               __FUNCTION__,vb,(long)sizeof(*vb),(long)size-sizeof(*vb),
+               __func__,vb,(long)sizeof(*vb),(long)size-sizeof(*vb),
                mem,(long)sizeof(*mem));
 
        return vb;
 }
 
+static void *__videobuf_to_vmalloc (struct videobuf_buffer *buf)
+{
+       struct videobuf_dma_sg_memory *mem = buf->priv;
+       BUG_ON(!mem);
+
+       MAGIC_CHECK(mem->magic, MAGIC_SG_MEM);
+
+       return mem->dma.vmalloc;
+}
+
 static int __videobuf_iolock (struct videobuf_queue* q,
                              struct videobuf_buffer *vb,
                              struct v4l2_framebuffer *fbuf)
 {
        int err,pages;
        dma_addr_t bus;
-       struct videbuf_pci_sg_memory *mem=vb->priv;
+       struct videobuf_dma_sg_memory *mem = vb->priv;
        BUG_ON(!mem);
 
-       MAGIC_CHECK(mem->magic,MAGIC_SG_MEM);
+       MAGIC_CHECK(mem->magic, MAGIC_SG_MEM);
 
        switch (vb->memory) {
        case V4L2_MEMORY_MMAP:
@@ -455,14 +460,14 @@ static int __videobuf_iolock (struct videobuf_queue* q,
                        /* no userspace addr -- kernel bounce buffer */
                        pages = PAGE_ALIGN(vb->size) >> PAGE_SHIFT;
                        err = videobuf_dma_init_kernel( &mem->dma,
-                                                       PCI_DMA_FROMDEVICE,
+                                                       DMA_FROM_DEVICE,
                                                        pages );
                        if (0 != err)
                                return err;
                } else if (vb->memory == V4L2_MEMORY_USERPTR) {
                        /* dma directly to userspace */
                        err = videobuf_dma_init_user( &mem->dma,
-                                                     PCI_DMA_FROMDEVICE,
+                                                     DMA_FROM_DEVICE,
                                                      vb->baddr,vb->bsize );
                        if (0 != err)
                                return err;
@@ -473,7 +478,7 @@ static int __videobuf_iolock (struct videobuf_queue* q,
                        locking inversion, so don't take it here */
 
                        err = videobuf_dma_init_user_locked(&mem->dma,
-                                                     PCI_DMA_FROMDEVICE,
+                                                     DMA_FROM_DEVICE,
                                                      vb->baddr, vb->bsize);
                        if (0 != err)
                                return err;
@@ -490,7 +495,7 @@ static int __videobuf_iolock (struct videobuf_queue* q,
                 */
                bus   = (dma_addr_t)(unsigned long)fbuf->base + vb->boff;
                pages = PAGE_ALIGN(vb->size) >> PAGE_SHIFT;
-               err = videobuf_dma_init_overlay(&mem->dma,PCI_DMA_FROMDEVICE,
+               err = videobuf_dma_init_overlay(&mem->dma, DMA_FROM_DEVICE,
                                                bus, pages);
                if (0 != err)
                        return err;
@@ -498,7 +503,7 @@ static int __videobuf_iolock (struct videobuf_queue* q,
        default:
                BUG();
        }
-       err = videobuf_dma_map(q,&mem->dma);
+       err = videobuf_dma_map(q, &mem->dma);
        if (0 != err)
                return err;
 
@@ -508,8 +513,8 @@ static int __videobuf_iolock (struct videobuf_queue* q,
 static int __videobuf_sync(struct videobuf_queue *q,
                           struct videobuf_buffer *buf)
 {
-       struct videbuf_pci_sg_memory *mem=buf->priv;
-       BUG_ON (!mem);
+       struct videobuf_dma_sg_memory *mem = buf->priv;
+       BUG_ON(!mem);
        MAGIC_CHECK(mem->magic,MAGIC_SG_MEM);
 
        return  videobuf_dma_sync(q,&mem->dma);
@@ -532,7 +537,7 @@ static int __videobuf_mmap_free(struct videobuf_queue *q)
 static int __videobuf_mmap_mapper(struct videobuf_queue *q,
                         struct vm_area_struct *vma)
 {
-       struct videbuf_pci_sg_memory *mem;
+       struct videobuf_dma_sg_memory *mem;
        struct videobuf_mapping *map;
        unsigned int first,last,size,i;
        int retval;
@@ -547,12 +552,20 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q,
                goto done;
        }
 
+       /* This function maintains backwards compatibility with V4L1 and will
+        * map more than one buffer if the vma length is equal to the combined
+        * size of multiple buffers than it will map them together.  See
+        * VIDIOCGMBUF in the v4l spec
+        *
+        * TODO: Allow drivers to specify if they support this mode
+        */
+
        /* look for first buffer to map */
        for (first = 0; first < VIDEO_MAX_FRAME; first++) {
                if (NULL == q->bufs[first])
                        continue;
                mem=q->bufs[first]->priv;
-               BUG_ON (!mem);
+               BUG_ON(!mem);
                MAGIC_CHECK(mem->magic,MAGIC_SG_MEM);
 
                if (V4L2_MEMORY_MMAP != q->bufs[first]->memory)
@@ -591,10 +604,16 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q,
        map = kmalloc(sizeof(struct videobuf_mapping),GFP_KERNEL);
        if (NULL == map)
                goto done;
-       for (size = 0, i = first; i <= last; size += q->bufs[i++]->bsize) {
+
+       size = 0;
+       for (i = first; i <= last; i++) {
+               if (NULL == q->bufs[i])
+                       continue;
                q->bufs[i]->map   = map;
                q->bufs[i]->baddr = vma->vm_start + size;
+               size += q->bufs[i]->bsize;
        }
+
        map->count    = 1;
        map->start    = vma->vm_start;
        map->end      = vma->vm_end;
@@ -615,8 +634,8 @@ static int __videobuf_copy_to_user ( struct videobuf_queue *q,
                                char __user *data, size_t count,
                                int nonblocking )
 {
-       struct videbuf_pci_sg_memory *mem=q->read_buf->priv;
-       BUG_ON (!mem);
+       struct videobuf_dma_sg_memory *mem = q->read_buf->priv;
+       BUG_ON(!mem);
        MAGIC_CHECK(mem->magic,MAGIC_SG_MEM);
 
        /* copy to userspace */
@@ -634,8 +653,8 @@ static int __videobuf_copy_stream ( struct videobuf_queue *q,
                                int vbihack, int nonblocking )
 {
        unsigned int  *fc;
-       struct videbuf_pci_sg_memory *mem=q->read_buf->priv;
-       BUG_ON (!mem);
+       struct videobuf_dma_sg_memory *mem = q->read_buf->priv;
+       BUG_ON(!mem);
        MAGIC_CHECK(mem->magic,MAGIC_SG_MEM);
 
        if (vbihack) {
@@ -658,7 +677,7 @@ static int __videobuf_copy_stream ( struct videobuf_queue *q,
        return count;
 }
 
-static struct videobuf_qtype_ops pci_ops = {
+static struct videobuf_qtype_ops sg_ops = {
        .magic        = MAGIC_QTYPE_OPS,
 
        .alloc        = __videobuf_alloc,
@@ -668,23 +687,24 @@ static struct videobuf_qtype_ops pci_ops = {
        .mmap_mapper  = __videobuf_mmap_mapper,
        .video_copy_to_user = __videobuf_copy_to_user,
        .copy_stream  = __videobuf_copy_stream,
+       .vmalloc      = __videobuf_to_vmalloc,
 };
 
-void *videobuf_pci_alloc (size_t size)
+void *videobuf_sg_alloc(size_t size)
 {
        struct videobuf_queue q;
 
        /* Required to make generic handler to call __videobuf_alloc */
-       q.int_ops=&pci_ops;
+       q.int_ops = &sg_ops;
 
-       q.msize=size;
+       q.msize = size;
 
-       return videobuf_alloc (&q);
+       return videobuf_alloc(&q);
 }
 
-void videobuf_queue_pci_init(struct videobuf_queue* q,
+void videobuf_queue_sg_init(struct videobuf_queue* q,
                         struct videobuf_queue_ops *ops,
-                        void *dev,
+                        struct device *dev,
                         spinlock_t *irqlock,
                         enum v4l2_buf_type type,
                         enum v4l2_field field,
@@ -692,7 +712,7 @@ void videobuf_queue_pci_init(struct videobuf_queue* q,
                         void *priv)
 {
        videobuf_queue_core_init(q, ops, dev, irqlock, type, field, msize,
-                                priv, &pci_ops);
+                                priv, &sg_ops);
 }
 
 /* --------------------------------------------------------------------- */
@@ -709,11 +729,11 @@ EXPORT_SYMBOL_GPL(videobuf_dma_sync);
 EXPORT_SYMBOL_GPL(videobuf_dma_unmap);
 EXPORT_SYMBOL_GPL(videobuf_dma_free);
 
-EXPORT_SYMBOL_GPL(videobuf_pci_dma_map);
-EXPORT_SYMBOL_GPL(videobuf_pci_dma_unmap);
-EXPORT_SYMBOL_GPL(videobuf_pci_alloc);
+EXPORT_SYMBOL_GPL(videobuf_sg_dma_map);
+EXPORT_SYMBOL_GPL(videobuf_sg_dma_unmap);
+EXPORT_SYMBOL_GPL(videobuf_sg_alloc);
 
-EXPORT_SYMBOL_GPL(videobuf_queue_pci_init);
+EXPORT_SYMBOL_GPL(videobuf_queue_sg_init);
 
 /*
  * Local variables:
index b73aba65d21d00850e7604fbb6b408c7a62879ce..6e4d73ec6855f274684df7e4b80cea0d4b9b0bd4 100644 (file)
 #include <linux/fs.h>
 #include <linux/kthread.h>
 #include <linux/file.h>
+
 #include <linux/freezer.h>
 
-#include <media/videobuf-dma-sg.h>
+#include <media/videobuf-core.h>
 #include <media/videobuf-dvb.h>
 
 /* ------------------------------------------------------------------ */
@@ -30,7 +31,7 @@
 MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
 MODULE_LICENSE("GPL");
 
-static unsigned int debug = 0;
+static unsigned int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug,"enable debug messages");
 
@@ -45,7 +46,7 @@ static int videobuf_dvb_thread(void *data)
        struct videobuf_buffer *buf;
        unsigned long flags;
        int err;
-       struct videobuf_dmabuf *dma;
+       void *outp;
 
        dprintk("dvb thread started\n");
        set_freezable();
@@ -66,9 +67,10 @@ static int videobuf_dvb_thread(void *data)
                try_to_freeze();
 
                /* feed buffer data to demux */
-               dma=videobuf_to_dma(buf);
+               outp = videobuf_queue_to_vmalloc (&dvb->dvbq, buf);
+
                if (buf->state == VIDEOBUF_DONE)
-                       dvb_dmx_swfilter(&dvb->demux, dma->vmalloc,
+                       dvb_dmx_swfilter(&dvb->demux, outp,
                                         buf->size);
 
                /* requeue buffer */
@@ -138,14 +140,16 @@ static int videobuf_dvb_stop_feed(struct dvb_demux_feed *feed)
 int videobuf_dvb_register(struct videobuf_dvb *dvb,
                          struct module *module,
                          void *adapter_priv,
-                         struct device *device)
+                         struct device *device,
+                         short *adapter_nr)
 {
        int result;
 
        mutex_init(&dvb->lock);
 
        /* register adapter */
-       result = dvb_register_adapter(&dvb->adapter, dvb->name, module, device);
+       result = dvb_register_adapter(&dvb->adapter, dvb->name, module, device,
+                                     adapter_nr);
        if (result < 0) {
                printk(KERN_WARNING "%s: dvb_register_adapter failed (errno = %d)\n",
                       dvb->name, result);
index 5266ecc91dababf0aea005e376b045ea4351a251..c91e1d8e38025d32c292d888cac3feeb20103d6d 100644 (file)
@@ -33,7 +33,7 @@
 #define MAGIC_CHECK(is,should) if (unlikely((is) != (should))) \
        { printk(KERN_ERR "magic mismatch: %x (expected %x)\n",is,should); BUG(); }
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0644);
 
 MODULE_DESCRIPTION("helper module to manage video4linux vmalloc buffers");
@@ -57,20 +57,26 @@ videobuf_vm_open(struct vm_area_struct *vma)
        map->count++;
 }
 
-static void
-videobuf_vm_close(struct vm_area_struct *vma)
+static void videobuf_vm_close(struct vm_area_struct *vma)
 {
        struct videobuf_mapping *map = vma->vm_private_data;
        struct videobuf_queue *q = map->q;
        int i;
 
-       dprintk(2,"vm_close %p [count=%u,vma=%08lx-%08lx]\n",map,
-               map->count,vma->vm_start,vma->vm_end);
+       dprintk(2,"vm_close %p [count=%u,vma=%08lx-%08lx]\n", map,
+               map->count, vma->vm_start, vma->vm_end);
 
        map->count--;
        if (0 == map->count) {
-               dprintk(1,"munmap %p q=%p\n",map,q);
+               struct videobuf_vmalloc_memory *mem;
+
+               dprintk(1, "munmap %p q=%p\n", map, q);
                mutex_lock(&q->vb_lock);
+
+               /* We need first to cancel streams, before unmapping */
+               if (q->streaming)
+                       videobuf_queue_cancel(q);
+
                for (i = 0; i < VIDEO_MAX_FRAME; i++) {
                        if (NULL == q->bufs[i])
                                continue;
@@ -78,14 +84,35 @@ videobuf_vm_close(struct vm_area_struct *vma)
                        if (q->bufs[i]->map != map)
                                continue;
 
-                       q->ops->buf_release(q,q->bufs[i]);
+                       mem = q->bufs[i]->priv;
+                       if (mem) {
+                               /* This callback is called only if kernel has
+                                  allocated memory and this memory is mmapped.
+                                  In this case, memory should be freed,
+                                  in order to do memory unmap.
+                                */
+
+                               MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
+
+                               /* vfree is not atomic - can't be
+                                  called with IRQ's disabled
+                                */
+                               dprintk(1, "%s: buf[%d] freeing (%p)\n",
+                                       __func__, i, mem->vmalloc);
+
+                               vfree(mem->vmalloc);
+                               mem->vmalloc = NULL;
+                       }
 
                        q->bufs[i]->map   = NULL;
                        q->bufs[i]->baddr = 0;
                }
-               mutex_unlock(&q->vb_lock);
+
                kfree(map);
+
+               mutex_unlock(&q->vb_lock);
        }
+
        return;
 }
 
@@ -102,7 +129,7 @@ static struct vm_operations_struct videobuf_vm_ops =
 /* Allocated area consists on 3 parts:
        struct video_buffer
        struct <driver>_buffer (cx88_buffer, saa7134_buf, ...)
-       struct videobuf_pci_sg_memory
+       struct videobuf_dma_sg_memory
  */
 
 static void *__videobuf_alloc(size_t size)
@@ -116,7 +143,7 @@ static void *__videobuf_alloc(size_t size)
        mem->magic=MAGIC_VMAL_MEM;
 
        dprintk(1,"%s: allocated at %p(%ld+%ld) & %p(%ld)\n",
-               __FUNCTION__,vb,(long)sizeof(*vb),(long)size-sizeof(*vb),
+               __func__,vb,(long)sizeof(*vb),(long)size-sizeof(*vb),
                mem,(long)sizeof(*mem));
 
        return vb;
@@ -126,45 +153,74 @@ static int __videobuf_iolock (struct videobuf_queue* q,
                              struct videobuf_buffer *vb,
                              struct v4l2_framebuffer *fbuf)
 {
+       struct videobuf_vmalloc_memory *mem = vb->priv;
        int pages;
-       struct videobuf_vmalloc_memory *mem=vb->priv;
 
        BUG_ON(!mem);
 
-       MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM);
+       MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
 
-       pages = PAGE_ALIGN(vb->size) >> PAGE_SHIFT;
+       switch (vb->memory) {
+       case V4L2_MEMORY_MMAP:
+               dprintk(1, "%s memory method MMAP\n", __func__);
 
-       /* Currently, doesn't support V4L2_MEMORY_OVERLAY */
-       if ((vb->memory != V4L2_MEMORY_MMAP) &&
-                               (vb->memory != V4L2_MEMORY_USERPTR) ) {
-               printk(KERN_ERR "Method currently unsupported.\n");
-               return -EINVAL;
-       }
+               /* All handling should be done by __videobuf_mmap_mapper() */
+               if (!mem->vmalloc) {
+                       printk(KERN_ERR "memory is not alloced/mmapped.\n");
+                       return -EINVAL;
+               }
+               break;
+       case V4L2_MEMORY_USERPTR:
+               pages = PAGE_ALIGN(vb->size);
 
-       /* FIXME: should be tested with kernel mmap mem */
-       mem->vmalloc=vmalloc_user (PAGE_ALIGN(vb->size));
-       if (NULL == mem->vmalloc) {
-               printk(KERN_ERR "vmalloc (%d pages) failed\n",pages);
-               return -ENOMEM;
-       }
+               dprintk(1, "%s memory method USERPTR\n", __func__);
 
-       dprintk(1,"vmalloc is at addr 0x%08lx, size=%d\n",
-                               (unsigned long)mem->vmalloc,
-                               pages << PAGE_SHIFT);
+#if 1
+               if (vb->baddr) {
+                       printk(KERN_ERR "USERPTR is currently not supported\n");
+                       return -EINVAL;
+               }
+#endif
 
-       /* It seems that some kernel versions need to do remap *after*
-          the mmap() call
-        */
-       if (mem->vma) {
-               int retval=remap_vmalloc_range(mem->vma, mem->vmalloc,0);
-               kfree(mem->vma);
-               mem->vma=NULL;
-               if (retval<0) {
-                       dprintk(1,"mmap app bug: remap_vmalloc_range area %p error %d\n",
-                               mem->vmalloc,retval);
-                       return retval;
+               /* The only USERPTR currently supported is the one needed for
+                  read() method.
+                */
+
+               mem->vmalloc = vmalloc_user(pages);
+               if (!mem->vmalloc) {
+                       printk(KERN_ERR "vmalloc (%d pages) failed\n", pages);
+                       return -ENOMEM;
+               }
+               dprintk(1, "vmalloc is at addr %p (%d pages)\n",
+                       mem->vmalloc, pages);
+
+#if 0
+               int rc;
+               /* Kernel userptr is used also by read() method. In this case,
+                  there's no need to remap, since data will be copied to user
+                */
+               if (!vb->baddr)
+                       return 0;
+
+               /* FIXME: to properly support USERPTR, remap should occur.
+                  The code bellow won't work, since mem->vma = NULL
+                */
+               /* Try to remap memory */
+               rc = remap_vmalloc_range(mem->vma, (void *)vb->baddr, 0);
+               if (rc < 0) {
+                       printk(KERN_ERR "mmap: remap failed with error %d. ", rc);
+                       return -ENOMEM;
                }
+#endif
+
+               break;
+       case V4L2_MEMORY_OVERLAY:
+       default:
+               dprintk(1, "%s memory method OVERLAY/unknown\n", __func__);
+
+               /* Currently, doesn't support V4L2_MEMORY_OVERLAY */
+               printk(KERN_ERR "Memory method currently unsupported.\n");
+               return -EINVAL;
        }
 
        return 0;
@@ -180,6 +236,7 @@ static int __videobuf_mmap_free(struct videobuf_queue *q)
 {
        unsigned int i;
 
+       dprintk(1, "%s\n", __func__);
        for (i = 0; i < VIDEO_MAX_FRAME; i++) {
                if (q->bufs[i]) {
                        if (q->bufs[i]->map)
@@ -196,10 +253,11 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q,
        struct videobuf_vmalloc_memory *mem;
        struct videobuf_mapping *map;
        unsigned int first;
-       int retval;
+       int retval, pages;
        unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
 
-       if (! (vma->vm_flags & VM_WRITE) || ! (vma->vm_flags & VM_SHARED))
+       dprintk(1, "%s\n", __func__);
+       if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED))
                return -EINVAL;
 
        /* look for first buffer to map */
@@ -219,46 +277,55 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q,
        }
 
        /* create mapping + update buffer list */
-       map = q->bufs[first]->map = kzalloc(sizeof(struct videobuf_mapping),GFP_KERNEL);
+       map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL);
        if (NULL == map)
                return -ENOMEM;
 
+       q->bufs[first]->map = map;
        map->start = vma->vm_start;
        map->end   = vma->vm_end;
        map->q     = q;
 
        q->bufs[first]->baddr = vma->vm_start;
 
-       vma->vm_ops          = &videobuf_vm_ops;
-       vma->vm_flags       |= VM_DONTEXPAND | VM_RESERVED;
-       vma->vm_private_data = map;
+       mem = q->bufs[first]->priv;
+       BUG_ON(!mem);
+       MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
 
-       mem=q->bufs[first]->priv;
-       BUG_ON (!mem);
-       MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM);
+       pages = PAGE_ALIGN(vma->vm_end - vma->vm_start);
+       mem->vmalloc = vmalloc_user(pages);
+       if (!mem->vmalloc) {
+               printk(KERN_ERR "vmalloc (%d pages) failed\n", pages);
+               goto error;
+       }
+       dprintk(1, "vmalloc is at addr %p (%d pages)\n",
+               mem->vmalloc, pages);
 
        /* Try to remap memory */
-       retval=remap_vmalloc_range(vma, mem->vmalloc,0);
-       if (retval<0) {
-               dprintk(1,"mmap: postponing remap_vmalloc_range\n");
-
-               mem->vma=kmalloc(sizeof(*vma),GFP_KERNEL);
-               if (!mem->vma) {
-                       kfree(map);
-                       q->bufs[first]->map=NULL;
-                       return -ENOMEM;
-               }
-               memcpy(mem->vma,vma,sizeof(*vma));
+       retval = remap_vmalloc_range(vma, mem->vmalloc, 0);
+       if (retval < 0) {
+               printk(KERN_ERR "mmap: remap failed with error %d. ", retval);
+               vfree(mem->vmalloc);
+               goto error;
        }
 
+       vma->vm_ops          = &videobuf_vm_ops;
+       vma->vm_flags       |= VM_DONTEXPAND | VM_RESERVED;
+       vma->vm_private_data = map;
+
        dprintk(1,"mmap %p: q=%p %08lx-%08lx (%lx) pgoff %08lx buf %d\n",
-               map,q,vma->vm_start,vma->vm_end,
+               map, q, vma->vm_start, vma->vm_end,
                (long int) q->bufs[first]->bsize,
-               vma->vm_pgoff,first);
+               vma->vm_pgoff, first);
 
        videobuf_vm_open(vma);
 
-       return (0);
+       return 0;
+
+error:
+       mem = NULL;
+       kfree(map);
+       return -ENOMEM;
 }
 
 static int __videobuf_copy_to_user ( struct videobuf_queue *q,
@@ -320,6 +387,7 @@ static struct videobuf_qtype_ops qops = {
        .mmap_mapper  = __videobuf_mmap_mapper,
        .video_copy_to_user = __videobuf_copy_to_user,
        .copy_stream  = __videobuf_copy_stream,
+       .vmalloc      = videobuf_to_vmalloc,
 };
 
 void videobuf_queue_vmalloc_init(struct videobuf_queue* q,
@@ -349,13 +417,24 @@ EXPORT_SYMBOL_GPL(videobuf_to_vmalloc);
 
 void videobuf_vmalloc_free (struct videobuf_buffer *buf)
 {
-       struct videobuf_vmalloc_memory *mem=buf->priv;
-       BUG_ON (!mem);
+       struct videobuf_vmalloc_memory *mem = buf->priv;
 
-       MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM);
+       /* mmapped memory can't be freed here, otherwise mmapped region
+          would be released, while still needed. In this case, the memory
+          release should happen inside videobuf_vm_close().
+          So, it should free memory only if the memory were allocated for
+          read() operation.
+        */
+       if ((buf->memory != V4L2_MEMORY_USERPTR) || (buf->baddr == 0))
+               return;
+
+       if (!mem)
+               return;
+
+       MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
 
        vfree(mem->vmalloc);
-       mem->vmalloc=NULL;
+       mem->vmalloc = NULL;
 
        return;
 }
index 87951ec8254f47cd8be33557237cd7bedf54d902..cf24956f3204272cd6b9eeebb5ecf7b8c20ffeaa 100644 (file)
 
 #ifdef CONFIG_PROC_FS
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <asm/uaccess.h>
 #endif
 
 #include "videocodec.h"
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0-4)");
 
@@ -320,56 +321,22 @@ videocodec_unregister (const struct videocodec *codec)
 }
 
 #ifdef CONFIG_PROC_FS
-/* ============ */
-/* procfs stuff */
-/* ============ */
-
-static char *videocodec_buf = NULL;
-static int videocodec_bufsize = 0;
-
-static int
-videocodec_build_table (void)
+static int proc_videocodecs_show(struct seq_file *m, void *v)
 {
        struct codec_list *h = codeclist_top;
        struct attached_list *a;
-       int i = 0, size;
-
-       // sum up amount of slaves plus their attached masters
-       while (h) {
-               i += h->attached + 1;
-               h = h->next;
-       }
-#define LINESIZE 100
-       size = LINESIZE * (i + 1);
 
-       dprintk(3, "videocodec_build table: %d entries, %d bytes\n", i,
-               size);
-
-       kfree(videocodec_buf);
-       videocodec_buf = kmalloc(size, GFP_KERNEL);
-
-       if (!videocodec_buf)
-               return 0;
-
-       i = 0;
-       i += scnprintf(videocodec_buf + i, size - 1,
-                     "<S>lave or attached <M>aster name  type flags    magic    ");
-       i += scnprintf(videocodec_buf + i, size -i - 1, "(connected as)\n");
+       seq_printf(m, "<S>lave or attached <M>aster name  type flags    magic    ");
+       seq_printf(m, "(connected as)\n");
 
        h = codeclist_top;
        while (h) {
-               if (i > (size - LINESIZE))
-                       break;  // security check
-               i += scnprintf(videocodec_buf + i, size -i -1,
-                             "S %32s %04x %08lx %08lx (TEMPLATE)\n",
+               seq_printf(m, "S %32s %04x %08lx %08lx (TEMPLATE)\n",
                              h->codec->name, h->codec->type,
                              h->codec->flags, h->codec->magic);
                a = h->list;
                while (a) {
-                       if (i > (size - LINESIZE))
-                               break;  // security check
-                       i += scnprintf(videocodec_buf + i, size -i -1,
-                                     "M %32s %04x %08lx %08lx (%s)\n",
+                       seq_printf(m, "M %32s %04x %08lx %08lx (%s)\n",
                                      a->codec->master_data->name,
                                      a->codec->master_data->type,
                                      a->codec->master_data->flags,
@@ -380,54 +347,21 @@ videocodec_build_table (void)
                h = h->next;
        }
 
-       return i;
+       return 0;
 }
 
-//The definition:
-//typedef int (read_proc_t)(char *page, char **start, off_t off,
-//                          int count, int *eof, void *data);
-
-static int
-videocodec_info (char  *buffer,
-                char **buffer_location,
-                off_t  offset,
-                int    buffer_length,
-                int   *eof,
-                void  *data)
+static int proc_videocodecs_open(struct inode *inode, struct file *file)
 {
-       int size;
-
-       dprintk(3, "videocodec_info: offset: %ld, len %d / size %d\n",
-               offset, buffer_length, videocodec_bufsize);
-
-       if (offset == 0) {
-               videocodec_bufsize = videocodec_build_table();
-       }
-       if ((offset < 0) || (offset >= videocodec_bufsize)) {
-               dprintk(4,
-                       "videocodec_info: call delivers no result, return 0\n");
-               *eof = 1;
-               return 0;
-       }
-
-       if (buffer_length < (videocodec_bufsize - offset)) {
-               dprintk(4, "videocodec_info: %ld needed, %d got\n",
-                       videocodec_bufsize - offset, buffer_length);
-               size = buffer_length;
-       } else {
-               dprintk(4, "videocodec_info: last reading of %ld bytes\n",
-                       videocodec_bufsize - offset);
-               size = videocodec_bufsize - offset;
-               *eof = 1;
-       }
-
-       memcpy(buffer, videocodec_buf + offset, size);
-       /* doesn't work...                           */
-       /* copy_to_user(buffer, videocodec_buf+offset, size); */
-       /* *buffer_location = videocodec_buf+offset; */
-
-       return size;
+       return single_open(file, proc_videocodecs_show, NULL);
 }
+
+static const struct file_operations videocodecs_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = proc_videocodecs_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
 #endif
 
 /* ===================== */
@@ -444,16 +378,8 @@ videocodec_init (void)
               VIDEOCODEC_VERSION);
 
 #ifdef CONFIG_PROC_FS
-       videocodec_buf = NULL;
-       videocodec_bufsize = 0;
-
-       videocodec_proc_entry = create_proc_entry("videocodecs", 0, NULL);
-       if (videocodec_proc_entry) {
-               videocodec_proc_entry->read_proc = videocodec_info;
-               videocodec_proc_entry->write_proc = NULL;
-               videocodec_proc_entry->data = NULL;
-               videocodec_proc_entry->owner = THIS_MODULE;
-       } else {
+       videocodec_proc_entry = proc_create("videocodecs", 0, NULL, &videocodecs_proc_fops);
+       if (!videocodec_proc_entry) {
                dprintk(1, KERN_ERR "videocodec: can't init procfs.\n");
        }
 #endif
@@ -465,7 +391,6 @@ videocodec_exit (void)
 {
 #ifdef CONFIG_PROC_FS
        remove_proc_entry("videocodecs", NULL);
-       kfree(videocodec_buf);
 #endif
 }
 
index 0d9b63762a48fd42aaaad60054d2a961dd1e83af..31e8af0ba2785e105e60587b8153602b948f55eb 100644 (file)
 
 #define dbgarg(cmd, fmt, arg...) \
                if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) {                \
-                       printk (KERN_DEBUG "%s: ",  vfd->name);         \
+                       printk(KERN_DEBUG "%s: ",  vfd->name);          \
                        v4l_printk_ioctl(cmd);                          \
-                       printk (KERN_DEBUG "%s: " fmt, vfd->name, ## arg); \
+                       printk(" " fmt,  ## arg);                       \
                }
 
 #define dbgarg2(fmt, arg...) \
                if (vfd->debug & V4L2_DEBUG_IOCTL_ARG)                  \
-                       printk (KERN_DEBUG "%s: " fmt, vfd->name, ## arg);
+                       printk(KERN_DEBUG "%s: " fmt, vfd->name, ## arg);
 
 #include <linux/module.h>
 #include <linux/types.h>
@@ -378,38 +378,45 @@ static const char *v4l2_int_ioctls[] = {
    external ioctl messages as well as internal V4L ioctl */
 void v4l_printk_ioctl(unsigned int cmd)
 {
-       char *dir;
+       char *dir, *type;
 
-       switch (_IOC_DIR(cmd)) {
-       case _IOC_NONE:              dir = "--"; break;
-       case _IOC_READ:              dir = "r-"; break;
-       case _IOC_WRITE:             dir = "-w"; break;
-       case _IOC_READ | _IOC_WRITE: dir = "rw"; break;
-       default:                     dir = "*ERR*"; break;
-       }
        switch (_IOC_TYPE(cmd)) {
        case 'd':
-               printk("v4l2_int ioctl %s, dir=%s (0x%08x)\n",
-                      (_IOC_NR(cmd) < V4L2_INT_IOCTLS) ?
-                      v4l2_int_ioctls[_IOC_NR(cmd)] : "UNKNOWN", dir, cmd);
-               break;
+               if (_IOC_NR(cmd) >= V4L2_INT_IOCTLS) {
+                       type = "v4l2_int";
+                       break;
+               }
+               printk("%s", v4l2_int_ioctls[_IOC_NR(cmd)]);
+               return;
 #ifdef CONFIG_VIDEO_V4L1_COMPAT
        case 'v':
-               printk("v4l1 ioctl %s, dir=%s (0x%08x)\n",
-                      (_IOC_NR(cmd) < V4L1_IOCTLS) ?
-                      v4l1_ioctls[_IOC_NR(cmd)] : "UNKNOWN", dir, cmd);
-               break;
+               if (_IOC_NR(cmd) >= V4L1_IOCTLS) {
+                       type = "v4l1";
+                       break;
+               }
+               printk("%s", v4l1_ioctls[_IOC_NR(cmd)]);
+               return;
 #endif
        case 'V':
-               printk("v4l2 ioctl %s, dir=%s (0x%08x)\n",
-                      (_IOC_NR(cmd) < V4L2_IOCTLS) ?
-                      v4l2_ioctls[_IOC_NR(cmd)] : "UNKNOWN", dir, cmd);
-               break;
-
+               if (_IOC_NR(cmd) >= V4L2_IOCTLS) {
+                       type = "v4l2";
+                       break;
+               }
+               printk("%s", v4l2_ioctls[_IOC_NR(cmd)]);
+               return;
        default:
-               printk("unknown ioctl '%c', dir=%s, #%d (0x%08x)\n",
-                      _IOC_TYPE(cmd), dir, _IOC_NR(cmd), cmd);
+               type = "unknown";
+       }
+
+       switch (_IOC_DIR(cmd)) {
+       case _IOC_NONE:              dir = "--"; break;
+       case _IOC_READ:              dir = "r-"; break;
+       case _IOC_WRITE:             dir = "-w"; break;
+       case _IOC_READ | _IOC_WRITE: dir = "rw"; break;
+       default:                     dir = "*ERR*"; break;
        }
+       printk("%s ioctl '%c', dir=%s, #%d (0x%08x)",
+               type, _IOC_TYPE(cmd), dir, _IOC_NR(cmd), cmd);
 }
 EXPORT_SYMBOL(v4l_printk_ioctl);
 
@@ -774,6 +781,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
        if ( (vfd->debug & V4L2_DEBUG_IOCTL) &&
                                !(vfd->debug & V4L2_DEBUG_IOCTL_ARG)) {
                v4l_print_ioctl(vfd->name, cmd);
+               printk("\n");
        }
 
 #ifdef CONFIG_VIDEO_V4L1_COMPAT
@@ -1853,12 +1861,20 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
                        dbgarg (cmd, "chip_ident=%u, revision=0x%x\n", p->ident, p->revision);
                break;
        }
+       default:
+       {
+               if (!vfd->vidioc_default)
+                       break;
+               ret = vfd->vidioc_default(file, fh, cmd, arg);
+               break;
+       }
        } /* switch */
 
        if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) {
                if (ret<0) {
-                       printk ("%s: err:\n", vfd->name);
+                       printk("%s: err: on ", vfd->name);
                        v4l_print_ioctl(vfd->name, cmd);
+                       printk("\n");
                }
        }
 
@@ -2019,7 +2035,7 @@ int video_register_device(struct video_device *vfd, int type, int nr)
                        break;
                default:
                        printk(KERN_ERR "%s called with unknown type: %d\n",
-                              __FUNCTION__, type);
+                              __func__, type);
                        return -1;
        }
 
@@ -2057,7 +2073,7 @@ int video_register_device(struct video_device *vfd, int type, int nr)
        ret = device_register(&vfd->class_dev);
        if (ret < 0) {
                printk(KERN_ERR "%s: device_register failed\n",
-                      __FUNCTION__);
+                      __func__);
                goto fail_minor;
        }
 
index 5bb75294b5aa8142ef1e94b2d321db8955def494..d545c98dd5e7e3eb1a85c12ff64adfa977ba9345 100644 (file)
@@ -333,7 +333,7 @@ struct vino_settings {
  *
  * Use non-zero value to enable conversion.
  */
-static int vino_pixel_conversion = 0;
+static int vino_pixel_conversion;
 
 module_param_named(pixelconv, vino_pixel_conversion, int, 0);
 
@@ -4370,8 +4370,8 @@ static int vino_ioctl(struct inode *inode, struct file *file,
 
 /* Initialization and cleanup */
 
-// __initdata
-static int vino_init_stage = 0;
+/* __initdata */
+static int vino_init_stage;
 
 static const struct file_operations vino_fops = {
        .owner          = THIS_MODULE,
@@ -4385,8 +4385,8 @@ static const struct file_operations vino_fops = {
 
 static struct video_device v4l_device_template = {
        .name           = "NOT SET",
-       //.type         = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE |
-       //      VID_TYPE_CLIPPING | VID_TYPE_SCALES, VID_TYPE_OVERLAY
+       /*.type         = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE | */
+       /*      VID_TYPE_CLIPPING | VID_TYPE_SCALES, VID_TYPE_OVERLAY */
        .fops           = &vino_fops,
        .minor          = -1,
 };
index 1db067c028157609c895b0124e72143acd94c8b2..b1e9592acb907bb06ca59d82e8fa6cafcf5384fc 100644 (file)
@@ -146,8 +146,6 @@ struct vivi_buffer {
 
 struct vivi_dmaqueue {
        struct list_head       active;
-       struct list_head       queued;
-       struct timer_list      timeout;
 
        /* thread for generating video stream*/
        struct task_struct         *kthread;
@@ -162,8 +160,8 @@ static LIST_HEAD(vivi_devlist);
 struct vivi_dev {
        struct list_head           vivi_devlist;
 
-       struct mutex               lock;
        spinlock_t                 slock;
+       struct mutex               mutex;
 
        int                        users;
 
@@ -322,24 +320,26 @@ static void gen_line(char *basep, int inipos, int wmax,
 end:
        return;
 }
+
 static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf)
 {
        int h , pos = 0;
        int hmax  = buf->vb.height;
        int wmax  = buf->vb.width;
        struct timeval ts;
-       char *tmpbuf = kmalloc(wmax * 2, GFP_KERNEL);
+       char *tmpbuf = kmalloc(wmax * 2, GFP_ATOMIC);
        void *vbuf = videobuf_to_vmalloc(&buf->vb);
 
        if (!tmpbuf)
                return;
 
+       if (!vbuf)
+               return;
+
        for (h = 0; h < hmax; h++) {
                gen_line(tmpbuf, 0, wmax, hmax, h, dev->mv_count,
                         dev->timestr);
-               /* FIXME: replacing to __copy_to_user */
-               if (copy_to_user(vbuf + pos, tmpbuf, wmax * 2) != 0)
-                       dprintk(dev, 2, "vivifill copy_to_user failed.\n");
+               memcpy(vbuf + pos, tmpbuf, wmax * 2);
                pos += wmax*2;
        }
 
@@ -372,107 +372,71 @@ static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf)
                        dev->timestr, (unsigned long)tmpbuf, pos);
 
        /* Advice that buffer was filled */
-       buf->vb.state = VIDEOBUF_DONE;
        buf->vb.field_count++;
        do_gettimeofday(&ts);
        buf->vb.ts = ts;
-
-       list_del(&buf->vb.queue);
-       wake_up(&buf->vb.done);
+       buf->vb.state = VIDEOBUF_DONE;
 }
 
-static int restart_video_queue(struct vivi_dmaqueue *dma_q);
-
-static void vivi_thread_tick(struct vivi_dmaqueue  *dma_q)
+static void vivi_thread_tick(struct vivi_fh *fh)
 {
-       struct vivi_buffer    *buf;
-       struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq);
+       struct vivi_buffer *buf;
+       struct vivi_dev *dev = fh->dev;
+       struct vivi_dmaqueue *dma_q = &dev->vidq;
 
-       int bc;
+       unsigned long flags = 0;
 
-       spin_lock(&dev->slock);
-       /* Announces videobuf that all went ok */
-       for (bc = 0;; bc++) {
-               if (list_empty(&dma_q->active)) {
-                       dprintk(dev, 1, "No active queue to serve\n");
-                       break;
-               }
+       dprintk(dev, 1, "Thread tick\n");
 
-               buf = list_entry(dma_q->active.next,
-                                struct vivi_buffer, vb.queue);
+       spin_lock_irqsave(&dev->slock, flags);
+       if (list_empty(&dma_q->active)) {
+               dprintk(dev, 1, "No active queue to serve\n");
+               goto unlock;
+       }
 
-               /* Nobody is waiting something to be done, just return */
-               if (!waitqueue_active(&buf->vb.done)) {
-                       mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT);
-                       spin_unlock(&dev->slock);
-                       return;
-               }
+       buf = list_entry(dma_q->active.next,
+                        struct vivi_buffer, vb.queue);
+
+       /* Nobody is waiting on this buffer, return */
+       if (!waitqueue_active(&buf->vb.done))
+               goto unlock;
 
-               do_gettimeofday(&buf->vb.ts);
-               dprintk(dev, 2, "[%p/%d] wakeup\n", buf, buf->vb. i);
+       list_del(&buf->vb.queue);
 
-               /* Fill buffer */
-               vivi_fillbuff(dev, buf);
+       do_gettimeofday(&buf->vb.ts);
 
-               if (list_empty(&dma_q->active)) {
-                       del_timer(&dma_q->timeout);
-               } else {
-                       mod_timer(&dma_q->timeout, jiffies + BUFFER_TIMEOUT);
-               }
-       }
-       if (bc != 1)
-               dprintk(dev, 1, "%s: %d buffers handled (should be 1)\n",
-                       __FUNCTION__, bc);
-       spin_unlock(&dev->slock);
+       /* Fill buffer */
+       vivi_fillbuff(dev, buf);
+       dprintk(dev, 1, "filled buffer %p\n", buf);
+
+       wake_up(&buf->vb.done);
+       dprintk(dev, 2, "[%p/%d] wakeup\n", buf, buf->vb. i);
+unlock:
+       spin_unlock_irqrestore(&dev->slock, flags);
+       return;
 }
 
 #define frames_to_ms(frames)                                   \
        ((frames * WAKE_NUMERATOR * 1000) / WAKE_DENOMINATOR)
 
-static void vivi_sleep(struct vivi_dmaqueue  *dma_q)
+static void vivi_sleep(struct vivi_fh *fh)
 {
-       struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq);
-       int timeout, running_time;
+       struct vivi_dev *dev = fh->dev;
+       struct vivi_dmaqueue *dma_q = &dev->vidq;
+       int timeout;
        DECLARE_WAITQUEUE(wait, current);
 
-       dprintk(dev, 1, "%s dma_q=0x%08lx\n", __FUNCTION__,
+       dprintk(dev, 1, "%s dma_q=0x%08lx\n", __func__,
                (unsigned long)dma_q);
 
        add_wait_queue(&dma_q->wq, &wait);
        if (kthread_should_stop())
                goto stop_task;
 
-       running_time = jiffies - dma_q->ini_jiffies;
-       dma_q->frame++;
-
        /* Calculate time to wake up */
-       timeout = msecs_to_jiffies(frames_to_ms(dma_q->frame)) - running_time;
-
-       if (timeout > msecs_to_jiffies(frames_to_ms(2)) || timeout <= 0) {
-               int old = dma_q->frame;
-               int nframes;
-
-               dma_q->frame = (jiffies_to_msecs(running_time) /
-                              frames_to_ms(1)) + 1;
-
-               timeout = msecs_to_jiffies(frames_to_ms(dma_q->frame))
-                         - running_time;
-
-               if (unlikely (timeout <= 0))
-                       timeout = 1;
-
-               nframes = (dma_q->frame > old)?
-                                 dma_q->frame - old : old - dma_q->frame;
-
-               dprintk(dev, 1, "%ld: %s %d frames. "
-                       "Current frame is %d. Will sleep for %d jiffies\n",
-                       jiffies,
-                       (dma_q->frame > old)? "Underrun, losed" : "Overrun of",
-                       nframes, dma_q->frame, timeout);
-       } else
-               dprintk(dev, 1, "will sleep for %d jiffies\n", timeout);
+       timeout = msecs_to_jiffies(frames_to_ms(1));
 
-       vivi_thread_tick(dma_q);
+       vivi_thread_tick(fh);
 
        schedule_timeout_interruptible(timeout);
 
@@ -483,16 +447,15 @@ stop_task:
 
 static int vivi_thread(void *data)
 {
-       struct vivi_dmaqueue  *dma_q = data;
-       struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq);
+       struct vivi_fh  *fh = data;
+       struct vivi_dev *dev = fh->dev;
 
        dprintk(dev, 1, "thread started\n");
 
-       mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT);
        set_freezable();
 
        for (;;) {
-               vivi_sleep(dma_q);
+               vivi_sleep(fh);
 
                if (kthread_should_stop())
                        break;
@@ -501,16 +464,17 @@ static int vivi_thread(void *data)
        return 0;
 }
 
-static int vivi_start_thread(struct vivi_dmaqueue  *dma_q)
+static int vivi_start_thread(struct vivi_fh *fh)
 {
-       struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq);
+       struct vivi_dev *dev = fh->dev;
+       struct vivi_dmaqueue *dma_q = &dev->vidq;
 
        dma_q->frame = 0;
        dma_q->ini_jiffies = jiffies;
 
-       dprintk(dev, 1, "%s\n", __FUNCTION__);
+       dprintk(dev, 1, "%s\n", __func__);
 
-       dma_q->kthread = kthread_run(vivi_thread, dma_q, "vivi");
+       dma_q->kthread = kthread_run(vivi_thread, fh, "vivi");
 
        if (IS_ERR(dma_q->kthread)) {
                printk(KERN_ERR "vivi: kernel_thread() failed\n");
@@ -519,7 +483,7 @@ static int vivi_start_thread(struct vivi_dmaqueue  *dma_q)
        /* Wakes thread */
        wake_up_interruptible(&dma_q->wq);
 
-       dprintk(dev, 1, "returning from %s\n", __FUNCTION__);
+       dprintk(dev, 1, "returning from %s\n", __func__);
        return 0;
 }
 
@@ -527,7 +491,7 @@ static void vivi_stop_thread(struct vivi_dmaqueue  *dma_q)
 {
        struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq);
 
-       dprintk(dev, 1, "%s\n", __FUNCTION__);
+       dprintk(dev, 1, "%s\n", __func__);
        /* shutdown control thread */
        if (dma_q->kthread) {
                kthread_stop(dma_q->kthread);
@@ -535,91 +499,6 @@ static void vivi_stop_thread(struct vivi_dmaqueue  *dma_q)
        }
 }
 
-static int restart_video_queue(struct vivi_dmaqueue *dma_q)
-{
-       struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq);
-       struct vivi_buffer *buf, *prev;
-
-       dprintk(dev, 1, "%s dma_q=0x%08lx\n", __FUNCTION__,
-               (unsigned long)dma_q);
-
-       if (!list_empty(&dma_q->active)) {
-               buf = list_entry(dma_q->active.next,
-                                struct vivi_buffer, vb.queue);
-               dprintk(dev, 2, "restart_queue [%p/%d]: restart dma\n",
-                       buf, buf->vb.i);
-
-               dprintk(dev, 1, "Restarting video dma\n");
-               vivi_stop_thread(dma_q);
-
-               /* cancel all outstanding capture / vbi requests */
-               list_for_each_entry_safe(buf, prev, &dma_q->active, vb.queue) {
-                       list_del(&buf->vb.queue);
-                       buf->vb.state = VIDEOBUF_ERROR;
-                       wake_up(&buf->vb.done);
-               }
-               mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT);
-
-               return 0;
-       }
-
-       prev = NULL;
-       for (;;) {
-               if (list_empty(&dma_q->queued))
-                       return 0;
-               buf = list_entry(dma_q->queued.next,
-                                struct vivi_buffer, vb.queue);
-               if (NULL == prev) {
-                       list_del(&buf->vb.queue);
-                       list_add_tail(&buf->vb.queue, &dma_q->active);
-
-                       dprintk(dev, 1, "Restarting video dma\n");
-                       vivi_stop_thread(dma_q);
-                       vivi_start_thread(dma_q);
-
-                       buf->vb.state = VIDEOBUF_ACTIVE;
-                       mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT);
-                       dprintk(dev, 2,
-                               "[%p/%d] restart_queue - first active\n",
-                               buf, buf->vb.i);
-
-               } else if (prev->vb.width  == buf->vb.width  &&
-                          prev->vb.height == buf->vb.height &&
-                          prev->fmt       == buf->fmt) {
-                       list_del(&buf->vb.queue);
-                       list_add_tail(&buf->vb.queue, &dma_q->active);
-                       buf->vb.state = VIDEOBUF_ACTIVE;
-                       dprintk(dev, 2,
-                               "[%p/%d] restart_queue - move to active\n",
-                               buf, buf->vb.i);
-               } else {
-                       return 0;
-               }
-               prev = buf;
-       }
-}
-
-static void vivi_vid_timeout(unsigned long data)
-{
-       struct vivi_dev      *dev  = (struct vivi_dev *)data;
-       struct vivi_dmaqueue *vidq = &dev->vidq;
-       struct vivi_buffer   *buf;
-
-       spin_lock(&dev->slock);
-
-       while (!list_empty(&vidq->active)) {
-               buf = list_entry(vidq->active.next,
-                                struct vivi_buffer, vb.queue);
-               list_del(&buf->vb.queue);
-               buf->vb.state = VIDEOBUF_ERROR;
-               wake_up(&buf->vb.done);
-               printk(KERN_INFO "vivi/0: [%p/%d] timeout\n", buf, buf->vb.i);
-       }
-       restart_video_queue(vidq);
-
-       spin_unlock(&dev->slock);
-}
-
 /* ------------------------------------------------------------------
        Videobuf operations
    ------------------------------------------------------------------*/
@@ -637,7 +516,7 @@ buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size)
        while (*size * *count > vid_limit * 1024 * 1024)
                (*count)--;
 
-       dprintk(dev, 1, "%s, count=%d, size=%d\n", __FUNCTION__,
+       dprintk(dev, 1, "%s, count=%d, size=%d\n", __func__,
                *count, *size);
 
        return 0;
@@ -648,13 +527,13 @@ static void free_buffer(struct videobuf_queue *vq, struct vivi_buffer *buf)
        struct vivi_fh  *fh = vq->priv_data;
        struct vivi_dev *dev  = fh->dev;
 
-       dprintk(dev, 1, "%s\n", __FUNCTION__);
+       dprintk(dev, 1, "%s, state: %i\n", __func__, buf->vb.state);
 
        if (in_interrupt())
                BUG();
 
-       videobuf_waiton(&buf->vb, 0, 0);
        videobuf_vmalloc_free(&buf->vb);
+       dprintk(dev, 1, "free_buffer: freed\n");
        buf->vb.state = VIDEOBUF_NEEDS_INIT;
 }
 
@@ -667,28 +546,25 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
        struct vivi_fh     *fh  = vq->priv_data;
        struct vivi_dev    *dev = fh->dev;
        struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);
-       int rc, init_buffer = 0;
+       int rc;
 
-       dprintk(dev, 1, "%s, field=%d\n", __FUNCTION__, field);
+       dprintk(dev, 1, "%s, field=%d\n", __func__, field);
 
        BUG_ON(NULL == fh->fmt);
+
        if (fh->width  < 48 || fh->width  > norm_maxw() ||
            fh->height < 32 || fh->height > norm_maxh())
                return -EINVAL;
+
        buf->vb.size = fh->width*fh->height*2;
        if (0 != buf->vb.baddr  &&  buf->vb.bsize < buf->vb.size)
                return -EINVAL;
 
-       if (buf->fmt       != fh->fmt    ||
-           buf->vb.width  != fh->width  ||
-           buf->vb.height != fh->height ||
-       buf->vb.field  != field) {
-               buf->fmt       = fh->fmt;
-               buf->vb.width  = fh->width;
-               buf->vb.height = fh->height;
-               buf->vb.field  = field;
-               init_buffer = 1;
-       }
+       /* These properties only change when queue is idle, see s_fmt */
+       buf->fmt       = fh->fmt;
+       buf->vb.width  = fh->width;
+       buf->vb.height = fh->height;
+       buf->vb.field  = field;
 
        if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
                rc = videobuf_iolock(vq, &buf->vb, NULL);
@@ -711,45 +587,12 @@ buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
        struct vivi_buffer    *buf  = container_of(vb, struct vivi_buffer, vb);
        struct vivi_fh        *fh   = vq->priv_data;
        struct vivi_dev       *dev  = fh->dev;
-       struct vivi_dmaqueue  *vidq = &dev->vidq;
-       struct vivi_buffer    *prev;
-
-       if (!list_empty(&vidq->queued)) {
-               dprintk(dev, 1, "adding vb queue=0x%08lx\n",
-                       (unsigned long)&buf->vb.queue);
-               list_add_tail(&buf->vb.queue, &vidq->queued);
-               buf->vb.state = VIDEOBUF_QUEUED;
-               dprintk(dev, 2, "[%p/%d] buffer_queue - append to queued\n",
-                       buf, buf->vb.i);
-       } else if (list_empty(&vidq->active)) {
-               list_add_tail(&buf->vb.queue, &vidq->active);
-
-               buf->vb.state = VIDEOBUF_ACTIVE;
-               mod_timer(&vidq->timeout, jiffies+BUFFER_TIMEOUT);
-               dprintk(dev, 2, "[%p/%d] buffer_queue - first active\n",
-                       buf, buf->vb.i);
-
-               vivi_start_thread(vidq);
-       } else {
-               prev = list_entry(vidq->active.prev,
-                                 struct vivi_buffer, vb.queue);
-               if (prev->vb.width  == buf->vb.width  &&
-                   prev->vb.height == buf->vb.height &&
-                   prev->fmt       == buf->fmt) {
-                       list_add_tail(&buf->vb.queue, &vidq->active);
-                       buf->vb.state = VIDEOBUF_ACTIVE;
-                       dprintk(dev, 2,
-                               "[%p/%d] buffer_queue - append to active\n",
-                               buf, buf->vb.i);
-
-               } else {
-                       list_add_tail(&buf->vb.queue, &vidq->queued);
-                       buf->vb.state = VIDEOBUF_QUEUED;
-                       dprintk(dev, 2,
-                               "[%p/%d] buffer_queue - first queued\n",
-                               buf, buf->vb.i);
-               }
-       }
+       struct vivi_dmaqueue *vidq = &dev->vidq;
+
+       dprintk(dev, 1, "%s\n", __func__);
+
+       buf->vb.state = VIDEOBUF_QUEUED;
+       list_add_tail(&buf->vb.queue, &vidq->active);
 }
 
 static void buffer_release(struct videobuf_queue *vq,
@@ -758,11 +601,8 @@ static void buffer_release(struct videobuf_queue *vq,
        struct vivi_buffer   *buf  = container_of(vb, struct vivi_buffer, vb);
        struct vivi_fh       *fh   = vq->priv_data;
        struct vivi_dev      *dev  = (struct vivi_dev *)fh->dev;
-       struct vivi_dmaqueue *vidq = &dev->vidq;
-
-       dprintk(dev, 1, "%s\n", __FUNCTION__);
 
-       vivi_stop_thread(vidq);
+       dprintk(dev, 1, "%s\n", __func__);
 
        free_buffer(vq, buf);
 }
@@ -869,17 +709,31 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv,
                                        struct v4l2_format *f)
 {
        struct vivi_fh  *fh = priv;
+       struct videobuf_queue *q = &fh->vb_vidq;
+
        int ret = vidioc_try_fmt_cap(file, fh, f);
        if (ret < 0)
                return (ret);
 
+       mutex_lock(&q->vb_lock);
+
+       if (videobuf_queue_is_busy(&fh->vb_vidq)) {
+               dprintk(fh->dev, 1, "%s queue busy\n", __func__);
+               ret = -EBUSY;
+               goto out;
+       }
+
        fh->fmt           = &format;
        fh->width         = f->fmt.pix.width;
        fh->height        = f->fmt.pix.height;
        fh->vb_vidq.field = f->fmt.pix.field;
        fh->type          = f->type;
 
-       return (0);
+       ret = 0;
+out:
+       mutex_unlock(&q->vb_lock);
+
+       return (ret);
 }
 
 static int vidioc_reqbufs(struct file *file, void *priv,
@@ -1036,6 +890,7 @@ static int vivi_open(struct inode *inode, struct file *file)
        struct vivi_dev *dev;
        struct vivi_fh *fh;
        int i;
+       int retval = 0;
 
        printk(KERN_DEBUG "vivi: open called (minor=%d)\n", minor);
 
@@ -1045,9 +900,15 @@ static int vivi_open(struct inode *inode, struct file *file)
        return -ENODEV;
 
 found:
-       /* If more than one user, mutex should be added */
+       mutex_lock(&dev->mutex);
        dev->users++;
 
+       if (dev->users > 1) {
+               dev->users--;
+               retval = -EBUSY;
+               goto unlock;
+       }
+
        dprintk(dev, 1, "open minor=%d type=%s users=%d\n", minor,
                v4l2_type_names[V4L2_BUF_TYPE_VIDEO_CAPTURE], dev->users);
 
@@ -1055,8 +916,13 @@ found:
        fh = kzalloc(sizeof(*fh), GFP_KERNEL);
        if (NULL == fh) {
                dev->users--;
-               return -ENOMEM;
+               retval = -ENOMEM;
+               goto unlock;
        }
+unlock:
+       mutex_unlock(&dev->mutex);
+       if (retval)
+               return retval;
 
        file->private_data = fh;
        fh->dev      = dev;
@@ -1084,6 +950,8 @@ found:
                        NULL, &dev->slock, fh->type, V4L2_FIELD_INTERLACED,
                        sizeof(struct vivi_buffer), fh);
 
+       vivi_start_thread(fh);
+
        return 0;
 }
 
@@ -1106,7 +974,7 @@ vivi_poll(struct file *file, struct poll_table_struct *wait)
        struct vivi_dev       *dev = fh->dev;
        struct videobuf_queue *q = &fh->vb_vidq;
 
-       dprintk(dev, 1, "%s\n", __FUNCTION__);
+       dprintk(dev, 1, "%s\n", __func__);
 
        if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type)
                return POLLERR;
@@ -1128,7 +996,9 @@ static int vivi_close(struct inode *inode, struct file *file)
 
        kfree(fh);
 
+       mutex_lock(&dev->mutex);
        dev->users--;
+       mutex_unlock(&dev->mutex);
 
        dprintk(dev, 1, "close called (minor=%d, users=%d)\n",
                minor, dev->users);
@@ -1182,6 +1052,7 @@ static const struct file_operations vivi_fops = {
        .read           = vivi_read,
        .poll           = vivi_poll,
        .ioctl          = video_ioctl2, /* V4L2 ioctl handler */
+       .compat_ioctl   = v4l_compat_ioctl32,
        .mmap           = vivi_mmap,
        .llseek         = no_llseek,
 };
@@ -1236,16 +1107,11 @@ static int __init vivi_init(void)
 
                /* init video dma queues */
                INIT_LIST_HEAD(&dev->vidq.active);
-               INIT_LIST_HEAD(&dev->vidq.queued);
                init_waitqueue_head(&dev->vidq.wq);
 
                /* initialize locks */
-               mutex_init(&dev->lock);
                spin_lock_init(&dev->slock);
-
-               dev->vidq.timeout.function = vivi_vid_timeout;
-               dev->vidq.timeout.data     = (unsigned long)dev;
-               init_timer(&dev->vidq.timeout);
+               mutex_init(&dev->mutex);
 
                vfd = video_device_alloc();
                if (NULL == vfd)
index a9133858e913552e62474792ad6b647a0865edd5..35293029da02423e1c31cb1aedb136f78c6b090f 100644 (file)
@@ -40,7 +40,7 @@
 #define I2C_VPX3220        0x86
 #define VPX3220_DEBUG  KERN_DEBUG "vpx3220: "
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0-1)");
 
index 08aaae07c7e0cb3c4a58e386bb49312068c2f613..33f702698a56f06d629bceb96bef454661282855 100644 (file)
 #include <media/v4l2-common.h>
 #include <linux/parport.h>
 
-//#define DEBUG                                // Undef me for production
+/*#define DEBUG*/                              /* Undef me for production */
 
 #ifdef DEBUG
-#define DPRINTF(x, a...) printk(KERN_DEBUG "W9966: %s(): "x, __FUNCTION__ , ##a)
+#define DPRINTF(x, a...) printk(KERN_DEBUG "W9966: %s(): "x, __func__ , ##a)
 #else
 #define DPRINTF(x...)
 #endif
@@ -134,7 +134,7 @@ MODULE_PARM_DESC(pardev, "pardev: where to search for\n\
 \tEg: >pardev=parport3,aggressive,parport2,parport1< would assign\n\
 \tcam 1 to parport3 and search every parport for cam 2 etc...");
 
-static int parmode = 0;
+static int parmode;
 module_param(parmode, int, 0);
 MODULE_PARM_DESC(parmode, "parmode: transfer mode (0=auto, 1=ecp, 2=epp");
 
@@ -188,7 +188,9 @@ static const struct file_operations w9966_fops = {
        .open           = video_exclusive_open,
        .release        = video_exclusive_release,
        .ioctl          = w9966_v4l_ioctl,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .read           = w9966_v4l_read,
        .llseek         = no_llseek,
 };
index 2ae1430f5f7d0165942d2427d80fdaa833448213..840522442d07d4a6316a76a7f658481da60de77f 100644 (file)
@@ -3461,7 +3461,9 @@ static const struct file_operations w9968cf_fops = {
        .release = w9968cf_release,
        .read =    w9968cf_read,
        .ioctl =   w9968cf_ioctl,
+#ifdef CONFIG_COMPAT
        .compat_ioctl = v4l_compat_ioctl32,
+#endif
        .mmap =    w9968cf_mmap,
        .llseek =  no_llseek,
 };
@@ -3481,7 +3483,7 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
        enum w9968cf_model_id mod_id;
        struct list_head* ptr;
        u8 sc = 0; /* number of simultaneous cameras */
-       static unsigned short dev_nr = 0; /* we are handling device number n */
+       static unsigned short dev_nr; /* 0 - we are handling device number n */
 
        if (le16_to_cpu(udev->descriptor.idVendor)  == winbond_id_table[0].idVendor &&
            le16_to_cpu(udev->descriptor.idProduct) == winbond_id_table[0].idProduct)
index ec7696e8f1fac3eaf3b47725c37db3ec1dde8154..3c95316bc030cf7dcbcfea1023a4cc5b5426eec7 100644 (file)
@@ -298,7 +298,7 @@ struct w9968cf_device {
                        dev_warn(&cam->dev, fmt "\n", ## args);               \
                else if ((level) >= 5)                                        \
                        dev_info(&cam->dev, "[%s:%d] " fmt "\n",              \
-                                __FUNCTION__, __LINE__ , ## args);           \
+                                __func__, __LINE__ , ## args);           \
        }                                                                     \
 }
 /* For generic kernel (not device specific) messages */
@@ -309,7 +309,7 @@ struct w9968cf_device {
                if ((level) >= 1 && (level) <= 4)                             \
                        pr_info("w9968cf: " fmt "\n", ## args);               \
                else if ((level) >= 5)                                        \
-                       pr_debug("w9968cf: [%s:%d] " fmt "\n", __FUNCTION__,  \
+                       pr_debug("w9968cf: [%s:%d] " fmt "\n", __func__,  \
                                 __LINE__ , ## args);                         \
        }                                                                     \
 }
@@ -321,7 +321,7 @@ struct w9968cf_device {
 
 #undef PDBG
 #define PDBG(fmt, args...)                                                    \
-dev_info(&cam->dev, "[%s:%d] " fmt "\n", __FUNCTION__, __LINE__ , ## args);
+dev_info(&cam->dev, "[%s:%d] " fmt "\n", __func__, __LINE__ , ## args);
 
 #undef PDBGG
 #define PDBGG(fmt, args...) do {;} while(0); /* nothing: it's a placeholder */
index a2de50efa31adec2c439b182070e8db95f6e7781..7bbab541a309d59f6141b7a0b10ff918baf945ce 100644 (file)
@@ -160,7 +160,7 @@ do {                                                                          \
                        dev_info(&cam->usbdev->dev, fmt "\n", ## args);       \
                else if ((level) >= 3)                                        \
                        dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n",   \
-                                __FILE__, __FUNCTION__, __LINE__ , ## args); \
+                                __FILE__, __func__, __LINE__ , ## args); \
        }                                                                     \
 } while (0)
 #      define KDBG(level, fmt, args...)                                      \
@@ -170,7 +170,7 @@ do {                                                                          \
                        pr_info("zc0301: " fmt "\n", ## args);                \
                else if ((level) == 3)                                        \
                        pr_debug("sn9c102: [%s:%s:%d] " fmt "\n", __FILE__,   \
-                                __FUNCTION__, __LINE__ , ## args);           \
+                                __func__, __LINE__ , ## args);           \
        }                                                                     \
 } while (0)
 #      define V4LDBG(level, name, cmd)                                       \
@@ -186,7 +186,7 @@ do {                                                                          \
 
 #undef PDBG
 #define PDBG(fmt, args...)                                                    \
-dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __FUNCTION__,   \
+dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __func__,   \
         __LINE__ , ## args)
 
 #undef PDBGG
index 2c5665c824423360481ea49a5f388a4a79c76223..363dd2b9475cfe40ca30fd3adfecdb2689d59d8c 100644 (file)
@@ -1925,7 +1925,9 @@ static const struct file_operations zc0301_fops = {
        .open =    zc0301_open,
        .release = zc0301_release,
        .ioctl =   zc0301_ioctl,
+#ifdef CONFIG_COMPAT
        .compat_ioctl = v4l_compat_ioctl32,
+#endif
        .read =    zc0301_read,
        .poll =    zc0301_poll,
        .mmap =    zc0301_mmap,
@@ -1939,7 +1941,7 @@ zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
 {
        struct usb_device *udev = interface_to_usbdev(intf);
        struct zc0301_device* cam;
-       static unsigned int dev_nr = 0;
+       static unsigned int dev_nr;
        unsigned int i;
        int err = 0;
 
index 498a43c1f2b1595fc2352c56a5fad686d971a4a0..81cc3b00a07912bbf0d512055151c0bfbce6c509 100644 (file)
@@ -243,10 +243,8 @@ struct zoran_format {
 #ifdef CONFIG_VIDEO_V4L1_COMPAT
        int palette;
 #endif
-#ifdef CONFIG_VIDEO_V4L2
        __u32 fourcc;
        int colorspace;
-#endif
        int depth;
        __u32 flags;
        __u32 vfespfr;
@@ -271,20 +269,6 @@ struct zoran_v4l_settings {
        const struct zoran_format *format;      /* capture format */
 };
 
-/* whoops, this one is undeclared if !v4l2 */
-#ifndef CONFIG_VIDEO_V4L2
-struct v4l2_jpegcompression {
-       int quality;
-       int APPn;
-       int APP_len;
-       char APP_data[60];
-       int COM_len;
-       char COM_data[60];
-       __u32 jpeg_markers;
-       __u8 reserved[116];
-};
-#endif
-
 /* jpg-capture/-playback settings */
 struct zoran_jpg_settings {
        int decimation;         /* this bit is used to set everything to default */
index 690281bb59ee616f71db4393d7b63a4080455284..006d48847e24a90396c0cfdaf29ad83554746a34 100644 (file)
@@ -83,7 +83,7 @@ MODULE_PARM_DESC(decoder, "i2c TV decoder");
    or set in in a VIDIOCSFBUF ioctl
  */
 
-static unsigned long vidmem = 0;       /* Video memory base address */
+static unsigned long vidmem;   /* default = 0 - Video memory base address */
 module_param(vidmem, ulong, 0444);
 MODULE_PARM_DESC(vidmem, "Default video memory base address");
 
@@ -91,7 +91,7 @@ MODULE_PARM_DESC(vidmem, "Default video memory base address");
    Default input and video norm at startup of the driver.
 */
 
-static unsigned int default_input = 0; /* 0=Composite, 1=S-Video */
+static unsigned int default_input;     /* default 0 = Composite, 1 = S-Video */
 module_param(default_input, uint, 0444);
 MODULE_PARM_DESC(default_input,
                 "Default input (0=Composite, 1=S-Video, 2=Internal)");
@@ -101,7 +101,7 @@ module_param(default_mux, int, 0644);
 MODULE_PARM_DESC(default_mux,
                 "Default 6 Eyes mux setting (Input selection)");
 
-static int default_norm = 0;   /* 0=PAL, 1=NTSC 2=SECAM */
+static int default_norm;       /* default 0 = PAL, 1 = NTSC 2 = SECAM */
 module_param(default_norm, int, 0444);
 MODULE_PARM_DESC(default_norm, "Default norm (0=PAL, 1=NTSC, 2=SECAM)");
 
index 8444ca0a5f3fd72837554f3edada9dbcbc4918dc..1b5c4171cf9c37f0b7c3f6f365490ded31b95da2 100644 (file)
@@ -50,4 +50,6 @@ extern int zoran_check_jpg_settings(struct zoran *zr,
 extern void zoran_open_init_params(struct zoran *zr);
 extern void zoran_vdev_release(struct video_device *vdev);
 
+void zr36016_write(struct videocodec *codec, u16 reg, u32 val);
+
 #endif                         /* __ZORAN_CARD_H__ */
index f97c206920579997c5e003c70ab9afb84998a9e9..7b60533efe456bb4b650f060acc02bf66396f1de 100644 (file)
@@ -60,7 +60,8 @@
 
 extern const struct zoran_format zoran_formats[];
 
-static int lml33dpath = 0;     /* 1 will use digital path in capture
+static int lml33dpath;         /* default = 0
+                                * 1 will use digital path in capture
                                 * mode instead of analog. It can be
                                 * used for picture adjustments using
                                 * tool like xawtv while watching image
@@ -927,11 +928,6 @@ count_reset_interrupt (struct zoran *zr)
        return isr;
 }
 
-/* hack */
-extern void zr36016_write (struct videocodec *codec,
-                          u16                reg,
-                          u32                val);
-
 void
 jpeg_start (struct zoran *zr)
 {
@@ -987,7 +983,7 @@ void
 zr36057_enable_jpg (struct zoran          *zr,
                    enum zoran_codec_mode  mode)
 {
-       static int zero = 0;
+       static int zero;
        static int one = 1;
        struct vfe_settings cap;
        int field_size =
@@ -1726,7 +1722,7 @@ decoder_command (struct zoran *zr,
                return -EIO;
 
        if (zr->card.type == LML33 &&
-           (cmd == DECODER_SET_NORM || DECODER_SET_INPUT)) {
+           (cmd == DECODER_SET_NORM || cmd == DECODER_SET_INPUT)) {
                int res;
 
                // Bt819 needs to reset its FIFO buffer using #FRST pin and
index fea4946ee713c82d4b17eaff5864ccb943a9f545..0134bec1e399e66fca43153dbe64c6c9066d84c0 100644 (file)
@@ -85,7 +85,6 @@
 #include "zoran_device.h"
 #include "zoran_card.h"
 
-#ifdef CONFIG_VIDEO_V4L2
        /* we declare some card type definitions here, they mean
         * the same as the v4l1 ZORAN_VID_TYPE above, except it's v4l2 */
 #define ZORAN_V4L2_VID_FLAGS ( \
                                V4L2_CAP_VIDEO_OUTPUT |\
                                V4L2_CAP_VIDEO_OVERLAY \
                              )
-#endif
 
 #include <asm/byteorder.h>
 
-#if defined(CONFIG_VIDEO_V4L2) && defined(CONFIG_VIDEO_V4L1_COMPAT)
+#if defined(CONFIG_VIDEO_V4L1_COMPAT)
 #define ZFMT(pal, fcc, cs) \
        .palette = (pal), .fourcc = (fcc), .colorspace = (cs)
-#elif defined(CONFIG_VIDEO_V4L2)
-#define ZFMT(pal, fcc, cs) \
-       .fourcc = (fcc), .colorspace = (cs)
 #else
 #define ZFMT(pal, fcc, cs) \
-       .palette = (pal)
+       .fourcc = (fcc), .colorspace = (cs)
 #endif
 
 const struct zoran_format zoran_formats[] = {
@@ -205,11 +200,10 @@ extern int jpg_nbufs;
 extern int jpg_bufsize;
 extern int pass_through;
 
-static int lock_norm = 0;      /* 1=Don't change TV standard (norm) */
+static int lock_norm;  /* 0 = default 1 = Don't change TV standard (norm) */
 module_param(lock_norm, int, 0644);
 MODULE_PARM_DESC(lock_norm, "Prevent norm changes (1 = ignore, >1 = fail)");
 
-#ifdef CONFIG_VIDEO_V4L2
        /* small helper function for calculating buffersizes for v4l2
         * we calculate the nearest higher power-of-two, which
         * will be the recommended buffersize */
@@ -232,7 +226,6 @@ zoran_v4l2_calc_bufsize (struct zoran_jpg_settings *settings)
                return 8192;
        return result;
 }
-#endif
 
 /* forward references */
 static void v4l_fbuffer_free(struct file *file);
@@ -1709,7 +1702,6 @@ setup_overlay (struct file *file,
        return wait_grab_pending(zr);
 }
 
-#ifdef CONFIG_VIDEO_V4L2
        /* get the status of a buffer in the clients buffer queue */
 static int
 zoran_v4l2_buffer_status (struct file        *file,
@@ -1815,7 +1807,6 @@ zoran_v4l2_buffer_status (struct file        *file,
 
        return 0;
 }
-#endif
 
 static int
 zoran_set_norm (struct zoran *zr,
@@ -2624,8 +2615,6 @@ zoran_do_ioctl (struct inode *inode,
        }
                break;
 
-#ifdef CONFIG_VIDEO_V4L2
-
                /* The new video4linux2 capture interface - much nicer than video4linux1, since
                 * it allows for integrating the JPEG capturing calls inside standard v4l2
                 */
@@ -4197,7 +4186,6 @@ zoran_do_ioctl (struct inode *inode,
                return 0;
        }
                break;
-#endif
 
        default:
                dprintk(1, KERN_DEBUG "%s: UNKNOWN ioctl cmd: 0x%x\n",
@@ -4247,7 +4235,7 @@ zoran_poll (struct file *file,
                dprintk(3,
                        KERN_DEBUG
                        "%s: %s() raw - active=%c, sync_tail=%lu/%c, pend_tail=%lu, pend_head=%lu\n",
-                       ZR_DEVNAME(zr), __FUNCTION__,
+                       ZR_DEVNAME(zr), __func__,
                        "FAL"[fh->v4l_buffers.active], zr->v4l_sync_tail,
                        "UPMD"[zr->v4l_buffers.buffer[frame].state],
                        zr->v4l_pend_tail, zr->v4l_pend_head);
@@ -4269,7 +4257,7 @@ zoran_poll (struct file *file,
                dprintk(3,
                        KERN_DEBUG
                        "%s: %s() jpg - active=%c, que_tail=%lu/%c, que_head=%lu, dma=%lu/%lu\n",
-                       ZR_DEVNAME(zr), __FUNCTION__,
+                       ZR_DEVNAME(zr), __func__,
                        "FAL"[fh->jpg_buffers.active], zr->jpg_que_tail,
                        "UPMD"[zr->jpg_buffers.buffer[frame].state],
                        zr->jpg_que_head, zr->jpg_dma_tail, zr->jpg_dma_head);
@@ -4644,7 +4632,9 @@ static const struct file_operations zoran_fops = {
        .open = zoran_open,
        .release = zoran_close,
        .ioctl = zoran_ioctl,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .llseek = no_llseek,
        .read = zoran_read,
        .write = zoran_write,
@@ -4655,9 +4645,7 @@ static const struct file_operations zoran_fops = {
 struct video_device zoran_template __devinitdata = {
        .name = ZORAN_NAME,
        .type = ZORAN_VID_TYPE,
-#ifdef CONFIG_VIDEO_V4L2
        .type2 = ZORAN_V4L2_VID_FLAGS,
-#endif
        .fops = &zoran_fops,
        .release = &zoran_vdev_release,
        .minor = -1
index dd084555da8f8f19c20cfb59455b62b0aefb4579..00d132bcd1e4fecb64860d9d165a61eedc547b29 100644 (file)
 #define MAX_CODECS 20
 
 /* amount of chips attached via this driver */
-static int zr36016_codecs = 0;
+static int zr36016_codecs;
 
 /* debugging is available via module parameter */
-
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0-4)");
 
index faae4ec3ea0bf5288f12a1c52a78ce75e12bd7c2..cf8b271a1c8f1907e3885773ba5dad02d67f07cf 100644 (file)
 #define MAX_CODECS 20
 
 /* amount of chips attached via this driver */
-static int zr36050_codecs = 0;
+static int zr36050_codecs;
 
 /* debugging is available via module parameter */
-
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0-4)");
 
index 7849b65969d0741e624b350aa80e79eb18d50321..8e74054d5ef10ea0615fbf927f3e17b06c04a81e 100644 (file)
 #define MAX_CODECS 20
 
 /* amount of chips attached via this driver */
-static int zr36060_codecs = 0;
+static int zr36060_codecs;
 
-static int low_bitrate = 0;
+static int low_bitrate;
 module_param(low_bitrate, bool, 0);
 MODULE_PARM_DESC(low_bitrate, "Buz compatibility option, halves bitrate");
 
 /* debugging is available via module parameter */
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0-4)");
 
index 04949c823654db4b4e95d4a4814d73a23a029d02..a0e49dc66301f06af6130441c9cc1e0fac6b50b2 100644 (file)
@@ -62,8 +62,8 @@
 
 
 /* Module parameters */
-static int debug = 0;
-static int mode = 0;
+static int debug;
+static int mode;
 
 
 /* Module parameters interface */
index af66f4f283000bd91a67390b2ab716ed525cd0a6..4edc120a6359490a816eca96f30dbbc3a5eda624 100644 (file)
@@ -19,8 +19,6 @@
 #include <linux/interrupt.h>
 #include <linux/mfd/htc-pasic3.h>
 
-#include <asm/arch/pxa-regs.h>
-
 struct pasic3_data {
        void __iomem *mapping;
        unsigned int bus_shift;
@@ -30,7 +28,6 @@ struct pasic3_data {
 
 #define REG_ADDR  5
 #define REG_DATA  6
-#define NUM_REGS  7
 
 #define READ_MODE 0x80
 
index 2399a3796f6ed2e0bd9f4049cc7ddbd87c468f00..015e163259738af5ba3e74dfd69da9bda5d350f2 100644 (file)
@@ -827,7 +827,7 @@ config ULTRA32
 
 config BFIN_MAC
        tristate "Blackfin 527/536/537 on-chip mac support"
-       depends on NET_ETHERNET && (BF527 || BF537 || BF536) && (!BF537_PORT_H)
+       depends on NET_ETHERNET && (BF527 || BF537 || BF536)
        select CRC32
        select MII
        select PHYLIB
index 4dc5b4b7a561b102e537ef85205b9ab72da334cc..d3207c0da89561eb345b1d0873eb19b5a3695438 100644 (file)
@@ -123,7 +123,6 @@ struct ppp {
        u32             minseq;         /* MP: min of most recent seqnos */
        struct sk_buff_head mrq;        /* MP: receive reconstruction queue */
 #endif /* CONFIG_PPP_MULTILINK */
-       struct net_device_stats stats;  /* statistics */
 #ifdef CONFIG_PPP_FILTER
        struct sock_filter *pass_filter;        /* filter for packets to pass */
        struct sock_filter *active_filter;/* filter for pkts to reset idle */
@@ -914,18 +913,10 @@ ppp_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
  outf:
        kfree_skb(skb);
-       ++ppp->stats.tx_dropped;
+       ++ppp->dev->stats.tx_dropped;
        return 0;
 }
 
-static struct net_device_stats *
-ppp_net_stats(struct net_device *dev)
-{
-       struct ppp *ppp = (struct ppp *) dev->priv;
-
-       return &ppp->stats;
-}
-
 static int
 ppp_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
@@ -1095,8 +1086,8 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb)
 #endif /* CONFIG_PPP_FILTER */
        }
 
-       ++ppp->stats.tx_packets;
-       ppp->stats.tx_bytes += skb->len - 2;
+       ++ppp->dev->stats.tx_packets;
+       ppp->dev->stats.tx_bytes += skb->len - 2;
 
        switch (proto) {
        case PPP_IP:
@@ -1171,7 +1162,7 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb)
  drop:
        if (skb)
                kfree_skb(skb);
-       ++ppp->stats.tx_errors;
+       ++ppp->dev->stats.tx_errors;
 }
 
 /*
@@ -1409,7 +1400,7 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
        spin_unlock_bh(&pch->downl);
        if (ppp->debug & 1)
                printk(KERN_ERR "PPP: no memory (fragment)\n");
-       ++ppp->stats.tx_errors;
+       ++ppp->dev->stats.tx_errors;
        ++ppp->nxseq;
        return 1;       /* abandon the frame */
 }
@@ -1538,7 +1529,7 @@ ppp_receive_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
 
        if (skb->len > 0)
                /* note: a 0-length skb is used as an error indication */
-               ++ppp->stats.rx_length_errors;
+               ++ppp->dev->stats.rx_length_errors;
 
        kfree_skb(skb);
        ppp_receive_error(ppp);
@@ -1547,7 +1538,7 @@ ppp_receive_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
 static void
 ppp_receive_error(struct ppp *ppp)
 {
-       ++ppp->stats.rx_errors;
+       ++ppp->dev->stats.rx_errors;
        if (ppp->vj)
                slhc_toss(ppp->vj);
 }
@@ -1627,8 +1618,8 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
                break;
        }
 
-       ++ppp->stats.rx_packets;
-       ppp->stats.rx_bytes += skb->len - 2;
+       ++ppp->dev->stats.rx_packets;
+       ppp->dev->stats.rx_bytes += skb->len - 2;
 
        npi = proto_to_npindex(proto);
        if (npi < 0) {
@@ -1806,7 +1797,7 @@ ppp_receive_mp_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
         */
        if (seq_before(seq, ppp->nextseq)) {
                kfree_skb(skb);
-               ++ppp->stats.rx_dropped;
+               ++ppp->dev->stats.rx_dropped;
                ppp_receive_error(ppp);
                return;
        }
@@ -1928,7 +1919,7 @@ ppp_mp_reconstruct(struct ppp *ppp)
                /* Got a complete packet yet? */
                if (lost == 0 && (p->BEbits & E) && (head->BEbits & B)) {
                        if (len > ppp->mrru + 2) {
-                               ++ppp->stats.rx_length_errors;
+                               ++ppp->dev->stats.rx_length_errors;
                                printk(KERN_DEBUG "PPP: reconstructed packet"
                                       " is too long (%d)\n", len);
                        } else if (p == head) {
@@ -1937,7 +1928,7 @@ ppp_mp_reconstruct(struct ppp *ppp)
                                skb = skb_get(p);
                                break;
                        } else if ((skb = dev_alloc_skb(len)) == NULL) {
-                               ++ppp->stats.rx_missed_errors;
+                               ++ppp->dev->stats.rx_missed_errors;
                                printk(KERN_DEBUG "PPP: no memory for "
                                       "reconstructed packet");
                        } else {
@@ -1966,7 +1957,7 @@ ppp_mp_reconstruct(struct ppp *ppp)
                        if (ppp->debug & 1)
                                printk(KERN_DEBUG "  missed pkts %u..%u\n",
                                       ppp->nextseq, head->sequence-1);
-                       ++ppp->stats.rx_dropped;
+                       ++ppp->dev->stats.rx_dropped;
                        ppp_receive_error(ppp);
                }
 
@@ -2377,12 +2368,12 @@ ppp_get_stats(struct ppp *ppp, struct ppp_stats *st)
        struct slcompress *vj = ppp->vj;
 
        memset(st, 0, sizeof(*st));
-       st->p.ppp_ipackets = ppp->stats.rx_packets;
-       st->p.ppp_ierrors = ppp->stats.rx_errors;
-       st->p.ppp_ibytes = ppp->stats.rx_bytes;
-       st->p.ppp_opackets = ppp->stats.tx_packets;
-       st->p.ppp_oerrors = ppp->stats.tx_errors;
-       st->p.ppp_obytes = ppp->stats.tx_bytes;
+       st->p.ppp_ipackets = ppp->dev->stats.rx_packets;
+       st->p.ppp_ierrors = ppp->dev->stats.rx_errors;
+       st->p.ppp_ibytes = ppp->dev->stats.rx_bytes;
+       st->p.ppp_opackets = ppp->dev->stats.tx_packets;
+       st->p.ppp_oerrors = ppp->dev->stats.tx_errors;
+       st->p.ppp_obytes = ppp->dev->stats.tx_bytes;
        if (!vj)
                return;
        st->vj.vjs_packets = vj->sls_o_compressed + vj->sls_o_uncompressed;
@@ -2436,7 +2427,6 @@ ppp_create_interface(int unit, int *retp)
        dev->priv = ppp;
 
        dev->hard_start_xmit = ppp_start_xmit;
-       dev->get_stats = ppp_net_stats;
        dev->do_ioctl = ppp_net_ioctl;
 
        ret = -EEXIST;
index d91856b19f6fdaff4322576af492d107c2c8e8aa..0ce07a339c7eee77a209fc365e664976ed4a6b57 100644 (file)
@@ -668,16 +668,23 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
                break;
 
        case TUNSETLINK:
+       {
+               int ret;
+
                /* Only allow setting the type when the interface is down */
+               rtnl_lock();
                if (tun->dev->flags & IFF_UP) {
                        DBG(KERN_INFO "%s: Linktype set failed because interface is up\n",
                                tun->dev->name);
-                       return -EBUSY;
+                       ret = -EBUSY;
                } else {
                        tun->dev->type = (int) arg;
                        DBG(KERN_INFO "%s: linktype set to %d\n", tun->dev->name, tun->dev->type);
+                       ret = 0;
                }
-               break;
+               rtnl_unlock();
+               return ret;
+       }
 
 #ifdef TUN_DEBUG
        case TUNSETDEBUG:
@@ -734,7 +741,12 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
        case SIOCADDMULTI:
                /** Add the specified group to the character device's multicast filter
                 * list. */
+               rtnl_lock();
+               netif_tx_lock_bh(tun->dev);
                add_multi(tun->chr_filter, ifr.ifr_hwaddr.sa_data);
+               netif_tx_unlock_bh(tun->dev);
+               rtnl_unlock();
+
                DBG(KERN_DEBUG "%s: add multi: %s\n",
                    tun->dev->name, print_mac(mac, ifr.ifr_hwaddr.sa_data));
                return 0;
@@ -742,7 +754,12 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
        case SIOCDELMULTI:
                /** Remove the specified group from the character device's multicast
                 * filter list. */
+               rtnl_lock();
+               netif_tx_lock_bh(tun->dev);
                del_multi(tun->chr_filter, ifr.ifr_hwaddr.sa_data);
+               netif_tx_unlock_bh(tun->dev);
+               rtnl_unlock();
+
                DBG(KERN_DEBUG "%s: del multi: %s\n",
                    tun->dev->name, print_mac(mac, ifr.ifr_hwaddr.sa_data));
                return 0;
index 70092191fc533079f78c3353f74d9dd20a056975..c2642bc1d49bdbb02d09f1424939ab6439926508 100644 (file)
@@ -56,8 +56,7 @@ obj-$(CONFIG_RTL8187) += rtl8187.o
 
 obj-$(CONFIG_ADM8211)  += adm8211.o
 
-obj-$(CONFIG_IWL3945)  += iwlwifi/
-obj-$(CONFIG_IWL4965)  += iwlwifi/
+obj-$(CONFIG_IWLCORE)  += iwlwifi/
 obj-$(CONFIG_RT2X00)   += rt2x00/
 
 obj-$(CONFIG_P54_COMMON)       += p54/
index 87e782291a0180536cef3329de66cfc5ad32dec6..5fb1ae6ad3e23edb6357a2da5a8610539e8e4a10 100644 (file)
@@ -304,14 +304,20 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
                ah->ah_radio = AR5K_RF2413;
                ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A;
        } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC2) {
-
                ah->ah_radio = AR5K_RF5413;
+               ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A;
+       } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5133) {
 
-               if (ah->ah_mac_srev <= AR5K_SREV_VER_AR5424 &&
-                       ah->ah_mac_srev >= AR5K_SREV_VER_AR2424)
+               /* AR5424 */
+               if (srev >= AR5K_SREV_VER_AR5424) {
+                       ah->ah_radio = AR5K_RF5413;
                        ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5424;
-               else
+               /* AR2424 */
+               } else {
+                       ah->ah_radio = AR5K_RF2413; /* For testing */
                        ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A;
+               }
+
        /*
         * Register returns 0x4 for radio revision
         * so ath5k_hw_radio_revision doesn't parse the value
index 21c886a9a1d96a85b79e30890379d67c6c5db8eb..6dcbb3c87e7207a01cf64f2269f3cea1438cfe04 100644 (file)
@@ -980,6 +980,42 @@ void b43_dma_free(struct b43_wldev *dev)
        destroy_ring(dma, tx_ring_mcast);
 }
 
+static int b43_dma_set_mask(struct b43_wldev *dev, u64 mask)
+{
+       u64 orig_mask = mask;
+       bool fallback = 0;
+       int err;
+
+       /* Try to set the DMA mask. If it fails, try falling back to a
+        * lower mask, as we can always also support a lower one. */
+       while (1) {
+               err = ssb_dma_set_mask(dev->dev, mask);
+               if (!err)
+                       break;
+               if (mask == DMA_64BIT_MASK) {
+                       mask = DMA_32BIT_MASK;
+                       fallback = 1;
+                       continue;
+               }
+               if (mask == DMA_32BIT_MASK) {
+                       mask = DMA_30BIT_MASK;
+                       fallback = 1;
+                       continue;
+               }
+               b43err(dev->wl, "The machine/kernel does not support "
+                      "the required %u-bit DMA mask\n",
+                      (unsigned int)dma_mask_to_engine_type(orig_mask));
+               return -EOPNOTSUPP;
+       }
+       if (fallback) {
+               b43info(dev->wl, "DMA mask fallback from %u-bit to %u-bit\n",
+                       (unsigned int)dma_mask_to_engine_type(orig_mask),
+                       (unsigned int)dma_mask_to_engine_type(mask));
+       }
+
+       return 0;
+}
+
 int b43_dma_init(struct b43_wldev *dev)
 {
        struct b43_dma *dma = &dev->dma;
@@ -989,14 +1025,9 @@ int b43_dma_init(struct b43_wldev *dev)
 
        dmamask = supported_dma_mask(dev);
        type = dma_mask_to_engine_type(dmamask);
-       err = ssb_dma_set_mask(dev->dev, dmamask);
-       if (err) {
-               b43err(dev->wl, "The machine/kernel does not support "
-                      "the required DMA mask (0x%08X%08X)\n",
-                      (unsigned int)((dmamask & 0xFFFFFFFF00000000ULL) >> 32),
-                      (unsigned int)(dmamask & 0x00000000FFFFFFFFULL));
-               return -EOPNOTSUPP;
-       }
+       err = b43_dma_set_mask(dev, dmamask);
+       if (err)
+               return err;
 
        err = -ENOMEM;
        /* setup TX DMA channels. */
index 943cc851c5043152d8ff521e18cc5a792da5fcad..4bf8a99099fee7713f357b5f3f450148441c19a6 100644 (file)
@@ -84,6 +84,10 @@ int b43_modparam_qos = 1;
 module_param_named(qos, b43_modparam_qos, int, 0444);
 MODULE_PARM_DESC(qos, "Enable QOS support (default on)");
 
+static int modparam_btcoex = 1;
+module_param_named(btcoex, modparam_btcoex, int, 0444);
+MODULE_PARM_DESC(btcoex, "Enable Bluetooth coexistance (default on)");
+
 
 static const struct ssb_device_id b43_ssb_tbl[] = {
        SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 5),
@@ -3706,8 +3710,10 @@ static void setup_struct_wldev_for_init(struct b43_wldev *dev)
 static void b43_bluetooth_coext_enable(struct b43_wldev *dev)
 {
        struct ssb_sprom *sprom = &dev->dev->bus->sprom;
-       u32 hf;
+       u64 hf;
 
+       if (!modparam_btcoex)
+               return;
        if (!(sprom->boardflags_lo & B43_BFL_BTCOEXIST))
                return;
        if (dev->phy.type != B43_PHYTYPE_B && !dev->phy.gmode)
@@ -3719,11 +3725,13 @@ static void b43_bluetooth_coext_enable(struct b43_wldev *dev)
        else
                hf |= B43_HF_BTCOEX;
        b43_hf_write(dev, hf);
-       //TODO
 }
 
 static void b43_bluetooth_coext_disable(struct b43_wldev *dev)
-{                              //TODO
+{
+       if (!modparam_btcoex)
+               return;
+       //TODO
 }
 
 static void b43_imcfglo_timeouts_workaround(struct b43_wldev *dev)
@@ -3852,7 +3860,8 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
        struct ssb_sprom *sprom = &bus->sprom;
        struct b43_phy *phy = &dev->phy;
        int err;
-       u32 hf, tmp;
+       u64 hf;
+       u32 tmp;
 
        B43_WARN_ON(b43_status(dev) != B43_STAT_UNINIT);
 
@@ -4414,8 +4423,16 @@ static int b43_one_core_attach(struct ssb_device *dev, struct b43_wl *wl)
        return err;
 }
 
+#define IS_PDEV(pdev, _vendor, _device, _subvendor, _subdevice)                ( \
+       (pdev->vendor == PCI_VENDOR_ID_##_vendor) &&                    \
+       (pdev->device == _device) &&                                    \
+       (pdev->subsystem_vendor == PCI_VENDOR_ID_##_subvendor) &&       \
+       (pdev->subsystem_device == _subdevice)                          )
+
 static void b43_sprom_fixup(struct ssb_bus *bus)
 {
+       struct pci_dev *pdev;
+
        /* boardflags workarounds */
        if (bus->boardinfo.vendor == SSB_BOARDVENDOR_DELL &&
            bus->chip_id == 0x4301 && bus->boardinfo.rev == 0x74)
@@ -4423,6 +4440,13 @@ static void b43_sprom_fixup(struct ssb_bus *bus)
        if (bus->boardinfo.vendor == PCI_VENDOR_ID_APPLE &&
            bus->boardinfo.type == 0x4E && bus->boardinfo.rev > 0x40)
                bus->sprom.boardflags_lo |= B43_BFL_PACTRL;
+       if (bus->bustype == SSB_BUSTYPE_PCI) {
+               pdev = bus->host_pci;
+               if (IS_PDEV(pdev, BROADCOM, 0x4318, ASUSTEK, 0x100F) ||
+                   IS_PDEV(pdev, BROADCOM, 0x4320, LINKSYS, 0x0015) ||
+                   IS_PDEV(pdev, BROADCOM, 0x4320, LINKSYS, 0x0013))
+                       bus->sprom.boardflags_lo &= ~B43_BFL_BTCOEXIST;
+       }
 }
 
 static void b43_wireless_exit(struct ssb_device *dev, struct b43_wl *wl)
index 575c5436ebdfdcdcfcd8ab56a8671c1da3dd0a9a..de024dc03718571296577a14bac34467b3ffd0f8 100644 (file)
@@ -2043,7 +2043,7 @@ int b43_phy_init(struct b43_wldev *dev)
 void b43_set_rx_antenna(struct b43_wldev *dev, int antenna)
 {
        struct b43_phy *phy = &dev->phy;
-       u32 hf;
+       u64 hf;
        u16 tmp;
        int autodiv = 0;
 
index 1a5678fe4224de0975592a9edc0f71a75a42fbf5..a1a0b3c581f1d469abbcc913b22f9a02b2be2f25 100644 (file)
@@ -6907,7 +6907,6 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
 
        if (priv->vif != vif) {
                IWL_DEBUG_MAC80211("leave - priv->vif != vif\n");
-               mutex_unlock(&priv->mutex);
                return 0;
        }
 
index d7e2358a213a1a32d5b7dadd084ae34daeed200a..d0bbcaaeb94c8a8d30a42e5f6bc5c488c861e6ee 100644 (file)
@@ -6473,7 +6473,6 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw,
 
        if (priv->vif != vif) {
                IWL_DEBUG_MAC80211("leave - priv->vif != vif\n");
-               mutex_unlock(&priv->mutex);
                return 0;
        }
 
index e5b3c282009ce8c7824efbb102ae398cfce97ecc..5b375b289036fe8d5f9ed2f5dd8fd73325831725 100644 (file)
@@ -1186,7 +1186,7 @@ prism54_get_encode(struct net_device *ndev, struct iw_request_info *info,
        rvalue |= mgt_get_request(priv, DOT11_OID_DEFKEYID, 0, NULL, &r);
        devindex = r.u;
        /* Now get the key, return it */
-       if ((index < 0) || (index > 3))
+       if (index == -1 || index > 3)
                /* no index provided, use the current one */
                index = devindex;
        rvalue |= mgt_get_request(priv, DOT11_OID_DEFKEYX, index, NULL, &r);
index 977751f372ffc9d8578b5692feed51cc455d5037..d0b1fb15c7091f8b3334c94f240fe6fa445e6c17 100644 (file)
@@ -2402,7 +2402,6 @@ static int bcm4320_early_init(struct usbnet *dev)
        priv->param_power_output = modparam_power_output;
        priv->param_roamtrigger  = modparam_roamtrigger;
        priv->param_roamdelta    = modparam_roamdelta;
-       priv->param_workaround_interval = modparam_workaround_interval;
 
        priv->param_country[0] = toupper(priv->param_country[0]);
        priv->param_country[1] = toupper(priv->param_country[1]);
@@ -2425,8 +2424,10 @@ static int bcm4320_early_init(struct usbnet *dev)
        else if (priv->param_roamdelta > 2)
                priv->param_roamdelta = 2;
 
-       if (priv->param_workaround_interval < 0)
+       if (modparam_workaround_interval < 0)
                priv->param_workaround_interval = 500;
+       else
+               priv->param_workaround_interval = modparam_workaround_interval;
 
        rndis_set_config_parameter_str(dev, "Country", priv->param_country);
        rndis_set_config_parameter_str(dev, "FrameBursting",
index 301c68fab03befa1c10d60d8fe6d9d65fcd9583d..1fd8bb7657024c2629858940fc050a35fc3acab7 100644 (file)
@@ -1905,32 +1905,31 @@ get_valid_domain_for_dev(struct pci_dev *pdev)
        return domain;
 }
 
-static dma_addr_t intel_map_single(struct device *hwdev, void *addr,
-       size_t size, int dir)
+static dma_addr_t
+intel_map_single(struct device *hwdev, phys_addr_t paddr, size_t size, int dir)
 {
        struct pci_dev *pdev = to_pci_dev(hwdev);
-       int ret;
        struct dmar_domain *domain;
-       unsigned long start_addr;
+       unsigned long start_paddr;
        struct iova *iova;
        int prot = 0;
+       int ret;
 
        BUG_ON(dir == DMA_NONE);
        if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO)
-               return virt_to_bus(addr);
+               return paddr;
 
        domain = get_valid_domain_for_dev(pdev);
        if (!domain)
                return 0;
 
-       addr = (void *)virt_to_phys(addr);
-       size = aligned_size((u64)addr, size);
+       size = aligned_size((u64)paddr, size);
 
        iova = __intel_alloc_iova(hwdev, domain, size);
        if (!iova)
                goto error;
 
-       start_addr = iova->pfn_lo << PAGE_SHIFT_4K;
+       start_paddr = iova->pfn_lo << PAGE_SHIFT_4K;
 
        /*
         * Check if DMAR supports zero-length reads on write only
@@ -1942,33 +1941,33 @@ static dma_addr_t intel_map_single(struct device *hwdev, void *addr,
        if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
                prot |= DMA_PTE_WRITE;
        /*
-        * addr - (addr + size) might be partial page, we should map the whole
+        * paddr - (paddr + size) might be partial page, we should map the whole
         * page.  Note: if two part of one page are separately mapped, we
-        * might have two guest_addr mapping to the same host addr, but this
+        * might have two guest_addr mapping to the same host paddr, but this
         * is not a big problem
         */
-       ret = domain_page_mapping(domain, start_addr,
-               ((u64)addr) & PAGE_MASK_4K, size, prot);
+       ret = domain_page_mapping(domain, start_paddr,
+               ((u64)paddr) & PAGE_MASK_4K, size, prot);
        if (ret)
                goto error;
 
        pr_debug("Device %s request: %lx@%llx mapping: %lx@%llx, dir %d\n",
-               pci_name(pdev), size, (u64)addr,
-               size, (u64)start_addr, dir);
+               pci_name(pdev), size, (u64)paddr,
+               size, (u64)start_paddr, dir);
 
        /* it's a non-present to present mapping */
        ret = iommu_flush_iotlb_psi(domain->iommu, domain->id,
-                       start_addr, size >> PAGE_SHIFT_4K, 1);
+                       start_paddr, size >> PAGE_SHIFT_4K, 1);
        if (ret)
                iommu_flush_write_buffer(domain->iommu);
 
-       return (start_addr + ((u64)addr & (~PAGE_MASK_4K)));
+       return (start_paddr + ((u64)paddr & (~PAGE_MASK_4K)));
 
 error:
        if (iova)
                __free_iova(&domain->iovad, iova);
        printk(KERN_ERR"Device %s request: %lx@%llx dir %d --- failed\n",
-               pci_name(pdev), size, (u64)addr, dir);
+               pci_name(pdev), size, (u64)paddr, dir);
        return 0;
 }
 
@@ -2082,7 +2081,7 @@ static void * intel_alloc_coherent(struct device *hwdev, size_t size,
                return NULL;
        memset(vaddr, 0, size);
 
-       *dma_handle = intel_map_single(hwdev, vaddr, size, DMA_BIDIRECTIONAL);
+       *dma_handle = intel_map_single(hwdev, virt_to_bus(vaddr), size, DMA_BIDIRECTIONAL);
        if (*dma_handle)
                return vaddr;
        free_pages((unsigned long)vaddr, order);
index ed8c06904807723540365699e892cacf68cc7a71..8d8852651fd2a7cc705877d661c1bcca90d2d545 100644 (file)
@@ -200,7 +200,6 @@ config PCMCIA_AU1X00
 config PCMCIA_SA1100
        tristate "SA1100 support"
        depends on ARM && ARCH_SA1100 && PCMCIA
-       depends on ARCH_LUBBOCK || MACH_MAINSTONE || PXA_SHARPSL || MACH_ARMCORE
        help
          Say Y here to include support for SA11x0-based PCMCIA or CF
          sockets, found on HP iPAQs, Yopy, and other StrongARM(R)/
@@ -221,6 +220,7 @@ config PCMCIA_SA1111
 config PCMCIA_PXA2XX
        tristate "PXA2xx support"
        depends on ARM && ARCH_PXA && PCMCIA
+       depends on ARCH_LUBBOCK || MACH_MAINSTONE || PXA_SHARPSL || MACH_ARMCORE
        help
          Say Y here to include support for the PXA2xx PCMCIA controller
 
index 46bb47f37b9a276089332cf23dbb5462eea8c47e..5f55534a290ba8d00000c694cef8c28496347090 100644 (file)
@@ -151,7 +151,8 @@ void kgdb_put_debug_char(int chr)
 {
        struct bfin_serial_port *uart;
        
-       if (CONFIG_KGDB_UART_PORT<0 || CONFIG_KGDB_UART_PORT>=NR_PORTS)
+       if (CONFIG_KGDB_UART_PORT < 0
+               || CONFIG_KGDB_UART_PORT >= BFIN_UART_NR_PORTS)
                uart = &bfin_serial_ports[0];
        else
                uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT];
@@ -173,7 +174,8 @@ int kgdb_get_debug_char(void)
        struct bfin_serial_port *uart;
        unsigned char chr;
 
-       if (CONFIG_KGDB_UART_PORT<0 || CONFIG_KGDB_UART_PORT>=NR_PORTS)
+       if (CONFIG_KGDB_UART_PORT < 0
+               || CONFIG_KGDB_UART_PORT >= BFIN_UART_NR_PORTS)
                uart = &bfin_serial_ports[0];
        else
                uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT];
@@ -192,7 +194,7 @@ int kgdb_get_debug_char(void)
 }
 #endif
 
-#if ANOMALY_05000230 && defined(CONFIG_SERIAL_BFIN_PIO)
+#if ANOMALY_05000363 && defined(CONFIG_SERIAL_BFIN_PIO)
 # define UART_GET_ANOMALY_THRESHOLD(uart)    ((uart)->anomaly_threshold)
 # define UART_SET_ANOMALY_THRESHOLD(uart, v) ((uart)->anomaly_threshold = (v))
 #else
@@ -237,7 +239,7 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart)
        }
 #endif
 
-       if (ANOMALY_05000230) {
+       if (ANOMALY_05000363) {
                /* The BF533 (and BF561) family of processors have a nice anomaly
                 * where they continuously generate characters for a "single" break.
                 * We have to basically ignore this flood until the "next" valid
@@ -249,9 +251,6 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart)
                 * timeout was picked as it must absolutely be larger than 1
                 * character time +/- some percent.  So 1.5 sounds good.  All other
                 * Blackfin families operate properly.  Woo.
-                * Note: While Anomaly 05000230 does not directly address this,
-                *       the changes that went in for it also fixed this issue.
-                *       That anomaly was fixed in 0.5+ silicon.  I like bunnies.
                 */
                if (anomaly_start.tv_sec) {
                        struct timeval curr;
@@ -285,7 +284,7 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart)
        }
 
        if (status & BI) {
-               if (ANOMALY_05000230)
+               if (ANOMALY_05000363)
                        if (bfin_revid() < 5)
                                do_gettimeofday(&anomaly_start);
                uart->port.icount.brk++;
@@ -507,8 +506,7 @@ void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart)
                uart->rx_dma_buf.tail = uart->rx_dma_buf.head;
        }
 
-       uart->rx_dma_timer.expires = jiffies + DMA_RX_FLUSH_JIFFIES;
-       add_timer(&(uart->rx_dma_timer));
+       mod_timer(&(uart->rx_dma_timer), jiffies + DMA_RX_FLUSH_JIFFIES);
 }
 
 static irqreturn_t bfin_serial_dma_tx_int(int irq, void *dev_id)
@@ -551,9 +549,7 @@ static irqreturn_t bfin_serial_dma_rx_int(int irq, void *dev_id)
        clear_dma_irqstat(uart->rx_dma_channel);
        spin_unlock(&uart->port.lock);
 
-       del_timer(&(uart->rx_dma_timer));
-       uart->rx_dma_timer.expires = jiffies;
-       add_timer(&(uart->rx_dma_timer));
+       mod_timer(&(uart->rx_dma_timer), jiffies);
 
        return IRQ_HANDLED;
 }
@@ -749,7 +745,7 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios,
        struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
        unsigned long flags;
        unsigned int baud, quot;
-       unsigned short val, ier, lsr, lcr = 0;
+       unsigned short val, ier, lcr = 0;
 
        switch (termios->c_cflag & CSIZE) {
        case CS8:
@@ -806,10 +802,6 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios,
 
        UART_SET_ANOMALY_THRESHOLD(uart, USEC_PER_SEC / baud * 15);
 
-       do {
-               lsr = UART_GET_LSR(uart);
-       } while (!(lsr & TEMT));
-
        /* Disable UART */
        ier = UART_GET_IER(uart);
 #ifdef CONFIG_BF54x
@@ -900,6 +892,31 @@ bfin_serial_verify_port(struct uart_port *port, struct serial_struct *ser)
        return 0;
 }
 
+/*
+ * Enable the IrDA function if tty->ldisc.num is N_IRDA.
+ * In other cases, disable IrDA function.
+ */
+static void bfin_set_ldisc(struct tty_struct *tty)
+{
+       int line = tty->index;
+       unsigned short val;
+
+       if (line >= tty->driver->num)
+               return;
+
+       switch (tty->ldisc.num) {
+       case N_IRDA:
+               val = UART_GET_GCTL(&bfin_serial_ports[line]);
+               val |= (IREN | RPOLC);
+               UART_PUT_GCTL(&bfin_serial_ports[line], val);
+               break;
+       default:
+               val = UART_GET_GCTL(&bfin_serial_ports[line]);
+               val &= ~(IREN | RPOLC);
+               UART_PUT_GCTL(&bfin_serial_ports[line], val);
+       }
+}
+
 static struct uart_ops bfin_serial_pops = {
        .tx_empty       = bfin_serial_tx_empty,
        .set_mctrl      = bfin_serial_set_mctrl,
@@ -1172,7 +1189,7 @@ static struct uart_driver bfin_serial_reg = {
        .dev_name               = BFIN_SERIAL_NAME,
        .major                  = BFIN_SERIAL_MAJOR,
        .minor                  = BFIN_SERIAL_MINOR,
-       .nr                     = NR_PORTS,
+       .nr                     = BFIN_UART_NR_PORTS,
        .cons                   = BFIN_SERIAL_CONSOLE,
 };
 
@@ -1261,6 +1278,7 @@ static int __init bfin_serial_init(void)
 
        ret = uart_register_driver(&bfin_serial_reg);
        if (ret == 0) {
+               bfin_serial_reg.tty_driver->set_ldisc = bfin_set_ldisc;
                ret = platform_driver_register(&bfin_serial_driver);
                if (ret) {
                        pr_debug("uart register failed\n");
index cb2e405063794f97922aaa6f5eaf9e0d77a15302..3271379a36dbc8b8cf8daede92fad77a5680e4a3 100644 (file)
@@ -1015,6 +1015,7 @@ static struct uart_ops sunzilog_pops = {
        .verify_port    =       sunzilog_verify_port,
 };
 
+static int uart_chip_count;
 static struct uart_sunzilog_port *sunzilog_port_table;
 static struct zilog_layout __iomem **sunzilog_chip_regs;
 
@@ -1350,16 +1351,22 @@ static int zilog_irq = -1;
 
 static int __devinit zs_probe(struct of_device *op, const struct of_device_id *match)
 {
-       static int inst;
+       static int kbm_inst, uart_inst;
+       int inst;
        struct uart_sunzilog_port *up;
        struct zilog_layout __iomem *rp;
-       int keyboard_mouse;
+       int keyboard_mouse = 0;
        int err;
 
-       keyboard_mouse = 0;
        if (of_find_property(op->node, "keyboard", NULL))
                keyboard_mouse = 1;
 
+       /* uarts must come before keyboards/mice */
+       if (keyboard_mouse)
+               inst = uart_chip_count + kbm_inst;
+       else
+               inst = uart_inst;
+
        sunzilog_chip_regs[inst] = of_ioremap(&op->resource[0], 0,
                                              sizeof(struct zilog_layout),
                                              "zs");
@@ -1427,6 +1434,7 @@ static int __devinit zs_probe(struct of_device *op, const struct of_device_id *m
                                   rp, sizeof(struct zilog_layout));
                        return err;
                }
+               uart_inst++;
        } else {
                printk(KERN_INFO "%s: Keyboard at MMIO 0x%llx (irq = %d) "
                       "is a %s\n",
@@ -1438,12 +1446,11 @@ static int __devinit zs_probe(struct of_device *op, const struct of_device_id *m
                       op->dev.bus_id,
                       (unsigned long long) up[1].port.mapbase,
                       op->irqs[0], sunzilog_type(&up[1].port));
+               kbm_inst++;
        }
 
        dev_set_drvdata(&op->dev, &up[0]);
 
-       inst++;
-
        return 0;
 }
 
@@ -1491,28 +1498,25 @@ static struct of_platform_driver zs_driver = {
 static int __init sunzilog_init(void)
 {
        struct device_node *dp;
-       int err, uart_count;
-       int num_keybms;
+       int err;
+       int num_keybms = 0;
        int num_sunzilog = 0;
 
-       num_keybms = 0;
        for_each_node_by_name(dp, "zs") {
                num_sunzilog++;
                if (of_find_property(dp, "keyboard", NULL))
                        num_keybms++;
        }
 
-       uart_count = 0;
        if (num_sunzilog) {
-               int uart_count;
-
                err = sunzilog_alloc_tables(num_sunzilog);
                if (err)
                        goto out;
 
-               uart_count = (num_sunzilog * 2) - (2 * num_keybms);
+               uart_chip_count = num_sunzilog - num_keybms;
 
-               err = sunserial_register_minors(&sunzilog_reg, uart_count);
+               err = sunserial_register_minors(&sunzilog_reg,
+                                               uart_chip_count * 2);
                if (err)
                        goto out_free_tables;
        }
index 904b1a8d088590bfc51d6d10935d35ce553b1a1c..57c4ccfab1ee79f28790c3fe7b8a48c1d0baa78e 100644 (file)
@@ -484,6 +484,11 @@ static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
                        goto unsupported;
        }
 
+       if (out->boardflags_lo == 0xFFFF)
+               out->boardflags_lo = 0;  /* per specs */
+       if (out->boardflags_hi == 0xFFFF)
+               out->boardflags_hi = 0;  /* per specs */
+
        return 0;
 unsupported:
        ssb_printk(KERN_WARNING PFX "Unsupported SPROM revision %d "
index 8b18a875867751cc9a95bdf85a9f6f9935b6b68d..2e43d46f65d6370c40c4a0ac33f36798fad909fb 100644 (file)
@@ -411,7 +411,7 @@ config JFS_STATISTICS
          to be made available to the user in the /proc/fs/jfs/ directory.
 
 config FS_POSIX_ACL
-# Posix ACL utility routines (for now, only ext2/ext3/jfs/reiserfs)
+# Posix ACL utility routines (for now, only ext2/ext3/jfs/reiserfs/nfs4)
 #
 # NOTE: you can implement Posix ACLs without these helpers (XFS does).
 #      Never use this symbol for ifdefs.
@@ -1664,105 +1664,86 @@ config NFS_V4
 
          If unsure, say N.
 
-config NFS_DIRECTIO
-       bool "Allow direct I/O on NFS files"
-       depends on NFS_FS
-       help
-         This option enables applications to perform uncached I/O on files
-         in NFS file systems using the O_DIRECT open() flag.  When O_DIRECT
-         is set for a file, its data is not cached in the system's page
-         cache.  Data is moved to and from user-level application buffers
-         directly.  Unlike local disk-based file systems, NFS O_DIRECT has
-         no alignment restrictions.
-
-         Unless your program is designed to use O_DIRECT properly, you are
-         much better off allowing the NFS client to manage data caching for
-         you.  Misusing O_DIRECT can cause poor server performance or network
-         storms.  This kernel build option defaults OFF to avoid exposing
-         system administrators unwittingly to a potentially hazardous
-         feature.
-
-         For more details on NFS O_DIRECT, see fs/nfs/direct.c.
-
-         If unsure, say N.  This reduces the size of the NFS client, and
-         causes open() to return EINVAL if a file residing in NFS is
-         opened with the O_DIRECT flag.
-
 config NFSD
        tristate "NFS server support"
        depends on INET
        select LOCKD
        select SUNRPC
        select EXPORTFS
-       select NFSD_V2_ACL if NFSD_V3_ACL
        select NFS_ACL_SUPPORT if NFSD_V2_ACL
-       select NFSD_TCP if NFSD_V4
-       select CRYPTO_MD5 if NFSD_V4
-       select CRYPTO if NFSD_V4
-       select FS_POSIX_ACL if NFSD_V4
-       select PROC_FS if NFSD_V4
-       select PROC_FS if SUNRPC_GSS
-       help
-         If you want your Linux box to act as an NFS *server*, so that other
-         computers on your local network which support NFS can access certain
-         directories on your box transparently, you have two options: you can
-         use the self-contained user space program nfsd, in which case you
-         should say N here, or you can say Y and use the kernel based NFS
-         server. The advantage of the kernel based solution is that it is
-         faster.
-
-         In either case, you will need support software; the respective
-         locations are given in the file <file:Documentation/Changes> in the
-         NFS section.
-
-         If you say Y here, you will get support for version 2 of the NFS
-         protocol (NFSv2). If you also want NFSv3, say Y to the next question
-         as well.
-
-         Please read the NFS-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         To compile the NFS server support as a module, choose M here: the
-         module will be called nfsd.  If unsure, say N.
+       help
+         Choose Y here if you want to allow other computers to access
+         files residing on this system using Sun's Network File System
+         protocol.  To compile the NFS server support as a module,
+         choose M here: the module will be called nfsd.
+
+         You may choose to use a user-space NFS server instead, in which
+         case you can choose N here.
+
+         To export local file systems using NFS, you also need to install
+         user space programs which can be found in the Linux nfs-utils
+         package, available from http://linux-nfs.org/.  More detail about
+         the Linux NFS server implementation is available via the
+         exports(5) man page.
+
+         Below you can choose which versions of the NFS protocol are
+         available to clients mounting the NFS server on this system.
+         Support for NFS version 2 (RFC 1094) is always available when
+         CONFIG_NFSD is selected.
+
+         If unsure, say N.
 
 config NFSD_V2_ACL
        bool
        depends on NFSD
 
 config NFSD_V3
-       bool "Provide NFSv3 server support"
+       bool "NFS server support for NFS version 3"
        depends on NFSD
        help
-         If you would like to include the NFSv3 server as well as the NFSv2
-         server, say Y here.  If unsure, say Y.
+         This option enables support in your system's NFS server for
+         version 3 of the NFS protocol (RFC 1813).
+
+         If unsure, say Y.
 
 config NFSD_V3_ACL
-       bool "Provide server support for the NFSv3 ACL protocol extension"
+       bool "NFS server support for the NFSv3 ACL protocol extension"
        depends on NFSD_V3
+       select NFSD_V2_ACL
        help
-         Implement the NFSv3 ACL protocol extension for manipulating POSIX
-         Access Control Lists on exported file systems. NFS clients should
-         be compiled with the NFSv3 ACL protocol extension; see the
-         CONFIG_NFS_V3_ACL option.  If unsure, say N.
+         Solaris NFS servers support an auxiliary NFSv3 ACL protocol that
+         never became an official part of the NFS version 3 protocol.
+         This protocol extension allows applications on NFS clients to
+         manipulate POSIX Access Control Lists on files residing on NFS
+         servers.  NFS servers enforce POSIX ACLs on local files whether
+         this protocol is available or not.
+
+         This option enables support in your system's NFS server for the
+         NFSv3 ACL protocol extension allowing NFS clients to manipulate
+         POSIX ACLs on files exported by your system's NFS server.  NFS
+         clients which support the Solaris NFSv3 ACL protocol can then
+         access and modify ACLs on your NFS server.
+
+         To store ACLs on your NFS server, you also need to enable ACL-
+         related CONFIG options for your local file systems of choice.
+
+         If unsure, say N.
 
 config NFSD_V4
-       bool "Provide NFSv4 server support (EXPERIMENTAL)"
-       depends on NFSD && NFSD_V3 && EXPERIMENTAL
+       bool "NFS server support for NFS version 4 (EXPERIMENTAL)"
+       depends on NFSD && PROC_FS && EXPERIMENTAL
+       select NFSD_V3
+       select FS_POSIX_ACL
        select RPCSEC_GSS_KRB5
        help
-         If you would like to include the NFSv4 server as well as the NFSv2
-         and NFSv3 servers, say Y here.  This feature is experimental, and
-         should only be used if you are interested in helping to test NFSv4.
-         If unsure, say N.
+         This option enables support in your system's NFS server for
+         version 4 of the NFS protocol (RFC 3530).
 
-config NFSD_TCP
-       bool "Provide NFS server over TCP support"
-       depends on NFSD
-       default y
-       help
-         If you want your NFS server to support TCP connections, say Y here.
-         TCP connections usually perform better than the default UDP when
-         the network is lossy or congested.  If unsure, say Y.
+         To export files using NFSv4, you need to install additional user
+         space programs which can be found in the Linux nfs-utils package,
+         available from http://linux-nfs.org/.
+
+         If unsure, say N.
 
 config ROOT_NFS
        bool "Root file system on NFS"
@@ -1808,15 +1789,33 @@ config SUNRPC_XPRT_RDMA
        tristate
        depends on SUNRPC && INFINIBAND && EXPERIMENTAL
        default SUNRPC && INFINIBAND
+       help
+         This option enables an RPC client transport capability that
+         allows the NFS client to mount servers via an RDMA-enabled
+         transport.
+
+         To compile RPC client RDMA transport support as a module,
+         choose M here: the module will be called xprtrdma.
+
+         If unsure, say N.
 
 config SUNRPC_BIND34
        bool "Support for rpcbind versions 3 & 4 (EXPERIMENTAL)"
        depends on SUNRPC && EXPERIMENTAL
+       default n
        help
-         Provides kernel support for querying rpcbind servers via versions 3
-         and 4 of the rpcbind protocol.  The kernel automatically falls back
-         to version 2 if a remote rpcbind service does not support versions
-         3 or 4.
+         RPC requests over IPv6 networks require support for larger
+         addresses when performing an RPC bind.  Sun added support for
+         IPv6 addressing by creating two new versions of the rpcbind
+         protocol (RFC 1833).
+
+         This option enables support in the kernel RPC client for
+         querying rpcbind servers via versions 3 and 4 of the rpcbind
+         protocol.  The kernel automatically falls back to version 2
+         if a remote rpcbind service does not support versions 3 or 4.
+         By themselves, these new versions do not provide support for
+         RPC over IPv6, but the new protocol versions are necessary to
+         support it.
 
          If unsure, say N to get traditional behavior (version 2 rpcbind
          requests only).
@@ -1830,12 +1829,13 @@ config RPCSEC_GSS_KRB5
        select CRYPTO_DES
        select CRYPTO_CBC
        help
-         Provides for secure RPC calls by means of a gss-api
-         mechanism based on Kerberos V5. This is required for
-         NFSv4.
+         Choose Y here to enable Secure RPC using the Kerberos version 5
+         GSS-API mechanism (RFC 1964).
 
-         Note: Requires an auxiliary userspace daemon which may be found on
-               http://www.citi.umich.edu/projects/nfsv4/
+         Secure RPC calls with Kerberos require an auxiliary user-space
+         daemon which may be found in the Linux nfs-utils package
+         available from http://linux-nfs.org/.  In addition, user-space
+         Kerberos support should be installed.
 
          If unsure, say N.
 
@@ -1849,11 +1849,12 @@ config RPCSEC_GSS_SPKM3
        select CRYPTO_CAST5
        select CRYPTO_CBC
        help
-         Provides for secure RPC calls by means of a gss-api
-         mechanism based on the SPKM3 public-key mechanism.
+         Choose Y here to enable Secure RPC using the SPKM3 public key
+         GSS-API mechansim (RFC 2025).
 
-         Note: Requires an auxiliary userspace daemon which may be found on
-               http://www.citi.umich.edu/projects/nfsv4/
+         Secure RPC calls with SPKM3 require an auxiliary userspace
+         daemon which may be found in the Linux nfs-utils package
+         available from http://linux-nfs.org/.
 
          If unsure, say N.
 
index dbd91461853c97fc1c5c4538c53c6514570f85d4..05c9da6181c3793cd540c803053fc2bd21e08bbc 100644 (file)
@@ -8,7 +8,8 @@ of second share to disconnected server session (autoreconnect on this).
 Add ability to modify cifs acls for handling chmod (when mounted with
 cifsacl flag). Fix prefixpath path separator so we can handle mounts
 with prefixpaths longer than one directory (one path component) when
-mounted to Windows servers.
+mounted to Windows servers.  Fix slow file open when cifsacl
+enabled.
 
 Version 1.51
 ------------
index 50306229b0f9f822b4f4e6d53cca9b9a5986ec07..621aa1a85971394d37424e2a50c9cf71c9aa2146 100644 (file)
@@ -3,7 +3,14 @@ features such as hierarchical dfs like namespace, hardlinks, locking and more.
 It was designed to comply with the SNIA CIFS Technical Reference (which 
 supersedes the 1992 X/Open SMB Standard) as well as to perform best practice 
 practical interoperability with Windows 2000, Windows XP, Samba and equivalent 
-servers.  
+servers.  This code was developed in participation with the Protocol Freedom
+Information Foundation.
+
+Please see
+  http://protocolfreedom.org/ and
+  http://samba.org/samba/PFIF/
+for more details.
+
 
 For questions or bug reports please contact:
     sfrench@samba.org (sfrench@us.ibm.com) 
index 56c924033b78d73d382f1a391e00c4710bf3f01a..f53f41ff16653622755973ebf1b7880bf8a0ca09 100644 (file)
@@ -23,7 +23,7 @@
 #include "dns_resolve.h"
 #include "cifs_debug.h"
 
-LIST_HEAD(cifs_dfs_automount_list);
+static LIST_HEAD(cifs_dfs_automount_list);
 
 /*
  * DFS functions
index 1cb5b0a9f2aca95b8790a8b6be3fae90157f9e68..e99d4faf5f022e5c3315dbd38b63e12e85ccf0e7 100644 (file)
@@ -516,7 +516,7 @@ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len,
 
 /* Convert permission bits from mode to equivalent CIFS ACL */
 static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
-                               int acl_len, struct inode *inode, __u64 nmode)
+                               struct inode *inode, __u64 nmode)
 {
        int rc = 0;
        __u32 dacloffset;
@@ -692,14 +692,14 @@ void acl_to_uid_mode(struct inode *inode, const char *path, const __u16 *pfid)
 int mode_to_acl(struct inode *inode, const char *path, __u64 nmode)
 {
        int rc = 0;
-       __u32 acllen = 0;
+       __u32 secdesclen = 0;
        struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */
        struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
 
        cFYI(DBG2, ("set ACL from mode for %s", path));
 
        /* Get the security descriptor */
-       pntsd = get_cifs_acl(&acllen, inode, path, NULL);
+       pntsd = get_cifs_acl(&secdesclen, inode, path, NULL);
 
        /* Add three ACEs for owner, group, everyone getting rid of
           other ACEs as chmod disables ACEs and set the security descriptor */
@@ -709,20 +709,22 @@ int mode_to_acl(struct inode *inode, const char *path, __u64 nmode)
                   set security descriptor request security descriptor
                   parameters, and secuirty descriptor itself */
 
-               pnntsd = kmalloc(acllen, GFP_KERNEL);
+               secdesclen = secdesclen < DEFSECDESCLEN ?
+                                       DEFSECDESCLEN : secdesclen;
+               pnntsd = kmalloc(secdesclen, GFP_KERNEL);
                if (!pnntsd) {
                        cERROR(1, ("Unable to allocate security descriptor"));
                        kfree(pntsd);
                        return (-ENOMEM);
                }
 
-               rc = build_sec_desc(pntsd, pnntsd, acllen, inode, nmode);
+               rc = build_sec_desc(pntsd, pnntsd, inode, nmode);
 
                cFYI(DBG2, ("build_sec_desc rc: %d", rc));
 
                if (!rc) {
                        /* Set the security descriptor */
-                       rc = set_cifs_acl(pnntsd, acllen, inode, path);
+                       rc = set_cifs_acl(pnntsd, secdesclen, inode, path);
                        cFYI(DBG2, ("set_cifs_acl rc: %d", rc));
                }
 
index 93a7c3462ea27c7c3080bbc963f545ba51fe1286..6c8096cf51557764aa10af6c28d108d3e93ce6e7 100644 (file)
@@ -27,6 +27,7 @@
 #define NUM_SUBAUTHS 5 /* number of sub authority fields */
 #define NUM_WK_SIDS 7 /* number of well known sids */
 #define SIDNAMELENGTH 20 /* long enough for the ones we care about */
+#define DEFSECDESCLEN 192 /* sec desc len contaiting a dacl with three aces */
 
 #define READ_BIT        0x4
 #define WRITE_BIT       0x2
index 68978306c3cad4333e7db69aa19e5eb7d1e89dfe..e1dd9f32e1d7600610ed084fa44548f7d153acb5 100644 (file)
@@ -62,11 +62,9 @@ extern int cifs_setattr(struct dentry *, struct iattr *);
 
 extern const struct inode_operations cifs_file_inode_ops;
 extern const struct inode_operations cifs_symlink_inode_ops;
-extern struct list_head cifs_dfs_automount_list;
 extern struct inode_operations cifs_dfs_referral_inode_operations;
 
 
-
 /* Functions related to files and directories */
 extern const struct file_operations cifs_file_ops;
 extern const struct file_operations cifs_file_direct_ops; /* if directio mnt */
index 47f79504f57b35524b5e9a6629e75264a2047184..9f49c2f3582c03bfa6f217776548605370cd00a4 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *   fs/cifs/cifspdu.h
  *
- *   Copyright (c) International Business Machines  Corp., 2002,2007
+ *   Copyright (c) International Business Machines  Corp., 2002,2008
  *   Author(s): Steve French (sfrench@us.ibm.com)
  *
  *   This library is free software; you can redistribute it and/or modify
                                                   path names in response */
 #define SMBFLG2_KNOWS_EAS cpu_to_le16(2)
 #define SMBFLG2_SECURITY_SIGNATURE cpu_to_le16(4)
+#define SMBFLG2_COMPRESSED (8)
+#define SMBFLG2_SECURITY_SIGNATURE_REQUIRED (0x10)
 #define SMBFLG2_IS_LONG_NAME cpu_to_le16(0x40)
+#define SMBFLG2_REPARSE_PATH (0x400)
 #define SMBFLG2_EXT_SEC cpu_to_le16(0x800)
 #define SMBFLG2_DFS cpu_to_le16(0x1000)
 #define SMBFLG2_PAGING_IO cpu_to_le16(0x2000)
 #define FILE_SHARE_DELETE 0x00000004
 #define FILE_SHARE_ALL    0x00000007
 
-/* CreateDisposition flags */
+/* CreateDisposition flags, similar to CreateAction as well */
 #define FILE_SUPERSEDE    0x00000000
 #define FILE_OPEN         0x00000001
 #define FILE_CREATE       0x00000002
 #define CREATE_NOT_FILE                0x00000001      /* if set must not be file */
 #define CREATE_WRITE_THROUGH   0x00000002
 #define CREATE_SEQUENTIAL       0x00000004
-#define CREATE_SYNC_ALERT       0x00000010
-#define CREATE_ASYNC_ALERT      0x00000020
+#define CREATE_NO_BUFFER        0x00000008      /* should not buffer on srv */
+#define CREATE_SYNC_ALERT       0x00000010     /* MBZ */
+#define CREATE_ASYNC_ALERT      0x00000020     /* MBZ */
 #define CREATE_NOT_DIR         0x00000040    /* if set must not be directory */
+#define CREATE_TREE_CONNECTION  0x00000080     /* should be zero */
+#define CREATE_COMPLETE_IF_OPLK 0x00000100     /* should be zero */
 #define CREATE_NO_EA_KNOWLEDGE  0x00000200
-#define CREATE_EIGHT_DOT_THREE  0x00000400
+#define CREATE_EIGHT_DOT_THREE  0x00000400     /* doc says this is obsolete
+                                                open for recovery flag - should
+                                                be zero */
 #define CREATE_RANDOM_ACCESS   0x00000800
 #define CREATE_DELETE_ON_CLOSE 0x00001000
 #define CREATE_OPEN_BY_ID       0x00002000
+#define CREATE_OPEN_BACKUP_INTN 0x00004000
+#define CREATE_NO_COMPRESSION   0x00008000
+#define CREATE_RESERVE_OPFILTER 0x00100000     /* should be zero */
 #define OPEN_REPARSE_POINT     0x00200000
+#define OPEN_NO_RECALL          0x00400000
+#define OPEN_FREE_SPACE_QUERY   0x00800000     /* should be zero */
 #define CREATE_OPTIONS_MASK     0x007FFFFF
 #define CREATE_OPTION_SPECIAL   0x20000000   /* system. NB not sent over wire */
 
@@ -470,7 +483,7 @@ typedef struct lanman_neg_rsp {
 
 typedef struct negotiate_rsp {
        struct smb_hdr hdr;     /* wct = 17 */
-       __le16 DialectIndex;
+       __le16 DialectIndex; /* 0xFFFF = no dialect acceptable */
        __u8 SecurityMode;
        __le16 MaxMpxCount;
        __le16 MaxNumberVcs;
@@ -516,10 +529,11 @@ typedef struct negotiate_rsp {
 #define CAP_INFOLEVEL_PASSTHRU 0x00002000
 #define CAP_LARGE_READ_X       0x00004000
 #define CAP_LARGE_WRITE_X      0x00008000
+#define CAP_LWIO               0x00010000 /* support fctl_srv_req_resume_key */
 #define CAP_UNIX               0x00800000
-#define CAP_RESERVED           0x02000000
-#define CAP_BULK_TRANSFER      0x20000000
-#define CAP_COMPRESSED_DATA    0x40000000
+#define CAP_COMPRESSED_DATA    0x02000000
+#define CAP_DYNAMIC_REAUTH     0x20000000
+#define CAP_PERSISTENT_HANDLES 0x40000000
 #define CAP_EXTENDED_SECURITY  0x80000000
 
 typedef union smb_com_session_setup_andx {
@@ -668,9 +682,7 @@ typedef struct smb_com_tconx_req {
 } __attribute__((packed)) TCONX_REQ;
 
 typedef struct smb_com_tconx_rsp {
-       struct smb_hdr hdr;     /* wct = 3 note that Win2000 has sent wct = 7
-                                in some cases on responses. Four unspecified
-                                words followed OptionalSupport */
+       struct smb_hdr hdr;     /* wct = 3 , not extended response */
        __u8 AndXCommand;
        __u8 AndXReserved;
        __le16 AndXOffset;
@@ -680,13 +692,48 @@ typedef struct smb_com_tconx_rsp {
        /* STRING NativeFileSystem */
 } __attribute__((packed)) TCONX_RSP;
 
+typedef struct smb_com_tconx_rsp_ext {
+       struct smb_hdr hdr;     /* wct = 7, extended response */
+       __u8 AndXCommand;
+       __u8 AndXReserved;
+       __le16 AndXOffset;
+       __le16 OptionalSupport; /* see below */
+       __le32 MaximalShareAccessRights;
+       __le32 GuestMaximalShareAccessRights;
+       __u16 ByteCount;
+       unsigned char Service[1];       /* always ASCII, not Unicode */
+       /* STRING NativeFileSystem */
+} __attribute__((packed)) TCONX_RSP_EXT;
+
+
 /* tree connect Flags */
 #define DISCONNECT_TID          0x0001
+#define TCON_EXTENDED_SIGNATURES 0x0004
 #define TCON_EXTENDED_SECINFO   0x0008
+
 /* OptionalSupport bits */
 #define SMB_SUPPORT_SEARCH_BITS 0x0001 /* "must have" directory search bits
                                         (exclusive searches supported) */
 #define SMB_SHARE_IS_IN_DFS     0x0002
+#define SMB_CSC_MASK               0x000C
+/* CSC flags defined as follows */
+#define SMB_CSC_CACHE_MANUAL_REINT 0x0000
+#define SMB_CSC_CACHE_AUTO_REINT   0x0004
+#define SMB_CSC_CACHE_VDO          0x0008
+#define SMB_CSC_NO_CACHING         0x000C
+
+#define SMB_UNIQUE_FILE_NAME    0x0010
+#define SMB_EXTENDED_SIGNATURES 0x0020
+
+/* services
+ *
+ * A:       ie disk
+ * LPT1:    ie printer
+ * IPC      ie named pipe
+ * COMM
+ * ?????    ie any type
+ *
+ */
 
 typedef struct smb_com_logoff_andx_req {
        struct smb_hdr hdr;     /* wct = 2 */
@@ -750,6 +797,17 @@ typedef struct smb_com_findclose_req {
 #define COMM_DEV_TYPE          0x0004
 #define UNKNOWN_TYPE           0xFFFF
 
+/* Device Type or File Status Flags */
+#define NO_EAS                 0x0001
+#define NO_SUBSTREAMS          0x0002
+#define NO_REPARSETAG          0x0004
+/* following flags can apply if pipe */
+#define ICOUNT_MASK            0x00FF
+#define PIPE_READ_MODE         0x0100
+#define NAMED_PIPE_TYPE                0x0400
+#define PIPE_END_POINT         0x0800
+#define BLOCKING_NAMED_PIPE    0x8000
+
 typedef struct smb_com_open_req {      /* also handles create */
        struct smb_hdr hdr;     /* wct = 24 */
        __u8 AndXCommand;
@@ -758,7 +816,7 @@ typedef struct smb_com_open_req {   /* also handles create */
        __u8 Reserved;          /* Must Be Zero */
        __le16 NameLength;
        __le32 OpenFlags;
-       __le32 RootDirectoryFid;
+       __u32  RootDirectoryFid;
        __le32 DesiredAccess;
        __le64 AllocationSize;
        __le32 FileAttributes;
@@ -801,6 +859,32 @@ typedef struct smb_com_open_rsp {
        __u16 ByteCount;        /* bct = 0 */
 } __attribute__((packed)) OPEN_RSP;
 
+typedef struct smb_com_open_rsp_ext {
+       struct smb_hdr hdr;     /* wct = 42 but meaningless due to MS bug? */
+       __u8 AndXCommand;
+       __u8 AndXReserved;
+       __le16 AndXOffset;
+       __u8 OplockLevel;
+       __u16 Fid;
+       __le32 CreateAction;
+       __le64 CreationTime;
+       __le64 LastAccessTime;
+       __le64 LastWriteTime;
+       __le64 ChangeTime;
+       __le32 FileAttributes;
+       __le64 AllocationSize;
+       __le64 EndOfFile;
+       __le16 FileType;
+       __le16 DeviceState;
+       __u8 DirectoryFlag;
+       __u8 VolumeGUID[16];
+       __u64 FileId; /* note no endian conversion - is opaque UniqueID */
+       __le32 MaximalAccessRights;
+       __le32 GuestMaximalAccessRights;
+       __u16 ByteCount;        /* bct = 0 */
+} __attribute__((packed)) OPEN_RSP_EXT;
+
+
 /* format of legacy open request */
 typedef struct smb_com_openx_req {
        struct smb_hdr  hdr;    /* wct = 15 */
@@ -1703,6 +1787,12 @@ typedef struct smb_com_transaction2_fnext_rsp_parms {
 #define SMB_QUERY_CIFS_UNIX_INFO    0x200
 #define SMB_QUERY_POSIX_FS_INFO     0x201
 #define SMB_QUERY_POSIX_WHO_AM_I    0x202
+#define SMB_REQUEST_TRANSPORT_ENCRYPTION 0x203
+#define SMB_QUERY_FS_PROXY          0x204 /* WAFS enabled. Returns structure
+                                           FILE_SYSTEM__UNIX_INFO to tell
+                                           whether new NTIOCTL available
+                                           (0xACE) for WAN friendly SMB
+                                           operations to be carried */
 #define SMB_QUERY_LABEL_INFO        0x3ea
 #define SMB_QUERY_FS_QUOTA_INFO     0x3ee
 #define SMB_QUERY_FS_FULL_SIZE_INFO 0x3ef
@@ -1959,7 +2049,10 @@ typedef struct {
 #define CIFS_UNIX_LARGE_READ_CAP        0x00000040 /* support reads >128K (up
                                                      to 0xFFFF00 */
 #define CIFS_UNIX_LARGE_WRITE_CAP       0x00000080
-
+#define CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP 0x00000100 /* can do SPNEGO crypt */
+#define CIFS_UNIX_TRANPSORT_ENCRYPTION_MANDATORY_CAP  0x00000200 /* must do  */
+#define CIFS_UNIX_PROXY_CAP             0x00000400 /* Proxy cap: 0xACE ioctl and
+                                                     QFS PROXY call */
 #ifdef CONFIG_CIFS_POSIX
 /* Can not set pathnames cap yet until we send new posix create SMB since
    otherwise server can treat such handles opened with older ntcreatex
index 7e5e0e78cd72c1c051ef5e23957de768687a664d..0c83da4a7dabe10017ab31d4de41002bbc78d318 100644 (file)
@@ -84,6 +84,7 @@ extern __u16 GetNextMid(struct TCP_Server_Info *server);
 extern struct oplock_q_entry *AllocOplockQEntry(struct inode *, u16,
                                                 struct cifsTconInfo *);
 extern void DeleteOplockQEntry(struct oplock_q_entry *);
+extern void DeleteTconOplockQEntries(struct cifsTconInfo *);
 extern struct timespec cifs_NTtimeToUnix(u64 utc_nanoseconds_since_1601);
 extern u64 cifs_UnixTimeToNT(struct timespec);
 extern __le64 cnvrtDosCifsTm(__u16 date, __u16 time);
index 30bbe448e260fa931a2a36098057bfdd8364fad3..4728fa982a4ed965237427b7386b838266ec497b 100644 (file)
@@ -165,17 +165,19 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
                                rc = CIFSTCon(0, tcon->ses, tcon->treeName,
                                              tcon, nls_codepage);
                                up(&tcon->ses->sesSem);
-                               /* tell server which Unix caps we support */
-                               if (tcon->ses->capabilities & CAP_UNIX)
-                                       reset_cifs_unix_caps(0 /* no xid */,
-                                               tcon,
-                                               NULL /* we do not know sb */,
-                                               NULL /* no vol info */);
                                /* BB FIXME add code to check if wsize needs
                                   update due to negotiated smb buffer size
                                   shrinking */
-                               if (rc == 0)
+                               if (rc == 0) {
                                        atomic_inc(&tconInfoReconnectCount);
+                                       /* tell server Unix caps we support */
+                                       if (tcon->ses->capabilities & CAP_UNIX)
+                                               reset_cifs_unix_caps(
+                                               0 /* no xid */,
+                                               tcon,
+                                               NULL /* we do not know sb */,
+                                               NULL /* no vol info */);
+                               }
 
                                cFYI(1, ("reconnect tcon rc = %d", rc));
                                /* Removed call to reopen open files here.
@@ -310,17 +312,19 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
                                rc = CIFSTCon(0, tcon->ses, tcon->treeName,
                                              tcon, nls_codepage);
                                up(&tcon->ses->sesSem);
-                               /* tell server which Unix caps we support */
-                               if (tcon->ses->capabilities & CAP_UNIX)
-                                       reset_cifs_unix_caps(0 /* no xid */,
-                                               tcon,
-                                               NULL /* do not know sb */,
-                                               NULL /* no vol info */);
                                /* BB FIXME add code to check if wsize needs
                                update due to negotiated smb buffer size
                                shrinking */
-                               if (rc == 0)
+                               if (rc == 0) {
                                        atomic_inc(&tconInfoReconnectCount);
+                                       /* tell server Unix caps we support */
+                                       if (tcon->ses->capabilities & CAP_UNIX)
+                                               reset_cifs_unix_caps(
+                                               0 /* no xid */,
+                                               tcon,
+                                               NULL /* do not know sb */,
+                                               NULL /* no vol info */);
+                               }
 
                                cFYI(1, ("reconnect tcon rc = %d", rc));
                                /* Removed call to reopen open files here.
index 8dbfa97cd18ca6ae60ba6621e8e9214cb7a1641d..e171067301689dee90ed97de96fc2fcb7eb3f518 100644 (file)
@@ -3527,6 +3527,7 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
                        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 */
index bc673c8c1e6b59eb7fc48464965db0e3e7835365..e1031b9e2c55ccfb13182e89c899ba6e49c89f7d 100644 (file)
@@ -161,12 +161,14 @@ static void cifs_unix_info_to_inode(struct inode *inode,
        spin_unlock(&inode->i_lock);
 }
 
-static const unsigned char *cifs_get_search_path(struct cifsTconInfo *pTcon,
-                                       const char *search_path)
+static const unsigned char *cifs_get_search_path(struct cifs_sb_info *cifs_sb,
+                                               const char *search_path)
 {
        int tree_len;
        int path_len;
+       int i;
        char *tmp_path;
+       struct cifsTconInfo *pTcon = cifs_sb->tcon;
 
        if (!(pTcon->Flags & SMB_SHARE_IS_IN_DFS))
                return search_path;
@@ -180,6 +182,11 @@ static const unsigned char *cifs_get_search_path(struct cifsTconInfo *pTcon,
                return search_path;
 
        strncpy(tmp_path, pTcon->treeName, tree_len);
+       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
+               for (i = 0; i < tree_len; i++) {
+                       if (tmp_path[i] == '\\')
+                               tmp_path[i] = '/';
+               }
        strncpy(tmp_path+tree_len, search_path, path_len);
        tmp_path[tree_len+path_len] = 0;
        return tmp_path;
@@ -199,7 +206,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
        pTcon = cifs_sb->tcon;
        cFYI(1, ("Getting info on %s", search_path));
 
-       full_path = cifs_get_search_path(pTcon, search_path);
+       full_path = cifs_get_search_path(cifs_sb, search_path);
 
 try_again_CIFSSMBUnixQPathInfo:
        /* could have done a find first instead but this returns more info */
@@ -402,7 +409,7 @@ int cifs_get_inode_info(struct inode **pinode,
                        return -ENOMEM;
                pfindData = (FILE_ALL_INFO *)buf;
 
-               full_path = cifs_get_search_path(pTcon, search_path);
+               full_path = cifs_get_search_path(cifs_sb, search_path);
 
 try_again_CIFSSMBQPathInfo:
                /* could do find first instead but this returns more info */
index 3612d6c0a0bbc1a4c9f64c2ce0f674517ce86d72..000ac509c98a32e884322149e88b53e4bdb2a4c1 100644 (file)
@@ -142,6 +142,24 @@ void DeleteOplockQEntry(struct oplock_q_entry *oplockEntry)
        kmem_cache_free(cifs_oplock_cachep, oplockEntry);
 }
 
+
+void DeleteTconOplockQEntries(struct cifsTconInfo *tcon)
+{
+       struct oplock_q_entry *temp;
+
+       if (tcon == NULL)
+               return;
+
+       spin_lock(&GlobalMid_Lock);
+       list_for_each_entry(temp, &GlobalOplock_Q, qhead) {
+               if ((temp->tcon) && (temp->tcon == tcon)) {
+                       list_del(&temp->qhead);
+                       kmem_cache_free(cifs_oplock_cachep, temp);
+               }
+       }
+       spin_unlock(&GlobalMid_Lock);
+}
+
 int
 smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
         unsigned int smb_buf_length, struct sockaddr *sin)
index b6b74a60e1ebb8cb18cfb4935e23c5ba9a6bfc02..40b16f23e49af4eb99c8060d5e52aad370e0613c 100644 (file)
@@ -155,8 +155,6 @@ static void nlmclnt_release_lockargs(struct nlm_rqst *req)
 int nlmclnt_proc(struct nlm_host *host, int cmd, struct file_lock *fl)
 {
        struct nlm_rqst         *call;
-       sigset_t                oldset;
-       unsigned long           flags;
        int                     status;
 
        nlm_get_host(host);
@@ -168,22 +166,6 @@ int nlmclnt_proc(struct nlm_host *host, int cmd, struct file_lock *fl)
        /* Set up the argument struct */
        nlmclnt_setlockargs(call, fl);
 
-       /* Keep the old signal mask */
-       spin_lock_irqsave(&current->sighand->siglock, flags);
-       oldset = current->blocked;
-
-       /* If we're cleaning up locks because the process is exiting,
-        * perform the RPC call asynchronously. */
-       if ((IS_SETLK(cmd) || IS_SETLKW(cmd))
-           && fl->fl_type == F_UNLCK
-           && (current->flags & PF_EXITING)) {
-               sigfillset(&current->blocked);  /* Mask all signals */
-               recalc_sigpending();
-
-               call->a_flags = RPC_TASK_ASYNC;
-       }
-       spin_unlock_irqrestore(&current->sighand->siglock, flags);
-
        if (IS_SETLK(cmd) || IS_SETLKW(cmd)) {
                if (fl->fl_type != F_UNLCK) {
                        call->a_args.block = IS_SETLKW(cmd) ? 1 : 0;
@@ -198,11 +180,6 @@ int nlmclnt_proc(struct nlm_host *host, int cmd, struct file_lock *fl)
        fl->fl_ops->fl_release_private(fl);
        fl->fl_ops = NULL;
 
-       spin_lock_irqsave(&current->sighand->siglock, flags);
-       current->blocked = oldset;
-       recalc_sigpending();
-       spin_unlock_irqrestore(&current->sighand->siglock, flags);
-
        dprintk("lockd: clnt proc returns %d\n", status);
        return status;
 }
@@ -221,6 +198,7 @@ struct nlm_rqst *nlm_alloc_call(struct nlm_host *host)
        for(;;) {
                call = kzalloc(sizeof(*call), GFP_KERNEL);
                if (call != NULL) {
+                       atomic_set(&call->a_count, 1);
                        locks_init_lock(&call->a_args.lock.fl);
                        locks_init_lock(&call->a_res.lock.fl);
                        call->a_host = host;
@@ -237,6 +215,8 @@ struct nlm_rqst *nlm_alloc_call(struct nlm_host *host)
 
 void nlm_release_call(struct nlm_rqst *call)
 {
+       if (!atomic_dec_and_test(&call->a_count))
+               return;
        nlm_release_host(call->a_host);
        nlmclnt_release_lockargs(call);
        kfree(call);
@@ -267,7 +247,7 @@ static int nlm_wait_on_grace(wait_queue_head_t *queue)
  * Generic NLM call
  */
 static int
-nlmclnt_call(struct nlm_rqst *req, u32 proc)
+nlmclnt_call(struct rpc_cred *cred, struct nlm_rqst *req, u32 proc)
 {
        struct nlm_host *host = req->a_host;
        struct rpc_clnt *clnt;
@@ -276,6 +256,7 @@ nlmclnt_call(struct nlm_rqst *req, u32 proc)
        struct rpc_message msg = {
                .rpc_argp       = argp,
                .rpc_resp       = resp,
+               .rpc_cred       = cred,
        };
        int             status;
 
@@ -343,10 +324,16 @@ in_grace_period:
 /*
  * Generic NLM call, async version.
  */
-static int __nlm_async_call(struct nlm_rqst *req, u32 proc, struct rpc_message *msg, const struct rpc_call_ops *tk_ops)
+static struct rpc_task *__nlm_async_call(struct nlm_rqst *req, u32 proc, struct rpc_message *msg, const struct rpc_call_ops *tk_ops)
 {
        struct nlm_host *host = req->a_host;
        struct rpc_clnt *clnt;
+       struct rpc_task_setup task_setup_data = {
+               .rpc_message = msg,
+               .callback_ops = tk_ops,
+               .callback_data = req,
+               .flags = RPC_TASK_ASYNC,
+       };
 
        dprintk("lockd: call procedure %d on %s (async)\n",
                        (int)proc, host->h_name);
@@ -356,21 +343,36 @@ static int __nlm_async_call(struct nlm_rqst *req, u32 proc, struct rpc_message *
        if (clnt == NULL)
                goto out_err;
        msg->rpc_proc = &clnt->cl_procinfo[proc];
+       task_setup_data.rpc_client = clnt;
 
         /* bootstrap and kick off the async RPC call */
-        return rpc_call_async(clnt, msg, RPC_TASK_ASYNC, tk_ops, req);
+       return rpc_run_task(&task_setup_data);
 out_err:
        tk_ops->rpc_release(req);
-       return -ENOLCK;
+       return ERR_PTR(-ENOLCK);
 }
 
+static int nlm_do_async_call(struct nlm_rqst *req, u32 proc, struct rpc_message *msg, const struct rpc_call_ops *tk_ops)
+{
+       struct rpc_task *task;
+
+       task = __nlm_async_call(req, proc, msg, tk_ops);
+       if (IS_ERR(task))
+               return PTR_ERR(task);
+       rpc_put_task(task);
+       return 0;
+}
+
+/*
+ * NLM asynchronous call.
+ */
 int nlm_async_call(struct nlm_rqst *req, u32 proc, const struct rpc_call_ops *tk_ops)
 {
        struct rpc_message msg = {
                .rpc_argp       = &req->a_args,
                .rpc_resp       = &req->a_res,
        };
-       return __nlm_async_call(req, proc, &msg, tk_ops);
+       return nlm_do_async_call(req, proc, &msg, tk_ops);
 }
 
 int nlm_async_reply(struct nlm_rqst *req, u32 proc, const struct rpc_call_ops *tk_ops)
@@ -378,7 +380,33 @@ int nlm_async_reply(struct nlm_rqst *req, u32 proc, const struct rpc_call_ops *t
        struct rpc_message msg = {
                .rpc_argp       = &req->a_res,
        };
-       return __nlm_async_call(req, proc, &msg, tk_ops);
+       return nlm_do_async_call(req, proc, &msg, tk_ops);
+}
+
+/*
+ * NLM client asynchronous call.
+ *
+ * Note that although the calls are asynchronous, and are therefore
+ *      guaranteed to complete, we still always attempt to wait for
+ *      completion in order to be able to correctly track the lock
+ *      state.
+ */
+static int nlmclnt_async_call(struct rpc_cred *cred, struct nlm_rqst *req, u32 proc, const struct rpc_call_ops *tk_ops)
+{
+       struct rpc_message msg = {
+               .rpc_argp       = &req->a_args,
+               .rpc_resp       = &req->a_res,
+               .rpc_cred       = cred,
+       };
+       struct rpc_task *task;
+       int err;
+
+       task = __nlm_async_call(req, proc, &msg, tk_ops);
+       if (IS_ERR(task))
+               return PTR_ERR(task);
+       err = rpc_wait_for_completion_task(task);
+       rpc_put_task(task);
+       return err;
 }
 
 /*
@@ -389,7 +417,7 @@ nlmclnt_test(struct nlm_rqst *req, struct file_lock *fl)
 {
        int     status;
 
-       status = nlmclnt_call(req, NLMPROC_TEST);
+       status = nlmclnt_call(nfs_file_cred(fl->fl_file), req, NLMPROC_TEST);
        if (status < 0)
                goto out;
 
@@ -480,10 +508,12 @@ static int do_vfs_lock(struct file_lock *fl)
 static int
 nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl)
 {
+       struct rpc_cred *cred = nfs_file_cred(fl->fl_file);
        struct nlm_host *host = req->a_host;
        struct nlm_res  *resp = &req->a_res;
        struct nlm_wait *block = NULL;
        unsigned char fl_flags = fl->fl_flags;
+       unsigned char fl_type;
        int status = -ENOLCK;
 
        if (nsm_monitor(host) < 0) {
@@ -493,18 +523,22 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl)
        }
        fl->fl_flags |= FL_ACCESS;
        status = do_vfs_lock(fl);
+       fl->fl_flags = fl_flags;
        if (status < 0)
                goto out;
 
        block = nlmclnt_prepare_block(host, fl);
 again:
+       /*
+        * Initialise resp->status to a valid non-zero value,
+        * since 0 == nlm_lck_granted
+        */
+       resp->status = nlm_lck_blocked;
        for(;;) {
                /* Reboot protection */
                fl->fl_u.nfs_fl.state = host->h_state;
-               status = nlmclnt_call(req, NLMPROC_LOCK);
+               status = nlmclnt_call(cred, req, NLMPROC_LOCK);
                if (status < 0)
-                       goto out_unblock;
-               if (!req->a_args.block)
                        break;
                /* Did a reclaimer thread notify us of a server reboot? */
                if (resp->status ==  nlm_lck_denied_grace_period)
@@ -513,15 +547,22 @@ again:
                        break;
                /* Wait on an NLM blocking lock */
                status = nlmclnt_block(block, req, NLMCLNT_POLL_TIMEOUT);
-               /* if we were interrupted. Send a CANCEL request to the server
-                * and exit
-                */
                if (status < 0)
-                       goto out_unblock;
+                       break;
                if (resp->status != nlm_lck_blocked)
                        break;
        }
 
+       /* if we were interrupted while blocking, then cancel the lock request
+        * and exit
+        */
+       if (resp->status == nlm_lck_blocked) {
+               if (!req->a_args.block)
+                       goto out_unlock;
+               if (nlmclnt_cancel(host, req->a_args.block, fl) == 0)
+                       goto out_unblock;
+       }
+
        if (resp->status == nlm_granted) {
                down_read(&host->h_rwsem);
                /* Check whether or not the server has rebooted */
@@ -530,20 +571,34 @@ again:
                        goto again;
                }
                /* Ensure the resulting lock will get added to granted list */
-               fl->fl_flags = fl_flags | FL_SLEEP;
+               fl->fl_flags |= FL_SLEEP;
                if (do_vfs_lock(fl) < 0)
                        printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n", __FUNCTION__);
                up_read(&host->h_rwsem);
+               fl->fl_flags = fl_flags;
+               status = 0;
        }
+       if (status < 0)
+               goto out_unlock;
        status = nlm_stat_to_errno(resp->status);
 out_unblock:
        nlmclnt_finish_block(block);
-       /* Cancel the blocked request if it is still pending */
-       if (resp->status == nlm_lck_blocked)
-               nlmclnt_cancel(host, req->a_args.block, fl);
 out:
        nlm_release_call(req);
+       return status;
+out_unlock:
+       /* Fatal error: ensure that we remove the lock altogether */
+       dprintk("lockd: lock attempt ended in fatal error.\n"
+               "       Attempting to unlock.\n");
+       nlmclnt_finish_block(block);
+       fl_type = fl->fl_type;
+       fl->fl_type = F_UNLCK;
+       down_read(&host->h_rwsem);
+       do_vfs_lock(fl);
+       up_read(&host->h_rwsem);
+       fl->fl_type = fl_type;
        fl->fl_flags = fl_flags;
+       nlmclnt_async_call(cred, req, NLMPROC_UNLOCK, &nlmclnt_unlock_ops);
        return status;
 }
 
@@ -567,8 +622,8 @@ nlmclnt_reclaim(struct nlm_host *host, struct file_lock *fl)
        nlmclnt_setlockargs(req, fl);
        req->a_args.reclaim = 1;
 
-       if ((status = nlmclnt_call(req, NLMPROC_LOCK)) >= 0
-        && req->a_res.status == nlm_granted)
+       status = nlmclnt_call(nfs_file_cred(fl->fl_file), req, NLMPROC_LOCK);
+       if (status >= 0 && req->a_res.status == nlm_granted)
                return 0;
 
        printk(KERN_WARNING "lockd: failed to reclaim lock for pid %d "
@@ -598,7 +653,8 @@ nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl)
 {
        struct nlm_host *host = req->a_host;
        struct nlm_res  *resp = &req->a_res;
-       int status = 0;
+       int status;
+       unsigned char fl_flags = fl->fl_flags;
 
        /*
         * Note: the server is supposed to either grant us the unlock
@@ -607,16 +663,17 @@ nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl)
         */
        fl->fl_flags |= FL_EXISTS;
        down_read(&host->h_rwsem);
-       if (do_vfs_lock(fl) == -ENOENT) {
-               up_read(&host->h_rwsem);
+       status = do_vfs_lock(fl);
+       up_read(&host->h_rwsem);
+       fl->fl_flags = fl_flags;
+       if (status == -ENOENT) {
+               status = 0;
                goto out;
        }
-       up_read(&host->h_rwsem);
-
-       if (req->a_flags & RPC_TASK_ASYNC)
-               return nlm_async_call(req, NLMPROC_UNLOCK, &nlmclnt_unlock_ops);
 
-       status = nlmclnt_call(req, NLMPROC_UNLOCK);
+       atomic_inc(&req->a_count);
+       status = nlmclnt_async_call(nfs_file_cred(fl->fl_file), req,
+                       NLMPROC_UNLOCK, &nlmclnt_unlock_ops);
        if (status < 0)
                goto out;
 
@@ -671,16 +728,10 @@ static const struct rpc_call_ops nlmclnt_unlock_ops = {
 static int nlmclnt_cancel(struct nlm_host *host, int block, struct file_lock *fl)
 {
        struct nlm_rqst *req;
-       unsigned long   flags;
-       sigset_t        oldset;
-       int             status;
+       int status;
 
-       /* Block all signals while setting up call */
-       spin_lock_irqsave(&current->sighand->siglock, flags);
-       oldset = current->blocked;
-       sigfillset(&current->blocked);
-       recalc_sigpending();
-       spin_unlock_irqrestore(&current->sighand->siglock, flags);
+       dprintk("lockd: blocking lock attempt was interrupted by a signal.\n"
+               "       Attempting to cancel lock.\n");
 
        req = nlm_alloc_call(nlm_get_host(host));
        if (!req)
@@ -690,13 +741,12 @@ static int nlmclnt_cancel(struct nlm_host *host, int block, struct file_lock *fl
        nlmclnt_setlockargs(req, fl);
        req->a_args.block = block;
 
-       status = nlm_async_call(req, NLMPROC_CANCEL, &nlmclnt_cancel_ops);
-
-       spin_lock_irqsave(&current->sighand->siglock, flags);
-       current->blocked = oldset;
-       recalc_sigpending();
-       spin_unlock_irqrestore(&current->sighand->siglock, flags);
-
+       atomic_inc(&req->a_count);
+       status = nlmclnt_async_call(nfs_file_cred(fl->fl_file), req,
+                       NLMPROC_CANCEL, &nlmclnt_cancel_ops);
+       if (status == 0 && req->a_res.status == nlm_lck_denied)
+               status = -ENOLCK;
+       nlm_release_call(req);
        return status;
 }
 
index f1ef49fff118ea8aa8322dd4404e0ca65ea3e518..a17664c7eacc4542ee8a27a6543c4b548f6efc62 100644 (file)
 
 
 #define NLMDBG_FACILITY                NLMDBG_HOSTCACHE
-#define NLM_HOST_MAX           64
 #define NLM_HOST_NRHASH                32
 #define NLM_ADDRHASH(addr)     (ntohl(addr) & (NLM_HOST_NRHASH-1))
 #define NLM_HOST_REBIND                (60 * HZ)
-#define NLM_HOST_EXPIRE                ((nrhosts > NLM_HOST_MAX)? 300 * HZ : 120 * HZ)
-#define NLM_HOST_COLLECT       ((nrhosts > NLM_HOST_MAX)? 120 * HZ :  60 * HZ)
+#define NLM_HOST_EXPIRE                (300 * HZ)
+#define NLM_HOST_COLLECT       (120 * HZ)
 
 static struct hlist_head       nlm_hosts[NLM_HOST_NRHASH];
 static unsigned long           next_gc;
@@ -42,11 +41,12 @@ static struct nsm_handle *  nsm_find(const struct sockaddr_in *sin,
 /*
  * Common host lookup routine for server & client
  */
-static struct nlm_host *
-nlm_lookup_host(int server, const struct sockaddr_in *sin,
-               int proto, int version, const char *hostname,
-               unsigned int hostname_len,
-               const struct sockaddr_in *ssin)
+static struct nlm_host *nlm_lookup_host(int server,
+                                       const struct sockaddr_in *sin,
+                                       int proto, u32 version,
+                                       const char *hostname,
+                                       unsigned int hostname_len,
+                                       const struct sockaddr_in *ssin)
 {
        struct hlist_head *chain;
        struct hlist_node *pos;
@@ -55,7 +55,7 @@ nlm_lookup_host(int server, const struct sockaddr_in *sin,
        int             hash;
 
        dprintk("lockd: nlm_lookup_host("NIPQUAD_FMT"->"NIPQUAD_FMT
-                       ", p=%d, v=%d, my role=%s, name=%.*s)\n",
+                       ", p=%d, v=%u, my role=%s, name=%.*s)\n",
                        NIPQUAD(ssin->sin_addr.s_addr),
                        NIPQUAD(sin->sin_addr.s_addr), proto, version,
                        server? "server" : "client",
@@ -142,9 +142,7 @@ nlm_lookup_host(int server, const struct sockaddr_in *sin,
        INIT_LIST_HEAD(&host->h_granted);
        INIT_LIST_HEAD(&host->h_reclaim);
 
-       if (++nrhosts > NLM_HOST_MAX)
-               next_gc = 0;
-
+       nrhosts++;
 out:
        mutex_unlock(&nlm_host_mutex);
        return host;
@@ -175,9 +173,10 @@ nlm_destroy_host(struct nlm_host *host)
 /*
  * Find an NLM server handle in the cache. If there is none, create it.
  */
-struct nlm_host *
-nlmclnt_lookup_host(const struct sockaddr_in *sin, int proto, int version,
-                       const char *hostname, unsigned int hostname_len)
+struct nlm_host *nlmclnt_lookup_host(const struct sockaddr_in *sin,
+                                    int proto, u32 version,
+                                    const char *hostname,
+                                    unsigned int hostname_len)
 {
        struct sockaddr_in ssin = {0};
 
@@ -460,7 +459,7 @@ nlm_gc_hosts(void)
  * Manage NSM handles
  */
 static LIST_HEAD(nsm_handles);
-static DEFINE_MUTEX(nsm_mutex);
+static DEFINE_SPINLOCK(nsm_lock);
 
 static struct nsm_handle *
 __nsm_find(const struct sockaddr_in *sin,
@@ -468,7 +467,7 @@ __nsm_find(const struct sockaddr_in *sin,
                int create)
 {
        struct nsm_handle *nsm = NULL;
-       struct list_head *pos;
+       struct nsm_handle *pos;
 
        if (!sin)
                return NULL;
@@ -482,38 +481,43 @@ __nsm_find(const struct sockaddr_in *sin,
                return NULL;
        }
 
-       mutex_lock(&nsm_mutex);
-       list_for_each(pos, &nsm_handles) {
-               nsm = list_entry(pos, struct nsm_handle, sm_link);
+retry:
+       spin_lock(&nsm_lock);
+       list_for_each_entry(pos, &nsm_handles, sm_link) {
 
                if (hostname && nsm_use_hostnames) {
-                       if (strlen(nsm->sm_name) != hostname_len
-                        || memcmp(nsm->sm_name, hostname, hostname_len))
+                       if (strlen(pos->sm_name) != hostname_len
+                        || memcmp(pos->sm_name, hostname, hostname_len))
                                continue;
-               } else if (!nlm_cmp_addr(&nsm->sm_addr, sin))
+               } else if (!nlm_cmp_addr(&pos->sm_addr, sin))
                        continue;
-               atomic_inc(&nsm->sm_count);
-               goto out;
+               atomic_inc(&pos->sm_count);
+               kfree(nsm);
+               nsm = pos;
+               goto found;
        }
-
-       if (!create) {
-               nsm = NULL;
-               goto out;
+       if (nsm) {
+               list_add(&nsm->sm_link, &nsm_handles);
+               goto found;
        }
+       spin_unlock(&nsm_lock);
+
+       if (!create)
+               return NULL;
 
        nsm = kzalloc(sizeof(*nsm) + hostname_len + 1, GFP_KERNEL);
-       if (nsm != NULL) {
-               nsm->sm_addr = *sin;
-               nsm->sm_name = (char *) (nsm + 1);
-               memcpy(nsm->sm_name, hostname, hostname_len);
-               nsm->sm_name[hostname_len] = '\0';
-               atomic_set(&nsm->sm_count, 1);
+       if (nsm == NULL)
+               return NULL;
 
-               list_add(&nsm->sm_link, &nsm_handles);
-       }
+       nsm->sm_addr = *sin;
+       nsm->sm_name = (char *) (nsm + 1);
+       memcpy(nsm->sm_name, hostname, hostname_len);
+       nsm->sm_name[hostname_len] = '\0';
+       atomic_set(&nsm->sm_count, 1);
+       goto retry;
 
-out:
-       mutex_unlock(&nsm_mutex);
+found:
+       spin_unlock(&nsm_lock);
        return nsm;
 }
 
@@ -532,12 +536,9 @@ nsm_release(struct nsm_handle *nsm)
 {
        if (!nsm)
                return;
-       if (atomic_dec_and_test(&nsm->sm_count)) {
-               mutex_lock(&nsm_mutex);
-               if (atomic_read(&nsm->sm_count) == 0) {
-                       list_del(&nsm->sm_link);
-                       kfree(nsm);
-               }
-               mutex_unlock(&nsm_mutex);
+       if (atomic_dec_and_lock(&nsm->sm_count, &nsm_lock)) {
+               list_del(&nsm->sm_link);
+               spin_unlock(&nsm_lock);
+               kfree(nsm);
        }
 }
index 908b23fadd05a98d28c533ab6bd7cfba3e859e8a..e4d563543b11066a1acd17a5beb7d0a8916aa520 100644 (file)
@@ -18,6 +18,8 @@
 
 #define NLMDBG_FACILITY                NLMDBG_MONITOR
 
+#define XDR_ADDRBUF_LEN                (20)
+
 static struct rpc_clnt *       nsm_create(void);
 
 static struct rpc_program      nsm_program;
@@ -147,28 +149,55 @@ nsm_create(void)
 
 /*
  * XDR functions for NSM.
+ *
+ * See http://www.opengroup.org/ for details on the Network
+ * Status Monitor wire protocol.
  */
 
-static __be32 *
-xdr_encode_common(struct rpc_rqst *rqstp, __be32 *p, struct nsm_args *argp)
+static __be32 *xdr_encode_nsm_string(__be32 *p, char *string)
 {
-       char    buffer[20], *name;
-
-       /*
-        * Use the dotted-quad IP address of the remote host as
-        * identifier. Linux statd always looks up the canonical
-        * hostname first for whatever remote hostname it receives,
-        * so this works alright.
-        */
-       if (nsm_use_hostnames) {
-               name = argp->mon_name;
-       } else {
-               sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(argp->addr));
+       size_t len = strlen(string);
+
+       if (len > SM_MAXSTRLEN)
+               len = SM_MAXSTRLEN;
+       return xdr_encode_opaque(p, string, len);
+}
+
+/*
+ * "mon_name" specifies the host to be monitored.
+ *
+ * Linux uses a text version of the IP address of the remote
+ * host as the host identifier (the "mon_name" argument).
+ *
+ * Linux statd always looks up the canonical hostname first for
+ * whatever remote hostname it receives, so this works alright.
+ */
+static __be32 *xdr_encode_mon_name(__be32 *p, struct nsm_args *argp)
+{
+       char    buffer[XDR_ADDRBUF_LEN + 1];
+       char    *name = argp->mon_name;
+
+       if (!nsm_use_hostnames) {
+               snprintf(buffer, XDR_ADDRBUF_LEN,
+                        NIPQUAD_FMT, NIPQUAD(argp->addr));
                name = buffer;
        }
-       if (!(p = xdr_encode_string(p, name))
-        || !(p = xdr_encode_string(p, utsname()->nodename)))
+
+       return xdr_encode_nsm_string(p, name);
+}
+
+/*
+ * The "my_id" argument specifies the hostname and RPC procedure
+ * to be called when the status manager receives notification
+ * (via the SM_NOTIFY call) that the state of host "mon_name"
+ * has changed.
+ */
+static __be32 *xdr_encode_my_id(__be32 *p, struct nsm_args *argp)
+{
+       p = xdr_encode_nsm_string(p, utsname()->nodename);
+       if (!p)
                return ERR_PTR(-EIO);
+
        *p++ = htonl(argp->prog);
        *p++ = htonl(argp->vers);
        *p++ = htonl(argp->proc);
@@ -176,18 +205,48 @@ xdr_encode_common(struct rpc_rqst *rqstp, __be32 *p, struct nsm_args *argp)
        return p;
 }
 
-static int
-xdr_encode_mon(struct rpc_rqst *rqstp, __be32 *p, struct nsm_args *argp)
+/*
+ * The "mon_id" argument specifies the non-private arguments
+ * of an SM_MON or SM_UNMON call.
+ */
+static __be32 *xdr_encode_mon_id(__be32 *p, struct nsm_args *argp)
 {
-       p = xdr_encode_common(rqstp, p, argp);
-       if (IS_ERR(p))
-               return PTR_ERR(p);
+       p = xdr_encode_mon_name(p, argp);
+       if (!p)
+               return ERR_PTR(-EIO);
 
-       /* Surprise - there may even be room for an IPv6 address now */
+       return xdr_encode_my_id(p, argp);
+}
+
+/*
+ * The "priv" argument may contain private information required
+ * by the SM_MON call. This information will be supplied in the
+ * SM_NOTIFY call.
+ *
+ * Linux provides the raw IP address of the monitored host,
+ * left in network byte order.
+ */
+static __be32 *xdr_encode_priv(__be32 *p, struct nsm_args *argp)
+{
        *p++ = argp->addr;
        *p++ = 0;
        *p++ = 0;
        *p++ = 0;
+
+       return p;
+}
+
+static int
+xdr_encode_mon(struct rpc_rqst *rqstp, __be32 *p, struct nsm_args *argp)
+{
+       p = xdr_encode_mon_id(p, argp);
+       if (IS_ERR(p))
+               return PTR_ERR(p);
+
+       p = xdr_encode_priv(p, argp);
+       if (IS_ERR(p))
+               return PTR_ERR(p);
+
        rqstp->rq_slen = xdr_adjust_iovec(rqstp->rq_svec, p);
        return 0;
 }
@@ -195,7 +254,7 @@ xdr_encode_mon(struct rpc_rqst *rqstp, __be32 *p, struct nsm_args *argp)
 static int
 xdr_encode_unmon(struct rpc_rqst *rqstp, __be32 *p, struct nsm_args *argp)
 {
-       p = xdr_encode_common(rqstp, p, argp);
+       p = xdr_encode_mon_id(p, argp);
        if (IS_ERR(p))
                return PTR_ERR(p);
        rqstp->rq_slen = xdr_adjust_iovec(rqstp->rq_svec, p);
@@ -220,9 +279,11 @@ xdr_decode_stat(struct rpc_rqst *rqstp, __be32 *p, struct nsm_res *resp)
 }
 
 #define SM_my_name_sz  (1+XDR_QUADLEN(SM_MAXSTRLEN))
-#define SM_my_id_sz    (3+1+SM_my_name_sz)
-#define SM_mon_id_sz   (1+XDR_QUADLEN(20)+SM_my_id_sz)
-#define SM_mon_sz      (SM_mon_id_sz+4)
+#define SM_my_id_sz    (SM_my_name_sz+3)
+#define SM_mon_name_sz (1+XDR_QUADLEN(SM_MAXSTRLEN))
+#define SM_mon_id_sz   (SM_mon_name_sz+SM_my_id_sz)
+#define SM_priv_sz     (XDR_QUADLEN(SM_PRIV_SIZE))
+#define SM_mon_sz      (SM_mon_id_sz+SM_priv_sz)
 #define SM_monres_sz   2
 #define SM_unmonres_sz 1
 
index 1ed8bd4de94143784080a98de6db2cbe3904368c..2169af4d54557bda54271482ac3c21d9710fdcbb 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 #include <linux/mutex.h>
+#include <linux/kthread.h>
 #include <linux/freezer.h>
 
 #include <linux/sunrpc/types.h>
@@ -48,14 +49,11 @@ EXPORT_SYMBOL(nlmsvc_ops);
 
 static DEFINE_MUTEX(nlmsvc_mutex);
 static unsigned int            nlmsvc_users;
-static pid_t                   nlmsvc_pid;
+static struct task_struct      *nlmsvc_task;
 static struct svc_serv         *nlmsvc_serv;
 int                            nlmsvc_grace_period;
 unsigned long                  nlmsvc_timeout;
 
-static DECLARE_COMPLETION(lockd_start_done);
-static DECLARE_WAIT_QUEUE_HEAD(lockd_exit);
-
 /*
  * These can be set at insmod time (useful for NFS as root filesystem),
  * and also changed through the sysctl interface.  -- Jamie Lokier, Aug 2003
@@ -74,7 +72,9 @@ static const unsigned long    nlm_timeout_min = 3;
 static const unsigned long     nlm_timeout_max = 20;
 static const int               nlm_port_min = 0, nlm_port_max = 65535;
 
+#ifdef CONFIG_SYSCTL
 static struct ctl_table_header * nlm_sysctl_table;
+#endif
 
 static unsigned long get_lockd_grace_period(void)
 {
@@ -111,35 +111,30 @@ static inline void clear_grace_period(void)
 /*
  * This is the lockd kernel thread
  */
-static void
-lockd(struct svc_rqst *rqstp)
+static int
+lockd(void *vrqstp)
 {
-       int             err = 0;
+       int             err = 0, preverr = 0;
+       struct svc_rqst *rqstp = vrqstp;
        unsigned long grace_period_expire;
 
-       /* Lock module and set up kernel thread */
-       /* lockd_up is waiting for us to startup, so will
-        * be holding a reference to this module, so it
-        * is safe to just claim another reference
-        */
-       __module_get(THIS_MODULE);
-       lock_kernel();
-
-       /*
-        * Let our maker know we're running.
-        */
-       nlmsvc_pid = current->pid;
-       nlmsvc_serv = rqstp->rq_server;
-       complete(&lockd_start_done);
-
-       daemonize("lockd");
+       /* try_to_freeze() is called from svc_recv() */
        set_freezable();
 
-       /* Process request with signals blocked, but allow SIGKILL.  */
+       /* Allow SIGKILL to tell lockd to drop all of its locks */
        allow_signal(SIGKILL);
 
        dprintk("NFS locking service started (ver " LOCKD_VERSION ").\n");
 
+       /*
+        * FIXME: it would be nice if lockd didn't spend its entire life
+        * running under the BKL. At the very least, it would be good to
+        * have someone clarify what it's intended to protect here. I've
+        * seen some handwavy posts about posix locking needing to be
+        * done under the BKL, but it's far from clear.
+        */
+       lock_kernel();
+
        if (!nlm_timeout)
                nlm_timeout = LOCKD_DFLT_TIMEO;
        nlmsvc_timeout = nlm_timeout * HZ;
@@ -148,10 +143,9 @@ lockd(struct svc_rqst *rqstp)
 
        /*
         * The main request loop. We don't terminate until the last
-        * NFS mount or NFS daemon has gone away, and we've been sent a
-        * signal, or else another process has taken over our job.
+        * NFS mount or NFS daemon has gone away.
         */
-       while ((nlmsvc_users || !signalled()) && nlmsvc_pid == current->pid) {
+       while (!kthread_should_stop()) {
                long timeout = MAX_SCHEDULE_TIMEOUT;
                RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]);
 
@@ -161,6 +155,7 @@ lockd(struct svc_rqst *rqstp)
                                nlmsvc_invalidate_all();
                                grace_period_expire = set_grace_period();
                        }
+                       continue;
                }
 
                /*
@@ -179,14 +174,20 @@ lockd(struct svc_rqst *rqstp)
                 * recvfrom routine.
                 */
                err = svc_recv(rqstp, timeout);
-               if (err == -EAGAIN || err == -EINTR)
+               if (err == -EAGAIN || err == -EINTR) {
+                       preverr = err;
                        continue;
+               }
                if (err < 0) {
-                       printk(KERN_WARNING
-                              "lockd: terminating on error %d\n",
-                              -err);
-                       break;
+                       if (err != preverr) {
+                               printk(KERN_WARNING "%s: unexpected error "
+                                       "from svc_recv (%d)\n", __func__, err);
+                               preverr = err;
+                       }
+                       schedule_timeout_interruptible(HZ);
+                       continue;
                }
+               preverr = err;
 
                dprintk("lockd: request from %s\n",
                                svc_print_addr(rqstp, buf, sizeof(buf)));
@@ -195,28 +196,19 @@ lockd(struct svc_rqst *rqstp)
        }
 
        flush_signals(current);
+       if (nlmsvc_ops)
+               nlmsvc_invalidate_all();
+       nlm_shutdown_hosts();
 
-       /*
-        * Check whether there's a new lockd process before
-        * shutting down the hosts and clearing the slot.
-        */
-       if (!nlmsvc_pid || current->pid == nlmsvc_pid) {
-               if (nlmsvc_ops)
-                       nlmsvc_invalidate_all();
-               nlm_shutdown_hosts();
-               nlmsvc_pid = 0;
-               nlmsvc_serv = NULL;
-       } else
-               printk(KERN_DEBUG
-                       "lockd: new process, skipping host shutdown\n");
-       wake_up(&lockd_exit);
+       unlock_kernel();
+
+       nlmsvc_task = NULL;
+       nlmsvc_serv = NULL;
 
        /* Exit the RPC thread */
        svc_exit_thread(rqstp);
 
-       /* Release module */
-       unlock_kernel();
-       module_put_and_exit(0);
+       return 0;
 }
 
 /*
@@ -261,14 +253,15 @@ static int make_socks(struct svc_serv *serv, int proto)
 int
 lockd_up(int proto) /* Maybe add a 'family' option when IPv6 is supported ?? */
 {
-       struct svc_serv *       serv;
-       int                     error = 0;
+       struct svc_serv *serv;
+       struct svc_rqst *rqstp;
+       int             error = 0;
 
        mutex_lock(&nlmsvc_mutex);
        /*
         * Check whether we're already up and running.
         */
-       if (nlmsvc_pid) {
+       if (nlmsvc_serv) {
                if (proto)
                        error = make_socks(nlmsvc_serv, proto);
                goto out;
@@ -295,13 +288,28 @@ lockd_up(int proto) /* Maybe add a 'family' option when IPv6 is supported ?? */
        /*
         * Create the kernel thread and wait for it to start.
         */
-       error = svc_create_thread(lockd, serv);
-       if (error) {
+       rqstp = svc_prepare_thread(serv, &serv->sv_pools[0]);
+       if (IS_ERR(rqstp)) {
+               error = PTR_ERR(rqstp);
+               printk(KERN_WARNING
+                       "lockd_up: svc_rqst allocation failed, error=%d\n",
+                       error);
+               goto destroy_and_out;
+       }
+
+       svc_sock_update_bufs(serv);
+       nlmsvc_serv = rqstp->rq_server;
+
+       nlmsvc_task = kthread_run(lockd, rqstp, serv->sv_name);
+       if (IS_ERR(nlmsvc_task)) {
+               error = PTR_ERR(nlmsvc_task);
+               nlmsvc_task = NULL;
+               nlmsvc_serv = NULL;
                printk(KERN_WARNING
-                       "lockd_up: create thread failed, error=%d\n", error);
+                       "lockd_up: kthread_run failed, error=%d\n", error);
+               svc_exit_thread(rqstp);
                goto destroy_and_out;
        }
-       wait_for_completion(&lockd_start_done);
 
        /*
         * Note: svc_serv structures have an initial use count of 1,
@@ -323,42 +331,28 @@ EXPORT_SYMBOL(lockd_up);
 void
 lockd_down(void)
 {
-       static int warned;
-
        mutex_lock(&nlmsvc_mutex);
        if (nlmsvc_users) {
                if (--nlmsvc_users)
                        goto out;
-       } else
-               printk(KERN_WARNING "lockd_down: no users! pid=%d\n", nlmsvc_pid);
-
-       if (!nlmsvc_pid) {
-               if (warned++ == 0)
-                       printk(KERN_WARNING "lockd_down: no lockd running.\n"); 
-               goto out;
+       } else {
+               printk(KERN_ERR "lockd_down: no users! task=%p\n",
+                       nlmsvc_task);
+               BUG();
        }
-       warned = 0;
 
-       kill_proc(nlmsvc_pid, SIGKILL, 1);
-       /*
-        * Wait for the lockd process to exit, but since we're holding
-        * the lockd semaphore, we can't wait around forever ...
-        */
-       clear_thread_flag(TIF_SIGPENDING);
-       interruptible_sleep_on_timeout(&lockd_exit, HZ);
-       if (nlmsvc_pid) {
-               printk(KERN_WARNING 
-                       "lockd_down: lockd failed to exit, clearing pid\n");
-               nlmsvc_pid = 0;
+       if (!nlmsvc_task) {
+               printk(KERN_ERR "lockd_down: no lockd running.\n");
+               BUG();
        }
-       spin_lock_irq(&current->sighand->siglock);
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+       kthread_stop(nlmsvc_task);
 out:
        mutex_unlock(&nlmsvc_mutex);
 }
 EXPORT_SYMBOL(lockd_down);
 
+#ifdef CONFIG_SYSCTL
+
 /*
  * Sysctl parameters (same as module parameters, different interface).
  */
@@ -443,6 +437,8 @@ static ctl_table nlm_sysctl_root[] = {
        { .ctl_name = 0 }
 };
 
+#endif /* CONFIG_SYSCTL */
+
 /*
  * Module (and sysfs) parameters.
  */
@@ -516,15 +512,21 @@ module_param(nsm_use_hostnames, bool, 0644);
 
 static int __init init_nlm(void)
 {
+#ifdef CONFIG_SYSCTL
        nlm_sysctl_table = register_sysctl_table(nlm_sysctl_root);
        return nlm_sysctl_table ? 0 : -ENOMEM;
+#else
+       return 0;
+#endif
 }
 
 static void __exit exit_nlm(void)
 {
        /* FIXME: delete all NLM clients */
        nlm_shutdown_hosts();
+#ifdef CONFIG_SYSCTL
        unregister_sysctl_table(nlm_sysctl_table);
+#endif
 }
 
 module_init(init_nlm);
index fe9bdb4a220cd32827c5818001651cabb5f1966d..1f122c1940afa069a6deb31f82103b990867136a 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/sunrpc/svc.h>
 #include <linux/lockd/nlm.h>
 #include <linux/lockd/lockd.h>
+#include <linux/kthread.h>
 
 #define NLMDBG_FACILITY                NLMDBG_SVCLOCK
 
@@ -226,8 +227,7 @@ failed:
 }
 
 /*
- * Delete a block. If the lock was cancelled or the grant callback
- * failed, unlock is set to 1.
+ * Delete a block.
  * It is the caller's responsibility to check whether the file
  * can be closed hereafter.
  */
@@ -887,7 +887,7 @@ nlmsvc_retry_blocked(void)
        unsigned long   timeout = MAX_SCHEDULE_TIMEOUT;
        struct nlm_block *block;
 
-       while (!list_empty(&nlm_blocked)) {
+       while (!list_empty(&nlm_blocked) && !kthread_should_stop()) {
                block = list_entry(nlm_blocked.next, struct nlm_block, b_list);
 
                if (block->b_when == NLM_NEVER)
index 068886de4dda19b176ab2340da64269c05d87da1..b0ae07008700c65de59ddb2404a51dd642c84aee 100644 (file)
@@ -71,7 +71,8 @@ nlmsvc_unshare_file(struct nlm_host *host, struct nlm_file *file,
        struct nlm_share        *share, **shpp;
        struct xdr_netobj       *oh = &argp->lock.oh;
 
-       for (shpp = &file->f_shares; (share = *shpp) != 0; shpp = &share->s_next) {
+       for (shpp = &file->f_shares; (share = *shpp) != NULL;
+                                       shpp = &share->s_next) {
                if (share->s_host == host && nlm_cmp_owner(share, oh)) {
                        *shpp = share->s_next;
                        kfree(share);
index df0f41e0988526fe8c8529fbfbe7f32e0b41c4eb..ac6170c594a37fadd988fd7027f84e66160f302d 100644 (file)
@@ -5,7 +5,7 @@
 obj-$(CONFIG_NFS_FS) += nfs.o
 
 nfs-y                  := client.o dir.o file.o getroot.o inode.o super.o nfs2xdr.o \
-                          pagelist.o proc.o read.o symlink.o unlink.o \
+                          direct.o pagelist.o proc.o read.o symlink.o unlink.o \
                           write.o namespace.o mount_clnt.o
 nfs-$(CONFIG_ROOT_NFS) += nfsroot.o
 nfs-$(CONFIG_NFS_V3)   += nfs3proc.o nfs3xdr.o
@@ -14,5 +14,4 @@ nfs-$(CONFIG_NFS_V4)  += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \
                           delegation.o idmap.o \
                           callback.o callback_xdr.o callback_proc.o \
                           nfs4namespace.o
-nfs-$(CONFIG_NFS_DIRECTIO) += direct.o
 nfs-$(CONFIG_SYSCTL) += sysctl.o
index 66648dd92d9731c2aa016cd82219d67268383958..5606ae3d72d377792bfd8689487389cc967315b5 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/nfs_fs.h>
 #include <linux/mutex.h>
 #include <linux/freezer.h>
+#include <linux/kthread.h>
 
 #include <net/inet_sock.h>
 
@@ -27,9 +28,7 @@
 struct nfs_callback_data {
        unsigned int users;
        struct svc_serv *serv;
-       pid_t pid;
-       struct completion started;
-       struct completion stopped;
+       struct task_struct *task;
 };
 
 static struct nfs_callback_data nfs_callback_info;
@@ -57,48 +56,44 @@ module_param_call(callback_tcpport, param_set_port, param_get_int,
 /*
  * This is the callback kernel thread.
  */
-static void nfs_callback_svc(struct svc_rqst *rqstp)
+static int
+nfs_callback_svc(void *vrqstp)
 {
-       int err;
+       int err, preverr = 0;
+       struct svc_rqst *rqstp = vrqstp;
 
-       __module_get(THIS_MODULE);
-       lock_kernel();
-
-       nfs_callback_info.pid = current->pid;
-       daemonize("nfsv4-svc");
-       /* Process request with signals blocked, but allow SIGKILL.  */
-       allow_signal(SIGKILL);
        set_freezable();
 
-       complete(&nfs_callback_info.started);
-
-       for(;;) {
-               if (signalled()) {
-                       if (nfs_callback_info.users == 0)
-                               break;
-                       flush_signals(current);
-               }
+       /*
+        * FIXME: do we really need to run this under the BKL? If so, please
+        * add a comment about what it's intended to protect.
+        */
+       lock_kernel();
+       while (!kthread_should_stop()) {
                /*
                 * Listen for a request on the socket
                 */
                err = svc_recv(rqstp, MAX_SCHEDULE_TIMEOUT);
-               if (err == -EAGAIN || err == -EINTR)
+               if (err == -EAGAIN || err == -EINTR) {
+                       preverr = err;
                        continue;
+               }
                if (err < 0) {
-                       printk(KERN_WARNING
-                                       "%s: terminating on error %d\n",
-                                       __FUNCTION__, -err);
-                       break;
+                       if (err != preverr) {
+                               printk(KERN_WARNING "%s: unexpected error "
+                                       "from svc_recv (%d)\n", __func__, err);
+                               preverr = err;
+                       }
+                       schedule_timeout_uninterruptible(HZ);
+                       continue;
                }
+               preverr = err;
                svc_process(rqstp);
        }
-
-       flush_signals(current);
-       svc_exit_thread(rqstp);
-       nfs_callback_info.pid = 0;
-       complete(&nfs_callback_info.stopped);
        unlock_kernel();
-       module_put_and_exit(0);
+       nfs_callback_info.task = NULL;
+       svc_exit_thread(rqstp);
+       return 0;
 }
 
 /*
@@ -107,14 +102,13 @@ static void nfs_callback_svc(struct svc_rqst *rqstp)
 int nfs_callback_up(void)
 {
        struct svc_serv *serv = NULL;
+       struct svc_rqst *rqstp;
        int ret = 0;
 
        lock_kernel();
        mutex_lock(&nfs_callback_mutex);
-       if (nfs_callback_info.users++ || nfs_callback_info.pid != 0)
+       if (nfs_callback_info.users++ || nfs_callback_info.task != NULL)
                goto out;
-       init_completion(&nfs_callback_info.started);
-       init_completion(&nfs_callback_info.stopped);
        serv = svc_create(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE, NULL);
        ret = -ENOMEM;
        if (!serv)
@@ -127,15 +121,28 @@ int nfs_callback_up(void)
        nfs_callback_tcpport = ret;
        dprintk("Callback port = 0x%x\n", nfs_callback_tcpport);
 
-       ret = svc_create_thread(nfs_callback_svc, serv);
-       if (ret < 0)
+       rqstp = svc_prepare_thread(serv, &serv->sv_pools[0]);
+       if (IS_ERR(rqstp)) {
+               ret = PTR_ERR(rqstp);
                goto out_err;
+       }
+
+       svc_sock_update_bufs(serv);
        nfs_callback_info.serv = serv;
-       wait_for_completion(&nfs_callback_info.started);
+
+       nfs_callback_info.task = kthread_run(nfs_callback_svc, rqstp,
+                                            "nfsv4-svc");
+       if (IS_ERR(nfs_callback_info.task)) {
+               ret = PTR_ERR(nfs_callback_info.task);
+               nfs_callback_info.serv = NULL;
+               nfs_callback_info.task = NULL;
+               svc_exit_thread(rqstp);
+               goto out_err;
+       }
 out:
        /*
         * svc_create creates the svc_serv with sv_nrthreads == 1, and then
-        * svc_create_thread increments that. So we need to call svc_destroy
+        * svc_prepare_thread increments that. So we need to call svc_destroy
         * on both success and failure so that the refcount is 1 when the
         * thread exits.
         */
@@ -152,19 +159,15 @@ out_err:
 }
 
 /*
- * Kill the server process if it is not already up.
+ * Kill the server process if it is not already down.
  */
 void nfs_callback_down(void)
 {
        lock_kernel();
        mutex_lock(&nfs_callback_mutex);
        nfs_callback_info.users--;
-       do {
-               if (nfs_callback_info.users != 0 || nfs_callback_info.pid == 0)
-                       break;
-               if (kill_proc(nfs_callback_info.pid, SIGKILL, 1) < 0)
-                       break;
-       } while (wait_for_completion_timeout(&nfs_callback_info.stopped, 5*HZ) == 0);
+       if (nfs_callback_info.users == 0 && nfs_callback_info.task != NULL)
+               kthread_stop(nfs_callback_info.task);
        mutex_unlock(&nfs_callback_mutex);
        unlock_kernel();
 }
index c5c0175898f68311f7a19c8c87e641de27acb30a..f2f3b284e6dd203a31c11032a195ecc9f6237f53 100644 (file)
@@ -112,6 +112,7 @@ struct nfs_client_initdata {
 static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init)
 {
        struct nfs_client *clp;
+       struct rpc_cred *cred;
 
        if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL)
                goto error_0;
@@ -150,6 +151,9 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
        clp->cl_boot_time = CURRENT_TIME;
        clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED;
 #endif
+       cred = rpc_lookup_machine_cred();
+       if (!IS_ERR(cred))
+               clp->cl_machine_cred = cred;
 
        return clp;
 
@@ -170,6 +174,8 @@ static void nfs4_shutdown_client(struct nfs_client *clp)
        BUG_ON(!RB_EMPTY_ROOT(&clp->cl_state_owners));
        if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state))
                nfs_idmap_delete(clp);
+
+       rpc_destroy_wait_queue(&clp->cl_rpcwaitq);
 #endif
 }
 
@@ -189,6 +195,9 @@ static void nfs_free_client(struct nfs_client *clp)
        if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state))
                nfs_callback_down();
 
+       if (clp->cl_machine_cred != NULL)
+               put_rpccred(clp->cl_machine_cred);
+
        kfree(clp->cl_hostname);
        kfree(clp);
 
@@ -680,10 +689,22 @@ static int nfs_init_server(struct nfs_server *server,
        if (error < 0)
                goto error;
 
+       server->port = data->nfs_server.port;
+
        error = nfs_init_server_rpcclient(server, &timeparms, data->auth_flavors[0]);
        if (error < 0)
                goto error;
 
+       /* Preserve the values of mount_server-related mount options */
+       if (data->mount_server.addrlen) {
+               memcpy(&server->mountd_address, &data->mount_server.address,
+                       data->mount_server.addrlen);
+               server->mountd_addrlen = data->mount_server.addrlen;
+       }
+       server->mountd_version = data->mount_server.version;
+       server->mountd_port = data->mount_server.port;
+       server->mountd_protocol = data->mount_server.protocol;
+
        server->namelen  = data->namlen;
        /* Create a client RPC handle for the NFSv3 ACL management interface */
        nfs_init_server_aclclient(server);
@@ -1062,6 +1083,8 @@ static int nfs4_init_server(struct nfs_server *server,
        server->acdirmin = data->acdirmin * HZ;
        server->acdirmax = data->acdirmax * HZ;
 
+       server->port = data->nfs_server.port;
+
        error = nfs_init_server_rpcclient(server, &timeparms, data->auth_flavors[0]);
 
 error:
index d9e30ac2798dc1d79ac46ad1a9b6b385252d4ab3..f288b3ecab4afad46334d311ac301f7a2e1e1fa4 100644 (file)
@@ -1967,7 +1967,7 @@ force_lookup:
        if (!NFS_PROTO(inode)->access)
                goto out_notsup;
 
-       cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0);
+       cred = rpc_lookup_cred();
        if (!IS_ERR(cred)) {
                res = nfs_do_access(inode, cred, mask);
                put_rpccred(cred);
index 16844f98f50e4b6f6ad24eea74470fb6da263adf..4757a2b326a1132d1e6e2d0d4401767eb06aa1d3 100644 (file)
@@ -229,14 +229,20 @@ static void nfs_direct_complete(struct nfs_direct_req *dreq)
 static void nfs_direct_read_result(struct rpc_task *task, void *calldata)
 {
        struct nfs_read_data *data = calldata;
-       struct nfs_direct_req *dreq = (struct nfs_direct_req *) data->req;
 
-       if (nfs_readpage_result(task, data) != 0)
-               return;
+       nfs_readpage_result(task, data);
+}
+
+static void nfs_direct_read_release(void *calldata)
+{
+
+       struct nfs_read_data *data = calldata;
+       struct nfs_direct_req *dreq = (struct nfs_direct_req *) data->req;
+       int status = data->task.tk_status;
 
        spin_lock(&dreq->lock);
-       if (unlikely(task->tk_status < 0)) {
-               dreq->error = task->tk_status;
+       if (unlikely(status < 0)) {
+               dreq->error = status;
                spin_unlock(&dreq->lock);
        } else {
                dreq->count += data->res.count;
@@ -249,11 +255,12 @@ static void nfs_direct_read_result(struct rpc_task *task, void *calldata)
 
        if (put_dreq(dreq))
                nfs_direct_complete(dreq);
+       nfs_readdata_release(calldata);
 }
 
 static const struct rpc_call_ops nfs_read_direct_ops = {
        .rpc_call_done = nfs_direct_read_result,
-       .rpc_release = nfs_readdata_release,
+       .rpc_release = nfs_direct_read_release,
 };
 
 /*
@@ -280,6 +287,7 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq,
                .rpc_client = NFS_CLIENT(inode),
                .rpc_message = &msg,
                .callback_ops = &nfs_read_direct_ops,
+               .workqueue = nfsiod_workqueue,
                .flags = RPC_TASK_ASYNC,
        };
        unsigned int pgbase;
@@ -323,7 +331,7 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq,
                data->inode = inode;
                data->cred = msg.rpc_cred;
                data->args.fh = NFS_FH(inode);
-               data->args.context = ctx;
+               data->args.context = get_nfs_open_context(ctx);
                data->args.offset = pos;
                data->args.pgbase = pgbase;
                data->args.pages = data->pagevec;
@@ -339,8 +347,9 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq,
                NFS_PROTO(inode)->read_setup(data, &msg);
 
                task = rpc_run_task(&task_setup_data);
-               if (!IS_ERR(task))
-                       rpc_put_task(task);
+               if (IS_ERR(task))
+                       break;
+               rpc_put_task(task);
 
                dprintk("NFS: %5u initiated direct read call "
                        "(req %s/%Ld, %zu bytes @ offset %Lu)\n",
@@ -446,6 +455,7 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq)
        struct rpc_task_setup task_setup_data = {
                .rpc_client = NFS_CLIENT(inode),
                .callback_ops = &nfs_write_direct_ops,
+               .workqueue = nfsiod_workqueue,
                .flags = RPC_TASK_ASYNC,
        };
 
@@ -499,27 +509,34 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq)
 static void nfs_direct_commit_result(struct rpc_task *task, void *calldata)
 {
        struct nfs_write_data *data = calldata;
-       struct nfs_direct_req *dreq = (struct nfs_direct_req *) data->req;
 
        /* Call the NFS version-specific code */
-       if (NFS_PROTO(data->inode)->commit_done(task, data) != 0)
-               return;
-       if (unlikely(task->tk_status < 0)) {
+       NFS_PROTO(data->inode)->commit_done(task, data);
+}
+
+static void nfs_direct_commit_release(void *calldata)
+{
+       struct nfs_write_data *data = calldata;
+       struct nfs_direct_req *dreq = (struct nfs_direct_req *) data->req;
+       int status = data->task.tk_status;
+
+       if (status < 0) {
                dprintk("NFS: %5u commit failed with error %d.\n",
-                               task->tk_pid, task->tk_status);
+                               data->task.tk_pid, status);
                dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
        } else if (memcmp(&dreq->verf, &data->verf, sizeof(data->verf))) {
-               dprintk("NFS: %5u commit verify failed\n", task->tk_pid);
+               dprintk("NFS: %5u commit verify failed\n", data->task.tk_pid);
                dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
        }
 
-       dprintk("NFS: %5u commit returned %d\n", task->tk_pid, task->tk_status);
+       dprintk("NFS: %5u commit returned %d\n", data->task.tk_pid, status);
        nfs_direct_write_complete(dreq, data->inode);
+       nfs_commitdata_release(calldata);
 }
 
 static const struct rpc_call_ops nfs_commit_direct_ops = {
        .rpc_call_done = nfs_direct_commit_result,
-       .rpc_release = nfs_commit_release,
+       .rpc_release = nfs_direct_commit_release,
 };
 
 static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq)
@@ -537,6 +554,7 @@ static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq)
                .rpc_message = &msg,
                .callback_ops = &nfs_commit_direct_ops,
                .callback_data = data,
+               .workqueue = nfsiod_workqueue,
                .flags = RPC_TASK_ASYNC,
        };
 
@@ -546,6 +564,7 @@ static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq)
        data->args.fh = NFS_FH(data->inode);
        data->args.offset = 0;
        data->args.count = 0;
+       data->args.context = get_nfs_open_context(dreq->ctx);
        data->res.count = 0;
        data->res.fattr = &data->fattr;
        data->res.verf = &data->verf;
@@ -585,7 +604,7 @@ static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode
 
 static void nfs_alloc_commit_data(struct nfs_direct_req *dreq)
 {
-       dreq->commit_data = nfs_commit_alloc();
+       dreq->commit_data = nfs_commitdata_alloc();
        if (dreq->commit_data != NULL)
                dreq->commit_data->req = (struct nfs_page *) dreq;
 }
@@ -606,11 +625,20 @@ static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode
 static void nfs_direct_write_result(struct rpc_task *task, void *calldata)
 {
        struct nfs_write_data *data = calldata;
-       struct nfs_direct_req *dreq = (struct nfs_direct_req *) data->req;
-       int status = task->tk_status;
 
        if (nfs_writeback_done(task, data) != 0)
                return;
+}
+
+/*
+ * NB: Return the value of the first error return code.  Subsequent
+ *     errors after the first one are ignored.
+ */
+static void nfs_direct_write_release(void *calldata)
+{
+       struct nfs_write_data *data = calldata;
+       struct nfs_direct_req *dreq = (struct nfs_direct_req *) data->req;
+       int status = data->task.tk_status;
 
        spin_lock(&dreq->lock);
 
@@ -632,23 +660,13 @@ static void nfs_direct_write_result(struct rpc_task *task, void *calldata)
                                break;
                        case NFS_ODIRECT_DO_COMMIT:
                                if (memcmp(&dreq->verf, &data->verf, sizeof(dreq->verf))) {
-                                       dprintk("NFS: %5u write verify failed\n", task->tk_pid);
+                                       dprintk("NFS: %5u write verify failed\n", data->task.tk_pid);
                                        dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
                                }
                }
        }
 out_unlock:
        spin_unlock(&dreq->lock);
-}
-
-/*
- * NB: Return the value of the first error return code.  Subsequent
- *     errors after the first one are ignored.
- */
-static void nfs_direct_write_release(void *calldata)
-{
-       struct nfs_write_data *data = calldata;
-       struct nfs_direct_req *dreq = (struct nfs_direct_req *) data->req;
 
        if (put_dreq(dreq))
                nfs_direct_write_complete(dreq, data->inode);
@@ -682,6 +700,7 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq,
                .rpc_client = NFS_CLIENT(inode),
                .rpc_message = &msg,
                .callback_ops = &nfs_write_direct_ops,
+               .workqueue = nfsiod_workqueue,
                .flags = RPC_TASK_ASYNC,
        };
        size_t wsize = NFS_SERVER(inode)->wsize;
@@ -728,7 +747,7 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq,
                data->inode = inode;
                data->cred = msg.rpc_cred;
                data->args.fh = NFS_FH(inode);
-               data->args.context = ctx;
+               data->args.context = get_nfs_open_context(ctx);
                data->args.offset = pos;
                data->args.pgbase = pgbase;
                data->args.pages = data->pagevec;
@@ -745,8 +764,9 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq,
                NFS_PROTO(inode)->write_setup(data, &msg);
 
                task = rpc_run_task(&task_setup_data);
-               if (!IS_ERR(task))
-                       rpc_put_task(task);
+               if (IS_ERR(task))
+                       break;
+               rpc_put_task(task);
 
                dprintk("NFS: %5u initiated direct write call "
                        "(req %s/%Ld, %zu bytes @ offset %Lu)\n",
index 5d2e9d9a4e28a390c15fd10a0c856baf2fe89058..3536b01164f9ca036aa102ee5211d670273f26df 100644 (file)
@@ -238,10 +238,8 @@ nfs_file_read(struct kiocb *iocb, const struct iovec *iov,
        ssize_t result;
        size_t count = iov_length(iov, nr_segs);
 
-#ifdef CONFIG_NFS_DIRECTIO
        if (iocb->ki_filp->f_flags & O_DIRECT)
                return nfs_file_direct_read(iocb, iov, nr_segs, pos);
-#endif
 
        dfprintk(VFS, "nfs: read(%s/%s, %lu@%lu)\n",
                dentry->d_parent->d_name.name, dentry->d_name.name,
@@ -387,9 +385,7 @@ const struct address_space_operations nfs_file_aops = {
        .write_end = nfs_write_end,
        .invalidatepage = nfs_invalidate_page,
        .releasepage = nfs_release_page,
-#ifdef CONFIG_NFS_DIRECTIO
        .direct_IO = nfs_direct_IO,
-#endif
        .launder_page = nfs_launder_page,
 };
 
@@ -447,10 +443,8 @@ static ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov,
        ssize_t result;
        size_t count = iov_length(iov, nr_segs);
 
-#ifdef CONFIG_NFS_DIRECTIO
        if (iocb->ki_filp->f_flags & O_DIRECT)
                return nfs_file_direct_write(iocb, iov, nr_segs, pos);
-#endif
 
        dfprintk(VFS, "nfs: write(%s/%s(%ld), %lu@%Ld)\n",
                dentry->d_parent->d_name.name, dentry->d_name.name,
@@ -576,17 +570,9 @@ static int do_setlk(struct file *filp, int cmd, struct file_lock *fl)
 
        lock_kernel();
        /* Use local locking if mounted with "-onolock" */
-       if (!(NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM)) {
+       if (!(NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM))
                status = NFS_PROTO(inode)->lock(filp, cmd, fl);
-               /* If we were signalled we still need to ensure that
-                * we clean up any state on the server. We therefore
-                * record the lock call as having succeeded in order to
-                * ensure that locks_remove_posix() cleans it out when
-                * the process exits.
-                */
-               if (status == -EINTR || status == -ERESTARTSYS)
-                       do_vfs_lock(filp, fl);
-       } else
+       else
                status = do_vfs_lock(filp, fl);
        unlock_kernel();
        if (status < 0)
index 6f88d7c77ac98e1b4bdb5a8f0b347227c271d5ac..5cb3345eb6940a7532457f447d7ea77d89b86113 100644 (file)
@@ -523,8 +523,12 @@ struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx)
 
 static void __put_nfs_open_context(struct nfs_open_context *ctx, int wait)
 {
-       struct inode *inode = ctx->path.dentry->d_inode;
+       struct inode *inode;
 
+       if (ctx == NULL)
+               return;
+
+       inode = ctx->path.dentry->d_inode;
        if (!atomic_dec_and_lock(&ctx->count, &inode->i_lock))
                return;
        list_del(&ctx->list);
@@ -610,7 +614,7 @@ int nfs_open(struct inode *inode, struct file *filp)
        struct nfs_open_context *ctx;
        struct rpc_cred *cred;
 
-       cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0);
+       cred = rpc_lookup_cred();
        if (IS_ERR(cred))
                return PTR_ERR(cred);
        ctx = alloc_nfs_open_context(filp->f_path.mnt, filp->f_path.dentry, cred);
@@ -1218,6 +1222,36 @@ static void nfs_destroy_inodecache(void)
        kmem_cache_destroy(nfs_inode_cachep);
 }
 
+struct workqueue_struct *nfsiod_workqueue;
+
+/*
+ * start up the nfsiod workqueue
+ */
+static int nfsiod_start(void)
+{
+       struct workqueue_struct *wq;
+       dprintk("RPC:       creating workqueue nfsiod\n");
+       wq = create_singlethread_workqueue("nfsiod");
+       if (wq == NULL)
+               return -ENOMEM;
+       nfsiod_workqueue = wq;
+       return 0;
+}
+
+/*
+ * Destroy the nfsiod workqueue
+ */
+static void nfsiod_stop(void)
+{
+       struct workqueue_struct *wq;
+
+       wq = nfsiod_workqueue;
+       if (wq == NULL)
+               return;
+       nfsiod_workqueue = NULL;
+       destroy_workqueue(wq);
+}
+
 /*
  * Initialize NFS
  */
@@ -1225,6 +1259,10 @@ static int __init init_nfs_fs(void)
 {
        int err;
 
+       err = nfsiod_start();
+       if (err)
+               goto out6;
+
        err = nfs_fs_proc_init();
        if (err)
                goto out5;
@@ -1271,6 +1309,8 @@ out3:
 out4:
        nfs_fs_proc_exit();
 out5:
+       nfsiod_stop();
+out6:
        return err;
 }
 
@@ -1286,6 +1326,7 @@ static void __exit exit_nfs_fs(void)
 #endif
        unregister_nfs_fs();
        nfs_fs_proc_exit();
+       nfsiod_stop();
 }
 
 /* Not quite true; I just maintain it */
index 931992763e68c2e68f7e1f3501de25a8340dc50b..04ae867dddba43a8267cb09771f07f057fa7ab59 100644 (file)
@@ -46,9 +46,9 @@ struct nfs_parsed_mount_data {
                struct sockaddr_storage address;
                size_t                  addrlen;
                char                    *hostname;
-               unsigned int            version;
+               u32                     version;
                unsigned short          port;
-               int                     protocol;
+               unsigned short          protocol;
        } mount_server;
 
        struct {
@@ -56,7 +56,8 @@ struct nfs_parsed_mount_data {
                size_t                  addrlen;
                char                    *hostname;
                char                    *export_path;
-               int                     protocol;
+               unsigned short          port;
+               unsigned short          protocol;
        } nfs_server;
 
        struct security_mnt_opts lsm_opts;
@@ -115,13 +116,8 @@ extern void nfs_destroy_readpagecache(void);
 extern int __init nfs_init_writepagecache(void);
 extern void nfs_destroy_writepagecache(void);
 
-#ifdef CONFIG_NFS_DIRECTIO
 extern int __init nfs_init_directcache(void);
 extern void nfs_destroy_directcache(void);
-#else
-#define nfs_init_directcache() (0)
-#define nfs_destroy_directcache() do {} while(0)
-#endif
 
 /* nfs2xdr.c */
 extern int nfs_stat_to_errno(int);
@@ -146,6 +142,7 @@ extern struct rpc_procinfo nfs4_procedures[];
 extern int nfs_access_cache_shrinker(int nr_to_scan, gfp_t gfp_mask);
 
 /* inode.c */
+extern struct workqueue_struct *nfsiod_workqueue;
 extern struct inode *nfs_alloc_inode(struct super_block *sb);
 extern void nfs_destroy_inode(struct inode *);
 extern int nfs_write_inode(struct inode *,int);
index 607f6eb9cdb519f549ce19e590470d24e52ed90e..af4d0f1e402cdc79696bbb96343ca004a4dd7a43 100644 (file)
@@ -20,7 +20,7 @@
 
 static void nfs_expire_automounts(struct work_struct *work);
 
-LIST_HEAD(nfs_automount_list);
+static LIST_HEAD(nfs_automount_list);
 static DECLARE_DELAYED_WORK(nfs_automount_task, nfs_expire_automounts);
 int nfs_mountpoint_expiry_timeout = 500 * HZ;
 
index 1f7ea675e0c5e9489d8316b60969d159f386d8ab..28bab67d1519bc23b1db1d190713e7971fe79d94 100644 (file)
@@ -267,7 +267,7 @@ nfs_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res)
        int status;
 
        if ((status = ntohl(*p++)))
-               return -nfs_stat_to_errno(status);
+               return nfs_stat_to_errno(status);
        p = xdr_decode_fattr(p, res->fattr);
 
        count = ntohl(*p++);
@@ -428,11 +428,11 @@ nfs_xdr_readdirres(struct rpc_rqst *req, __be32 *p, void *dummy)
        size_t hdrlen;
        unsigned int pglen, recvd;
        u32 len;
-       int status, nr;
+       int status, nr = 0;
        __be32 *end, *entry, *kaddr;
 
        if ((status = ntohl(*p++)))
-               return -nfs_stat_to_errno(status);
+               return nfs_stat_to_errno(status);
 
        hdrlen = (u8 *) p - (u8 *) iov->iov_base;
        if (iov->iov_len < hdrlen) {
@@ -452,7 +452,12 @@ nfs_xdr_readdirres(struct rpc_rqst *req, __be32 *p, void *dummy)
        kaddr = p = kmap_atomic(*page, KM_USER0);
        end = (__be32 *)((char *)p + pglen);
        entry = p;
-       for (nr = 0; *p++; nr++) {
+
+       /* Make sure the packet actually has a value_follows and EOF entry */
+       if ((entry + 1) > end)
+               goto short_pkt;
+
+       for (; *p++; nr++) {
                if (p + 2 > end)
                        goto short_pkt;
                p++; /* fileid */
@@ -467,18 +472,32 @@ nfs_xdr_readdirres(struct rpc_rqst *req, __be32 *p, void *dummy)
                        goto short_pkt;
                entry = p;
        }
-       if (!nr && (entry[0] != 0 || entry[1] == 0))
-               goto short_pkt;
+
+       /*
+        * Apparently some server sends responses that are a valid size, but
+        * contain no entries, and have value_follows==0 and EOF==0. For
+        * those, just set the EOF marker.
+        */
+       if (!nr && entry[1] == 0) {
+               dprintk("NFS: readdir reply truncated!\n");
+               entry[1] = 1;
+       }
  out:
        kunmap_atomic(kaddr, KM_USER0);
        return nr;
  short_pkt:
+       /*
+        * When we get a short packet there are 2 possibilities. We can
+        * return an error, or fix up the response to look like a valid
+        * response and return what we have so far. If there are no
+        * entries and the packet was short, then return -EIO. If there
+        * are valid entries in the response, return them and pretend that
+        * the call was successful, but incomplete. The caller can retry the
+        * readdir starting at the last cookie.
+        */
        entry[0] = entry[1] = 0;
-       /* truncate listing ? */
-       if (!nr) {
-               dprintk("NFS: readdir reply truncated!\n");
-               entry[1] = 1;
-       }
+       if (!nr)
+               nr = -errno_NFSERR_IO;
        goto out;
 err_unmap:
        nr = -errno_NFSERR_IO;
@@ -518,7 +537,7 @@ nfs_xdr_stat(struct rpc_rqst *req, __be32 *p, void *dummy)
        int     status;
 
        if ((status = ntohl(*p++)) != 0)
-               status = -nfs_stat_to_errno(status);
+               status = nfs_stat_to_errno(status);
        return status;
 }
 
@@ -532,7 +551,7 @@ nfs_xdr_attrstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
        int     status;
 
        if ((status = ntohl(*p++)))
-               return -nfs_stat_to_errno(status);
+               return nfs_stat_to_errno(status);
        xdr_decode_fattr(p, fattr);
        return 0;
 }
@@ -547,7 +566,7 @@ nfs_xdr_diropres(struct rpc_rqst *req, __be32 *p, struct nfs_diropok *res)
        int     status;
 
        if ((status = ntohl(*p++)))
-               return -nfs_stat_to_errno(status);
+               return nfs_stat_to_errno(status);
        p = xdr_decode_fhandle(p, res->fh);
        xdr_decode_fattr(p, res->fattr);
        return 0;
@@ -585,7 +604,7 @@ nfs_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, void *dummy)
        int     status;
 
        if ((status = ntohl(*p++)))
-               return -nfs_stat_to_errno(status);
+               return nfs_stat_to_errno(status);
        /* Convert length of symlink */
        len = ntohl(*p++);
        if (len >= rcvbuf->page_len) {
@@ -634,7 +653,7 @@ nfs_xdr_statfsres(struct rpc_rqst *req, __be32 *p, struct nfs2_fsstat *res)
        int     status;
 
        if ((status = ntohl(*p++)))
-               return -nfs_stat_to_errno(status);
+               return nfs_stat_to_errno(status);
 
        res->tsize  = ntohl(*p++);
        res->bsize  = ntohl(*p++);
@@ -653,39 +672,39 @@ static struct {
        int errno;
 } nfs_errtbl[] = {
        { NFS_OK,               0               },
-       { NFSERR_PERM,          EPERM           },
-       { NFSERR_NOENT,         ENOENT          },
-       { NFSERR_IO,            errno_NFSERR_IO },
-       { NFSERR_NXIO,          ENXIO           },
-/*     { NFSERR_EAGAIN,        EAGAIN          }, */
-       { NFSERR_ACCES,         EACCES          },
-       { NFSERR_EXIST,         EEXIST          },
-       { NFSERR_XDEV,          EXDEV           },
-       { NFSERR_NODEV,         ENODEV          },
-       { NFSERR_NOTDIR,        ENOTDIR         },
-       { NFSERR_ISDIR,         EISDIR          },
-       { NFSERR_INVAL,         EINVAL          },
-       { NFSERR_FBIG,          EFBIG           },
-       { NFSERR_NOSPC,         ENOSPC          },
-       { NFSERR_ROFS,          EROFS           },
-       { NFSERR_MLINK,         EMLINK          },
-       { NFSERR_NAMETOOLONG,   ENAMETOOLONG    },
-       { NFSERR_NOTEMPTY,      ENOTEMPTY       },
-       { NFSERR_DQUOT,         EDQUOT          },
-       { NFSERR_STALE,         ESTALE          },
-       { NFSERR_REMOTE,        EREMOTE         },
+       { NFSERR_PERM,          -EPERM          },
+       { NFSERR_NOENT,         -ENOENT         },
+       { NFSERR_IO,            -errno_NFSERR_IO},
+       { NFSERR_NXIO,          -ENXIO          },
+/*     { NFSERR_EAGAIN,        -EAGAIN         }, */
+       { NFSERR_ACCES,         -EACCES         },
+       { NFSERR_EXIST,         -EEXIST         },
+       { NFSERR_XDEV,          -EXDEV          },
+       { NFSERR_NODEV,         -ENODEV         },
+       { NFSERR_NOTDIR,        -ENOTDIR        },
+       { NFSERR_ISDIR,         -EISDIR         },
+       { NFSERR_INVAL,         -EINVAL         },
+       { NFSERR_FBIG,          -EFBIG          },
+       { NFSERR_NOSPC,         -ENOSPC         },
+       { NFSERR_ROFS,          -EROFS          },
+       { NFSERR_MLINK,         -EMLINK         },
+       { NFSERR_NAMETOOLONG,   -ENAMETOOLONG   },
+       { NFSERR_NOTEMPTY,      -ENOTEMPTY      },
+       { NFSERR_DQUOT,         -EDQUOT         },
+       { NFSERR_STALE,         -ESTALE         },
+       { NFSERR_REMOTE,        -EREMOTE        },
 #ifdef EWFLUSH
-       { NFSERR_WFLUSH,        EWFLUSH         },
+       { NFSERR_WFLUSH,        -EWFLUSH        },
 #endif
-       { NFSERR_BADHANDLE,     EBADHANDLE      },
-       { NFSERR_NOT_SYNC,      ENOTSYNC        },
-       { NFSERR_BAD_COOKIE,    EBADCOOKIE      },
-       { NFSERR_NOTSUPP,       ENOTSUPP        },
-       { NFSERR_TOOSMALL,      ETOOSMALL       },
-       { NFSERR_SERVERFAULT,   ESERVERFAULT    },
-       { NFSERR_BADTYPE,       EBADTYPE        },
-       { NFSERR_JUKEBOX,       EJUKEBOX        },
-       { -1,                   EIO             }
+       { NFSERR_BADHANDLE,     -EBADHANDLE     },
+       { NFSERR_NOT_SYNC,      -ENOTSYNC       },
+       { NFSERR_BAD_COOKIE,    -EBADCOOKIE     },
+       { NFSERR_NOTSUPP,       -ENOTSUPP       },
+       { NFSERR_TOOSMALL,      -ETOOSMALL      },
+       { NFSERR_SERVERFAULT,   -ESERVERFAULT   },
+       { NFSERR_BADTYPE,       -EBADTYPE       },
+       { NFSERR_JUKEBOX,       -EJUKEBOX       },
+       { -1,                   -EIO            }
 };
 
 /*
index 3917e2fa4e40f3e1a18c12bee149c576847d4b5f..11cdddec1432cfae1199aa2f89257ce00dd033d1 100644 (file)
@@ -508,14 +508,14 @@ nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res
        struct page **page;
        size_t hdrlen;
        u32 len, recvd, pglen;
-       int status, nr;
+       int status, nr = 0;
        __be32 *entry, *end, *kaddr;
 
        status = ntohl(*p++);
        /* Decode post_op_attrs */
        p = xdr_decode_post_op_attr(p, res->dir_attr);
        if (status)
-               return -nfs_stat_to_errno(status);
+               return nfs_stat_to_errno(status);
        /* Decode verifier cookie */
        if (res->verf) {
                res->verf[0] = *p++;
@@ -542,7 +542,12 @@ nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res
        kaddr = p = kmap_atomic(*page, KM_USER0);
        end = (__be32 *)((char *)p + pglen);
        entry = p;
-       for (nr = 0; *p++; nr++) {
+
+       /* Make sure the packet actually has a value_follows and EOF entry */
+       if ((entry + 1) > end)
+               goto short_pkt;
+
+       for (; *p++; nr++) {
                if (p + 3 > end)
                        goto short_pkt;
                p += 2;                         /* inode # */
@@ -581,18 +586,32 @@ nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res
                        goto short_pkt;
                entry = p;
        }
-       if (!nr && (entry[0] != 0 || entry[1] == 0))
-               goto short_pkt;
+
+       /*
+        * Apparently some server sends responses that are a valid size, but
+        * contain no entries, and have value_follows==0 and EOF==0. For
+        * those, just set the EOF marker.
+        */
+       if (!nr && entry[1] == 0) {
+               dprintk("NFS: readdir reply truncated!\n");
+               entry[1] = 1;
+       }
  out:
        kunmap_atomic(kaddr, KM_USER0);
        return nr;
  short_pkt:
+       /*
+        * When we get a short packet there are 2 possibilities. We can
+        * return an error, or fix up the response to look like a valid
+        * response and return what we have so far. If there are no
+        * entries and the packet was short, then return -EIO. If there
+        * are valid entries in the response, return them and pretend that
+        * the call was successful, but incomplete. The caller can retry the
+        * readdir starting at the last cookie.
+        */
        entry[0] = entry[1] = 0;
-       /* truncate listing ? */
-       if (!nr) {
-               dprintk("NFS: readdir reply truncated!\n");
-               entry[1] = 1;
-       }
+       if (!nr)
+               nr = -errno_NFSERR_IO;
        goto out;
 err_unmap:
        nr = -errno_NFSERR_IO;
@@ -732,7 +751,7 @@ nfs3_xdr_attrstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
        int     status;
 
        if ((status = ntohl(*p++)))
-               return -nfs_stat_to_errno(status);
+               return nfs_stat_to_errno(status);
        xdr_decode_fattr(p, fattr);
        return 0;
 }
@@ -747,7 +766,7 @@ nfs3_xdr_wccstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
        int     status;
 
        if ((status = ntohl(*p++)))
-               status = -nfs_stat_to_errno(status);
+               status = nfs_stat_to_errno(status);
        xdr_decode_wcc_data(p, fattr);
        return status;
 }
@@ -767,7 +786,7 @@ nfs3_xdr_lookupres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res)
        int     status;
 
        if ((status = ntohl(*p++))) {
-               status = -nfs_stat_to_errno(status);
+               status = nfs_stat_to_errno(status);
        } else {
                if (!(p = xdr_decode_fhandle(p, res->fh)))
                        return -errno_NFSERR_IO;
@@ -787,7 +806,7 @@ nfs3_xdr_accessres(struct rpc_rqst *req, __be32 *p, struct nfs3_accessres *res)
 
        p = xdr_decode_post_op_attr(p, res->fattr);
        if (status)
-               return -nfs_stat_to_errno(status);
+               return nfs_stat_to_errno(status);
        res->access = ntohl(*p++);
        return 0;
 }
@@ -824,7 +843,7 @@ nfs3_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
        p = xdr_decode_post_op_attr(p, fattr);
 
        if (status != 0)
-               return -nfs_stat_to_errno(status);
+               return nfs_stat_to_errno(status);
 
        /* Convert length of symlink */
        len = ntohl(*p++);
@@ -872,7 +891,7 @@ nfs3_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res)
        p = xdr_decode_post_op_attr(p, res->fattr);
 
        if (status != 0)
-               return -nfs_stat_to_errno(status);
+               return nfs_stat_to_errno(status);
 
        /* Decode reply count and EOF flag. NFSv3 is somewhat redundant
         * in that it puts the count both in the res struct and in the
@@ -922,7 +941,7 @@ nfs3_xdr_writeres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res)
        p = xdr_decode_wcc_data(p, res->fattr);
 
        if (status != 0)
-               return -nfs_stat_to_errno(status);
+               return nfs_stat_to_errno(status);
 
        res->count = ntohl(*p++);
        res->verf->committed = (enum nfs3_stable_how)ntohl(*p++);
@@ -953,7 +972,7 @@ nfs3_xdr_createres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res)
                        res->fattr->valid = 0;
                }
        } else {
-               status = -nfs_stat_to_errno(status);
+               status = nfs_stat_to_errno(status);
        }
        p = xdr_decode_wcc_data(p, res->dir_attr);
        return status;
@@ -968,7 +987,7 @@ nfs3_xdr_renameres(struct rpc_rqst *req, __be32 *p, struct nfs3_renameres *res)
        int     status;
 
        if ((status = ntohl(*p++)) != 0)
-               status = -nfs_stat_to_errno(status);
+               status = nfs_stat_to_errno(status);
        p = xdr_decode_wcc_data(p, res->fromattr);
        p = xdr_decode_wcc_data(p, res->toattr);
        return status;
@@ -983,7 +1002,7 @@ nfs3_xdr_linkres(struct rpc_rqst *req, __be32 *p, struct nfs3_linkres *res)
        int     status;
 
        if ((status = ntohl(*p++)) != 0)
-               status = -nfs_stat_to_errno(status);
+               status = nfs_stat_to_errno(status);
        p = xdr_decode_post_op_attr(p, res->fattr);
        p = xdr_decode_wcc_data(p, res->dir_attr);
        return status;
@@ -1001,7 +1020,7 @@ nfs3_xdr_fsstatres(struct rpc_rqst *req, __be32 *p, struct nfs_fsstat *res)
 
        p = xdr_decode_post_op_attr(p, res->fattr);
        if (status != 0)
-               return -nfs_stat_to_errno(status);
+               return nfs_stat_to_errno(status);
 
        p = xdr_decode_hyper(p, &res->tbytes);
        p = xdr_decode_hyper(p, &res->fbytes);
@@ -1026,7 +1045,7 @@ nfs3_xdr_fsinfores(struct rpc_rqst *req, __be32 *p, struct nfs_fsinfo *res)
 
        p = xdr_decode_post_op_attr(p, res->fattr);
        if (status != 0)
-               return -nfs_stat_to_errno(status);
+               return nfs_stat_to_errno(status);
 
        res->rtmax  = ntohl(*p++);
        res->rtpref = ntohl(*p++);
@@ -1054,7 +1073,7 @@ nfs3_xdr_pathconfres(struct rpc_rqst *req, __be32 *p, struct nfs_pathconf *res)
 
        p = xdr_decode_post_op_attr(p, res->fattr);
        if (status != 0)
-               return -nfs_stat_to_errno(status);
+               return nfs_stat_to_errno(status);
        res->max_link = ntohl(*p++);
        res->max_namelen = ntohl(*p++);
 
@@ -1073,7 +1092,7 @@ nfs3_xdr_commitres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res)
        status = ntohl(*p++);
        p = xdr_decode_wcc_data(p, res->fattr);
        if (status != 0)
-               return -nfs_stat_to_errno(status);
+               return nfs_stat_to_errno(status);
 
        res->verf->verifier[0] = *p++;
        res->verf->verifier[1] = *p++;
@@ -1095,7 +1114,7 @@ nfs3_xdr_getaclres(struct rpc_rqst *req, __be32 *p,
        int err, base;
 
        if (status != 0)
-               return -nfs_stat_to_errno(status);
+               return nfs_stat_to_errno(status);
        p = xdr_decode_post_op_attr(p, res->fattr);
        res->mask = ntohl(*p++);
        if (res->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
@@ -1122,7 +1141,7 @@ nfs3_xdr_setaclres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
        int status = ntohl(*p++);
 
        if (status)
-               return -nfs_stat_to_errno(status);
+               return nfs_stat_to_errno(status);
        xdr_decode_post_op_attr(p, fattr);
        return 0;
 }
index 7ce07862c2fbcd825f03a2041675e6ae66b43b7a..dbc09271af027f9d48b316e5a987c85aca79788e 100644 (file)
@@ -51,6 +51,7 @@
 
 #include "nfs4_fs.h"
 #include "delegation.h"
+#include "internal.h"
 #include "iostat.h"
 
 #define NFSDBG_FACILITY                NFSDBG_PROC
@@ -239,6 +240,8 @@ static void nfs4_init_opendata_res(struct nfs4_opendata *p)
 {
        p->o_res.f_attr = &p->f_attr;
        p->o_res.dir_attr = &p->dir_attr;
+       p->o_res.seqid = p->o_arg.seqid;
+       p->c_res.seqid = p->c_arg.seqid;
        p->o_res.server = p->o_arg.server;
        nfs_fattr_init(&p->f_attr);
        nfs_fattr_init(&p->dir_attr);
@@ -729,7 +732,6 @@ static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata)
                renew_lease(data->o_res.server, data->timestamp);
                data->rpc_done = 1;
        }
-       nfs_increment_open_seqid(data->rpc_status, data->c_arg.seqid);
 }
 
 static void nfs4_open_confirm_release(void *calldata)
@@ -773,6 +775,7 @@ static int _nfs4_proc_open_confirm(struct nfs4_opendata *data)
                .rpc_message = &msg,
                .callback_ops = &nfs4_open_confirm_ops,
                .callback_data = data,
+               .workqueue = nfsiod_workqueue,
                .flags = RPC_TASK_ASYNC,
        };
        int status;
@@ -858,7 +861,6 @@ static void nfs4_open_done(struct rpc_task *task, void *calldata)
                if (!(data->o_res.rflags & NFS4_OPEN_RESULT_CONFIRM))
                        nfs_confirm_seqid(&data->owner->so_seqid, 0);
        }
-       nfs_increment_open_seqid(data->rpc_status, data->o_arg.seqid);
        data->rpc_done = 1;
 }
 
@@ -910,6 +912,7 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
                .rpc_message = &msg,
                .callback_ops = &nfs4_open_ops,
                .callback_data = data,
+               .workqueue = nfsiod_workqueue,
                .flags = RPC_TASK_ASYNC,
        };
        int status;
@@ -979,11 +982,8 @@ static int _nfs4_open_expired(struct nfs_open_context *ctx, struct nfs4_state *s
        if (IS_ERR(opendata))
                return PTR_ERR(opendata);
        ret = nfs4_open_recover(opendata, state);
-       if (ret == -ESTALE) {
-               /* Invalidate the state owner so we don't ever use it again */
-               nfs4_drop_state_owner(state->owner);
+       if (ret == -ESTALE)
                d_drop(ctx->path.dentry);
-       }
        nfs4_opendata_put(opendata);
        return ret;
 }
@@ -1226,7 +1226,6 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
         /* hmm. we are done with the inode, and in the process of freeing
         * the state_owner. we keep this around to process errors
         */
-       nfs_increment_open_seqid(task->tk_status, calldata->arg.seqid);
        switch (task->tk_status) {
                case 0:
                        nfs_set_open_stateid(state, &calldata->res.stateid, 0);
@@ -1315,6 +1314,7 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait)
                .rpc_client = server->client,
                .rpc_message = &msg,
                .callback_ops = &nfs4_close_ops,
+               .workqueue = nfsiod_workqueue,
                .flags = RPC_TASK_ASYNC,
        };
        int status = -ENOMEM;
@@ -1332,6 +1332,7 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait)
                goto out_free_calldata;
        calldata->arg.bitmask = server->attr_bitmask;
        calldata->res.fattr = &calldata->fattr;
+       calldata->res.seqid = calldata->arg.seqid;
        calldata->res.server = server;
        calldata->path.mnt = mntget(path->mnt);
        calldata->path.dentry = dget(path->dentry);
@@ -1404,7 +1405,7 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
                BUG_ON(nd->intent.open.flags & O_CREAT);
        }
 
-       cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0);
+       cred = rpc_lookup_cred();
        if (IS_ERR(cred))
                return (struct dentry *)cred;
        parent = dentry->d_parent;
@@ -1439,7 +1440,7 @@ nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, st
        struct rpc_cred *cred;
        struct nfs4_state *state;
 
-       cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0);
+       cred = rpc_lookup_cred();
        if (IS_ERR(cred))
                return PTR_ERR(cred);
        state = nfs4_do_open(dir, &path, openflags, NULL, cred);
@@ -1656,7 +1657,7 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
 
        nfs_fattr_init(fattr);
        
-       cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0);
+       cred = rpc_lookup_cred();
        if (IS_ERR(cred))
                return PTR_ERR(cred);
 
@@ -1892,7 +1893,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
        struct rpc_cred *cred;
        int status = 0;
 
-       cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0);
+       cred = rpc_lookup_cred();
        if (IS_ERR(cred)) {
                status = PTR_ERR(cred);
                goto out;
@@ -2761,10 +2762,10 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server)
                case -NFS4ERR_STALE_CLIENTID:
                case -NFS4ERR_STALE_STATEID:
                case -NFS4ERR_EXPIRED:
-                       rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL, NULL);
+                       rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL);
                        nfs4_schedule_state_recovery(clp);
                        if (test_bit(NFS4CLNT_STATE_RECOVER, &clp->cl_state) == 0)
-                               rpc_wake_up_task(task);
+                               rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task);
                        task->tk_status = 0;
                        return -EAGAIN;
                case -NFS4ERR_DELAY:
@@ -2884,7 +2885,7 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, unsigned short po
                                                        RPC_DISPLAY_ADDR),
                                rpc_peeraddr2str(clp->cl_rpcclient,
                                                        RPC_DISPLAY_PROTO),
-                               cred->cr_ops->cr_name,
+                               clp->cl_rpcclient->cl_auth->au_ops->au_name,
                                clp->cl_id_uniquifier);
                setclientid.sc_netid_len = scnprintf(setclientid.sc_netid,
                                sizeof(setclientid.sc_netid),
@@ -3158,6 +3159,7 @@ static struct nfs4_unlockdata *nfs4_alloc_unlockdata(struct file_lock *fl,
        p->arg.fh = NFS_FH(inode);
        p->arg.fl = &p->fl;
        p->arg.seqid = seqid;
+       p->res.seqid = seqid;
        p->arg.stateid = &lsp->ls_stateid;
        p->lsp = lsp;
        atomic_inc(&lsp->ls_count);
@@ -3183,7 +3185,6 @@ static void nfs4_locku_done(struct rpc_task *task, void *data)
 
        if (RPC_ASSASSINATED(task))
                return;
-       nfs_increment_lock_seqid(task->tk_status, calldata->arg.seqid);
        switch (task->tk_status) {
                case 0:
                        memcpy(calldata->lsp->ls_stateid.data,
@@ -3235,6 +3236,7 @@ static struct rpc_task *nfs4_do_unlck(struct file_lock *fl,
                .rpc_client = NFS_CLIENT(lsp->ls_state->inode),
                .rpc_message = &msg,
                .callback_ops = &nfs4_locku_ops,
+               .workqueue = nfsiod_workqueue,
                .flags = RPC_TASK_ASYNC,
        };
 
@@ -3261,6 +3263,7 @@ static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *
        struct nfs4_lock_state *lsp;
        struct rpc_task *task;
        int status = 0;
+       unsigned char fl_flags = request->fl_flags;
 
        status = nfs4_set_lock_state(state, request);
        /* Unlock _before_ we do the RPC call */
@@ -3284,6 +3287,7 @@ static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *
        status = nfs4_wait_for_completion_rpc_task(task);
        rpc_put_task(task);
 out:
+       request->fl_flags = fl_flags;
        return status;
 }
 
@@ -3320,6 +3324,7 @@ static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl,
        p->arg.lock_stateid = &lsp->ls_stateid;
        p->arg.lock_owner.clientid = server->nfs_client->cl_clientid;
        p->arg.lock_owner.id = lsp->ls_id.id;
+       p->res.lock_seqid = p->arg.lock_seqid;
        p->lsp = lsp;
        atomic_inc(&lsp->ls_count);
        p->ctx = get_nfs_open_context(ctx);
@@ -3346,6 +3351,7 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata)
                        return;
                data->arg.open_stateid = &state->stateid;
                data->arg.new_lock_owner = 1;
+               data->res.open_seqid = data->arg.open_seqid;
        } else
                data->arg.new_lock_owner = 0;
        data->timestamp = jiffies;
@@ -3363,7 +3369,6 @@ static void nfs4_lock_done(struct rpc_task *task, void *calldata)
        if (RPC_ASSASSINATED(task))
                goto out;
        if (data->arg.new_lock_owner != 0) {
-               nfs_increment_open_seqid(data->rpc_status, data->arg.open_seqid);
                if (data->rpc_status == 0)
                        nfs_confirm_seqid(&data->lsp->ls_seqid, 0);
                else
@@ -3375,7 +3380,6 @@ static void nfs4_lock_done(struct rpc_task *task, void *calldata)
                data->lsp->ls_flags |= NFS_LOCK_INITIALIZED;
                renew_lease(NFS_SERVER(data->ctx->path.dentry->d_inode), data->timestamp);
        }
-       nfs_increment_lock_seqid(data->rpc_status, data->arg.lock_seqid);
 out:
        dprintk("%s: done, ret = %d!\n", __FUNCTION__, data->rpc_status);
 }
@@ -3419,6 +3423,7 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f
                .rpc_client = NFS_CLIENT(state->inode),
                .rpc_message = &msg,
                .callback_ops = &nfs4_lock_ops,
+               .workqueue = nfsiod_workqueue,
                .flags = RPC_TASK_ASYNC,
        };
        int ret;
index b962397004c18aba751c395add7e6dc3e397b28b..46eb624e4f167d0f14189313655971a623f314b5 100644 (file)
@@ -71,6 +71,29 @@ static int nfs4_init_client(struct nfs_client *clp, struct rpc_cred *cred)
        return status;
 }
 
+static struct rpc_cred *nfs4_get_machine_cred(struct nfs_client *clp)
+{
+       struct rpc_cred *cred = NULL;
+
+       spin_lock(&clp->cl_lock);
+       if (clp->cl_machine_cred != NULL)
+               cred = get_rpccred(clp->cl_machine_cred);
+       spin_unlock(&clp->cl_lock);
+       return cred;
+}
+
+static void nfs4_clear_machine_cred(struct nfs_client *clp)
+{
+       struct rpc_cred *cred;
+
+       spin_lock(&clp->cl_lock);
+       cred = clp->cl_machine_cred;
+       clp->cl_machine_cred = NULL;
+       spin_unlock(&clp->cl_lock);
+       if (cred != NULL)
+               put_rpccred(cred);
+}
+
 struct rpc_cred *nfs4_get_renew_cred(struct nfs_client *clp)
 {
        struct nfs4_state_owner *sp;
@@ -91,13 +114,18 @@ static struct rpc_cred *nfs4_get_setclientid_cred(struct nfs_client *clp)
 {
        struct nfs4_state_owner *sp;
        struct rb_node *pos;
+       struct rpc_cred *cred;
 
+       cred = nfs4_get_machine_cred(clp);
+       if (cred != NULL)
+               goto out;
        pos = rb_first(&clp->cl_state_owners);
        if (pos != NULL) {
                sp = rb_entry(pos, struct nfs4_state_owner, so_client_node);
-               return get_rpccred(sp->so_cred);
+               cred = get_rpccred(sp->so_cred);
        }
-       return NULL;
+out:
+       return cred;
 }
 
 static void nfs_alloc_unique_id(struct rb_root *root, struct nfs_unique_id *new,
@@ -292,8 +320,10 @@ struct nfs4_state_owner *nfs4_get_state_owner(struct nfs_server *server, struct
        spin_unlock(&clp->cl_lock);
        if (sp == new)
                get_rpccred(cred);
-       else
+       else {
+               rpc_destroy_wait_queue(&new->so_sequence.wait);
                kfree(new);
+       }
        return sp;
 }
 
@@ -310,6 +340,7 @@ void nfs4_put_state_owner(struct nfs4_state_owner *sp)
                return;
        nfs4_remove_state_owner(clp, sp);
        spin_unlock(&clp->cl_lock);
+       rpc_destroy_wait_queue(&sp->so_sequence.wait);
        put_rpccred(cred);
        kfree(sp);
 }
@@ -529,6 +560,7 @@ static void nfs4_free_lock_state(struct nfs4_lock_state *lsp)
        spin_lock(&clp->cl_lock);
        nfs_free_unique_id(&clp->cl_lockowner_id, &lsp->ls_id);
        spin_unlock(&clp->cl_lock);
+       rpc_destroy_wait_queue(&lsp->ls_sequence.wait);
        kfree(lsp);
 }
 
@@ -731,7 +763,7 @@ int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task)
                list_add_tail(&seqid->list, &sequence->list);
        if (list_first_entry(&sequence->list, struct nfs_seqid, list) == seqid)
                goto unlock;
-       rpc_sleep_on(&sequence->wait, task, NULL, NULL);
+       rpc_sleep_on(&sequence->wait, task, NULL);
        status = -EAGAIN;
 unlock:
        spin_unlock(&sequence->lock);
@@ -920,10 +952,10 @@ restart_loop:
        if (cred != NULL) {
                /* Yes there are: try to renew the old lease */
                status = nfs4_proc_renew(clp, cred);
+               put_rpccred(cred);
                switch (status) {
                        case 0:
                        case -NFS4ERR_CB_PATH_DOWN:
-                               put_rpccred(cred);
                                goto out;
                        case -NFS4ERR_STALE_CLIENTID:
                        case -NFS4ERR_LEASE_MOVED:
@@ -932,14 +964,19 @@ restart_loop:
        } else {
                /* "reboot" to ensure we clear all state on the server */
                clp->cl_boot_time = CURRENT_TIME;
-               cred = nfs4_get_setclientid_cred(clp);
        }
        /* We're going to have to re-establish a clientid */
        nfs4_state_mark_reclaim(clp);
        status = -ENOENT;
+       cred = nfs4_get_setclientid_cred(clp);
        if (cred != NULL) {
                status = nfs4_init_client(clp, cred);
                put_rpccred(cred);
+               /* Handle case where the user hasn't set up machine creds */
+               if (status == -EACCES && cred == clp->cl_machine_cred) {
+                       nfs4_clear_machine_cred(clp);
+                       goto restart_loop;
+               }
        }
        if (status)
                goto out_error;
index db1ed9c46ede9f4d9c899e45c63289ccb5296546..5a2d64927b35fd038d9a74edd5390ee071fe0edf 100644 (file)
@@ -110,7 +110,7 @@ static int nfs4_stat_to_errno(int);
 #define decode_savefh_maxsz     (op_decode_hdr_maxsz)
 #define encode_restorefh_maxsz  (op_encode_hdr_maxsz)
 #define decode_restorefh_maxsz  (op_decode_hdr_maxsz)
-#define encode_fsinfo_maxsz    (op_encode_hdr_maxsz + 2)
+#define encode_fsinfo_maxsz    (encode_getattr_maxsz)
 #define decode_fsinfo_maxsz    (op_decode_hdr_maxsz + 11)
 #define encode_renew_maxsz     (op_encode_hdr_maxsz + 3)
 #define decode_renew_maxsz     (op_decode_hdr_maxsz)
@@ -1191,8 +1191,8 @@ static int encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg
                attrs[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID;
        WRITE32(attrs[0] & readdir->bitmask[0]);
        WRITE32(attrs[1] & readdir->bitmask[1]);
-       dprintk("%s: cookie = %Lu, verifier = 0x%x%x, bitmap = 0x%x%x\n",
-                       __FUNCTION__,
+       dprintk("%s: cookie = %Lu, verifier = %08x:%08x, bitmap = %08x:%08x\n",
+                       __func__,
                        (unsigned long long)readdir->cookie,
                        ((u32 *)readdir->verifier.data)[0],
                        ((u32 *)readdir->verifier.data)[1],
@@ -2241,7 +2241,7 @@ static int decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected)
        }
        READ32(nfserr);
        if (nfserr != NFS_OK)
-               return -nfs4_stat_to_errno(nfserr);
+               return nfs4_stat_to_errno(nfserr);
        return 0;
 }
 
@@ -2291,7 +2291,7 @@ static int decode_attr_supported(struct xdr_stream *xdr, uint32_t *bitmap, uint3
                bitmap[0] &= ~FATTR4_WORD0_SUPPORTED_ATTRS;
        } else
                bitmask[0] = bitmask[1] = 0;
-       dprintk("%s: bitmask=0x%x%x\n", __FUNCTION__, bitmask[0], bitmask[1]);
+       dprintk("%s: bitmask=%08x:%08x\n", __func__, bitmask[0], bitmask[1]);
        return 0;
 }
 
@@ -3005,6 +3005,8 @@ static int decode_close(struct xdr_stream *xdr, struct nfs_closeres *res)
        int status;
 
        status = decode_op_hdr(xdr, OP_CLOSE);
+       if (status != -EIO)
+               nfs_increment_open_seqid(status, res->seqid);
        if (status)
                return status;
        READ_BUF(NFS4_STATEID_SIZE);
@@ -3296,11 +3298,17 @@ static int decode_lock(struct xdr_stream *xdr, struct nfs_lock_res *res)
        int status;
 
        status = decode_op_hdr(xdr, OP_LOCK);
+       if (status == -EIO)
+               goto out;
        if (status == 0) {
                READ_BUF(NFS4_STATEID_SIZE);
                COPYMEM(res->stateid.data, NFS4_STATEID_SIZE);
        } else if (status == -NFS4ERR_DENIED)
-               return decode_lock_denied(xdr, NULL);
+               status = decode_lock_denied(xdr, NULL);
+       if (res->open_seqid != NULL)
+               nfs_increment_open_seqid(status, res->open_seqid);
+       nfs_increment_lock_seqid(status, res->lock_seqid);
+out:
        return status;
 }
 
@@ -3319,6 +3327,8 @@ static int decode_locku(struct xdr_stream *xdr, struct nfs_locku_res *res)
        int status;
 
        status = decode_op_hdr(xdr, OP_LOCKU);
+       if (status != -EIO)
+               nfs_increment_lock_seqid(status, res->seqid);
        if (status == 0) {
                READ_BUF(NFS4_STATEID_SIZE);
                COPYMEM(res->stateid.data, NFS4_STATEID_SIZE);
@@ -3384,6 +3394,8 @@ static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res)
         int status;
 
         status = decode_op_hdr(xdr, OP_OPEN);
+       if (status != -EIO)
+               nfs_increment_open_seqid(status, res->seqid);
         if (status)
                 return status;
         READ_BUF(NFS4_STATEID_SIZE);
@@ -3416,6 +3428,8 @@ static int decode_open_confirm(struct xdr_stream *xdr, struct nfs_open_confirmre
        int status;
 
         status = decode_op_hdr(xdr, OP_OPEN_CONFIRM);
+       if (status != -EIO)
+               nfs_increment_open_seqid(status, res->seqid);
         if (status)
                 return status;
         READ_BUF(NFS4_STATEID_SIZE);
@@ -3429,6 +3443,8 @@ static int decode_open_downgrade(struct xdr_stream *xdr, struct nfs_closeres *re
        int status;
 
        status = decode_op_hdr(xdr, OP_OPEN_DOWNGRADE);
+       if (status != -EIO)
+               nfs_increment_open_seqid(status, res->seqid);
        if (status)
                return status;
        READ_BUF(NFS4_STATEID_SIZE);
@@ -3481,7 +3497,7 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n
        size_t          hdrlen;
        u32             recvd, pglen = rcvbuf->page_len;
        __be32          *end, *entry, *p, *kaddr;
-       unsigned int    nr;
+       unsigned int    nr = 0;
        int             status;
 
        status = decode_op_hdr(xdr, OP_READDIR);
@@ -3489,8 +3505,8 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n
                return status;
        READ_BUF(8);
        COPYMEM(readdir->verifier.data, 8);
-       dprintk("%s: verifier = 0x%x%x\n",
-                       __FUNCTION__,
+       dprintk("%s: verifier = %08x:%08x\n",
+                       __func__,
                        ((u32 *)readdir->verifier.data)[0],
                        ((u32 *)readdir->verifier.data)[1]);
 
@@ -3505,7 +3521,12 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n
        kaddr = p = kmap_atomic(page, KM_USER0);
        end = p + ((pglen + readdir->pgbase) >> 2);
        entry = p;
-       for (nr = 0; *p++; nr++) {
+
+       /* Make sure the packet actually has a value_follows and EOF entry */
+       if ((entry + 1) > end)
+               goto short_pkt;
+
+       for (; *p++; nr++) {
                u32 len, attrlen, xlen;
                if (end - p < 3)
                        goto short_pkt;
@@ -3532,20 +3553,32 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n
                p += attrlen;           /* attributes */
                entry = p;
        }
-       if (!nr && (entry[0] != 0 || entry[1] == 0))
-               goto short_pkt;
+       /*
+        * Apparently some server sends responses that are a valid size, but
+        * contain no entries, and have value_follows==0 and EOF==0. For
+        * those, just set the EOF marker.
+        */
+       if (!nr && entry[1] == 0) {
+               dprintk("NFS: readdir reply truncated!\n");
+               entry[1] = 1;
+       }
 out:   
        kunmap_atomic(kaddr, KM_USER0);
        return 0;
 short_pkt:
+       /*
+        * When we get a short packet there are 2 possibilities. We can
+        * return an error, or fix up the response to look like a valid
+        * response and return what we have so far. If there are no
+        * entries and the packet was short, then return -EIO. If there
+        * are valid entries in the response, return them and pretend that
+        * the call was successful, but incomplete. The caller can retry the
+        * readdir starting at the last cookie.
+        */
        dprintk("%s: short packet at entry %d\n", __FUNCTION__, nr);
        entry[0] = entry[1] = 0;
-       /* truncate listing ? */
-       if (!nr) {
-               dprintk("NFS: readdir reply truncated!\n");
-               entry[1] = 1;
-       }
-       goto out;
+       if (nr)
+               goto out;
 err_unmap:
        kunmap_atomic(kaddr, KM_USER0);
        return -errno_NFSERR_IO;
@@ -3727,7 +3760,7 @@ static int decode_setclientid(struct xdr_stream *xdr, struct nfs_client *clp)
                READ_BUF(len);
                return -NFSERR_CLID_INUSE;
        } else
-               return -nfs4_stat_to_errno(nfserr);
+               return nfs4_stat_to_errno(nfserr);
 
        return 0;
 }
@@ -4389,7 +4422,7 @@ static int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, __be32 *p, struct nfs_fsinf
        if (!status)
                status = decode_fsinfo(&xdr, fsinfo);
        if (!status)
-               status = -nfs4_stat_to_errno(hdr.status);
+               status = nfs4_stat_to_errno(hdr.status);
        return status;
 }
 
@@ -4479,7 +4512,7 @@ static int nfs4_xdr_dec_setclientid(struct rpc_rqst *req, __be32 *p,
        if (!status)
                status = decode_setclientid(&xdr, clp);
        if (!status)
-               status = -nfs4_stat_to_errno(hdr.status);
+               status = nfs4_stat_to_errno(hdr.status);
        return status;
 }
 
@@ -4501,7 +4534,7 @@ static int nfs4_xdr_dec_setclientid_confirm(struct rpc_rqst *req, __be32 *p, str
        if (!status)
                status = decode_fsinfo(&xdr, fsinfo);
        if (!status)
-               status = -nfs4_stat_to_errno(hdr.status);
+               status = nfs4_stat_to_errno(hdr.status);
        return status;
 }
 
@@ -4611,42 +4644,42 @@ static struct {
        int errno;
 } nfs_errtbl[] = {
        { NFS4_OK,              0               },
-       { NFS4ERR_PERM,         EPERM           },
-       { NFS4ERR_NOENT,        ENOENT          },
-       { NFS4ERR_IO,           errno_NFSERR_IO },
-       { NFS4ERR_NXIO,         ENXIO           },
-       { NFS4ERR_ACCESS,       EACCES          },
-       { NFS4ERR_EXIST,        EEXIST          },
-       { NFS4ERR_XDEV,         EXDEV           },
-       { NFS4ERR_NOTDIR,       ENOTDIR         },
-       { NFS4ERR_ISDIR,        EISDIR          },
-       { NFS4ERR_INVAL,        EINVAL          },
-       { NFS4ERR_FBIG,         EFBIG           },
-       { NFS4ERR_NOSPC,        ENOSPC          },
-       { NFS4ERR_ROFS,         EROFS           },
-       { NFS4ERR_MLINK,        EMLINK          },
-       { NFS4ERR_NAMETOOLONG,  ENAMETOOLONG    },
-       { NFS4ERR_NOTEMPTY,     ENOTEMPTY       },
-       { NFS4ERR_DQUOT,        EDQUOT          },
-       { NFS4ERR_STALE,        ESTALE          },
-       { NFS4ERR_BADHANDLE,    EBADHANDLE      },
-       { NFS4ERR_BADOWNER,     EINVAL          },
-       { NFS4ERR_BADNAME,      EINVAL          },
-       { NFS4ERR_BAD_COOKIE,   EBADCOOKIE      },
-       { NFS4ERR_NOTSUPP,      ENOTSUPP        },
-       { NFS4ERR_TOOSMALL,     ETOOSMALL       },
-       { NFS4ERR_SERVERFAULT,  ESERVERFAULT    },
-       { NFS4ERR_BADTYPE,      EBADTYPE        },
-       { NFS4ERR_LOCKED,       EAGAIN          },
-       { NFS4ERR_RESOURCE,     EREMOTEIO       },
-       { NFS4ERR_SYMLINK,      ELOOP           },
-       { NFS4ERR_OP_ILLEGAL,   EOPNOTSUPP      },
-       { NFS4ERR_DEADLOCK,     EDEADLK         },
-       { NFS4ERR_WRONGSEC,     EPERM           }, /* FIXME: this needs
+       { NFS4ERR_PERM,         -EPERM          },
+       { NFS4ERR_NOENT,        -ENOENT         },
+       { NFS4ERR_IO,           -errno_NFSERR_IO},
+       { NFS4ERR_NXIO,         -ENXIO          },
+       { NFS4ERR_ACCESS,       -EACCES         },
+       { NFS4ERR_EXIST,        -EEXIST         },
+       { NFS4ERR_XDEV,         -EXDEV          },
+       { NFS4ERR_NOTDIR,       -ENOTDIR        },
+       { NFS4ERR_ISDIR,        -EISDIR         },
+       { NFS4ERR_INVAL,        -EINVAL         },
+       { NFS4ERR_FBIG,         -EFBIG          },
+       { NFS4ERR_NOSPC,        -ENOSPC         },
+       { NFS4ERR_ROFS,         -EROFS          },
+       { NFS4ERR_MLINK,        -EMLINK         },
+       { NFS4ERR_NAMETOOLONG,  -ENAMETOOLONG   },
+       { NFS4ERR_NOTEMPTY,     -ENOTEMPTY      },
+       { NFS4ERR_DQUOT,        -EDQUOT         },
+       { NFS4ERR_STALE,        -ESTALE         },
+       { NFS4ERR_BADHANDLE,    -EBADHANDLE     },
+       { NFS4ERR_BADOWNER,     -EINVAL         },
+       { NFS4ERR_BADNAME,      -EINVAL         },
+       { NFS4ERR_BAD_COOKIE,   -EBADCOOKIE     },
+       { NFS4ERR_NOTSUPP,      -ENOTSUPP       },
+       { NFS4ERR_TOOSMALL,     -ETOOSMALL      },
+       { NFS4ERR_SERVERFAULT,  -ESERVERFAULT   },
+       { NFS4ERR_BADTYPE,      -EBADTYPE       },
+       { NFS4ERR_LOCKED,       -EAGAIN         },
+       { NFS4ERR_RESOURCE,     -EREMOTEIO      },
+       { NFS4ERR_SYMLINK,      -ELOOP          },
+       { NFS4ERR_OP_ILLEGAL,   -EOPNOTSUPP     },
+       { NFS4ERR_DEADLOCK,     -EDEADLK        },
+       { NFS4ERR_WRONGSEC,     -EPERM          }, /* FIXME: this needs
                                                    * to be handled by a
                                                    * middle-layer.
                                                    */
-       { -1,                   EIO             }
+       { -1,                   -EIO            }
 };
 
 /*
@@ -4663,14 +4696,14 @@ nfs4_stat_to_errno(int stat)
        }
        if (stat <= 10000 || stat > 10100) {
                /* The server is looney tunes. */
-               return ESERVERFAULT;
+               return -ESERVERFAULT;
        }
        /* If we cannot translate the error, the recovery routines should
         * handle it.
         * Note: remaining NFSv4 error codes have values > 10000, so should
         * not conflict with native Linux error codes.
         */
-       return stat;
+       return -stat;
 }
 
 #define PROC(proc, argtype, restype)                           \
index 5a70be589bbe2025eee4c6fc64aaba1c0b5958c3..16f57e0af999a51dc166b181dd01c3e8ef72e79d 100644 (file)
@@ -58,22 +58,19 @@ struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount)
        return p;
 }
 
-static void nfs_readdata_rcu_free(struct rcu_head *head)
+static void nfs_readdata_free(struct nfs_read_data *p)
 {
-       struct nfs_read_data *p = container_of(head, struct nfs_read_data, task.u.tk_rcu);
        if (p && (p->pagevec != &p->page_array[0]))
                kfree(p->pagevec);
        mempool_free(p, nfs_rdata_mempool);
 }
 
-static void nfs_readdata_free(struct nfs_read_data *rdata)
-{
-       call_rcu_bh(&rdata->task.u.tk_rcu, nfs_readdata_rcu_free);
-}
-
 void nfs_readdata_release(void *data)
 {
-        nfs_readdata_free(data);
+       struct nfs_read_data *rdata = data;
+
+       put_nfs_open_context(rdata->args.context);
+       nfs_readdata_free(rdata);
 }
 
 static
@@ -156,7 +153,7 @@ static void nfs_readpage_release(struct nfs_page *req)
 /*
  * Set up the NFS read request struct
  */
-static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
+static int nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
                const struct rpc_call_ops *call_ops,
                unsigned int count, unsigned int offset)
 {
@@ -174,6 +171,7 @@ static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
                .rpc_message = &msg,
                .callback_ops = call_ops,
                .callback_data = data,
+               .workqueue = nfsiod_workqueue,
                .flags = RPC_TASK_ASYNC | swap_flags,
        };
 
@@ -186,7 +184,7 @@ static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
        data->args.pgbase = req->wb_pgbase + offset;
        data->args.pages  = data->pagevec;
        data->args.count  = count;
-       data->args.context = req->wb_context;
+       data->args.context = get_nfs_open_context(req->wb_context);
 
        data->res.fattr   = &data->fattr;
        data->res.count   = count;
@@ -204,8 +202,10 @@ static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
                        (unsigned long long)data->args.offset);
 
        task = rpc_run_task(&task_setup_data);
-       if (!IS_ERR(task))
-               rpc_put_task(task);
+       if (IS_ERR(task))
+               return PTR_ERR(task);
+       rpc_put_task(task);
+       return 0;
 }
 
 static void
@@ -242,6 +242,7 @@ static int nfs_pagein_multi(struct inode *inode, struct list_head *head, unsigne
        size_t rsize = NFS_SERVER(inode)->rsize, nbytes;
        unsigned int offset;
        int requests = 0;
+       int ret = 0;
        LIST_HEAD(list);
 
        nfs_list_remove_request(req);
@@ -253,7 +254,6 @@ static int nfs_pagein_multi(struct inode *inode, struct list_head *head, unsigne
                data = nfs_readdata_alloc(1);
                if (!data)
                        goto out_bad;
-               INIT_LIST_HEAD(&data->pages);
                list_add(&data->pages, &list);
                requests++;
                nbytes -= len;
@@ -264,6 +264,8 @@ static int nfs_pagein_multi(struct inode *inode, struct list_head *head, unsigne
        offset = 0;
        nbytes = count;
        do {
+               int ret2;
+
                data = list_entry(list.next, struct nfs_read_data, pages);
                list_del_init(&data->pages);
 
@@ -271,13 +273,15 @@ static int nfs_pagein_multi(struct inode *inode, struct list_head *head, unsigne
 
                if (nbytes < rsize)
                        rsize = nbytes;
-               nfs_read_rpcsetup(req, data, &nfs_read_partial_ops,
+               ret2 = nfs_read_rpcsetup(req, data, &nfs_read_partial_ops,
                                  rsize, offset);
+               if (ret == 0)
+                       ret = ret2;
                offset += rsize;
                nbytes -= rsize;
        } while (nbytes != 0);
 
-       return 0;
+       return ret;
 
 out_bad:
        while (!list_empty(&list)) {
@@ -295,12 +299,12 @@ static int nfs_pagein_one(struct inode *inode, struct list_head *head, unsigned
        struct nfs_page         *req;
        struct page             **pages;
        struct nfs_read_data    *data;
+       int ret = -ENOMEM;
 
        data = nfs_readdata_alloc(npages);
        if (!data)
                goto out_bad;
 
-       INIT_LIST_HEAD(&data->pages);
        pages = data->pagevec;
        while (!list_empty(head)) {
                req = nfs_list_entry(head->next);
@@ -311,11 +315,10 @@ static int nfs_pagein_one(struct inode *inode, struct list_head *head, unsigned
        }
        req = nfs_list_entry(data->pages.next);
 
-       nfs_read_rpcsetup(req, data, &nfs_read_full_ops, count, 0);
-       return 0;
+       return nfs_read_rpcsetup(req, data, &nfs_read_full_ops, count, 0);
 out_bad:
        nfs_async_read_error(head);
-       return -ENOMEM;
+       return ret;
 }
 
 /*
@@ -342,26 +345,25 @@ int nfs_readpage_result(struct rpc_task *task, struct nfs_read_data *data)
        return 0;
 }
 
-static int nfs_readpage_retry(struct rpc_task *task, struct nfs_read_data *data)
+static void nfs_readpage_retry(struct rpc_task *task, struct nfs_read_data *data)
 {
        struct nfs_readargs *argp = &data->args;
        struct nfs_readres *resp = &data->res;
 
        if (resp->eof || resp->count == argp->count)
-               return 0;
+               return;
 
        /* This is a short read! */
        nfs_inc_stats(data->inode, NFSIOS_SHORTREAD);
        /* Has the server at least made some progress? */
        if (resp->count == 0)
-               return 0;
+               return;
 
        /* Yes, so retry the read at the end of the data */
        argp->offset += resp->count;
        argp->pgbase += resp->count;
        argp->count -= resp->count;
        rpc_restart_call(task);
-       return -EAGAIN;
 }
 
 /*
@@ -370,29 +372,37 @@ static int nfs_readpage_retry(struct rpc_task *task, struct nfs_read_data *data)
 static void nfs_readpage_result_partial(struct rpc_task *task, void *calldata)
 {
        struct nfs_read_data *data = calldata;
-       struct nfs_page *req = data->req;
-       struct page *page = req->wb_page;
  
        if (nfs_readpage_result(task, data) != 0)
                return;
+       if (task->tk_status < 0)
+               return;
 
-       if (likely(task->tk_status >= 0)) {
-               nfs_readpage_truncate_uninitialised_page(data);
-               if (nfs_readpage_retry(task, data) != 0)
-                       return;
-       }
-       if (unlikely(task->tk_status < 0))
+       nfs_readpage_truncate_uninitialised_page(data);
+       nfs_readpage_retry(task, data);
+}
+
+static void nfs_readpage_release_partial(void *calldata)
+{
+       struct nfs_read_data *data = calldata;
+       struct nfs_page *req = data->req;
+       struct page *page = req->wb_page;
+       int status = data->task.tk_status;
+
+       if (status < 0)
                SetPageError(page);
+
        if (atomic_dec_and_test(&req->wb_complete)) {
                if (!PageError(page))
                        SetPageUptodate(page);
                nfs_readpage_release(req);
        }
+       nfs_readdata_release(calldata);
 }
 
 static const struct rpc_call_ops nfs_read_partial_ops = {
        .rpc_call_done = nfs_readpage_result_partial,
-       .rpc_release = nfs_readdata_release,
+       .rpc_release = nfs_readpage_release_partial,
 };
 
 static void nfs_readpage_set_pages_uptodate(struct nfs_read_data *data)
@@ -427,29 +437,35 @@ static void nfs_readpage_result_full(struct rpc_task *task, void *calldata)
 
        if (nfs_readpage_result(task, data) != 0)
                return;
+       if (task->tk_status < 0)
+               return;
        /*
         * Note: nfs_readpage_retry may change the values of
         * data->args. In the multi-page case, we therefore need
         * to ensure that we call nfs_readpage_set_pages_uptodate()
         * first.
         */
-       if (likely(task->tk_status >= 0)) {
-               nfs_readpage_truncate_uninitialised_page(data);
-               nfs_readpage_set_pages_uptodate(data);
-               if (nfs_readpage_retry(task, data) != 0)
-                       return;
-       }
+       nfs_readpage_truncate_uninitialised_page(data);
+       nfs_readpage_set_pages_uptodate(data);
+       nfs_readpage_retry(task, data);
+}
+
+static void nfs_readpage_release_full(void *calldata)
+{
+       struct nfs_read_data *data = calldata;
+
        while (!list_empty(&data->pages)) {
                struct nfs_page *req = nfs_list_entry(data->pages.next);
 
                nfs_list_remove_request(req);
                nfs_readpage_release(req);
        }
+       nfs_readdata_release(calldata);
 }
 
 static const struct rpc_call_ops nfs_read_full_ops = {
        .rpc_call_done = nfs_readpage_result_full,
-       .rpc_release = nfs_readdata_release,
+       .rpc_release = nfs_readpage_release_full,
 };
 
 /*
index f9219024f31aca9fd56962050823d4e46bdbbb37..20a1cb1810fef50c9a4ce67f5ec9a5f1312e25ba 100644 (file)
@@ -441,10 +441,52 @@ static const char *nfs_pseudoflavour_to_name(rpc_authflavor_t flavour)
        return sec_flavours[i].str;
 }
 
+static void nfs_show_mountd_options(struct seq_file *m, struct nfs_server *nfss,
+                                   int showdefaults)
+{
+       struct sockaddr *sap = (struct sockaddr *)&nfss->mountd_address;
+
+       switch (sap->sa_family) {
+       case AF_INET: {
+               struct sockaddr_in *sin = (struct sockaddr_in *)sap;
+               seq_printf(m, ",mountaddr=" NIPQUAD_FMT,
+                               NIPQUAD(sin->sin_addr.s_addr));
+               break;
+       }
+       case AF_INET6: {
+               struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap;
+               seq_printf(m, ",mountaddr=" NIP6_FMT,
+                               NIP6(sin6->sin6_addr));
+               break;
+       }
+       default:
+               if (showdefaults)
+                       seq_printf(m, ",mountaddr=unspecified");
+       }
+
+       if (nfss->mountd_version || showdefaults)
+               seq_printf(m, ",mountvers=%u", nfss->mountd_version);
+       if (nfss->mountd_port || showdefaults)
+               seq_printf(m, ",mountport=%u", nfss->mountd_port);
+
+       switch (nfss->mountd_protocol) {
+       case IPPROTO_UDP:
+               seq_printf(m, ",mountproto=udp");
+               break;
+       case IPPROTO_TCP:
+               seq_printf(m, ",mountproto=tcp");
+               break;
+       default:
+               if (showdefaults)
+                       seq_printf(m, ",mountproto=auto");
+       }
+}
+
 /*
  * Describe the mount options in force on this server representation
  */
-static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss, int showdefaults)
+static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
+                                  int showdefaults)
 {
        static const struct proc_nfs_info {
                int flag;
@@ -452,6 +494,8 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
                const char *nostr;
        } nfs_info[] = {
                { NFS_MOUNT_SOFT, ",soft", ",hard" },
+               { NFS_MOUNT_INTR, ",intr", ",nointr" },
+               { NFS_MOUNT_POSIX, ",posix", "" },
                { NFS_MOUNT_NOCTO, ",nocto", "" },
                { NFS_MOUNT_NOAC, ",noac", "" },
                { NFS_MOUNT_NONLM, ",nolock", "" },
@@ -462,18 +506,22 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
        };
        const struct proc_nfs_info *nfs_infop;
        struct nfs_client *clp = nfss->nfs_client;
-
-       seq_printf(m, ",vers=%d", clp->rpc_ops->version);
-       seq_printf(m, ",rsize=%d", nfss->rsize);
-       seq_printf(m, ",wsize=%d", nfss->wsize);
+       u32 version = clp->rpc_ops->version;
+
+       seq_printf(m, ",vers=%u", version);
+       seq_printf(m, ",rsize=%u", nfss->rsize);
+       seq_printf(m, ",wsize=%u", nfss->wsize);
+       if (nfss->bsize != 0)
+               seq_printf(m, ",bsize=%u", nfss->bsize);
+       seq_printf(m, ",namlen=%u", nfss->namelen);
        if (nfss->acregmin != 3*HZ || showdefaults)
-               seq_printf(m, ",acregmin=%d", nfss->acregmin/HZ);
+               seq_printf(m, ",acregmin=%u", nfss->acregmin/HZ);
        if (nfss->acregmax != 60*HZ || showdefaults)
-               seq_printf(m, ",acregmax=%d", nfss->acregmax/HZ);
+               seq_printf(m, ",acregmax=%u", nfss->acregmax/HZ);
        if (nfss->acdirmin != 30*HZ || showdefaults)
-               seq_printf(m, ",acdirmin=%d", nfss->acdirmin/HZ);
+               seq_printf(m, ",acdirmin=%u", nfss->acdirmin/HZ);
        if (nfss->acdirmax != 60*HZ || showdefaults)
-               seq_printf(m, ",acdirmax=%d", nfss->acdirmax/HZ);
+               seq_printf(m, ",acdirmax=%u", nfss->acdirmax/HZ);
        for (nfs_infop = nfs_info; nfs_infop->flag; nfs_infop++) {
                if (nfss->flags & nfs_infop->flag)
                        seq_puts(m, nfs_infop->str);
@@ -482,9 +530,24 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
        }
        seq_printf(m, ",proto=%s",
                   rpc_peeraddr2str(nfss->client, RPC_DISPLAY_PROTO));
+       if (version == 4) {
+               if (nfss->port != NFS_PORT)
+                       seq_printf(m, ",port=%u", nfss->port);
+       } else
+               if (nfss->port)
+                       seq_printf(m, ",port=%u", nfss->port);
+
        seq_printf(m, ",timeo=%lu", 10U * nfss->client->cl_timeout->to_initval / HZ);
        seq_printf(m, ",retrans=%u", nfss->client->cl_timeout->to_retries);
        seq_printf(m, ",sec=%s", nfs_pseudoflavour_to_name(nfss->client->cl_auth->au_flavor));
+
+       if (version != 4)
+               nfs_show_mountd_options(m, nfss, showdefaults);
+
+#ifdef CONFIG_NFS_V4
+       if (clp->rpc_ops->version == 4)
+               seq_printf(m, ",clientaddr=%s", clp->cl_ipaddr);
+#endif
 }
 
 /*
@@ -529,10 +592,10 @@ static int nfs_show_stats(struct seq_file *m, struct vfsmount *mnt)
 
        seq_printf(m, "\n\tcaps:\t");
        seq_printf(m, "caps=0x%x", nfss->caps);
-       seq_printf(m, ",wtmult=%d", nfss->wtmult);
-       seq_printf(m, ",dtsize=%d", nfss->dtsize);
-       seq_printf(m, ",bsize=%d", nfss->bsize);
-       seq_printf(m, ",namelen=%d", nfss->namelen);
+       seq_printf(m, ",wtmult=%u", nfss->wtmult);
+       seq_printf(m, ",dtsize=%u", nfss->dtsize);
+       seq_printf(m, ",bsize=%u", nfss->bsize);
+       seq_printf(m, ",namlen=%u", nfss->namelen);
 
 #ifdef CONFIG_NFS_V4
        if (nfss->nfs_client->rpc_ops->version == 4) {
@@ -546,9 +609,9 @@ static int nfs_show_stats(struct seq_file *m, struct vfsmount *mnt)
        /*
         * Display security flavor in effect for this mount
         */
-       seq_printf(m, "\n\tsec:\tflavor=%d", auth->au_ops->au_flavor);
+       seq_printf(m, "\n\tsec:\tflavor=%u", auth->au_ops->au_flavor);
        if (auth->au_flavor)
-               seq_printf(m, ",pseudoflavor=%d", auth->au_flavor);
+               seq_printf(m, ",pseudoflavor=%u", auth->au_flavor);
 
        /*
         * Display superblock I/O counters
@@ -683,7 +746,6 @@ static int nfs_parse_mount_options(char *raw,
                                   struct nfs_parsed_mount_data *mnt)
 {
        char *p, *string, *secdata;
-       unsigned short port = 0;
        int rc;
 
        if (!raw) {
@@ -798,7 +860,7 @@ static int nfs_parse_mount_options(char *raw,
                                return 0;
                        if (option < 0 || option > 65535)
                                return 0;
-                       port = option;
+                       mnt->nfs_server.port = option;
                        break;
                case Opt_rsize:
                        if (match_int(args, &mnt->rsize))
@@ -1048,7 +1110,8 @@ static int nfs_parse_mount_options(char *raw,
                }
        }
 
-       nfs_set_port((struct sockaddr *)&mnt->nfs_server.address, port);
+       nfs_set_port((struct sockaddr *)&mnt->nfs_server.address,
+                               mnt->nfs_server.port);
 
        return 1;
 
@@ -1169,7 +1232,9 @@ static int nfs_validate_mount_data(void *options,
        args->acregmax          = 60;
        args->acdirmin          = 30;
        args->acdirmax          = 60;
+       args->mount_server.port = 0;    /* autobind unless user sets port */
        args->mount_server.protocol = XPRT_TRANSPORT_UDP;
+       args->nfs_server.port   = 0;    /* autobind unless user sets port */
        args->nfs_server.protocol = XPRT_TRANSPORT_TCP;
 
        switch (data->version) {
@@ -1208,7 +1273,6 @@ static int nfs_validate_mount_data(void *options,
                args->flags             = data->flags;
                args->rsize             = data->rsize;
                args->wsize             = data->wsize;
-               args->flags             = data->flags;
                args->timeo             = data->timeo;
                args->retrans           = data->retrans;
                args->acregmin          = data->acregmin;
@@ -1230,6 +1294,8 @@ static int nfs_validate_mount_data(void *options,
                args->namlen            = data->namlen;
                args->bsize             = data->bsize;
                args->auth_flavors[0]   = data->pseudoflavor;
+               if (!args->nfs_server.hostname)
+                       goto out_nomem;
 
                /*
                 * The legacy version 6 binary mount data from userspace has a
@@ -1276,6 +1342,8 @@ static int nfs_validate_mount_data(void *options,
                len = c - dev_name;
                /* N.B. caller will free nfs_server.hostname in all cases */
                args->nfs_server.hostname = kstrndup(dev_name, len, GFP_KERNEL);
+               if (!args->nfs_server.hostname)
+                       goto out_nomem;
 
                c++;
                if (strlen(c) > NFS_MAXPATHLEN)
@@ -1319,6 +1387,10 @@ out_v3_not_compiled:
        return -EPROTONOSUPPORT;
 #endif /* !CONFIG_NFS_V3 */
 
+out_nomem:
+       dfprintk(MOUNT, "NFS: not enough memory to handle mount options\n");
+       return -ENOMEM;
+
 out_no_address:
        dfprintk(MOUNT, "NFS: mount program didn't pass remote address\n");
        return -EINVAL;
@@ -1705,28 +1777,6 @@ static void nfs4_fill_super(struct super_block *sb)
        nfs_initialise_sb(sb);
 }
 
-/*
- * If the user didn't specify a port, set the port number to
- * the NFS version 4 default port.
- */
-static void nfs4_default_port(struct sockaddr *sap)
-{
-       switch (sap->sa_family) {
-       case AF_INET: {
-               struct sockaddr_in *ap = (struct sockaddr_in *)sap;
-               if (ap->sin_port == 0)
-                       ap->sin_port = htons(NFS_PORT);
-               break;
-       }
-       case AF_INET6: {
-               struct sockaddr_in6 *ap = (struct sockaddr_in6 *)sap;
-               if (ap->sin6_port == 0)
-                       ap->sin6_port = htons(NFS_PORT);
-               break;
-       }
-       }
-}
-
 /*
  * Validate NFSv4 mount options
  */
@@ -1751,6 +1801,7 @@ static int nfs4_validate_mount_data(void *options,
        args->acregmax          = 60;
        args->acdirmin          = 30;
        args->acdirmax          = 60;
+       args->nfs_server.port   = NFS_PORT; /* 2049 unless user set port= */
        args->nfs_server.protocol = XPRT_TRANSPORT_TCP;
 
        switch (data->version) {
@@ -1767,9 +1818,6 @@ static int nfs4_validate_mount_data(void *options,
                                                &args->nfs_server.address))
                        goto out_no_address;
 
-               nfs4_default_port((struct sockaddr *)
-                                 &args->nfs_server.address);
-
                switch (data->auth_flavourlen) {
                case 0:
                        args->auth_flavors[0] = RPC_AUTH_UNIX;
@@ -1827,9 +1875,6 @@ static int nfs4_validate_mount_data(void *options,
                                                &args->nfs_server.address))
                        return -EINVAL;
 
-               nfs4_default_port((struct sockaddr *)
-                                 &args->nfs_server.address);
-
                switch (args->auth_flavor_len) {
                case 0:
                        args->auth_flavors[0] = RPC_AUTH_UNIX;
@@ -1852,12 +1897,16 @@ static int nfs4_validate_mount_data(void *options,
                        return -ENAMETOOLONG;
                /* N.B. caller will free nfs_server.hostname in all cases */
                args->nfs_server.hostname = kstrndup(dev_name, len, GFP_KERNEL);
+               if (!args->nfs_server.hostname)
+                       goto out_nomem;
 
                c++;                    /* step over the ':' */
                len = strlen(c);
                if (len > NFS4_MAXPATHLEN)
                        return -ENAMETOOLONG;
                args->nfs_server.export_path = kstrndup(c, len, GFP_KERNEL);
+               if (!args->nfs_server.export_path)
+                       goto out_nomem;
 
                dprintk("NFS: MNTPATH: '%s'\n", args->nfs_server.export_path);
 
@@ -1879,6 +1928,10 @@ out_inval_auth:
                 data->auth_flavourlen);
        return -EINVAL;
 
+out_nomem:
+       dfprintk(MOUNT, "NFS4: not enough memory to handle mount options\n");
+       return -ENOMEM;
+
 out_no_address:
        dfprintk(MOUNT, "NFS4: mount program didn't pass remote address\n");
        return -EINVAL;
index 83e865a16ad1393cc25ce62377bed94855880ff0..412738dbfbc7e1024f90887e5e3cdd1a07a34563 100644 (file)
@@ -10,7 +10,6 @@
  *  nfs symlink handling code
  */
 
-#define NFS_NEED_XDR_TYPES
 #include <linux/time.h>
 #include <linux/errno.h>
 #include <linux/sunrpc/clnt.h>
index 757415363422da022f2c7197779233d93b86e653..3adf8b266461fbf3562d7876ed57f50de2f974df 100644 (file)
@@ -234,7 +234,7 @@ nfs_async_unlink(struct inode *dir, struct dentry *dentry)
        if (data == NULL)
                goto out;
 
-       data->cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0);
+       data->cred = rpc_lookup_cred();
        if (IS_ERR(data->cred)) {
                status = PTR_ERR(data->cred);
                goto out_free;
index bed63416a55b3c51ab539666c4f3f5f5ca8321b0..1ade11d1ba078c922e8dc24b0d2d98eec022d09f 100644 (file)
@@ -48,7 +48,7 @@ static struct kmem_cache *nfs_wdata_cachep;
 static mempool_t *nfs_wdata_mempool;
 static mempool_t *nfs_commit_mempool;
 
-struct nfs_write_data *nfs_commit_alloc(void)
+struct nfs_write_data *nfs_commitdata_alloc(void)
 {
        struct nfs_write_data *p = mempool_alloc(nfs_commit_mempool, GFP_NOFS);
 
@@ -59,19 +59,13 @@ struct nfs_write_data *nfs_commit_alloc(void)
        return p;
 }
 
-static void nfs_commit_rcu_free(struct rcu_head *head)
+void nfs_commit_free(struct nfs_write_data *p)
 {
-       struct nfs_write_data *p = container_of(head, struct nfs_write_data, task.u.tk_rcu);
        if (p && (p->pagevec != &p->page_array[0]))
                kfree(p->pagevec);
        mempool_free(p, nfs_commit_mempool);
 }
 
-void nfs_commit_free(struct nfs_write_data *wdata)
-{
-       call_rcu_bh(&wdata->task.u.tk_rcu, nfs_commit_rcu_free);
-}
-
 struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount)
 {
        struct nfs_write_data *p = mempool_alloc(nfs_wdata_mempool, GFP_NOFS);
@@ -93,21 +87,18 @@ struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount)
        return p;
 }
 
-static void nfs_writedata_rcu_free(struct rcu_head *head)
+static void nfs_writedata_free(struct nfs_write_data *p)
 {
-       struct nfs_write_data *p = container_of(head, struct nfs_write_data, task.u.tk_rcu);
        if (p && (p->pagevec != &p->page_array[0]))
                kfree(p->pagevec);
        mempool_free(p, nfs_wdata_mempool);
 }
 
-static void nfs_writedata_free(struct nfs_write_data *wdata)
+void nfs_writedata_release(void *data)
 {
-       call_rcu_bh(&wdata->task.u.tk_rcu, nfs_writedata_rcu_free);
-}
+       struct nfs_write_data *wdata = data;
 
-void nfs_writedata_release(void *wdata)
-{
+       put_nfs_open_context(wdata->args.context);
        nfs_writedata_free(wdata);
 }
 
@@ -291,8 +282,6 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio,
        spin_unlock(&inode->i_lock);
        if (!nfs_pageio_add_request(pgio, req)) {
                nfs_redirty_request(req);
-               nfs_end_page_writeback(page);
-               nfs_clear_page_tag_locked(req);
                return pgio->pg_error;
        }
        return 0;
@@ -366,15 +355,13 @@ int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc)
 /*
  * Insert a write request into an inode
  */
-static int nfs_inode_add_request(struct inode *inode, struct nfs_page *req)
+static void nfs_inode_add_request(struct inode *inode, struct nfs_page *req)
 {
        struct nfs_inode *nfsi = NFS_I(inode);
        int error;
 
        error = radix_tree_insert(&nfsi->nfs_page_tree, req->wb_index, req);
-       BUG_ON(error == -EEXIST);
-       if (error)
-               return error;
+       BUG_ON(error);
        if (!nfsi->npages) {
                igrab(inode);
                if (nfs_have_delegation(inode, FMODE_WRITE))
@@ -384,8 +371,8 @@ static int nfs_inode_add_request(struct inode *inode, struct nfs_page *req)
        set_page_private(req->wb_page, (unsigned long)req);
        nfsi->npages++;
        kref_get(&req->wb_kref);
-       radix_tree_tag_set(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_LOCKED);
-       return 0;
+       radix_tree_tag_set(&nfsi->nfs_page_tree, req->wb_index,
+                               NFS_PAGE_TAG_LOCKED);
 }
 
 /*
@@ -413,7 +400,7 @@ static void nfs_inode_remove_request(struct nfs_page *req)
 }
 
 static void
-nfs_redirty_request(struct nfs_page *req)
+nfs_mark_request_dirty(struct nfs_page *req)
 {
        __set_page_dirty_nobuffers(req->wb_page);
 }
@@ -467,7 +454,7 @@ int nfs_reschedule_unstable_write(struct nfs_page *req)
                return 1;
        }
        if (test_and_clear_bit(PG_NEED_RESCHED, &req->wb_flags)) {
-               nfs_redirty_request(req);
+               nfs_mark_request_dirty(req);
                return 1;
        }
        return 0;
@@ -597,6 +584,13 @@ static struct nfs_page * nfs_update_request(struct nfs_open_context* ctx,
                /* Loop over all inode entries and see if we find
                 * A request for the page we wish to update
                 */
+               if (new) {
+                       if (radix_tree_preload(GFP_NOFS)) {
+                               nfs_release_request(new);
+                               return ERR_PTR(-ENOMEM);
+                       }
+               }
+
                spin_lock(&inode->i_lock);
                req = nfs_page_find_request_locked(page);
                if (req) {
@@ -607,28 +601,27 @@ static struct nfs_page * nfs_update_request(struct nfs_open_context* ctx,
                                error = nfs_wait_on_request(req);
                                nfs_release_request(req);
                                if (error < 0) {
-                                       if (new)
+                                       if (new) {
+                                               radix_tree_preload_end();
                                                nfs_release_request(new);
+                                       }
                                        return ERR_PTR(error);
                                }
                                continue;
                        }
                        spin_unlock(&inode->i_lock);
-                       if (new)
+                       if (new) {
+                               radix_tree_preload_end();
                                nfs_release_request(new);
+                       }
                        break;
                }
 
                if (new) {
-                       int error;
                        nfs_lock_request_dontget(new);
-                       error = nfs_inode_add_request(inode, new);
-                       if (error) {
-                               spin_unlock(&inode->i_lock);
-                               nfs_unlock_request(new);
-                               return ERR_PTR(error);
-                       }
+                       nfs_inode_add_request(inode, new);
                        spin_unlock(&inode->i_lock);
+                       radix_tree_preload_end();
                        req = new;
                        goto zero_page;
                }
@@ -785,7 +778,7 @@ static int flush_task_priority(int how)
 /*
  * Set up the argument/result storage required for the RPC call.
  */
-static void nfs_write_rpcsetup(struct nfs_page *req,
+static int nfs_write_rpcsetup(struct nfs_page *req,
                struct nfs_write_data *data,
                const struct rpc_call_ops *call_ops,
                unsigned int count, unsigned int offset,
@@ -806,6 +799,7 @@ static void nfs_write_rpcsetup(struct nfs_page *req,
                .rpc_message = &msg,
                .callback_ops = call_ops,
                .callback_data = data,
+               .workqueue = nfsiod_workqueue,
                .flags = flags,
                .priority = priority,
        };
@@ -822,7 +816,7 @@ static void nfs_write_rpcsetup(struct nfs_page *req,
        data->args.pgbase = req->wb_pgbase + offset;
        data->args.pages  = data->pagevec;
        data->args.count  = count;
-       data->args.context = req->wb_context;
+       data->args.context = get_nfs_open_context(req->wb_context);
        data->args.stable  = NFS_UNSTABLE;
        if (how & FLUSH_STABLE) {
                data->args.stable = NFS_DATA_SYNC;
@@ -847,8 +841,21 @@ static void nfs_write_rpcsetup(struct nfs_page *req,
                (unsigned long long)data->args.offset);
 
        task = rpc_run_task(&task_setup_data);
-       if (!IS_ERR(task))
-               rpc_put_task(task);
+       if (IS_ERR(task))
+               return PTR_ERR(task);
+       rpc_put_task(task);
+       return 0;
+}
+
+/* If a nfs_flush_* function fails, it should remove reqs from @head and
+ * call this on each, which will prepare them to be retried on next
+ * writeback using standard nfs.
+ */
+static void nfs_redirty_request(struct nfs_page *req)
+{
+       nfs_mark_request_dirty(req);
+       nfs_end_page_writeback(req->wb_page);
+       nfs_clear_page_tag_locked(req);
 }
 
 /*
@@ -863,6 +870,7 @@ static int nfs_flush_multi(struct inode *inode, struct list_head *head, unsigned
        size_t wsize = NFS_SERVER(inode)->wsize, nbytes;
        unsigned int offset;
        int requests = 0;
+       int ret = 0;
        LIST_HEAD(list);
 
        nfs_list_remove_request(req);
@@ -884,6 +892,8 @@ static int nfs_flush_multi(struct inode *inode, struct list_head *head, unsigned
        offset = 0;
        nbytes = count;
        do {
+               int ret2;
+
                data = list_entry(list.next, struct nfs_write_data, pages);
                list_del_init(&data->pages);
 
@@ -891,13 +901,15 @@ static int nfs_flush_multi(struct inode *inode, struct list_head *head, unsigned
 
                if (nbytes < wsize)
                        wsize = nbytes;
-               nfs_write_rpcsetup(req, data, &nfs_write_partial_ops,
+               ret2 = nfs_write_rpcsetup(req, data, &nfs_write_partial_ops,
                                   wsize, offset, how);
+               if (ret == 0)
+                       ret = ret2;
                offset += wsize;
                nbytes -= wsize;
        } while (nbytes != 0);
 
-       return 0;
+       return ret;
 
 out_bad:
        while (!list_empty(&list)) {
@@ -906,8 +918,6 @@ out_bad:
                nfs_writedata_release(data);
        }
        nfs_redirty_request(req);
-       nfs_end_page_writeback(req->wb_page);
-       nfs_clear_page_tag_locked(req);
        return -ENOMEM;
 }
 
@@ -940,16 +950,12 @@ static int nfs_flush_one(struct inode *inode, struct list_head *head, unsigned i
        req = nfs_list_entry(data->pages.next);
 
        /* Set up the argument struct */
-       nfs_write_rpcsetup(req, data, &nfs_write_full_ops, count, 0, how);
-
-       return 0;
+       return nfs_write_rpcsetup(req, data, &nfs_write_full_ops, count, 0, how);
  out_bad:
        while (!list_empty(head)) {
                req = nfs_list_entry(head->next);
                nfs_list_remove_request(req);
                nfs_redirty_request(req);
-               nfs_end_page_writeback(req->wb_page);
-               nfs_clear_page_tag_locked(req);
        }
        return -ENOMEM;
 }
@@ -972,7 +978,6 @@ static void nfs_writeback_done_partial(struct rpc_task *task, void *calldata)
 {
        struct nfs_write_data   *data = calldata;
        struct nfs_page         *req = data->req;
-       struct page             *page = req->wb_page;
 
        dprintk("NFS: write (%s/%Ld %d@%Ld)",
                req->wb_context->path.dentry->d_inode->i_sb->s_id,
@@ -980,13 +985,20 @@ static void nfs_writeback_done_partial(struct rpc_task *task, void *calldata)
                req->wb_bytes,
                (long long)req_offset(req));
 
-       if (nfs_writeback_done(task, data) != 0)
-               return;
+       nfs_writeback_done(task, data);
+}
 
-       if (task->tk_status < 0) {
+static void nfs_writeback_release_partial(void *calldata)
+{
+       struct nfs_write_data   *data = calldata;
+       struct nfs_page         *req = data->req;
+       struct page             *page = req->wb_page;
+       int status = data->task.tk_status;
+
+       if (status < 0) {
                nfs_set_pageerror(page);
-               nfs_context_set_write_error(req->wb_context, task->tk_status);
-               dprintk(", error = %d\n", task->tk_status);
+               nfs_context_set_write_error(req->wb_context, status);
+               dprintk(", error = %d\n", status);
                goto out;
        }
 
@@ -1011,11 +1023,12 @@ static void nfs_writeback_done_partial(struct rpc_task *task, void *calldata)
 out:
        if (atomic_dec_and_test(&req->wb_complete))
                nfs_writepage_release(req);
+       nfs_writedata_release(calldata);
 }
 
 static const struct rpc_call_ops nfs_write_partial_ops = {
        .rpc_call_done = nfs_writeback_done_partial,
-       .rpc_release = nfs_writedata_release,
+       .rpc_release = nfs_writeback_release_partial,
 };
 
 /*
@@ -1028,17 +1041,21 @@ static const struct rpc_call_ops nfs_write_partial_ops = {
 static void nfs_writeback_done_full(struct rpc_task *task, void *calldata)
 {
        struct nfs_write_data   *data = calldata;
-       struct nfs_page         *req;
-       struct page             *page;
 
-       if (nfs_writeback_done(task, data) != 0)
-               return;
+       nfs_writeback_done(task, data);
+}
+
+static void nfs_writeback_release_full(void *calldata)
+{
+       struct nfs_write_data   *data = calldata;
+       int status = data->task.tk_status;
 
        /* Update attributes as result of writeback. */
        while (!list_empty(&data->pages)) {
-               req = nfs_list_entry(data->pages.next);
+               struct nfs_page *req = nfs_list_entry(data->pages.next);
+               struct page *page = req->wb_page;
+
                nfs_list_remove_request(req);
-               page = req->wb_page;
 
                dprintk("NFS: write (%s/%Ld %d@%Ld)",
                        req->wb_context->path.dentry->d_inode->i_sb->s_id,
@@ -1046,10 +1063,10 @@ static void nfs_writeback_done_full(struct rpc_task *task, void *calldata)
                        req->wb_bytes,
                        (long long)req_offset(req));
 
-               if (task->tk_status < 0) {
+               if (status < 0) {
                        nfs_set_pageerror(page);
-                       nfs_context_set_write_error(req->wb_context, task->tk_status);
-                       dprintk(", error = %d\n", task->tk_status);
+                       nfs_context_set_write_error(req->wb_context, status);
+                       dprintk(", error = %d\n", status);
                        goto remove_request;
                }
 
@@ -1069,11 +1086,12 @@ remove_request:
        next:
                nfs_clear_page_tag_locked(req);
        }
+       nfs_writedata_release(calldata);
 }
 
 static const struct rpc_call_ops nfs_write_full_ops = {
        .rpc_call_done = nfs_writeback_done_full,
-       .rpc_release = nfs_writedata_release,
+       .rpc_release = nfs_writeback_release_full,
 };
 
 
@@ -1159,15 +1177,18 @@ int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data)
 
 
 #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
-void nfs_commit_release(void *wdata)
+void nfs_commitdata_release(void *data)
 {
+       struct nfs_write_data *wdata = data;
+
+       put_nfs_open_context(wdata->args.context);
        nfs_commit_free(wdata);
 }
 
 /*
  * Set up the argument/result storage required for the RPC call.
  */
-static void nfs_commit_rpcsetup(struct list_head *head,
+static int nfs_commit_rpcsetup(struct list_head *head,
                struct nfs_write_data *data,
                int how)
 {
@@ -1187,6 +1208,7 @@ static void nfs_commit_rpcsetup(struct list_head *head,
                .rpc_message = &msg,
                .callback_ops = &nfs_commit_ops,
                .callback_data = data,
+               .workqueue = nfsiod_workqueue,
                .flags = flags,
                .priority = priority,
        };
@@ -1203,6 +1225,7 @@ static void nfs_commit_rpcsetup(struct list_head *head,
        /* Note: we always request a commit of the entire inode */
        data->args.offset = 0;
        data->args.count  = 0;
+       data->args.context = get_nfs_open_context(first->wb_context);
        data->res.count   = 0;
        data->res.fattr   = &data->fattr;
        data->res.verf    = &data->verf;
@@ -1214,8 +1237,10 @@ static void nfs_commit_rpcsetup(struct list_head *head,
        dprintk("NFS: %5u initiated commit call\n", data->task.tk_pid);
 
        task = rpc_run_task(&task_setup_data);
-       if (!IS_ERR(task))
-               rpc_put_task(task);
+       if (IS_ERR(task))
+               return PTR_ERR(task);
+       rpc_put_task(task);
+       return 0;
 }
 
 /*
@@ -1227,15 +1252,13 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how)
        struct nfs_write_data   *data;
        struct nfs_page         *req;
 
-       data = nfs_commit_alloc();
+       data = nfs_commitdata_alloc();
 
        if (!data)
                goto out_bad;
 
        /* Set up the argument struct */
-       nfs_commit_rpcsetup(head, data, how);
-
-       return 0;
+       return nfs_commit_rpcsetup(head, data, how);
  out_bad:
        while (!list_empty(head)) {
                req = nfs_list_entry(head->next);
@@ -1255,7 +1278,6 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how)
 static void nfs_commit_done(struct rpc_task *task, void *calldata)
 {
        struct nfs_write_data   *data = calldata;
-       struct nfs_page         *req;
 
         dprintk("NFS: %5u nfs_commit_done (status %d)\n",
                                 task->tk_pid, task->tk_status);
@@ -1263,6 +1285,13 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata)
        /* Call the NFS version-specific code */
        if (NFS_PROTO(data->inode)->commit_done(task, data) != 0)
                return;
+}
+
+static void nfs_commit_release(void *calldata)
+{
+       struct nfs_write_data   *data = calldata;
+       struct nfs_page         *req;
+       int status = data->task.tk_status;
 
        while (!list_empty(&data->pages)) {
                req = nfs_list_entry(data->pages.next);
@@ -1277,10 +1306,10 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata)
                        (long long)NFS_FILEID(req->wb_context->path.dentry->d_inode),
                        req->wb_bytes,
                        (long long)req_offset(req));
-               if (task->tk_status < 0) {
-                       nfs_context_set_write_error(req->wb_context, task->tk_status);
+               if (status < 0) {
+                       nfs_context_set_write_error(req->wb_context, status);
                        nfs_inode_remove_request(req);
-                       dprintk(", error = %d\n", task->tk_status);
+                       dprintk(", error = %d\n", status);
                        goto next;
                }
 
@@ -1297,10 +1326,11 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata)
                }
                /* We have a mismatch. Write the page again */
                dprintk(" mismatch\n");
-               nfs_redirty_request(req);
+               nfs_mark_request_dirty(req);
        next:
                nfs_clear_page_tag_locked(req);
        }
+       nfs_commitdata_release(calldata);
 }
 
 static const struct rpc_call_ops nfs_commit_ops = {
@@ -1487,18 +1517,19 @@ static int nfs_wb_page_priority(struct inode *inode, struct page *page,
        };
        int ret;
 
-       BUG_ON(!PageLocked(page));
-       if (clear_page_dirty_for_io(page)) {
-               ret = nfs_writepage_locked(page, &wbc);
+       do {
+               if (clear_page_dirty_for_io(page)) {
+                       ret = nfs_writepage_locked(page, &wbc);
+                       if (ret < 0)
+                               goto out_error;
+               } else if (!PagePrivate(page))
+                       break;
+               ret = nfs_sync_mapping_wait(page->mapping, &wbc, how);
                if (ret < 0)
-                       goto out;
-       }
-       if (!PagePrivate(page))
-               return 0;
-       ret = nfs_sync_mapping_wait(page->mapping, &wbc, how);
-       if (ret >= 0)
-               return 0;
-out:
+                       goto out_error;
+       } while (PagePrivate(page));
+       return 0;
+out_error:
        __mark_inode_dirty(inode, I_DIRTY_PAGES);
        return ret;
 }
index d13403e33622eaade5d483d4453f7d58ff4b9a8f..294992e9bf69e18b17a52964dd0af23841894f26 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/sunrpc/svcauth.h>
 #include <linux/nfsd/nfsd.h>
 #include <linux/nfsd/export.h>
+#include "auth.h"
 
 int nfsexp_flags(struct svc_rqst *rqstp, struct svc_export *exp)
 {
index 8a6f7c924c7597d0e851a84f45ae479714856f33..33bfcf09db46faaffa13472d1ffd351c7dad28fb 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/lockd/bind.h>
 #include <linux/sunrpc/msg_prot.h>
 #include <linux/sunrpc/gss_api.h>
+#include <net/ipv6.h>
 
 #define NFSDDBG_FACILITY       NFSDDBG_EXPORT
 
@@ -1548,6 +1549,7 @@ exp_addclient(struct nfsctl_client *ncp)
 {
        struct auth_domain      *dom;
        int                     i, err;
+       struct in6_addr addr6;
 
        /* First, consistency check. */
        err = -EINVAL;
@@ -1566,9 +1568,10 @@ exp_addclient(struct nfsctl_client *ncp)
                goto out_unlock;
 
        /* Insert client into hashtable. */
-       for (i = 0; i < ncp->cl_naddr; i++)
-               auth_unix_add_addr(ncp->cl_addrlist[i], dom);
-
+       for (i = 0; i < ncp->cl_naddr; i++) {
+               ipv6_addr_set_v4mapped(ncp->cl_addrlist[i].s_addr, &addr6);
+               auth_unix_add_addr(&addr6, dom);
+       }
        auth_unix_forget_old(dom);
        auth_domain_put(dom);
 
index aae2b29ae2c9e6d4b645f91bf68b50046030accc..562abf3380d032e96342589fa13232233698c130 100644 (file)
@@ -344,6 +344,21 @@ static struct rpc_version *        nfs_cb_version[] = {
        &nfs_cb_version4,
 };
 
+static struct rpc_program cb_program;
+
+static struct rpc_stat cb_stats = {
+               .program        = &cb_program
+};
+
+#define NFS4_CALLBACK 0x40000000
+static struct rpc_program cb_program = {
+               .name           = "nfs4_cb",
+               .number         = NFS4_CALLBACK,
+               .nrvers         = ARRAY_SIZE(nfs_cb_version),
+               .version        = nfs_cb_version,
+               .stats          = &cb_stats,
+};
+
 /* Reference counting, callback cleanup, etc., all look racy as heck.
  * And why is cb_set an atomic? */
 
@@ -358,13 +373,12 @@ static int do_probe_callback(void *data)
                .to_maxval      = (NFSD_LEASE_TIME/2) * HZ,
                .to_exponential = 1,
        };
-       struct rpc_program *    program = &cb->cb_program;
        struct rpc_create_args args = {
                .protocol       = IPPROTO_TCP,
                .address        = (struct sockaddr *)&addr,
                .addrsize       = sizeof(addr),
                .timeout        = &timeparms,
-               .program        = program,
+               .program        = &cb_program,
                .version        = nfs_cb_version[1]->number,
                .authflavor     = RPC_AUTH_UNIX, /* XXX: need AUTH_GSS... */
                .flags          = (RPC_CLNT_CREATE_NOPING),
@@ -382,16 +396,8 @@ static int do_probe_callback(void *data)
        addr.sin_port = htons(cb->cb_port);
        addr.sin_addr.s_addr = htonl(cb->cb_addr);
 
-       /* Initialize rpc_program */
-       program->name = "nfs4_cb";
-       program->number = cb->cb_prog;
-       program->nrvers = ARRAY_SIZE(nfs_cb_version);
-       program->version = nfs_cb_version;
-       program->stats = &cb->cb_stat;
-
        /* Initialize rpc_stat */
-       memset(program->stats, 0, sizeof(cb->cb_stat));
-       program->stats->program = program;
+       memset(args.program->stats, 0, sizeof(struct rpc_stat));
 
        /* Create RPC client */
        client = rpc_create(&args);
index 996bd88b75ba4d4e094129d6e856c561f6843b57..5b398421b0518130240157dd2b02aa4c77a6ed0a 100644 (file)
@@ -202,7 +202,7 @@ static struct cache_detail idtoname_cache = {
        .alloc          = ent_alloc,
 };
 
-int
+static int
 idtoname_parse(struct cache_detail *cd, char *buf, int buflen)
 {
        struct ent ent, *res;
index 81a75f3081f434891ad5e39ad7514182853bd837..55dfdd71f1b0d8be42a3ce01a4a15e8228b9aaa0 100644 (file)
@@ -1639,6 +1639,7 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta
        locks_init_lock(&fl);
        fl.fl_lmops = &nfsd_lease_mng_ops;
        fl.fl_flags = FL_LEASE;
+       fl.fl_type = flag == NFS4_OPEN_DELEGATE_READ? F_RDLCK: F_WRLCK;
        fl.fl_end = OFFSET_MAX;
        fl.fl_owner =  (fl_owner_t)dp;
        fl.fl_file = stp->st_vfs_file;
@@ -1647,8 +1648,7 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta
        /* vfs_setlease checks to see if delegation should be handed out.
         * the lock_manager callbacks fl_mylease and fl_change are used
         */
-       if ((status = vfs_setlease(stp->st_vfs_file,
-               flag == NFS4_OPEN_DELEGATE_READ? F_RDLCK: F_WRLCK, &flp))) {
+       if ((status = vfs_setlease(stp->st_vfs_file, fl.fl_type, &flp))) {
                dprintk("NFSD: setlease failed [%d], no delegation\n", status);
                unhash_delegation(dp);
                flag = NFS4_OPEN_DELEGATE_NONE;
@@ -1763,10 +1763,6 @@ out:
        return status;
 }
 
-static struct workqueue_struct *laundry_wq;
-static void laundromat_main(struct work_struct *);
-static DECLARE_DELAYED_WORK(laundromat_work, laundromat_main);
-
 __be32
 nfsd4_renew(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
            clientid_t *clid)
@@ -1874,7 +1870,11 @@ nfs4_laundromat(void)
        return clientid_val;
 }
 
-void
+static struct workqueue_struct *laundry_wq;
+static void laundromat_main(struct work_struct *);
+static DECLARE_DELAYED_WORK(laundromat_work, laundromat_main);
+
+static void
 laundromat_main(struct work_struct *not_used)
 {
        time_t t;
@@ -1975,6 +1975,26 @@ io_during_grace_disallowed(struct inode *inode, int flags)
                && mandatory_lock(inode);
 }
 
+static int check_stateid_generation(stateid_t *in, stateid_t *ref)
+{
+       /* If the client sends us a stateid from the future, it's buggy: */
+       if (in->si_generation > ref->si_generation)
+               return nfserr_bad_stateid;
+       /*
+        * The following, however, can happen.  For example, if the
+        * client sends an open and some IO at the same time, the open
+        * may bump si_generation while the IO is still in flight.
+        * Thanks to hard links and renames, the client never knows what
+        * file an open will affect.  So it could avoid that situation
+        * only by serializing all opens and IO from the same open
+        * owner.  To recover from the old_stateid error, the client
+        * will just have to retry the IO:
+        */
+       if (in->si_generation < ref->si_generation)
+               return nfserr_old_stateid;
+       return nfs_ok;
+}
+
 /*
 * Checks for stateid operations
 */
@@ -2023,12 +2043,8 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl
                        goto out;
                stidp = &stp->st_stateid;
        }
-       if (stateid->si_generation > stidp->si_generation)
-               goto out;
-
-       /* OLD STATEID */
-       status = nfserr_old_stateid;
-       if (stateid->si_generation < stidp->si_generation)
+       status = check_stateid_generation(stateid, stidp);
+       if (status)
                goto out;
        if (stp) {
                if ((status = nfs4_check_openmode(stp,flags)))
@@ -2036,7 +2052,7 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl
                renew_client(stp->st_stateowner->so_client);
                if (filpp)
                        *filpp = stp->st_vfs_file;
-       } else if (dp) {
+       } else {
                if ((status = nfs4_check_delegmode(dp, flags)))
                        goto out;
                renew_client(dp->dl_client);
@@ -2065,6 +2081,7 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei
 {
        struct nfs4_stateid *stp;
        struct nfs4_stateowner *sop;
+       __be32 status;
 
        dprintk("NFSD: preprocess_seqid_op: seqid=%d " 
                        "stateid = (%08x/%08x/%08x/%08x)\n", seqid,
@@ -2127,7 +2144,7 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei
                }
        }
 
-       if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp)) {
+       if (nfs4_check_fh(current_fh, stp)) {
                dprintk("NFSD: preprocess_seqid_op: fh-stateid mismatch!\n");
                return nfserr_bad_stateid;
        }
@@ -2150,15 +2167,9 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei
                                " confirmed yet!\n");
                return nfserr_bad_stateid;
        }
-       if (stateid->si_generation > stp->st_stateid.si_generation) {
-               dprintk("NFSD: preprocess_seqid_op: future stateid?!\n");
-               return nfserr_bad_stateid;
-       }
-
-       if (stateid->si_generation < stp->st_stateid.si_generation) {
-               dprintk("NFSD: preprocess_seqid_op: old stateid!\n");
-               return nfserr_old_stateid;
-       }
+       status = check_stateid_generation(stateid, &stp->st_stateid);
+       if (status)
+               return status;
        renew_client(sop->so_client);
        return nfs_ok;
 
@@ -2194,7 +2205,7 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 
        if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh,
                                        oc->oc_seqid, &oc->oc_req_stateid,
-                                       CHECK_FH | CONFIRM | OPEN_STATE,
+                                       CONFIRM | OPEN_STATE,
                                        &oc->oc_stateowner, &stp, NULL)))
                goto out; 
 
@@ -2265,7 +2276,7 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp,
        if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh,
                                        od->od_seqid,
                                        &od->od_stateid, 
-                                       CHECK_FH | OPEN_STATE, 
+                                       OPEN_STATE,
                                        &od->od_stateowner, &stp, NULL)))
                goto out; 
 
@@ -2318,7 +2329,7 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh,
                                        close->cl_seqid,
                                        &close->cl_stateid, 
-                                       CHECK_FH | OPEN_STATE | CLOSE_STATE,
+                                       OPEN_STATE | CLOSE_STATE,
                                        &close->cl_stateowner, &stp, NULL)))
                goto out; 
        status = nfs_ok;
@@ -2623,7 +2634,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                status = nfs4_preprocess_seqid_op(&cstate->current_fh,
                                        lock->lk_new_open_seqid,
                                        &lock->lk_new_open_stateid,
-                                       CHECK_FH | OPEN_STATE,
+                                       OPEN_STATE,
                                        &lock->lk_replay_owner, &open_stp,
                                        lock);
                if (status)
@@ -2650,7 +2661,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                status = nfs4_preprocess_seqid_op(&cstate->current_fh,
                                       lock->lk_old_lock_seqid, 
                                       &lock->lk_old_lock_stateid, 
-                                      CHECK_FH | LOCK_STATE, 
+                                      LOCK_STATE,
                                       &lock->lk_replay_owner, &lock_stp, lock);
                if (status)
                        goto out;
@@ -2847,7 +2858,7 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh,
                                        locku->lu_seqid, 
                                        &locku->lu_stateid, 
-                                       CHECK_FH | LOCK_STATE, 
+                                       LOCK_STATE,
                                        &locku->lu_stateowner, &stp, NULL)))
                goto out;
 
index 0e6a179eccaf99e7635b31284cc04614fc5604bb..1ba7ad981935d6f455d5c3185c78ba0842913898 100644 (file)
@@ -1867,6 +1867,15 @@ out_serverfault:
        goto out;
 }
 
+static inline int attributes_need_mount(u32 *bmval)
+{
+       if (bmval[0] & ~(FATTR4_WORD0_RDATTR_ERROR | FATTR4_WORD0_LEASE_TIME))
+               return 1;
+       if (bmval[1] & ~FATTR4_WORD1_MOUNTED_ON_FILEID)
+               return 1;
+       return 0;
+}
+
 static __be32
 nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd,
                const char *name, int namlen, __be32 *p, int *buflen)
@@ -1888,9 +1897,7 @@ nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd,
         * we will not follow the cross mount and will fill the attribtutes
         * directly from the mountpoint dentry.
         */
-       if (d_mountpoint(dentry) &&
-           (cd->rd_bmval[0] & ~FATTR4_WORD0_RDATTR_ERROR) == 0 &&
-           (cd->rd_bmval[1] & ~FATTR4_WORD1_MOUNTED_ON_FILEID) == 0)
+       if (d_mountpoint(dentry) && !attributes_need_mount(cd->rd_bmval))
                ignore_crossmnt = 1;
        else if (d_mountpoint(dentry)) {
                int err;
index 8516137cdbb055ac87d1673c482126d2e670f488..613bcb8171a5da1a649f5a5ab01601e42830a9f5 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/nfsd/syscall.h>
 
 #include <asm/uaccess.h>
+#include <net/ipv6.h>
 
 /*
  *     We have a single directory with 9 nodes in it.
@@ -149,7 +150,6 @@ static const struct file_operations transaction_ops = {
        .release        = simple_transaction_release,
 };
 
-extern struct seq_operations nfs_exports_op;
 static int exports_open(struct inode *inode, struct file *file)
 {
        return seq_open(file, &nfs_exports_op);
@@ -222,6 +222,7 @@ static ssize_t write_getfs(struct file *file, char *buf, size_t size)
        struct auth_domain *clp;
        int err = 0;
        struct knfsd_fh *res;
+       struct in6_addr in6;
 
        if (size < sizeof(*data))
                return -EINVAL;
@@ -236,7 +237,11 @@ static ssize_t write_getfs(struct file *file, char *buf, size_t size)
        res = (struct knfsd_fh*)buf;
 
        exp_readlock();
-       if (!(clp = auth_unix_lookup(sin->sin_addr)))
+
+       ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &in6);
+
+       clp = auth_unix_lookup(&in6);
+       if (!clp)
                err = -EPERM;
        else {
                err = exp_rootfh(clp, data->gd_path, res, data->gd_maxlen);
@@ -257,6 +262,7 @@ static ssize_t write_getfd(struct file *file, char *buf, size_t size)
        int err = 0;
        struct knfsd_fh fh;
        char *res;
+       struct in6_addr in6;
 
        if (size < sizeof(*data))
                return -EINVAL;
@@ -271,7 +277,11 @@ static ssize_t write_getfd(struct file *file, char *buf, size_t size)
        res = buf;
        sin = (struct sockaddr_in *)&data->gd_addr;
        exp_readlock();
-       if (!(clp = auth_unix_lookup(sin->sin_addr)))
+
+       ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &in6);
+
+       clp = auth_unix_lookup(&in6);
+       if (!clp)
                err = -EPERM;
        else {
                err = exp_rootfh(clp, data->gd_path, &fh, NFS_FHSIZE);
@@ -347,8 +357,6 @@ static ssize_t write_filehandle(struct file *file, char *buf, size_t size)
        return mesg - buf;      
 }
 
-extern int nfsd_nrthreads(void);
-
 static ssize_t write_threads(struct file *file, char *buf, size_t size)
 {
        /* if size > 0, look for a number of threads and call nfsd_svc
@@ -371,10 +379,6 @@ static ssize_t write_threads(struct file *file, char *buf, size_t size)
        return strlen(buf);
 }
 
-extern int nfsd_nrpools(void);
-extern int nfsd_get_nrthreads(int n, int *);
-extern int nfsd_set_nrthreads(int n, int *);
-
 static ssize_t write_pool_threads(struct file *file, char *buf, size_t size)
 {
        /* if size > 0, look for an array of number of threads per node
index 3e6b3f41ee1f342918e6e3f57493f3c0ab21b033..100ae5641162b97c7fb0e57032a9b30ecc5b899e 100644 (file)
@@ -112,6 +112,124 @@ static __be32 nfsd_setuser_and_check_port(struct svc_rqst *rqstp,
        return nfserrno(nfsd_setuser(rqstp, exp));
 }
 
+/*
+ * Use the given filehandle to look up the corresponding export and
+ * dentry.  On success, the results are used to set fh_export and
+ * fh_dentry.
+ */
+static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp)
+{
+       struct knfsd_fh *fh = &fhp->fh_handle;
+       struct fid *fid = NULL, sfid;
+       struct svc_export *exp;
+       struct dentry *dentry;
+       int fileid_type;
+       int data_left = fh->fh_size/4;
+       __be32 error;
+
+       error = nfserr_stale;
+       if (rqstp->rq_vers > 2)
+               error = nfserr_badhandle;
+       if (rqstp->rq_vers == 4 && fh->fh_size == 0)
+               return nfserr_nofilehandle;
+
+       if (fh->fh_version == 1) {
+               int len;
+
+               if (--data_left < 0)
+                       return error;
+               if (fh->fh_auth_type != 0)
+                       return error;
+               len = key_len(fh->fh_fsid_type) / 4;
+               if (len == 0)
+                       return error;
+               if  (fh->fh_fsid_type == FSID_MAJOR_MINOR) {
+                       /* deprecated, convert to type 3 */
+                       len = key_len(FSID_ENCODE_DEV)/4;
+                       fh->fh_fsid_type = FSID_ENCODE_DEV;
+                       fh->fh_fsid[0] = new_encode_dev(MKDEV(ntohl(fh->fh_fsid[0]), ntohl(fh->fh_fsid[1])));
+                       fh->fh_fsid[1] = fh->fh_fsid[2];
+               }
+               data_left -= len;
+               if (data_left < 0)
+                       return error;
+               exp = rqst_exp_find(rqstp, fh->fh_fsid_type, fh->fh_auth);
+               fid = (struct fid *)(fh->fh_auth + len);
+       } else {
+               __u32 tfh[2];
+               dev_t xdev;
+               ino_t xino;
+
+               if (fh->fh_size != NFS_FHSIZE)
+                       return error;
+               /* assume old filehandle format */
+               xdev = old_decode_dev(fh->ofh_xdev);
+               xino = u32_to_ino_t(fh->ofh_xino);
+               mk_fsid(FSID_DEV, tfh, xdev, xino, 0, NULL);
+               exp = rqst_exp_find(rqstp, FSID_DEV, tfh);
+       }
+
+       error = nfserr_stale;
+       if (PTR_ERR(exp) == -ENOENT)
+               return error;
+
+       if (IS_ERR(exp))
+               return nfserrno(PTR_ERR(exp));
+
+       error = nfsd_setuser_and_check_port(rqstp, exp);
+       if (error)
+               goto out;
+
+       /*
+        * Look up the dentry using the NFS file handle.
+        */
+       error = nfserr_stale;
+       if (rqstp->rq_vers > 2)
+               error = nfserr_badhandle;
+
+       if (fh->fh_version != 1) {
+               sfid.i32.ino = fh->ofh_ino;
+               sfid.i32.gen = fh->ofh_generation;
+               sfid.i32.parent_ino = fh->ofh_dirino;
+               fid = &sfid;
+               data_left = 3;
+               if (fh->ofh_dirino == 0)
+                       fileid_type = FILEID_INO32_GEN;
+               else
+                       fileid_type = FILEID_INO32_GEN_PARENT;
+       } else
+               fileid_type = fh->fh_fileid_type;
+
+       if (fileid_type == FILEID_ROOT)
+               dentry = dget(exp->ex_path.dentry);
+       else {
+               dentry = exportfs_decode_fh(exp->ex_path.mnt, fid,
+                               data_left, fileid_type,
+                               nfsd_acceptable, exp);
+       }
+       if (dentry == NULL)
+               goto out;
+       if (IS_ERR(dentry)) {
+               if (PTR_ERR(dentry) != -EINVAL)
+                       error = nfserrno(PTR_ERR(dentry));
+               goto out;
+       }
+
+       if (S_ISDIR(dentry->d_inode->i_mode) &&
+                       (dentry->d_flags & DCACHE_DISCONNECTED)) {
+               printk("nfsd: find_fh_dentry returned a DISCONNECTED directory: %s/%s\n",
+                               dentry->d_parent->d_name.name, dentry->d_name.name);
+       }
+
+       fhp->fh_dentry = dentry;
+       fhp->fh_export = exp;
+       nfsd_nr_verified++;
+       return 0;
+out:
+       exp_put(exp);
+       return error;
+}
+
 /*
  * Perform sanity checks on the dentry in a client's file handle.
  *
@@ -124,115 +242,18 @@ static __be32 nfsd_setuser_and_check_port(struct svc_rqst *rqstp,
 __be32
 fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
 {
-       struct knfsd_fh *fh = &fhp->fh_handle;
-       struct svc_export *exp = NULL;
+       struct svc_export *exp;
        struct dentry   *dentry;
-       __be32          error = 0;
+       __be32          error;
 
        dprintk("nfsd: fh_verify(%s)\n", SVCFH_fmt(fhp));
 
        if (!fhp->fh_dentry) {
-               struct fid *fid = NULL, sfid;
-               int fileid_type;
-               int data_left = fh->fh_size/4;
-
-               error = nfserr_stale;
-               if (rqstp->rq_vers > 2)
-                       error = nfserr_badhandle;
-               if (rqstp->rq_vers == 4 && fh->fh_size == 0)
-                       return nfserr_nofilehandle;
-
-               if (fh->fh_version == 1) {
-                       int len;
-                       if (--data_left<0) goto out;
-                       switch (fh->fh_auth_type) {
-                       case 0: break;
-                       default: goto out;
-                       }
-                       len = key_len(fh->fh_fsid_type) / 4;
-                       if (len == 0) goto out;
-                       if  (fh->fh_fsid_type == FSID_MAJOR_MINOR) {
-                               /* deprecated, convert to type 3 */
-                               len = key_len(FSID_ENCODE_DEV)/4;
-                               fh->fh_fsid_type = FSID_ENCODE_DEV;
-                               fh->fh_fsid[0] = new_encode_dev(MKDEV(ntohl(fh->fh_fsid[0]), ntohl(fh->fh_fsid[1])));
-                               fh->fh_fsid[1] = fh->fh_fsid[2];
-                       }
-                       if ((data_left -= len)<0) goto out;
-                       exp = rqst_exp_find(rqstp, fh->fh_fsid_type,
-                                           fh->fh_auth);
-                       fid = (struct fid *)(fh->fh_auth + len);
-               } else {
-                       __u32 tfh[2];
-                       dev_t xdev;
-                       ino_t xino;
-                       if (fh->fh_size != NFS_FHSIZE)
-                               goto out;
-                       /* assume old filehandle format */
-                       xdev = old_decode_dev(fh->ofh_xdev);
-                       xino = u32_to_ino_t(fh->ofh_xino);
-                       mk_fsid(FSID_DEV, tfh, xdev, xino, 0, NULL);
-                       exp = rqst_exp_find(rqstp, FSID_DEV, tfh);
-               }
-
-               error = nfserr_stale;
-               if (PTR_ERR(exp) == -ENOENT)
-                       goto out;
-
-               if (IS_ERR(exp)) {
-                       error = nfserrno(PTR_ERR(exp));
-                       goto out;
-               }
-
-               error = nfsd_setuser_and_check_port(rqstp, exp);
+               error = nfsd_set_fh_dentry(rqstp, fhp);
                if (error)
                        goto out;
-
-               /*
-                * Look up the dentry using the NFS file handle.
-                */
-               error = nfserr_stale;
-               if (rqstp->rq_vers > 2)
-                       error = nfserr_badhandle;
-
-               if (fh->fh_version != 1) {
-                       sfid.i32.ino = fh->ofh_ino;
-                       sfid.i32.gen = fh->ofh_generation;
-                       sfid.i32.parent_ino = fh->ofh_dirino;
-                       fid = &sfid;
-                       data_left = 3;
-                       if (fh->ofh_dirino == 0)
-                               fileid_type = FILEID_INO32_GEN;
-                       else
-                               fileid_type = FILEID_INO32_GEN_PARENT;
-               } else
-                       fileid_type = fh->fh_fileid_type;
-
-               if (fileid_type == FILEID_ROOT)
-                       dentry = dget(exp->ex_path.dentry);
-               else {
-                       dentry = exportfs_decode_fh(exp->ex_path.mnt, fid,
-                                       data_left, fileid_type,
-                                       nfsd_acceptable, exp);
-               }
-               if (dentry == NULL)
-                       goto out;
-               if (IS_ERR(dentry)) {
-                       if (PTR_ERR(dentry) != -EINVAL)
-                               error = nfserrno(PTR_ERR(dentry));
-                       goto out;
-               }
-
-               if (S_ISDIR(dentry->d_inode->i_mode) &&
-                   (dentry->d_flags & DCACHE_DISCONNECTED)) {
-                       printk("nfsd: find_fh_dentry returned a DISCONNECTED directory: %s/%s\n",
-                              dentry->d_parent->d_name.name, dentry->d_name.name);
-               }
-
-               fhp->fh_dentry = dentry;
-               fhp->fh_export = exp;
-               nfsd_nr_verified++;
-               cache_get(&exp->h);
+               dentry = fhp->fh_dentry;
+               exp = fhp->fh_export;
        } else {
                /*
                 * just rechecking permissions
@@ -242,7 +263,6 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
                dprintk("nfsd: fh_verify - just checking\n");
                dentry = fhp->fh_dentry;
                exp = fhp->fh_export;
-               cache_get(&exp->h);
                /*
                 * Set user creds for this exportpoint; necessary even
                 * in the "just checking" case because this may be a
@@ -281,8 +301,6 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
                        access, ntohl(error));
        }
 out:
-       if (exp && !IS_ERR(exp))
-               exp_put(exp);
        if (error == nfserr_stale)
                nfsdstats.fh_stale++;
        return error;
index 9647b0f7bc0c0d52610bf1419c9bafcd466b57dc..941041f4b1365fb72f77558aa93b376f9d5818fb 100644 (file)
@@ -244,7 +244,6 @@ static int nfsd_init_socks(int port)
        if (error < 0)
                return error;
 
-#ifdef CONFIG_NFSD_TCP
        error = lockd_up(IPPROTO_TCP);
        if (error >= 0) {
                error = svc_create_xprt(nfsd_serv, "tcp", port,
@@ -254,7 +253,6 @@ static int nfsd_init_socks(int port)
        }
        if (error < 0)
                return error;
-#endif
        return 0;
 }
 
index 304bf5f643c944e5dae2607798310ff3299aff22..a3a291f771f40de4467142b7401b8c10d91d0810 100644 (file)
@@ -264,7 +264,6 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
        struct inode    *inode;
        int             accmode = MAY_SATTR;
        int             ftype = 0;
-       int             imode;
        __be32          err;
        int             host_err;
        int             size_change = 0;
@@ -360,25 +359,25 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
                DQUOT_INIT(inode);
        }
 
-       imode = inode->i_mode;
+       /* sanitize the mode change */
        if (iap->ia_valid & ATTR_MODE) {
                iap->ia_mode &= S_IALLUGO;
-               imode = iap->ia_mode |= (imode & ~S_IALLUGO);
-               /* if changing uid/gid revoke setuid/setgid in mode */
-               if ((iap->ia_valid & ATTR_UID) && iap->ia_uid != inode->i_uid) {
-                       iap->ia_valid |= ATTR_KILL_PRIV;
+               iap->ia_mode |= (inode->i_mode & ~S_IALLUGO);
+       }
+
+       /* Revoke setuid/setgid on chown */
+       if (((iap->ia_valid & ATTR_UID) && iap->ia_uid != inode->i_uid) ||
+           ((iap->ia_valid & ATTR_GID) && iap->ia_gid != inode->i_gid)) {
+               iap->ia_valid |= ATTR_KILL_PRIV;
+               if (iap->ia_valid & ATTR_MODE) {
+                       /* we're setting mode too, just clear the s*id bits */
                        iap->ia_mode &= ~S_ISUID;
+                       if (iap->ia_mode & S_IXGRP)
+                               iap->ia_mode &= ~S_ISGID;
+               } else {
+                       /* set ATTR_KILL_* bits and let VFS handle it */
+                       iap->ia_valid |= (ATTR_KILL_SUID | ATTR_KILL_SGID);
                }
-               if ((iap->ia_valid & ATTR_GID) && iap->ia_gid != inode->i_gid)
-                       iap->ia_mode &= ~S_ISGID;
-       } else {
-               /*
-                * Revoke setuid/setgid bit on chown/chgrp
-                */
-               if ((iap->ia_valid & ATTR_UID) && iap->ia_uid != inode->i_uid)
-                       iap->ia_valid |= ATTR_KILL_SUID | ATTR_KILL_PRIV;
-               if ((iap->ia_valid & ATTR_GID) && iap->ia_gid != inode->i_gid)
-                       iap->ia_valid |= ATTR_KILL_SGID;
        }
 
        /* Change the attributes. */
@@ -988,7 +987,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
         * flushing the data to disk is handled separately below.
         */
 
-       if (file->f_op->fsync == 0) {/* COMMIT3 cannot work */
+       if (!file->f_op->fsync) {/* COMMIT3 cannot work */
               stable = 2;
               *stablep = 2; /* FILE_SYNC */
        }
@@ -1152,7 +1151,7 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp,
 }
 #endif /* CONFIG_NFSD_V3 */
 
-__be32
+static __be32
 nfsd_create_setattr(struct svc_rqst *rqstp, struct svc_fh *resfhp,
                        struct iattr *iap)
 {
diff --git a/include/asm-blackfin/.gitignore b/include/asm-blackfin/.gitignore
new file mode 100644 (file)
index 0000000..7858564
--- /dev/null
@@ -0,0 +1 @@
++mach
index 5dba3a735596d495fafd8726dcb33e4677418bfc..716df7c8592322d2b8e851a81a0dcefb7efe0bf4 100644 (file)
@@ -112,20 +112,10 @@ extern void init_leds(void);
 
 extern const char bfin_board_name[];
 extern unsigned long wall_jiffies;
-extern unsigned long ipdt_table[];
-extern unsigned long dpdt_table[];
-extern unsigned long icplb_table[];
-extern unsigned long dcplb_table[];
-
-extern unsigned long ipdt_swapcount_table[];
-extern unsigned long dpdt_swapcount_table[];
-
-extern unsigned long table_start, table_end;
 
 extern unsigned long bfin_sic_iwr[];
 extern u16 _bfin_swrst; /* shadow for Software Reset Register (SWRST) */
 extern struct file_operations dpmc_fops;
-extern char _start;
 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[],
index 41e53b29f167cba5159180a35feb2b14b0d07f65..6d3e11b1fc576c6f141c98e3086e477c691a23df 100644 (file)
@@ -1,4 +1,17 @@
 #ifndef _BLACKFIN_BUG_H
 #define _BLACKFIN_BUG_H
+
+#ifdef CONFIG_BUG
+#define HAVE_ARCH_BUG
+
+#define BUG() do { \
+       dump_bfin_trace_buffer(); \
+       printk(KERN_EMERG "BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \
+       panic("BUG!"); \
+} while (0)
+
+#endif
+
 #include <asm-generic/bug.h>
+
 #endif
index 654375c2b7468214fc534ad77daf58e42bc1c642..5b0da9a69b6714529f38b759b9145d898f5bbb60 100644 (file)
 #define ASYNC_MEMORY_CPLB_COVERAGE     ((ASYNC_BANK0_SIZE + ASYNC_BANK1_SIZE + \
                                 ASYNC_BANK2_SIZE + ASYNC_BANK3_SIZE) / SIZE_4M)
 
-/*
-* Number of required data CPLB switchtable entries
-* MEMSIZE / 4 (we mostly install 4M page size CPLBs
-* approx 16 for smaller 1MB page size CPLBs for allignment purposes
-* 1 for L1 Data Memory
-* possibly 1 for L2 Data Memory
-* 1 for CONFIG_DEBUG_HUNT_FOR_ZERO
-* 1 for ASYNC Memory
-*/
-
-
-#define MAX_SWITCH_D_CPLBS (((CONFIG_MEM_SIZE / 4) + 16 + 1 + 1 + 1 \
-                                + ASYNC_MEMORY_CPLB_COVERAGE) * 2)
-
-/*
-* Number of required instruction CPLB switchtable entries
-* MEMSIZE / 4 (we mostly install 4M page size CPLBs
-* approx 12 for smaller 1MB page size CPLBs for allignment purposes
-* 1 for L1 Instruction Memory
-* possibly 1 for L2 Instruction Memory
-* 1 for CONFIG_DEBUG_HUNT_FOR_ZERO
-*/
-
-#define MAX_SWITCH_I_CPLBS (((CONFIG_MEM_SIZE / 4) + 12 + 1 + 1 + 1) * 2)
-
-
 #define CPLB_ENABLE_ICACHE_P   0
 #define CPLB_ENABLE_DCACHE_P   1
 #define CPLB_ENABLE_DCACHE2_P  2
index 282fabccf6a6204b64b9caff45de5bcd2ee3da8c..1a13c2fc3667326a78b7267cf27fb71de75922f5 100644 (file)
@@ -27,6 +27,14 @@ void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
 extern dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
                                 enum dma_data_direction direction);
 
+static inline dma_addr_t
+dma_map_page(struct device *dev, struct page *page,
+            unsigned long offset, size_t size,
+            enum dma_data_direction dir)
+{
+       return dma_map_single(dev, page_address(page) + offset, size, dir);
+}
+
 /*
  * Unmap a single streaming mode DMA translation.  The dma_addr and size
  * must match what was provided for in a previous pci_map_single call.  All
@@ -38,6 +46,13 @@ extern dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
 extern void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
                          enum dma_data_direction direction);
 
+static inline void
+dma_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
+              enum dma_data_direction dir)
+{
+       dma_unmap_single(dev, dma_addr, size, dir);
+}
+
 /*
  * Map a set of buffers described by scatterlist in streaming
  * mode for DMA.  This is the scather-gather version of the
index 16d493574ba8cb97e4ee78a2cd62420909e4b6bd..c0d5259e315b05f155d3bcc9dd299b5fb0062679 100644 (file)
@@ -191,4 +191,7 @@ void clear_dma_irqstat(unsigned int channel);
 void *dma_memcpy(void *dest, const void *src, size_t count);
 void *safe_dma_memcpy(void *dest, const void *src, size_t count);
 
+extern int channel2irq(unsigned int channel);
+extern struct dma_register *dma_io_base_addr[MAX_BLACKFIN_DMA_CHANNEL];
+
 #endif
index 4f318f1fd2d901214b5771c53d3e19854db971c6..0520d2aac8f3f2d1cf600a31ff964b2643732e6b 100644 (file)
 # define MAX_BLACKFIN_GPTIMERS 8
 # define TIMER0_GROUP_REG      TIMER_ENABLE
 #endif
+/*
+ * BF54x: 11 timers (BF542: 8 timers):
+ */
+#if defined(BF548_FAMILY)
+# ifdef CONFIG_BF542
+#  define MAX_BLACKFIN_GPTIMERS 8
+# else
+#  define MAX_BLACKFIN_GPTIMERS 11
+#  define TIMER8_GROUP_REG      TIMER_ENABLE1
+# endif
+# define TIMER0_GROUP_REG       TIMER_ENABLE0
+#endif
 /*
  * BF561: 12 timers:
  */
 #define TIMER0bit  0x0001  /*  0001b */
 #define TIMER1bit  0x0002  /*  0010b */
 #define TIMER2bit  0x0004  /*  0100b */
-
-#if (MAX_BLACKFIN_GPTIMERS > 3)
-# define TIMER3bit  0x0008
-# define TIMER4bit  0x0010
-# define TIMER5bit  0x0020
-# define TIMER6bit  0x0040
-# define TIMER7bit  0x0080
-#endif
-
-#if (MAX_BLACKFIN_GPTIMERS > 8)
-# define TIMER8bit  0x0100
-# define TIMER9bit  0x0200
-# define TIMER10bit 0x0400
-# define TIMER11bit 0x0800
-#endif
+#define TIMER3bit  0x0008
+#define TIMER4bit  0x0010
+#define TIMER5bit  0x0020
+#define TIMER6bit  0x0040
+#define TIMER7bit  0x0080
+#define TIMER8bit  0x0100
+#define TIMER9bit  0x0200
+#define TIMER10bit 0x0400
+#define TIMER11bit 0x0800
 
 #define TIMER0_id   0
 #define TIMER1_id   1
 #define TIMER2_id   2
-
-#if (MAX_BLACKFIN_GPTIMERS > 3)
-# define TIMER3_id   3
-# define TIMER4_id   4
-# define TIMER5_id   5
-# define TIMER6_id   6
-# define TIMER7_id   7
-#endif
-
-#if (MAX_BLACKFIN_GPTIMERS > 8)
-# define TIMER8_id   8
-# define TIMER9_id   9
-# define TIMER10_id 10
-# define TIMER11_id 11
-#endif
+#define TIMER3_id   3
+#define TIMER4_id   4
+#define TIMER5_id   5
+#define TIMER6_id   6
+#define TIMER7_id   7
+#define TIMER8_id   8
+#define TIMER9_id   9
+#define TIMER10_id 10
+#define TIMER11_id 11
 
 /* associated timers for ppi framesync: */
 
 /*
  * Timer Status Register Bits
  */
-#define TIMER_STATUS_TIMIL0 0x0001
-#define TIMER_STATUS_TIMIL1 0x0002
-#define TIMER_STATUS_TIMIL2 0x0004
-#if (MAX_BLACKFIN_GPTIMERS > 3)
-# define TIMER_STATUS_TIMIL3 0x00000008
-# define TIMER_STATUS_TIMIL4 0x00010000
-# define TIMER_STATUS_TIMIL5 0x00020000
-# define TIMER_STATUS_TIMIL6 0x00040000
-# define TIMER_STATUS_TIMIL7 0x00080000
-# if (MAX_BLACKFIN_GPTIMERS > 8)
-#  define TIMER_STATUS_TIMIL8  0x0001
-#  define TIMER_STATUS_TIMIL9  0x0002
-#  define TIMER_STATUS_TIMIL10 0x0004
-#  define TIMER_STATUS_TIMIL11 0x0008
-# endif
-# define TIMER_STATUS_INTR   0x000F000F
-#else
-# define TIMER_STATUS_INTR   0x0007    /* any timer interrupt */
-#endif
-
-#define TIMER_STATUS_TOVF0  0x0010     /* timer 0 overflow error */
-#define TIMER_STATUS_TOVF1  0x0020
-#define TIMER_STATUS_TOVF2  0x0040
-#if (MAX_BLACKFIN_GPTIMERS > 3)
-# define TIMER_STATUS_TOVF3  0x00000080
-# define TIMER_STATUS_TOVF4  0x00100000
-# define TIMER_STATUS_TOVF5  0x00200000
-# define TIMER_STATUS_TOVF6  0x00400000
-# define TIMER_STATUS_TOVF7  0x00800000
-# if (MAX_BLACKFIN_GPTIMERS > 8)
-#  define TIMER_STATUS_TOVF8   0x0010
-#  define TIMER_STATUS_TOVF9   0x0020
-#  define TIMER_STATUS_TOVF10  0x0040
-#  define TIMER_STATUS_TOVF11  0x0080
-# endif
-# define TIMER_STATUS_OFLOW  0x00F000F0
-#else
-# define TIMER_STATUS_OFLOW  0x0070    /* any timer overflow */
-#endif
+#define TIMER_STATUS_TIMIL0  0x0001
+#define TIMER_STATUS_TIMIL1  0x0002
+#define TIMER_STATUS_TIMIL2  0x0004
+#define TIMER_STATUS_TIMIL3  0x00000008
+#define TIMER_STATUS_TIMIL4  0x00010000
+#define TIMER_STATUS_TIMIL5  0x00020000
+#define TIMER_STATUS_TIMIL6  0x00040000
+#define TIMER_STATUS_TIMIL7  0x00080000
+#define TIMER_STATUS_TIMIL8  0x0001
+#define TIMER_STATUS_TIMIL9  0x0002
+#define TIMER_STATUS_TIMIL10 0x0004
+#define TIMER_STATUS_TIMIL11 0x0008
+
+#define TIMER_STATUS_TOVF0   0x0010    /* timer 0 overflow error */
+#define TIMER_STATUS_TOVF1   0x0020
+#define TIMER_STATUS_TOVF2   0x0040
+#define TIMER_STATUS_TOVF3   0x00000080
+#define TIMER_STATUS_TOVF4   0x00100000
+#define TIMER_STATUS_TOVF5   0x00200000
+#define TIMER_STATUS_TOVF6   0x00400000
+#define TIMER_STATUS_TOVF7   0x00800000
+#define TIMER_STATUS_TOVF8   0x0010
+#define TIMER_STATUS_TOVF9   0x0020
+#define TIMER_STATUS_TOVF10  0x0040
+#define TIMER_STATUS_TOVF11  0x0080
 
 /*
  * Timer Slave Enable Status : write 1 to clear
 #define TIMER_STATUS_TRUN0  0x1000
 #define TIMER_STATUS_TRUN1  0x2000
 #define TIMER_STATUS_TRUN2  0x4000
-#if (MAX_BLACKFIN_GPTIMERS > 3)
-# define TIMER_STATUS_TRUN3  0x00008000
-# define TIMER_STATUS_TRUN4  0x10000000
-# define TIMER_STATUS_TRUN5  0x20000000
-# define TIMER_STATUS_TRUN6  0x40000000
-# define TIMER_STATUS_TRUN7  0x80000000
-# define TIMER_STATUS_TRUN   0xF000F000
-# if (MAX_BLACKFIN_GPTIMERS > 8)
-#  define TIMER_STATUS_TRUN8  0x1000
-#  define TIMER_STATUS_TRUN9  0x2000
-#  define TIMER_STATUS_TRUN10 0x4000
-#  define TIMER_STATUS_TRUN11 0x8000
-# endif
-#else
-# define TIMER_STATUS_TRUN   0x7000
-#endif
+#define TIMER_STATUS_TRUN3  0x00008000
+#define TIMER_STATUS_TRUN4  0x10000000
+#define TIMER_STATUS_TRUN5  0x20000000
+#define TIMER_STATUS_TRUN6  0x40000000
+#define TIMER_STATUS_TRUN7  0x80000000
+#define TIMER_STATUS_TRUN   0xF000F000
+#define TIMER_STATUS_TRUN8  0x1000
+#define TIMER_STATUS_TRUN9  0x2000
+#define TIMER_STATUS_TRUN10 0x4000
+#define TIMER_STATUS_TRUN11 0x8000
 
 /* The actual gptimer API */
 
index a89120445be66e790403153add1e569ed456daa2..735fa02fafb2699af2d5abe203cd6a941bae4b9c 100644 (file)
@@ -2,12 +2,12 @@
  * File: include/asm-blackfin/mach-bf527/anomaly.h
  * Bugs: Enter bugs at http://blackfin.uclinux.org/
  *
- * Copyright (C) 2004-2007 Analog Devices Inc.
+ * Copyright (C) 2004-2008 Analog Devices Inc.
  * Licensed under the GPL-2 or later.
  */
 
 /* This file shoule be up to date with:
- *  - Revision A, May 30, 2007; ADSP-BF527 Blackfin Processor Anomaly List
+ *  - Revision C, 01/25/2008; ADSP-BF527 Blackfin Processor Anomaly List
  */
 
 #ifndef _MACH_ANOMALY_H_
 
 /* Multi-Issue Instruction with dsp32shiftimm in slot1 and P-reg Store in slot2 Not Supported */
 #define ANOMALY_05000074 (1)
-/* DMA_RUN Bit Is Not Valid after a Peripheral Receive Channel DMA Stops */
-#define ANOMALY_05000119 (1)
 /* Rx.H Cannot Be Used to Access 16-bit System MMR Registers */
 #define ANOMALY_05000122 (1)
 /* Spurious Hardware Error from an Access in the Shadow of a Conditional Branch */
 #define ANOMALY_05000245 (1)
 /* Sensitivity To Noise with Slow Input Edge Rates on External SPORT TX and RX Clocks */
 #define ANOMALY_05000265 (1)
-/* Memory-To-Memory DMA Source/Destination Descriptors Must Be in Same Memory Space */
-#define ANOMALY_05000301 (1)
-/* Errors When SSYNC, CSYNC, or Loads to LT, LB and LC Registers Are Interrupted */
-#define ANOMALY_05000312 (1)
 /* Incorrect Access of OTP_STATUS During otp_write() Function */
 #define ANOMALY_05000328 (1)
 /* Disallowed Configuration Prevents Subsequent Allowed Configuration on Host DMA Port */
 #define ANOMALY_05000337 (1)
-/* TWI Does Not Operate Correctly Under Certain Signal Termination Conditions */
+/* Ethernet MAC MDIO Reads Do Not Meet IEEE Specification */
+#define ANOMALY_05000341 (1)
+/* TWI May Not Operate Correctly Under Certain Signal Termination Conditions */
 #define ANOMALY_05000342 (1)
-/* Boot ROM Kernel Incorrectly Alters Reset Value of USB Register */
+/* USB Calibration Value Is Not Initialized */
+#define ANOMALY_05000346 (1)
+/* Preboot Routine Incorrectly Alters Reset Value of USB Register */
 #define ANOMALY_05000347 (1)
+/* Security Features Are Not Functional */
+#define ANOMALY_05000348 (__SILICON_REVISION__ < 1)
+/* Regulator Programming Blocked when Hibernate Wakeup Source Remains Active */
+#define ANOMALY_05000355 (1)
+/* Serial Port (SPORT) Multichannel Transmit Failure when Channel 0 Is Disabled */
+#define ANOMALY_05000357 (1)
+/* Incorrect Revision Number in DSPID Register */
+#define ANOMALY_05000364 (__SILICON_REVISION__ > 0)
+/* PPI Underflow Error Goes Undetected in ITU-R 656 Mode */
+#define ANOMALY_05000366 (1)
+/* New Feature: Higher Default CCLK Rate */
+#define ANOMALY_05000368 (1)
+/* Possible RETS Register Corruption when Subroutine Is under 5 Cycles in Duration */
+#define ANOMALY_05000371 (1)
+/* Authentication Fails To Initiate */
+#define ANOMALY_05000376 (__SILICON_REVISION__ > 0)
+/* Data Read From L3 Memory by USB DMA May be Corrupted */
+#define ANOMALY_05000380 (1)
+/* USB Full-speed Mode not Fully Tested */
+#define ANOMALY_05000381 (1)
+/* New Feature: Boot from OTP Memory */
+#define ANOMALY_05000385 (1)
+/* New Feature: bfrom_SysControl() Routine */
+#define ANOMALY_05000386 (1)
+/* New Feature: Programmable Preboot Settings */
+#define ANOMALY_05000387 (1)
+/* Reset Vector Must Not Be in SDRAM Memory Space */
+#define ANOMALY_05000389 (1)
+/* New Feature: pTempCurrent Added to ADI_BOOT_DATA Structure */
+#define ANOMALY_05000392 (1)
+/* New Feature: dTempByteCount Value Increased in ADI_BOOT_DATA Structure */
+#define ANOMALY_05000393 (1)
+/* New Feature: Log Buffer Functionality */
+#define ANOMALY_05000394 (1)
+/* New Feature: Hook Routine Functionality */
+#define ANOMALY_05000395 (1)
+/* New Feature: Header Indirect Bit */
+#define ANOMALY_05000396 (1)
+/* New Feature: BK_ONES, BK_ZEROS, and BK_DATECODE Constants */
+#define ANOMALY_05000397 (1)
+/* New Feature: SWRESET, DFRESET and WDRESET Bits Added to SYSCR Register */
+#define ANOMALY_05000398 (1)
+/* New Feature: BCODE_NOBOOT Added to BCODE Field of SYSCR Register */
+#define ANOMALY_05000399 (1)
+/* PPI Data Signals D0 and D8 do not Tristate After Disabling PPI */
+#define ANOMALY_05000401 (1)
 
 /* Anomalies that don't exist on this proc */
-#define ANOMALY_05000323 (0)
-#define ANOMALY_05000244 (0)
-#define ANOMALY_05000198 (0)
 #define ANOMALY_05000125 (0)
 #define ANOMALY_05000158 (0)
-#define ANOMALY_05000273 (0)
+#define ANOMALY_05000183 (0)
+#define ANOMALY_05000198 (0)
+#define ANOMALY_05000230 (0)
+#define ANOMALY_05000244 (0)
+#define ANOMALY_05000261 (0)
 #define ANOMALY_05000263 (0)
+#define ANOMALY_05000266 (0)
+#define ANOMALY_05000273 (0)
 #define ANOMALY_05000311 (0)
-#define ANOMALY_05000230 (0)
+#define ANOMALY_05000312 (0)
+#define ANOMALY_05000323 (0)
+#define ANOMALY_05000363 (0)
+
 #endif
index c0694ecd2ecde47ecb91b99c43e26bed588d28f2..f0ab2736a680415f42c25fc0714233d70b32994c 100644 (file)
@@ -1,22 +1,38 @@
+/*
+ * file:        include/asm-blackfin/mach-bf527/bfin_serial_5xx.h
+ * based on:
+ * author:
+ *
+ * created:
+ * description:
+ *     blackfin serial driver head file
+ * rev:
+ *
+ * modified:
+ *
+ *
+ * bugs:         enter bugs at http://blackfin.uclinux.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, 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; see the file copying.
+ * if not, write to the free software foundation,
+ * 59 temple place - suite 330, boston, ma 02111-1307, usa.
+ */
+
 #include <linux/serial.h>
 #include <asm/dma.h>
 #include <asm/portmux.h>
 
-#define NR_PORTS               2
-
-#define OFFSET_THR              0x00   /* Transmit Holding register            */
-#define OFFSET_RBR              0x00   /* Receive Buffer register              */
-#define OFFSET_DLL              0x00   /* Divisor Latch (Low-Byte)             */
-#define OFFSET_IER              0x04   /* Interrupt Enable Register            */
-#define OFFSET_DLH              0x04   /* Divisor Latch (High-Byte)            */
-#define OFFSET_IIR              0x08   /* Interrupt Identification Register    */
-#define OFFSET_LCR              0x0C   /* Line Control Register                */
-#define OFFSET_MCR              0x10   /* Modem Control Register               */
-#define OFFSET_LSR              0x14   /* Line Status Register                 */
-#define OFFSET_MSR              0x18   /* Modem Status Register                */
-#define OFFSET_SCR              0x1C   /* SCR Scratch Register                 */
-#define OFFSET_GCTL             0x24   /* Global Control Register              */
-
 #define UART_GET_CHAR(uart)     bfin_read16(((uart)->port.membase + OFFSET_RBR))
 #define UART_GET_DLL(uart)     bfin_read16(((uart)->port.membase + OFFSET_DLL))
 #define UART_GET_IER(uart)      bfin_read16(((uart)->port.membase + OFFSET_IER))
@@ -92,7 +108,7 @@ static inline void UART_CLEAR_LSR(struct bfin_serial_port *uart)
        bfin_write16(uart->port.membase + OFFSET_LSR, -1);
 }
 
-struct bfin_serial_port bfin_serial_ports[NR_PORTS];
+struct bfin_serial_port bfin_serial_ports[BFIN_UART_NR_PORTS];
 struct bfin_serial_res {
        unsigned long uart_base_addr;
        int uart_irq;
diff --git a/include/asm-blackfin/mach-bf527/bfin_sir.h b/include/asm-blackfin/mach-bf527/bfin_sir.h
new file mode 100644 (file)
index 0000000..0612d0c
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * Blackfin Infra-red Driver
+ *
+ * Copyright 2006-2008 Analog Devices Inc.
+ *
+ * Enter bugs at http://blackfin.uclinux.org/
+ *
+ * Licensed under the GPL-2 or later.
+ *
+ */
+
+#include <linux/serial.h>
+#include <asm/dma.h>
+#include <asm/portmux.h>
+
+#define SIR_UART_GET_CHAR(port)   bfin_read16((port)->membase + OFFSET_RBR)
+#define SIR_UART_GET_DLL(port)    bfin_read16((port)->membase + OFFSET_DLL)
+#define SIR_UART_GET_IER(port)    bfin_read16((port)->membase + OFFSET_IER)
+#define SIR_UART_GET_DLH(port)    bfin_read16((port)->membase + OFFSET_DLH)
+#define SIR_UART_GET_IIR(port)    bfin_read16((port)->membase + OFFSET_IIR)
+#define SIR_UART_GET_LCR(port)    bfin_read16((port)->membase + OFFSET_LCR)
+#define SIR_UART_GET_GCTL(port)   bfin_read16((port)->membase + OFFSET_GCTL)
+
+#define SIR_UART_PUT_CHAR(port, v) bfin_write16(((port)->membase + OFFSET_THR), v)
+#define SIR_UART_PUT_DLL(port, v)  bfin_write16(((port)->membase + OFFSET_DLL), v)
+#define SIR_UART_PUT_IER(port, v)  bfin_write16(((port)->membase + OFFSET_IER), v)
+#define SIR_UART_PUT_DLH(port, v)  bfin_write16(((port)->membase + OFFSET_DLH), v)
+#define SIR_UART_PUT_LCR(port, v)  bfin_write16(((port)->membase + OFFSET_LCR), v)
+#define SIR_UART_PUT_GCTL(port, v) bfin_write16(((port)->membase + OFFSET_GCTL), v)
+
+#ifdef CONFIG_SIR_BFIN_DMA
+struct dma_rx_buf {
+       char *buf;
+       int head;
+       int tail;
+       };
+#endif /* CONFIG_SIR_BFIN_DMA */
+
+struct bfin_sir_port {
+       unsigned char __iomem   *membase;
+       unsigned int            irq;
+       unsigned int            lsr;
+       unsigned long           clk;
+       struct net_device       *dev;
+#ifdef CONFIG_SIR_BFIN_DMA
+       int                     tx_done;
+       struct dma_rx_buf       rx_dma_buf;
+       struct timer_list       rx_dma_timer;
+       int                     rx_dma_nrows;
+#endif /* CONFIG_SIR_BFIN_DMA */
+       unsigned int            tx_dma_channel;
+       unsigned int            rx_dma_channel;
+};
+
+struct bfin_sir_port sir_ports[BFIN_UART_NR_PORTS];
+
+struct bfin_sir_port_res {
+       unsigned long   base_addr;
+       int             irq;
+       unsigned int    rx_dma_channel;
+       unsigned int    tx_dma_channel;
+};
+
+struct bfin_sir_port_res bfin_sir_port_resource[] = {
+#ifdef CONFIG_BFIN_SIR0
+       {
+       0xFFC00400,
+       IRQ_UART0_RX,
+       CH_UART0_RX,
+       CH_UART0_TX,
+       },
+#endif
+#ifdef CONFIG_BFIN_SIR1
+       {
+       0xFFC02000,
+       IRQ_UART1_RX,
+       CH_UART1_RX,
+       CH_UART1_TX,
+       },
+#endif
+};
+
+int nr_sirs = ARRAY_SIZE(bfin_sir_port_resource);
+
+struct bfin_sir_self {
+       struct bfin_sir_port    *sir_port;
+       spinlock_t              lock;
+       unsigned int            open;
+       int                     speed;
+       int                     newspeed;
+
+       struct sk_buff          *txskb;
+       struct sk_buff          *rxskb;
+       struct net_device_stats stats;
+       struct device           *dev;
+       struct irlap_cb         *irlap;
+       struct qos_info         qos;
+
+       iobuff_t                tx_buff;
+       iobuff_t                rx_buff;
+
+       struct work_struct      work;
+       int                     mtt;
+};
+
+static inline unsigned int SIR_UART_GET_LSR(struct bfin_sir_port *port)
+{
+       unsigned int lsr = bfin_read16(port->membase + OFFSET_LSR);
+       port->lsr |= (lsr & (BI|FE|PE|OE));
+       return lsr | port->lsr;
+}
+
+static inline void SIR_UART_CLEAR_LSR(struct bfin_sir_port *port)
+{
+       port->lsr = 0;
+       bfin_read16(port->membase + OFFSET_LSR);
+}
+
+#define DRIVER_NAME "bfin_sir"
+
+static void bfin_sir_hw_init(void)
+{
+#ifdef CONFIG_BFIN_SIR0
+       peripheral_request(P_UART0_TX, DRIVER_NAME);
+       peripheral_request(P_UART0_RX, DRIVER_NAME);
+#endif
+
+#ifdef CONFIG_BFIN_SIR1
+       peripheral_request(P_UART1_TX, DRIVER_NAME);
+       peripheral_request(P_UART1_RX, DRIVER_NAME);
+#endif
+       SSYNC();
+}
index 1bd07e30781c5581d72a928b9605d065f4cdfc07..2891727b61766809c085d1b5e29f646160c34fee 100644 (file)
 #define STATUS_P1      0x02
 #define STATUS_P0      0x01
 
+#define BFIN_UART_NR_PORTS     2
+
+#define OFFSET_THR              0x00   /* Transmit Holding register            */
+#define OFFSET_RBR              0x00   /* Receive Buffer register              */
+#define OFFSET_DLL              0x00   /* Divisor Latch (Low-Byte)             */
+#define OFFSET_IER              0x04   /* Interrupt Enable Register            */
+#define OFFSET_DLH              0x04   /* Divisor Latch (High-Byte)            */
+#define OFFSET_IIR              0x08   /* Interrupt Identification Register    */
+#define OFFSET_LCR              0x0C   /* Line Control Register                */
+#define OFFSET_MCR              0x10   /* Modem Control Register               */
+#define OFFSET_LSR              0x14   /* Line Status Register                 */
+#define OFFSET_MSR              0x18   /* Modem Status Register                */
+#define OFFSET_SCR              0x1C   /* SCR Scratch Register                 */
+#define OFFSET_GCTL             0x24   /* Global Control Register              */
+
 /* DPMC*/
 #define bfin_read_STOPCK_OFF() bfin_read_STOPCK()
 #define bfin_write_STOPCK_OFF(val) bfin_write_STOPCK(val)
index 3f4de5d9d4cb06d705462edf06b7acc35d962cfe..9dbdbec8ea1b93187ffb60ff7fbee48848c61911 100644 (file)
  */
 
 #ifndef _CDEF_BF52X_H
+#define _CDEF_BF52X_H
+
+#include <asm/system.h>
+#include <asm/blackfin.h>
 
 #include "defBF52x_base.h"
 
+/* Include core specific register pointer definitions                                                          */
+#include <asm/mach-common/cdef_LPBlackfin.h>
+
 /* ==== begin from cdefBF534.h ==== */
 
 /* Clock and System Control    (0xFFC00000 - 0xFFC000FF)                                                               */
 #define bfin_read_PLL_CTL()                    bfin_read16(PLL_CTL)
-#define bfin_write_PLL_CTL(val)                        bfin_write16(PLL_CTL, val)
+/* Writing to PLL_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_PLL_CTL(unsigned int val)
+{
+       unsigned long flags, iwr0, iwr1;
+
+       if (val == bfin_read_PLL_CTL())
+               return;
+
+       local_irq_save(flags);
+       /* Enable the PLL Wakeup bit in SIC IWR */
+       iwr0 = bfin_read32(SIC_IWR0);
+       iwr1 = bfin_read32(SIC_IWR1);
+       /* Only allow PPL Wakeup) */
+       bfin_write32(SIC_IWR0, IWR_ENABLE(0));
+       bfin_write32(SIC_IWR1, 0);
+
+       bfin_write16(PLL_CTL, val);
+       SSYNC();
+       asm("IDLE;");
+
+       bfin_write32(SIC_IWR0, iwr0);
+       bfin_write32(SIC_IWR1, iwr1);
+       local_irq_restore(flags);
+}
 #define bfin_read_PLL_DIV()                    bfin_read16(PLL_DIV)
 #define bfin_write_PLL_DIV(val)                        bfin_write16(PLL_DIV, val)
 #define bfin_read_VR_CTL()                     bfin_read16(VR_CTL)
-#define bfin_write_VR_CTL(val)                 bfin_write16(VR_CTL, val)
+/* Writing to VR_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_VR_CTL(unsigned int val)
+{
+       unsigned long flags, iwr0, iwr1;
+
+       if (val == bfin_read_VR_CTL())
+               return;
+
+       local_irq_save(flags);
+       /* Enable the PLL Wakeup bit in SIC IWR */
+       iwr0 = bfin_read32(SIC_IWR0);
+       iwr1 = bfin_read32(SIC_IWR1);
+       /* Only allow PPL Wakeup) */
+       bfin_write32(SIC_IWR0, IWR_ENABLE(0));
+       bfin_write32(SIC_IWR1, 0);
+
+       bfin_write16(VR_CTL, val);
+       SSYNC();
+       asm("IDLE;");
+
+       bfin_write32(SIC_IWR0, iwr0);
+       bfin_write32(SIC_IWR1, iwr1);
+       local_irq_restore(flags);
+}
 #define bfin_read_PLL_STAT()                   bfin_read16(PLL_STAT)
 #define bfin_write_PLL_STAT(val)               bfin_write16(PLL_STAT, val)
 #define bfin_read_PLL_LOCKCNT()                        bfin_read16(PLL_LOCKCNT)
 
 
 /* Two-Wire Interface          (0xFFC01400 - 0xFFC014FF)                                                               */
-#define bfin_read_TWI_CLKDIV()                 bfin_read16(TWI_CLKDIV)
-#define bfin_write_TWI_CLKDIV(val)             bfin_write16(TWI_CLKDIV, val)
-#define bfin_read_TWI_CONTROL()                        bfin_read16(TWI_CONTROL)
-#define bfin_write_TWI_CONTROL(val)            bfin_write16(TWI_CONTROL, val)
-#define bfin_read_TWI_SLAVE_CTL()              bfin_read16(TWI_SLAVE_CTL)
-#define bfin_write_TWI_SLAVE_CTL(val)          bfin_write16(TWI_SLAVE_CTL, val)
-#define bfin_read_TWI_SLAVE_STAT()             bfin_read16(TWI_SLAVE_STAT)
-#define bfin_write_TWI_SLAVE_STAT(val)         bfin_write16(TWI_SLAVE_STAT, val)
-#define bfin_read_TWI_SLAVE_ADDR()             bfin_read16(TWI_SLAVE_ADDR)
-#define bfin_write_TWI_SLAVE_ADDR(val)         bfin_write16(TWI_SLAVE_ADDR, val)
-#define bfin_read_TWI_MASTER_CTL()             bfin_read16(TWI_MASTER_CTL)
-#define bfin_write_TWI_MASTER_CTL(val)         bfin_write16(TWI_MASTER_CTL, val)
-#define bfin_read_TWI_MASTER_STAT()            bfin_read16(TWI_MASTER_STAT)
-#define bfin_write_TWI_MASTER_STAT(val)                bfin_write16(TWI_MASTER_STAT, val)
-#define bfin_read_TWI_MASTER_ADDR()            bfin_read16(TWI_MASTER_ADDR)
-#define bfin_write_TWI_MASTER_ADDR(val)                bfin_write16(TWI_MASTER_ADDR, val)
-#define bfin_read_TWI_INT_STAT()               bfin_read16(TWI_INT_STAT)
-#define bfin_write_TWI_INT_STAT(val)           bfin_write16(TWI_INT_STAT, val)
-#define bfin_read_TWI_INT_MASK()               bfin_read16(TWI_INT_MASK)
-#define bfin_write_TWI_INT_MASK(val)           bfin_write16(TWI_INT_MASK, val)
-#define bfin_read_TWI_FIFO_CTL()               bfin_read16(TWI_FIFO_CTL)
-#define bfin_write_TWI_FIFO_CTL(val)           bfin_write16(TWI_FIFO_CTL, val)
-#define bfin_read_TWI_FIFO_STAT()              bfin_read16(TWI_FIFO_STAT)
-#define bfin_write_TWI_FIFO_STAT(val)          bfin_write16(TWI_FIFO_STAT, val)
-#define bfin_read_TWI_XMT_DATA8()              bfin_read16(TWI_XMT_DATA8)
-#define bfin_write_TWI_XMT_DATA8(val)          bfin_write16(TWI_XMT_DATA8, val)
-#define bfin_read_TWI_XMT_DATA16()             bfin_read16(TWI_XMT_DATA16)
-#define bfin_write_TWI_XMT_DATA16(val)         bfin_write16(TWI_XMT_DATA16, val)
-#define bfin_read_TWI_RCV_DATA8()              bfin_read16(TWI_RCV_DATA8)
-#define bfin_write_TWI_RCV_DATA8(val)          bfin_write16(TWI_RCV_DATA8, val)
-#define bfin_read_TWI_RCV_DATA16()             bfin_read16(TWI_RCV_DATA16)
-#define bfin_write_TWI_RCV_DATA16(val)         bfin_write16(TWI_RCV_DATA16, val)
-
 
 /* General Purpose I/O Port G (0xFFC01500 - 0xFFC015FF)                                                                */
 #define bfin_read_PORTGIO()                    bfin_read16(PORTGIO)
index 2dfee12864f684010e99496942cca94858ff3f42..49dd693223e8739c62d3422e2cffc6226f21e7d6 100644 (file)
@@ -59,7 +59,4 @@
 #define CH_NFC                 CH_EMAC_TX /* PPI receive/transmit or NFC */
 #endif
 
-extern int channel2irq(unsigned int channel);
-extern struct dma_register *base_addr[];
-
 #endif
index 98209d40abbaaffccff61ffbd897eabac1f875c0..5a6dcc5fa36c2fb3336bacd1b556d57a40f15129 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 /* This file shoule be up to date with:
- *  - Revision B, 12/10/2007; ADSP-BF531/BF532/BF533 Blackfin Processor Anomaly List
+ *  - Revision C, 02/08/2008; ADSP-BF531/BF532/BF533 Blackfin Processor Anomaly List
  */
 
 #ifndef _MACH_ANOMALY_H_
 #define ANOMALY_05000206 (__SILICON_REVISION__ < 3)
 /* Serial Port (SPORT) Multichannel Transmit Failure when Channel 0 Is Disabled */
 #define ANOMALY_05000357 (1)
+/* UART Break Signal Issues */
+#define ANOMALY_05000363 (__SILICON_REVISION__ < 5)
 /* PPI Underflow Error Goes Undetected in ITU-R 656 Mode */
 #define ANOMALY_05000366 (1)
 /* Possible RETS Register Corruption when Subroutine Is under 5 Cycles in Duration */
 #define ANOMALY_05000371 (1)
+/* PPI Does Not Start Properly In Specific Mode */
+#define ANOMALY_05000400 (__SILICON_REVISION__ == 5)
+/* SSYNC Stalls Processor when Executed from Non-Cacheable Memory */
+#define ANOMALY_05000402 (__SILICON_REVISION__ == 5)
+/* Level-Sensitive External GPIO Wakeups May Cause Indefinite Stall */
+#define ANOMALY_05000403 (1)
 
 /* Anomalies that don't exist on this proc */
 #define ANOMALY_05000266 (0)
index b6f513bee56ece582d69bdba072e722b557099f0..fbe88dee3e2d8d379fbd713e4a405d7366ab7daa 100644 (file)
@@ -1,22 +1,38 @@
+/*
+ * file:        include/asm-blackfin/mach-bf533/bfin_serial_5xx.h
+ * based on:
+ * author:
+ *
+ * created:
+ * description:
+ *     blackfin serial driver head file
+ * rev:
+ *
+ * modified:
+ *
+ *
+ * bugs:         enter bugs at http://blackfin.uclinux.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, 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; see the file copying.
+ * if not, write to the free software foundation,
+ * 59 temple place - suite 330, boston, ma 02111-1307, usa.
+ */
+
 #include <linux/serial.h>
 #include <asm/dma.h>
 #include <asm/portmux.h>
 
-#define NR_PORTS                1
-
-#define OFFSET_THR              0x00   /* Transmit Holding register            */
-#define OFFSET_RBR              0x00   /* Receive Buffer register              */
-#define OFFSET_DLL              0x00   /* Divisor Latch (Low-Byte)             */
-#define OFFSET_IER              0x04   /* Interrupt Enable Register            */
-#define OFFSET_DLH              0x04   /* Divisor Latch (High-Byte)            */
-#define OFFSET_IIR              0x08   /* Interrupt Identification Register    */
-#define OFFSET_LCR              0x0C   /* Line Control Register                */
-#define OFFSET_MCR              0x10   /* Modem Control Register               */
-#define OFFSET_LSR              0x14   /* Line Status Register                 */
-#define OFFSET_MSR              0x18   /* Modem Status Register                */
-#define OFFSET_SCR              0x1C   /* SCR Scratch Register                 */
-#define OFFSET_GCTL             0x24   /* Global Control Register              */
-
 #define UART_GET_CHAR(uart)     bfin_read16(((uart)->port.membase + OFFSET_RBR))
 #define UART_GET_DLL(uart)     bfin_read16(((uart)->port.membase + OFFSET_DLL))
 #define UART_GET_IER(uart)      bfin_read16(((uart)->port.membase + OFFSET_IER))
@@ -84,7 +100,7 @@ static inline void UART_CLEAR_LSR(struct bfin_serial_port *uart)
        bfin_write16(uart->port.membase + OFFSET_LSR, -1);
 }
 
-struct bfin_serial_port bfin_serial_ports[NR_PORTS];
+struct bfin_serial_port bfin_serial_ports[BFIN_UART_NR_PORTS];
 struct bfin_serial_res {
        unsigned long   uart_base_addr;
        int             uart_irq;
@@ -115,7 +131,7 @@ struct bfin_serial_res bfin_serial_resource[] = {
 
 #define DRIVER_NAME "bfin-uart"
 
-int nr_ports = NR_PORTS;
+int nr_ports = BFIN_UART_NR_PORTS;
 static void bfin_serial_hw_init(struct bfin_serial_port *uart)
 {
 
diff --git a/include/asm-blackfin/mach-bf533/bfin_sir.h b/include/asm-blackfin/mach-bf533/bfin_sir.h
new file mode 100644 (file)
index 0000000..cefcf8b
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * Blackfin Infra-red Driver
+ *
+ * Copyright 2006-2008 Analog Devices Inc.
+ *
+ * Enter bugs at http://blackfin.uclinux.org/
+ *
+ * Licensed under the GPL-2 or later.
+ *
+ */
+
+#include <linux/serial.h>
+#include <asm/dma.h>
+#include <asm/portmux.h>
+
+#define SIR_UART_GET_CHAR(port)   bfin_read16((port)->membase + OFFSET_RBR)
+#define SIR_UART_GET_DLL(port)    bfin_read16((port)->membase + OFFSET_DLL)
+#define SIR_UART_GET_IER(port)    bfin_read16((port)->membase + OFFSET_IER)
+#define SIR_UART_GET_DLH(port)    bfin_read16((port)->membase + OFFSET_DLH)
+#define SIR_UART_GET_IIR(port)    bfin_read16((port)->membase + OFFSET_IIR)
+#define SIR_UART_GET_LCR(port)    bfin_read16((port)->membase + OFFSET_LCR)
+#define SIR_UART_GET_GCTL(port)   bfin_read16((port)->membase + OFFSET_GCTL)
+
+#define SIR_UART_PUT_CHAR(port, v) bfin_write16(((port)->membase + OFFSET_THR), v)
+#define SIR_UART_PUT_DLL(port, v)  bfin_write16(((port)->membase + OFFSET_DLL), v)
+#define SIR_UART_PUT_IER(port, v)  bfin_write16(((port)->membase + OFFSET_IER), v)
+#define SIR_UART_PUT_DLH(port, v)  bfin_write16(((port)->membase + OFFSET_DLH), v)
+#define SIR_UART_PUT_LCR(port, v)  bfin_write16(((port)->membase + OFFSET_LCR), v)
+#define SIR_UART_PUT_GCTL(port, v) bfin_write16(((port)->membase + OFFSET_GCTL), v)
+
+#ifdef CONFIG_SIR_BFIN_DMA
+struct dma_rx_buf {
+       char *buf;
+       int head;
+       int tail;
+       };
+#endif /* CONFIG_SIR_BFIN_DMA */
+
+struct bfin_sir_port {
+       unsigned char __iomem   *membase;
+       unsigned int            irq;
+       unsigned int            lsr;
+       unsigned long           clk;
+       struct net_device       *dev;
+#ifdef CONFIG_SIR_BFIN_DMA
+       int                     tx_done;
+       struct dma_rx_buf       rx_dma_buf;
+       struct timer_list       rx_dma_timer;
+       int                     rx_dma_nrows;
+#endif /* CONFIG_SIR_BFIN_DMA */
+       unsigned int            tx_dma_channel;
+       unsigned int            rx_dma_channel;
+};
+
+struct bfin_sir_port sir_ports[BFIN_UART_NR_PORTS];
+
+struct bfin_sir_port_res {
+       unsigned long   base_addr;
+       int             irq;
+       unsigned int    rx_dma_channel;
+       unsigned int    tx_dma_channel;
+};
+
+struct bfin_sir_port_res bfin_sir_port_resource[] = {
+#ifdef CONFIG_BFIN_SIR0
+       {
+       0xFFC00400,
+       IRQ_UART_RX,
+       CH_UART_RX,
+       CH_UART_TX,
+       },
+#endif
+};
+
+int nr_sirs = ARRAY_SIZE(bfin_sir_port_resource);
+
+struct bfin_sir_self {
+       struct bfin_sir_port    *sir_port;
+       spinlock_t              lock;
+       unsigned int            open;
+       int                     speed;
+       int                     newspeed;
+
+       struct sk_buff          *txskb;
+       struct sk_buff          *rxskb;
+       struct net_device_stats stats;
+       struct device           *dev;
+       struct irlap_cb         *irlap;
+       struct qos_info         qos;
+
+       iobuff_t                tx_buff;
+       iobuff_t                rx_buff;
+
+       struct work_struct      work;
+       int                     mtt;
+};
+
+static inline unsigned int SIR_UART_GET_LSR(struct bfin_sir_port *port)
+{
+       unsigned int lsr = bfin_read16(port->membase + OFFSET_LSR);
+       port->lsr |= (lsr & (BI|FE|PE|OE));
+       return lsr | port->lsr;
+}
+
+static inline void SIR_UART_CLEAR_LSR(struct bfin_sir_port *port)
+{
+       port->lsr = 0;
+       bfin_read16(port->membase + OFFSET_LSR);
+}
+
+#define DRIVER_NAME "bfin_sir"
+
+static void bfin_sir_hw_init(void)
+{
+#ifdef CONFIG_BFIN_SIR0
+       peripheral_request(P_UART0_TX, DRIVER_NAME);
+       peripheral_request(P_UART0_RX, DRIVER_NAME);
+#endif
+       SSYNC();
+}
index f3b240abf170b550d58496d1d8948e9ba3f9d96c..d80971b4e3aa79fe2fd492e2cde99b7cf4977c5a 100644 (file)
 #include "cdefBF532.h"
 #endif
 
+#define BFIN_UART_NR_PORTS      1
+
+#define OFFSET_THR              0x00   /* Transmit Holding register            */
+#define OFFSET_RBR              0x00   /* Receive Buffer register              */
+#define OFFSET_DLL              0x00   /* Divisor Latch (Low-Byte)             */
+#define OFFSET_IER              0x04   /* Interrupt Enable Register            */
+#define OFFSET_DLH              0x04   /* Divisor Latch (High-Byte)            */
+#define OFFSET_IIR              0x08   /* Interrupt Identification Register    */
+#define OFFSET_LCR              0x0C   /* Line Control Register                */
+#define OFFSET_MCR              0x10   /* Modem Control Register               */
+#define OFFSET_LSR              0x14   /* Line Status Register                 */
+#define OFFSET_MSR              0x18   /* Modem Status Register                */
+#define OFFSET_SCR              0x1C   /* SCR Scratch Register                 */
+#define OFFSET_GCTL             0x24   /* Global Control Register              */
+
 #endif                         /* _MACH_BLACKFIN_H_ */
index c803e14b529c4aef65cee494d54193e08ae152bb..154655452d4c97d93d1cbe6d6397e1b68c61012b 100644 (file)
 
 /* Clock and System Control (0xFFC0 0400-0xFFC0 07FF) */
 #define bfin_read_PLL_CTL()                  bfin_read16(PLL_CTL)
-#define bfin_write_PLL_CTL(val)              bfin_write16(PLL_CTL,val)
+/* Writing to PLL_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_PLL_CTL(unsigned int val)
+{
+       unsigned long flags, iwr;
+
+       if (val == bfin_read_PLL_CTL())
+               return;
+
+       local_irq_save(flags);
+       /* Enable the PLL Wakeup bit in SIC IWR */
+       iwr = bfin_read32(SIC_IWR);
+       /* Only allow PPL Wakeup) */
+       bfin_write32(SIC_IWR, IWR_ENABLE(0));
+
+       bfin_write16(PLL_CTL, val);
+       SSYNC();
+       asm("IDLE;");
+
+       bfin_write32(SIC_IWR, iwr);
+       local_irq_restore(flags);
+}
 #define bfin_read_PLL_STAT()                 bfin_read16(PLL_STAT)
 #define bfin_write_PLL_STAT(val)             bfin_write16(PLL_STAT,val)
 #define bfin_read_PLL_LOCKCNT()              bfin_read16(PLL_LOCKCNT)
@@ -57,6 +77,10 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 {
        unsigned long flags, iwr;
 
+       if (val == bfin_read_VR_CTL())
+               return;
+
+       local_irq_save(flags);
        /* Enable the PLL Wakeup bit in SIC IWR */
        iwr = bfin_read32(SIC_IWR);
        /* Only allow PPL Wakeup) */
@@ -64,11 +88,10 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 
        bfin_write16(VR_CTL, val);
        SSYNC();
-
-       local_irq_save(flags);
        asm("IDLE;");
-       local_irq_restore(flags);
+
        bfin_write32(SIC_IWR, iwr);
+       local_irq_restore(flags);
 }
 
 /* System Interrupt Controller (0xFFC0 0C00-0xFFC0 0FFF) */
index 37134aaf9954f8fcaa2343f45406e9e0f00ae667..17e1548cec0813cd1004e57e7c19cec638a7cba5 100644 (file)
 #define RTC_PREN                       0xFFC00314      /* RTC Prescaler Enable Register (alternate macro) */
 
 /* UART Controller (0xFFC00400 - 0xFFC004FF) */
-#define UART_THR                        0xFFC00400     /* Transmit Holding register */
-#define UART_RBR                        0xFFC00400     /* Receive Buffer register */
-#define UART_DLL                        0xFFC00400     /* Divisor Latch (Low-Byte) */
-#define UART_IER                        0xFFC00404     /* Interrupt Enable Register */
-#define UART_DLH                        0xFFC00404     /* Divisor Latch (High-Byte) */
-#define UART_IIR                        0xFFC00408     /* Interrupt Identification Register */
-#define UART_LCR                        0xFFC0040C     /* Line Control Register */
-#define UART_MCR                        0xFFC00410     /* Modem Control Register */
-#define UART_LSR                        0xFFC00414     /* Line Status Register */
+
+/*
+ * Because include/linux/serial_reg.h have defined UART_*,
+ * So we define blackfin uart regs to BFIN_UART_*.
+ */
+#define BFIN_UART_THR                  0xFFC00400      /* Transmit Holding register */
+#define BFIN_UART_RBR                  0xFFC00400      /* Receive Buffer register */
+#define BFIN_UART_DLL                  0xFFC00400      /* Divisor Latch (Low-Byte) */
+#define BFIN_UART_IER                  0xFFC00404      /* Interrupt Enable Register */
+#define BFIN_UART_DLH                  0xFFC00404      /* Divisor Latch (High-Byte) */
+#define BFIN_UART_IIR                  0xFFC00408      /* Interrupt Identification Register */
+#define BFIN_UART_LCR                  0xFFC0040C      /* Line Control Register */
+#define BFIN_UART_MCR                  0xFFC00410      /* Modem Control Register */
+#define BFIN_UART_LSR                  0xFFC00414      /* Line Status Register */
 #if 0
-#define UART_MSR                        0xFFC00418   /* Modem Status Register (UNUSED in ADSP-BF532) */
+#define BFIN_UART_MSR                  0xFFC00418      /* Modem Status Register (UNUSED in ADSP-BF532) */
 #endif
-#define UART_SCR                        0xFFC0041C     /* SCR Scratch Register */
-#define UART_GCTL                               0xFFC00424     /* Global Control Register */
+#define BFIN_UART_SCR                  0xFFC0041C      /* SCR Scratch Register */
+#define BFIN_UART_GCTL                 0xFFC00424      /* Global Control Register */
 
 /* SPI Controller (0xFFC00500 - 0xFFC005FF) */
 #define SPI0_REGBASE                   0xFFC00500
index 16c672c01d80cb490d2dc0fceff35ed6d67947f7..bd9d5e94307d0ca7823ff50c88bf19d0f74c94f0 100644 (file)
@@ -51,7 +51,4 @@
 #define CH_MEM_STREAM1_DEST     10      /* TX */
 #define CH_MEM_STREAM1_SRC      11      /* RX */
 
-extern int channel2irq(unsigned int channel);
-extern struct dma_register *base_addr[];
-
 #endif
index 1620dae5254d3bb11130f6ff3c882dc27b9f6196..f8f31901fca9984d854eb182840cd757ea2a001f 100644 (file)
@@ -29,7 +29,8 @@
  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
-#if (CONFIG_MEM_MT48LC16M16A2TG_75 || CONFIG_MEM_MT48LC64M4A2FB_7E || CONFIG_MEM_GENERIC_BOARD)
+#if (CONFIG_MEM_MT48LC16M16A2TG_75 || CONFIG_MEM_MT48LC64M4A2FB_7E || \
+     CONFIG_MEM_MT48LC32M16A2TG_75 || CONFIG_MEM_GENERIC_BOARD)
 #if (CONFIG_SCLK_HZ > 119402985)
 #define SDRAM_tRP       TRP_2
 #define SDRAM_tRP_num   2
 #define SDRAM_CL    CL_3
 #endif
 
+#if (CONFIG_MEM_MT48LC32M16A2TG_75)
+  /*SDRAM INFORMATION: */
+#define SDRAM_Tref  64         /* Refresh period in milliseconds   */
+#define SDRAM_NRA   8192       /* Number of row addresses in SDRAM */
+#define SDRAM_CL    CL_3
+#endif
+
 #if (CONFIG_MEM_GENERIC_BOARD)
   /*SDRAM INFORMATION: Modify this for your board */
 #define SDRAM_Tref  64         /* Refresh period in milliseconds   */
index 746a794b3119fd8b4302276db5ef445a8426e6dd..a6b08facb2422f968b3fd88bdbb9e0e12fba1f0e 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 /* This file shoule be up to date with:
- *  - Revision A, 09/04/2007; ADSP-BF534/ADSP-BF536/ADSP-BF537 Blackfin Processor Anomaly List
+ *  - Revision C, 02/08/2008; ADSP-BF534/ADSP-BF536/ADSP-BF537 Blackfin Processor Anomaly List
  */
 
 #ifndef _MACH_ANOMALY_H_
 #define ANOMALY_05000322 (1)
 /* Ethernet MAC MDIO Reads Do Not Meet IEEE Specification */
 #define ANOMALY_05000341 (__SILICON_REVISION__ >= 3)
+/* New Feature: UART Remains Enabled after UART Boot (Not Available on Older Silicon) */
+#define ANOMALY_05000350 (__SILICON_REVISION__ < 3)
+/* Regulator Programming Blocked when Hibernate Wakeup Source Remains Active */
+#define ANOMALY_05000355 (1)
 /* Serial Port (SPORT) Multichannel Transmit Failure when Channel 0 Is Disabled */
 #define ANOMALY_05000357 (1)
 /* DMAs that Go Urgent during Tight Core Writes to External Memory Are Blocked */
 #define ANOMALY_05000359 (1)
+/* PPI Underflow Error Goes Undetected in ITU-R 656 Mode */
+#define ANOMALY_05000366 (1)
+/* Possible RETS Register Corruption when Subroutine Is under 5 Cycles in Duration */
+#define ANOMALY_05000371 (1)
+/* SSYNC Stalls Processor when Executed from Non-Cacheable Memory */
+#define ANOMALY_05000402 (__SILICON_REVISION__ >= 3)
+/* Level-Sensitive External GPIO Wakeups May Cause Indefinite Stall */
+#define ANOMALY_05000403 (1)
+
+
 
 /* Anomalies that don't exist on this proc */
 #define ANOMALY_05000125 (0)
 #define ANOMALY_05000266 (0)
 #define ANOMALY_05000311 (0)
 #define ANOMALY_05000323 (0)
+#define ANOMALY_05000363 (0)
 
 #endif
index 8fc672d3105747a75efa3cb86676f6877c176a0c..fd100a415b98bb937efbc87b22ff326f997b0da5 100644 (file)
@@ -1,22 +1,38 @@
+/*
+ * file:         include/asm-blackfin/mach-bf537/bfin_serial_5xx.h
+ * based on:
+ * author:
+ *
+ * created:
+ * description:
+ *     blackfin serial driver header files
+ * rev:
+ *
+ * modified:
+ *
+ *
+ * bugs:         enter bugs at http://blackfin.uclinux.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, 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; see the file copying.
+ * if not, write to the free software foundation,
+ * 59 temple place - suite 330, boston, ma 02111-1307, usa.
+ */
+
 #include <linux/serial.h>
 #include <asm/dma.h>
 #include <asm/portmux.h>
 
-#define NR_PORTS               2
-
-#define OFFSET_THR              0x00   /* Transmit Holding register            */
-#define OFFSET_RBR              0x00   /* Receive Buffer register              */
-#define OFFSET_DLL              0x00   /* Divisor Latch (Low-Byte)             */
-#define OFFSET_IER              0x04   /* Interrupt Enable Register            */
-#define OFFSET_DLH              0x04   /* Divisor Latch (High-Byte)            */
-#define OFFSET_IIR              0x08   /* Interrupt Identification Register    */
-#define OFFSET_LCR              0x0C   /* Line Control Register                */
-#define OFFSET_MCR              0x10   /* Modem Control Register               */
-#define OFFSET_LSR              0x14   /* Line Status Register                 */
-#define OFFSET_MSR              0x18   /* Modem Status Register                */
-#define OFFSET_SCR              0x1C   /* SCR Scratch Register                 */
-#define OFFSET_GCTL             0x24   /* Global Control Register              */
-
 #define UART_GET_CHAR(uart)     bfin_read16(((uart)->port.membase + OFFSET_RBR))
 #define UART_GET_DLL(uart)     bfin_read16(((uart)->port.membase + OFFSET_DLL))
 #define UART_GET_IER(uart)      bfin_read16(((uart)->port.membase + OFFSET_IER))
@@ -92,7 +108,7 @@ static inline void UART_CLEAR_LSR(struct bfin_serial_port *uart)
        bfin_write16(uart->port.membase + OFFSET_LSR, -1);
 }
 
-struct bfin_serial_port bfin_serial_ports[NR_PORTS];
+struct bfin_serial_port bfin_serial_ports[BFIN_UART_NR_PORTS];
 struct bfin_serial_res {
        unsigned long   uart_base_addr;
        int             uart_irq;
diff --git a/include/asm-blackfin/mach-bf537/bfin_sir.h b/include/asm-blackfin/mach-bf537/bfin_sir.h
new file mode 100644 (file)
index 0000000..0612d0c
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * Blackfin Infra-red Driver
+ *
+ * Copyright 2006-2008 Analog Devices Inc.
+ *
+ * Enter bugs at http://blackfin.uclinux.org/
+ *
+ * Licensed under the GPL-2 or later.
+ *
+ */
+
+#include <linux/serial.h>
+#include <asm/dma.h>
+#include <asm/portmux.h>
+
+#define SIR_UART_GET_CHAR(port)   bfin_read16((port)->membase + OFFSET_RBR)
+#define SIR_UART_GET_DLL(port)    bfin_read16((port)->membase + OFFSET_DLL)
+#define SIR_UART_GET_IER(port)    bfin_read16((port)->membase + OFFSET_IER)
+#define SIR_UART_GET_DLH(port)    bfin_read16((port)->membase + OFFSET_DLH)
+#define SIR_UART_GET_IIR(port)    bfin_read16((port)->membase + OFFSET_IIR)
+#define SIR_UART_GET_LCR(port)    bfin_read16((port)->membase + OFFSET_LCR)
+#define SIR_UART_GET_GCTL(port)   bfin_read16((port)->membase + OFFSET_GCTL)
+
+#define SIR_UART_PUT_CHAR(port, v) bfin_write16(((port)->membase + OFFSET_THR), v)
+#define SIR_UART_PUT_DLL(port, v)  bfin_write16(((port)->membase + OFFSET_DLL), v)
+#define SIR_UART_PUT_IER(port, v)  bfin_write16(((port)->membase + OFFSET_IER), v)
+#define SIR_UART_PUT_DLH(port, v)  bfin_write16(((port)->membase + OFFSET_DLH), v)
+#define SIR_UART_PUT_LCR(port, v)  bfin_write16(((port)->membase + OFFSET_LCR), v)
+#define SIR_UART_PUT_GCTL(port, v) bfin_write16(((port)->membase + OFFSET_GCTL), v)
+
+#ifdef CONFIG_SIR_BFIN_DMA
+struct dma_rx_buf {
+       char *buf;
+       int head;
+       int tail;
+       };
+#endif /* CONFIG_SIR_BFIN_DMA */
+
+struct bfin_sir_port {
+       unsigned char __iomem   *membase;
+       unsigned int            irq;
+       unsigned int            lsr;
+       unsigned long           clk;
+       struct net_device       *dev;
+#ifdef CONFIG_SIR_BFIN_DMA
+       int                     tx_done;
+       struct dma_rx_buf       rx_dma_buf;
+       struct timer_list       rx_dma_timer;
+       int                     rx_dma_nrows;
+#endif /* CONFIG_SIR_BFIN_DMA */
+       unsigned int            tx_dma_channel;
+       unsigned int            rx_dma_channel;
+};
+
+struct bfin_sir_port sir_ports[BFIN_UART_NR_PORTS];
+
+struct bfin_sir_port_res {
+       unsigned long   base_addr;
+       int             irq;
+       unsigned int    rx_dma_channel;
+       unsigned int    tx_dma_channel;
+};
+
+struct bfin_sir_port_res bfin_sir_port_resource[] = {
+#ifdef CONFIG_BFIN_SIR0
+       {
+       0xFFC00400,
+       IRQ_UART0_RX,
+       CH_UART0_RX,
+       CH_UART0_TX,
+       },
+#endif
+#ifdef CONFIG_BFIN_SIR1
+       {
+       0xFFC02000,
+       IRQ_UART1_RX,
+       CH_UART1_RX,
+       CH_UART1_TX,
+       },
+#endif
+};
+
+int nr_sirs = ARRAY_SIZE(bfin_sir_port_resource);
+
+struct bfin_sir_self {
+       struct bfin_sir_port    *sir_port;
+       spinlock_t              lock;
+       unsigned int            open;
+       int                     speed;
+       int                     newspeed;
+
+       struct sk_buff          *txskb;
+       struct sk_buff          *rxskb;
+       struct net_device_stats stats;
+       struct device           *dev;
+       struct irlap_cb         *irlap;
+       struct qos_info         qos;
+
+       iobuff_t                tx_buff;
+       iobuff_t                rx_buff;
+
+       struct work_struct      work;
+       int                     mtt;
+};
+
+static inline unsigned int SIR_UART_GET_LSR(struct bfin_sir_port *port)
+{
+       unsigned int lsr = bfin_read16(port->membase + OFFSET_LSR);
+       port->lsr |= (lsr & (BI|FE|PE|OE));
+       return lsr | port->lsr;
+}
+
+static inline void SIR_UART_CLEAR_LSR(struct bfin_sir_port *port)
+{
+       port->lsr = 0;
+       bfin_read16(port->membase + OFFSET_LSR);
+}
+
+#define DRIVER_NAME "bfin_sir"
+
+static void bfin_sir_hw_init(void)
+{
+#ifdef CONFIG_BFIN_SIR0
+       peripheral_request(P_UART0_TX, DRIVER_NAME);
+       peripheral_request(P_UART0_RX, DRIVER_NAME);
+#endif
+
+#ifdef CONFIG_BFIN_SIR1
+       peripheral_request(P_UART1_TX, DRIVER_NAME);
+       peripheral_request(P_UART1_RX, DRIVER_NAME);
+#endif
+       SSYNC();
+}
index 53fcfa3408d0eb019157b5c5928226e75abd0dc5..cffc786b2a2b1ea731463f0fe2aa24e2e472de52 100644 (file)
@@ -82,8 +82,6 @@
 #define STATUS_P1      0x02
 #define STATUS_P0      0x01
 
-/* UART 0*/
-
 /* DMA Channnel */
 #define bfin_read_CH_UART_RX() bfin_read_CH_UART0_RX()
 #define bfin_write_CH_UART_RX(val) bfin_write_CH_UART0_RX(val)
 /* MMR Registers*/
 #define bfin_read_UART_THR() bfin_read_UART0_THR()
 #define bfin_write_UART_THR(val) bfin_write_UART0_THR(val)
-#define UART_THR UART0_THR
+#define BFIN_UART_THR UART0_THR
 #define bfin_read_UART_RBR() bfin_read_UART0_RBR()
 #define bfin_write_UART_RBR(val) bfin_write_UART0_RBR(val)
-#define UART_RBR UART0_RBR
+#define BFIN_UART_RBR UART0_RBR
 #define bfin_read_UART_DLL() bfin_read_UART0_DLL()
 #define bfin_write_UART_DLL(val) bfin_write_UART0_DLL(val)
-#define UART_DLL UART0_DLL
+#define BFIN_UART_DLL UART0_DLL
 #define bfin_read_UART_IER() bfin_read_UART0_IER()
 #define bfin_write_UART_IER(val) bfin_write_UART0_IER(val)
-#define UART_IER UART0_IER
+#define BFIN_UART_IER UART0_IER
 #define bfin_read_UART_DLH() bfin_read_UART0_DLH()
 #define bfin_write_UART_DLH(val) bfin_write_UART0_DLH(val)
-#define UART_DLH UART0_DLH
+#define BFIN_UART_DLH UART0_DLH
 #define bfin_read_UART_IIR() bfin_read_UART0_IIR()
 #define bfin_write_UART_IIR(val) bfin_write_UART0_IIR(val)
-#define UART_IIR UART0_IIR
+#define BFIN_UART_IIR UART0_IIR
 #define bfin_read_UART_LCR() bfin_read_UART0_LCR()
 #define bfin_write_UART_LCR(val) bfin_write_UART0_LCR(val)
-#define UART_LCR UART0_LCR
+#define BFIN_UART_LCR UART0_LCR
 #define bfin_read_UART_MCR() bfin_read_UART0_MCR()
 #define bfin_write_UART_MCR(val) bfin_write_UART0_MCR(val)
-#define UART_MCR UART0_MCR
+#define BFIN_UART_MCR UART0_MCR
 #define bfin_read_UART_LSR() bfin_read_UART0_LSR()
 #define bfin_write_UART_LSR(val) bfin_write_UART0_LSR(val)
-#define UART_LSR UART0_LSR
+#define BFIN_UART_LSR UART0_LSR
 #define bfin_read_UART_SCR() bfin_read_UART0_SCR()
 #define bfin_write_UART_SCR(val) bfin_write_UART0_SCR(val)
-#define UART_SCR  UART0_SCR
+#define BFIN_UART_SCR  UART0_SCR
 #define bfin_read_UART_GCTL() bfin_read_UART0_GCTL()
 #define bfin_write_UART_GCTL(val) bfin_write_UART0_GCTL(val)
-#define UART_GCTL UART0_GCTL
+#define BFIN_UART_GCTL UART0_GCTL
+
+#define BFIN_UART_NR_PORTS     2
+
+#define OFFSET_THR              0x00   /* Transmit Holding register            */
+#define OFFSET_RBR              0x00   /* Receive Buffer register              */
+#define OFFSET_DLL              0x00   /* Divisor Latch (Low-Byte)             */
+#define OFFSET_IER              0x04   /* Interrupt Enable Register            */
+#define OFFSET_DLH              0x04   /* Divisor Latch (High-Byte)            */
+#define OFFSET_IIR              0x08   /* Interrupt Identification Register    */
+#define OFFSET_LCR              0x0C   /* Line Control Register                */
+#define OFFSET_MCR              0x10   /* Modem Control Register               */
+#define OFFSET_LSR              0x14   /* Line Status Register                 */
+#define OFFSET_MSR              0x18   /* Modem Status Register                */
+#define OFFSET_SCR              0x1C   /* SCR Scratch Register                 */
+#define OFFSET_GCTL             0x24   /* Global Control Register              */
 
 /* DPMC*/
 #define bfin_read_STOPCK_OFF() bfin_read_STOPCK()
index 78227bc855df54bca56220dc55d777fec0e6a04a..82de526f8097532ecf05ecff23aa0db277316a11 100644 (file)
 
 /* Clock and System Control    (0xFFC00000 - 0xFFC000FF)                                                               */
 #define bfin_read_PLL_CTL()                  bfin_read16(PLL_CTL)
-#define bfin_write_PLL_CTL(val)              bfin_write16(PLL_CTL,val)
+/* Writing to PLL_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_PLL_CTL(unsigned int val)
+{
+       unsigned long flags, iwr;
+
+       if (val == bfin_read_PLL_CTL())
+               return;
+
+       local_irq_save(flags);
+       /* Enable the PLL Wakeup bit in SIC IWR */
+       iwr = bfin_read32(SIC_IWR);
+       /* Only allow PPL Wakeup) */
+       bfin_write32(SIC_IWR, IWR_ENABLE(0));
+
+       bfin_write16(PLL_CTL, val);
+       SSYNC();
+       asm("IDLE;");
+
+       bfin_write32(SIC_IWR, iwr);
+       local_irq_restore(flags);
+}
 #define bfin_read_PLL_DIV()                  bfin_read16(PLL_DIV)
 #define bfin_write_PLL_DIV(val)              bfin_write16(PLL_DIV,val)
 #define bfin_read_VR_CTL()                   bfin_read16(VR_CTL)
@@ -53,6 +73,10 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 {
        unsigned long flags, iwr;
 
+       if (val == bfin_read_VR_CTL())
+               return;
+
+       local_irq_save(flags);
        /* Enable the PLL Wakeup bit in SIC IWR */
        iwr = bfin_read32(SIC_IWR);
        /* Only allow PPL Wakeup) */
@@ -60,11 +84,10 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 
        bfin_write16(VR_CTL, val);
        SSYNC();
-
-       local_irq_save(flags);
        asm("IDLE;");
-       local_irq_restore(flags);
+
        bfin_write32(SIC_IWR, iwr);
+       local_irq_restore(flags);
 }
 #define bfin_read_PLL_STAT()                 bfin_read16(PLL_STAT)
 #define bfin_write_PLL_STAT(val)             bfin_write16(PLL_STAT,val)
@@ -858,39 +881,7 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 #define bfin_read_PPI_FRAME()                bfin_read16(PPI_FRAME)
 #define bfin_write_PPI_FRAME(val)            bfin_write16(PPI_FRAME,val)
 
-/* Two-Wire Interface          (0xFFC01400 - 0xFFC014FF)                                                               */
-#define bfin_read_TWI_CLKDIV()               bfin_read16(TWI_CLKDIV)
-#define bfin_write_TWI_CLKDIV(val)           bfin_write16(TWI_CLKDIV,val)
-#define bfin_read_TWI_CONTROL()              bfin_read16(TWI_CONTROL)
-#define bfin_write_TWI_CONTROL(val)          bfin_write16(TWI_CONTROL,val)
-#define bfin_read_TWI_SLAVE_CTL()            bfin_read16(TWI_SLAVE_CTL)
-#define bfin_write_TWI_SLAVE_CTL(val)        bfin_write16(TWI_SLAVE_CTL,val)
-#define bfin_read_TWI_SLAVE_STAT()           bfin_read16(TWI_SLAVE_STAT)
-#define bfin_write_TWI_SLAVE_STAT(val)       bfin_write16(TWI_SLAVE_STAT,val)
-#define bfin_read_TWI_SLAVE_ADDR()           bfin_read16(TWI_SLAVE_ADDR)
-#define bfin_write_TWI_SLAVE_ADDR(val)       bfin_write16(TWI_SLAVE_ADDR,val)
-#define bfin_read_TWI_MASTER_CTL()           bfin_read16(TWI_MASTER_CTL)
-#define bfin_write_TWI_MASTER_CTL(val)       bfin_write16(TWI_MASTER_CTL,val)
-#define bfin_read_TWI_MASTER_STAT()          bfin_read16(TWI_MASTER_STAT)
-#define bfin_write_TWI_MASTER_STAT(val)      bfin_write16(TWI_MASTER_STAT,val)
-#define bfin_read_TWI_MASTER_ADDR()          bfin_read16(TWI_MASTER_ADDR)
-#define bfin_write_TWI_MASTER_ADDR(val)      bfin_write16(TWI_MASTER_ADDR,val)
-#define bfin_read_TWI_INT_STAT()             bfin_read16(TWI_INT_STAT)
-#define bfin_write_TWI_INT_STAT(val)         bfin_write16(TWI_INT_STAT,val)
-#define bfin_read_TWI_INT_MASK()             bfin_read16(TWI_INT_MASK)
-#define bfin_write_TWI_INT_MASK(val)         bfin_write16(TWI_INT_MASK,val)
-#define bfin_read_TWI_FIFO_CTL()             bfin_read16(TWI_FIFO_CTL)
-#define bfin_write_TWI_FIFO_CTL(val)         bfin_write16(TWI_FIFO_CTL,val)
-#define bfin_read_TWI_FIFO_STAT()            bfin_read16(TWI_FIFO_STAT)
-#define bfin_write_TWI_FIFO_STAT(val)        bfin_write16(TWI_FIFO_STAT,val)
-#define bfin_read_TWI_XMT_DATA8()            bfin_read16(TWI_XMT_DATA8)
-#define bfin_write_TWI_XMT_DATA8(val)        bfin_write16(TWI_XMT_DATA8,val)
-#define bfin_read_TWI_XMT_DATA16()           bfin_read16(TWI_XMT_DATA16)
-#define bfin_write_TWI_XMT_DATA16(val)       bfin_write16(TWI_XMT_DATA16,val)
-#define bfin_read_TWI_RCV_DATA8()            bfin_read16(TWI_RCV_DATA8)
-#define bfin_write_TWI_RCV_DATA8(val)        bfin_write16(TWI_RCV_DATA8,val)
-#define bfin_read_TWI_RCV_DATA16()           bfin_read16(TWI_RCV_DATA16)
-#define bfin_write_TWI_RCV_DATA16(val)       bfin_write16(TWI_RCV_DATA16,val)
+/* Two-Wire Interface (0xFFC01400 - 0xFFC014FF) */
 
 /* General Purpose I/O Port G (0xFFC01500 - 0xFFC015FF)                                                                */
 #define bfin_read_PORTGIO()                  bfin_read16(PORTGIO)
index 021991984e6e7ce4f5ae7adc197396d954bf83ca..7a964040870a047292f84678c3788dc2c2bff07f 100644 (file)
@@ -52,7 +52,4 @@
 #define CH_MEM_STREAM1_DEST    14       /* TX */
 #define CH_MEM_STREAM1_SRC     15       /* RX */
 
-extern int channel2irq(unsigned int channel);
-extern struct dma_register *base_addr[];
-
 #endif
index 850dc12eb7f2ae95f21fd226569cf6caafe58a9f..49d3cebc529389fc0d4a63d805b31c9b3a5d6fb2 100644 (file)
@@ -93,5 +93,6 @@
 #define ANOMALY_05000273 (0)
 #define ANOMALY_05000311 (0)
 #define ANOMALY_05000323 (0)
+#define ANOMALY_05000363 (0)
 
 #endif
index 7e6339f62a5058ae5e4226fef033c9985968f96e..6547027cd3e62174a0bd5a0f9ee2aa0a6429fe5d 100644 (file)
@@ -1,22 +1,38 @@
+/*
+ * file:        include/asm-blackfin/mach-bf548/bfin_serial_5xx.h
+ * based on:
+ * author:
+ *
+ * created:
+ * description:
+ *     blackfin serial driver head file
+ * rev:
+ *
+ * modified:
+ *
+ *
+ * bugs:         enter bugs at http://blackfin.uclinux.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, 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; see the file copying.
+ * if not, write to the free software foundation,
+ * 59 temple place - suite 330, boston, ma 02111-1307, usa.
+ */
+
 #include <linux/serial.h>
 #include <asm/dma.h>
 #include <asm/portmux.h>
 
-#define NR_PORTS               4
-
-#define OFFSET_DLL              0x00   /* Divisor Latch (Low-Byte)             */
-#define OFFSET_DLH              0x04   /* Divisor Latch (High-Byte)            */
-#define OFFSET_GCTL             0x08   /* Global Control Register              */
-#define OFFSET_LCR              0x0C   /* Line Control Register                */
-#define OFFSET_MCR              0x10   /* Modem Control Register               */
-#define OFFSET_LSR              0x14   /* Line Status Register                 */
-#define OFFSET_MSR              0x18   /* Modem Status Register                */
-#define OFFSET_SCR              0x1C   /* SCR Scratch Register                 */
-#define OFFSET_IER_SET          0x20   /* Set Interrupt Enable Register        */
-#define OFFSET_IER_CLEAR        0x24   /* Clear Interrupt Enable Register      */
-#define OFFSET_THR              0x28   /* Transmit Holding register            */
-#define OFFSET_RBR              0x2C   /* Receive Buffer register              */
-
 #define UART_GET_CHAR(uart)     bfin_read16(((uart)->port.membase + OFFSET_RBR))
 #define UART_GET_DLL(uart)     bfin_read16(((uart)->port.membase + OFFSET_DLL))
 #define UART_GET_DLH(uart)     bfin_read16(((uart)->port.membase + OFFSET_DLH))
@@ -80,7 +96,7 @@ struct bfin_serial_port {
 #endif
 };
 
-struct bfin_serial_port bfin_serial_ports[NR_PORTS];
+struct bfin_serial_port bfin_serial_ports[BFIN_UART_NR_PORTS];
 struct bfin_serial_res {
        unsigned long   uart_base_addr;
        int             uart_irq;
diff --git a/include/asm-blackfin/mach-bf548/bfin_sir.h b/include/asm-blackfin/mach-bf548/bfin_sir.h
new file mode 100644 (file)
index 0000000..5e94271
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * Blackfin Infra-red Driver
+ *
+ * Copyright 2006-2008 Analog Devices Inc.
+ *
+ * Enter bugs at http://blackfin.uclinux.org/
+ *
+ * Licensed under the GPL-2 or later.
+ *
+ */
+
+#include <linux/serial.h>
+#include <asm/dma.h>
+#include <asm/portmux.h>
+
+#define SIR_UART_GET_CHAR(port)   bfin_read16((port)->membase + OFFSET_RBR)
+#define SIR_UART_GET_DLL(port)    bfin_read16((port)->membase + OFFSET_DLL)
+#define SIR_UART_GET_IER(port)    bfin_read16((port)->membase + OFFSET_IER_SET)
+#define SIR_UART_GET_DLH(port)    bfin_read16((port)->membase + OFFSET_DLH)
+#define SIR_UART_GET_LCR(port)    bfin_read16((port)->membase + OFFSET_LCR)
+#define SIR_UART_GET_LSR(port)    bfin_read16((port)->membase + OFFSET_LSR)
+#define SIR_UART_GET_GCTL(port)   bfin_read16((port)->membase + OFFSET_GCTL)
+
+#define SIR_UART_PUT_CHAR(port, v) bfin_write16(((port)->membase + OFFSET_THR), v)
+#define SIR_UART_PUT_DLL(port, v)  bfin_write16(((port)->membase + OFFSET_DLL), v)
+#define SIR_UART_SET_IER(port, v)  bfin_write16(((port)->membase + OFFSET_IER_SET), v)
+#define SIR_UART_CLEAR_IER(port, v)  bfin_write16(((port)->membase + OFFSET_IER_CLEAR), v)
+#define SIR_UART_PUT_DLH(port, v)  bfin_write16(((port)->membase + OFFSET_DLH), v)
+#define SIR_UART_PUT_LSR(port, v)  bfin_write16(((port)->membase + OFFSET_LSR), v)
+#define SIR_UART_PUT_LCR(port, v)  bfin_write16(((port)->membase + OFFSET_LCR), v)
+#define SIR_UART_CLEAR_LSR(port)  bfin_write16(((port)->membase + OFFSET_LSR), -1)
+#define SIR_UART_PUT_GCTL(port, v) bfin_write16(((port)->membase + OFFSET_GCTL), v)
+
+#ifdef CONFIG_SIR_BFIN_DMA
+struct dma_rx_buf {
+       char *buf;
+       int head;
+       int tail;
+       };
+#endif /* CONFIG_SIR_BFIN_DMA */
+
+struct bfin_sir_port {
+       unsigned char __iomem   *membase;
+       unsigned int            irq;
+       unsigned int            lsr;
+       unsigned long           clk;
+       struct net_device       *dev;
+#ifdef CONFIG_SIR_BFIN_DMA
+       int                     tx_done;
+       struct dma_rx_buf       rx_dma_buf;
+       struct timer_list       rx_dma_timer;
+       int                     rx_dma_nrows;
+#endif /* CONFIG_SIR_BFIN_DMA */
+       unsigned int            tx_dma_channel;
+       unsigned int            rx_dma_channel;
+};
+
+struct bfin_sir_port sir_ports[BFIN_UART_NR_PORTS];
+
+struct bfin_sir_port_res {
+       unsigned long   base_addr;
+       int             irq;
+       unsigned int    rx_dma_channel;
+       unsigned int    tx_dma_channel;
+};
+
+struct bfin_sir_port_res bfin_sir_port_resource[] = {
+#ifdef CONFIG_BFIN_SIR0
+       {
+       0xFFC00400,
+       IRQ_UART0_RX,
+       CH_UART0_RX,
+       CH_UART0_TX,
+       },
+#endif
+#ifdef CONFIG_BFIN_SIR1
+       {
+       0xFFC02000,
+       IRQ_UART1_RX,
+       CH_UART1_RX,
+       CH_UART1_TX,
+       },
+#endif
+#ifdef CONFIG_BFIN_SIR2
+       {
+       0xFFC02100,
+       IRQ_UART2_RX,
+       CH_UART2_RX,
+       CH_UART2_TX,
+       },
+#endif
+#ifdef CONFIG_BFIN_SIR3
+       {
+       0xFFC03100,
+       IRQ_UART3_RX,
+       CH_UART3_RX,
+       CH_UART3_TX,
+       },
+#endif
+};
+
+int nr_sirs = ARRAY_SIZE(bfin_sir_port_resource);
+
+struct bfin_sir_self {
+       struct bfin_sir_port    *sir_port;
+       spinlock_t              lock;
+       unsigned int            open;
+       int                     speed;
+       int                     newspeed;
+
+       struct sk_buff          *txskb;
+       struct sk_buff          *rxskb;
+       struct net_device_stats stats;
+       struct device           *dev;
+       struct irlap_cb         *irlap;
+       struct qos_info         qos;
+
+       iobuff_t                tx_buff;
+       iobuff_t                rx_buff;
+
+       struct work_struct      work;
+       int                     mtt;
+};
+
+#define DRIVER_NAME "bfin_sir"
+
+static void bfin_sir_hw_init(void)
+{
+#ifdef CONFIG_BFIN_SIR0
+       peripheral_request(P_UART0_TX, DRIVER_NAME);
+       peripheral_request(P_UART0_RX, DRIVER_NAME);
+#endif
+
+#ifdef CONFIG_BFIN_SIR1
+       peripheral_request(P_UART1_TX, DRIVER_NAME);
+       peripheral_request(P_UART1_RX, DRIVER_NAME);
+#endif
+
+#ifdef CONFIG_BFIN_SIR2
+       peripheral_request(P_UART2_TX, DRIVER_NAME);
+       peripheral_request(P_UART2_RX, DRIVER_NAME);
+#endif
+
+#ifdef CONFIG_BFIN_SIR3
+       peripheral_request(P_UART3_TX, DRIVER_NAME);
+       peripheral_request(P_UART3_RX, DRIVER_NAME);
+#endif
+       SSYNC();
+}
index 3bd67da860532d556e4e8157e668c76e61d81a15..d6ee74ac04605227e9b917bb4dc5e6579573e833 100644 (file)
 #define bfin_write_UART_SCR(val)       bfin_write_UART1_SCR(val)
 #define bfin_read_UART_GCTL()          bfin_read_UART1_GCTL()
 #define bfin_write_UART_GCTL(val)      bfin_write_UART1_GCTL(val)
-#define UART_THR                       UART1_THR
-#define UART_RBR                       UART1_RBR
-#define UART_DLL                       UART1_DLL
-#define UART_IER                       UART1_IER
-#define UART_DLH                       UART1_DLH
-#define UART_IIR                       UART1_IIR
-#define UART_LCR                       UART1_LCR
-#define UART_MCR                       UART1_MCR
-#define UART_LSR                       UART1_LSR
-#define UART_SCR                       UART1_SCR
-#define UART_GCTL                      UART1_GCTL
+
+#define BFIN_UART_THR                  UART1_THR
+#define BFIN_UART_RBR                  UART1_RBR
+#define BFIN_UART_DLL                  UART1_DLL
+#define BFIN_UART_IER                  UART1_IER
+#define BFIN_UART_DLH                  UART1_DLH
+#define BFIN_UART_IIR                  UART1_IIR
+#define BFIN_UART_LCR                  UART1_LCR
+#define BFIN_UART_MCR                  UART1_MCR
+#define BFIN_UART_LSR                  UART1_LSR
+#define BFIN_UART_SCR                  UART1_SCR
+#define BFIN_UART_GCTL                 UART1_GCTL
+
+#define BFIN_UART_NR_PORTS     4
+
+#define OFFSET_DLL              0x00   /* Divisor Latch (Low-Byte)             */
+#define OFFSET_DLH              0x04   /* Divisor Latch (High-Byte)            */
+#define OFFSET_GCTL             0x08   /* Global Control Register              */
+#define OFFSET_LCR              0x0C   /* Line Control Register                */
+#define OFFSET_MCR              0x10   /* Modem Control Register               */
+#define OFFSET_LSR              0x14   /* Line Status Register                 */
+#define OFFSET_MSR              0x18   /* Modem Status Register                */
+#define OFFSET_SCR              0x1C   /* SCR Scratch Register                 */
+#define OFFSET_IER_SET          0x20   /* Set Interrupt Enable Register        */
+#define OFFSET_IER_CLEAR        0x24   /* Clear Interrupt Enable Register      */
+#define OFFSET_THR              0x28   /* Transmit Holding register            */
+#define OFFSET_RBR              0x2C   /* Receive Buffer register              */
 
 /* PLL_DIV Masks */
 #define CCLK_DIV1 CSEL_DIV1    /* CCLK = VCO / 1 */
index 308b33ab5311988c6df3e02b881350505d1ee0e3..60b9f77576f155fe4eeba9a5c4559cab81dad16a 100644 (file)
 #define bfin_write_SDH_DATA_LGTH(val)  bfin_write16(SDH_DATA_LGTH, val)
 #define bfin_read_SDH_DATA_CTL()       bfin_read16(SDH_DATA_CTL)
 #define bfin_write_SDH_DATA_CTL(val)   bfin_write16(SDH_DATA_CTL, val)
-#define bfin_read_SDH_DATA_CNT()       fin_read16(SDH_DATA_CNT)
+#define bfin_read_SDH_DATA_CNT()       bfin_read16(SDH_DATA_CNT)
 #define bfin_write_SDH_DATA_CNT(val)   bfin_write16(SDH_DATA_CNT, val)
 #define bfin_read_SDH_STATUS()         bfin_read32(SDH_STATUS)
 #define bfin_write_SDH_STATUS(val)     bfin_write32(SDH_STATUS, val)
-#define bfin_read_SDH_STATUS_CLR()     fin_read16(SDH_STATUS_CLR)
-#define bfin_write_SDH_STATUS_CLR(val) fin_write16(SDH_STATUS_CLR, val)
+#define bfin_read_SDH_STATUS_CLR()     bfin_read16(SDH_STATUS_CLR)
+#define bfin_write_SDH_STATUS_CLR(val) bfin_write16(SDH_STATUS_CLR, val)
 #define bfin_read_SDH_MASK0()          bfin_read32(SDH_MASK0)
 #define bfin_write_SDH_MASK0(val)      bfin_write32(SDH_MASK0, val)
 #define bfin_read_SDH_MASK1()          bfin_read32(SDH_MASK1)
 #define bfin_write_USB_FRAME(val)      bfin_write16(USB_FRAME, val)
 #define bfin_read_USB_INDEX()          bfin_read16(USB_INDEX)
 #define bfin_write_USB_INDEX(val)      bfin_write16(USB_INDEX, val)
-#define bfin_read_USB_TESTMODE()       fin_read16(USB_TESTMODE)
-#define bfin_write_USB_TESTMODE(val)   fin_write16(USB_TESTMODE, val)
+#define bfin_read_USB_TESTMODE()       bfin_read16(USB_TESTMODE)
+#define bfin_write_USB_TESTMODE(val)   bfin_write16(USB_TESTMODE, val)
 #define bfin_read_USB_GLOBINTR()       bfin_read16(USB_GLOBINTR)
 #define bfin_write_USB_GLOBINTR(val)   bfin_write16(USB_GLOBINTR, val)
 #define bfin_read_USB_GLOBAL_CTL()     bfin_read16(USB_GLOBAL_CTL)
 #define bfin_read_USB_OTG_DEV_CTL()            bfin_read16(USB_OTG_DEV_CTL)
 #define bfin_write_USB_OTG_DEV_CTL(val)                bfin_write16(USB_OTG_DEV_CTL, val)
 #define bfin_read_USB_OTG_VBUS_IRQ()           bfin_read16(USB_OTG_VBUS_IRQ)
-#define bfin_write_USB_OTG_VBUS_IRQ(val)       fin_write16(USB_OTG_VBUS_IRQ, val)
+#define bfin_write_USB_OTG_VBUS_IRQ(val)       bfin_write16(USB_OTG_VBUS_IRQ, val)
 #define bfin_read_USB_OTG_VBUS_MASK()          bfin_read16(USB_OTG_VBUS_MASK)
 #define bfin_write_USB_OTG_VBUS_MASK(val)      bfin_write16(USB_OTG_VBUS_MASK, val)
 
index 7a2d177c8dc219f9456d02d93d817b846c91bbbc..ea9b4ab496f3da78e152ae6b3bdf4586d7da991b 100644 (file)
 
 /* Two Wire Interface Registers (TWI1) */
 
-#define bfin_read_TWI1_CLKDIV()                        bfin_read16(TWI1_CLKDIV)
-#define bfin_write_TWI1_CLKDIV(val)            bfin_write16(TWI1_CLKDIV, val)
-#define bfin_read_TWI1_CONTROL()               bfin_read16(TWI1_CONTROL)
-#define bfin_write_TWI1_CONTROL(val)           bfin_write16(TWI1_CONTROL, val)
-#define bfin_read_TWI1_SLAVE_CTRL()            bfin_read16(TWI1_SLAVE_CTRL)
-#define bfin_write_TWI1_SLAVE_CTRL(val)                bfin_write16(TWI1_SLAVE_CTRL, val)
-#define bfin_read_TWI1_SLAVE_STAT()            bfin_read16(TWI1_SLAVE_STAT)
-#define bfin_write_TWI1_SLAVE_STAT(val)                bfin_write16(TWI1_SLAVE_STAT, val)
-#define bfin_read_TWI1_SLAVE_ADDR()            bfin_read16(TWI1_SLAVE_ADDR)
-#define bfin_write_TWI1_SLAVE_ADDR(val)                bfin_write16(TWI1_SLAVE_ADDR, val)
-#define bfin_read_TWI1_MASTER_CTRL()           bfin_read16(TWI1_MASTER_CTRL)
-#define bfin_write_TWI1_MASTER_CTRL(val)       bfin_write16(TWI1_MASTER_CTRL, val)
-#define bfin_read_TWI1_MASTER_STAT()           bfin_read16(TWI1_MASTER_STAT)
-#define bfin_write_TWI1_MASTER_STAT(val)       bfin_write16(TWI1_MASTER_STAT, val)
-#define bfin_read_TWI1_MASTER_ADDR()           bfin_read16(TWI1_MASTER_ADDR)
-#define bfin_write_TWI1_MASTER_ADDR(val)       bfin_write16(TWI1_MASTER_ADDR, val)
-#define bfin_read_TWI1_INT_STAT()              bfin_read16(TWI1_INT_STAT)
-#define bfin_write_TWI1_INT_STAT(val)          bfin_write16(TWI1_INT_STAT, val)
-#define bfin_read_TWI1_INT_MASK()              bfin_read16(TWI1_INT_MASK)
-#define bfin_write_TWI1_INT_MASK(val)          bfin_write16(TWI1_INT_MASK, val)
-#define bfin_read_TWI1_FIFO_CTRL()             bfin_read16(TWI1_FIFO_CTRL)
-#define bfin_write_TWI1_FIFO_CTRL(val)         bfin_write16(TWI1_FIFO_CTRL, val)
-#define bfin_read_TWI1_FIFO_STAT()             bfin_read16(TWI1_FIFO_STAT)
-#define bfin_write_TWI1_FIFO_STAT(val)         bfin_write16(TWI1_FIFO_STAT, val)
-#define bfin_read_TWI1_XMT_DATA8()             bfin_read16(TWI1_XMT_DATA8)
-#define bfin_write_TWI1_XMT_DATA8(val)         bfin_write16(TWI1_XMT_DATA8, val)
-#define bfin_read_TWI1_XMT_DATA16()            bfin_read16(TWI1_XMT_DATA16)
-#define bfin_write_TWI1_XMT_DATA16(val)                bfin_write16(TWI1_XMT_DATA16, val)
-#define bfin_read_TWI1_RCV_DATA8()             bfin_read16(TWI1_RCV_DATA8)
-#define bfin_write_TWI1_RCV_DATA8(val)         bfin_write16(TWI1_RCV_DATA8, val)
-#define bfin_read_TWI1_RCV_DATA16()            bfin_read16(TWI1_RCV_DATA16)
-#define bfin_write_TWI1_RCV_DATA16(val)                bfin_write16(TWI1_RCV_DATA16, val)
-
 /* CAN Controller 1 Config 1 Registers */
 
 #define bfin_read_CAN1_MC1()           bfin_read16(CAN1_MC1)
index d0a200b08abd53985767cad382b072daebf199aa..ba716277c00d53b2d8aefef2bc2402fc8648652d 100644 (file)
 
 /* Two Wire Interface Registers (TWI1) */
 
-#define bfin_read_TWI1_CLKDIV()                        bfin_read16(TWI1_CLKDIV)
-#define bfin_write_TWI1_CLKDIV(val)            bfin_write16(TWI1_CLKDIV, val)
-#define bfin_read_TWI1_CONTROL()               bfin_read16(TWI1_CONTROL)
-#define bfin_write_TWI1_CONTROL(val)           bfin_write16(TWI1_CONTROL, val)
-#define bfin_read_TWI1_SLAVE_CTRL()            bfin_read16(TWI1_SLAVE_CTRL)
-#define bfin_write_TWI1_SLAVE_CTRL(val)                bfin_write16(TWI1_SLAVE_CTRL, val)
-#define bfin_read_TWI1_SLAVE_STAT()            bfin_read16(TWI1_SLAVE_STAT)
-#define bfin_write_TWI1_SLAVE_STAT(val)                bfin_write16(TWI1_SLAVE_STAT, val)
-#define bfin_read_TWI1_SLAVE_ADDR()            bfin_read16(TWI1_SLAVE_ADDR)
-#define bfin_write_TWI1_SLAVE_ADDR(val)                bfin_write16(TWI1_SLAVE_ADDR, val)
-#define bfin_read_TWI1_MASTER_CTRL()           bfin_read16(TWI1_MASTER_CTRL)
-#define bfin_write_TWI1_MASTER_CTRL(val)       bfin_write16(TWI1_MASTER_CTRL, val)
-#define bfin_read_TWI1_MASTER_STAT()           bfin_read16(TWI1_MASTER_STAT)
-#define bfin_write_TWI1_MASTER_STAT(val)       bfin_write16(TWI1_MASTER_STAT, val)
-#define bfin_read_TWI1_MASTER_ADDR()           bfin_read16(TWI1_MASTER_ADDR)
-#define bfin_write_TWI1_MASTER_ADDR(val)       bfin_write16(TWI1_MASTER_ADDR, val)
-#define bfin_read_TWI1_INT_STAT()              bfin_read16(TWI1_INT_STAT)
-#define bfin_write_TWI1_INT_STAT(val)          bfin_write16(TWI1_INT_STAT, val)
-#define bfin_read_TWI1_INT_MASK()              bfin_read16(TWI1_INT_MASK)
-#define bfin_write_TWI1_INT_MASK(val)          bfin_write16(TWI1_INT_MASK, val)
-#define bfin_read_TWI1_FIFO_CTRL()             bfin_read16(TWI1_FIFO_CTRL)
-#define bfin_write_TWI1_FIFO_CTRL(val)         bfin_write16(TWI1_FIFO_CTRL, val)
-#define bfin_read_TWI1_FIFO_STAT()             bfin_read16(TWI1_FIFO_STAT)
-#define bfin_write_TWI1_FIFO_STAT(val)         bfin_write16(TWI1_FIFO_STAT, val)
-#define bfin_read_TWI1_XMT_DATA8()             bfin_read16(TWI1_XMT_DATA8)
-#define bfin_write_TWI1_XMT_DATA8(val)         bfin_write16(TWI1_XMT_DATA8, val)
-#define bfin_read_TWI1_XMT_DATA16()            bfin_read16(TWI1_XMT_DATA16)
-#define bfin_write_TWI1_XMT_DATA16(val)                bfin_write16(TWI1_XMT_DATA16, val)
-#define bfin_read_TWI1_RCV_DATA8()             bfin_read16(TWI1_RCV_DATA8)
-#define bfin_write_TWI1_RCV_DATA8(val)         bfin_write16(TWI1_RCV_DATA8, val)
-#define bfin_read_TWI1_RCV_DATA16()            bfin_read16(TWI1_RCV_DATA16)
-#define bfin_write_TWI1_RCV_DATA16(val)                bfin_write16(TWI1_RCV_DATA16, val)
-
 /* SPI2  Registers */
 
 #define bfin_read_SPI2_CTL()           bfin_read16(SPI2_CTL)
index 674be0216bff17b521e7137c7e5b1bf27219914b..ae971ebff6a07fefca9326bef05e7260af244be4 100644 (file)
 
 /* Two Wire Interface Registers (TWI1) */
 
-#define bfin_read_TWI1_CLKDIV()                        bfin_read16(TWI1_CLKDIV)
-#define bfin_write_TWI1_CLKDIV(val)            bfin_write16(TWI1_CLKDIV, val)
-#define bfin_read_TWI1_CONTROL()               bfin_read16(TWI1_CONTROL)
-#define bfin_write_TWI1_CONTROL(val)           bfin_write16(TWI1_CONTROL, val)
-#define bfin_read_TWI1_SLAVE_CTRL()            bfin_read16(TWI1_SLAVE_CTRL)
-#define bfin_write_TWI1_SLAVE_CTRL(val)                bfin_write16(TWI1_SLAVE_CTRL, val)
-#define bfin_read_TWI1_SLAVE_STAT()            bfin_read16(TWI1_SLAVE_STAT)
-#define bfin_write_TWI1_SLAVE_STAT(val)                bfin_write16(TWI1_SLAVE_STAT, val)
-#define bfin_read_TWI1_SLAVE_ADDR()            bfin_read16(TWI1_SLAVE_ADDR)
-#define bfin_write_TWI1_SLAVE_ADDR(val)                bfin_write16(TWI1_SLAVE_ADDR, val)
-#define bfin_read_TWI1_MASTER_CTRL()           bfin_read16(TWI1_MASTER_CTRL)
-#define bfin_write_TWI1_MASTER_CTRL(val)       bfin_write16(TWI1_MASTER_CTRL, val)
-#define bfin_read_TWI1_MASTER_STAT()           bfin_read16(TWI1_MASTER_STAT)
-#define bfin_write_TWI1_MASTER_STAT(val)       bfin_write16(TWI1_MASTER_STAT, val)
-#define bfin_read_TWI1_MASTER_ADDR()           bfin_read16(TWI1_MASTER_ADDR)
-#define bfin_write_TWI1_MASTER_ADDR(val)       bfin_write16(TWI1_MASTER_ADDR, val)
-#define bfin_read_TWI1_INT_STAT()              bfin_read16(TWI1_INT_STAT)
-#define bfin_write_TWI1_INT_STAT(val)          bfin_write16(TWI1_INT_STAT, val)
-#define bfin_read_TWI1_INT_MASK()              bfin_read16(TWI1_INT_MASK)
-#define bfin_write_TWI1_INT_MASK(val)          bfin_write16(TWI1_INT_MASK, val)
-#define bfin_read_TWI1_FIFO_CTRL()             bfin_read16(TWI1_FIFO_CTRL)
-#define bfin_write_TWI1_FIFO_CTRL(val)         bfin_write16(TWI1_FIFO_CTRL, val)
-#define bfin_read_TWI1_FIFO_STAT()             bfin_read16(TWI1_FIFO_STAT)
-#define bfin_write_TWI1_FIFO_STAT(val)         bfin_write16(TWI1_FIFO_STAT, val)
-#define bfin_read_TWI1_XMT_DATA8()             bfin_read16(TWI1_XMT_DATA8)
-#define bfin_write_TWI1_XMT_DATA8(val)         bfin_write16(TWI1_XMT_DATA8, val)
-#define bfin_read_TWI1_XMT_DATA16()            bfin_read16(TWI1_XMT_DATA16)
-#define bfin_write_TWI1_XMT_DATA16(val)                bfin_write16(TWI1_XMT_DATA16, val)
-#define bfin_read_TWI1_RCV_DATA8()             bfin_read16(TWI1_RCV_DATA8)
-#define bfin_write_TWI1_RCV_DATA8(val)         bfin_write16(TWI1_RCV_DATA8, val)
-#define bfin_read_TWI1_RCV_DATA16()            bfin_read16(TWI1_RCV_DATA16)
-#define bfin_write_TWI1_RCV_DATA16(val)                bfin_write16(TWI1_RCV_DATA16, val)
-
 /* SPI2  Registers */
 
 #define bfin_read_SPI2_CTL()           bfin_read16(SPI2_CTL)
index 2ab5b7c008206f5b981bd3fd2c5d0162207a0ac3..92d07d96199905a651676e0d057d8dcf6c63ec0b 100644 (file)
 
 /* Two Wire Interface Registers (TWI1) */
 
-#define bfin_read_TWI1_CLKDIV()                        bfin_read16(TWI1_CLKDIV)
-#define bfin_write_TWI1_CLKDIV(val)            bfin_write16(TWI1_CLKDIV, val)
-#define bfin_read_TWI1_CONTROL()               bfin_read16(TWI1_CONTROL)
-#define bfin_write_TWI1_CONTROL(val)           bfin_write16(TWI1_CONTROL, val)
-#define bfin_read_TWI1_SLAVE_CTRL()            bfin_read16(TWI1_SLAVE_CTRL)
-#define bfin_write_TWI1_SLAVE_CTRL(val)                bfin_write16(TWI1_SLAVE_CTRL, val)
-#define bfin_read_TWI1_SLAVE_STAT()            bfin_read16(TWI1_SLAVE_STAT)
-#define bfin_write_TWI1_SLAVE_STAT(val)                bfin_write16(TWI1_SLAVE_STAT, val)
-#define bfin_read_TWI1_SLAVE_ADDR()            bfin_read16(TWI1_SLAVE_ADDR)
-#define bfin_write_TWI1_SLAVE_ADDR(val)                bfin_write16(TWI1_SLAVE_ADDR, val)
-#define bfin_read_TWI1_MASTER_CTRL()           bfin_read16(TWI1_MASTER_CTRL)
-#define bfin_write_TWI1_MASTER_CTRL(val)       bfin_write16(TWI1_MASTER_CTRL, val)
-#define bfin_read_TWI1_MASTER_STAT()           bfin_read16(TWI1_MASTER_STAT)
-#define bfin_write_TWI1_MASTER_STAT(val)       bfin_write16(TWI1_MASTER_STAT, val)
-#define bfin_read_TWI1_MASTER_ADDR()           bfin_read16(TWI1_MASTER_ADDR)
-#define bfin_write_TWI1_MASTER_ADDR(val)       bfin_write16(TWI1_MASTER_ADDR, val)
-#define bfin_read_TWI1_INT_STAT()              bfin_read16(TWI1_INT_STAT)
-#define bfin_write_TWI1_INT_STAT(val)          bfin_write16(TWI1_INT_STAT, val)
-#define bfin_read_TWI1_INT_MASK()              bfin_read16(TWI1_INT_MASK)
-#define bfin_write_TWI1_INT_MASK(val)          bfin_write16(TWI1_INT_MASK, val)
-#define bfin_read_TWI1_FIFO_CTRL()             bfin_read16(TWI1_FIFO_CTRL)
-#define bfin_write_TWI1_FIFO_CTRL(val)         bfin_write16(TWI1_FIFO_CTRL, val)
-#define bfin_read_TWI1_FIFO_STAT()             bfin_read16(TWI1_FIFO_STAT)
-#define bfin_write_TWI1_FIFO_STAT(val)         bfin_write16(TWI1_FIFO_STAT, val)
-#define bfin_read_TWI1_XMT_DATA8()             bfin_read16(TWI1_XMT_DATA8)
-#define bfin_write_TWI1_XMT_DATA8(val)         bfin_write16(TWI1_XMT_DATA8, val)
-#define bfin_read_TWI1_XMT_DATA16()            bfin_read16(TWI1_XMT_DATA16)
-#define bfin_write_TWI1_XMT_DATA16(val)                bfin_write16(TWI1_XMT_DATA16, val)
-#define bfin_read_TWI1_RCV_DATA8()             bfin_read16(TWI1_RCV_DATA8)
-#define bfin_write_TWI1_RCV_DATA8(val)         bfin_write16(TWI1_RCV_DATA8, val)
-#define bfin_read_TWI1_RCV_DATA16()            bfin_read16(TWI1_RCV_DATA16)
-#define bfin_write_TWI1_RCV_DATA16(val)                bfin_write16(TWI1_RCV_DATA16, val)
-
 /* SPI2 Registers */
 
 #define bfin_read_SPI2_CTL()           bfin_read16(SPI2_CTL)
 #define bfin_read_USB_DMA5ADDRHIGH()           bfin_read16(USB_DMA5ADDRHIGH)
 #define bfin_write_USB_DMA5ADDRHIGH(val)               bfin_write16(USB_DMA5ADDRHIGH, val)
 #define bfin_read_USB_DMA5COUNTLOW()           bfin_read16(USB_DMA5COUNTLOW)
-#define bfin_write_USB_DMA5COUNTLOW(val)       fin_write16(USB_DMA5COUNTLOW, val)
+#define bfin_write_USB_DMA5COUNTLOW(val)       bfin_write16(USB_DMA5COUNTLOW, val)
 #define bfin_read_USB_DMA5COUNTHIGH()          bfin_read16(USB_DMA5COUNTHIGH)
 #define bfin_write_USB_DMA5COUNTHIGH(val)      bfin_write16(USB_DMA5COUNTHIGH, val)
 
index 19ddcd83c71f130c658ea593495660faa1f6cb2a..57ac8cb9b1f6be7c968aa28b4e3ca2fbee284d7e 100644 (file)
 /* PLL Registers */
 
 #define bfin_read_PLL_CTL()            bfin_read16(PLL_CTL)
-#define bfin_write_PLL_CTL(val)                bfin_write16(PLL_CTL, val)
+/* Writing to PLL_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_PLL_CTL(unsigned int val)
+{
+       unsigned long flags, iwr0, iwr1, iwr2;
+
+       if (val == bfin_read_PLL_CTL())
+               return;
+
+       local_irq_save(flags);
+       /* Enable the PLL Wakeup bit in SIC IWR */
+       iwr0 = bfin_read32(SIC_IWR0);
+       iwr1 = bfin_read32(SIC_IWR1);
+       iwr2 = bfin_read32(SIC_IWR2);
+       /* Only allow PPL Wakeup) */
+       bfin_write32(SIC_IWR0, IWR_ENABLE(0));
+       bfin_write32(SIC_IWR1, 0);
+       bfin_write32(SIC_IWR2, 0);
+
+       bfin_write16(PLL_CTL, val);
+       SSYNC();
+       asm("IDLE;");
+
+       bfin_write32(SIC_IWR0, iwr0);
+       bfin_write32(SIC_IWR1, iwr1);
+       bfin_write32(SIC_IWR2, iwr2);
+       local_irq_restore(flags);
+}
 #define bfin_read_PLL_DIV()            bfin_read16(PLL_DIV)
 #define bfin_write_PLL_DIV(val)                bfin_write16(PLL_DIV, val)
 #define bfin_read_VR_CTL()             bfin_read16(VR_CTL)
@@ -52,6 +78,10 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 {
        unsigned long flags, iwr0, iwr1, iwr2;
 
+       if (val == bfin_read_VR_CTL())
+               return;
+
+       local_irq_save(flags);
        /* Enable the PLL Wakeup bit in SIC IWR */
        iwr0 = bfin_read32(SIC_IWR0);
        iwr1 = bfin_read32(SIC_IWR1);
@@ -63,13 +93,12 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 
        bfin_write16(VR_CTL, val);
        SSYNC();
-
-       local_irq_save(flags);
        asm("IDLE;");
-       local_irq_restore(flags);
+
        bfin_write32(SIC_IWR0, iwr0);
        bfin_write32(SIC_IWR1, iwr1);
        bfin_write32(SIC_IWR2, iwr2);
+       local_irq_restore(flags);
 }
 #define bfin_read_PLL_STAT()           bfin_read16(PLL_STAT)
 #define bfin_write_PLL_STAT(val)       bfin_write16(PLL_STAT, val)
@@ -211,39 +240,6 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 
 /* Two Wire Interface Registers (TWI0) */
 
-#define bfin_read_TWI0_CLKDIV()                        bfin_read16(TWI0_CLKDIV)
-#define bfin_write_TWI0_CLKDIV(val)            bfin_write16(TWI0_CLKDIV, val)
-#define bfin_read_TWI0_CONTROL()               bfin_read16(TWI0_CONTROL)
-#define bfin_write_TWI0_CONTROL(val)           bfin_write16(TWI0_CONTROL, val)
-#define bfin_read_TWI0_SLAVE_CTRL()            bfin_read16(TWI0_SLAVE_CTRL)
-#define bfin_write_TWI0_SLAVE_CTRL(val)                bfin_write16(TWI0_SLAVE_CTRL, val)
-#define bfin_read_TWI0_SLAVE_STAT()            bfin_read16(TWI0_SLAVE_STAT)
-#define bfin_write_TWI0_SLAVE_STAT(val)                bfin_write16(TWI0_SLAVE_STAT, val)
-#define bfin_read_TWI0_SLAVE_ADDR()            bfin_read16(TWI0_SLAVE_ADDR)
-#define bfin_write_TWI0_SLAVE_ADDR(val)                bfin_write16(TWI0_SLAVE_ADDR, val)
-#define bfin_read_TWI0_MASTER_CTRL()           bfin_read16(TWI0_MASTER_CTRL)
-#define bfin_write_TWI0_MASTER_CTRL(val)       bfin_write16(TWI0_MASTER_CTRL, val)
-#define bfin_read_TWI0_MASTER_STAT()           bfin_read16(TWI0_MASTER_STAT)
-#define bfin_write_TWI0_MASTER_STAT(val)       bfin_write16(TWI0_MASTER_STAT, val)
-#define bfin_read_TWI0_MASTER_ADDR()           bfin_read16(TWI0_MASTER_ADDR)
-#define bfin_write_TWI0_MASTER_ADDR(val)       bfin_write16(TWI0_MASTER_ADDR, val)
-#define bfin_read_TWI0_INT_STAT()              bfin_read16(TWI0_INT_STAT)
-#define bfin_write_TWI0_INT_STAT(val)          bfin_write16(TWI0_INT_STAT, val)
-#define bfin_read_TWI0_INT_MASK()              bfin_read16(TWI0_INT_MASK)
-#define bfin_write_TWI0_INT_MASK(val)          bfin_write16(TWI0_INT_MASK, val)
-#define bfin_read_TWI0_FIFO_CTRL()             bfin_read16(TWI0_FIFO_CTRL)
-#define bfin_write_TWI0_FIFO_CTRL(val)         bfin_write16(TWI0_FIFO_CTRL, val)
-#define bfin_read_TWI0_FIFO_STAT()             bfin_read16(TWI0_FIFO_STAT)
-#define bfin_write_TWI0_FIFO_STAT(val)         bfin_write16(TWI0_FIFO_STAT, val)
-#define bfin_read_TWI0_XMT_DATA8()             bfin_read16(TWI0_XMT_DATA8)
-#define bfin_write_TWI0_XMT_DATA8(val)         bfin_write16(TWI0_XMT_DATA8, val)
-#define bfin_read_TWI0_XMT_DATA16()            bfin_read16(TWI0_XMT_DATA16)
-#define bfin_write_TWI0_XMT_DATA16(val)                bfin_write16(TWI0_XMT_DATA16, val)
-#define bfin_read_TWI0_RCV_DATA8()             bfin_read16(TWI0_RCV_DATA8)
-#define bfin_write_TWI0_RCV_DATA8(val)         bfin_write16(TWI0_RCV_DATA8, val)
-#define bfin_read_TWI0_RCV_DATA16()            bfin_read16(TWI0_RCV_DATA16)
-#define bfin_write_TWI0_RCV_DATA16(val)                bfin_write16(TWI0_RCV_DATA16, val)
-
 /* SPORT0 is not defined in the shared file because it is not available on the ADSP-BF542 and ADSP-BF544 bfin_read_()rocessors */
 
 /* SPORT1 Registers */
@@ -323,7 +319,7 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 #define bfin_read_EBIU_DDRQUE()                bfin_read32(EBIU_DDRQUE)
 #define bfin_write_EBIU_DDRQUE(val)    bfin_write32(EBIU_DDRQUE, val)
 #define bfin_read_EBIU_ERRADD()        bfin_read32(EBIU_ERRADD)
-#define bfin_write_EBIU_ERRADD(val)    bfin_write32(EBIU_ERRADD)
+#define bfin_write_EBIU_ERRADD(val)    bfin_write32(EBIU_ERRADD, val)
 #define bfin_read_EBIU_ERRMST()                bfin_read16(EBIU_ERRMST)
 #define bfin_write_EBIU_ERRMST(val)    bfin_write16(EBIU_ERRMST, val)
 #define bfin_read_EBIU_RSTCTL()                bfin_read16(EBIU_RSTCTL)
@@ -392,23 +388,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 /* DMA Channel 0 Registers */
 
 #define bfin_read_DMA0_NEXT_DESC_PTR()                 bfin_read32(DMA0_NEXT_DESC_PTR)
-#define bfin_write_DMA0_NEXT_DESC_PTR(val)     bfin_write32(DMA0_NEXT_DESC_PTR)
+#define bfin_write_DMA0_NEXT_DESC_PTR(val)     bfin_write32(DMA0_NEXT_DESC_PTR, val)
 #define bfin_read_DMA0_START_ADDR()            bfin_read32(DMA0_START_ADDR)
-#define bfin_write_DMA0_START_ADDR(val)        bfin_write32(DMA0_START_ADDR)
+#define bfin_write_DMA0_START_ADDR(val)        bfin_write32(DMA0_START_ADDR, val)
 #define bfin_read_DMA0_CONFIG()                        bfin_read16(DMA0_CONFIG)
 #define bfin_write_DMA0_CONFIG(val)            bfin_write16(DMA0_CONFIG, val)
 #define bfin_read_DMA0_X_COUNT()               bfin_read16(DMA0_X_COUNT)
 #define bfin_write_DMA0_X_COUNT(val)           bfin_write16(DMA0_X_COUNT, val)
 #define bfin_read_DMA0_X_MODIFY()              bfin_read16(DMA0_X_MODIFY)
-#define bfin_write_DMA0_X_MODIFY(val)          bfin_write16(DMA0_X_MODIFY)
+#define bfin_write_DMA0_X_MODIFY(val)          bfin_write16(DMA0_X_MODIFY, val)
 #define bfin_read_DMA0_Y_COUNT()               bfin_read16(DMA0_Y_COUNT)
 #define bfin_write_DMA0_Y_COUNT(val)           bfin_write16(DMA0_Y_COUNT, val)
 #define bfin_read_DMA0_Y_MODIFY()              bfin_read16(DMA0_Y_MODIFY)
-#define bfin_write_DMA0_Y_MODIFY(val)          bfin_write16(DMA0_Y_MODIFY)
+#define bfin_write_DMA0_Y_MODIFY(val)          bfin_write16(DMA0_Y_MODIFY, val)
 #define bfin_read_DMA0_CURR_DESC_PTR()                 bfin_read32(DMA0_CURR_DESC_PTR)
-#define bfin_write_DMA0_CURR_DESC_PTR(val)     bfin_write32(DMA0_CURR_DESC_PTR)
+#define bfin_write_DMA0_CURR_DESC_PTR(val)     bfin_write32(DMA0_CURR_DESC_PTR, val)
 #define bfin_read_DMA0_CURR_ADDR()             bfin_read32(DMA0_CURR_ADDR)
-#define bfin_write_DMA0_CURR_ADDR(val)                 bfin_write32(DMA0_CURR_ADDR)
+#define bfin_write_DMA0_CURR_ADDR(val)                 bfin_write32(DMA0_CURR_ADDR, val)
 #define bfin_read_DMA0_IRQ_STATUS()            bfin_read16(DMA0_IRQ_STATUS)
 #define bfin_write_DMA0_IRQ_STATUS(val)                bfin_write16(DMA0_IRQ_STATUS, val)
 #define bfin_read_DMA0_PERIPHERAL_MAP()                bfin_read16(DMA0_PERIPHERAL_MAP)
@@ -421,23 +417,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 /* DMA Channel 1 Registers */
 
 #define bfin_read_DMA1_NEXT_DESC_PTR()                 bfin_read32(DMA1_NEXT_DESC_PTR)
-#define bfin_write_DMA1_NEXT_DESC_PTR(val)     bfin_write32(DMA1_NEXT_DESC_PTR)
+#define bfin_write_DMA1_NEXT_DESC_PTR(val)     bfin_write32(DMA1_NEXT_DESC_PTR, val)
 #define bfin_read_DMA1_START_ADDR()            bfin_read32(DMA1_START_ADDR)
-#define bfin_write_DMA1_START_ADDR(val)        bfin_write32(DMA1_START_ADDR)
+#define bfin_write_DMA1_START_ADDR(val)        bfin_write32(DMA1_START_ADDR, val)
 #define bfin_read_DMA1_CONFIG()                        bfin_read16(DMA1_CONFIG)
 #define bfin_write_DMA1_CONFIG(val)            bfin_write16(DMA1_CONFIG, val)
 #define bfin_read_DMA1_X_COUNT()               bfin_read16(DMA1_X_COUNT)
 #define bfin_write_DMA1_X_COUNT(val)           bfin_write16(DMA1_X_COUNT, val)
 #define bfin_read_DMA1_X_MODIFY()              bfin_read16(DMA1_X_MODIFY)
-#define bfin_write_DMA1_X_MODIFY(val)          bfin_write16(DMA1_X_MODIFY)
+#define bfin_write_DMA1_X_MODIFY(val)          bfin_write16(DMA1_X_MODIFY, val)
 #define bfin_read_DMA1_Y_COUNT()               bfin_read16(DMA1_Y_COUNT)
 #define bfin_write_DMA1_Y_COUNT(val)           bfin_write16(DMA1_Y_COUNT, val)
 #define bfin_read_DMA1_Y_MODIFY()              bfin_read16(DMA1_Y_MODIFY)
-#define bfin_write_DMA1_Y_MODIFY(val)          bfin_write16(DMA1_Y_MODIFY)
+#define bfin_write_DMA1_Y_MODIFY(val)          bfin_write16(DMA1_Y_MODIFY, val)
 #define bfin_read_DMA1_CURR_DESC_PTR()                 bfin_read32(DMA1_CURR_DESC_PTR)
-#define bfin_write_DMA1_CURR_DESC_PTR(val)     bfin_write32(DMA1_CURR_DESC_PTR)
+#define bfin_write_DMA1_CURR_DESC_PTR(val)     bfin_write32(DMA1_CURR_DESC_PTR, val)
 #define bfin_read_DMA1_CURR_ADDR()             bfin_read32(DMA1_CURR_ADDR)
-#define bfin_write_DMA1_CURR_ADDR(val)                 bfin_write32(DMA1_CURR_ADDR)
+#define bfin_write_DMA1_CURR_ADDR(val)                 bfin_write32(DMA1_CURR_ADDR, val)
 #define bfin_read_DMA1_IRQ_STATUS()            bfin_read16(DMA1_IRQ_STATUS)
 #define bfin_write_DMA1_IRQ_STATUS(val)                bfin_write16(DMA1_IRQ_STATUS, val)
 #define bfin_read_DMA1_PERIPHERAL_MAP()                bfin_read16(DMA1_PERIPHERAL_MAP)
@@ -450,23 +446,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 /* DMA Channel 2 Registers */
 
 #define bfin_read_DMA2_NEXT_DESC_PTR()                 bfin_read32(DMA2_NEXT_DESC_PTR)
-#define bfin_write_DMA2_NEXT_DESC_PTR(val)     bfin_write32(DMA2_NEXT_DESC_PTR)
+#define bfin_write_DMA2_NEXT_DESC_PTR(val)     bfin_write32(DMA2_NEXT_DESC_PTR, val)
 #define bfin_read_DMA2_START_ADDR()            bfin_read32(DMA2_START_ADDR)
-#define bfin_write_DMA2_START_ADDR(val)        bfin_write32(DMA2_START_ADDR)
+#define bfin_write_DMA2_START_ADDR(val)        bfin_write32(DMA2_START_ADDR, val)
 #define bfin_read_DMA2_CONFIG()                        bfin_read16(DMA2_CONFIG)
 #define bfin_write_DMA2_CONFIG(val)            bfin_write16(DMA2_CONFIG, val)
 #define bfin_read_DMA2_X_COUNT()               bfin_read16(DMA2_X_COUNT)
 #define bfin_write_DMA2_X_COUNT(val)           bfin_write16(DMA2_X_COUNT, val)
 #define bfin_read_DMA2_X_MODIFY()              bfin_read16(DMA2_X_MODIFY)
-#define bfin_write_DMA2_X_MODIFY(val)          bfin_write16(DMA2_X_MODIFY)
+#define bfin_write_DMA2_X_MODIFY(val)          bfin_write16(DMA2_X_MODIFY, val)
 #define bfin_read_DMA2_Y_COUNT()               bfin_read16(DMA2_Y_COUNT)
 #define bfin_write_DMA2_Y_COUNT(val)           bfin_write16(DMA2_Y_COUNT, val)
 #define bfin_read_DMA2_Y_MODIFY()              bfin_read16(DMA2_Y_MODIFY)
-#define bfin_write_DMA2_Y_MODIFY(val)          bfin_write16(DMA2_Y_MODIFY)
+#define bfin_write_DMA2_Y_MODIFY(val)          bfin_write16(DMA2_Y_MODIFY, val)
 #define bfin_read_DMA2_CURR_DESC_PTR()                 bfin_read32(DMA2_CURR_DESC_PTR)
-#define bfin_write_DMA2_CURR_DESC_PTR(val)     bfin_write32(DMA2_CURR_DESC_PTR)
+#define bfin_write_DMA2_CURR_DESC_PTR(val)     bfin_write32(DMA2_CURR_DESC_PTR, val)
 #define bfin_read_DMA2_CURR_ADDR()             bfin_read32(DMA2_CURR_ADDR)
-#define bfin_write_DMA2_CURR_ADDR(val)                 bfin_write32(DMA2_CURR_ADDR)
+#define bfin_write_DMA2_CURR_ADDR(val)                 bfin_write32(DMA2_CURR_ADDR, val)
 #define bfin_read_DMA2_IRQ_STATUS()            bfin_read16(DMA2_IRQ_STATUS)
 #define bfin_write_DMA2_IRQ_STATUS(val)                bfin_write16(DMA2_IRQ_STATUS, val)
 #define bfin_read_DMA2_PERIPHERAL_MAP()                bfin_read16(DMA2_PERIPHERAL_MAP)
@@ -479,23 +475,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 /* DMA Channel 3 Registers */
 
 #define bfin_read_DMA3_NEXT_DESC_PTR()                 bfin_read32(DMA3_NEXT_DESC_PTR)
-#define bfin_write_DMA3_NEXT_DESC_PTR(val)     bfin_write32(DMA3_NEXT_DESC_PTR)
+#define bfin_write_DMA3_NEXT_DESC_PTR(val)     bfin_write32(DMA3_NEXT_DESC_PTR, val)
 #define bfin_read_DMA3_START_ADDR()            bfin_read32(DMA3_START_ADDR)
-#define bfin_write_DMA3_START_ADDR(val)        bfin_write32(DMA3_START_ADDR)
+#define bfin_write_DMA3_START_ADDR(val)        bfin_write32(DMA3_START_ADDR, val)
 #define bfin_read_DMA3_CONFIG()                        bfin_read16(DMA3_CONFIG)
 #define bfin_write_DMA3_CONFIG(val)            bfin_write16(DMA3_CONFIG, val)
 #define bfin_read_DMA3_X_COUNT()               bfin_read16(DMA3_X_COUNT)
 #define bfin_write_DMA3_X_COUNT(val)           bfin_write16(DMA3_X_COUNT, val)
 #define bfin_read_DMA3_X_MODIFY()              bfin_read16(DMA3_X_MODIFY)
-#define bfin_write_DMA3_X_MODIFY(val)          bfin_write16(DMA3_X_MODIFY)
+#define bfin_write_DMA3_X_MODIFY(val)          bfin_write16(DMA3_X_MODIFY, val)
 #define bfin_read_DMA3_Y_COUNT()               bfin_read16(DMA3_Y_COUNT)
 #define bfin_write_DMA3_Y_COUNT(val)           bfin_write16(DMA3_Y_COUNT, val)
 #define bfin_read_DMA3_Y_MODIFY()              bfin_read16(DMA3_Y_MODIFY)
-#define bfin_write_DMA3_Y_MODIFY(val)          bfin_write16(DMA3_Y_MODIFY)
+#define bfin_write_DMA3_Y_MODIFY(val)          bfin_write16(DMA3_Y_MODIFY, val)
 #define bfin_read_DMA3_CURR_DESC_PTR()                 bfin_read32(DMA3_CURR_DESC_PTR)
-#define bfin_write_DMA3_CURR_DESC_PTR(val)     bfin_write32(DMA3_CURR_DESC_PTR)
+#define bfin_write_DMA3_CURR_DESC_PTR(val)     bfin_write32(DMA3_CURR_DESC_PTR, val)
 #define bfin_read_DMA3_CURR_ADDR()             bfin_read32(DMA3_CURR_ADDR)
-#define bfin_write_DMA3_CURR_ADDR(val)                 bfin_write32(DMA3_CURR_ADDR)
+#define bfin_write_DMA3_CURR_ADDR(val)                 bfin_write32(DMA3_CURR_ADDR, val)
 #define bfin_read_DMA3_IRQ_STATUS()            bfin_read16(DMA3_IRQ_STATUS)
 #define bfin_write_DMA3_IRQ_STATUS(val)                bfin_write16(DMA3_IRQ_STATUS, val)
 #define bfin_read_DMA3_PERIPHERAL_MAP()                bfin_read16(DMA3_PERIPHERAL_MAP)
@@ -508,23 +504,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 /* DMA Channel 4 Registers */
 
 #define bfin_read_DMA4_NEXT_DESC_PTR()                 bfin_read32(DMA4_NEXT_DESC_PTR)
-#define bfin_write_DMA4_NEXT_DESC_PTR(val)     bfin_write32(DMA4_NEXT_DESC_PTR)
+#define bfin_write_DMA4_NEXT_DESC_PTR(val)     bfin_write32(DMA4_NEXT_DESC_PTR, val)
 #define bfin_read_DMA4_START_ADDR()            bfin_read32(DMA4_START_ADDR)
-#define bfin_write_DMA4_START_ADDR(val)        bfin_write32(DMA4_START_ADDR)
+#define bfin_write_DMA4_START_ADDR(val)        bfin_write32(DMA4_START_ADDR, val)
 #define bfin_read_DMA4_CONFIG()                        bfin_read16(DMA4_CONFIG)
 #define bfin_write_DMA4_CONFIG(val)            bfin_write16(DMA4_CONFIG, val)
 #define bfin_read_DMA4_X_COUNT()               bfin_read16(DMA4_X_COUNT)
 #define bfin_write_DMA4_X_COUNT(val)           bfin_write16(DMA4_X_COUNT, val)
 #define bfin_read_DMA4_X_MODIFY()              bfin_read16(DMA4_X_MODIFY)
-#define bfin_write_DMA4_X_MODIFY(val)          bfin_write16(DMA4_X_MODIFY)
+#define bfin_write_DMA4_X_MODIFY(val)          bfin_write16(DMA4_X_MODIFY, val)
 #define bfin_read_DMA4_Y_COUNT()               bfin_read16(DMA4_Y_COUNT)
 #define bfin_write_DMA4_Y_COUNT(val)           bfin_write16(DMA4_Y_COUNT, val)
 #define bfin_read_DMA4_Y_MODIFY()              bfin_read16(DMA4_Y_MODIFY)
-#define bfin_write_DMA4_Y_MODIFY(val)          bfin_write16(DMA4_Y_MODIFY)
+#define bfin_write_DMA4_Y_MODIFY(val)          bfin_write16(DMA4_Y_MODIFY, val)
 #define bfin_read_DMA4_CURR_DESC_PTR()                 bfin_read32(DMA4_CURR_DESC_PTR)
-#define bfin_write_DMA4_CURR_DESC_PTR(val)     bfin_write32(DMA4_CURR_DESC_PTR)
+#define bfin_write_DMA4_CURR_DESC_PTR(val)     bfin_write32(DMA4_CURR_DESC_PTR, val)
 #define bfin_read_DMA4_CURR_ADDR()             bfin_read32(DMA4_CURR_ADDR)
-#define bfin_write_DMA4_CURR_ADDR(val)                 bfin_write32(DMA4_CURR_ADDR)
+#define bfin_write_DMA4_CURR_ADDR(val)                 bfin_write32(DMA4_CURR_ADDR, val)
 #define bfin_read_DMA4_IRQ_STATUS()            bfin_read16(DMA4_IRQ_STATUS)
 #define bfin_write_DMA4_IRQ_STATUS(val)                bfin_write16(DMA4_IRQ_STATUS, val)
 #define bfin_read_DMA4_PERIPHERAL_MAP()                bfin_read16(DMA4_PERIPHERAL_MAP)
@@ -537,23 +533,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 /* DMA Channel 5 Registers */
 
 #define bfin_read_DMA5_NEXT_DESC_PTR()                 bfin_read32(DMA5_NEXT_DESC_PTR)
-#define bfin_write_DMA5_NEXT_DESC_PTR(val)     bfin_write32(DMA5_NEXT_DESC_PTR)
+#define bfin_write_DMA5_NEXT_DESC_PTR(val)     bfin_write32(DMA5_NEXT_DESC_PTR, val)
 #define bfin_read_DMA5_START_ADDR()            bfin_read32(DMA5_START_ADDR)
-#define bfin_write_DMA5_START_ADDR(val)        bfin_write32(DMA5_START_ADDR)
+#define bfin_write_DMA5_START_ADDR(val)        bfin_write32(DMA5_START_ADDR, val)
 #define bfin_read_DMA5_CONFIG()                        bfin_read16(DMA5_CONFIG)
 #define bfin_write_DMA5_CONFIG(val)            bfin_write16(DMA5_CONFIG, val)
 #define bfin_read_DMA5_X_COUNT()               bfin_read16(DMA5_X_COUNT)
 #define bfin_write_DMA5_X_COUNT(val)           bfin_write16(DMA5_X_COUNT, val)
 #define bfin_read_DMA5_X_MODIFY()              bfin_read16(DMA5_X_MODIFY)
-#define bfin_write_DMA5_X_MODIFY(val)          bfin_write16(DMA5_X_MODIFY)
+#define bfin_write_DMA5_X_MODIFY(val)          bfin_write16(DMA5_X_MODIFY, val)
 #define bfin_read_DMA5_Y_COUNT()               bfin_read16(DMA5_Y_COUNT)
 #define bfin_write_DMA5_Y_COUNT(val)           bfin_write16(DMA5_Y_COUNT, val)
 #define bfin_read_DMA5_Y_MODIFY()              bfin_read16(DMA5_Y_MODIFY)
-#define bfin_write_DMA5_Y_MODIFY(val)          bfin_write16(DMA5_Y_MODIFY)
+#define bfin_write_DMA5_Y_MODIFY(val)          bfin_write16(DMA5_Y_MODIFY, val)
 #define bfin_read_DMA5_CURR_DESC_PTR()                 bfin_read32(DMA5_CURR_DESC_PTR)
-#define bfin_write_DMA5_CURR_DESC_PTR(val)     bfin_write32(DMA5_CURR_DESC_PTR)
+#define bfin_write_DMA5_CURR_DESC_PTR(val)     bfin_write32(DMA5_CURR_DESC_PTR, val)
 #define bfin_read_DMA5_CURR_ADDR()             bfin_read32(DMA5_CURR_ADDR)
-#define bfin_write_DMA5_CURR_ADDR(val)                 bfin_write32(DMA5_CURR_ADDR)
+#define bfin_write_DMA5_CURR_ADDR(val)                 bfin_write32(DMA5_CURR_ADDR, val)
 #define bfin_read_DMA5_IRQ_STATUS()            bfin_read16(DMA5_IRQ_STATUS)
 #define bfin_write_DMA5_IRQ_STATUS(val)                bfin_write16(DMA5_IRQ_STATUS, val)
 #define bfin_read_DMA5_PERIPHERAL_MAP()                bfin_read16(DMA5_PERIPHERAL_MAP)
@@ -566,23 +562,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 /* DMA Channel 6 Registers */
 
 #define bfin_read_DMA6_NEXT_DESC_PTR()                 bfin_read32(DMA6_NEXT_DESC_PTR)
-#define bfin_write_DMA6_NEXT_DESC_PTR(val)     bfin_write32(DMA6_NEXT_DESC_PTR)
+#define bfin_write_DMA6_NEXT_DESC_PTR(val)     bfin_write32(DMA6_NEXT_DESC_PTR, val)
 #define bfin_read_DMA6_START_ADDR()            bfin_read32(DMA6_START_ADDR)
-#define bfin_write_DMA6_START_ADDR(val)        bfin_write32(DMA6_START_ADDR)
+#define bfin_write_DMA6_START_ADDR(val)        bfin_write32(DMA6_START_ADDR, val)
 #define bfin_read_DMA6_CONFIG()                        bfin_read16(DMA6_CONFIG)
 #define bfin_write_DMA6_CONFIG(val)            bfin_write16(DMA6_CONFIG, val)
 #define bfin_read_DMA6_X_COUNT()               bfin_read16(DMA6_X_COUNT)
 #define bfin_write_DMA6_X_COUNT(val)           bfin_write16(DMA6_X_COUNT, val)
 #define bfin_read_DMA6_X_MODIFY()              bfin_read16(DMA6_X_MODIFY)
-#define bfin_write_DMA6_X_MODIFY(val)          bfin_write16(DMA6_X_MODIFY)
+#define bfin_write_DMA6_X_MODIFY(val)          bfin_write16(DMA6_X_MODIFY, val)
 #define bfin_read_DMA6_Y_COUNT()               bfin_read16(DMA6_Y_COUNT)
 #define bfin_write_DMA6_Y_COUNT(val)           bfin_write16(DMA6_Y_COUNT, val)
 #define bfin_read_DMA6_Y_MODIFY()              bfin_read16(DMA6_Y_MODIFY)
-#define bfin_write_DMA6_Y_MODIFY(val)          bfin_write16(DMA6_Y_MODIFY)
+#define bfin_write_DMA6_Y_MODIFY(val)          bfin_write16(DMA6_Y_MODIFY, val)
 #define bfin_read_DMA6_CURR_DESC_PTR()                 bfin_read32(DMA6_CURR_DESC_PTR)
-#define bfin_write_DMA6_CURR_DESC_PTR(val)     bfin_write32(DMA6_CURR_DESC_PTR)
+#define bfin_write_DMA6_CURR_DESC_PTR(val)     bfin_write32(DMA6_CURR_DESC_PTR, val)
 #define bfin_read_DMA6_CURR_ADDR()             bfin_read32(DMA6_CURR_ADDR)
-#define bfin_write_DMA6_CURR_ADDR(val)                 bfin_write32(DMA6_CURR_ADDR)
+#define bfin_write_DMA6_CURR_ADDR(val)                 bfin_write32(DMA6_CURR_ADDR, val)
 #define bfin_read_DMA6_IRQ_STATUS()            bfin_read16(DMA6_IRQ_STATUS)
 #define bfin_write_DMA6_IRQ_STATUS(val)                bfin_write16(DMA6_IRQ_STATUS, val)
 #define bfin_read_DMA6_PERIPHERAL_MAP()                bfin_read16(DMA6_PERIPHERAL_MAP)
@@ -595,23 +591,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 /* DMA Channel 7 Registers */
 
 #define bfin_read_DMA7_NEXT_DESC_PTR()                 bfin_read32(DMA7_NEXT_DESC_PTR)
-#define bfin_write_DMA7_NEXT_DESC_PTR(val)     bfin_write32(DMA7_NEXT_DESC_PTR)
+#define bfin_write_DMA7_NEXT_DESC_PTR(val)     bfin_write32(DMA7_NEXT_DESC_PTR, val)
 #define bfin_read_DMA7_START_ADDR()            bfin_read32(DMA7_START_ADDR)
-#define bfin_write_DMA7_START_ADDR(val)        bfin_write32(DMA7_START_ADDR)
+#define bfin_write_DMA7_START_ADDR(val)        bfin_write32(DMA7_START_ADDR, val)
 #define bfin_read_DMA7_CONFIG()                        bfin_read16(DMA7_CONFIG)
 #define bfin_write_DMA7_CONFIG(val)            bfin_write16(DMA7_CONFIG, val)
 #define bfin_read_DMA7_X_COUNT()               bfin_read16(DMA7_X_COUNT)
 #define bfin_write_DMA7_X_COUNT(val)           bfin_write16(DMA7_X_COUNT, val)
 #define bfin_read_DMA7_X_MODIFY()              bfin_read16(DMA7_X_MODIFY)
-#define bfin_write_DMA7_X_MODIFY(val)          bfin_write16(DMA7_X_MODIFY)
+#define bfin_write_DMA7_X_MODIFY(val)          bfin_write16(DMA7_X_MODIFY, val)
 #define bfin_read_DMA7_Y_COUNT()               bfin_read16(DMA7_Y_COUNT)
 #define bfin_write_DMA7_Y_COUNT(val)           bfin_write16(DMA7_Y_COUNT, val)
 #define bfin_read_DMA7_Y_MODIFY()              bfin_read16(DMA7_Y_MODIFY)
-#define bfin_write_DMA7_Y_MODIFY(val)          bfin_write16(DMA7_Y_MODIFY)
+#define bfin_write_DMA7_Y_MODIFY(val)          bfin_write16(DMA7_Y_MODIFY, val)
 #define bfin_read_DMA7_CURR_DESC_PTR()                 bfin_read32(DMA7_CURR_DESC_PTR)
-#define bfin_write_DMA7_CURR_DESC_PTR(val)     bfin_write32(DMA7_CURR_DESC_PTR)
+#define bfin_write_DMA7_CURR_DESC_PTR(val)     bfin_write32(DMA7_CURR_DESC_PTR, val)
 #define bfin_read_DMA7_CURR_ADDR()             bfin_read32(DMA7_CURR_ADDR)
-#define bfin_write_DMA7_CURR_ADDR(val)                 bfin_write32(DMA7_CURR_ADDR)
+#define bfin_write_DMA7_CURR_ADDR(val)                 bfin_write32(DMA7_CURR_ADDR, val)
 #define bfin_read_DMA7_IRQ_STATUS()            bfin_read16(DMA7_IRQ_STATUS)
 #define bfin_write_DMA7_IRQ_STATUS(val)                bfin_write16(DMA7_IRQ_STATUS, val)
 #define bfin_read_DMA7_PERIPHERAL_MAP()                bfin_read16(DMA7_PERIPHERAL_MAP)
@@ -624,23 +620,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 /* DMA Channel 8 Registers */
 
 #define bfin_read_DMA8_NEXT_DESC_PTR()                 bfin_read32(DMA8_NEXT_DESC_PTR)
-#define bfin_write_DMA8_NEXT_DESC_PTR(val)     bfin_write32(DMA8_NEXT_DESC_PTR)
+#define bfin_write_DMA8_NEXT_DESC_PTR(val)     bfin_write32(DMA8_NEXT_DESC_PTR, val)
 #define bfin_read_DMA8_START_ADDR()            bfin_read32(DMA8_START_ADDR)
-#define bfin_write_DMA8_START_ADDR(val)        bfin_write32(DMA8_START_ADDR)
+#define bfin_write_DMA8_START_ADDR(val)        bfin_write32(DMA8_START_ADDR, val)
 #define bfin_read_DMA8_CONFIG()                        bfin_read16(DMA8_CONFIG)
 #define bfin_write_DMA8_CONFIG(val)            bfin_write16(DMA8_CONFIG, val)
 #define bfin_read_DMA8_X_COUNT()               bfin_read16(DMA8_X_COUNT)
 #define bfin_write_DMA8_X_COUNT(val)           bfin_write16(DMA8_X_COUNT, val)
 #define bfin_read_DMA8_X_MODIFY()              bfin_read16(DMA8_X_MODIFY)
-#define bfin_write_DMA8_X_MODIFY(val)          bfin_write16(DMA8_X_MODIFY)
+#define bfin_write_DMA8_X_MODIFY(val)          bfin_write16(DMA8_X_MODIFY, val)
 #define bfin_read_DMA8_Y_COUNT()               bfin_read16(DMA8_Y_COUNT)
 #define bfin_write_DMA8_Y_COUNT(val)           bfin_write16(DMA8_Y_COUNT, val)
 #define bfin_read_DMA8_Y_MODIFY()              bfin_read16(DMA8_Y_MODIFY)
-#define bfin_write_DMA8_Y_MODIFY(val)          bfin_write16(DMA8_Y_MODIFY)
+#define bfin_write_DMA8_Y_MODIFY(val)          bfin_write16(DMA8_Y_MODIFY, val)
 #define bfin_read_DMA8_CURR_DESC_PTR()                 bfin_read32(DMA8_CURR_DESC_PTR)
-#define bfin_write_DMA8_CURR_DESC_PTR(val)     bfin_write32(DMA8_CURR_DESC_PTR)
+#define bfin_write_DMA8_CURR_DESC_PTR(val)     bfin_write32(DMA8_CURR_DESC_PTR, val)
 #define bfin_read_DMA8_CURR_ADDR()             bfin_read32(DMA8_CURR_ADDR)
-#define bfin_write_DMA8_CURR_ADDR(val)                 bfin_write32(DMA8_CURR_ADDR)
+#define bfin_write_DMA8_CURR_ADDR(val)                 bfin_write32(DMA8_CURR_ADDR, val)
 #define bfin_read_DMA8_IRQ_STATUS()            bfin_read16(DMA8_IRQ_STATUS)
 #define bfin_write_DMA8_IRQ_STATUS(val)                bfin_write16(DMA8_IRQ_STATUS, val)
 #define bfin_read_DMA8_PERIPHERAL_MAP()                bfin_read16(DMA8_PERIPHERAL_MAP)
@@ -653,23 +649,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 /* DMA Channel 9 Registers */
 
 #define bfin_read_DMA9_NEXT_DESC_PTR()                 bfin_read32(DMA9_NEXT_DESC_PTR)
-#define bfin_write_DMA9_NEXT_DESC_PTR(val)     bfin_write32(DMA9_NEXT_DESC_PTR)
+#define bfin_write_DMA9_NEXT_DESC_PTR(val)     bfin_write32(DMA9_NEXT_DESC_PTR, val)
 #define bfin_read_DMA9_START_ADDR()            bfin_read32(DMA9_START_ADDR)
-#define bfin_write_DMA9_START_ADDR(val)        bfin_write32(DMA9_START_ADDR)
+#define bfin_write_DMA9_START_ADDR(val)        bfin_write32(DMA9_START_ADDR, val)
 #define bfin_read_DMA9_CONFIG()                        bfin_read16(DMA9_CONFIG)
 #define bfin_write_DMA9_CONFIG(val)            bfin_write16(DMA9_CONFIG, val)
 #define bfin_read_DMA9_X_COUNT()               bfin_read16(DMA9_X_COUNT)
 #define bfin_write_DMA9_X_COUNT(val)           bfin_write16(DMA9_X_COUNT, val)
 #define bfin_read_DMA9_X_MODIFY()              bfin_read16(DMA9_X_MODIFY)
-#define bfin_write_DMA9_X_MODIFY(val)          bfin_write16(DMA9_X_MODIFY)
+#define bfin_write_DMA9_X_MODIFY(val)          bfin_write16(DMA9_X_MODIFY, val)
 #define bfin_read_DMA9_Y_COUNT()               bfin_read16(DMA9_Y_COUNT)
 #define bfin_write_DMA9_Y_COUNT(val)           bfin_write16(DMA9_Y_COUNT, val)
 #define bfin_read_DMA9_Y_MODIFY()              bfin_read16(DMA9_Y_MODIFY)
-#define bfin_write_DMA9_Y_MODIFY(val)          bfin_write16(DMA9_Y_MODIFY)
+#define bfin_write_DMA9_Y_MODIFY(val)          bfin_write16(DMA9_Y_MODIFY, val)
 #define bfin_read_DMA9_CURR_DESC_PTR()                 bfin_read32(DMA9_CURR_DESC_PTR)
-#define bfin_write_DMA9_CURR_DESC_PTR(val)     bfin_write32(DMA9_CURR_DESC_PTR)
+#define bfin_write_DMA9_CURR_DESC_PTR(val)     bfin_write32(DMA9_CURR_DESC_PTR, val)
 #define bfin_read_DMA9_CURR_ADDR()             bfin_read32(DMA9_CURR_ADDR)
-#define bfin_write_DMA9_CURR_ADDR(val)                 bfin_write32(DMA9_CURR_ADDR)
+#define bfin_write_DMA9_CURR_ADDR(val)                 bfin_write32(DMA9_CURR_ADDR, val)
 #define bfin_read_DMA9_IRQ_STATUS()            bfin_read16(DMA9_IRQ_STATUS)
 #define bfin_write_DMA9_IRQ_STATUS(val)                bfin_write16(DMA9_IRQ_STATUS, val)
 #define bfin_read_DMA9_PERIPHERAL_MAP()                bfin_read16(DMA9_PERIPHERAL_MAP)
@@ -682,23 +678,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 /* DMA Channel 10 Registers */
 
 #define bfin_read_DMA10_NEXT_DESC_PTR()        bfin_read32(DMA10_NEXT_DESC_PTR)
-#define bfin_write_DMA10_NEXT_DESC_PTR(val)    bfin_write32(DMA10_NEXT_DESC_PTR)
+#define bfin_write_DMA10_NEXT_DESC_PTR(val)    bfin_write32(DMA10_NEXT_DESC_PTR, val)
 #define bfin_read_DMA10_START_ADDR()           bfin_read32(DMA10_START_ADDR)
-#define bfin_write_DMA10_START_ADDR(val)       bfin_write32(DMA10_START_ADDR)
+#define bfin_write_DMA10_START_ADDR(val)       bfin_write32(DMA10_START_ADDR, val)
 #define bfin_read_DMA10_CONFIG()               bfin_read16(DMA10_CONFIG)
 #define bfin_write_DMA10_CONFIG(val)           bfin_write16(DMA10_CONFIG, val)
 #define bfin_read_DMA10_X_COUNT()              bfin_read16(DMA10_X_COUNT)
 #define bfin_write_DMA10_X_COUNT(val)          bfin_write16(DMA10_X_COUNT, val)
 #define bfin_read_DMA10_X_MODIFY()             bfin_read16(DMA10_X_MODIFY)
-#define bfin_write_DMA10_X_MODIFY(val)                 bfin_write16(DMA10_X_MODIFY)
+#define bfin_write_DMA10_X_MODIFY(val)                 bfin_write16(DMA10_X_MODIFY, val)
 #define bfin_read_DMA10_Y_COUNT()              bfin_read16(DMA10_Y_COUNT)
 #define bfin_write_DMA10_Y_COUNT(val)          bfin_write16(DMA10_Y_COUNT, val)
 #define bfin_read_DMA10_Y_MODIFY()             bfin_read16(DMA10_Y_MODIFY)
-#define bfin_write_DMA10_Y_MODIFY(val)                 bfin_write16(DMA10_Y_MODIFY)
+#define bfin_write_DMA10_Y_MODIFY(val)                 bfin_write16(DMA10_Y_MODIFY, val)
 #define bfin_read_DMA10_CURR_DESC_PTR()        bfin_read32(DMA10_CURR_DESC_PTR)
-#define bfin_write_DMA10_CURR_DESC_PTR(val)    bfin_write32(DMA10_CURR_DESC_PTR)
+#define bfin_write_DMA10_CURR_DESC_PTR(val)    bfin_write32(DMA10_CURR_DESC_PTR, val)
 #define bfin_read_DMA10_CURR_ADDR()            bfin_read32(DMA10_CURR_ADDR)
-#define bfin_write_DMA10_CURR_ADDR(val)        bfin_write32(DMA10_CURR_ADDR)
+#define bfin_write_DMA10_CURR_ADDR(val)        bfin_write32(DMA10_CURR_ADDR, val)
 #define bfin_read_DMA10_IRQ_STATUS()           bfin_read16(DMA10_IRQ_STATUS)
 #define bfin_write_DMA10_IRQ_STATUS(val)       bfin_write16(DMA10_IRQ_STATUS, val)
 #define bfin_read_DMA10_PERIPHERAL_MAP()       bfin_read16(DMA10_PERIPHERAL_MAP)
@@ -711,23 +707,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 /* DMA Channel 11 Registers */
 
 #define bfin_read_DMA11_NEXT_DESC_PTR()        bfin_read32(DMA11_NEXT_DESC_PTR)
-#define bfin_write_DMA11_NEXT_DESC_PTR(val)    bfin_write32(DMA11_NEXT_DESC_PTR)
+#define bfin_write_DMA11_NEXT_DESC_PTR(val)    bfin_write32(DMA11_NEXT_DESC_PTR, val)
 #define bfin_read_DMA11_START_ADDR()           bfin_read32(DMA11_START_ADDR)
-#define bfin_write_DMA11_START_ADDR(val)       bfin_write32(DMA11_START_ADDR)
+#define bfin_write_DMA11_START_ADDR(val)       bfin_write32(DMA11_START_ADDR, val)
 #define bfin_read_DMA11_CONFIG()               bfin_read16(DMA11_CONFIG)
 #define bfin_write_DMA11_CONFIG(val)           bfin_write16(DMA11_CONFIG, val)
 #define bfin_read_DMA11_X_COUNT()              bfin_read16(DMA11_X_COUNT)
 #define bfin_write_DMA11_X_COUNT(val)          bfin_write16(DMA11_X_COUNT, val)
 #define bfin_read_DMA11_X_MODIFY()             bfin_read16(DMA11_X_MODIFY)
-#define bfin_write_DMA11_X_MODIFY(val)                 bfin_write16(DMA11_X_MODIFY)
+#define bfin_write_DMA11_X_MODIFY(val)                 bfin_write16(DMA11_X_MODIFY, val)
 #define bfin_read_DMA11_Y_COUNT()              bfin_read16(DMA11_Y_COUNT)
 #define bfin_write_DMA11_Y_COUNT(val)          bfin_write16(DMA11_Y_COUNT, val)
 #define bfin_read_DMA11_Y_MODIFY()             bfin_read16(DMA11_Y_MODIFY)
-#define bfin_write_DMA11_Y_MODIFY(val)                 bfin_write16(DMA11_Y_MODIFY)
+#define bfin_write_DMA11_Y_MODIFY(val)                 bfin_write16(DMA11_Y_MODIFY, val)
 #define bfin_read_DMA11_CURR_DESC_PTR()        bfin_read32(DMA11_CURR_DESC_PTR)
-#define bfin_write_DMA11_CURR_DESC_PTR(val)    bfin_write32(DMA11_CURR_DESC_PTR)
+#define bfin_write_DMA11_CURR_DESC_PTR(val)    bfin_write32(DMA11_CURR_DESC_PTR, val)
 #define bfin_read_DMA11_CURR_ADDR()            bfin_read32(DMA11_CURR_ADDR)
-#define bfin_write_DMA11_CURR_ADDR(val)        bfin_write32(DMA11_CURR_ADDR)
+#define bfin_write_DMA11_CURR_ADDR(val)        bfin_write32(DMA11_CURR_ADDR, val)
 #define bfin_read_DMA11_IRQ_STATUS()           bfin_read16(DMA11_IRQ_STATUS)
 #define bfin_write_DMA11_IRQ_STATUS(val)       bfin_write16(DMA11_IRQ_STATUS, val)
 #define bfin_read_DMA11_PERIPHERAL_MAP()       bfin_read16(DMA11_PERIPHERAL_MAP)
@@ -740,7 +736,7 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 /* MDMA Stream 0 Registers */
 
 #define bfin_read_MDMA_D0_NEXT_DESC_PTR()      bfin_read32(MDMA_D0_NEXT_DESC_PTR)
-#define bfin_write_MDMA_D0_NEXT_DESC_PTR(val)  bfin_write32(MDMA_D0_NEXT_DESC_PTR)
+#define bfin_write_MDMA_D0_NEXT_DESC_PTR(val)  bfin_write32(MDMA_D0_NEXT_DESC_PTR, val)
 #define bfin_read_MDMA_D0_START_ADDR()                 bfin_read32(MDMA_D0_START_ADDR)
 #define bfin_write_MDMA_D0_START_ADDR(val)     bfin_write32(MDMA_D0_START_ADDR, val)
 #define bfin_read_MDMA_D0_CONFIG()             bfin_read16(MDMA_D0_CONFIG)
@@ -803,11 +799,11 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 #define bfin_read_MDMA_D1_X_COUNT()            bfin_read16(MDMA_D1_X_COUNT)
 #define bfin_write_MDMA_D1_X_COUNT(val)                bfin_write16(MDMA_D1_X_COUNT, val)
 #define bfin_read_MDMA_D1_X_MODIFY()           bfin_read16(MDMA_D1_X_MODIFY)
-#define bfin_write_MDMA_D1_X_MODIFY(val)       bfin_write16(MDMA_D1_X_MODIFY)
+#define bfin_write_MDMA_D1_X_MODIFY(val)       bfin_write16(MDMA_D1_X_MODIFY, val)
 #define bfin_read_MDMA_D1_Y_COUNT()            bfin_read16(MDMA_D1_Y_COUNT)
 #define bfin_write_MDMA_D1_Y_COUNT(val)                bfin_write16(MDMA_D1_Y_COUNT, val)
 #define bfin_read_MDMA_D1_Y_MODIFY()           bfin_read16(MDMA_D1_Y_MODIFY)
-#define bfin_write_MDMA_D1_Y_MODIFY(val)       bfin_write16(MDMA_D1_Y_MODIFY)
+#define bfin_write_MDMA_D1_Y_MODIFY(val)       bfin_write16(MDMA_D1_Y_MODIFY, val)
 #define bfin_read_MDMA_D1_CURR_DESC_PTR()      bfin_read32(MDMA_D1_CURR_DESC_PTR)
 #define bfin_write_MDMA_D1_CURR_DESC_PTR(val)  bfin_write32(MDMA_D1_CURR_DESC_PTR, val)
 #define bfin_read_MDMA_D1_CURR_ADDR()          bfin_read32(MDMA_D1_CURR_ADDR)
@@ -829,11 +825,11 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 #define bfin_read_MDMA_S1_X_COUNT()            bfin_read16(MDMA_S1_X_COUNT)
 #define bfin_write_MDMA_S1_X_COUNT(val)                bfin_write16(MDMA_S1_X_COUNT, val)
 #define bfin_read_MDMA_S1_X_MODIFY()           bfin_read16(MDMA_S1_X_MODIFY)
-#define bfin_write_MDMA_S1_X_MODIFY(val)       bfin_write16(MDMA_S1_X_MODIFY)
+#define bfin_write_MDMA_S1_X_MODIFY(val)       bfin_write16(MDMA_S1_X_MODIFY, val)
 #define bfin_read_MDMA_S1_Y_COUNT()            bfin_read16(MDMA_S1_Y_COUNT)
 #define bfin_write_MDMA_S1_Y_COUNT(val)                bfin_write16(MDMA_S1_Y_COUNT, val)
 #define bfin_read_MDMA_S1_Y_MODIFY()           bfin_read16(MDMA_S1_Y_MODIFY)
-#define bfin_write_MDMA_S1_Y_MODIFY(val)       bfin_write16(MDMA_S1_Y_MODIFY)
+#define bfin_write_MDMA_S1_Y_MODIFY(val)       bfin_write16(MDMA_S1_Y_MODIFY, val)
 #define bfin_read_MDMA_S1_CURR_DESC_PTR()      bfin_read32(MDMA_S1_CURR_DESC_PTR)
 #define bfin_write_MDMA_S1_CURR_DESC_PTR(val)  bfin_write32(MDMA_S1_CURR_DESC_PTR, val)
 #define bfin_read_MDMA_S1_CURR_ADDR()          bfin_read32(MDMA_S1_CURR_ADDR)
@@ -1246,23 +1242,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 /* DMA Channel 12 Registers */
 
 #define bfin_read_DMA12_NEXT_DESC_PTR()        bfin_read32(DMA12_NEXT_DESC_PTR)
-#define bfin_write_DMA12_NEXT_DESC_PTR(val)    bfin_write32(DMA12_NEXT_DESC_PTR)
+#define bfin_write_DMA12_NEXT_DESC_PTR(val)    bfin_write32(DMA12_NEXT_DESC_PTR, val)
 #define bfin_read_DMA12_START_ADDR()           bfin_read32(DMA12_START_ADDR)
-#define bfin_write_DMA12_START_ADDR(val)       bfin_write32(DMA12_START_ADDR)
+#define bfin_write_DMA12_START_ADDR(val)       bfin_write32(DMA12_START_ADDR, val)
 #define bfin_read_DMA12_CONFIG()               bfin_read16(DMA12_CONFIG)
 #define bfin_write_DMA12_CONFIG(val)           bfin_write16(DMA12_CONFIG, val)
 #define bfin_read_DMA12_X_COUNT()              bfin_read16(DMA12_X_COUNT)
 #define bfin_write_DMA12_X_COUNT(val)          bfin_write16(DMA12_X_COUNT, val)
 #define bfin_read_DMA12_X_MODIFY()             bfin_read16(DMA12_X_MODIFY)
-#define bfin_write_DMA12_X_MODIFY(val)                 bfin_write16(DMA12_X_MODIFY)
+#define bfin_write_DMA12_X_MODIFY(val)                 bfin_write16(DMA12_X_MODIFY, val)
 #define bfin_read_DMA12_Y_COUNT()              bfin_read16(DMA12_Y_COUNT)
 #define bfin_write_DMA12_Y_COUNT(val)          bfin_write16(DMA12_Y_COUNT, val)
 #define bfin_read_DMA12_Y_MODIFY()             bfin_read16(DMA12_Y_MODIFY)
-#define bfin_write_DMA12_Y_MODIFY(val)                 bfin_write16(DMA12_Y_MODIFY)
+#define bfin_write_DMA12_Y_MODIFY(val)                 bfin_write16(DMA12_Y_MODIFY, val)
 #define bfin_read_DMA12_CURR_DESC_PTR()        bfin_read32(DMA12_CURR_DESC_PTR)
-#define bfin_write_DMA12_CURR_DESC_PTR(val)    bfin_write32(DMA12_CURR_DESC_PTR)
+#define bfin_write_DMA12_CURR_DESC_PTR(val)    bfin_write32(DMA12_CURR_DESC_PTR, val)
 #define bfin_read_DMA12_CURR_ADDR()            bfin_read32(DMA12_CURR_ADDR)
-#define bfin_write_DMA12_CURR_ADDR(val)        bfin_write32(DMA12_CURR_ADDR)
+#define bfin_write_DMA12_CURR_ADDR(val)        bfin_write32(DMA12_CURR_ADDR, val)
 #define bfin_read_DMA12_IRQ_STATUS()           bfin_read16(DMA12_IRQ_STATUS)
 #define bfin_write_DMA12_IRQ_STATUS(val)       bfin_write16(DMA12_IRQ_STATUS, val)
 #define bfin_read_DMA12_PERIPHERAL_MAP()       bfin_read16(DMA12_PERIPHERAL_MAP)
@@ -1275,23 +1271,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 /* DMA Channel 13 Registers */
 
 #define bfin_read_DMA13_NEXT_DESC_PTR()        bfin_read32(DMA13_NEXT_DESC_PTR)
-#define bfin_write_DMA13_NEXT_DESC_PTR(val)    bfin_write32(DMA13_NEXT_DESC_PTR)
+#define bfin_write_DMA13_NEXT_DESC_PTR(val)    bfin_write32(DMA13_NEXT_DESC_PTR, val)
 #define bfin_read_DMA13_START_ADDR()           bfin_read32(DMA13_START_ADDR)
-#define bfin_write_DMA13_START_ADDR(val)       bfin_write32(DMA13_START_ADDR)
+#define bfin_write_DMA13_START_ADDR(val)       bfin_write32(DMA13_START_ADDR, val)
 #define bfin_read_DMA13_CONFIG()               bfin_read16(DMA13_CONFIG)
 #define bfin_write_DMA13_CONFIG(val)           bfin_write16(DMA13_CONFIG, val)
 #define bfin_read_DMA13_X_COUNT()              bfin_read16(DMA13_X_COUNT)
 #define bfin_write_DMA13_X_COUNT(val)          bfin_write16(DMA13_X_COUNT, val)
 #define bfin_read_DMA13_X_MODIFY()             bfin_read16(DMA13_X_MODIFY)
-#define bfin_write_DMA13_X_MODIFY(val)                 bfin_write16(DMA13_X_MODIFY)
+#define bfin_write_DMA13_X_MODIFY(val)                 bfin_write16(DMA13_X_MODIFY, val)
 #define bfin_read_DMA13_Y_COUNT()              bfin_read16(DMA13_Y_COUNT)
 #define bfin_write_DMA13_Y_COUNT(val)          bfin_write16(DMA13_Y_COUNT, val)
 #define bfin_read_DMA13_Y_MODIFY()             bfin_read16(DMA13_Y_MODIFY)
-#define bfin_write_DMA13_Y_MODIFY(val)                 bfin_write16(DMA13_Y_MODIFY)
+#define bfin_write_DMA13_Y_MODIFY(val)                 bfin_write16(DMA13_Y_MODIFY, val)
 #define bfin_read_DMA13_CURR_DESC_PTR()        bfin_read32(DMA13_CURR_DESC_PTR)
-#define bfin_write_DMA13_CURR_DESC_PTR(val)    bfin_write32(DMA13_CURR_DESC_PTR)
+#define bfin_write_DMA13_CURR_DESC_PTR(val)    bfin_write32(DMA13_CURR_DESC_PTR, val)
 #define bfin_read_DMA13_CURR_ADDR()            bfin_read32(DMA13_CURR_ADDR)
-#define bfin_write_DMA13_CURR_ADDR(val)        bfin_write32(DMA13_CURR_ADDR)
+#define bfin_write_DMA13_CURR_ADDR(val)        bfin_write32(DMA13_CURR_ADDR, val)
 #define bfin_read_DMA13_IRQ_STATUS()           bfin_read16(DMA13_IRQ_STATUS)
 #define bfin_write_DMA13_IRQ_STATUS(val)       bfin_write16(DMA13_IRQ_STATUS, val)
 #define bfin_read_DMA13_PERIPHERAL_MAP()       bfin_read16(DMA13_PERIPHERAL_MAP)
@@ -1304,23 +1300,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 /* DMA Channel 14 Registers */
 
 #define bfin_read_DMA14_NEXT_DESC_PTR()        bfin_read32(DMA14_NEXT_DESC_PTR)
-#define bfin_write_DMA14_NEXT_DESC_PTR(val)    bfin_write32(DMA14_NEXT_DESC_PTR)
+#define bfin_write_DMA14_NEXT_DESC_PTR(val)    bfin_write32(DMA14_NEXT_DESC_PTR, val)
 #define bfin_read_DMA14_START_ADDR()           bfin_read32(DMA14_START_ADDR)
-#define bfin_write_DMA14_START_ADDR(val)       bfin_write32(DMA14_START_ADDR)
+#define bfin_write_DMA14_START_ADDR(val)       bfin_write32(DMA14_START_ADDR, val)
 #define bfin_read_DMA14_CONFIG()               bfin_read16(DMA14_CONFIG)
 #define bfin_write_DMA14_CONFIG(val)           bfin_write16(DMA14_CONFIG, val)
 #define bfin_read_DMA14_X_COUNT()              bfin_read16(DMA14_X_COUNT)
 #define bfin_write_DMA14_X_COUNT(val)          bfin_write16(DMA14_X_COUNT, val)
 #define bfin_read_DMA14_X_MODIFY()             bfin_read16(DMA14_X_MODIFY)
-#define bfin_write_DMA14_X_MODIFY(val)                 bfin_write16(DMA14_X_MODIFY)
+#define bfin_write_DMA14_X_MODIFY(val)                 bfin_write16(DMA14_X_MODIFY, val)
 #define bfin_read_DMA14_Y_COUNT()              bfin_read16(DMA14_Y_COUNT)
 #define bfin_write_DMA14_Y_COUNT(val)          bfin_write16(DMA14_Y_COUNT, val)
 #define bfin_read_DMA14_Y_MODIFY()             bfin_read16(DMA14_Y_MODIFY)
-#define bfin_write_DMA14_Y_MODIFY(val)                 bfin_write16(DMA14_Y_MODIFY)
+#define bfin_write_DMA14_Y_MODIFY(val)                 bfin_write16(DMA14_Y_MODIFY, val)
 #define bfin_read_DMA14_CURR_DESC_PTR()        bfin_read32(DMA14_CURR_DESC_PTR)
-#define bfin_write_DMA14_CURR_DESC_PTR(val)    bfin_write32(DMA14_CURR_DESC_PTR)
+#define bfin_write_DMA14_CURR_DESC_PTR(val)    bfin_write32(DMA14_CURR_DESC_PTR, val)
 #define bfin_read_DMA14_CURR_ADDR()            bfin_read32(DMA14_CURR_ADDR)
-#define bfin_write_DMA14_CURR_ADDR(val)        bfin_write32(DMA14_CURR_ADDR)
+#define bfin_write_DMA14_CURR_ADDR(val)        bfin_write32(DMA14_CURR_ADDR, val)
 #define bfin_read_DMA14_IRQ_STATUS()           bfin_read16(DMA14_IRQ_STATUS)
 #define bfin_write_DMA14_IRQ_STATUS(val)       bfin_write16(DMA14_IRQ_STATUS, val)
 #define bfin_read_DMA14_PERIPHERAL_MAP()       bfin_read16(DMA14_PERIPHERAL_MAP)
@@ -1333,23 +1329,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 /* DMA Channel 15 Registers */
 
 #define bfin_read_DMA15_NEXT_DESC_PTR()        bfin_read32(DMA15_NEXT_DESC_PTR)
-#define bfin_write_DMA15_NEXT_DESC_PTR(val)    bfin_write32(DMA15_NEXT_DESC_PTR)
+#define bfin_write_DMA15_NEXT_DESC_PTR(val)    bfin_write32(DMA15_NEXT_DESC_PTR, val)
 #define bfin_read_DMA15_START_ADDR()           bfin_read32(DMA15_START_ADDR)
-#define bfin_write_DMA15_START_ADDR(val)       bfin_write32(DMA15_START_ADDR)
+#define bfin_write_DMA15_START_ADDR(val)       bfin_write32(DMA15_START_ADDR, val)
 #define bfin_read_DMA15_CONFIG()               bfin_read16(DMA15_CONFIG)
 #define bfin_write_DMA15_CONFIG(val)           bfin_write16(DMA15_CONFIG, val)
 #define bfin_read_DMA15_X_COUNT()              bfin_read16(DMA15_X_COUNT)
 #define bfin_write_DMA15_X_COUNT(val)          bfin_write16(DMA15_X_COUNT, val)
 #define bfin_read_DMA15_X_MODIFY()             bfin_read16(DMA15_X_MODIFY)
-#define bfin_write_DMA15_X_MODIFY(val)                 bfin_write16(DMA15_X_MODIFY)
+#define bfin_write_DMA15_X_MODIFY(val)                 bfin_write16(DMA15_X_MODIFY, val)
 #define bfin_read_DMA15_Y_COUNT()              bfin_read16(DMA15_Y_COUNT)
 #define bfin_write_DMA15_Y_COUNT(val)          bfin_write16(DMA15_Y_COUNT, val)
 #define bfin_read_DMA15_Y_MODIFY()             bfin_read16(DMA15_Y_MODIFY)
-#define bfin_write_DMA15_Y_MODIFY(val)                 bfin_write16(DMA15_Y_MODIFY)
+#define bfin_write_DMA15_Y_MODIFY(val)                 bfin_write16(DMA15_Y_MODIFY, val)
 #define bfin_read_DMA15_CURR_DESC_PTR()        bfin_read32(DMA15_CURR_DESC_PTR)
-#define bfin_write_DMA15_CURR_DESC_PTR(val)    bfin_write32(DMA15_CURR_DESC_PTR)
+#define bfin_write_DMA15_CURR_DESC_PTR(val)    bfin_write32(DMA15_CURR_DESC_PTR, val)
 #define bfin_read_DMA15_CURR_ADDR()            bfin_read32(DMA15_CURR_ADDR)
-#define bfin_write_DMA15_CURR_ADDR(val)        bfin_write32(DMA15_CURR_ADDR)
+#define bfin_write_DMA15_CURR_ADDR(val)        bfin_write32(DMA15_CURR_ADDR, val)
 #define bfin_read_DMA15_IRQ_STATUS()           bfin_read16(DMA15_IRQ_STATUS)
 #define bfin_write_DMA15_IRQ_STATUS(val)       bfin_write16(DMA15_IRQ_STATUS, val)
 #define bfin_read_DMA15_PERIPHERAL_MAP()       bfin_read16(DMA15_PERIPHERAL_MAP)
@@ -1362,23 +1358,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 /* DMA Channel 16 Registers */
 
 #define bfin_read_DMA16_NEXT_DESC_PTR()        bfin_read32(DMA16_NEXT_DESC_PTR)
-#define bfin_write_DMA16_NEXT_DESC_PTR(val)    bfin_write32(DMA16_NEXT_DESC_PTR)
+#define bfin_write_DMA16_NEXT_DESC_PTR(val)    bfin_write32(DMA16_NEXT_DESC_PTR, val)
 #define bfin_read_DMA16_START_ADDR()           bfin_read32(DMA16_START_ADDR)
-#define bfin_write_DMA16_START_ADDR(val)       bfin_write32(DMA16_START_ADDR)
+#define bfin_write_DMA16_START_ADDR(val)       bfin_write32(DMA16_START_ADDR, val)
 #define bfin_read_DMA16_CONFIG()               bfin_read16(DMA16_CONFIG)
 #define bfin_write_DMA16_CONFIG(val)           bfin_write16(DMA16_CONFIG, val)
 #define bfin_read_DMA16_X_COUNT()              bfin_read16(DMA16_X_COUNT)
 #define bfin_write_DMA16_X_COUNT(val)          bfin_write16(DMA16_X_COUNT, val)
 #define bfin_read_DMA16_X_MODIFY()             bfin_read16(DMA16_X_MODIFY)
-#define bfin_write_DMA16_X_MODIFY(val)                 bfin_write16(DMA16_X_MODIFY)
+#define bfin_write_DMA16_X_MODIFY(val)                 bfin_write16(DMA16_X_MODIFY, val)
 #define bfin_read_DMA16_Y_COUNT()              bfin_read16(DMA16_Y_COUNT)
 #define bfin_write_DMA16_Y_COUNT(val)          bfin_write16(DMA16_Y_COUNT, val)
 #define bfin_read_DMA16_Y_MODIFY()             bfin_read16(DMA16_Y_MODIFY)
-#define bfin_write_DMA16_Y_MODIFY(val)                 bfin_write16(DMA16_Y_MODIFY)
+#define bfin_write_DMA16_Y_MODIFY(val)                 bfin_write16(DMA16_Y_MODIFY, val)
 #define bfin_read_DMA16_CURR_DESC_PTR()        bfin_read32(DMA16_CURR_DESC_PTR)
-#define bfin_write_DMA16_CURR_DESC_PTR(val)    bfin_write32(DMA16_CURR_DESC_PTR)
+#define bfin_write_DMA16_CURR_DESC_PTR(val)    bfin_write32(DMA16_CURR_DESC_PTR, val)
 #define bfin_read_DMA16_CURR_ADDR()            bfin_read32(DMA16_CURR_ADDR)
-#define bfin_write_DMA16_CURR_ADDR(val)        bfin_write32(DMA16_CURR_ADDR)
+#define bfin_write_DMA16_CURR_ADDR(val)        bfin_write32(DMA16_CURR_ADDR, val)
 #define bfin_read_DMA16_IRQ_STATUS()           bfin_read16(DMA16_IRQ_STATUS)
 #define bfin_write_DMA16_IRQ_STATUS(val)       bfin_write16(DMA16_IRQ_STATUS, val)
 #define bfin_read_DMA16_PERIPHERAL_MAP()       bfin_read16(DMA16_PERIPHERAL_MAP)
@@ -1391,23 +1387,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 /* DMA Channel 17 Registers */
 
 #define bfin_read_DMA17_NEXT_DESC_PTR()        bfin_read32(DMA17_NEXT_DESC_PTR)
-#define bfin_write_DMA17_NEXT_DESC_PTR(val)    bfin_write32(DMA17_NEXT_DESC_PTR)
+#define bfin_write_DMA17_NEXT_DESC_PTR(val)    bfin_write32(DMA17_NEXT_DESC_PTR, val)
 #define bfin_read_DMA17_START_ADDR()           bfin_read32(DMA17_START_ADDR)
-#define bfin_write_DMA17_START_ADDR(val)       bfin_write32(DMA17_START_ADDR)
+#define bfin_write_DMA17_START_ADDR(val)       bfin_write32(DMA17_START_ADDR, val)
 #define bfin_read_DMA17_CONFIG()               bfin_read16(DMA17_CONFIG)
 #define bfin_write_DMA17_CONFIG(val)           bfin_write16(DMA17_CONFIG, val)
 #define bfin_read_DMA17_X_COUNT()              bfin_read16(DMA17_X_COUNT)
 #define bfin_write_DMA17_X_COUNT(val)          bfin_write16(DMA17_X_COUNT, val)
 #define bfin_read_DMA17_X_MODIFY()             bfin_read16(DMA17_X_MODIFY)
-#define bfin_write_DMA17_X_MODIFY(val)                 bfin_write16(DMA17_X_MODIFY)
+#define bfin_write_DMA17_X_MODIFY(val)                 bfin_write16(DMA17_X_MODIFY, val)
 #define bfin_read_DMA17_Y_COUNT()              bfin_read16(DMA17_Y_COUNT)
 #define bfin_write_DMA17_Y_COUNT(val)          bfin_write16(DMA17_Y_COUNT, val)
 #define bfin_read_DMA17_Y_MODIFY()             bfin_read16(DMA17_Y_MODIFY)
-#define bfin_write_DMA17_Y_MODIFY(val)                 bfin_write16(DMA17_Y_MODIFY)
+#define bfin_write_DMA17_Y_MODIFY(val)                 bfin_write16(DMA17_Y_MODIFY, val)
 #define bfin_read_DMA17_CURR_DESC_PTR()        bfin_read32(DMA17_CURR_DESC_PTR)
-#define bfin_write_DMA17_CURR_DESC_PTR(val)    bfin_write32(DMA17_CURR_DESC_PTR)
+#define bfin_write_DMA17_CURR_DESC_PTR(val)    bfin_write32(DMA17_CURR_DESC_PTR, val)
 #define bfin_read_DMA17_CURR_ADDR()            bfin_read32(DMA17_CURR_ADDR)
-#define bfin_write_DMA17_CURR_ADDR(val)        bfin_write32(DMA17_CURR_ADDR)
+#define bfin_write_DMA17_CURR_ADDR(val)        bfin_write32(DMA17_CURR_ADDR, val)
 #define bfin_read_DMA17_IRQ_STATUS()           bfin_read16(DMA17_IRQ_STATUS)
 #define bfin_write_DMA17_IRQ_STATUS(val)       bfin_write16(DMA17_IRQ_STATUS, val)
 #define bfin_read_DMA17_PERIPHERAL_MAP()       bfin_read16(DMA17_PERIPHERAL_MAP)
@@ -1420,23 +1416,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 /* DMA Channel 18 Registers */
 
 #define bfin_read_DMA18_NEXT_DESC_PTR()        bfin_read32(DMA18_NEXT_DESC_PTR)
-#define bfin_write_DMA18_NEXT_DESC_PTR(val)    bfin_write32(DMA18_NEXT_DESC_PTR)
+#define bfin_write_DMA18_NEXT_DESC_PTR(val)    bfin_write32(DMA18_NEXT_DESC_PTR, val)
 #define bfin_read_DMA18_START_ADDR()           bfin_read32(DMA18_START_ADDR)
-#define bfin_write_DMA18_START_ADDR(val)       bfin_write32(DMA18_START_ADDR)
+#define bfin_write_DMA18_START_ADDR(val)       bfin_write32(DMA18_START_ADDR, val)
 #define bfin_read_DMA18_CONFIG()               bfin_read16(DMA18_CONFIG)
 #define bfin_write_DMA18_CONFIG(val)           bfin_write16(DMA18_CONFIG, val)
 #define bfin_read_DMA18_X_COUNT()              bfin_read16(DMA18_X_COUNT)
 #define bfin_write_DMA18_X_COUNT(val)          bfin_write16(DMA18_X_COUNT, val)
 #define bfin_read_DMA18_X_MODIFY()             bfin_read16(DMA18_X_MODIFY)
-#define bfin_write_DMA18_X_MODIFY(val)                 bfin_write16(DMA18_X_MODIFY)
+#define bfin_write_DMA18_X_MODIFY(val)                 bfin_write16(DMA18_X_MODIFY, val)
 #define bfin_read_DMA18_Y_COUNT()              bfin_read16(DMA18_Y_COUNT)
 #define bfin_write_DMA18_Y_COUNT(val)          bfin_write16(DMA18_Y_COUNT, val)
 #define bfin_read_DMA18_Y_MODIFY()             bfin_read16(DMA18_Y_MODIFY)
-#define bfin_write_DMA18_Y_MODIFY(val)                 bfin_write16(DMA18_Y_MODIFY)
+#define bfin_write_DMA18_Y_MODIFY(val)                 bfin_write16(DMA18_Y_MODIFY, val)
 #define bfin_read_DMA18_CURR_DESC_PTR()        bfin_read32(DMA18_CURR_DESC_PTR)
-#define bfin_write_DMA18_CURR_DESC_PTR(val)    bfin_write32(DMA18_CURR_DESC_PTR)
+#define bfin_write_DMA18_CURR_DESC_PTR(val)    bfin_write32(DMA18_CURR_DESC_PTR, val)
 #define bfin_read_DMA18_CURR_ADDR()            bfin_read32(DMA18_CURR_ADDR)
-#define bfin_write_DMA18_CURR_ADDR(val)        bfin_write32(DMA18_CURR_ADDR)
+#define bfin_write_DMA18_CURR_ADDR(val)        bfin_write32(DMA18_CURR_ADDR, val)
 #define bfin_read_DMA18_IRQ_STATUS()           bfin_read16(DMA18_IRQ_STATUS)
 #define bfin_write_DMA18_IRQ_STATUS(val)       bfin_write16(DMA18_IRQ_STATUS, val)
 #define bfin_read_DMA18_PERIPHERAL_MAP()       bfin_read16(DMA18_PERIPHERAL_MAP)
@@ -1449,23 +1445,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 /* DMA Channel 19 Registers */
 
 #define bfin_read_DMA19_NEXT_DESC_PTR()        bfin_read32(DMA19_NEXT_DESC_PTR)
-#define bfin_write_DMA19_NEXT_DESC_PTR(val)    bfin_write32(DMA19_NEXT_DESC_PTR)
+#define bfin_write_DMA19_NEXT_DESC_PTR(val)    bfin_write32(DMA19_NEXT_DESC_PTR, val)
 #define bfin_read_DMA19_START_ADDR()           bfin_read32(DMA19_START_ADDR)
-#define bfin_write_DMA19_START_ADDR(val)       bfin_write32(DMA19_START_ADDR)
+#define bfin_write_DMA19_START_ADDR(val)       bfin_write32(DMA19_START_ADDR, val)
 #define bfin_read_DMA19_CONFIG()               bfin_read16(DMA19_CONFIG)
 #define bfin_write_DMA19_CONFIG(val)           bfin_write16(DMA19_CONFIG, val)
 #define bfin_read_DMA19_X_COUNT()              bfin_read16(DMA19_X_COUNT)
 #define bfin_write_DMA19_X_COUNT(val)          bfin_write16(DMA19_X_COUNT, val)
 #define bfin_read_DMA19_X_MODIFY()             bfin_read16(DMA19_X_MODIFY)
-#define bfin_write_DMA19_X_MODIFY(val)                 bfin_write16(DMA19_X_MODIFY)
+#define bfin_write_DMA19_X_MODIFY(val)                 bfin_write16(DMA19_X_MODIFY, val)
 #define bfin_read_DMA19_Y_COUNT()              bfin_read16(DMA19_Y_COUNT)
 #define bfin_write_DMA19_Y_COUNT(val)          bfin_write16(DMA19_Y_COUNT, val)
 #define bfin_read_DMA19_Y_MODIFY()             bfin_read16(DMA19_Y_MODIFY)
-#define bfin_write_DMA19_Y_MODIFY(val)                 bfin_write16(DMA19_Y_MODIFY)
+#define bfin_write_DMA19_Y_MODIFY(val)                 bfin_write16(DMA19_Y_MODIFY, val)
 #define bfin_read_DMA19_CURR_DESC_PTR()        bfin_read32(DMA19_CURR_DESC_PTR)
-#define bfin_write_DMA19_CURR_DESC_PTR(val)    bfin_write32(DMA19_CURR_DESC_PTR)
+#define bfin_write_DMA19_CURR_DESC_PTR(val)    bfin_write32(DMA19_CURR_DESC_PTR, val)
 #define bfin_read_DMA19_CURR_ADDR()            bfin_read32(DMA19_CURR_ADDR)
-#define bfin_write_DMA19_CURR_ADDR(val)        bfin_write32(DMA19_CURR_ADDR)
+#define bfin_write_DMA19_CURR_ADDR(val)        bfin_write32(DMA19_CURR_ADDR, val)
 #define bfin_read_DMA19_IRQ_STATUS()           bfin_read16(DMA19_IRQ_STATUS)
 #define bfin_write_DMA19_IRQ_STATUS(val)       bfin_write16(DMA19_IRQ_STATUS, val)
 #define bfin_read_DMA19_PERIPHERAL_MAP()       bfin_read16(DMA19_PERIPHERAL_MAP)
@@ -1478,23 +1474,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 /* DMA Channel 20 Registers */
 
 #define bfin_read_DMA20_NEXT_DESC_PTR()        bfin_read32(DMA20_NEXT_DESC_PTR)
-#define bfin_write_DMA20_NEXT_DESC_PTR(val)    bfin_write32(DMA20_NEXT_DESC_PTR)
+#define bfin_write_DMA20_NEXT_DESC_PTR(val)    bfin_write32(DMA20_NEXT_DESC_PTR, val)
 #define bfin_read_DMA20_START_ADDR()           bfin_read32(DMA20_START_ADDR)
-#define bfin_write_DMA20_START_ADDR(val)       bfin_write32(DMA20_START_ADDR)
+#define bfin_write_DMA20_START_ADDR(val)       bfin_write32(DMA20_START_ADDR, val)
 #define bfin_read_DMA20_CONFIG()               bfin_read16(DMA20_CONFIG)
 #define bfin_write_DMA20_CONFIG(val)           bfin_write16(DMA20_CONFIG, val)
 #define bfin_read_DMA20_X_COUNT()              bfin_read16(DMA20_X_COUNT)
 #define bfin_write_DMA20_X_COUNT(val)          bfin_write16(DMA20_X_COUNT, val)
 #define bfin_read_DMA20_X_MODIFY()             bfin_read16(DMA20_X_MODIFY)
-#define bfin_write_DMA20_X_MODIFY(val)                 bfin_write16(DMA20_X_MODIFY)
+#define bfin_write_DMA20_X_MODIFY(val)                 bfin_write16(DMA20_X_MODIFY, val)
 #define bfin_read_DMA20_Y_COUNT()              bfin_read16(DMA20_Y_COUNT)
 #define bfin_write_DMA20_Y_COUNT(val)          bfin_write16(DMA20_Y_COUNT, val)
 #define bfin_read_DMA20_Y_MODIFY()             bfin_read16(DMA20_Y_MODIFY)
-#define bfin_write_DMA20_Y_MODIFY(val)                 bfin_write16(DMA20_Y_MODIFY)
+#define bfin_write_DMA20_Y_MODIFY(val)                 bfin_write16(DMA20_Y_MODIFY, val)
 #define bfin_read_DMA20_CURR_DESC_PTR()        bfin_read32(DMA20_CURR_DESC_PTR)
-#define bfin_write_DMA20_CURR_DESC_PTR(val)    bfin_write32(DMA20_CURR_DESC_PTR)
+#define bfin_write_DMA20_CURR_DESC_PTR(val)    bfin_write32(DMA20_CURR_DESC_PTR, val)
 #define bfin_read_DMA20_CURR_ADDR()            bfin_read32(DMA20_CURR_ADDR)
-#define bfin_write_DMA20_CURR_ADDR(val)        bfin_write32(DMA20_CURR_ADDR)
+#define bfin_write_DMA20_CURR_ADDR(val)        bfin_write32(DMA20_CURR_ADDR, val)
 #define bfin_read_DMA20_IRQ_STATUS()           bfin_read16(DMA20_IRQ_STATUS)
 #define bfin_write_DMA20_IRQ_STATUS(val)       bfin_write16(DMA20_IRQ_STATUS, val)
 #define bfin_read_DMA20_PERIPHERAL_MAP()       bfin_read16(DMA20_PERIPHERAL_MAP)
@@ -1507,23 +1503,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 /* DMA Channel 21 Registers */
 
 #define bfin_read_DMA21_NEXT_DESC_PTR()        bfin_read32(DMA21_NEXT_DESC_PTR)
-#define bfin_write_DMA21_NEXT_DESC_PTR(val)    bfin_write32(DMA21_NEXT_DESC_PTR)
+#define bfin_write_DMA21_NEXT_DESC_PTR(val)    bfin_write32(DMA21_NEXT_DESC_PTR, val)
 #define bfin_read_DMA21_START_ADDR()           bfin_read32(DMA21_START_ADDR)
-#define bfin_write_DMA21_START_ADDR(val)       bfin_write32(DMA21_START_ADDR)
+#define bfin_write_DMA21_START_ADDR(val)       bfin_write32(DMA21_START_ADDR, val)
 #define bfin_read_DMA21_CONFIG()               bfin_read16(DMA21_CONFIG)
 #define bfin_write_DMA21_CONFIG(val)           bfin_write16(DMA21_CONFIG, val)
 #define bfin_read_DMA21_X_COUNT()              bfin_read16(DMA21_X_COUNT)
 #define bfin_write_DMA21_X_COUNT(val)          bfin_write16(DMA21_X_COUNT, val)
 #define bfin_read_DMA21_X_MODIFY()             bfin_read16(DMA21_X_MODIFY)
-#define bfin_write_DMA21_X_MODIFY(val)                 bfin_write16(DMA21_X_MODIFY)
+#define bfin_write_DMA21_X_MODIFY(val)                 bfin_write16(DMA21_X_MODIFY, val)
 #define bfin_read_DMA21_Y_COUNT()              bfin_read16(DMA21_Y_COUNT)
 #define bfin_write_DMA21_Y_COUNT(val)          bfin_write16(DMA21_Y_COUNT, val)
 #define bfin_read_DMA21_Y_MODIFY()             bfin_read16(DMA21_Y_MODIFY)
-#define bfin_write_DMA21_Y_MODIFY(val)                 bfin_write16(DMA21_Y_MODIFY)
+#define bfin_write_DMA21_Y_MODIFY(val)                 bfin_write16(DMA21_Y_MODIFY, val)
 #define bfin_read_DMA21_CURR_DESC_PTR()        bfin_read32(DMA21_CURR_DESC_PTR)
-#define bfin_write_DMA21_CURR_DESC_PTR(val)    bfin_write32(DMA21_CURR_DESC_PTR)
+#define bfin_write_DMA21_CURR_DESC_PTR(val)    bfin_write32(DMA21_CURR_DESC_PTR, val)
 #define bfin_read_DMA21_CURR_ADDR()            bfin_read32(DMA21_CURR_ADDR)
-#define bfin_write_DMA21_CURR_ADDR(val)        bfin_write32(DMA21_CURR_ADDR)
+#define bfin_write_DMA21_CURR_ADDR(val)        bfin_write32(DMA21_CURR_ADDR, val)
 #define bfin_read_DMA21_IRQ_STATUS()           bfin_read16(DMA21_IRQ_STATUS)
 #define bfin_write_DMA21_IRQ_STATUS(val)       bfin_write16(DMA21_IRQ_STATUS, val)
 #define bfin_read_DMA21_PERIPHERAL_MAP()       bfin_read16(DMA21_PERIPHERAL_MAP)
@@ -1536,23 +1532,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 /* DMA Channel 22 Registers */
 
 #define bfin_read_DMA22_NEXT_DESC_PTR()        bfin_read32(DMA22_NEXT_DESC_PTR)
-#define bfin_write_DMA22_NEXT_DESC_PTR(val)    bfin_write32(DMA22_NEXT_DESC_PTR)
+#define bfin_write_DMA22_NEXT_DESC_PTR(val)    bfin_write32(DMA22_NEXT_DESC_PTR, val)
 #define bfin_read_DMA22_START_ADDR()           bfin_read32(DMA22_START_ADDR)
-#define bfin_write_DMA22_START_ADDR(val)       bfin_write32(DMA22_START_ADDR)
+#define bfin_write_DMA22_START_ADDR(val)       bfin_write32(DMA22_START_ADDR, val)
 #define bfin_read_DMA22_CONFIG()               bfin_read16(DMA22_CONFIG)
 #define bfin_write_DMA22_CONFIG(val)           bfin_write16(DMA22_CONFIG, val)
 #define bfin_read_DMA22_X_COUNT()              bfin_read16(DMA22_X_COUNT)
 #define bfin_write_DMA22_X_COUNT(val)          bfin_write16(DMA22_X_COUNT, val)
 #define bfin_read_DMA22_X_MODIFY()             bfin_read16(DMA22_X_MODIFY)
-#define bfin_write_DMA22_X_MODIFY(val)                 bfin_write16(DMA22_X_MODIFY)
+#define bfin_write_DMA22_X_MODIFY(val)                 bfin_write16(DMA22_X_MODIFY, val)
 #define bfin_read_DMA22_Y_COUNT()              bfin_read16(DMA22_Y_COUNT)
 #define bfin_write_DMA22_Y_COUNT(val)          bfin_write16(DMA22_Y_COUNT, val)
 #define bfin_read_DMA22_Y_MODIFY()             bfin_read16(DMA22_Y_MODIFY)
-#define bfin_write_DMA22_Y_MODIFY(val)                 bfin_write16(DMA22_Y_MODIFY)
+#define bfin_write_DMA22_Y_MODIFY(val)                 bfin_write16(DMA22_Y_MODIFY, val)
 #define bfin_read_DMA22_CURR_DESC_PTR()        bfin_read32(DMA22_CURR_DESC_PTR)
-#define bfin_write_DMA22_CURR_DESC_PTR(val)    bfin_write32(DMA22_CURR_DESC_PTR)
+#define bfin_write_DMA22_CURR_DESC_PTR(val)    bfin_write32(DMA22_CURR_DESC_PTR, val)
 #define bfin_read_DMA22_CURR_ADDR()            bfin_read32(DMA22_CURR_ADDR)
-#define bfin_write_DMA22_CURR_ADDR(val)        bfin_write32(DMA22_CURR_ADDR)
+#define bfin_write_DMA22_CURR_ADDR(val)        bfin_write32(DMA22_CURR_ADDR, val)
 #define bfin_read_DMA22_IRQ_STATUS()           bfin_read16(DMA22_IRQ_STATUS)
 #define bfin_write_DMA22_IRQ_STATUS(val)       bfin_write16(DMA22_IRQ_STATUS, val)
 #define bfin_read_DMA22_PERIPHERAL_MAP()       bfin_read16(DMA22_PERIPHERAL_MAP)
@@ -1565,23 +1561,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 /* DMA Channel 23 Registers */
 
 #define bfin_read_DMA23_NEXT_DESC_PTR()                bfin_read32(DMA23_NEXT_DESC_PTR)
-#define bfin_write_DMA23_NEXT_DESC_PTR(val)            bfin_write32(DMA23_NEXT_DESC_PTR)
+#define bfin_write_DMA23_NEXT_DESC_PTR(val)            bfin_write32(DMA23_NEXT_DESC_PTR, val)
 #define bfin_read_DMA23_START_ADDR()                   bfin_read32(DMA23_START_ADDR)
-#define bfin_write_DMA23_START_ADDR(val)               bfin_write32(DMA23_START_ADDR)
+#define bfin_write_DMA23_START_ADDR(val)               bfin_write32(DMA23_START_ADDR, val)
 #define bfin_read_DMA23_CONFIG()                       bfin_read16(DMA23_CONFIG)
 #define bfin_write_DMA23_CONFIG(val)                   bfin_write16(DMA23_CONFIG, val)
 #define bfin_read_DMA23_X_COUNT()                      bfin_read16(DMA23_X_COUNT)
 #define bfin_write_DMA23_X_COUNT(val)                  bfin_write16(DMA23_X_COUNT, val)
 #define bfin_read_DMA23_X_MODIFY()                     bfin_read16(DMA23_X_MODIFY)
-#define bfin_write_DMA23_X_MODIFY(val)                         bfin_write16(DMA23_X_MODIFY)
+#define bfin_write_DMA23_X_MODIFY(val)                         bfin_write16(DMA23_X_MODIFY, val)
 #define bfin_read_DMA23_Y_COUNT()                      bfin_read16(DMA23_Y_COUNT)
 #define bfin_write_DMA23_Y_COUNT(val)                  bfin_write16(DMA23_Y_COUNT, val)
 #define bfin_read_DMA23_Y_MODIFY()                     bfin_read16(DMA23_Y_MODIFY)
-#define bfin_write_DMA23_Y_MODIFY(val)                         bfin_write16(DMA23_Y_MODIFY)
+#define bfin_write_DMA23_Y_MODIFY(val)                         bfin_write16(DMA23_Y_MODIFY, val)
 #define bfin_read_DMA23_CURR_DESC_PTR()                bfin_read32(DMA23_CURR_DESC_PTR)
-#define bfin_write_DMA23_CURR_DESC_PTR(val)            bfin_write32(DMA23_CURR_DESC_PTR)
+#define bfin_write_DMA23_CURR_DESC_PTR(val)            bfin_write32(DMA23_CURR_DESC_PTR, val)
 #define bfin_read_DMA23_CURR_ADDR()                    bfin_read32(DMA23_CURR_ADDR)
-#define bfin_write_DMA23_CURR_ADDR(val)                bfin_write32(DMA23_CURR_ADDR)
+#define bfin_write_DMA23_CURR_ADDR(val)                bfin_write32(DMA23_CURR_ADDR, val)
 #define bfin_read_DMA23_IRQ_STATUS()                   bfin_read16(DMA23_IRQ_STATUS)
 #define bfin_write_DMA23_IRQ_STATUS(val)               bfin_write16(DMA23_IRQ_STATUS, val)
 #define bfin_read_DMA23_PERIPHERAL_MAP()               bfin_read16(DMA23_PERIPHERAL_MAP)
@@ -1594,23 +1590,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 /* MDMA Stream 2 Registers */
 
 #define bfin_read_MDMA_D2_NEXT_DESC_PTR()              bfin_read32(MDMA_D2_NEXT_DESC_PTR)
-#define bfin_write_MDMA_D2_NEXT_DESC_PTR(val)          bfin_write32(MDMA_D2_NEXT_DESC_PTR)
+#define bfin_write_MDMA_D2_NEXT_DESC_PTR(val)          bfin_write32(MDMA_D2_NEXT_DESC_PTR, val)
 #define bfin_read_MDMA_D2_START_ADDR()                         bfin_read32(MDMA_D2_START_ADDR)
-#define bfin_write_MDMA_D2_START_ADDR(val)             bfin_write32(MDMA_D2_START_ADDR)
+#define bfin_write_MDMA_D2_START_ADDR(val)             bfin_write32(MDMA_D2_START_ADDR, val)
 #define bfin_read_MDMA_D2_CONFIG()                     bfin_read16(MDMA_D2_CONFIG)
 #define bfin_write_MDMA_D2_CONFIG(val)                 bfin_write16(MDMA_D2_CONFIG, val)
 #define bfin_read_MDMA_D2_X_COUNT()                    bfin_read16(MDMA_D2_X_COUNT)
 #define bfin_write_MDMA_D2_X_COUNT(val)                        bfin_write16(MDMA_D2_X_COUNT, val)
 #define bfin_read_MDMA_D2_X_MODIFY()                   bfin_read16(MDMA_D2_X_MODIFY)
-#define bfin_write_MDMA_D2_X_MODIFY(val)               bfin_write16(MDMA_D2_X_MODIFY)
+#define bfin_write_MDMA_D2_X_MODIFY(val)               bfin_write16(MDMA_D2_X_MODIFY, val)
 #define bfin_read_MDMA_D2_Y_COUNT()                    bfin_read16(MDMA_D2_Y_COUNT)
 #define bfin_write_MDMA_D2_Y_COUNT(val)                        bfin_write16(MDMA_D2_Y_COUNT, val)
 #define bfin_read_MDMA_D2_Y_MODIFY()                   bfin_read16(MDMA_D2_Y_MODIFY)
-#define bfin_write_MDMA_D2_Y_MODIFY(val)               bfin_write16(MDMA_D2_Y_MODIFY)
+#define bfin_write_MDMA_D2_Y_MODIFY(val)               bfin_write16(MDMA_D2_Y_MODIFY, val)
 #define bfin_read_MDMA_D2_CURR_DESC_PTR()              bfin_read32(MDMA_D2_CURR_DESC_PTR)
-#define bfin_write_MDMA_D2_CURR_DESC_PTR(val)          bfin_write32(MDMA_D2_CURR_DESC_PTR)
+#define bfin_write_MDMA_D2_CURR_DESC_PTR(val)          bfin_write32(MDMA_D2_CURR_DESC_PTR, val)
 #define bfin_read_MDMA_D2_CURR_ADDR()                  bfin_read32(MDMA_D2_CURR_ADDR)
-#define bfin_write_MDMA_D2_CURR_ADDR(val)              bfin_write32(MDMA_D2_CURR_ADDR)
+#define bfin_write_MDMA_D2_CURR_ADDR(val)              bfin_write32(MDMA_D2_CURR_ADDR, val)
 #define bfin_read_MDMA_D2_IRQ_STATUS()                 bfin_read16(MDMA_D2_IRQ_STATUS)
 #define bfin_write_MDMA_D2_IRQ_STATUS(val)             bfin_write16(MDMA_D2_IRQ_STATUS, val)
 #define bfin_read_MDMA_D2_PERIPHERAL_MAP()             bfin_read16(MDMA_D2_PERIPHERAL_MAP)
@@ -1620,23 +1616,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 #define bfin_read_MDMA_D2_CURR_Y_COUNT()               bfin_read16(MDMA_D2_CURR_Y_COUNT)
 #define bfin_write_MDMA_D2_CURR_Y_COUNT(val)           bfin_write16(MDMA_D2_CURR_Y_COUNT, val)
 #define bfin_read_MDMA_S2_NEXT_DESC_PTR()              bfin_read32(MDMA_S2_NEXT_DESC_PTR)
-#define bfin_write_MDMA_S2_NEXT_DESC_PTR(val)          bfin_write32(MDMA_S2_NEXT_DESC_PTR)
+#define bfin_write_MDMA_S2_NEXT_DESC_PTR(val)          bfin_write32(MDMA_S2_NEXT_DESC_PTR, val)
 #define bfin_read_MDMA_S2_START_ADDR()                         bfin_read32(MDMA_S2_START_ADDR)
-#define bfin_write_MDMA_S2_START_ADDR(val)             bfin_write32(MDMA_S2_START_ADDR)
+#define bfin_write_MDMA_S2_START_ADDR(val)             bfin_write32(MDMA_S2_START_ADDR, val)
 #define bfin_read_MDMA_S2_CONFIG()                     bfin_read16(MDMA_S2_CONFIG)
 #define bfin_write_MDMA_S2_CONFIG(val)                 bfin_write16(MDMA_S2_CONFIG, val)
 #define bfin_read_MDMA_S2_X_COUNT()                    bfin_read16(MDMA_S2_X_COUNT)
 #define bfin_write_MDMA_S2_X_COUNT(val)                        bfin_write16(MDMA_S2_X_COUNT, val)
 #define bfin_read_MDMA_S2_X_MODIFY()                   bfin_read16(MDMA_S2_X_MODIFY)
-#define bfin_write_MDMA_S2_X_MODIFY(val)               bfin_write16(MDMA_S2_X_MODIFY)
+#define bfin_write_MDMA_S2_X_MODIFY(val)               bfin_write16(MDMA_S2_X_MODIFY, val)
 #define bfin_read_MDMA_S2_Y_COUNT()                    bfin_read16(MDMA_S2_Y_COUNT)
 #define bfin_write_MDMA_S2_Y_COUNT(val)                        bfin_write16(MDMA_S2_Y_COUNT, val)
 #define bfin_read_MDMA_S2_Y_MODIFY()                   bfin_read16(MDMA_S2_Y_MODIFY)
-#define bfin_write_MDMA_S2_Y_MODIFY(val)               bfin_write16(MDMA_S2_Y_MODIFY)
+#define bfin_write_MDMA_S2_Y_MODIFY(val)               bfin_write16(MDMA_S2_Y_MODIFY, val)
 #define bfin_read_MDMA_S2_CURR_DESC_PTR()              bfin_read32(MDMA_S2_CURR_DESC_PTR)
-#define bfin_write_MDMA_S2_CURR_DESC_PTR(val)          bfin_write32(MDMA_S2_CURR_DESC_PTR)
+#define bfin_write_MDMA_S2_CURR_DESC_PTR(val)          bfin_write32(MDMA_S2_CURR_DESC_PTR, val)
 #define bfin_read_MDMA_S2_CURR_ADDR()                  bfin_read32(MDMA_S2_CURR_ADDR)
-#define bfin_write_MDMA_S2_CURR_ADDR(val)              bfin_write32(MDMA_S2_CURR_ADDR)
+#define bfin_write_MDMA_S2_CURR_ADDR(val)              bfin_write32(MDMA_S2_CURR_ADDR, val)
 #define bfin_read_MDMA_S2_IRQ_STATUS()                 bfin_read16(MDMA_S2_IRQ_STATUS)
 #define bfin_write_MDMA_S2_IRQ_STATUS(val)             bfin_write16(MDMA_S2_IRQ_STATUS, val)
 #define bfin_read_MDMA_S2_PERIPHERAL_MAP()             bfin_read16(MDMA_S2_PERIPHERAL_MAP)
@@ -1649,23 +1645,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 /* MDMA Stream 3 Registers */
 
 #define bfin_read_MDMA_D3_NEXT_DESC_PTR()              bfin_read32(MDMA_D3_NEXT_DESC_PTR)
-#define bfin_write_MDMA_D3_NEXT_DESC_PTR(val)          bfin_write32(MDMA_D3_NEXT_DESC_PTR)
+#define bfin_write_MDMA_D3_NEXT_DESC_PTR(val)          bfin_write32(MDMA_D3_NEXT_DESC_PTR, val)
 #define bfin_read_MDMA_D3_START_ADDR()                         bfin_read32(MDMA_D3_START_ADDR)
-#define bfin_write_MDMA_D3_START_ADDR(val)             bfin_write32(MDMA_D3_START_ADDR)
+#define bfin_write_MDMA_D3_START_ADDR(val)             bfin_write32(MDMA_D3_START_ADDR, val)
 #define bfin_read_MDMA_D3_CONFIG()                     bfin_read16(MDMA_D3_CONFIG)
 #define bfin_write_MDMA_D3_CONFIG(val)                 bfin_write16(MDMA_D3_CONFIG, val)
 #define bfin_read_MDMA_D3_X_COUNT()                    bfin_read16(MDMA_D3_X_COUNT)
 #define bfin_write_MDMA_D3_X_COUNT(val)                        bfin_write16(MDMA_D3_X_COUNT, val)
 #define bfin_read_MDMA_D3_X_MODIFY()                   bfin_read16(MDMA_D3_X_MODIFY)
-#define bfin_write_MDMA_D3_X_MODIFY(val)               bfin_write16(MDMA_D3_X_MODIFY)
+#define bfin_write_MDMA_D3_X_MODIFY(val)               bfin_write16(MDMA_D3_X_MODIFY, val)
 #define bfin_read_MDMA_D3_Y_COUNT()                    bfin_read16(MDMA_D3_Y_COUNT)
 #define bfin_write_MDMA_D3_Y_COUNT(val)                        bfin_write16(MDMA_D3_Y_COUNT, val)
 #define bfin_read_MDMA_D3_Y_MODIFY()                   bfin_read16(MDMA_D3_Y_MODIFY)
-#define bfin_write_MDMA_D3_Y_MODIFY(val)               bfin_write16(MDMA_D3_Y_MODIFY)
+#define bfin_write_MDMA_D3_Y_MODIFY(val)               bfin_write16(MDMA_D3_Y_MODIFY, val)
 #define bfin_read_MDMA_D3_CURR_DESC_PTR()              bfin_read32(MDMA_D3_CURR_DESC_PTR)
-#define bfin_write_MDMA_D3_CURR_DESC_PTR(val)          bfin_write32(MDMA_D3_CURR_DESC_PTR)
+#define bfin_write_MDMA_D3_CURR_DESC_PTR(val)          bfin_write32(MDMA_D3_CURR_DESC_PTR, val)
 #define bfin_read_MDMA_D3_CURR_ADDR()                  bfin_read32(MDMA_D3_CURR_ADDR)
-#define bfin_write_MDMA_D3_CURR_ADDR(val)              bfin_write32(MDMA_D3_CURR_ADDR)
+#define bfin_write_MDMA_D3_CURR_ADDR(val)              bfin_write32(MDMA_D3_CURR_ADDR, val)
 #define bfin_read_MDMA_D3_IRQ_STATUS()                 bfin_read16(MDMA_D3_IRQ_STATUS)
 #define bfin_write_MDMA_D3_IRQ_STATUS(val)             bfin_write16(MDMA_D3_IRQ_STATUS, val)
 #define bfin_read_MDMA_D3_PERIPHERAL_MAP()             bfin_read16(MDMA_D3_PERIPHERAL_MAP)
@@ -1675,23 +1671,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 #define bfin_read_MDMA_D3_CURR_Y_COUNT()               bfin_read16(MDMA_D3_CURR_Y_COUNT)
 #define bfin_write_MDMA_D3_CURR_Y_COUNT(val)           bfin_write16(MDMA_D3_CURR_Y_COUNT, val)
 #define bfin_read_MDMA_S3_NEXT_DESC_PTR()              bfin_read32(MDMA_S3_NEXT_DESC_PTR)
-#define bfin_write_MDMA_S3_NEXT_DESC_PTR(val)          bfin_write32(MDMA_S3_NEXT_DESC_PTR)
+#define bfin_write_MDMA_S3_NEXT_DESC_PTR(val)          bfin_write32(MDMA_S3_NEXT_DESC_PTR, val)
 #define bfin_read_MDMA_S3_START_ADDR()                         bfin_read32(MDMA_S3_START_ADDR)
-#define bfin_write_MDMA_S3_START_ADDR(val)             bfin_write32(MDMA_S3_START_ADDR)
+#define bfin_write_MDMA_S3_START_ADDR(val)             bfin_write32(MDMA_S3_START_ADDR, val)
 #define bfin_read_MDMA_S3_CONFIG()                     bfin_read16(MDMA_S3_CONFIG)
 #define bfin_write_MDMA_S3_CONFIG(val)                 bfin_write16(MDMA_S3_CONFIG, val)
 #define bfin_read_MDMA_S3_X_COUNT()                    bfin_read16(MDMA_S3_X_COUNT)
 #define bfin_write_MDMA_S3_X_COUNT(val)                        bfin_write16(MDMA_S3_X_COUNT, val)
 #define bfin_read_MDMA_S3_X_MODIFY()                   bfin_read16(MDMA_S3_X_MODIFY)
-#define bfin_write_MDMA_S3_X_MODIFY(val)               bfin_write16(MDMA_S3_X_MODIFY)
+#define bfin_write_MDMA_S3_X_MODIFY(val)               bfin_write16(MDMA_S3_X_MODIFY, val)
 #define bfin_read_MDMA_S3_Y_COUNT()                    bfin_read16(MDMA_S3_Y_COUNT)
 #define bfin_write_MDMA_S3_Y_COUNT(val)                        bfin_write16(MDMA_S3_Y_COUNT, val)
 #define bfin_read_MDMA_S3_Y_MODIFY()                   bfin_read16(MDMA_S3_Y_MODIFY)
-#define bfin_write_MDMA_S3_Y_MODIFY(val)               bfin_write16(MDMA_S3_Y_MODIFY)
+#define bfin_write_MDMA_S3_Y_MODIFY(val)               bfin_write16(MDMA_S3_Y_MODIFY, val)
 #define bfin_read_MDMA_S3_CURR_DESC_PTR()              bfin_read32(MDMA_S3_CURR_DESC_PTR)
-#define bfin_write_MDMA_S3_CURR_DESC_PTR(val)          bfin_write32(MDMA_S3_CURR_DESC_PTR)
+#define bfin_write_MDMA_S3_CURR_DESC_PTR(val)          bfin_write32(MDMA_S3_CURR_DESC_PTR, val)
 #define bfin_read_MDMA_S3_CURR_ADDR()                  bfin_read32(MDMA_S3_CURR_ADDR)
-#define bfin_write_MDMA_S3_CURR_ADDR(val)              bfin_write32(MDMA_S3_CURR_ADDR)
+#define bfin_write_MDMA_S3_CURR_ADDR(val)              bfin_write32(MDMA_S3_CURR_ADDR, val)
 #define bfin_read_MDMA_S3_IRQ_STATUS()                 bfin_read16(MDMA_S3_IRQ_STATUS)
 #define bfin_write_MDMA_S3_IRQ_STATUS(val)             bfin_write16(MDMA_S3_IRQ_STATUS, val)
 #define bfin_read_MDMA_S3_PERIPHERAL_MAP()             bfin_read16(MDMA_S3_PERIPHERAL_MAP)
index 46ff31f20ae5b821d7205b1b20a1e910f6854483..36a2ef7e7849fa6dc3d40653678277d009f130a3 100644 (file)
@@ -73,6 +73,4 @@
 
 #define MAX_BLACKFIN_DMA_CHANNEL 32
 
-extern int channel2irq(unsigned int channel);
-extern struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL];
 #endif
index befc2903d5a594378faeefcb66f3673aa3d94e75..ab0b863eee66c49a851daf24e90790eda302fdbf 100644 (file)
  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 #define MIN_DDR_SCLK(x)        (x*(CONFIG_SCLK_HZ/1000/1000)/1000 + 1)
+#define MAX_DDR_SCLK(x)        (x*(CONFIG_SCLK_HZ/1000/1000)/1000)
+#define DDR_CLK_HZ(x)  (1000*1000*1000/x)
 
 #if (CONFIG_MEM_MT46V32M16_6T)
 #define DDR_SIZE       DEVSZ_512
 #define DDR_WIDTH      DEVWD_16
+#define DDR_MAX_tCK    13
 
 #define DDR_tRC                DDR_TRC(MIN_DDR_SCLK(60))
 #define DDR_tRAS       DDR_TRAS(MIN_DDR_SCLK(42))
 #define DDR_tRP                DDR_TRP(MIN_DDR_SCLK(15))
 #define DDR_tRFC       DDR_TRFC(MIN_DDR_SCLK(72))
-#define DDR_tREFI      DDR_TREFI(MIN_DDR_SCLK(7800))
+#define DDR_tREFI      DDR_TREFI(MAX_DDR_SCLK(7800))
 
 #define DDR_tRCD       DDR_TRCD(MIN_DDR_SCLK(15))
 #define DDR_tWTR       DDR_TWTR(1)
 #if (CONFIG_MEM_MT46V32M16_5B)
 #define DDR_SIZE       DEVSZ_512
 #define DDR_WIDTH      DEVWD_16
+#define DDR_MAX_tCK    13
 
 #define DDR_tRC                DDR_TRC(MIN_DDR_SCLK(55))
 #define DDR_tRAS       DDR_TRAS(MIN_DDR_SCLK(40))
 #define DDR_tRP                DDR_TRP(MIN_DDR_SCLK(15))
 #define DDR_tRFC       DDR_TRFC(MIN_DDR_SCLK(70))
-#define DDR_tREFI      DDR_TREFI(MIN_DDR_SCLK(7800))
+#define DDR_tREFI      DDR_TREFI(MAX_DDR_SCLK(7800))
 
 #define DDR_tRCD       DDR_TRCD(MIN_DDR_SCLK(15))
 #define DDR_tWTR       DDR_TWTR(2)
@@ -65,6 +69,7 @@
 #if (CONFIG_MEM_GENERIC_BOARD)
 #define DDR_SIZE       DEVSZ_512
 #define DDR_WIDTH      DEVWD_16
+#define DDR_MAX_tCK    13
 
 #define DDR_tRCD       DDR_TRCD(3)
 #define DDR_tWTR       DDR_TWTR(2)
 #define DDR_tREFI      DDR_TREFI(1288)
 #endif
 
-#if (CONFIG_SCLK_HZ <= 133333333)
-#define        DDR_CL          CL_2
-#elif (CONFIG_SCLK_HZ <= 166666666)
-#define        DDR_CL          CL_2_5
+#if (CONFIG_SCLK_HZ < DDR_CLK_HZ(DDR_MAX_tCK))
+# error "CONFIG_SCLK_HZ is too small (<DDR_CLK_HZ(DDR_MAX_tCK) Hz)."
+#elif(CONFIG_SCLK_HZ <= 133333333)
+# define       DDR_CL          CL_2
 #else
-#define        DDR_CL          CL_3
+# error "CONFIG_SCLK_HZ is too large (>133333333 Hz)."
 #endif
 
+
 #define mem_DDRCTL0    (DDR_tRP | DDR_tRAS | DDR_tRC | DDR_tRFC | DDR_tREFI)
 #define mem_DDRCTL1    (DDR_DATWIDTH | EXTBANK_1 | DDR_SIZE | DDR_WIDTH | DDR_tWTR \
                        | DDR_tMRD | DDR_tWR | DDR_tRCD)
index 0c1d461939397ab9caadd65e4f8e3cd6df867768..82157caa96a22d46c067652400dd01508824d2ff 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 /* This file shoule be up to date with:
- *  - Revision O, 11/15/2007; ADSP-BF561 Blackfin Processor Anomaly List
+ *  - Revision P, 02/08/2008; ADSP-BF561 Blackfin Processor Anomaly List
  */
 
 #ifndef _MACH_ANOMALY_H_
 #define ANOMALY_05000357 (1)
 /* Conflicting Column Address Widths Causes SDRAM Errors */
 #define ANOMALY_05000362 (1)
+/* UART Break Signal Issues */
+#define ANOMALY_05000363 (__SILICON_REVISION__ < 5)
 /* PPI Underflow Error Goes Undetected in ITU-R 656 Mode */
 #define ANOMALY_05000366 (1)
 /* Possible RETS Register Corruption when Subroutine Is under 5 Cycles in Duration */
 #define ANOMALY_05000371 (1)
+/* Level-Sensitive External GPIO Wakeups May Cause Indefinite Stall */
+#define ANOMALY_05000403 (1)
 
 /* Anomalies that don't exist on this proc */
 #define ANOMALY_05000158 (0)
index b6f513bee56ece582d69bdba072e722b557099f0..8a4e66d1db37aa0b80423cf3c54639833480a1c4 100644 (file)
@@ -1,22 +1,38 @@
+/*
+ * file:        include/asm-blackfin/mach-bf561/bfin_serial_5xx.h
+ * based on:
+ * author:
+ *
+ * created:
+ * description:
+ *     blackfin serial driver head file
+ * rev:
+ *
+ * modified:
+ *
+ *
+ * bugs:         enter bugs at http://blackfin.uclinux.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, 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; see the file copying.
+ * if not, write to the free software foundation,
+ * 59 temple place - suite 330, boston, ma 02111-1307, usa.
+ */
+
 #include <linux/serial.h>
 #include <asm/dma.h>
 #include <asm/portmux.h>
 
-#define NR_PORTS                1
-
-#define OFFSET_THR              0x00   /* Transmit Holding register            */
-#define OFFSET_RBR              0x00   /* Receive Buffer register              */
-#define OFFSET_DLL              0x00   /* Divisor Latch (Low-Byte)             */
-#define OFFSET_IER              0x04   /* Interrupt Enable Register            */
-#define OFFSET_DLH              0x04   /* Divisor Latch (High-Byte)            */
-#define OFFSET_IIR              0x08   /* Interrupt Identification Register    */
-#define OFFSET_LCR              0x0C   /* Line Control Register                */
-#define OFFSET_MCR              0x10   /* Modem Control Register               */
-#define OFFSET_LSR              0x14   /* Line Status Register                 */
-#define OFFSET_MSR              0x18   /* Modem Status Register                */
-#define OFFSET_SCR              0x1C   /* SCR Scratch Register                 */
-#define OFFSET_GCTL             0x24   /* Global Control Register              */
-
 #define UART_GET_CHAR(uart)     bfin_read16(((uart)->port.membase + OFFSET_RBR))
 #define UART_GET_DLL(uart)     bfin_read16(((uart)->port.membase + OFFSET_DLL))
 #define UART_GET_IER(uart)      bfin_read16(((uart)->port.membase + OFFSET_IER))
@@ -84,7 +100,7 @@ static inline void UART_CLEAR_LSR(struct bfin_serial_port *uart)
        bfin_write16(uart->port.membase + OFFSET_LSR, -1);
 }
 
-struct bfin_serial_port bfin_serial_ports[NR_PORTS];
+struct bfin_serial_port bfin_serial_ports[BFIN_UART_NR_PORTS];
 struct bfin_serial_res {
        unsigned long   uart_base_addr;
        int             uart_irq;
@@ -115,7 +131,7 @@ struct bfin_serial_res bfin_serial_resource[] = {
 
 #define DRIVER_NAME "bfin-uart"
 
-int nr_ports = NR_PORTS;
+int nr_ports = BFIN_UART_NR_PORTS;
 static void bfin_serial_hw_init(struct bfin_serial_port *uart)
 {
 
diff --git a/include/asm-blackfin/mach-bf561/bfin_sir.h b/include/asm-blackfin/mach-bf561/bfin_sir.h
new file mode 100644 (file)
index 0000000..cefcf8b
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * Blackfin Infra-red Driver
+ *
+ * Copyright 2006-2008 Analog Devices Inc.
+ *
+ * Enter bugs at http://blackfin.uclinux.org/
+ *
+ * Licensed under the GPL-2 or later.
+ *
+ */
+
+#include <linux/serial.h>
+#include <asm/dma.h>
+#include <asm/portmux.h>
+
+#define SIR_UART_GET_CHAR(port)   bfin_read16((port)->membase + OFFSET_RBR)
+#define SIR_UART_GET_DLL(port)    bfin_read16((port)->membase + OFFSET_DLL)
+#define SIR_UART_GET_IER(port)    bfin_read16((port)->membase + OFFSET_IER)
+#define SIR_UART_GET_DLH(port)    bfin_read16((port)->membase + OFFSET_DLH)
+#define SIR_UART_GET_IIR(port)    bfin_read16((port)->membase + OFFSET_IIR)
+#define SIR_UART_GET_LCR(port)    bfin_read16((port)->membase + OFFSET_LCR)
+#define SIR_UART_GET_GCTL(port)   bfin_read16((port)->membase + OFFSET_GCTL)
+
+#define SIR_UART_PUT_CHAR(port, v) bfin_write16(((port)->membase + OFFSET_THR), v)
+#define SIR_UART_PUT_DLL(port, v)  bfin_write16(((port)->membase + OFFSET_DLL), v)
+#define SIR_UART_PUT_IER(port, v)  bfin_write16(((port)->membase + OFFSET_IER), v)
+#define SIR_UART_PUT_DLH(port, v)  bfin_write16(((port)->membase + OFFSET_DLH), v)
+#define SIR_UART_PUT_LCR(port, v)  bfin_write16(((port)->membase + OFFSET_LCR), v)
+#define SIR_UART_PUT_GCTL(port, v) bfin_write16(((port)->membase + OFFSET_GCTL), v)
+
+#ifdef CONFIG_SIR_BFIN_DMA
+struct dma_rx_buf {
+       char *buf;
+       int head;
+       int tail;
+       };
+#endif /* CONFIG_SIR_BFIN_DMA */
+
+struct bfin_sir_port {
+       unsigned char __iomem   *membase;
+       unsigned int            irq;
+       unsigned int            lsr;
+       unsigned long           clk;
+       struct net_device       *dev;
+#ifdef CONFIG_SIR_BFIN_DMA
+       int                     tx_done;
+       struct dma_rx_buf       rx_dma_buf;
+       struct timer_list       rx_dma_timer;
+       int                     rx_dma_nrows;
+#endif /* CONFIG_SIR_BFIN_DMA */
+       unsigned int            tx_dma_channel;
+       unsigned int            rx_dma_channel;
+};
+
+struct bfin_sir_port sir_ports[BFIN_UART_NR_PORTS];
+
+struct bfin_sir_port_res {
+       unsigned long   base_addr;
+       int             irq;
+       unsigned int    rx_dma_channel;
+       unsigned int    tx_dma_channel;
+};
+
+struct bfin_sir_port_res bfin_sir_port_resource[] = {
+#ifdef CONFIG_BFIN_SIR0
+       {
+       0xFFC00400,
+       IRQ_UART_RX,
+       CH_UART_RX,
+       CH_UART_TX,
+       },
+#endif
+};
+
+int nr_sirs = ARRAY_SIZE(bfin_sir_port_resource);
+
+struct bfin_sir_self {
+       struct bfin_sir_port    *sir_port;
+       spinlock_t              lock;
+       unsigned int            open;
+       int                     speed;
+       int                     newspeed;
+
+       struct sk_buff          *txskb;
+       struct sk_buff          *rxskb;
+       struct net_device_stats stats;
+       struct device           *dev;
+       struct irlap_cb         *irlap;
+       struct qos_info         qos;
+
+       iobuff_t                tx_buff;
+       iobuff_t                rx_buff;
+
+       struct work_struct      work;
+       int                     mtt;
+};
+
+static inline unsigned int SIR_UART_GET_LSR(struct bfin_sir_port *port)
+{
+       unsigned int lsr = bfin_read16(port->membase + OFFSET_LSR);
+       port->lsr |= (lsr & (BI|FE|PE|OE));
+       return lsr | port->lsr;
+}
+
+static inline void SIR_UART_CLEAR_LSR(struct bfin_sir_port *port)
+{
+       port->lsr = 0;
+       bfin_read16(port->membase + OFFSET_LSR);
+}
+
+#define DRIVER_NAME "bfin_sir"
+
+static void bfin_sir_hw_init(void)
+{
+#ifdef CONFIG_BFIN_SIR0
+       peripheral_request(P_UART0_TX, DRIVER_NAME);
+       peripheral_request(P_UART0_RX, DRIVER_NAME);
+#endif
+       SSYNC();
+}
index 3a16df2c86d857fe5df7f0768919fba6158e4594..0ea8666e6764befcdafdfd412bb75fbdae8ee978 100644 (file)
 #define bfin_read_SIC_ISR(x)           bfin_read32(SICA_ISR0 + (x << 2))
 #define bfin_write_SIC_ISR(x, val)     bfin_write32((SICA_ISR0 + (x << 2)), val)
 
+#define BFIN_UART_NR_PORTS      1
+
+#define OFFSET_THR              0x00   /* Transmit Holding register            */
+#define OFFSET_RBR              0x00   /* Receive Buffer register              */
+#define OFFSET_DLL              0x00   /* Divisor Latch (Low-Byte)             */
+#define OFFSET_IER              0x04   /* Interrupt Enable Register            */
+#define OFFSET_DLH              0x04   /* Divisor Latch (High-Byte)            */
+#define OFFSET_IIR              0x08   /* Interrupt Identification Register    */
+#define OFFSET_LCR              0x0C   /* Line Control Register                */
+#define OFFSET_MCR              0x10   /* Modem Control Register               */
+#define OFFSET_LSR              0x14   /* Line Status Register                 */
+#define OFFSET_MSR              0x18   /* Modem Status Register                */
+#define OFFSET_SCR              0x1C   /* SCR Scratch Register                 */
+#define OFFSET_GCTL             0x24   /* Global Control Register              */
 
 #endif                         /* _MACH_BLACKFIN_H_ */
index 1bc8d2f89cccf7ae69baaa1a29477f20406b7b2d..b07ffccd66dd8a6f960487123895f3cc80d21c07 100644 (file)
 
 /* Clock and System Control (0xFFC00000 - 0xFFC000FF) */
 #define bfin_read_PLL_CTL()                  bfin_read16(PLL_CTL)
-#define bfin_write_PLL_CTL(val)              bfin_write16(PLL_CTL,val)
+/* Writing to PLL_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_PLL_CTL(unsigned int val)
+{
+       unsigned long flags, iwr0, iwr1;
+
+       if (val == bfin_read_PLL_CTL())
+               return;
+
+       local_irq_save(flags);
+       /* Enable the PLL Wakeup bit in SIC IWR */
+       iwr0 = bfin_read32(SICA_IWR0);
+       iwr1 = bfin_read32(SICA_IWR1);
+       /* Only allow PPL Wakeup) */
+       bfin_write32(SICA_IWR0, IWR_ENABLE(0));
+       bfin_write32(SICA_IWR1, 0);
+
+       bfin_write16(PLL_CTL, val);
+       SSYNC();
+       asm("IDLE;");
+
+       bfin_write32(SICA_IWR0, iwr0);
+       bfin_write32(SICA_IWR1, iwr1);
+       local_irq_restore(flags);
+}
 #define bfin_read_PLL_DIV()                  bfin_read16(PLL_DIV)
 #define bfin_write_PLL_DIV(val)              bfin_write16(PLL_DIV,val)
 #define bfin_read_VR_CTL()                   bfin_read16(VR_CTL)
@@ -56,6 +79,10 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 {
        unsigned long flags, iwr0, iwr1;
 
+       if (val == bfin_read_VR_CTL())
+               return;
+
+       local_irq_save(flags);
        /* Enable the PLL Wakeup bit in SIC IWR */
        iwr0 = bfin_read32(SICA_IWR0);
        iwr1 = bfin_read32(SICA_IWR1);
@@ -65,12 +92,11 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 
        bfin_write16(VR_CTL, val);
        SSYNC();
-
-       local_irq_save(flags);
        asm("IDLE;");
-       local_irq_restore(flags);
+
        bfin_write32(SICA_IWR0, iwr0);
        bfin_write32(SICA_IWR1, iwr1);
+       local_irq_restore(flags);
 }
 #define bfin_read_PLL_STAT()                 bfin_read16(PLL_STAT)
 #define bfin_write_PLL_STAT(val)             bfin_write16(PLL_STAT,val)
index c3c0eb13c819e43cd843bfdedb6bdbf039b57208..366c9b9a0cb70cf2f345b2075024df35b8ea3671 100644 (file)
 #define WDOGB_STAT                             0xFFC01208      /* Watchdog Status register */
 
 /* UART Controller (0xFFC00400 - 0xFFC004FF) */
-#define UART_THR               0xFFC00400      /* Transmit Holding register */
-#define UART_RBR               0xFFC00400      /* Receive Buffer register */
-#define UART_DLL               0xFFC00400      /* Divisor Latch (Low-Byte) */
-#define UART_IER               0xFFC00404      /* Interrupt Enable Register */
-#define UART_DLH               0xFFC00404      /* Divisor Latch (High-Byte) */
-#define UART_IIR               0xFFC00408      /* Interrupt Identification Register */
-#define UART_LCR               0xFFC0040C      /* Line Control Register */
-#define UART_MCR                               0xFFC00410      /* Modem Control Register */
-#define UART_LSR               0xFFC00414      /* Line Status Register */
-#define UART_MSR               0xFFC00418      /* Modem Status Register */
-#define UART_SCR               0xFFC0041C      /* SCR Scratch Register */
-#define UART_GCTL                      0xFFC00424      /* Global Control Register */
+
+/*
+ * Because include/linux/serial_reg.h have defined UART_*,
+ * So we define blackfin uart regs to BFIN_UART0_*.
+ */
+#define BFIN_UART_THR                  0xFFC00400  /* Transmit Holding register */
+#define BFIN_UART_RBR                  0xFFC00400  /* Receive Buffer register */
+#define BFIN_UART_DLL                  0xFFC00400  /* Divisor Latch (Low-Byte) */
+#define BFIN_UART_IER                  0xFFC00404  /* Interrupt Enable Register */
+#define BFIN_UART_DLH                  0xFFC00404  /* Divisor Latch (High-Byte) */
+#define BFIN_UART_IIR                  0xFFC00408  /* Interrupt Identification Register */
+#define BFIN_UART_LCR                  0xFFC0040C  /* Line Control Register */
+#define BFIN_UART_MCR                  0xFFC00410  /* Modem Control Register */
+#define BFIN_UART_LSR                  0xFFC00414  /* Line Status Register */
+#define BFIN_UART_MSR                  0xFFC00418  /* Modem Status Register */
+#define BFIN_UART_SCR                  0xFFC0041C  /* SCR Scratch Register */
+#define BFIN_UART_GCTL                 0xFFC00424  /* Global Control Register */
 
 /* SPI Controller (0xFFC00500 - 0xFFC005FF) */
 #define SPI0_REGBASE                   0xFFC00500
 /* PLL_DIV Masks */
 #define SCLK_DIV(x)  (x)       /* SCLK = VCO / x */
 
+#define CSEL                   0x30            /* Core Select */
+#define SSEL                   0xf             /* System Select */
 #define CCLK_DIV1              0x00000000      /* CCLK = VCO / 1 */
 #define CCLK_DIV2              0x00000010      /* CCLK = VCO / 2 */
 #define CCLK_DIV4              0x00000020      /* CCLK = VCO / 4 */
index 766334b7d8ab8bf3a225408bb1dc6fe353356714..21d982003e7525c80188ae55bf2df8985ec77658 100644 (file)
@@ -32,7 +32,4 @@
 #define CH_IMEM_STREAM1_SRC    34
 #define CH_IMEM_STREAM1_DEST   35
 
-extern int channel2irq(unsigned int channel);
-extern struct dma_register *base_addr[];
-
 #endif
index 0d3f650d2d99ad50ecc4dc4269d1117581985507..0807b286cd9e9e5fa9ebfeb92bc81f953fefb3eb 100644 (file)
@@ -17,8 +17,8 @@
 
 int peripheral_request(unsigned short per, const char *label);
 void peripheral_free(unsigned short per);
-int peripheral_request_list(unsigned short per[], const char *label);
-void peripheral_free_list(unsigned short per[]);
+int peripheral_request_list(const unsigned short per[], const char *label);
+void peripheral_free_list(const unsigned short per[]);
 
 #include <asm/gpio.h>
 #include <asm/mach/portmux.h>
index 1033e5c7601190089dfbd6cf7a19b95d32e796d2..1c004072461257a2b7ebb2c850858103f30cf620 100644 (file)
@@ -26,9 +26,10 @@ static inline void wrusp(unsigned long usp)
 
 /*
  * User space process size: 1st byte beyond user address space.
+ * Fairly meaningless on nommu.  Parts of user programs can be scattered
+ * in a lot of places, so just disable this by setting it to 0xFFFFFFFF.
  */
-extern unsigned long memory_end;
-#define TASK_SIZE      (memory_end)
+#define TASK_SIZE      0xFFFFFFFF
 
 #ifdef __KERNEL__
 #define STACK_TOP      TASK_SIZE
index 0250429b736a1fe8a074cbc96f0860e0f1812b14..87951d25145813e183459d03a15bf7000da69408 100644 (file)
@@ -143,7 +143,7 @@ struct sigaction {
 #endif                         /* __KERNEL__ */
 
 typedef struct sigaltstack {
-       void *ss_sp;
+       void __user *ss_sp;
        int ss_flags;
        size_t ss_size;
 } stack_t;
index 15b99cf4f50bbbad4a6cf2fe633bfae25b7043bb..bc2fe5accf20a7f4c55f5b45c640e7e025a29ec1 100644 (file)
@@ -81,14 +81,11 @@ struct thread_info {
 #define init_thread_info       (init_thread_union.thread_info)
 #define init_stack             (init_thread_union.stack)
 
-/* How to get the thread information struct from C */
-
-static inline struct thread_info *current_thread_info(void)
-    __attribute__ ((__const__));
-
-/* Given a task stack pointer, you can find it's task structure
- * just by masking it to the 8K boundary.
+/* Given a task stack pointer, you can find its corresponding
+ * thread_info structure just by masking it to the THREAD_SIZE
+ * boundary (currently 8K as you can see above).
  */
+__attribute_const__
 static inline struct thread_info *current_thread_info(void)
 {
        struct thread_info *ti;
diff --git a/include/asm-blackfin/time.h b/include/asm-blackfin/time.h
new file mode 100644 (file)
index 0000000..6e5859b
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * asm-blackfin/time.h:
+ *
+ * Copyright 2004-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef _ASM_BLACKFIN_TIME_H
+#define _ASM_BLACKFIN_TIME_H
+
+/*
+ * The way that the Blackfin core timer works is:
+ *  - CCLK is divided by a programmable 8-bit pre-scaler (TSCALE)
+ *  - Every time TSCALE ticks, a 32bit is counted down (TCOUNT)
+ *
+ * If you take the fastest clock (1ns, or 1GHz to make the math work easier)
+ *    10ms is 10,000,000 clock ticks, which fits easy into a 32-bit counter
+ *    (32 bit counter is 4,294,967,296ns or 4.2 seconds) so, we don't need
+ *    to use TSCALE, and program it to zero (which is pass CCLK through).
+ *    If you feel like using it, try to keep HZ * TIMESCALE to some
+ *    value that divides easy (like power of 2).
+ */
+
+#ifndef CONFIG_CPU_FREQ
+#define TIME_SCALE 1
+#else
+/*
+ * Blackfin CPU frequency scaling supports max Core Clock 1, 1/2 and 1/4 .
+ * Whenever we change the Core Clock frequency changes we immediately
+ * adjust the Core Timer Presale Register. This way we don't lose time.
+ */
+#define TIME_SCALE 4
+#endif
+
+#endif
index 828590117f51acd105fe52c0f7e69e4c30eee9a3..22b0806161bb614b2179c7ec1eee002a0255779e 100644 (file)
@@ -1,18 +1,23 @@
-/* blackfin architecture timex specifications: Lineo Inc. 2001
+/*
+ * asm-blackfin/timex.h: cpu cycles!
  *
- * Based on: include/asm-m68knommu/timex.h
+ * Copyright 2004-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
  */
 
-#ifndef _ASMBLACKFIN_TIMEX_H
-#define _ASMBLACKFIN_TIMEX_H
+#ifndef _ASM_BLACKFIN_TIMEX_H
+#define _ASM_BLACKFIN_TIMEX_H
 
 #define CLOCK_TICK_RATE        1000000 /* Underlying HZ */
 
-typedef unsigned long cycles_t;
+typedef unsigned long long cycles_t;
 
 static inline cycles_t get_cycles(void)
 {
-       return 0;
+       unsigned long tmp, tmp2;
+       __asm__("%0 = cycles; %1 = cycles2;" : "=d"(tmp), "=d"(tmp2));
+       return tmp | ((cycles_t)tmp2 << 32);
 }
 
 #endif
index ef18afbc2101061b23118dfacb8f0880daf9f897..312b596b9731f477ac1c2238ef7ad92478c626dd 100644 (file)
@@ -62,14 +62,14 @@ extern unsigned long software_trace_buff[];
        preg.L = LO(TBUFCTL); \
        preg.H = HI(TBUFCTL); \
        dreg = [preg]; \
-       [sp++] = dreg; \
+       [--sp] = dreg; \
        dreg = 0x1; \
        [preg] = dreg;
 
 #define trace_buffer_restore(preg, dreg) \
        preg.L = LO(TBUFCTL); \
        preg.H = HI(TBUFCTL); \
-       dreg = [sp--]; \
+       dreg = [sp++]; \
        [preg] = dreg;
 
 #else /* CONFIG_DEBUG_BFIN_HWTRACE_ON */
index 22a410b8003b78954f972523e98d341d30eefa27..d928b8099056ab15b9fd9a840043909588c93ab4 100644 (file)
@@ -133,7 +133,7 @@ static inline int bad_user_access_length(void)
 }
 
 #define __put_user_bad() (printk(KERN_INFO "put_user_bad %s:%d %s\n",\
-                           __FILE__, __LINE__, __FUNCTION__),\
+                           __FILE__, __LINE__, __func__),\
                            bad_user_access_length(), (-EFAULT))
 
 /*
@@ -177,7 +177,7 @@ static inline int bad_user_access_length(void)
                default:                                                \
                        x = 0;                                          \
                        printk(KERN_INFO "get_user_bad: %s:%d %s\n",    \
-                              __FILE__, __LINE__, __FUNCTION__);       \
+                              __FILE__, __LINE__, __func__);   \
                        _err = __get_user_bad();                        \
                        break;                                          \
                }                                                       \
index c18a399f6e3ed863a64693eeaa573b04465cd0d0..42955d0c439b8bb84986a177fc3e1fb0beb74fb7 100644 (file)
                                /* 258 __NR_remap_file_pages */
 #define __NR_set_tid_address   259
 #define __NR_timer_create      260
-#define __NR_timer_settime     (__NR_timer_create+1)
-#define __NR_timer_gettime     (__NR_timer_create+2)
-#define __NR_timer_getoverrun  (__NR_timer_create+3)
-#define __NR_timer_delete      (__NR_timer_create+4)
-#define __NR_clock_settime     (__NR_timer_create+5)
-#define __NR_clock_gettime     (__NR_timer_create+6)
-#define __NR_clock_getres      (__NR_timer_create+7)
-#define __NR_clock_nanosleep   (__NR_timer_create+8)
+#define __NR_timer_settime     261
+#define __NR_timer_gettime     262
+#define __NR_timer_getoverrun  263
+#define __NR_timer_delete      264
+#define __NR_clock_settime     265
+#define __NR_clock_gettime     266
+#define __NR_clock_getres      267
+#define __NR_clock_nanosleep   268
 #define __NR_statfs64          269
 #define __NR_fstatfs64         270
 #define __NR_tgkill            271
                                /* 276 __NR_get_mempolicy */
                                /* 277 __NR_set_mempolicy */
 #define __NR_mq_open           278
-#define __NR_mq_unlink         (__NR_mq_open+1)
-#define __NR_mq_timedsend      (__NR_mq_open+2)
-#define __NR_mq_timedreceive   (__NR_mq_open+3)
-#define __NR_mq_notify         (__NR_mq_open+4)
-#define __NR_mq_getsetattr     (__NR_mq_open+5)
+#define __NR_mq_unlink         279
+#define __NR_mq_timedsend      280
+#define __NR_mq_timedreceive   281
+#define __NR_mq_notify         282
+#define __NR_mq_getsetattr     283
 #define __NR_kexec_load                284
 #define __NR_waitid            285
 #define __NR_add_key           286
index 680e51d87374cde9ab41d3d88f8c7f6655f438e5..19790eb99cc6830820522a74c11492528ec0f567 100644 (file)
@@ -16,6 +16,8 @@ struct dev_archdata {
 
        struct device_node      *prom_node;
        struct of_device        *op;
+
+       int                     numa_node;
 };
 
 #endif /* _ASM_SPARC_DEVICE_H */
index df5dc442248322878f6d6831a56bfef54a3ceade..fd55522481cd9dc0d14a14302446dff9d13017ee 100644 (file)
@@ -77,6 +77,11 @@ extern int of_getintprop_default(struct device_node *np,
                                 const char *name,
                                 int def);
 extern int of_find_in_proplist(const char *list, const char *match, int len);
+#ifdef CONFIG_NUMA
+extern int of_node_to_nid(struct device_node *dp);
+#else
+#define of_node_to_nid(dp)     (-1)
+#endif
 
 extern void prom_build_devicetree(void);
 
index 46325ddee23b32f3677638e11d2b76ae7c8f4840..d7b9afcba08bf433c87d8569f0169d1eaec68343 100644 (file)
@@ -56,6 +56,7 @@ struct strbuf {
 };
 
 extern int iommu_table_init(struct iommu *iommu, int tsbsize,
-                           u32 dma_offset, u32 dma_addr_mask);
+                           u32 dma_offset, u32 dma_addr_mask,
+                           int numa_node);
 
 #endif /* !(_SPARC64_IOMMU_H) */
diff --git a/include/asm-sparc64/mmzone.h b/include/asm-sparc64/mmzone.h
new file mode 100644 (file)
index 0000000..ebf5986
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef _SPARC64_MMZONE_H
+#define _SPARC64_MMZONE_H
+
+#ifdef CONFIG_NEED_MULTIPLE_NODES
+
+extern struct pglist_data *node_data[];
+
+#define NODE_DATA(nid)         (node_data[nid])
+#define node_start_pfn(nid)    (NODE_DATA(nid)->node_start_pfn)
+#define node_end_pfn(nid)      (NODE_DATA(nid)->node_end_pfn)
+
+extern int numa_cpu_lookup_table[];
+extern cpumask_t numa_cpumask_lookup_table[];
+
+#endif /* CONFIG_NEED_MULTIPLE_NODES */
+
+#endif /* _SPARC64_MMZONE_H */
diff --git a/include/asm-sparc64/numnodes.h b/include/asm-sparc64/numnodes.h
deleted file mode 100644 (file)
index 017e7e7..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _SPARC64_NUMNODES_H
-#define _SPARC64_NUMNODES_H
-
-#define NODES_SHIFT    0
-
-#endif /* !(_SPARC64_NUMNODES_H) */
index 6da197803efcd501fbf81ab2ca0a59572b41fd9c..b4b951d570bbf3915fdf5ddad8624c95f70b453c 100644 (file)
@@ -8,6 +8,8 @@
  * stack during a system call and basically all traps.
  */
 
+#define PT_REGS_MAGIC 0x57ac6c00
+
 #ifndef __ASSEMBLY__
 
 struct pt_regs {
@@ -16,7 +18,19 @@ struct pt_regs {
        unsigned long tpc;
        unsigned long tnpc;
        unsigned int y;
-       unsigned int fprs;
+
+       /* We encode a magic number, PT_REGS_MAGIC, along
+        * with the %tt (trap type) register value at trap
+        * entry time.  The magic number allows us to identify
+        * accurately a trap stack frame in the stack
+        * unwinder, and the %tt value allows us to test
+        * things like "in a system call" etc. for an arbitray
+        * process.
+        *
+        * The PT_REGS_MAGIC is choosen such that it can be
+        * loaded completely using just a sethi instruction.
+        */
+       unsigned int magic;
 };
 
 struct pt_regs32 {
@@ -147,7 +161,7 @@ extern void __show_regs(struct pt_regs *);
 #define PT_V9_TPC    0x88
 #define PT_V9_TNPC   0x90
 #define PT_V9_Y      0x98
-#define PT_V9_FPRS   0x9c
+#define PT_V9_MAGIC  0x9c
 #define PT_TSTATE      PT_V9_TSTATE
 #define PT_TPC         PT_V9_TPC
 #define PT_TNPC                PT_V9_TNPC
index 77bcd2bfa53ceb81d2fb82e7eac66ebef149b3a4..b99d4e4b6d284a6a93d6d9450de4f3da2e446b61 100644 (file)
@@ -3,7 +3,7 @@
 
 #ifdef __KERNEL__
 
-#define SECTION_SIZE_BITS       31
+#define SECTION_SIZE_BITS       30
 #define MAX_PHYSADDR_BITS       42
 #define MAX_PHYSMEM_BITS        42
 
index c6b557034f686623ab59a6a109b92302b5e4a3d2..001c04027c82b3f774a8c4aaeed12f5eff8c8835 100644 (file)
@@ -1,6 +1,77 @@
 #ifndef _ASM_SPARC64_TOPOLOGY_H
 #define _ASM_SPARC64_TOPOLOGY_H
 
+#ifdef CONFIG_NUMA
+
+#include <asm/mmzone.h>
+
+static inline int cpu_to_node(int cpu)
+{
+       return numa_cpu_lookup_table[cpu];
+}
+
+#define parent_node(node)      (node)
+
+static inline cpumask_t node_to_cpumask(int node)
+{
+       return numa_cpumask_lookup_table[node];
+}
+
+/* Returns a pointer to the cpumask of CPUs on Node 'node'. */
+#define node_to_cpumask_ptr(v, node)           \
+               cpumask_t *v = &(numa_cpumask_lookup_table[node])
+
+#define node_to_cpumask_ptr_next(v, node)      \
+                          v = &(numa_cpumask_lookup_table[node])
+
+static inline int node_to_first_cpu(int node)
+{
+       cpumask_t tmp;
+       tmp = node_to_cpumask(node);
+       return first_cpu(tmp);
+}
+
+struct pci_bus;
+#ifdef CONFIG_PCI
+extern int pcibus_to_node(struct pci_bus *pbus);
+#else
+static inline int pcibus_to_node(struct pci_bus *pbus)
+{
+       return -1;
+}
+#endif
+
+#define pcibus_to_cpumask(bus) \
+       (pcibus_to_node(bus) == -1 ? \
+        CPU_MASK_ALL : \
+        node_to_cpumask(pcibus_to_node(bus)))
+
+#define SD_NODE_INIT (struct sched_domain) {           \
+       .min_interval           = 8,                    \
+       .max_interval           = 32,                   \
+       .busy_factor            = 32,                   \
+       .imbalance_pct          = 125,                  \
+       .cache_nice_tries       = 2,                    \
+       .busy_idx               = 3,                    \
+       .idle_idx               = 2,                    \
+       .newidle_idx            = 0,                    \
+       .wake_idx               = 1,                    \
+       .forkexec_idx           = 1,                    \
+       .flags                  = SD_LOAD_BALANCE       \
+                               | SD_BALANCE_FORK       \
+                               | SD_BALANCE_EXEC       \
+                               | SD_SERIALIZE          \
+                               | SD_WAKE_BALANCE,      \
+       .last_balance           = jiffies,              \
+       .balance_interval       = 1,                    \
+}
+
+#else /* CONFIG_NUMA */
+
+#include <asm-generic/topology.h>
+
+#endif /* !(CONFIG_NUMA) */
+
 #ifdef CONFIG_SMP
 #define topology_physical_package_id(cpu)      (cpu_data(cpu).proc_id)
 #define topology_core_id(cpu)                  (cpu_data(cpu).core_id)
@@ -10,8 +81,6 @@
 #define smt_capable()                          (sparc64_multi_core)
 #endif /* CONFIG_SMP */
 
-#include <asm-generic/topology.h>
-
 #define cpu_coregroup_map(cpu)                 (cpu_core_map[cpu])
 
 #endif /* _ASM_SPARC64_TOPOLOGY_H */
index 7208a777750e77e624507f7ce4a53b5c44335c0d..d3cc4eff39a663984a73054caef84624f31fba36 100644 (file)
@@ -28,7 +28,7 @@
        call    routine;                                \
         add    %sp, PTREGS_OFF, %o0;                   \
        ba,pt   %xcc, rtrap;                            \
-        clr    %l6;                                    \
+        nop;                                           \
        nop;
 
 #define TRAP_7INSNS(routine)                           \
@@ -38,7 +38,7 @@
        call    routine;                                \
         add    %sp, PTREGS_OFF, %o0;                   \
        ba,pt   %xcc, rtrap;                            \
-        clr    %l6;
+        nop;
 
 #define TRAP_SAVEFPU(routine)                          \
        sethi   %hi(109f), %g7;                         \
@@ -47,7 +47,7 @@
        call    routine;                                \
         add    %sp, PTREGS_OFF, %o0;                   \
        ba,pt   %xcc, rtrap;                            \
-        clr    %l6;                                    \
+        nop;                                           \
        nop;
 
 #define TRAP_NOSAVE(routine)                           \
@@ -67,7 +67,7 @@
        call    routine;                                \
         add    %sp, PTREGS_OFF, %o0;                   \
        ba,pt   %xcc, rtrap;                            \
-        clr    %l6;                                    \
+        nop;                                           \
        nop;
        
 #define TRAP_ARG(routine, arg)                         \
@@ -78,7 +78,7 @@
        call    routine;                                \
         mov    arg, %o1;                               \
        ba,pt   %xcc, rtrap;                            \
-        clr    %l6;
+        nop;
        
 #define TRAPTL1_ARG(routine, arg)                      \
        sethi   %hi(109f), %g7;                         \
@@ -88,7 +88,7 @@
        call    routine;                                \
         mov    arg, %o1;                               \
        ba,pt   %xcc, rtrap;                            \
-        clr    %l6;
+        nop;
        
 #define SYSCALL_TRAP(routine, systbl)                  \
        sethi   %hi(109f), %g7;                         \
        ldx     [%sp + PTREGS_OFF + PT_V9_TNPC], %l1;                   \
        add     %l1, 4, %l2;                                            \
        stx     %l1, [%sp + PTREGS_OFF + PT_V9_TPC];                    \
-       ba,pt   %xcc, rtrap_clr_l6;                                     \
+       ba,pt   %xcc, rtrap;                                            \
         stx    %l2, [%sp + PTREGS_OFF + PT_V9_TNPC];
                
 #ifdef CONFIG_KPROBES
index 62ebdec394b96866d59f2d74e843721e9af052cf..1ebaa5cd31128eb40a7ca2c918aa17d7d8d8f244 100644 (file)
@@ -199,7 +199,6 @@ static inline int hard_smp_processor_id(void)
 #ifdef CONFIG_HOTPLUG_CPU
 extern void cpu_exit_clear(void);
 extern void cpu_uninit(void);
-extern void remove_siblinginfo(int cpu);
 #endif
 
 extern void smp_alloc_memory(void);
index 0434bd8349a7456f27f8ca95c18b472e07c1ba8e..d2d8eb5b55f532365f9277b5f776109626f7ed4b 100644 (file)
@@ -18,7 +18,6 @@ extern unsigned int cpu_khz;
 extern unsigned int tsc_khz;
 
 extern void disable_TSC(void);
-extern void enable_TSC(void);
 
 static inline cycles_t get_cycles(void)
 {
index c6a2353c4e68f2831db0007fcc9d9070da1202ae..402fb7a8d922531809a2b19a4ec1d590587e578f 100644 (file)
@@ -39,9 +39,10 @@ typedef enum
        DMX_OUT_DECODER, /* Streaming directly to decoder. */
        DMX_OUT_TAP,     /* Output going to a memory buffer */
                         /* (to be retrieved via the read command).*/
-       DMX_OUT_TS_TAP   /* Output multiplexed into a new TS  */
+       DMX_OUT_TS_TAP,  /* Output multiplexed into a new TS  */
                         /* (to be retrieved by reading from the */
                         /* logical DVR device).                 */
+       DMX_OUT_TSDEMUX_TAP /* Like TS_TAP but retrieved from the DMX device */
 } dmx_output_t;
 
 
index adcbb05b120b156758c4a8894990869ad473e103..de8387b7ceb6cd85ab872c3fe5e5f62c366af260 100644 (file)
@@ -43,7 +43,7 @@ struct fid {
                        u32 parent_ino;
                        u32 parent_gen;
                } i32;
-               __u32 raw[6];
+               __u32 raw[0];
        };
 };
 
index 96527f810d3496dbd055c770eed006e715926f02..57912590a7475dbd22d0ff33c09ee0983da97091 100644 (file)
 #define I2C_HW_B_CX2341X       0x010020 /* Conexant CX2341X MPEG encoder cards */
 #define I2C_HW_B_INTELFB       0x010021 /* intel framebuffer driver */
 #define I2C_HW_B_CX23885       0x010022 /* conexant 23885 based tv cards (bus1) */
+#define I2C_HW_B_AU0828                0x010023 /* auvitek au0828 usb bridge */
 
 /* --- PCF 8584 based algorithms                                       */
 #define I2C_HW_P_ELEK          0x020002 /* Elektor ISA Bus inteface card */
index f27d11ab418be8ff1255319c31c6e814e1504c22..529f301d9372d85ed588441894140edbd5d79321 100644 (file)
@@ -465,13 +465,19 @@ enum ieee80211_eid {
        WLAN_EID_TS_DELAY = 43,
        WLAN_EID_TCLAS_PROCESSING = 44,
        WLAN_EID_QOS_CAPA = 46,
-       /* 802.11s */
-       WLAN_EID_MESH_CONFIG = 36,      /* Pending IEEE 802.11 ANA approval */
-       WLAN_EID_MESH_ID = 37,          /* Pending IEEE 802.11 ANA approval */
-       WLAN_EID_PEER_LINK = 40,        /* Pending IEEE 802.11 ANA approval */
-       WLAN_EID_PREQ = 53,             /* Pending IEEE 802.11 ANA approval */
-       WLAN_EID_PREP = 54,             /* Pending IEEE 802.11 ANA approval */
-       WLAN_EID_PERR = 55,             /* Pending IEEE 802.11 ANA approval */
+       /* 802.11s
+        *
+        * All mesh EID numbers are pending IEEE 802.11 ANA approval.
+        * The numbers have been incremented from those suggested in
+        * 802.11s/D2.0 so that MESH_CONFIG does not conflict with
+        * EXT_SUPP_RATES.
+        */
+       WLAN_EID_MESH_CONFIG = 51,
+       WLAN_EID_MESH_ID = 52,
+       WLAN_EID_PEER_LINK = 55,
+       WLAN_EID_PREQ = 68,
+       WLAN_EID_PREP = 69,
+       WLAN_EID_PERR = 70,
        /* 802.11h */
        WLAN_EID_PWR_CONSTRAINT = 32,
        WLAN_EID_PWR_CAPABILITY = 33,
index 4babb2a129ac946decc0478dc6690a6818e3b0e4..94649a8da01403975c0c24e657f8062b9ec5dc80 100644 (file)
@@ -91,6 +91,7 @@ struct nlm_wait;
  */
 #define NLMCLNT_OHSIZE         ((__NEW_UTS_LEN) + 10u)
 struct nlm_rqst {
+       atomic_t                a_count;
        unsigned int            a_flags;        /* initial RPC task flags */
        struct nlm_host *       a_host;         /* host handle */
        struct nlm_args         a_args;         /* arguments */
@@ -173,8 +174,10 @@ void                 nlmclnt_next_cookie(struct nlm_cookie *);
 /*
  * Host cache
  */
-struct nlm_host  *nlmclnt_lookup_host(const struct sockaddr_in *, int, int,
-                                       const char *, unsigned int);
+struct nlm_host  *nlmclnt_lookup_host(const struct sockaddr_in *sin,
+                                       int proto, u32 version,
+                                       const char *hostname,
+                                       unsigned int hostname_len);
 struct nlm_host  *nlmsvc_lookup_host(struct svc_rqst *, const char *,
                                        unsigned int);
 struct rpc_clnt * nlm_bind_host(struct nlm_host *);
@@ -217,8 +220,7 @@ void                  nlmsvc_mark_resources(void);
 void             nlmsvc_free_host_resources(struct nlm_host *);
 void             nlmsvc_invalidate_all(void);
 
-static __inline__ struct inode *
-nlmsvc_file_inode(struct nlm_file *file)
+static inline struct inode *nlmsvc_file_inode(struct nlm_file *file)
 {
        return file->f_file->f_path.dentry->d_inode;
 }
@@ -226,8 +228,8 @@ nlmsvc_file_inode(struct nlm_file *file)
 /*
  * Compare two host addresses (needs modifying for ipv6)
  */
-static __inline__ int
-nlm_cmp_addr(const struct sockaddr_in *sin1, const struct sockaddr_in *sin2)
+static inline int nlm_cmp_addr(const struct sockaddr_in *sin1,
+                              const struct sockaddr_in *sin2)
 {
        return sin1->sin_addr.s_addr == sin2->sin_addr.s_addr;
 }
@@ -236,8 +238,8 @@ nlm_cmp_addr(const struct sockaddr_in *sin1, const struct sockaddr_in *sin2)
  * Compare two NLM locks.
  * When the second lock is of type F_UNLCK, this acts like a wildcard.
  */
-static __inline__ int
-nlm_compare_locks(const struct file_lock *fl1, const struct file_lock *fl2)
+static inline int nlm_compare_locks(const struct file_lock *fl1,
+                                   const struct file_lock *fl2)
 {
        return  fl1->fl_pid   == fl2->fl_pid
             && fl1->fl_owner == fl2->fl_owner
index 22a645828f268e5639ae73fec10494ed21ecd05c..5a5448bdb17d129da806dd95e0033995eaf63895 100644 (file)
@@ -19,6 +19,7 @@
 #define SM_NOTIFY      6
 
 #define SM_MAXSTRLEN   1024
+#define SM_PRIV_SIZE   16
 
 /*
  * Arguments for all calls to statd
index 39fd9c8ddd4b27b2adcf14659e5b4477a3ba8194..12010ace1f04abd1d556cdb3b9e4935a0d697af7 100644 (file)
@@ -58,7 +58,7 @@ struct meye_params {
 
 /* V4L2 private controls */
 #define V4L2_CID_AGC           V4L2_CID_PRIVATE_BASE
-#define V4L2_CID_SHARPNESS     (V4L2_CID_PRIVATE_BASE + 1)
+#define V4L2_CID_MEYE_SHARPNESS        (V4L2_CID_PRIVATE_BASE + 1)
 #define V4L2_CID_PICTURE       (V4L2_CID_PRIVATE_BASE + 2)
 #define V4L2_CID_JPEGQUAL      (V4L2_CID_PRIVATE_BASE + 3)
 #define V4L2_CID_FRAMERATE     (V4L2_CID_PRIVATE_BASE + 4)
index 7f11fa589207408d908d5628176de2810dbfedcc..539f3b550eab3a0b328610d9d00e09332bb07632 100644 (file)
@@ -96,7 +96,7 @@ struct nfs3_fh {
 #define MOUNTPROC3_UMNTALL     4
  
 
-#if defined(__KERNEL__) || defined(NFS_NEED_KERNEL_TYPES)
+#if defined(__KERNEL__)
 
 /* Number of 32bit words in post_op_attr */
 #define NFS3_POST_OP_ATTR_WORDS                22
index f4a0e4c218df0411fb358d2d2dad5e5d8a53baec..27d6a8d98cef02477abf89c69337a1f77fbc208b 100644 (file)
@@ -430,7 +430,6 @@ extern void nfs_unregister_sysctl(void);
 /*
  * linux/fs/nfs/namespace.c
  */
-extern struct list_head nfs_automount_list;
 extern const struct inode_operations nfs_mountpoint_inode_operations;
 extern const struct inode_operations nfs_referral_inode_operations;
 extern int nfs_mountpoint_expiry_timeout;
@@ -466,9 +465,9 @@ extern int nfs_wb_page(struct inode *inode, struct page* page);
 extern int nfs_wb_page_cancel(struct inode *inode, struct page* page);
 #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
 extern int  nfs_commit_inode(struct inode *, int);
-extern struct nfs_write_data *nfs_commit_alloc(void);
+extern struct nfs_write_data *nfs_commitdata_alloc(void);
 extern void nfs_commit_free(struct nfs_write_data *wdata);
-extern void nfs_commit_release(void *wdata);
+extern void nfs_commitdata_release(void *wdata);
 #else
 static inline int
 nfs_commit_inode(struct inode *inode, int how)
index 3423c6761bf7b561ad1ea4f4f7fce48f6541137e..c9beacd16c0073545a3518bb3f1ccabacbf5d6cf 100644 (file)
@@ -32,6 +32,8 @@ struct nfs_client {
        const struct nfs_rpc_ops *rpc_ops;      /* NFS protocol vector */
        int                     cl_proto;       /* Network transport protocol */
 
+       struct rpc_cred         *cl_machine_cred;
+
 #ifdef CONFIG_NFS_V4
        u64                     cl_clientid;    /* constant */
        nfs4_verifier           cl_confirm;
@@ -93,6 +95,7 @@ struct nfs_server {
        unsigned int            wpages;         /* write size (in pages) */
        unsigned int            wtmult;         /* server disk block size */
        unsigned int            dtsize;         /* readdir size */
+       unsigned short          port;           /* "port=" setting */
        unsigned int            bsize;          /* server block size */
        unsigned int            acregmin;       /* attr cache timeouts */
        unsigned int            acregmax;
@@ -117,6 +120,13 @@ struct nfs_server {
 
        atomic_t active; /* Keep trace of any activity to this server */
        wait_queue_head_t active_wq;  /* Wait for any activity to stop  */
+
+       /* mountd-related mount options */
+       struct sockaddr_storage mountd_address;
+       size_t                  mountd_addrlen;
+       u32                     mountd_version;
+       unsigned short          mountd_port;
+       unsigned short          mountd_protocol;
 };
 
 /* Server capabilities */
index f301d0b8babc99a94485e089cdfbca401c1407d8..24263bb8e0bebdc62892cdb6b1a2527e0a0023cc 100644 (file)
@@ -140,6 +140,7 @@ struct nfs_openres {
        __u32                   rflags;
        struct nfs_fattr *      f_attr;
        struct nfs_fattr *      dir_attr;
+       struct nfs_seqid *      seqid;
        const struct nfs_server *server;
        int                     delegation_type;
        nfs4_stateid            delegation;
@@ -159,6 +160,7 @@ struct nfs_open_confirmargs {
 
 struct nfs_open_confirmres {
        nfs4_stateid            stateid;
+       struct nfs_seqid *      seqid;
 };
 
 /*
@@ -175,6 +177,7 @@ struct nfs_closeargs {
 struct nfs_closeres {
        nfs4_stateid            stateid;
        struct nfs_fattr *      fattr;
+       struct nfs_seqid *      seqid;
        const struct nfs_server *server;
 };
 /*
@@ -199,7 +202,9 @@ struct nfs_lock_args {
 };
 
 struct nfs_lock_res {
-       nfs4_stateid                    stateid;
+       nfs4_stateid            stateid;
+       struct nfs_seqid *      lock_seqid;
+       struct nfs_seqid *      open_seqid;
 };
 
 struct nfs_locku_args {
@@ -210,7 +215,8 @@ struct nfs_locku_args {
 };
 
 struct nfs_locku_res {
-       nfs4_stateid                    stateid;
+       nfs4_stateid            stateid;
+       struct nfs_seqid *      seqid;
 };
 
 struct nfs_lockt_args {
index e726fc3a4375f5948d395e6756e10bca0673d9b6..fc972048e572d42656d4af8b845a88ca9cf4aa04 100644 (file)
@@ -1,6 +1,6 @@
 unifdef-y += const.h
+unifdef-y += debug.h
 unifdef-y += export.h
+unifdef-y += nfsfh.h
 unifdef-y += stats.h
 unifdef-y += syscall.h
-unifdef-y += nfsfh.h
-unifdef-y += debug.h
index 7b5d784cc8587cd80c8bd31125f56a793ebae253..04b355c801d83fa1f537cb6fa596b3649220f071 100644 (file)
@@ -10,7 +10,6 @@
 #ifndef NFSCACHE_H
 #define NFSCACHE_H
 
-#ifdef __KERNEL__
 #include <linux/in.h>
 #include <linux/uio.h>
 
@@ -77,5 +76,4 @@ void  nfsd_reply_cache_shutdown(void);
 int    nfsd_cache_lookup(struct svc_rqst *, int);
 void   nfsd_cache_update(struct svc_rqst *, int, __be32 *);
 
-#endif /* __KERNEL__ */
 #endif /* NFSCACHE_H */
index 8caf4c4f64e68df30c686a396d60252e63915319..21ee440dd3e768eb2bbb1e72f3a33d54c31b69da 100644 (file)
@@ -27,7 +27,6 @@
 #define NFSD_VERSION           "0.5"
 #define NFSD_SUPPORTED_MINOR_VERSION   0
 
-#ifdef __KERNEL__
 /*
  * Special flags for nfsd_permission. These must be different from MAY_READ,
  * MAY_WRITE, and MAY_EXEC.
@@ -56,12 +55,20 @@ extern struct svc_program   nfsd_program;
 extern struct svc_version      nfsd_version2, nfsd_version3,
                                nfsd_version4;
 extern struct svc_serv         *nfsd_serv;
+
+extern struct seq_operations nfs_exports_op;
+
 /*
  * Function prototypes.
  */
 int            nfsd_svc(unsigned short port, int nrservs);
 int            nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp);
 
+int            nfsd_nrthreads(void);
+int            nfsd_nrpools(void);
+int            nfsd_get_nrthreads(int n, int *);
+int            nfsd_set_nrthreads(int n, int *);
+
 /* nfsd/vfs.c */
 int            fh_lock_parent(struct svc_fh *, struct dentry *);
 int            nfsd_racache_init(int);
@@ -326,6 +333,4 @@ extern struct timeval       nfssvc_boot;
 
 #endif /* CONFIG_NFSD_V4 */
 
-#endif /* __KERNEL__ */
-
 #endif /* LINUX_NFSD_NFSD_H */
index b9e174079002300dee538600e8e6e5585757aed8..44c81c74453816b77208edb22c8d1507f83720f0 100644 (file)
@@ -740,13 +740,13 @@ extern void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change);
 extern void rtnl_lock(void);
 extern void rtnl_unlock(void);
 extern int rtnl_trylock(void);
+extern int rtnl_is_locked(void);
 
 extern void rtnetlink_init(void);
 extern void __rtnl_unlock(void);
 
 #define ASSERT_RTNL() do { \
-       if (unlikely(rtnl_trylock())) { \
-               rtnl_unlock(); \
+       if (unlikely(!rtnl_is_locked())) { \
                printk(KERN_ERR "RTNL: assertion failed at %s (%d)\n", \
                       __FILE__,  __LINE__); \
                dump_stack(); \
index 7a69ca3bebaf8cc33fcd1542d7a8e900774f50aa..3f632182d8eb03e966530c04fdb7a675e2cc08c7 100644 (file)
@@ -26,6 +26,7 @@ struct auth_cred {
        uid_t   uid;
        gid_t   gid;
        struct group_info *group_info;
+       unsigned char machine_cred : 1;
 };
 
 /*
@@ -59,8 +60,8 @@ struct rpc_cred {
 /*
  * Client authentication handle
  */
-#define RPC_CREDCACHE_NR       8
-#define RPC_CREDCACHE_MASK     (RPC_CREDCACHE_NR - 1)
+#define RPC_CREDCACHE_HASHBITS 4
+#define RPC_CREDCACHE_NR       (1 << RPC_CREDCACHE_HASHBITS)
 struct rpc_cred_cache {
        struct hlist_head       hashtable[RPC_CREDCACHE_NR];
        spinlock_t              lock;
@@ -89,7 +90,6 @@ struct rpc_auth {
 
 /* Flags for rpcauth_lookupcred() */
 #define RPCAUTH_LOOKUP_NEW             0x01    /* Accept an uninitialised cred */
-#define RPCAUTH_LOOKUP_ROOTCREDS       0x02    /* This really ought to go! */
 
 /*
  * Client authentication ops
@@ -97,9 +97,7 @@ struct rpc_auth {
 struct rpc_authops {
        struct module           *owner;
        rpc_authflavor_t        au_flavor;      /* flavor (RPC_AUTH_*) */
-#ifdef RPC_DEBUG
        char *                  au_name;
-#endif
        struct rpc_auth *       (*create)(struct rpc_clnt *, rpc_authflavor_t);
        void                    (*destroy)(struct rpc_auth *);
 
@@ -113,6 +111,7 @@ struct rpc_credops {
        void                    (*crdestroy)(struct rpc_cred *);
 
        int                     (*crmatch)(struct auth_cred *, struct rpc_cred *, int);
+       void                    (*crbind)(struct rpc_task *, struct rpc_cred *);
        __be32 *                (*crmarshal)(struct rpc_task *, __be32 *);
        int                     (*crrefresh)(struct rpc_task *);
        __be32 *                (*crvalidate)(struct rpc_task *, __be32 *);
@@ -126,9 +125,13 @@ extern const struct rpc_authops    authunix_ops;
 extern const struct rpc_authops        authnull_ops;
 
 void __init            rpc_init_authunix(void);
+void __init            rpc_init_generic_auth(void);
 void __init            rpcauth_init_module(void);
 void __exit            rpcauth_remove_module(void);
+void __exit            rpc_destroy_generic_auth(void);
 
+struct rpc_cred *      rpc_lookup_cred(void);
+struct rpc_cred *      rpc_lookup_machine_cred(void);
 int                    rpcauth_register(const struct rpc_authops *);
 int                    rpcauth_unregister(const struct rpc_authops *);
 struct rpc_auth *      rpcauth_create(rpc_authflavor_t, struct rpc_clnt *);
@@ -136,8 +139,8 @@ void                        rpcauth_release(struct rpc_auth *);
 struct rpc_cred *      rpcauth_lookup_credcache(struct rpc_auth *, struct auth_cred *, int);
 void                   rpcauth_init_cred(struct rpc_cred *, const struct auth_cred *, struct rpc_auth *, const struct rpc_credops *);
 struct rpc_cred *      rpcauth_lookupcred(struct rpc_auth *, int);
-struct rpc_cred *      rpcauth_bindcred(struct rpc_task *);
-void                   rpcauth_holdcred(struct rpc_task *);
+void                   rpcauth_bindcred(struct rpc_task *, struct rpc_cred *, int);
+void                   rpcauth_generic_bind_cred(struct rpc_task *, struct rpc_cred *);
 void                   put_rpccred(struct rpc_cred *);
 void                   rpcauth_unbindcred(struct rpc_task *);
 __be32 *               rpcauth_marshcred(struct rpc_task *, __be32 *);
index 67658e17a375194fd2e18753a7323e0ac1f2cbb6..fec6899bf3553f564bd148c72d54689a77a72f1a 100644 (file)
@@ -84,6 +84,7 @@ struct gss_cred {
        enum rpc_gss_svc        gc_service;
        struct gss_cl_ctx       *gc_ctx;
        struct gss_upcall_msg   *gc_upcall;
+       unsigned char           gc_machine_cred : 1;
 };
 
 #endif /* __KERNEL__ */
index 03547d6abee50be5c73373dd14b6811700655b59..2d8b211b9324a2bed283048161472d57b13a5977 100644 (file)
@@ -120,7 +120,6 @@ struct cache_deferred_req {
        struct list_head        hash;   /* on hash chain */
        struct list_head        recent; /* on fifo */
        struct cache_head       *item;  /* cache item we wait on */
-       time_t                  recv_time;
        void                    *owner; /* we might need to discard all defered requests
                                         * owned by someone */
        void                    (*revisit)(struct cache_deferred_req *req,
index 129a86e25d2989df395e29913fe4322b614701c7..6fff7f82ef1275e70495493759cc56019951f1ad 100644 (file)
@@ -127,11 +127,12 @@ int               rpcb_getport_sync(struct sockaddr_in *, u32, u32, int);
 void           rpcb_getport_async(struct rpc_task *);
 
 void           rpc_call_start(struct rpc_task *);
-int            rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg,
-                              int flags, const struct rpc_call_ops *tk_ops,
+int            rpc_call_async(struct rpc_clnt *clnt,
+                              const struct rpc_message *msg, int flags,
+                              const struct rpc_call_ops *tk_ops,
                               void *calldata);
-int            rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg,
-                             int flags);
+int            rpc_call_sync(struct rpc_clnt *clnt,
+                             const struct rpc_message *msg, int flags);
 struct rpc_task *rpc_call_null(struct rpc_clnt *clnt, struct rpc_cred *cred,
                               int flags);
 void           rpc_restart_call(struct rpc_task *);
index 5a4b1e0206e3a8afff8bf8f7a7fc00051f121ba0..a10f1fb0bf7c45dc4998112096b4d1ebb86a105a 100644 (file)
@@ -70,8 +70,6 @@ enum seal_alg {
        SEAL_ALG_DES3KD = 0x0002
 };
 
-#define KRB5_CKSUM_LENGTH 8
-
 #define CKSUMTYPE_CRC32                        0x0001
 #define CKSUMTYPE_RSA_MD4              0x0002
 #define CKSUMTYPE_RSA_MD4_DES          0x0003
@@ -150,9 +148,9 @@ gss_decrypt_xdr_buf(struct crypto_blkcipher *tfm, struct xdr_buf *inbuf,
 s32
 krb5_make_seq_num(struct crypto_blkcipher *key,
                int direction,
-               s32 seqnum, unsigned char *cksum, unsigned char *buf);
+               u32 seqnum, unsigned char *cksum, unsigned char *buf);
 
 s32
 krb5_get_seq_num(struct crypto_blkcipher *key,
               unsigned char *cksum,
-              unsigned char *buf, int *direction, s32 * seqnum);
+              unsigned char *buf, int *direction, u32 *seqnum);
index f689f02e6793de2aa6ee21d9a3054af669714cb1..d1a5c8c1a0f1ceef22eba19980667052bfedf10e 100644 (file)
@@ -11,7 +11,6 @@
 
 #include <linux/timer.h>
 #include <linux/sunrpc/types.h>
-#include <linux/rcupdate.h>
 #include <linux/spinlock.h>
 #include <linux/wait.h>
 #include <linux/workqueue.h>
@@ -33,7 +32,8 @@ struct rpc_wait_queue;
 struct rpc_wait {
        struct list_head        list;           /* wait queue links */
        struct list_head        links;          /* Links to related tasks */
-       struct rpc_wait_queue * rpc_waitq;      /* RPC wait queue we're on */
+       struct list_head        timer_list;     /* Timer list */
+       unsigned long           expires;
 };
 
 /*
@@ -57,33 +57,25 @@ struct rpc_task {
        __u8                    tk_cred_retry;
 
        /*
-        * timeout_fn   to be executed by timer bottom half
         * callback     to be executed after waking up
         * action       next procedure for async tasks
         * tk_ops       caller callbacks
         */
-       void                    (*tk_timeout_fn)(struct rpc_task *);
        void                    (*tk_callback)(struct rpc_task *);
        void                    (*tk_action)(struct rpc_task *);
        const struct rpc_call_ops *tk_ops;
        void *                  tk_calldata;
 
-       /*
-        * tk_timer is used for async processing by the RPC scheduling
-        * primitives. You should not access this directly unless
-        * you have a pathological interest in kernel oopses.
-        */
-       struct timer_list       tk_timer;       /* kernel timer */
        unsigned long           tk_timeout;     /* timeout for rpc_sleep() */
        unsigned short          tk_flags;       /* misc flags */
        unsigned long           tk_runstate;    /* Task run status */
        struct workqueue_struct *tk_workqueue;  /* Normally rpciod, but could
                                                 * be any workqueue
                                                 */
+       struct rpc_wait_queue   *tk_waitqueue;  /* RPC wait queue we're on */
        union {
                struct work_struct      tk_work;        /* Async task work queue */
                struct rpc_wait         tk_wait;        /* RPC wait */
-               struct rcu_head         tk_rcu;         /* for task deletion */
        } u;
 
        unsigned short          tk_timeouts;    /* maj timeouts */
@@ -123,6 +115,7 @@ struct rpc_task_setup {
        const struct rpc_message *rpc_message;
        const struct rpc_call_ops *callback_ops;
        void *callback_data;
+       struct workqueue_struct *workqueue;
        unsigned short flags;
        signed char priority;
 };
@@ -147,9 +140,7 @@ struct rpc_task_setup {
 
 #define RPC_TASK_RUNNING       0
 #define RPC_TASK_QUEUED                1
-#define RPC_TASK_WAKEUP                2
-#define RPC_TASK_HAS_TIMER     3
-#define RPC_TASK_ACTIVE                4
+#define RPC_TASK_ACTIVE                2
 
 #define RPC_IS_RUNNING(t)      test_bit(RPC_TASK_RUNNING, &(t)->tk_runstate)
 #define rpc_set_running(t)     set_bit(RPC_TASK_RUNNING, &(t)->tk_runstate)
@@ -171,15 +162,6 @@ struct rpc_task_setup {
                smp_mb__after_clear_bit(); \
        } while (0)
 
-#define rpc_start_wakeup(t) \
-       (test_and_set_bit(RPC_TASK_WAKEUP, &(t)->tk_runstate) == 0)
-#define rpc_finish_wakeup(t) \
-       do { \
-               smp_mb__before_clear_bit(); \
-               clear_bit(RPC_TASK_WAKEUP, &(t)->tk_runstate); \
-               smp_mb__after_clear_bit(); \
-       } while (0)
-
 #define RPC_IS_ACTIVATED(t)    test_bit(RPC_TASK_ACTIVE, &(t)->tk_runstate)
 
 /*
@@ -192,6 +174,12 @@ struct rpc_task_setup {
 #define RPC_PRIORITY_HIGH      (1)
 #define RPC_NR_PRIORITY                (1 + RPC_PRIORITY_HIGH - RPC_PRIORITY_LOW)
 
+struct rpc_timer {
+       struct timer_list timer;
+       struct list_head list;
+       unsigned long expires;
+};
+
 /*
  * RPC synchronization objects
  */
@@ -204,6 +192,7 @@ struct rpc_wait_queue {
        unsigned char           count;                  /* # task groups remaining serviced so far */
        unsigned char           nr;                     /* # tasks remaining for cookie */
        unsigned short          qlen;                   /* total # tasks waiting in queue */
+       struct rpc_timer        timer_list;
 #ifdef RPC_DEBUG
        const char *            name;
 #endif
@@ -229,9 +218,11 @@ void               rpc_killall_tasks(struct rpc_clnt *);
 void           rpc_execute(struct rpc_task *);
 void           rpc_init_priority_wait_queue(struct rpc_wait_queue *, const char *);
 void           rpc_init_wait_queue(struct rpc_wait_queue *, const char *);
+void           rpc_destroy_wait_queue(struct rpc_wait_queue *);
 void           rpc_sleep_on(struct rpc_wait_queue *, struct rpc_task *,
-                                       rpc_action action, rpc_action timer);
-void           rpc_wake_up_task(struct rpc_task *);
+                                       rpc_action action);
+void           rpc_wake_up_queued_task(struct rpc_wait_queue *,
+                                       struct rpc_task *);
 void           rpc_wake_up(struct rpc_wait_queue *);
 struct rpc_task *rpc_wake_up_next(struct rpc_wait_queue *);
 void           rpc_wake_up_status(struct rpc_wait_queue *, int);
index 64c97552964a42f523b5c3dcba8a149f5edd4b3e..4b54c5fdcfd928ef1407bf9eb76242b801394b51 100644 (file)
@@ -386,7 +386,6 @@ struct svc_serv *  svc_create(struct svc_program *, unsigned int,
                              void (*shutdown)(struct svc_serv*));
 struct svc_rqst *svc_prepare_thread(struct svc_serv *serv,
                                        struct svc_pool *pool);
-int               svc_create_thread(svc_thread_fn, struct svc_serv *);
 void              svc_exit_thread(struct svc_rqst *);
 struct svc_serv *  svc_create_pooled(struct svc_program *, unsigned int,
                        void (*shutdown)(struct svc_serv*),
index 22e1ef8e200e9634b91de1b33f8d729a2d565039..d39dbdc7b10f383332caf249c1872458c35562cd 100644 (file)
@@ -24,6 +24,7 @@ struct svc_cred {
 };
 
 struct svc_rqst;               /* forward decl */
+struct in6_addr;
 
 /* Authentication is done in the context of a domain.
  *
@@ -120,10 +121,10 @@ extern void       svc_auth_unregister(rpc_authflavor_t flavor);
 
 extern struct auth_domain *unix_domain_find(char *name);
 extern void auth_domain_put(struct auth_domain *item);
-extern int auth_unix_add_addr(struct in_addr addr, struct auth_domain *dom);
+extern int auth_unix_add_addr(struct in6_addr *addr, struct auth_domain *dom);
 extern struct auth_domain *auth_domain_lookup(char *name, struct auth_domain *new);
 extern struct auth_domain *auth_domain_find(char *name);
-extern struct auth_domain *auth_unix_lookup(struct in_addr addr);
+extern struct auth_domain *auth_unix_lookup(struct in6_addr *addr);
 extern int auth_unix_forget_old(struct auth_domain *dom);
 extern void svcauth_unix_purge(void);
 extern void svcauth_unix_info_release(void *);
index 206f092ad4c7dbd09a120352f538141ad9e58977..8cff696dedf58413dac70ab00294c19ba898bcba 100644 (file)
@@ -26,8 +26,8 @@ struct svc_sock {
        void                    (*sk_owspace)(struct sock *);
 
        /* private TCP part */
-       int                     sk_reclen;      /* length of record */
-       int                     sk_tcplen;      /* current read length */
+       u32                     sk_reclen;      /* length of record */
+       u32                     sk_tcplen;      /* current read length */
 };
 
 /*
index b3ff9a815e6fe5cf8627335ea9c65f4105115b33..4d80a118d5383d073d64609c84a91249921d236c 100644 (file)
@@ -86,6 +86,10 @@ struct rpc_rqst {
        unsigned long           rq_majortimeo;  /* major timeout alarm */
        unsigned long           rq_timeout;     /* Current timeout value */
        unsigned int            rq_retries;     /* # of retries */
+       unsigned int            rq_connect_cookie;
+                                               /* A cookie used to track the
+                                                  state of the transport
+                                                  connection */
        
        /*
         * Partial send handling
@@ -152,6 +156,9 @@ struct rpc_xprt {
        unsigned long           connect_timeout,
                                bind_timeout,
                                reestablish_timeout;
+       unsigned int            connect_cookie; /* A cookie that gets bumped
+                                                  every time the transport
+                                                  is reconnected */
 
        /*
         * Disconnection of idle transports
@@ -232,7 +239,7 @@ int                 xprt_unregister_transport(struct xprt_class *type);
 void                   xprt_set_retrans_timeout_def(struct rpc_task *task);
 void                   xprt_set_retrans_timeout_rtt(struct rpc_task *task);
 void                   xprt_wake_pending_tasks(struct rpc_xprt *xprt, int status);
-void                   xprt_wait_for_buffer_space(struct rpc_task *task);
+void                   xprt_wait_for_buffer_space(struct rpc_task *task, rpc_action action);
 void                   xprt_write_space(struct rpc_xprt *xprt);
 void                   xprt_update_rtt(struct rpc_task *task);
 void                   xprt_adjust_cwnd(struct rpc_task *task, int result);
@@ -241,6 +248,7 @@ void                        xprt_complete_rqst(struct rpc_task *task, int copied);
 void                   xprt_release_rqst_cong(struct rpc_task *task);
 void                   xprt_disconnect_done(struct rpc_xprt *xprt);
 void                   xprt_force_disconnect(struct rpc_xprt *xprt);
+void                   xprt_conditional_disconnect(struct rpc_xprt *xprt, unsigned int cookie);
 
 /*
  * Reserved bit positions in xprt->state
index 17a80177a674194460f389a331f2fead05a80818..c1411189ba6c5983f3396a60f801f21ee2688789 100644 (file)
@@ -282,6 +282,7 @@ struct v4l2_pix_format
 #define V4L2_PIX_FMT_BGR32   v4l2_fourcc('B','G','R','4') /* 32  BGR-8-8-8-8   */
 #define V4L2_PIX_FMT_RGB32   v4l2_fourcc('R','G','B','4') /* 32  RGB-8-8-8-8   */
 #define V4L2_PIX_FMT_GREY    v4l2_fourcc('G','R','E','Y') /*  8  Greyscale     */
+#define V4L2_PIX_FMT_Y16     v4l2_fourcc('Y','1','6',' ') /* 16  Greyscale     */
 #define V4L2_PIX_FMT_PAL8    v4l2_fourcc('P','A','L','8') /*  8  8-bit palette */
 #define V4L2_PIX_FMT_YVU410  v4l2_fourcc('Y','V','U','9') /*  9  YVU 4:1:0     */
 #define V4L2_PIX_FMT_YVU420  v4l2_fourcc('Y','V','1','2') /* 12  YVU 4:2:0     */
@@ -308,6 +309,7 @@ struct v4l2_pix_format
 
 /* see http://www.siliconimaging.com/RGB%20Bayer.htm */
 #define V4L2_PIX_FMT_SBGGR8  v4l2_fourcc('B','A','8','1') /*  8  BGBG.. GRGR.. */
+#define V4L2_PIX_FMT_SBGGR16 v4l2_fourcc('B','Y','R','2') /* 16  BGBG.. GRGR.. */
 
 /* compressed formats */
 #define V4L2_PIX_FMT_MJPEG    v4l2_fourcc('M','J','P','G') /* Motion-JPEG   */
@@ -793,6 +795,7 @@ struct v4l2_ext_controls
 /*  Values for ctrl_class field */
 #define V4L2_CTRL_CLASS_USER 0x00980000        /* Old-style 'user' controls */
 #define V4L2_CTRL_CLASS_MPEG 0x00990000        /* MPEG-compression controls */
+#define V4L2_CTRL_CLASS_CAMERA 0x009a0000      /* Camera class controls */
 
 #define V4L2_CTRL_ID_MASK                (0x0fffffff)
 #define V4L2_CTRL_ID2CLASS(id)    ((id) & 0x0fff0000UL)
@@ -849,21 +852,37 @@ struct v4l2_querymenu
 #define V4L2_CID_AUDIO_TREBLE          (V4L2_CID_BASE+8)
 #define V4L2_CID_AUDIO_MUTE            (V4L2_CID_BASE+9)
 #define V4L2_CID_AUDIO_LOUDNESS                (V4L2_CID_BASE+10)
-#define V4L2_CID_BLACK_LEVEL           (V4L2_CID_BASE+11)
+#define V4L2_CID_BLACK_LEVEL           (V4L2_CID_BASE+11) /* Deprecated */
 #define V4L2_CID_AUTO_WHITE_BALANCE    (V4L2_CID_BASE+12)
 #define V4L2_CID_DO_WHITE_BALANCE      (V4L2_CID_BASE+13)
 #define V4L2_CID_RED_BALANCE           (V4L2_CID_BASE+14)
 #define V4L2_CID_BLUE_BALANCE          (V4L2_CID_BASE+15)
 #define V4L2_CID_GAMMA                 (V4L2_CID_BASE+16)
-#define V4L2_CID_WHITENESS             (V4L2_CID_GAMMA) /* ? Not sure */
+#define V4L2_CID_WHITENESS             (V4L2_CID_GAMMA) /* Deprecated */
 #define V4L2_CID_EXPOSURE              (V4L2_CID_BASE+17)
 #define V4L2_CID_AUTOGAIN              (V4L2_CID_BASE+18)
 #define V4L2_CID_GAIN                  (V4L2_CID_BASE+19)
 #define V4L2_CID_HFLIP                 (V4L2_CID_BASE+20)
 #define V4L2_CID_VFLIP                 (V4L2_CID_BASE+21)
-#define V4L2_CID_HCENTER               (V4L2_CID_BASE+22)
-#define V4L2_CID_VCENTER               (V4L2_CID_BASE+23)
-#define V4L2_CID_LASTP1                        (V4L2_CID_BASE+24) /* last CID + 1 */
+
+/* Deprecated, use V4L2_CID_PAN_RESET and V4L2_CID_TILT_RESET */
+#define V4L2_CID_HCENTER_DEPRECATED    (V4L2_CID_BASE+22)
+#define V4L2_CID_VCENTER_DEPRECATED    (V4L2_CID_BASE+23)
+
+#define V4L2_CID_POWER_LINE_FREQUENCY  (V4L2_CID_BASE+24)
+enum v4l2_power_line_frequency {
+       V4L2_CID_POWER_LINE_FREQUENCY_DISABLED  = 0,
+       V4L2_CID_POWER_LINE_FREQUENCY_50HZ      = 1,
+       V4L2_CID_POWER_LINE_FREQUENCY_60HZ      = 2,
+};
+#define V4L2_CID_HUE_AUTO                      (V4L2_CID_BASE+25)
+#define V4L2_CID_WHITE_BALANCE_TEMPERATURE     (V4L2_CID_BASE+26)
+#define V4L2_CID_SHARPNESS                     (V4L2_CID_BASE+27)
+#define V4L2_CID_BACKLIGHT_COMPENSATION        (V4L2_CID_BASE+28)
+#define V4L2_CID_CHROMA_AGC                     (V4L2_CID_BASE+29)
+#define V4L2_CID_COLOR_KILLER                   (V4L2_CID_BASE+30)
+/* last CID + 1 */
+#define V4L2_CID_LASTP1                         (V4L2_CID_BASE+31)
 
 /*  MPEG-class control IDs defined by V4L2 */
 #define V4L2_CID_MPEG_BASE                     (V4L2_CTRL_CLASS_MPEG | 0x900)
@@ -1051,6 +1070,32 @@ enum v4l2_mpeg_cx2341x_video_median_filter_type {
 #define V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP   (V4L2_CID_MPEG_CX2341X_BASE+10)
 #define V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS        (V4L2_CID_MPEG_CX2341X_BASE+11)
 
+/*  Camera class control IDs */
+#define V4L2_CID_CAMERA_CLASS_BASE     (V4L2_CTRL_CLASS_CAMERA | 0x900)
+#define V4L2_CID_CAMERA_CLASS          (V4L2_CTRL_CLASS_CAMERA | 1)
+
+#define V4L2_CID_EXPOSURE_AUTO                 (V4L2_CID_CAMERA_CLASS_BASE+1)
+enum  v4l2_exposure_auto_type {
+       V4L2_EXPOSURE_AUTO = 0,
+       V4L2_EXPOSURE_MANUAL = 1,
+       V4L2_EXPOSURE_SHUTTER_PRIORITY = 2,
+       V4L2_EXPOSURE_APERTURE_PRIORITY = 3
+};
+#define V4L2_CID_EXPOSURE_ABSOLUTE             (V4L2_CID_CAMERA_CLASS_BASE+2)
+#define V4L2_CID_EXPOSURE_AUTO_PRIORITY                (V4L2_CID_CAMERA_CLASS_BASE+3)
+
+#define V4L2_CID_PAN_RELATIVE                  (V4L2_CID_CAMERA_CLASS_BASE+4)
+#define V4L2_CID_TILT_RELATIVE                 (V4L2_CID_CAMERA_CLASS_BASE+5)
+#define V4L2_CID_PAN_RESET                     (V4L2_CID_CAMERA_CLASS_BASE+6)
+#define V4L2_CID_TILT_RESET                    (V4L2_CID_CAMERA_CLASS_BASE+7)
+
+#define V4L2_CID_PAN_ABSOLUTE                  (V4L2_CID_CAMERA_CLASS_BASE+8)
+#define V4L2_CID_TILT_ABSOLUTE                 (V4L2_CID_CAMERA_CLASS_BASE+9)
+
+#define V4L2_CID_FOCUS_ABSOLUTE                        (V4L2_CID_CAMERA_CLASS_BASE+10)
+#define V4L2_CID_FOCUS_RELATIVE                        (V4L2_CID_CAMERA_CLASS_BASE+11)
+#define V4L2_CID_FOCUS_AUTO                    (V4L2_CID_CAMERA_CLASS_BASE+12)
+
 /*
  *     T U N I N G
  */
index a4274203f25298ca78aafece33c91bf8de40bfc5..bfee8be5d63fb6b69765535a8384e928017b8b40 100644 (file)
@@ -107,6 +107,7 @@ extern IR_KEYTAB_TYPE ir_codes_avermedia[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_avermedia_dvbt[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE];
+extern IR_KEYTAB_TYPE ir_codes_pixelview_new[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_nebula[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_dntv_live_dvb_t[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_iodata_bctv7e[IR_KEYTAB_SIZE];
@@ -141,8 +142,10 @@ extern IR_KEYTAB_TYPE ir_codes_encore_enltv[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_tt_1500[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_fusionhdtv_mce[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE];
+extern IR_KEYTAB_TYPE ir_codes_behold_columbus[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_pinnacle_pctv_hd[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_genius_tvgo_a11mce[IR_KEYTAB_SIZE];
+extern IR_KEYTAB_TYPE ir_codes_powercolor_real_angel[IR_KEYTAB_SIZE];
 
 #endif
 
diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h
new file mode 100644 (file)
index 0000000..6a8c8be
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * camera image capture (abstract) bus driver header
+ *
+ * Copyright (C) 2006, Sascha Hauer, Pengutronix
+ * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
+ *
+ * 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 SOC_CAMERA_H
+#define SOC_CAMERA_H
+
+#include <linux/videodev2.h>
+#include <media/videobuf-dma-sg.h>
+
+struct soc_camera_device {
+       struct list_head list;
+       struct device dev;
+       struct device *control;
+       unsigned short width;           /* Current window */
+       unsigned short height;          /* sizes */
+       unsigned short x_min;           /* Camera capabilities */
+       unsigned short y_min;
+       unsigned short x_current;       /* Current window location */
+       unsigned short y_current;
+       unsigned short width_min;
+       unsigned short width_max;
+       unsigned short height_min;
+       unsigned short height_max;
+       unsigned short y_skip_top;      /* Lines to skip at the top */
+       unsigned short gain;
+       unsigned short exposure;
+       unsigned char iface;            /* Host number */
+       unsigned char devnum;           /* Device number per host */
+       unsigned char buswidth;         /* See comment in .c */
+       struct soc_camera_ops *ops;
+       struct video_device *vdev;
+       const struct soc_camera_data_format *current_fmt;
+       const struct soc_camera_data_format *formats;
+       int num_formats;
+       struct module *owner;
+       /* soc_camera.c private count. Only accessed with video_lock held */
+       int use_count;
+};
+
+struct soc_camera_file {
+       struct soc_camera_device *icd;
+       struct videobuf_queue vb_vidq;
+       spinlock_t *lock;
+};
+
+struct soc_camera_host {
+       struct list_head list;
+       struct device dev;
+       unsigned char nr;                               /* Host number */
+       size_t msize;
+       struct videobuf_queue_ops *vbq_ops;
+       void *priv;
+       char *drv_name;
+       struct soc_camera_host_ops *ops;
+};
+
+struct soc_camera_host_ops {
+       struct module *owner;
+       int (*add)(struct soc_camera_device *);
+       void (*remove)(struct soc_camera_device *);
+       int (*set_fmt_cap)(struct soc_camera_device *, __u32,
+                          struct v4l2_rect *);
+       int (*try_fmt_cap)(struct soc_camera_device *, struct v4l2_format *);
+       int (*reqbufs)(struct soc_camera_file *, struct v4l2_requestbuffers *);
+       int (*querycap)(struct soc_camera_host *, struct v4l2_capability *);
+       int (*try_bus_param)(struct soc_camera_device *, __u32);
+       int (*set_bus_param)(struct soc_camera_device *, __u32);
+       unsigned int (*poll)(struct file *, poll_table *);
+       spinlock_t* (*spinlock_alloc)(struct soc_camera_file *);
+       void (*spinlock_free)(spinlock_t *);
+};
+
+struct soc_camera_link {
+       /* Camera bus id, used to match a camera and a bus */
+       int bus_id;
+       /* GPIO number to switch between 8 and 10 bit modes */
+       unsigned int gpio;
+};
+
+static inline struct soc_camera_device *to_soc_camera_dev(struct device *dev)
+{
+       return container_of(dev, struct soc_camera_device, dev);
+}
+
+static inline struct soc_camera_host *to_soc_camera_host(struct device *dev)
+{
+       return container_of(dev, struct soc_camera_host, dev);
+}
+
+extern int soc_camera_host_register(struct soc_camera_host *ici);
+extern void soc_camera_host_unregister(struct soc_camera_host *ici);
+extern int soc_camera_device_register(struct soc_camera_device *icd);
+extern void soc_camera_device_unregister(struct soc_camera_device *icd);
+
+extern int soc_camera_video_start(struct soc_camera_device *icd);
+extern void soc_camera_video_stop(struct soc_camera_device *icd);
+
+struct soc_camera_data_format {
+       char *name;
+       unsigned int depth;
+       __u32 fourcc;
+       enum v4l2_colorspace colorspace;
+};
+
+struct soc_camera_ops {
+       struct module *owner;
+       int (*probe)(struct soc_camera_device *);
+       void (*remove)(struct soc_camera_device *);
+       int (*init)(struct soc_camera_device *);
+       int (*release)(struct soc_camera_device *);
+       int (*start_capture)(struct soc_camera_device *);
+       int (*stop_capture)(struct soc_camera_device *);
+       int (*set_fmt_cap)(struct soc_camera_device *, __u32,
+                          struct v4l2_rect *);
+       int (*try_fmt_cap)(struct soc_camera_device *, struct v4l2_format *);
+       unsigned long (*query_bus_param)(struct soc_camera_device *);
+       int (*set_bus_param)(struct soc_camera_device *, unsigned long);
+       int (*get_chip_id)(struct soc_camera_device *,
+                          struct v4l2_chip_ident *);
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       int (*get_register)(struct soc_camera_device *, struct v4l2_register *);
+       int (*set_register)(struct soc_camera_device *, struct v4l2_register *);
+#endif
+       int (*get_control)(struct soc_camera_device *, struct v4l2_control *);
+       int (*set_control)(struct soc_camera_device *, struct v4l2_control *);
+       const struct v4l2_queryctrl *controls;
+       int num_controls;
+};
+
+static inline struct v4l2_queryctrl const *soc_camera_find_qctrl(
+       struct soc_camera_ops *ops, int id)
+{
+       int i;
+
+       for (i = 0; i < ops->num_controls; i++)
+               if (ops->controls[i].id == id)
+                       return &ops->controls[i];
+
+       return NULL;
+}
+
+#define SOCAM_MASTER                   (1 << 0)
+#define SOCAM_SLAVE                    (1 << 1)
+#define SOCAM_HSYNC_ACTIVE_HIGH                (1 << 2)
+#define SOCAM_HSYNC_ACTIVE_LOW         (1 << 3)
+#define SOCAM_VSYNC_ACTIVE_HIGH                (1 << 4)
+#define SOCAM_VSYNC_ACTIVE_LOW         (1 << 5)
+#define SOCAM_DATAWIDTH_8              (1 << 6)
+#define SOCAM_DATAWIDTH_9              (1 << 7)
+#define SOCAM_DATAWIDTH_10             (1 << 8)
+#define SOCAM_PCLK_SAMPLE_RISING       (1 << 9)
+#define SOCAM_PCLK_SAMPLE_FALLING      (1 << 10)
+
+#define SOCAM_DATAWIDTH_MASK (SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_9 | \
+                             SOCAM_DATAWIDTH_10)
+
+static inline unsigned long soc_camera_bus_param_compatible(
+                       unsigned long camera_flags, unsigned long bus_flags)
+{
+       unsigned long common_flags, hsync, vsync, pclk;
+
+       common_flags = camera_flags & bus_flags;
+
+       hsync = common_flags & (SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW);
+       vsync = common_flags & (SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW);
+       pclk = common_flags & (SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING);
+
+       return (!hsync || !vsync || !pclk) ? 0 : common_flags;
+}
+
+#endif
index b201371416a0c793473b1fdd96dc9885f06746d5..ab03c5344209937818de9200a9f33b678e64c2c5 100644 (file)
@@ -6,10 +6,11 @@
 #define __TUNER_TYPES_H__
 
 enum param_type {
-       TUNER_PARAM_TYPE_RADIO, \
-       TUNER_PARAM_TYPE_PAL, \
-       TUNER_PARAM_TYPE_SECAM, \
-       TUNER_PARAM_TYPE_NTSC
+       TUNER_PARAM_TYPE_RADIO,
+       TUNER_PARAM_TYPE_PAL,
+       TUNER_PARAM_TYPE_SECAM,
+       TUNER_PARAM_TYPE_NTSC,
+       TUNER_PARAM_TYPE_DIGITAL,
 };
 
 struct tuner_range {
@@ -105,6 +106,7 @@ struct tuner_params {
           the SECAM-L/L' standards. Range: -16:+15 */
        signed int default_top_secam_high:5;
 
+       u16 iffreq;
 
        unsigned int count;
        struct tuner_range *ranges;
@@ -114,6 +116,13 @@ struct tunertype {
        char *name;
        unsigned int count;
        struct tuner_params *params;
+
+       u16 min;
+       u16 max;
+       u32 stepsize;
+
+       u8 *initdata;
+       u8 *sleepdata;
 };
 
 extern struct tunertype tuners[];
index 1bf24a6ed8f10e4fbc0bbb25ab04dda09a20fd83..77068fcc86bd9cb60a801732b24b67e28fc75103 100644 (file)
@@ -78,7 +78,7 @@
 
 #define TUNER_HITACHI_NTSC             40
 #define TUNER_PHILIPS_PAL_MK           41
-#define TUNER_PHILIPS_ATSC             42
+#define TUNER_PHILIPS_FCV1236D         42
 #define TUNER_PHILIPS_FM1236_MK3       43
 
 #define TUNER_PHILIPS_4IN1             44      /* ATI TV Wonder Pro - Conexant */
index 032bb75f69c2ea7b92be53f274a52799c20e43eb..0ea0bd85c0368543dae9bc754e7cd97dd50be61d 100644 (file)
@@ -153,6 +153,12 @@ enum {
        V4L2_IDENT_MSP4428G = 44287,
        V4L2_IDENT_MSP4448G = 44487,
        V4L2_IDENT_MSP4458G = 44587,
+
+       /* Micron CMOS sensor chips: 45000-45099 */
+       V4L2_IDENT_MT9M001C12ST         = 45000,
+       V4L2_IDENT_MT9M001C12STM        = 45005,
+       V4L2_IDENT_MT9V022IX7ATC        = 45010, /* No way to detect "normal" I77ATx */
+       V4L2_IDENT_MT9V022IX7ATM        = 45015, /* and "lead free" IA7ATx chips */
 };
 
 #endif
index f2114459995d94826b9530e3a4f9c6feea1e5b00..a807d2f86ee849a5201ebfffc3ea54ff5c66e32e 100644 (file)
@@ -318,6 +318,10 @@ struct video_device
        int (*vidioc_g_chip_ident)     (struct file *file, void *fh,
                                        struct v4l2_chip_ident *chip);
 
+       /* For other private ioctls */
+       int (*vidioc_default)          (struct file *file, void *fh,
+                                       int cmd, void *arg);
+
 
 #ifdef OBSOLETE_OWNER /* to be removed soon */
 /* obsolete -- fops->owner is used instead */
index 99033945cdee3790c45240ac0f43a2f61fdec749..5b39a22533fea113254186a9157c9b24f0be5bbf 100644 (file)
@@ -13,6 +13,9 @@
  * the Free Software Foundation; either version 2
  */
 
+#ifndef _VIDEOBUF_CORE_H
+#define _VIDEOBUF_CORE_H
+
 #include <linux/poll.h>
 #ifdef CONFIG_VIDEO_V4L1_COMPAT
 #include <linux/videodev.h>
@@ -123,7 +126,8 @@ struct videobuf_queue_ops {
 struct videobuf_qtype_ops {
        u32                     magic;
 
-       void* (*alloc)          (size_t size);
+       void *(*alloc)          (size_t size);
+       void *(*vmalloc)        (struct videobuf_buffer *buf);
        int (*iolock)           (struct videobuf_queue* q,
                                 struct videobuf_buffer *vb,
                                 struct v4l2_framebuffer *fbuf);
@@ -151,7 +155,9 @@ struct videobuf_qtype_ops {
 struct videobuf_queue {
        struct mutex               vb_lock;
        spinlock_t                 *irqlock;
-       void                       *dev; /* on pci, points to struct pci_dev */
+       struct device              *dev;
+
+       wait_queue_head_t          wait; /* wait if queue is empty */
 
        enum v4l2_buf_type         type;
        unsigned int               inputs; /* for V4L2_BUF_FLAG_INPUT */
@@ -183,9 +189,13 @@ int videobuf_iolock(struct videobuf_queue* q, struct videobuf_buffer *vb,
 
 void *videobuf_alloc(struct videobuf_queue* q);
 
+/* Used on videobuf-dvb */
+void *videobuf_queue_to_vmalloc (struct videobuf_queue* q,
+                                struct videobuf_buffer *buf);
+
 void videobuf_queue_core_init(struct videobuf_queue *q,
                         struct videobuf_queue_ops *ops,
-                        void *dev,
+                        struct device *dev,
                         spinlock_t *irqlock,
                         enum v4l2_buf_type type,
                         enum v4l2_field field,
@@ -231,10 +241,4 @@ int videobuf_mmap_free(struct videobuf_queue *q);
 int videobuf_mmap_mapper(struct videobuf_queue *q,
                         struct vm_area_struct *vma);
 
-/* --------------------------------------------------------------------- */
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
+#endif
index 38105031db23b0d89aaf7f838830e3fdab0efb4f..be8da269ee334c0fae41b01dc5def2877f63ed83 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * helper functions for PCI DMA video4linux capture buffers
+ * helper functions for SG DMA video4linux capture buffers
  *
  * The functions expect the hardware being able to scatter gatter
  * (i.e. the buffers are not linear in physical memory, but fragmented
@@ -68,9 +68,6 @@ struct videobuf_dmabuf {
        /* for kernel buffers */
        void                *vmalloc;
 
-       /* Stores the userspace pointer to vmalloc area */
-       void                *varea;
-
        /* for overlay buffers (pci-pci dma) */
        dma_addr_t          bus_addr;
 
@@ -81,7 +78,7 @@ struct videobuf_dmabuf {
        int                 direction;
 };
 
-struct videbuf_pci_sg_memory
+struct videobuf_dma_sg_memory
 {
        u32                 magic;
 
@@ -103,11 +100,11 @@ int videobuf_dma_sync(struct videobuf_queue* q,struct videobuf_dmabuf *dma);
 int videobuf_dma_unmap(struct videobuf_queue* q,struct videobuf_dmabuf *dma);
 struct videobuf_dmabuf *videobuf_to_dma (struct videobuf_buffer *buf);
 
-void *videobuf_pci_alloc (size_t size);
+void *videobuf_sg_alloc(size_t size);
 
-void videobuf_queue_pci_init(struct videobuf_queue* q,
+void videobuf_queue_sg_init(struct videobuf_queue* q,
                         struct videobuf_queue_ops *ops,
-                        void *dev,
+                        struct device *dev,
                         spinlock_t *irqlock,
                         enum v4l2_buf_type type,
                         enum v4l2_field field,
@@ -117,6 +114,6 @@ void videobuf_queue_pci_init(struct videobuf_queue* q,
        /*FIXME: these variants are used only on *-alsa code, where videobuf is
         * used without queue
         */
-int videobuf_pci_dma_map(struct pci_dev *pci,struct videobuf_dmabuf *dma);
-int videobuf_pci_dma_unmap(struct pci_dev *pci,struct videobuf_dmabuf *dma);
+int videobuf_sg_dma_map(struct device *dev, struct videobuf_dmabuf *dma);
+int videobuf_sg_dma_unmap(struct device *dev, struct videobuf_dmabuf *dma);
 
index 8233cafdeef6de74970ed18f752294e42005c525..b777486963292443ebd9ed9e07b732d34a997ffe 100644 (file)
@@ -27,7 +27,8 @@ struct videobuf_dvb {
 int videobuf_dvb_register(struct videobuf_dvb *dvb,
                          struct module *module,
                          void *adapter_priv,
-                         struct device *device);
+                         struct device *device,
+                         short *adapter_nr);
 void videobuf_dvb_unregister(struct videobuf_dvb *dvb);
 
 /*
index ec63ab0fab93eabc848f3d36690abc5a4c6b77c2..aed39460c154cf73a8d8ecb55fe5edd51dec35b9 100644 (file)
@@ -12,6 +12,8 @@
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2
  */
+#ifndef _VIDEOBUF_VMALLOC_H
+#define _VIDEOBUF_VMALLOC_H
 
 #include <media/videobuf-core.h>
 
@@ -39,3 +41,5 @@ void videobuf_queue_vmalloc_init(struct videobuf_queue* q,
 void *videobuf_to_vmalloc (struct videobuf_buffer *buf);
 
 void videobuf_vmalloc_free (struct videobuf_buffer *buf);
+
+#endif
index 49c48983019f89aac0f9732b83db492291515095..e0a612bc9c4ef8f5bdb1a3b70a1685b153ca38fa 100644 (file)
@@ -383,6 +383,15 @@ static inline int ipv6_addr_orchid(const struct in6_addr *a)
                == htonl(0x20010010));
 }
 
+static inline void ipv6_addr_set_v4mapped(const __be32 addr,
+                                         struct in6_addr *v4mapped)
+{
+       ipv6_addr_set(v4mapped,
+                       0, 0,
+                       htonl(0x0000FFFF),
+                       addr);
+}
+
 /*
  * find the first different bit between two addresses
  * length of address must be a multiple of 32bits
index 01480581f825c6886b990972104c7541dcc837a5..049edc5e6461a08ac13fadebfe1367275bd1a7a4 100644 (file)
 #define AC97_HAS_NO_TONE       (1<<16) /* no Tone volume */
 #define AC97_HAS_NO_STD_PCM    (1<<17) /* no standard AC97 PCM volume and mute */
 #define AC97_HAS_NO_AUX                (1<<18) /* no standard AC97 AUX volume and mute */
+#define AC97_HAS_8CH           (1<<19) /* supports 8-channel output */
 
 /* rates indexes */
 #define AC97_RATES_FRONT_DAC   0
index 4e80d3fe738130c7cefad9673c771a756df2de8b..d293d36a66b86760fae36591ac0c9dbf032720ba 100644 (file)
@@ -182,6 +182,7 @@ struct ak4114 {
        unsigned char rcs0;
        unsigned char rcs1;
        struct delayed_work work;
+       unsigned int check_flags;
        void *change_callback_private;
        void (*change_callback)(struct ak4114 *ak4114, unsigned char c0, unsigned char c1);
 };
index 6153b91cdc3ea4f71e79f9ea44a7550f4995b54b..891cf1aea8b139db918705149a9e7ffb25760fd5 100644 (file)
@@ -68,7 +68,7 @@ struct snd_akm4xxx {
        enum {
                SND_AK4524, SND_AK4528, SND_AK4529,
                SND_AK4355, SND_AK4358, SND_AK4381,
-               SND_AK5365, NON_AKM
+               SND_AK5365
        } type;
 
        /* (array) information of combined codecs */
index 024ce62f7d16799462fb8083f86d7f9643c71d4d..a6e0facf8a37ecf616910690c59f78a8eee7a03c 100644 (file)
 #define IEC958_AES3_CON_CLOCK_1000PPM  (0<<4)  /* 1000 ppm */
 #define IEC958_AES3_CON_CLOCK_50PPM    (1<<4)  /* 50 ppm */
 #define IEC958_AES3_CON_CLOCK_VARIABLE (2<<4)  /* variable pitch */
+#define IEC958_AES4_CON_MAX_WORDLEN_24 (1<<0)  /* 0 = 20-bit, 1 = 24-bit */
+#define IEC958_AES4_CON_WORDLEN                (7<<1)  /* mask - sample word length */
+#define IEC958_AES4_CON_WORDLEN_NOTID  (0<<1)  /* not indicated */
+#define IEC958_AES4_CON_WORDLEN_20_16  (1<<1)  /* 20-bit or 16-bit */
+#define IEC958_AES4_CON_WORDLEN_22_18  (2<<1)  /* 22-bit or 18-bit */
+#define IEC958_AES4_CON_WORDLEN_23_19  (4<<1)  /* 23-bit or 19-bit */
+#define IEC958_AES4_CON_WORDLEN_24_20  (5<<1)  /* 24-bit or 20-bit */
+#define IEC958_AES4_CON_WORDLEN_21_17  (6<<1)  /* 21-bit or 17-bit */
 
 /*****************************************************************************
  *                                                                           *
index e79baa63912f018ad2e600b5e9db893427dede9b..3dc1291f52db78e8f525801f1b79204180e91dbf 100644 (file)
@@ -169,4 +169,11 @@ int snd_ctl_boolean_mono_info(struct snd_kcontrol *kcontrol,
 int snd_ctl_boolean_stereo_info(struct snd_kcontrol *kcontrol,
                                struct snd_ctl_elem_info *uinfo);
 
+/*
+ * virtual master control
+ */
+struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
+                                                const unsigned int *tlv);
+int snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave);
+                     
 #endif /* __SOUND_CONTROL_H */
index 4fc0235ad78433a314f4b2f406a47d8e1c5827fc..695ee53488a382ab85d90f1deb5e3b83a5fe82e6 100644 (file)
@@ -277,8 +277,8 @@ int snd_minor_info_done(void);
 int snd_minor_info_oss_init(void);
 int snd_minor_info_oss_done(void);
 #else
-#define snd_minor_info_oss_init() /*NOP*/
-#define snd_minor_info_oss_done() /*NOP*/
+static inline int snd_minor_info_oss_init(void) { return 0; }
+static inline int snd_minor_info_oss_done(void) { return 0; }
 #endif
 
 /* memory.c */
@@ -310,7 +310,7 @@ int snd_card_file_add(struct snd_card *card, struct file *file);
 int snd_card_file_remove(struct snd_card *card, struct file *file);
 
 #ifndef snd_card_set_dev
-#define snd_card_set_dev(card,devptr) ((card)->dev = (devptr))
+#define snd_card_set_dev(card, devptr) ((card)->dev = (devptr))
 #endif
 
 /* device.c */
@@ -373,7 +373,7 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...)
  * snd_printd - debug printk
  * @fmt: format string
  *
- * Compiled only when Works like snd_printk() for debugging purpose.
+ * Works like snd_printk() for debugging purposes.
  * Ignored when CONFIG_SND_DEBUG is not set.
  */
 #define snd_printd(fmt, args...) \
@@ -417,7 +417,7 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...)
  * snd_printdd - debug printk
  * @format: format string
  *
- * Compiled only when Works like snd_printk() for debugging purpose.
+ * Works like snd_printk() for debugging purposes.
  * Ignored when CONFIG_SND_DEBUG_DETECT is not set.
  */
 #define snd_printdd(format, args...) snd_printk(format, ##args)
index d45218b44dfe590364acc94af00c039c32e15e30..68b634b75068bfe9e33573d6c1fe2d6f475a8b53 100644 (file)
@@ -102,6 +102,21 @@ struct snd_mpu401 {
 #define MPU401C(mpu) (mpu)->cport
 #define MPU401D(mpu) (mpu)->port
 
+/*
+ * control register bits
+ */
+/* read MPU401C() */
+#define MPU401_RX_EMPTY                0x80
+#define MPU401_TX_FULL         0x40
+
+/* write MPU401C() */
+#define MPU401_RESET           0xff
+#define MPU401_ENTER_UART      0x3f
+
+/* read MPU401D() */
+#define MPU401_ACK             0xfe
+
+
 /*
 
  */
index fac66c49445af8379faba913337002aa51e8d742..ed6fb2eb1eac210d8812bfe26016ff9dd2bbeab0 100644 (file)
@@ -1,3 +1,3 @@
 /* include/version.h.  Generated by alsa/ksync script.  */
-#define CONFIG_SND_VERSION "1.0.16rc2"
-#define CONFIG_SND_DATE " (Thu Jan 31 16:40:16 2008 UTC)"
+#define CONFIG_SND_VERSION "1.0.16"
+#define CONFIG_SND_DATE ""
index 896e2832099ea207b36c02af276a0fd2c15516ea..207147ab25e46a90cfa0d17bd703f352c56e2526 100644 (file)
--- a/lib/lmb.c
+++ b/lib/lmb.c
@@ -346,7 +346,7 @@ u64 __init __lmb_alloc_base(u64 size, u64 align, u64 max_addr)
                        if (j < 0) {
                                /* this area isn't reserved, take it */
                                if (lmb_add_region(&lmb.reserved, base,
-                                                  size) < 0)
+                                                  lmb_align_up(size, align)) < 0)
                                        return 0;
                                return base;
                        }
index bc39e417694a4dab95e9a463de3a1daef78558a0..cf857c4dc7b12ab6e0ca2d79d17a036844a8eb53 100644 (file)
@@ -82,6 +82,11 @@ int rtnl_trylock(void)
        return mutex_trylock(&rtnl_mutex);
 }
 
+int rtnl_is_locked(void)
+{
+       return mutex_is_locked(&rtnl_mutex);
+}
+
 static struct rtnl_link *rtnl_msg_handlers[NPROTO];
 
 static inline int rtm_msgindex(int msgtype)
@@ -1402,6 +1407,7 @@ EXPORT_SYMBOL(rtnetlink_put_metrics);
 EXPORT_SYMBOL(rtnl_lock);
 EXPORT_SYMBOL(rtnl_trylock);
 EXPORT_SYMBOL(rtnl_unlock);
+EXPORT_SYMBOL(rtnl_is_locked);
 EXPORT_SYMBOL(rtnl_unicast);
 EXPORT_SYMBOL(rtnl_notify);
 EXPORT_SYMBOL(rtnl_set_sk_err);
index 02088deb046193262b81342bcca1cd5f2bf88506..2e2fc3376ac99e876f2bfcad7d44188695c83034 100644 (file)
@@ -1003,7 +1003,7 @@ static unsigned fib_flag_trans(int type, __be32 mask, struct fib_info *fi)
 static int fib_seq_show(struct seq_file *seq, void *v)
 {
        struct fib_iter_state *iter;
-       char bf[128];
+       int len;
        __be32 prefix, mask;
        unsigned flags;
        struct fib_node *f;
@@ -1025,18 +1025,19 @@ static int fib_seq_show(struct seq_file *seq, void *v)
        mask    = FZ_MASK(iter->zone);
        flags   = fib_flag_trans(fa->fa_type, mask, fi);
        if (fi)
-               snprintf(bf, sizeof(bf),
-                        "%s\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u",
+               seq_printf(seq,
+                        "%s\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u%n",
                         fi->fib_dev ? fi->fib_dev->name : "*", prefix,
                         fi->fib_nh->nh_gw, flags, 0, 0, fi->fib_priority,
                         mask, (fi->fib_advmss ? fi->fib_advmss + 40 : 0),
                         fi->fib_window,
-                        fi->fib_rtt >> 3);
+                        fi->fib_rtt >> 3, &len);
        else
-               snprintf(bf, sizeof(bf),
-                        "*\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u",
-                        prefix, 0, flags, 0, 0, 0, mask, 0, 0, 0);
-       seq_printf(seq, "%-127s\n", bf);
+               seq_printf(seq,
+                        "*\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u%n",
+                        prefix, 0, flags, 0, 0, 0, mask, 0, 0, 0, &len);
+
+       seq_printf(seq, "%*s\n", 127 - len, "");
 out:
        return 0;
 }
index ea294fffb9cef37c621fec8c9e14485d98475f83..4b02d14e7ab9685cece9fa1565e528132313eb26 100644 (file)
@@ -2602,15 +2602,16 @@ static int fib_route_seq_show(struct seq_file *seq, void *v)
                list_for_each_entry_rcu(fa, &li->falh, fa_list) {
                        const struct fib_info *fi = fa->fa_info;
                        unsigned flags = fib_flag_trans(fa->fa_type, mask, fi);
-                       char bf[128];
+                       int len;
 
                        if (fa->fa_type == RTN_BROADCAST
                            || fa->fa_type == RTN_MULTICAST)
                                continue;
 
                        if (fi)
-                               snprintf(bf, sizeof(bf),
-                                        "%s\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u",
+                               seq_printf(seq,
+                                        "%s\t%08X\t%08X\t%04X\t%d\t%u\t"
+                                        "%d\t%08X\t%d\t%u\t%u%n",
                                         fi->fib_dev ? fi->fib_dev->name : "*",
                                         prefix,
                                         fi->fib_nh->nh_gw, flags, 0, 0,
@@ -2619,14 +2620,15 @@ static int fib_route_seq_show(struct seq_file *seq, void *v)
                                         (fi->fib_advmss ?
                                          fi->fib_advmss + 40 : 0),
                                         fi->fib_window,
-                                        fi->fib_rtt >> 3);
+                                        fi->fib_rtt >> 3, &len);
                        else
-                               snprintf(bf, sizeof(bf),
-                                        "*\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u",
+                               seq_printf(seq,
+                                        "*\t%08X\t%08X\t%04X\t%d\t%u\t"
+                                        "%d\t%08X\t%d\t%u\t%u%n",
                                         prefix, 0, flags, 0, 0, 0,
-                                        mask, 0, 0, 0);
+                                        mask, 0, 0, 0, &len);
 
-                       seq_printf(seq, "%-127s\n", bf);
+                       seq_printf(seq, "%*s\n", 127 - len, "");
                }
        }
 
index 780e9484c825e96c9994bf7ea2ac8cb96026c400..ce25a13f3430b06f27445c8a3fa5e30c6a117baa 100644 (file)
@@ -367,10 +367,10 @@ static int rt_cache_seq_show(struct seq_file *seq, void *v)
                           "HHUptod\tSpecDst");
        else {
                struct rtable *r = v;
-               char temp[256];
+               int len;
 
-               sprintf(temp, "%s\t%08lX\t%08lX\t%8X\t%d\t%u\t%d\t"
-                             "%08lX\t%d\t%u\t%u\t%02X\t%d\t%1d\t%08X",
+               seq_printf(seq, "%s\t%08lX\t%08lX\t%8X\t%d\t%u\t%d\t"
+                             "%08lX\t%d\t%u\t%u\t%02X\t%d\t%1d\t%08X%n",
                        r->u.dst.dev ? r->u.dst.dev->name : "*",
                        (unsigned long)r->rt_dst, (unsigned long)r->rt_gateway,
                        r->rt_flags, atomic_read(&r->u.dst.__refcnt),
@@ -384,8 +384,9 @@ static int rt_cache_seq_show(struct seq_file *seq, void *v)
                        r->u.dst.hh ? atomic_read(&r->u.dst.hh->hh_refcnt) : -1,
                        r->u.dst.hh ? (r->u.dst.hh->hh_output ==
                                       dev_queue_xmit) : 0,
-                       r->rt_spec_dst);
-               seq_printf(seq, "%-127s\n", temp);
+                       r->rt_spec_dst, &len);
+
+               seq_printf(seq, "%*s\n", 127 - len, "");
        }
        return 0;
 }
index 776615180b93b3747d0c9207dde73bb8223c9503..0e9bc120707d469183facf86c33cf4b1b2446ce9 100644 (file)
@@ -2255,13 +2255,13 @@ void tcp_proc_unregister(struct net *net, struct tcp_seq_afinfo *afinfo)
 }
 
 static void get_openreq4(struct sock *sk, struct request_sock *req,
-                        char *tmpbuf, int i, int uid)
+                        struct seq_file *f, int i, int uid, int *len)
 {
        const struct inet_request_sock *ireq = inet_rsk(req);
        int ttd = req->expires - jiffies;
 
-       sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X"
-               " %02X %08X:%08X %02X:%08lX %08X %5d %8d %u %d %p",
+       seq_printf(f, "%4d: %08X:%04X %08X:%04X"
+               " %02X %08X:%08X %02X:%08lX %08X %5d %8d %u %d %p%n",
                i,
                ireq->loc_addr,
                ntohs(inet_sk(sk)->sport),
@@ -2276,10 +2276,11 @@ static void get_openreq4(struct sock *sk, struct request_sock *req,
                0,  /* non standard timer */
                0, /* open_requests have no inode */
                atomic_read(&sk->sk_refcnt),
-               req);
+               req,
+               len);
 }
 
-static void get_tcp4_sock(struct sock *sk, char *tmpbuf, int i)
+static void get_tcp4_sock(struct sock *sk, struct seq_file *f, int i, int *len)
 {
        int timer_active;
        unsigned long timer_expires;
@@ -2305,8 +2306,8 @@ static void get_tcp4_sock(struct sock *sk, char *tmpbuf, int i)
                timer_expires = jiffies;
        }
 
-       sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X %02X %08X:%08X %02X:%08lX "
-                       "%08X %5d %8d %lu %d %p %u %u %u %u %d",
+       seq_printf(f, "%4d: %08X:%04X %08X:%04X %02X %08X:%08X %02X:%08lX "
+                       "%08X %5d %8d %lu %d %p %u %u %u %u %d%n",
                i, src, srcp, dest, destp, sk->sk_state,
                tp->write_seq - tp->snd_una,
                sk->sk_state == TCP_LISTEN ? sk->sk_ack_backlog :
@@ -2322,11 +2323,12 @@ static void get_tcp4_sock(struct sock *sk, char *tmpbuf, int i)
                icsk->icsk_ack.ato,
                (icsk->icsk_ack.quick << 1) | icsk->icsk_ack.pingpong,
                tp->snd_cwnd,
-               tp->snd_ssthresh >= 0xFFFF ? -1 : tp->snd_ssthresh);
+               tp->snd_ssthresh >= 0xFFFF ? -1 : tp->snd_ssthresh,
+               len);
 }
 
 static void get_timewait4_sock(struct inet_timewait_sock *tw,
-                              char *tmpbuf, int i)
+                              struct seq_file *f, int i, int *len)
 {
        __be32 dest, src;
        __u16 destp, srcp;
@@ -2340,11 +2342,11 @@ static void get_timewait4_sock(struct inet_timewait_sock *tw,
        destp = ntohs(tw->tw_dport);
        srcp  = ntohs(tw->tw_sport);
 
-       sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X"
-               " %02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %p",
+       seq_printf(f, "%4d: %08X:%04X %08X:%04X"
+               " %02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %p%n",
                i, src, srcp, dest, destp, tw->tw_substate, 0, 0,
                3, jiffies_to_clock_t(ttd), 0, 0, 0, 0,
-               atomic_read(&tw->tw_refcnt), tw);
+               atomic_read(&tw->tw_refcnt), tw, len);
 }
 
 #define TMPSZ 150
@@ -2352,7 +2354,7 @@ static void get_timewait4_sock(struct inet_timewait_sock *tw,
 static int tcp4_seq_show(struct seq_file *seq, void *v)
 {
        struct tcp_iter_state* st;
-       char tmpbuf[TMPSZ + 1];
+       int len;
 
        if (v == SEQ_START_TOKEN) {
                seq_printf(seq, "%-*s\n", TMPSZ - 1,
@@ -2366,16 +2368,16 @@ static int tcp4_seq_show(struct seq_file *seq, void *v)
        switch (st->state) {
        case TCP_SEQ_STATE_LISTENING:
        case TCP_SEQ_STATE_ESTABLISHED:
-               get_tcp4_sock(v, tmpbuf, st->num);
+               get_tcp4_sock(v, seq, st->num, &len);
                break;
        case TCP_SEQ_STATE_OPENREQ:
-               get_openreq4(st->syn_wait_sk, v, tmpbuf, st->num, st->uid);
+               get_openreq4(st->syn_wait_sk, v, seq, st->num, st->uid, &len);
                break;
        case TCP_SEQ_STATE_TIME_WAIT:
-               get_timewait4_sock(v, tmpbuf, st->num);
+               get_timewait4_sock(v, seq, st->num, &len);
                break;
        }
-       seq_printf(seq, "%-*s\n", TMPSZ - 1, tmpbuf);
+       seq_printf(seq, "%*s\n", TMPSZ - 1 - len, "");
 out:
        return 0;
 }
index b053ac795275a56c7a88f89c5b9b748aa81acda3..1f535e315188858a4ec2f935efb431293d055dec 100644 (file)
@@ -1619,7 +1619,8 @@ void udp_proc_unregister(struct net *net, struct udp_seq_afinfo *afinfo)
 }
 
 /* ------------------------------------------------------------------------ */
-static void udp4_format_sock(struct sock *sp, char *tmpbuf, int bucket)
+static void udp4_format_sock(struct sock *sp, struct seq_file *f,
+               int bucket, int *len)
 {
        struct inet_sock *inet = inet_sk(sp);
        __be32 dest = inet->daddr;
@@ -1627,13 +1628,13 @@ static void udp4_format_sock(struct sock *sp, char *tmpbuf, int bucket)
        __u16 destp       = ntohs(inet->dport);
        __u16 srcp        = ntohs(inet->sport);
 
-       sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X"
-               " %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p",
+       seq_printf(f, "%4d: %08X:%04X %08X:%04X"
+               " %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p%n",
                bucket, src, srcp, dest, destp, sp->sk_state,
                atomic_read(&sp->sk_wmem_alloc),
                atomic_read(&sp->sk_rmem_alloc),
                0, 0L, 0, sock_i_uid(sp), 0, sock_i_ino(sp),
-               atomic_read(&sp->sk_refcnt), sp);
+               atomic_read(&sp->sk_refcnt), sp, len);
 }
 
 int udp4_seq_show(struct seq_file *seq, void *v)
@@ -1644,11 +1645,11 @@ int udp4_seq_show(struct seq_file *seq, void *v)
                           "rx_queue tr tm->when retrnsmt   uid  timeout "
                           "inode");
        else {
-               char tmpbuf[129];
                struct udp_iter_state *state = seq->private;
+               int len;
 
-               udp4_format_sock(v, tmpbuf, state->bucket);
-               seq_printf(seq, "%-127s\n", tmpbuf);
+               udp4_format_sock(v, seq, state->bucket, &len);
+               seq_printf(seq, "%*s\n", 127 - len ,"");
        }
        return 0;
 }
index 6b75cb6c63008370a081dfc68e1a892cdd02d0dd..a5e5c31c23abf3d23bca0d0ce9186e1776249215 100644 (file)
@@ -2248,10 +2248,13 @@ static void ieee80211_rx_bss_put(struct net_device *dev,
                                 struct ieee80211_sta_bss *bss)
 {
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-       if (!atomic_dec_and_test(&bss->users))
+
+       local_bh_disable();
+       if (!atomic_dec_and_lock(&bss->users, &local->sta_bss_lock)) {
+               local_bh_enable();
                return;
+       }
 
-       spin_lock_bh(&local->sta_bss_lock);
        __ieee80211_rx_bss_hash_del(dev, bss);
        list_del(&bss->list);
        spin_unlock_bh(&local->sta_bss_lock);
@@ -2709,7 +2712,26 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
                        bss->wmm_ie_len = elems.wmm_param_len + 2;
                } else
                        bss->wmm_ie_len = 0;
-       } else if (!elems.wmm_param && bss->wmm_ie) {
+       } else if (elems.wmm_info &&
+                   (!bss->wmm_ie || bss->wmm_ie_len != elems.wmm_info_len ||
+                    memcmp(bss->wmm_ie, elems.wmm_info, elems.wmm_info_len))) {
+                /* As for certain AP's Fifth bit is not set in WMM IE in
+                 * beacon frames.So while parsing the beacon frame the
+                 * wmm_info structure is used instead of wmm_param.
+                 * wmm_info structure was never used to set bss->wmm_ie.
+                 * This code fixes this problem by copying the WME
+                 * information from wmm_info to bss->wmm_ie and enabling
+                 * n-band association.
+                 */
+               kfree(bss->wmm_ie);
+               bss->wmm_ie = kmalloc(elems.wmm_info_len + 2, GFP_ATOMIC);
+               if (bss->wmm_ie) {
+                       memcpy(bss->wmm_ie, elems.wmm_info - 2,
+                              elems.wmm_info_len + 2);
+                       bss->wmm_ie_len = elems.wmm_info_len + 2;
+               } else
+                       bss->wmm_ie_len = 0;
+       } else if (!elems.wmm_param && !elems.wmm_info && bss->wmm_ie) {
                kfree(bss->wmm_ie);
                bss->wmm_ie = NULL;
                bss->wmm_ie_len = 0;
index 52e4554fdde7a292755b86ba381e9d94f694ac09..02f436a86061a33c99c3c38dc4787b03d27c6c39 100644 (file)
@@ -2170,7 +2170,7 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
        struct ieee80211_supported_band *sband;
 
        if (status->band < 0 ||
-           status->band > IEEE80211_NUM_BANDS) {
+           status->band >= IEEE80211_NUM_BANDS) {
                WARN_ON(1);
                return;
        }
index 4e94e4026e78c3103630bfa9f5a673735339edfd..64faa3dc488f70d2cfb09fae1bb1c3470424153e 100644 (file)
@@ -709,7 +709,7 @@ void ieee80211_requeue(struct ieee80211_local *local, int queue)
        struct ieee80211_sched_data *q = qdisc_priv(root_qd);
        struct Qdisc *qdisc = q->queues[queue];
        struct sk_buff *skb = NULL;
-       u32 len = qdisc->q.qlen;
+       u32 len;
 
        if (!qdisc || !qdisc->dequeue)
                return;
index 6d38a81b336d50e89942637f8ad8b715c2a0ae7f..ba3f6e49fddc59164fed12773b483ee699aa1a3d 100644 (file)
@@ -493,8 +493,8 @@ static int rxkad_verify_packet(const struct rxrpc_call *call,
                __be32 x[2];
        } tmpbuf __attribute__((aligned(8))); /* must all be in same page */
        __be32 x;
-       u16 y;
        __be16 cksum;
+       u32 y;
        int ret;
 
        sp = rxrpc_skb(skb);
index cfeb07ea1b046a814592207e1da3e6b3e387f498..f73ec0ea93ba374f6b15810abe6789828dafa0d4 100644 (file)
@@ -83,13 +83,12 @@ static sctp_dbg_objcnt_entry_t sctp_dbg_objcnt[] = {
  */
 static int sctp_objcnt_seq_show(struct seq_file *seq, void *v)
 {
-       int i;
-       char temp[128];
+       int i, len;
 
        i = (int)*(loff_t *)v;
-       sprintf(temp, "%s: %d", sctp_dbg_objcnt[i].label,
-                               atomic_read(sctp_dbg_objcnt[i].counter));
-       seq_printf(seq, "%-127s\n", temp);
+       seq_printf(seq, "%s: %d%n", sctp_dbg_objcnt[i].label,
+                               atomic_read(sctp_dbg_objcnt[i].counter), &len);
+       seq_printf(seq, "%*s\n", 127 - len, "");
        return 0;
 }
 
index 92e1dbe50947adb5d2612f1070362cc6f30d352e..5369aa369b353f9c32f10fcd0836b344353686d4 100644 (file)
@@ -8,7 +8,7 @@ obj-$(CONFIG_SUNRPC_GSS) += auth_gss/
 obj-$(CONFIG_SUNRPC_XPRT_RDMA) += xprtrdma/
 
 sunrpc-y := clnt.o xprt.o socklib.o xprtsock.o sched.o \
-           auth.o auth_null.o auth_unix.o \
+           auth.o auth_null.o auth_unix.o auth_generic.o \
            svc.o svcsock.o svcauth.o svcauth_unix.o \
            rpcb_clnt.o timer.o xdr.o \
            sunrpc_syms.o cache.o rpc_pipe.o \
index eca941ce298b6465507c2f672dc5bf44350fffe6..6bfea9ed6869f4142d356b468a70493817b233b7 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
+#include <linux/hash.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/spinlock.h>
 
@@ -219,6 +220,9 @@ rpcauth_destroy_credcache(struct rpc_auth *auth)
 }
 EXPORT_SYMBOL_GPL(rpcauth_destroy_credcache);
 
+
+#define RPC_AUTH_EXPIRY_MORATORIUM (60 * HZ)
+
 /*
  * Remove stale credentials. Avoid sleeping inside the loop.
  */
@@ -227,6 +231,7 @@ rpcauth_prune_expired(struct list_head *free, int nr_to_scan)
 {
        spinlock_t *cache_lock;
        struct rpc_cred *cred;
+       unsigned long expired = jiffies - RPC_AUTH_EXPIRY_MORATORIUM;
 
        while (!list_empty(&cred_unused)) {
                cred = list_entry(cred_unused.next, struct rpc_cred, cr_lru);
@@ -234,6 +239,10 @@ rpcauth_prune_expired(struct list_head *free, int nr_to_scan)
                number_cred_unused--;
                if (atomic_read(&cred->cr_count) != 0)
                        continue;
+               /* Enforce a 5 second garbage collection moratorium */
+               if (time_in_range(cred->cr_expire, expired, jiffies) &&
+                   test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) != 0)
+                       continue;
                cache_lock = &cred->cr_auth->au_credcache->lock;
                spin_lock(cache_lock);
                if (atomic_read(&cred->cr_count) == 0) {
@@ -280,10 +289,9 @@ rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred,
        struct hlist_node *pos;
        struct rpc_cred *cred = NULL,
                        *entry, *new;
-       int             nr = 0;
+       unsigned int nr;
 
-       if (!(flags & RPCAUTH_LOOKUP_ROOTCREDS))
-               nr = acred->uid & RPC_CREDCACHE_MASK;
+       nr = hash_long(acred->uid, RPC_CREDCACHE_HASHBITS);
 
        rcu_read_lock();
        hlist_for_each_entry_rcu(entry, pos, &cache->hashtable[nr], cr_hash) {
@@ -356,7 +364,6 @@ rpcauth_lookupcred(struct rpc_auth *auth, int flags)
        put_group_info(acred.group_info);
        return ret;
 }
-EXPORT_SYMBOL_GPL(rpcauth_lookupcred);
 
 void
 rpcauth_init_cred(struct rpc_cred *cred, const struct auth_cred *acred,
@@ -375,41 +382,58 @@ rpcauth_init_cred(struct rpc_cred *cred, const struct auth_cred *acred,
 }
 EXPORT_SYMBOL_GPL(rpcauth_init_cred);
 
-struct rpc_cred *
-rpcauth_bindcred(struct rpc_task *task)
+void
+rpcauth_generic_bind_cred(struct rpc_task *task, struct rpc_cred *cred)
+{
+       task->tk_msg.rpc_cred = get_rpccred(cred);
+       dprintk("RPC: %5u holding %s cred %p\n", task->tk_pid,
+                       cred->cr_auth->au_ops->au_name, cred);
+}
+EXPORT_SYMBOL_GPL(rpcauth_generic_bind_cred);
+
+static void
+rpcauth_bind_root_cred(struct rpc_task *task)
 {
        struct rpc_auth *auth = task->tk_client->cl_auth;
        struct auth_cred acred = {
-               .uid = current->fsuid,
-               .gid = current->fsgid,
-               .group_info = current->group_info,
+               .uid = 0,
+               .gid = 0,
        };
        struct rpc_cred *ret;
-       int flags = 0;
 
        dprintk("RPC: %5u looking up %s cred\n",
                task->tk_pid, task->tk_client->cl_auth->au_ops->au_name);
-       get_group_info(acred.group_info);
-       if (task->tk_flags & RPC_TASK_ROOTCREDS)
-               flags |= RPCAUTH_LOOKUP_ROOTCREDS;
-       ret = auth->au_ops->lookup_cred(auth, &acred, flags);
+       ret = auth->au_ops->lookup_cred(auth, &acred, 0);
+       if (!IS_ERR(ret))
+               task->tk_msg.rpc_cred = ret;
+       else
+               task->tk_status = PTR_ERR(ret);
+}
+
+static void
+rpcauth_bind_new_cred(struct rpc_task *task)
+{
+       struct rpc_auth *auth = task->tk_client->cl_auth;
+       struct rpc_cred *ret;
+
+       dprintk("RPC: %5u looking up %s cred\n",
+               task->tk_pid, auth->au_ops->au_name);
+       ret = rpcauth_lookupcred(auth, 0);
        if (!IS_ERR(ret))
                task->tk_msg.rpc_cred = ret;
        else
                task->tk_status = PTR_ERR(ret);
-       put_group_info(acred.group_info);
-       return ret;
 }
 
 void
-rpcauth_holdcred(struct rpc_task *task)
+rpcauth_bindcred(struct rpc_task *task, struct rpc_cred *cred, int flags)
 {
-       struct rpc_cred *cred = task->tk_msg.rpc_cred;
-       if (cred != NULL) {
-               get_rpccred(cred);
-               dprintk("RPC: %5u holding %s cred %p\n", task->tk_pid,
-                               cred->cr_auth->au_ops->au_name, cred);
-       }
+       if (cred != NULL)
+               cred->cr_ops->crbind(task, cred);
+       else if (flags & RPC_TASK_ROOTCREDS)
+               rpcauth_bind_root_cred(task);
+       else
+               rpcauth_bind_new_cred(task);
 }
 
 void
@@ -550,6 +574,7 @@ static struct shrinker rpc_cred_shrinker = {
 void __init rpcauth_init_module(void)
 {
        rpc_init_authunix();
+       rpc_init_generic_auth();
        register_shrinker(&rpc_cred_shrinker);
 }
 
diff --git a/net/sunrpc/auth_generic.c b/net/sunrpc/auth_generic.c
new file mode 100644 (file)
index 0000000..d927d9f
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * Generic RPC credential
+ *
+ * Copyright (C) 2008, Trond Myklebust <Trond.Myklebust@netapp.com>
+ */
+
+#include <linux/err.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/sunrpc/auth.h>
+#include <linux/sunrpc/clnt.h>
+#include <linux/sunrpc/debug.h>
+#include <linux/sunrpc/sched.h>
+
+#ifdef RPC_DEBUG
+# define RPCDBG_FACILITY       RPCDBG_AUTH
+#endif
+
+#define RPC_ANONYMOUS_USERID   ((uid_t)-2)
+#define RPC_ANONYMOUS_GROUPID  ((gid_t)-2)
+
+struct generic_cred {
+       struct rpc_cred gc_base;
+       struct auth_cred acred;
+};
+
+static struct rpc_auth generic_auth;
+static struct rpc_cred_cache generic_cred_cache;
+static const struct rpc_credops generic_credops;
+
+/*
+ * Public call interface
+ */
+struct rpc_cred *rpc_lookup_cred(void)
+{
+       return rpcauth_lookupcred(&generic_auth, 0);
+}
+EXPORT_SYMBOL_GPL(rpc_lookup_cred);
+
+/*
+ * Public call interface for looking up machine creds.
+ */
+struct rpc_cred *rpc_lookup_machine_cred(void)
+{
+       struct auth_cred acred = {
+               .uid = RPC_ANONYMOUS_USERID,
+               .gid = RPC_ANONYMOUS_GROUPID,
+               .machine_cred = 1,
+       };
+
+       dprintk("RPC:       looking up machine cred\n");
+       return generic_auth.au_ops->lookup_cred(&generic_auth, &acred, 0);
+}
+EXPORT_SYMBOL_GPL(rpc_lookup_machine_cred);
+
+static void
+generic_bind_cred(struct rpc_task *task, struct rpc_cred *cred)
+{
+       struct rpc_auth *auth = task->tk_client->cl_auth;
+       struct auth_cred *acred = &container_of(cred, struct generic_cred, gc_base)->acred;
+       struct rpc_cred *ret;
+
+       ret = auth->au_ops->lookup_cred(auth, acred, 0);
+       if (!IS_ERR(ret))
+               task->tk_msg.rpc_cred = ret;
+       else
+               task->tk_status = PTR_ERR(ret);
+}
+
+/*
+ * Lookup generic creds for current process
+ */
+static struct rpc_cred *
+generic_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
+{
+       return rpcauth_lookup_credcache(&generic_auth, acred, flags);
+}
+
+static struct rpc_cred *
+generic_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
+{
+       struct generic_cred *gcred;
+
+       gcred = kmalloc(sizeof(*gcred), GFP_KERNEL);
+       if (gcred == NULL)
+               return ERR_PTR(-ENOMEM);
+
+       rpcauth_init_cred(&gcred->gc_base, acred, &generic_auth, &generic_credops);
+       gcred->gc_base.cr_flags = 1UL << RPCAUTH_CRED_UPTODATE;
+
+       gcred->acred.uid = acred->uid;
+       gcred->acred.gid = acred->gid;
+       gcred->acred.group_info = acred->group_info;
+       if (gcred->acred.group_info != NULL)
+               get_group_info(gcred->acred.group_info);
+       gcred->acred.machine_cred = acred->machine_cred;
+
+       dprintk("RPC:       allocated %s cred %p for uid %d gid %d\n",
+                       gcred->acred.machine_cred ? "machine" : "generic",
+                       gcred, acred->uid, acred->gid);
+       return &gcred->gc_base;
+}
+
+static void
+generic_free_cred(struct rpc_cred *cred)
+{
+       struct generic_cred *gcred = container_of(cred, struct generic_cred, gc_base);
+
+       dprintk("RPC:       generic_free_cred %p\n", gcred);
+       if (gcred->acred.group_info != NULL)
+               put_group_info(gcred->acred.group_info);
+       kfree(gcred);
+}
+
+static void
+generic_free_cred_callback(struct rcu_head *head)
+{
+       struct rpc_cred *cred = container_of(head, struct rpc_cred, cr_rcu);
+       generic_free_cred(cred);
+}
+
+static void
+generic_destroy_cred(struct rpc_cred *cred)
+{
+       call_rcu(&cred->cr_rcu, generic_free_cred_callback);
+}
+
+/*
+ * Match credentials against current process creds.
+ */
+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);
+
+       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;
+       return 1;
+}
+
+void __init rpc_init_generic_auth(void)
+{
+       spin_lock_init(&generic_cred_cache.lock);
+}
+
+void __exit rpc_destroy_generic_auth(void)
+{
+       rpcauth_clear_credcache(&generic_cred_cache);
+}
+
+static struct rpc_cred_cache generic_cred_cache = {
+       {{ NULL, },},
+};
+
+static const struct rpc_authops generic_auth_ops = {
+       .owner = THIS_MODULE,
+       .au_name = "Generic",
+       .lookup_cred = generic_lookup_cred,
+       .crcreate = generic_create_cred,
+};
+
+static struct rpc_auth generic_auth = {
+       .au_ops = &generic_auth_ops,
+       .au_count = ATOMIC_INIT(0),
+       .au_credcache = &generic_cred_cache,
+};
+
+static const struct rpc_credops generic_credops = {
+       .cr_name = "Generic cred",
+       .crdestroy = generic_destroy_cred,
+       .crbind = generic_bind_cred,
+       .crmatch = generic_match,
+};
index 5828e5c060ca6f0fd7f8db305774261cd8d3e76e..cc12d5f5d5da57e61db43d1d11bf6e2498432970 100644 (file)
@@ -114,27 +114,14 @@ static void
 gss_cred_set_ctx(struct rpc_cred *cred, struct gss_cl_ctx *ctx)
 {
        struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base);
-       struct gss_cl_ctx *old;
 
-       old = gss_cred->gc_ctx;
+       if (!test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags))
+               return;
+       gss_get_ctx(ctx);
        rcu_assign_pointer(gss_cred->gc_ctx, ctx);
        set_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
+       smp_mb__before_clear_bit();
        clear_bit(RPCAUTH_CRED_NEW, &cred->cr_flags);
-       if (old)
-               gss_put_ctx(old);
-}
-
-static int
-gss_cred_is_uptodate_ctx(struct rpc_cred *cred)
-{
-       struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base);
-       int res = 0;
-
-       rcu_read_lock();
-       if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) && gss_cred->gc_ctx)
-               res = 1;
-       rcu_read_unlock();
-       return res;
 }
 
 static const void *
@@ -266,6 +253,7 @@ gss_release_msg(struct gss_upcall_msg *gss_msg)
        BUG_ON(!list_empty(&gss_msg->list));
        if (gss_msg->ctx != NULL)
                gss_put_ctx(gss_msg->ctx);
+       rpc_destroy_wait_queue(&gss_msg->rpc_waitqueue);
        kfree(gss_msg);
 }
 
@@ -339,7 +327,7 @@ gss_upcall_callback(struct rpc_task *task)
 
        spin_lock(&inode->i_lock);
        if (gss_msg->ctx)
-               gss_cred_set_ctx(task->tk_msg.rpc_cred, gss_get_ctx(gss_msg->ctx));
+               gss_cred_set_ctx(task->tk_msg.rpc_cred, gss_msg->ctx);
        else
                task->tk_status = gss_msg->msg.errno;
        gss_cred->gc_upcall = NULL;
@@ -370,9 +358,16 @@ gss_alloc_msg(struct gss_auth *gss_auth, uid_t uid)
 static struct gss_upcall_msg *
 gss_setup_upcall(struct rpc_clnt *clnt, struct gss_auth *gss_auth, struct rpc_cred *cred)
 {
+       struct gss_cred *gss_cred = container_of(cred,
+                       struct gss_cred, gc_base);
        struct gss_upcall_msg *gss_new, *gss_msg;
+       uid_t uid = cred->cr_uid;
 
-       gss_new = gss_alloc_msg(gss_auth, cred->cr_uid);
+       /* Special case: rpc.gssd assumes that uid == 0 implies machine creds */
+       if (gss_cred->gc_machine_cred != 0)
+               uid = 0;
+
+       gss_new = gss_alloc_msg(gss_auth, uid);
        if (gss_new == NULL)
                return ERR_PTR(-ENOMEM);
        gss_msg = gss_add_msg(gss_auth, gss_new);
@@ -408,13 +403,17 @@ gss_refresh_upcall(struct rpc_task *task)
        }
        spin_lock(&inode->i_lock);
        if (gss_cred->gc_upcall != NULL)
-               rpc_sleep_on(&gss_cred->gc_upcall->rpc_waitqueue, task, NULL, NULL);
-       else if (gss_msg->ctx == NULL && gss_msg->msg.errno >= 0) {
+               rpc_sleep_on(&gss_cred->gc_upcall->rpc_waitqueue, task, NULL);
+       else if (gss_msg->ctx != NULL) {
+               gss_cred_set_ctx(task->tk_msg.rpc_cred, gss_msg->ctx);
+               gss_cred->gc_upcall = NULL;
+               rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno);
+       } else if (gss_msg->msg.errno >= 0) {
                task->tk_timeout = 0;
                gss_cred->gc_upcall = gss_msg;
                /* gss_upcall_callback will release the reference to gss_upcall_msg */
                atomic_inc(&gss_msg->count);
-               rpc_sleep_on(&gss_msg->rpc_waitqueue, task, gss_upcall_callback, NULL);
+               rpc_sleep_on(&gss_msg->rpc_waitqueue, task, gss_upcall_callback);
        } else
                err = gss_msg->msg.errno;
        spin_unlock(&inode->i_lock);
@@ -454,7 +453,7 @@ gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred)
                schedule();
        }
        if (gss_msg->ctx)
-               gss_cred_set_ctx(cred, gss_get_ctx(gss_msg->ctx));
+               gss_cred_set_ctx(cred, gss_msg->ctx);
        else
                err = gss_msg->msg.errno;
        spin_unlock(&inode->i_lock);
@@ -709,7 +708,7 @@ gss_destroying_context(struct rpc_cred *cred)
        struct rpc_task *task;
 
        if (gss_cred->gc_ctx == NULL ||
-                       gss_cred->gc_ctx->gc_proc == RPC_GSS_PROC_DESTROY)
+           test_and_clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) == 0)
                return 0;
 
        gss_cred->gc_ctx->gc_proc = RPC_GSS_PROC_DESTROY;
@@ -719,7 +718,7 @@ gss_destroying_context(struct rpc_cred *cred)
         * by the RPC call or by the put_rpccred() below */
        get_rpccred(cred);
 
-       task = rpc_call_null(gss_auth->client, cred, RPC_TASK_ASYNC);
+       task = rpc_call_null(gss_auth->client, cred, RPC_TASK_ASYNC|RPC_TASK_SOFT);
        if (!IS_ERR(task))
                rpc_put_task(task);
 
@@ -817,6 +816,7 @@ gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
         */
        cred->gc_base.cr_flags = 1UL << RPCAUTH_CRED_NEW;
        cred->gc_service = gss_auth->service;
+       cred->gc_machine_cred = acred->machine_cred;
        kref_get(&gss_auth->kref);
        return &cred->gc_base;
 
@@ -843,17 +843,16 @@ gss_match(struct auth_cred *acred, struct rpc_cred *rc, int flags)
 {
        struct gss_cred *gss_cred = container_of(rc, struct gss_cred, gc_base);
 
-       /*
-        * If the searchflags have set RPCAUTH_LOOKUP_NEW, then
-        * we don't really care if the credential has expired or not,
-        * since the caller should be prepared to reinitialise it.
-        */
-       if ((flags & RPCAUTH_LOOKUP_NEW) && test_bit(RPCAUTH_CRED_NEW, &rc->cr_flags))
+       if (test_bit(RPCAUTH_CRED_NEW, &rc->cr_flags))
                goto out;
        /* Don't match with creds that have expired. */
-       if (gss_cred->gc_ctx && time_after(jiffies, gss_cred->gc_ctx->gc_expiry))
+       if (time_after(jiffies, gss_cred->gc_ctx->gc_expiry))
+               return 0;
+       if (!test_bit(RPCAUTH_CRED_UPTODATE, &rc->cr_flags))
                return 0;
 out:
+       if (acred->machine_cred != gss_cred->gc_machine_cred)
+               return 0;
        return (rc->cr_uid == acred->uid);
 }
 
@@ -917,16 +916,48 @@ out_put_ctx:
        return NULL;
 }
 
+static int gss_renew_cred(struct rpc_task *task)
+{
+       struct rpc_cred *oldcred = task->tk_msg.rpc_cred;
+       struct gss_cred *gss_cred = container_of(oldcred,
+                                                struct gss_cred,
+                                                gc_base);
+       struct rpc_auth *auth = oldcred->cr_auth;
+       struct auth_cred acred = {
+               .uid = oldcred->cr_uid,
+               .machine_cred = gss_cred->gc_machine_cred,
+       };
+       struct rpc_cred *new;
+
+       new = gss_lookup_cred(auth, &acred, RPCAUTH_LOOKUP_NEW);
+       if (IS_ERR(new))
+               return PTR_ERR(new);
+       task->tk_msg.rpc_cred = new;
+       put_rpccred(oldcred);
+       return 0;
+}
+
 /*
 * Refresh credentials. XXX - finish
 */
 static int
 gss_refresh(struct rpc_task *task)
 {
+       struct rpc_cred *cred = task->tk_msg.rpc_cred;
+       int ret = 0;
+
+       if (!test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags) &&
+                       !test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags)) {
+               ret = gss_renew_cred(task);
+               if (ret < 0)
+                       goto out;
+               cred = task->tk_msg.rpc_cred;
+       }
 
-       if (!gss_cred_is_uptodate_ctx(task->tk_msg.rpc_cred))
-               return gss_refresh_upcall(task);
-       return 0;
+       if (test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags))
+               ret = gss_refresh_upcall(task);
+out:
+       return ret;
 }
 
 /* Dummy refresh routine: used only when destroying the context */
@@ -1286,9 +1317,7 @@ out:
 static const struct rpc_authops authgss_ops = {
        .owner          = THIS_MODULE,
        .au_flavor      = RPC_AUTH_GSS,
-#ifdef RPC_DEBUG
        .au_name        = "RPCSEC_GSS",
-#endif
        .create         = gss_create,
        .destroy        = gss_destroy,
        .lookup_cred    = gss_lookup_cred,
@@ -1299,6 +1328,7 @@ static const struct rpc_credops gss_credops = {
        .cr_name        = "AUTH_GSS",
        .crdestroy      = gss_destroy_cred,
        .cr_init        = gss_cred_init,
+       .crbind         = rpcauth_generic_bind_cred,
        .crmatch        = gss_match,
        .crmarshal      = gss_marshal,
        .crrefresh      = gss_refresh,
@@ -1310,6 +1340,7 @@ static const struct rpc_credops gss_credops = {
 static const struct rpc_credops gss_nullops = {
        .cr_name        = "AUTH_GSS",
        .crdestroy      = gss_destroy_cred,
+       .crbind         = rpcauth_generic_bind_cred,
        .crmatch        = gss_match,
        .crmarshal      = gss_marshal,
        .crrefresh      = gss_refresh_null,
index ea8c92ecdae5294834253f552fb8f1523501bc5d..d83b881685fe52d5c5e22e53c6c394f4a0fc4245 100644 (file)
@@ -148,7 +148,7 @@ int
 g_token_size(struct xdr_netobj *mech, unsigned int body_size)
 {
        /* set body_size to sequence contents size */
-       body_size += 4 + (int) mech->len;         /* NEED overflow check */
+       body_size += 2 + (int) mech->len;         /* NEED overflow check */
        return(1 + der_length_size(body_size) + body_size);
 }
 
@@ -161,7 +161,7 @@ void
 g_make_token_header(struct xdr_netobj *mech, int body_size, unsigned char **buf)
 {
        *(*buf)++ = 0x60;
-       der_write_length(buf, 4 + mech->len + body_size);
+       der_write_length(buf, 2 + mech->len + body_size);
        *(*buf)++ = 0x06;
        *(*buf)++ = (unsigned char) mech->len;
        TWRITE_STR(*buf, mech->data, ((int) mech->len));
index 0dd792338fa96298bb523812e10ff81ebf4a7480..1d52308ca3246597a89ef9f2f120111b64f9b21e 100644 (file)
@@ -66,8 +66,8 @@ krb5_encrypt(
                goto out;
 
        if (crypto_blkcipher_ivsize(tfm) > 16) {
-               dprintk("RPC:       gss_k5encrypt: tfm iv size to large %d\n",
-                        crypto_blkcipher_ivsize(tfm));
+               dprintk("RPC:       gss_k5encrypt: tfm iv size too large %d\n",
+                       crypto_blkcipher_ivsize(tfm));
                goto out;
        }
 
@@ -102,7 +102,7 @@ krb5_decrypt(
                goto out;
 
        if (crypto_blkcipher_ivsize(tfm) > 16) {
-               dprintk("RPC:       gss_k5decrypt: tfm iv size to large %d\n",
+               dprintk("RPC:       gss_k5decrypt: tfm iv size too large %d\n",
                        crypto_blkcipher_ivsize(tfm));
                goto out;
        }
index dedcbd6108f4272e76c3cf2f7fac4c82d85e856f..5f1d36dfbcf70896abcf7ab0bb5e372e84aea5c7 100644 (file)
@@ -87,10 +87,10 @@ gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text,
 
        now = get_seconds();
 
-       token->len = g_token_size(&ctx->mech_used, 22);
+       token->len = g_token_size(&ctx->mech_used, 24);
 
        ptr = token->data;
-       g_make_token_header(&ctx->mech_used, 22, &ptr);
+       g_make_token_header(&ctx->mech_used, 24, &ptr);
 
        *ptr++ = (unsigned char) ((KG_TOK_MIC_MSG>>8)&0xff);
        *ptr++ = (unsigned char) (KG_TOK_MIC_MSG&0xff);
@@ -109,15 +109,14 @@ gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text,
                          md5cksum.data, md5cksum.len))
                return GSS_S_FAILURE;
 
-       memcpy(krb5_hdr + 16, md5cksum.data + md5cksum.len - KRB5_CKSUM_LENGTH,
-              KRB5_CKSUM_LENGTH);
+       memcpy(krb5_hdr + 16, md5cksum.data + md5cksum.len - 8, 8);
 
        spin_lock(&krb5_seq_lock);
        seq_send = ctx->seq_send++;
        spin_unlock(&krb5_seq_lock);
 
        if (krb5_make_seq_num(ctx->seq, ctx->initiate ? 0 : 0xff,
-                              ctx->seq_send, krb5_hdr + 16, krb5_hdr + 8))
+                             seq_send, krb5_hdr + 16, krb5_hdr + 8))
                return GSS_S_FAILURE;
 
        return (ctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE;
index 43f3421f1e6a829f640fe4b4ba7874638c86f9bd..f160be6c1a465bfd3d3e87e809f48b22768fe62e 100644 (file)
@@ -43,7 +43,7 @@
 s32
 krb5_make_seq_num(struct crypto_blkcipher *key,
                int direction,
-               s32 seqnum,
+               u32 seqnum,
                unsigned char *cksum, unsigned char *buf)
 {
        unsigned char plain[8];
@@ -65,7 +65,7 @@ s32
 krb5_get_seq_num(struct crypto_blkcipher *key,
               unsigned char *cksum,
               unsigned char *buf,
-              int *direction, s32 * seqnum)
+              int *direction, u32 *seqnum)
 {
        s32 code;
        unsigned char plain[8];
index e30a993466bc2ccb27de86c66656390baecf22dc..d91a5d0048039558bb4af282136ef54b0d2f95e3 100644 (file)
@@ -82,7 +82,7 @@ gss_verify_mic_kerberos(struct gss_ctx *gss_ctx,
        struct xdr_netobj       md5cksum = {.len = 0, .data = cksumdata};
        s32                     now;
        int                     direction;
-       s32                     seqnum;
+       u32                     seqnum;
        unsigned char           *ptr = (unsigned char *)read_token->data;
        int                     bodysize;
 
index 3bdc527ee64a131e7b1dd705af5aa9e30e28952a..b00b1b426301a8408c518fe23276322a48cd4744 100644 (file)
@@ -137,7 +137,7 @@ gss_wrap_kerberos(struct gss_ctx *ctx, int offset,
        BUG_ON((buf->len - offset) % blocksize);
        plainlen = blocksize + buf->len - offset;
 
-       headlen = g_token_size(&kctx->mech_used, 22 + plainlen) -
+       headlen = g_token_size(&kctx->mech_used, 24 + plainlen) -
                                                (buf->len - offset);
 
        ptr = buf->head[0].iov_base + offset;
@@ -149,7 +149,7 @@ gss_wrap_kerberos(struct gss_ctx *ctx, int offset,
        buf->len += headlen;
        BUG_ON((buf->len - offset - headlen) % blocksize);
 
-       g_make_token_header(&kctx->mech_used, 22 + plainlen, &ptr);
+       g_make_token_header(&kctx->mech_used, 24 + plainlen, &ptr);
 
 
        *ptr++ = (unsigned char) ((KG_TOK_WRAP_MSG>>8)&0xff);
@@ -176,9 +176,7 @@ gss_wrap_kerberos(struct gss_ctx *ctx, int offset,
        if (krb5_encrypt(kctx->seq, NULL, md5cksum.data,
                          md5cksum.data, md5cksum.len))
                return GSS_S_FAILURE;
-       memcpy(krb5_hdr + 16,
-              md5cksum.data + md5cksum.len - KRB5_CKSUM_LENGTH,
-              KRB5_CKSUM_LENGTH);
+       memcpy(krb5_hdr + 16, md5cksum.data + md5cksum.len - 8, 8);
 
        spin_lock(&krb5_seq_lock);
        seq_send = kctx->seq_send++;
index abf17ce2e3b1b13997c9b6181ea76fa5b1794882..c832712f8d55484c30144c2232730a3c60dc339b 100644 (file)
@@ -107,10 +107,10 @@ spkm3_make_token(struct spkm3_ctx *ctx,
                tokenlen = 10 + ctxelen + 1 + md5elen + 1;
 
                /* Create token header using generic routines */
-               token->len = g_token_size(&ctx->mech_used, tokenlen);
+               token->len = g_token_size(&ctx->mech_used, tokenlen + 2);
 
                ptr = token->data;
-               g_make_token_header(&ctx->mech_used, tokenlen, &ptr);
+               g_make_token_header(&ctx->mech_used, tokenlen + 2, &ptr);
 
                spkm3_make_mic_token(&ptr, tokenlen, &mic_hdr, &md5cksum, md5elen, md5zbit);
        } else if (toktype == SPKM_WRAP_TOK) { /* Not Supported */
index 481f984e9a22278bc9ef1993bc3064c77fc65a51..5905d56737d6052a6ea10afbe975e9349a8530d0 100644 (file)
@@ -1146,7 +1146,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
                case RPC_GSS_SVC_INTEGRITY:
                        if (unwrap_integ_data(&rqstp->rq_arg,
                                        gc->gc_seq, rsci->mechctx))
-                               goto auth_err;
+                               goto garbage_args;
                        /* placeholders for length and seq. number: */
                        svc_putnl(resv, 0);
                        svc_putnl(resv, 0);
@@ -1154,7 +1154,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
                case RPC_GSS_SVC_PRIVACY:
                        if (unwrap_priv_data(rqstp, &rqstp->rq_arg,
                                        gc->gc_seq, rsci->mechctx))
-                               goto auth_err;
+                               goto garbage_args;
                        /* placeholders for length and seq. number: */
                        svc_putnl(resv, 0);
                        svc_putnl(resv, 0);
@@ -1169,6 +1169,11 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
                ret = SVC_OK;
                goto out;
        }
+garbage_args:
+       /* Restore write pointer to its original value: */
+       xdr_ressize_check(rqstp, reject_stat);
+       ret = SVC_GARBAGE;
+       goto out;
 auth_err:
        /* Restore write pointer to its original value: */
        xdr_ressize_check(rqstp, reject_stat);
index 537d0e8589ddb598c9137eb97ccea1a870af04a6..c70dd7f5258e18b440f02a072a9a62337cd61d87 100644 (file)
@@ -104,9 +104,7 @@ nul_validate(struct rpc_task *task, __be32 *p)
 const struct rpc_authops authnull_ops = {
        .owner          = THIS_MODULE,
        .au_flavor      = RPC_AUTH_NULL,
-#ifdef RPC_DEBUG
        .au_name        = "NULL",
-#endif
        .create         = nul_create,
        .destroy        = nul_destroy,
        .lookup_cred    = nul_lookup_cred,
@@ -125,6 +123,7 @@ static
 const struct rpc_credops null_credops = {
        .cr_name        = "AUTH_NULL",
        .crdestroy      = nul_destroy_cred,
+       .crbind         = rpcauth_generic_bind_cred,
        .crmatch        = nul_match,
        .crmarshal      = nul_marshal,
        .crrefresh      = nul_refresh,
index 5ed91e5bcee4a9ce04e22a167450b6c612362970..44920b90bdc45a438faca8b2aa8d5cfb388a26c7 100644 (file)
@@ -60,7 +60,8 @@ static struct rpc_cred *
 unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
 {
        struct unx_cred *cred;
-       int             i;
+       unsigned int groups = 0;
+       unsigned int i;
 
        dprintk("RPC:       allocating UNIX cred for uid %d gid %d\n",
                        acred->uid, acred->gid);
@@ -70,21 +71,17 @@ unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
 
        rpcauth_init_cred(&cred->uc_base, acred, auth, &unix_credops);
        cred->uc_base.cr_flags = 1UL << RPCAUTH_CRED_UPTODATE;
-       if (flags & RPCAUTH_LOOKUP_ROOTCREDS) {
-               cred->uc_uid = 0;
-               cred->uc_gid = 0;
-               cred->uc_gids[0] = NOGROUP;
-       } else {
-               int groups = acred->group_info->ngroups;
-               if (groups > NFS_NGROUPS)
-                       groups = NFS_NGROUPS;
-
-               cred->uc_gid = acred->gid;
-               for (i = 0; i < groups; i++)
-                       cred->uc_gids[i] = GROUP_AT(acred->group_info, i);
-               if (i < NFS_NGROUPS)
-                 cred->uc_gids[i] = NOGROUP;
-       }
+
+       if (acred->group_info != NULL)
+               groups = acred->group_info->ngroups;
+       if (groups > NFS_NGROUPS)
+               groups = NFS_NGROUPS;
+
+       cred->uc_gid = acred->gid;
+       for (i = 0; i < groups; i++)
+               cred->uc_gids[i] = GROUP_AT(acred->group_info, i);
+       if (i < NFS_NGROUPS)
+               cred->uc_gids[i] = NOGROUP;
 
        return &cred->uc_base;
 }
@@ -118,26 +115,21 @@ static int
 unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int flags)
 {
        struct unx_cred *cred = container_of(rcred, struct unx_cred, uc_base);
-       int             i;
+       unsigned int groups = 0;
+       unsigned int i;
 
-       if (!(flags & RPCAUTH_LOOKUP_ROOTCREDS)) {
-               int groups;
 
-               if (cred->uc_uid != acred->uid
-                || cred->uc_gid != acred->gid)
-                       return 0;
+       if (cred->uc_uid != acred->uid || cred->uc_gid != acred->gid)
+               return 0;
 
+       if (acred->group_info != NULL)
                groups = acred->group_info->ngroups;
-               if (groups > NFS_NGROUPS)
-                       groups = NFS_NGROUPS;
-               for (i = 0; i < groups ; i++)
-                       if (cred->uc_gids[i] != GROUP_AT(acred->group_info, i))
-                               return 0;
-               return 1;
-       }
-       return (cred->uc_uid == 0
-            && cred->uc_gid == 0
-            && cred->uc_gids[0] == (gid_t) NOGROUP);
+       if (groups > NFS_NGROUPS)
+               groups = NFS_NGROUPS;
+       for (i = 0; i < groups ; i++)
+               if (cred->uc_gids[i] != GROUP_AT(acred->group_info, i))
+                       return 0;
+       return 1;
 }
 
 /*
@@ -218,9 +210,7 @@ void __init rpc_init_authunix(void)
 const struct rpc_authops authunix_ops = {
        .owner          = THIS_MODULE,
        .au_flavor      = RPC_AUTH_UNIX,
-#ifdef RPC_DEBUG
        .au_name        = "UNIX",
-#endif
        .create         = unx_create,
        .destroy        = unx_destroy,
        .lookup_cred    = unx_lookup_cred,
@@ -245,6 +235,7 @@ static
 const struct rpc_credops unix_credops = {
        .cr_name        = "AUTH_UNIX",
        .crdestroy      = unx_destroy_cred,
+       .crbind         = rpcauth_generic_bind_cred,
        .crmatch        = unx_match,
        .crmarshal      = unx_marshal,
        .crrefresh      = unx_refresh,
index b5f2786251b95368f4bccda69290683e1c3f0b28..d75530ff2a6d90aaca6f9a4f39cada3e56b89fc7 100644 (file)
@@ -571,7 +571,6 @@ static int cache_defer_req(struct cache_req *req, struct cache_head *item)
                return -ETIMEDOUT;
 
        dreq->item = item;
-       dreq->recv_time = get_seconds();
 
        spin_lock(&cache_defer_lock);
 
index 7b96ff38002feaef24b575cdf5f35516fe38d4dd..8945307556ec32c1a02da6f505748cb5f813b490 100644 (file)
@@ -544,7 +544,7 @@ EXPORT_SYMBOL_GPL(rpc_run_task);
  * @msg: RPC call parameters
  * @flags: RPC call flags
  */
-int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
+int rpc_call_sync(struct rpc_clnt *clnt, const struct rpc_message *msg, int flags)
 {
        struct rpc_task *task;
        struct rpc_task_setup task_setup_data = {
@@ -575,7 +575,7 @@ EXPORT_SYMBOL_GPL(rpc_call_sync);
  * @data: user call data
  */
 int
-rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags,
+rpc_call_async(struct rpc_clnt *clnt, const struct rpc_message *msg, int flags,
               const struct rpc_call_ops *tk_ops, void *data)
 {
        struct rpc_task *task;
@@ -1062,7 +1062,7 @@ call_transmit(struct rpc_task *task)
        if (task->tk_msg.rpc_proc->p_decode != NULL)
                return;
        task->tk_action = rpc_exit_task;
-       rpc_wake_up_task(task);
+       rpc_wake_up_queued_task(&task->tk_xprt->pending, task);
 }
 
 /*
@@ -1116,7 +1116,8 @@ call_status(struct rpc_task *task)
        case -ETIMEDOUT:
                task->tk_action = call_timeout;
                if (task->tk_client->cl_discrtry)
-                       xprt_force_disconnect(task->tk_xprt);
+                       xprt_conditional_disconnect(task->tk_xprt,
+                                       req->rq_connect_cookie);
                break;
        case -ECONNREFUSED:
        case -ENOTCONN:
@@ -1168,6 +1169,11 @@ call_timeout(struct rpc_task *task)
                        clnt->cl_protname, clnt->cl_server);
        }
        rpc_force_rebind(clnt);
+       /*
+        * Did our request time out due to an RPCSEC_GSS out-of-sequence
+        * event? RFC2203 requires the server to drop all such requests.
+        */
+       rpcauth_invalcred(task);
 
 retry:
        clnt->cl_stats->rpcretrans++;
@@ -1195,18 +1201,6 @@ call_decode(struct rpc_task *task)
                task->tk_flags &= ~RPC_CALL_MAJORSEEN;
        }
 
-       if (task->tk_status < 12) {
-               if (!RPC_IS_SOFT(task)) {
-                       task->tk_action = call_bind;
-                       clnt->cl_stats->rpcretrans++;
-                       goto out_retry;
-               }
-               dprintk("RPC:       %s: too small RPC reply size (%d bytes)\n",
-                               clnt->cl_protname, task->tk_status);
-               task->tk_action = call_timeout;
-               goto out_retry;
-       }
-
        /*
         * Ensure that we see all writes made by xprt_complete_rqst()
         * before it changed req->rq_received.
@@ -1218,6 +1212,18 @@ call_decode(struct rpc_task *task)
        WARN_ON(memcmp(&req->rq_rcv_buf, &req->rq_private_buf,
                                sizeof(req->rq_rcv_buf)) != 0);
 
+       if (req->rq_rcv_buf.len < 12) {
+               if (!RPC_IS_SOFT(task)) {
+                       task->tk_action = call_bind;
+                       clnt->cl_stats->rpcretrans++;
+                       goto out_retry;
+               }
+               dprintk("RPC:       %s: too small RPC reply size (%d bytes)\n",
+                               clnt->cl_protname, task->tk_status);
+               task->tk_action = call_timeout;
+               goto out_retry;
+       }
+
        /* Verify the RPC header */
        p = call_verify(task);
        if (IS_ERR(p)) {
@@ -1236,10 +1242,14 @@ call_decode(struct rpc_task *task)
                        task->tk_status);
        return;
 out_retry:
-       req->rq_received = req->rq_private_buf.len = 0;
        task->tk_status = 0;
-       if (task->tk_client->cl_discrtry)
-               xprt_force_disconnect(task->tk_xprt);
+       /* Note: call_verify() may have freed the RPC slot */
+       if (task->tk_rqstp == req) {
+               req->rq_received = req->rq_rcv_buf.len = 0;
+               if (task->tk_client->cl_discrtry)
+                       xprt_conditional_disconnect(task->tk_xprt,
+                                       req->rq_connect_cookie);
+       }
 }
 
 /*
@@ -1531,7 +1541,7 @@ void rpc_show_tasks(void)
                                proc = -1;
 
                        if (RPC_IS_QUEUED(t))
-                               rpc_waitq = rpc_qname(t->u.tk_wait.rpc_waitq);
+                               rpc_waitq = rpc_qname(t->tk_waitqueue);
 
                        printk("%5u %04d %04x %6d %8p %6d %8p %8ld %8s %8p %8p\n",
                                t->tk_pid, proc,
index 56aa018dce3a026b063262e086b6456e2af6b1fa..0517967a68bf85571919923e9935658d4c63e6f3 100644 (file)
@@ -298,7 +298,7 @@ void rpcb_getport_async(struct rpc_task *task)
 
        /* Put self on queue before sending rpcbind request, in case
         * rpcb_getport_done completes before we return from rpc_run_task */
-       rpc_sleep_on(&xprt->binding, task, NULL, NULL);
+       rpc_sleep_on(&xprt->binding, task, NULL);
 
        /* Someone else may have bound if we slept */
        if (xprt_bound(xprt)) {
index 4c669121e607f774b7739a326639e8f2aec146a3..6eab9bf94baf3ebef9c2b1300ffe8505c3694a78 100644 (file)
@@ -38,9 +38,9 @@ static struct kmem_cache      *rpc_buffer_slabp __read_mostly;
 static mempool_t       *rpc_task_mempool __read_mostly;
 static mempool_t       *rpc_buffer_mempool __read_mostly;
 
-static void                    __rpc_default_timer(struct rpc_task *task);
 static void                    rpc_async_schedule(struct work_struct *);
 static void                     rpc_release_task(struct rpc_task *task);
+static void __rpc_queue_timer_fn(unsigned long ptr);
 
 /*
  * RPC tasks sit here while waiting for conditions to improve.
@@ -57,41 +57,30 @@ struct workqueue_struct *rpciod_workqueue;
  * queue->lock and bh_disabled in order to avoid races within
  * rpc_run_timer().
  */
-static inline void
-__rpc_disable_timer(struct rpc_task *task)
+static void
+__rpc_disable_timer(struct rpc_wait_queue *queue, struct rpc_task *task)
 {
+       if (task->tk_timeout == 0)
+               return;
        dprintk("RPC: %5u disabling timer\n", task->tk_pid);
-       task->tk_timeout_fn = NULL;
        task->tk_timeout = 0;
+       list_del(&task->u.tk_wait.timer_list);
+       if (list_empty(&queue->timer_list.list))
+               del_timer(&queue->timer_list.timer);
 }
 
-/*
- * Run a timeout function.
- * We use the callback in order to allow __rpc_wake_up_task()
- * and friends to disable the timer synchronously on SMP systems
- * without calling del_timer_sync(). The latter could cause a
- * deadlock if called while we're holding spinlocks...
- */
-static void rpc_run_timer(struct rpc_task *task)
+static void
+rpc_set_queue_timer(struct rpc_wait_queue *queue, unsigned long expires)
 {
-       void (*callback)(struct rpc_task *);
-
-       callback = task->tk_timeout_fn;
-       task->tk_timeout_fn = NULL;
-       if (callback && RPC_IS_QUEUED(task)) {
-               dprintk("RPC: %5u running timer\n", task->tk_pid);
-               callback(task);
-       }
-       smp_mb__before_clear_bit();
-       clear_bit(RPC_TASK_HAS_TIMER, &task->tk_runstate);
-       smp_mb__after_clear_bit();
+       queue->timer_list.expires = expires;
+       mod_timer(&queue->timer_list.timer, expires);
 }
 
 /*
  * Set up a timer for the current task.
  */
-static inline void
-__rpc_add_timer(struct rpc_task *task, rpc_action timer)
+static void
+__rpc_add_timer(struct rpc_wait_queue *queue, struct rpc_task *task)
 {
        if (!task->tk_timeout)
                return;
@@ -99,27 +88,10 @@ __rpc_add_timer(struct rpc_task *task, rpc_action timer)
        dprintk("RPC: %5u setting alarm for %lu ms\n",
                        task->tk_pid, task->tk_timeout * 1000 / HZ);
 
-       if (timer)
-               task->tk_timeout_fn = timer;
-       else
-               task->tk_timeout_fn = __rpc_default_timer;
-       set_bit(RPC_TASK_HAS_TIMER, &task->tk_runstate);
-       mod_timer(&task->tk_timer, jiffies + task->tk_timeout);
-}
-
-/*
- * Delete any timer for the current task. Because we use del_timer_sync(),
- * this function should never be called while holding queue->lock.
- */
-static void
-rpc_delete_timer(struct rpc_task *task)
-{
-       if (RPC_IS_QUEUED(task))
-               return;
-       if (test_and_clear_bit(RPC_TASK_HAS_TIMER, &task->tk_runstate)) {
-               del_singleshot_timer_sync(&task->tk_timer);
-               dprintk("RPC: %5u deleting timer\n", task->tk_pid);
-       }
+       task->u.tk_wait.expires = jiffies + task->tk_timeout;
+       if (list_empty(&queue->timer_list.list) || time_before(task->u.tk_wait.expires, queue->timer_list.expires))
+               rpc_set_queue_timer(queue, task->u.tk_wait.expires);
+       list_add(&task->u.tk_wait.timer_list, &queue->timer_list.list);
 }
 
 /*
@@ -161,7 +133,7 @@ static void __rpc_add_wait_queue(struct rpc_wait_queue *queue, struct rpc_task *
                list_add(&task->u.tk_wait.list, &queue->tasks[0]);
        else
                list_add_tail(&task->u.tk_wait.list, &queue->tasks[0]);
-       task->u.tk_wait.rpc_waitq = queue;
+       task->tk_waitqueue = queue;
        queue->qlen++;
        rpc_set_queued(task);
 
@@ -181,22 +153,18 @@ static void __rpc_remove_wait_queue_priority(struct rpc_task *task)
                list_move(&t->u.tk_wait.list, &task->u.tk_wait.list);
                list_splice_init(&task->u.tk_wait.links, &t->u.tk_wait.links);
        }
-       list_del(&task->u.tk_wait.list);
 }
 
 /*
  * Remove request from queue.
  * Note: must be called with spin lock held.
  */
-static void __rpc_remove_wait_queue(struct rpc_task *task)
+static void __rpc_remove_wait_queue(struct rpc_wait_queue *queue, struct rpc_task *task)
 {
-       struct rpc_wait_queue *queue;
-       queue = task->u.tk_wait.rpc_waitq;
-
+       __rpc_disable_timer(queue, task);
        if (RPC_IS_PRIORITY(queue))
                __rpc_remove_wait_queue_priority(task);
-       else
-               list_del(&task->u.tk_wait.list);
+       list_del(&task->u.tk_wait.list);
        queue->qlen--;
        dprintk("RPC: %5u removed from queue %p \"%s\"\n",
                        task->tk_pid, queue, rpc_qname(queue));
@@ -229,6 +197,9 @@ static void __rpc_init_priority_wait_queue(struct rpc_wait_queue *queue, const c
                INIT_LIST_HEAD(&queue->tasks[i]);
        queue->maxpriority = nr_queues - 1;
        rpc_reset_waitqueue_priority(queue);
+       queue->qlen = 0;
+       setup_timer(&queue->timer_list.timer, __rpc_queue_timer_fn, (unsigned long)queue);
+       INIT_LIST_HEAD(&queue->timer_list.list);
 #ifdef RPC_DEBUG
        queue->name = qname;
 #endif
@@ -245,6 +216,12 @@ void rpc_init_wait_queue(struct rpc_wait_queue *queue, const char *qname)
 }
 EXPORT_SYMBOL_GPL(rpc_init_wait_queue);
 
+void rpc_destroy_wait_queue(struct rpc_wait_queue *queue)
+{
+       del_timer_sync(&queue->timer_list.timer);
+}
+EXPORT_SYMBOL_GPL(rpc_destroy_wait_queue);
+
 static int rpc_wait_bit_killable(void *word)
 {
        if (fatal_signal_pending(current))
@@ -313,7 +290,6 @@ EXPORT_SYMBOL_GPL(__rpc_wait_for_completion_task);
  */
 static void rpc_make_runnable(struct rpc_task *task)
 {
-       BUG_ON(task->tk_timeout_fn);
        rpc_clear_queued(task);
        if (rpc_test_and_set_running(task))
                return;
@@ -326,7 +302,7 @@ static void rpc_make_runnable(struct rpc_task *task)
                int status;
 
                INIT_WORK(&task->u.tk_work, rpc_async_schedule);
-               status = queue_work(task->tk_workqueue, &task->u.tk_work);
+               status = queue_work(rpciod_workqueue, &task->u.tk_work);
                if (status < 0) {
                        printk(KERN_WARNING "RPC: failed to add task to queue: error: %d!\n", status);
                        task->tk_status = status;
@@ -343,7 +319,7 @@ static void rpc_make_runnable(struct rpc_task *task)
  * as it's on a wait queue.
  */
 static void __rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task,
-                       rpc_action action, rpc_action timer)
+                       rpc_action action)
 {
        dprintk("RPC: %5u sleep_on(queue \"%s\" time %lu)\n",
                        task->tk_pid, rpc_qname(q), jiffies);
@@ -357,11 +333,11 @@ static void __rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task,
 
        BUG_ON(task->tk_callback != NULL);
        task->tk_callback = action;
-       __rpc_add_timer(task, timer);
+       __rpc_add_timer(q, task);
 }
 
 void rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task,
-                               rpc_action action, rpc_action timer)
+                               rpc_action action)
 {
        /* Mark the task as being activated if so needed */
        rpc_set_active(task);
@@ -370,18 +346,19 @@ void rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task,
         * Protect the queue operations.
         */
        spin_lock_bh(&q->lock);
-       __rpc_sleep_on(q, task, action, timer);
+       __rpc_sleep_on(q, task, action);
        spin_unlock_bh(&q->lock);
 }
 EXPORT_SYMBOL_GPL(rpc_sleep_on);
 
 /**
  * __rpc_do_wake_up_task - wake up a single rpc_task
+ * @queue: wait queue
  * @task: task to be woken up
  *
  * Caller must hold queue->lock, and have cleared the task queued flag.
  */
-static void __rpc_do_wake_up_task(struct rpc_task *task)
+static void __rpc_do_wake_up_task(struct rpc_wait_queue *queue, struct rpc_task *task)
 {
        dprintk("RPC: %5u __rpc_wake_up_task (now %lu)\n",
                        task->tk_pid, jiffies);
@@ -395,8 +372,7 @@ static void __rpc_do_wake_up_task(struct rpc_task *task)
                return;
        }
 
-       __rpc_disable_timer(task);
-       __rpc_remove_wait_queue(task);
+       __rpc_remove_wait_queue(queue, task);
 
        rpc_make_runnable(task);
 
@@ -404,48 +380,32 @@ static void __rpc_do_wake_up_task(struct rpc_task *task)
 }
 
 /*
- * Wake up the specified task
+ * Wake up a queued task while the queue lock is being held
  */
-static void __rpc_wake_up_task(struct rpc_task *task)
+static void rpc_wake_up_task_queue_locked(struct rpc_wait_queue *queue, struct rpc_task *task)
 {
-       if (rpc_start_wakeup(task)) {
-               if (RPC_IS_QUEUED(task))
-                       __rpc_do_wake_up_task(task);
-               rpc_finish_wakeup(task);
-       }
+       if (RPC_IS_QUEUED(task) && task->tk_waitqueue == queue)
+               __rpc_do_wake_up_task(queue, task);
 }
 
 /*
- * Default timeout handler if none specified by user
+ * Wake up a task on a specific queue
  */
-static void
-__rpc_default_timer(struct rpc_task *task)
+void rpc_wake_up_queued_task(struct rpc_wait_queue *queue, struct rpc_task *task)
 {
-       dprintk("RPC: %5u timeout (default timer)\n", task->tk_pid);
-       task->tk_status = -ETIMEDOUT;
-       rpc_wake_up_task(task);
+       spin_lock_bh(&queue->lock);
+       rpc_wake_up_task_queue_locked(queue, task);
+       spin_unlock_bh(&queue->lock);
 }
+EXPORT_SYMBOL_GPL(rpc_wake_up_queued_task);
 
 /*
  * Wake up the specified task
  */
-void rpc_wake_up_task(struct rpc_task *task)
+static void rpc_wake_up_task(struct rpc_task *task)
 {
-       rcu_read_lock_bh();
-       if (rpc_start_wakeup(task)) {
-               if (RPC_IS_QUEUED(task)) {
-                       struct rpc_wait_queue *queue = task->u.tk_wait.rpc_waitq;
-
-                       /* Note: we're already in a bh-safe context */
-                       spin_lock(&queue->lock);
-                       __rpc_do_wake_up_task(task);
-                       spin_unlock(&queue->lock);
-               }
-               rpc_finish_wakeup(task);
-       }
-       rcu_read_unlock_bh();
+       rpc_wake_up_queued_task(task->tk_waitqueue, task);
 }
-EXPORT_SYMBOL_GPL(rpc_wake_up_task);
 
 /*
  * Wake up the next task on a priority queue.
@@ -495,7 +455,7 @@ new_queue:
 new_owner:
        rpc_set_waitqueue_owner(queue, task->tk_owner);
 out:
-       __rpc_wake_up_task(task);
+       rpc_wake_up_task_queue_locked(queue, task);
        return task;
 }
 
@@ -508,16 +468,14 @@ struct rpc_task * rpc_wake_up_next(struct rpc_wait_queue *queue)
 
        dprintk("RPC:       wake_up_next(%p \"%s\")\n",
                        queue, rpc_qname(queue));
-       rcu_read_lock_bh();
-       spin_lock(&queue->lock);
+       spin_lock_bh(&queue->lock);
        if (RPC_IS_PRIORITY(queue))
                task = __rpc_wake_up_next_priority(queue);
        else {
                task_for_first(task, &queue->tasks[0])
-                       __rpc_wake_up_task(task);
+                       rpc_wake_up_task_queue_locked(queue, task);
        }
-       spin_unlock(&queue->lock);
-       rcu_read_unlock_bh();
+       spin_unlock_bh(&queue->lock);
 
        return task;
 }
@@ -534,18 +492,16 @@ void rpc_wake_up(struct rpc_wait_queue *queue)
        struct rpc_task *task, *next;
        struct list_head *head;
 
-       rcu_read_lock_bh();
-       spin_lock(&queue->lock);
+       spin_lock_bh(&queue->lock);
        head = &queue->tasks[queue->maxpriority];
        for (;;) {
                list_for_each_entry_safe(task, next, head, u.tk_wait.list)
-                       __rpc_wake_up_task(task);
+                       rpc_wake_up_task_queue_locked(queue, task);
                if (head == &queue->tasks[0])
                        break;
                head--;
        }
-       spin_unlock(&queue->lock);
-       rcu_read_unlock_bh();
+       spin_unlock_bh(&queue->lock);
 }
 EXPORT_SYMBOL_GPL(rpc_wake_up);
 
@@ -561,26 +517,48 @@ void rpc_wake_up_status(struct rpc_wait_queue *queue, int status)
        struct rpc_task *task, *next;
        struct list_head *head;
 
-       rcu_read_lock_bh();
-       spin_lock(&queue->lock);
+       spin_lock_bh(&queue->lock);
        head = &queue->tasks[queue->maxpriority];
        for (;;) {
                list_for_each_entry_safe(task, next, head, u.tk_wait.list) {
                        task->tk_status = status;
-                       __rpc_wake_up_task(task);
+                       rpc_wake_up_task_queue_locked(queue, task);
                }
                if (head == &queue->tasks[0])
                        break;
                head--;
        }
-       spin_unlock(&queue->lock);
-       rcu_read_unlock_bh();
+       spin_unlock_bh(&queue->lock);
 }
 EXPORT_SYMBOL_GPL(rpc_wake_up_status);
 
+static void __rpc_queue_timer_fn(unsigned long ptr)
+{
+       struct rpc_wait_queue *queue = (struct rpc_wait_queue *)ptr;
+       struct rpc_task *task, *n;
+       unsigned long expires, now, timeo;
+
+       spin_lock(&queue->lock);
+       expires = now = jiffies;
+       list_for_each_entry_safe(task, n, &queue->timer_list.list, u.tk_wait.timer_list) {
+               timeo = task->u.tk_wait.expires;
+               if (time_after_eq(now, timeo)) {
+                       dprintk("RPC: %5u timeout\n", task->tk_pid);
+                       task->tk_status = -ETIMEDOUT;
+                       rpc_wake_up_task_queue_locked(queue, task);
+                       continue;
+               }
+               if (expires == now || time_after(expires, timeo))
+                       expires = timeo;
+       }
+       if (!list_empty(&queue->timer_list.list))
+               rpc_set_queue_timer(queue, expires);
+       spin_unlock(&queue->lock);
+}
+
 static void __rpc_atrun(struct rpc_task *task)
 {
-       rpc_wake_up_task(task);
+       task->tk_status = 0;
 }
 
 /*
@@ -589,7 +567,7 @@ static void __rpc_atrun(struct rpc_task *task)
 void rpc_delay(struct rpc_task *task, unsigned long delay)
 {
        task->tk_timeout = delay;
-       rpc_sleep_on(&delay_queue, task, NULL, __rpc_atrun);
+       rpc_sleep_on(&delay_queue, task, __rpc_atrun);
 }
 EXPORT_SYMBOL_GPL(rpc_delay);
 
@@ -644,10 +622,6 @@ static void __rpc_execute(struct rpc_task *task)
        BUG_ON(RPC_IS_QUEUED(task));
 
        for (;;) {
-               /*
-                * Garbage collection of pending timers...
-                */
-               rpc_delete_timer(task);
 
                /*
                 * Execute any pending callback.
@@ -816,8 +790,6 @@ EXPORT_SYMBOL_GPL(rpc_free);
 static void rpc_init_task(struct rpc_task *task, const struct rpc_task_setup *task_setup_data)
 {
        memset(task, 0, sizeof(*task));
-       setup_timer(&task->tk_timer, (void (*)(unsigned long))rpc_run_timer,
-                       (unsigned long)task);
        atomic_set(&task->tk_count, 1);
        task->tk_flags  = task_setup_data->flags;
        task->tk_ops = task_setup_data->callback_ops;
@@ -832,7 +804,7 @@ static void rpc_init_task(struct rpc_task *task, const struct rpc_task_setup *ta
        task->tk_owner = current->tgid;
 
        /* Initialize workqueue for async tasks */
-       task->tk_workqueue = rpciod_workqueue;
+       task->tk_workqueue = task_setup_data->workqueue;
 
        task->tk_client = task_setup_data->rpc_client;
        if (task->tk_client != NULL) {
@@ -845,12 +817,11 @@ static void rpc_init_task(struct rpc_task *task, const struct rpc_task_setup *ta
                task->tk_action = rpc_prepare_task;
 
        if (task_setup_data->rpc_message != NULL) {
-               memcpy(&task->tk_msg, task_setup_data->rpc_message, sizeof(task->tk_msg));
+               task->tk_msg.rpc_proc = task_setup_data->rpc_message->rpc_proc;
+               task->tk_msg.rpc_argp = task_setup_data->rpc_message->rpc_argp;
+               task->tk_msg.rpc_resp = task_setup_data->rpc_message->rpc_resp;
                /* Bind the user cred */
-               if (task->tk_msg.rpc_cred != NULL)
-                       rpcauth_holdcred(task);
-               else
-                       rpcauth_bindcred(task);
+               rpcauth_bindcred(task, task_setup_data->rpc_message->rpc_cred, task_setup_data->flags);
                if (task->tk_action == NULL)
                        rpc_call_start(task);
        }
@@ -868,13 +839,6 @@ rpc_alloc_task(void)
        return (struct rpc_task *)mempool_alloc(rpc_task_mempool, GFP_NOFS);
 }
 
-static void rpc_free_task(struct rcu_head *rcu)
-{
-       struct rpc_task *task = container_of(rcu, struct rpc_task, u.tk_rcu);
-       dprintk("RPC: %5u freeing task\n", task->tk_pid);
-       mempool_free(task, rpc_task_mempool);
-}
-
 /*
  * Create a new task for the specified client.
  */
@@ -898,12 +862,25 @@ out:
        return task;
 }
 
-
-void rpc_put_task(struct rpc_task *task)
+static void rpc_free_task(struct rpc_task *task)
 {
        const struct rpc_call_ops *tk_ops = task->tk_ops;
        void *calldata = task->tk_calldata;
 
+       if (task->tk_flags & RPC_TASK_DYNAMIC) {
+               dprintk("RPC: %5u freeing task\n", task->tk_pid);
+               mempool_free(task, rpc_task_mempool);
+       }
+       rpc_release_calldata(tk_ops, calldata);
+}
+
+static void rpc_async_release(struct work_struct *work)
+{
+       rpc_free_task(container_of(work, struct rpc_task, u.tk_work));
+}
+
+void rpc_put_task(struct rpc_task *task)
+{
        if (!atomic_dec_and_test(&task->tk_count))
                return;
        /* Release resources */
@@ -915,9 +892,11 @@ void rpc_put_task(struct rpc_task *task)
                rpc_release_client(task->tk_client);
                task->tk_client = NULL;
        }
-       if (task->tk_flags & RPC_TASK_DYNAMIC)
-               call_rcu_bh(&task->u.tk_rcu, rpc_free_task);
-       rpc_release_calldata(tk_ops, calldata);
+       if (task->tk_workqueue != NULL) {
+               INIT_WORK(&task->u.tk_work, rpc_async_release);
+               queue_work(task->tk_workqueue, &task->u.tk_work);
+       } else
+               rpc_free_task(task);
 }
 EXPORT_SYMBOL_GPL(rpc_put_task);
 
@@ -937,9 +916,6 @@ static void rpc_release_task(struct rpc_task *task)
        }
        BUG_ON (RPC_IS_QUEUED(task));
 
-       /* Synchronously delete any running timer */
-       rpc_delete_timer(task);
-
 #ifdef RPC_DEBUG
        task->tk_magic = 0;
 #endif
@@ -1029,11 +1005,20 @@ rpc_destroy_mempool(void)
                kmem_cache_destroy(rpc_task_slabp);
        if (rpc_buffer_slabp)
                kmem_cache_destroy(rpc_buffer_slabp);
+       rpc_destroy_wait_queue(&delay_queue);
 }
 
 int
 rpc_init_mempool(void)
 {
+       /*
+        * The following is not strictly a mempool initialisation,
+        * but there is no harm in doing it here
+        */
+       rpc_init_wait_queue(&delay_queue, "delayq");
+       if (!rpciod_start())
+               goto err_nomem;
+
        rpc_task_slabp = kmem_cache_create("rpc_tasks",
                                             sizeof(struct rpc_task),
                                             0, SLAB_HWCACHE_ALIGN,
@@ -1054,13 +1039,6 @@ rpc_init_mempool(void)
                                                      rpc_buffer_slabp);
        if (!rpc_buffer_mempool)
                goto err_nomem;
-       if (!rpciod_start())
-               goto err_nomem;
-       /*
-        * The following is not strictly a mempool initialisation,
-        * but there is no harm in doing it here
-        */
-       rpc_init_wait_queue(&delay_queue, "delayq");
        return 0;
 err_nomem:
        rpc_destroy_mempool();
index 090af78d68b5a4d010757b7d725721a1db3141fc..d74c2d269539a03a4267dcc93d195ca20e68d522 100644 (file)
@@ -510,8 +510,7 @@ EXPORT_SYMBOL(svc_destroy);
 static int
 svc_init_buffer(struct svc_rqst *rqstp, unsigned int size)
 {
-       int pages;
-       int arghi;
+       unsigned int pages, arghi;
 
        pages = size / PAGE_SIZE + 1; /* extra page as we hold both request and reply.
                                       * We assume one is at most one page
@@ -525,7 +524,7 @@ svc_init_buffer(struct svc_rqst *rqstp, unsigned int size)
                rqstp->rq_pages[arghi++] = p;
                pages--;
        }
-       return ! pages;
+       return pages == 0;
 }
 
 /*
@@ -534,8 +533,9 @@ svc_init_buffer(struct svc_rqst *rqstp, unsigned int size)
 static void
 svc_release_buffer(struct svc_rqst *rqstp)
 {
-       int i;
-       for (i=0; i<ARRAY_SIZE(rqstp->rq_pages); i++)
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(rqstp->rq_pages); i++)
                if (rqstp->rq_pages[i])
                        put_page(rqstp->rq_pages[i]);
 }
@@ -590,7 +590,7 @@ __svc_create_thread(svc_thread_fn func, struct svc_serv *serv,
        struct svc_rqst *rqstp;
        int             error = -ENOMEM;
        int             have_oldmask = 0;
-       cpumask_t       oldmask;
+       cpumask_t       uninitialized_var(oldmask);
 
        rqstp = svc_prepare_thread(serv, pool);
        if (IS_ERR(rqstp)) {
@@ -618,16 +618,6 @@ out_thread:
        goto out;
 }
 
-/*
- * Create a thread in the default pool.  Caller must hold BKL.
- */
-int
-svc_create_thread(svc_thread_fn func, struct svc_serv *serv)
-{
-       return __svc_create_thread(func, serv, &serv->sv_pools[0]);
-}
-EXPORT_SYMBOL(svc_create_thread);
-
 /*
  * Choose a pool in which to create a new thread, for svc_set_num_threads
  */
@@ -921,8 +911,7 @@ svc_process(struct svc_rqst *rqstp)
        case SVC_OK:
                break;
        case SVC_GARBAGE:
-               rpc_stat = rpc_garbage_args;
-               goto err_bad;
+               goto err_garbage;
        case SVC_SYSERR:
                rpc_stat = rpc_system_err;
                goto err_bad;
index 332eb47539e16a18a5dd7313dfaf76525078976b..d8e8d79a84514aebcd003b65ef2cda5002bc391c 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/skbuff.h>
 #include <linux/file.h>
 #include <linux/freezer.h>
+#include <linux/kthread.h>
 #include <net/sock.h>
 #include <net/checksum.h>
 #include <net/ip.h>
@@ -586,8 +587,12 @@ int svc_recv(struct svc_rqst *rqstp, long timeout)
                while (rqstp->rq_pages[i] == NULL) {
                        struct page *p = alloc_page(GFP_KERNEL);
                        if (!p) {
-                               int j = msecs_to_jiffies(500);
-                               schedule_timeout_uninterruptible(j);
+                               set_current_state(TASK_INTERRUPTIBLE);
+                               if (signalled() || kthread_should_stop()) {
+                                       set_current_state(TASK_RUNNING);
+                                       return -EINTR;
+                               }
+                               schedule_timeout(msecs_to_jiffies(500));
                        }
                        rqstp->rq_pages[i] = p;
                }
@@ -607,7 +612,7 @@ int svc_recv(struct svc_rqst *rqstp, long timeout)
 
        try_to_freeze();
        cond_resched();
-       if (signalled())
+       if (signalled() || kthread_should_stop())
                return -EINTR;
 
        spin_lock_bh(&pool->sp_lock);
@@ -626,6 +631,20 @@ int svc_recv(struct svc_rqst *rqstp, long timeout)
                 * to bring down the daemons ...
                 */
                set_current_state(TASK_INTERRUPTIBLE);
+
+               /*
+                * checking kthread_should_stop() here allows us to avoid
+                * locking and signalling when stopping kthreads that call
+                * svc_recv. If the thread has already been woken up, then
+                * we can exit here without sleeping. If not, then it
+                * it'll be woken up quickly during the schedule_timeout
+                */
+               if (kthread_should_stop()) {
+                       set_current_state(TASK_RUNNING);
+                       spin_unlock_bh(&pool->sp_lock);
+                       return -EINTR;
+               }
+
                add_wait_queue(&rqstp->rq_wait, &wait);
                spin_unlock_bh(&pool->sp_lock);
 
@@ -641,7 +660,10 @@ int svc_recv(struct svc_rqst *rqstp, long timeout)
                        svc_thread_dequeue(pool, rqstp);
                        spin_unlock_bh(&pool->sp_lock);
                        dprintk("svc: server %p, no data yet\n", rqstp);
-                       return signalled()? -EINTR : -EAGAIN;
+                       if (signalled() || kthread_should_stop())
+                               return -EINTR;
+                       else
+                               return -EAGAIN;
                }
        }
        spin_unlock_bh(&pool->sp_lock);
index 3c64051e455533aeb11df479f3c72877838e4483..3f30ee6006ae449c14ea7540dd548ec96859b451 100644 (file)
@@ -11,7 +11,8 @@
 #include <linux/hash.h>
 #include <linux/string.h>
 #include <net/sock.h>
-
+#include <net/ipv6.h>
+#include <linux/kernel.h>
 #define RPCDBG_FACILITY        RPCDBG_AUTH
 
 
@@ -85,7 +86,7 @@ static void svcauth_unix_domain_release(struct auth_domain *dom)
 struct ip_map {
        struct cache_head       h;
        char                    m_class[8]; /* e.g. "nfsd" */
-       struct in_addr          m_addr;
+       struct in6_addr         m_addr;
        struct unix_domain      *m_client;
        int                     m_add_change;
 };
@@ -113,12 +114,19 @@ static inline int hash_ip(__be32 ip)
        return (hash ^ (hash>>8)) & 0xff;
 }
 #endif
+static inline int hash_ip6(struct in6_addr ip)
+{
+       return (hash_ip(ip.s6_addr32[0]) ^
+               hash_ip(ip.s6_addr32[1]) ^
+               hash_ip(ip.s6_addr32[2]) ^
+               hash_ip(ip.s6_addr32[3]));
+}
 static int ip_map_match(struct cache_head *corig, struct cache_head *cnew)
 {
        struct ip_map *orig = container_of(corig, struct ip_map, h);
        struct ip_map *new = container_of(cnew, struct ip_map, h);
        return strcmp(orig->m_class, new->m_class) == 0
-               && orig->m_addr.s_addr == new->m_addr.s_addr;
+               && ipv6_addr_equal(&orig->m_addr, &new->m_addr);
 }
 static void ip_map_init(struct cache_head *cnew, struct cache_head *citem)
 {
@@ -126,7 +134,7 @@ static void ip_map_init(struct cache_head *cnew, struct cache_head *citem)
        struct ip_map *item = container_of(citem, struct ip_map, h);
 
        strcpy(new->m_class, item->m_class);
-       new->m_addr.s_addr = item->m_addr.s_addr;
+       ipv6_addr_copy(&new->m_addr, &item->m_addr);
 }
 static void update(struct cache_head *cnew, struct cache_head *citem)
 {
@@ -150,22 +158,24 @@ static void ip_map_request(struct cache_detail *cd,
                                  struct cache_head *h,
                                  char **bpp, int *blen)
 {
-       char text_addr[20];
+       char text_addr[40];
        struct ip_map *im = container_of(h, struct ip_map, h);
-       __be32 addr = im->m_addr.s_addr;
-
-       snprintf(text_addr, 20, "%u.%u.%u.%u",
-                ntohl(addr) >> 24 & 0xff,
-                ntohl(addr) >> 16 & 0xff,
-                ntohl(addr) >>  8 & 0xff,
-                ntohl(addr) >>  0 & 0xff);
 
+       if (ipv6_addr_v4mapped(&(im->m_addr))) {
+               snprintf(text_addr, 20, NIPQUAD_FMT,
+                               ntohl(im->m_addr.s6_addr32[3]) >> 24 & 0xff,
+                               ntohl(im->m_addr.s6_addr32[3]) >> 16 & 0xff,
+                               ntohl(im->m_addr.s6_addr32[3]) >>  8 & 0xff,
+                               ntohl(im->m_addr.s6_addr32[3]) >>  0 & 0xff);
+       } else {
+               snprintf(text_addr, 40, NIP6_FMT, NIP6(im->m_addr));
+       }
        qword_add(bpp, blen, im->m_class);
        qword_add(bpp, blen, text_addr);
        (*bpp)[-1] = '\n';
 }
 
-static struct ip_map *ip_map_lookup(char *class, struct in_addr addr);
+static struct ip_map *ip_map_lookup(char *class, struct in6_addr *addr);
 static int ip_map_update(struct ip_map *ipm, struct unix_domain *udom, time_t expiry);
 
 static int ip_map_parse(struct cache_detail *cd,
@@ -176,10 +186,10 @@ static int ip_map_parse(struct cache_detail *cd,
         * for scratch: */
        char *buf = mesg;
        int len;
-       int b1,b2,b3,b4;
+       int b1, b2, b3, b4, b5, b6, b7, b8;
        char c;
        char class[8];
-       struct in_addr addr;
+       struct in6_addr addr;
        int err;
 
        struct ip_map *ipmp;
@@ -198,7 +208,23 @@ static int ip_map_parse(struct cache_detail *cd,
        len = qword_get(&mesg, buf, mlen);
        if (len <= 0) return -EINVAL;
 
-       if (sscanf(buf, "%u.%u.%u.%u%c", &b1, &b2, &b3, &b4, &c) != 4)
+       if (sscanf(buf, NIPQUAD_FMT "%c", &b1, &b2, &b3, &b4, &c) == 4) {
+               addr.s6_addr32[0] = 0;
+               addr.s6_addr32[1] = 0;
+               addr.s6_addr32[2] = htonl(0xffff);
+               addr.s6_addr32[3] =
+                       htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4);
+       } else if (sscanf(buf, NIP6_FMT "%c",
+                       &b1, &b2, &b3, &b4, &b5, &b6, &b7, &b8, &c) == 8) {
+               addr.s6_addr16[0] = htons(b1);
+               addr.s6_addr16[1] = htons(b2);
+               addr.s6_addr16[2] = htons(b3);
+               addr.s6_addr16[3] = htons(b4);
+               addr.s6_addr16[4] = htons(b5);
+               addr.s6_addr16[5] = htons(b6);
+               addr.s6_addr16[6] = htons(b7);
+               addr.s6_addr16[7] = htons(b8);
+       } else
                return -EINVAL;
 
        expiry = get_expiry(&mesg);
@@ -216,10 +242,7 @@ static int ip_map_parse(struct cache_detail *cd,
        } else
                dom = NULL;
 
-       addr.s_addr =
-               htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4);
-
-       ipmp = ip_map_lookup(class,addr);
+       ipmp = ip_map_lookup(class, &addr);
        if (ipmp) {
                err = ip_map_update(ipmp,
                             container_of(dom, struct unix_domain, h),
@@ -239,7 +262,7 @@ static int ip_map_show(struct seq_file *m,
                       struct cache_head *h)
 {
        struct ip_map *im;
-       struct in_addr addr;
+       struct in6_addr addr;
        char *dom = "-no-domain-";
 
        if (h == NULL) {
@@ -248,20 +271,24 @@ static int ip_map_show(struct seq_file *m,
        }
        im = container_of(h, struct ip_map, h);
        /* class addr domain */
-       addr = im->m_addr;
+       ipv6_addr_copy(&addr, &im->m_addr);
 
        if (test_bit(CACHE_VALID, &h->flags) &&
            !test_bit(CACHE_NEGATIVE, &h->flags))
                dom = im->m_client->h.name;
 
-       seq_printf(m, "%s %d.%d.%d.%d %s\n",
-                  im->m_class,
-                  ntohl(addr.s_addr) >> 24 & 0xff,
-                  ntohl(addr.s_addr) >> 16 & 0xff,
-                  ntohl(addr.s_addr) >>  8 & 0xff,
-                  ntohl(addr.s_addr) >>  0 & 0xff,
-                  dom
-                  );
+       if (ipv6_addr_v4mapped(&addr)) {
+               seq_printf(m, "%s" NIPQUAD_FMT "%s\n",
+                       im->m_class,
+                       ntohl(addr.s6_addr32[3]) >> 24 & 0xff,
+                       ntohl(addr.s6_addr32[3]) >> 16 & 0xff,
+                       ntohl(addr.s6_addr32[3]) >>  8 & 0xff,
+                       ntohl(addr.s6_addr32[3]) >>  0 & 0xff,
+                       dom);
+       } else {
+               seq_printf(m, "%s" NIP6_FMT "%s\n",
+                       im->m_class, NIP6(addr), dom);
+       }
        return 0;
 }
 
@@ -281,16 +308,16 @@ struct cache_detail ip_map_cache = {
        .alloc          = ip_map_alloc,
 };
 
-static struct ip_map *ip_map_lookup(char *class, struct in_addr addr)
+static struct ip_map *ip_map_lookup(char *class, struct in6_addr *addr)
 {
        struct ip_map ip;
        struct cache_head *ch;
 
        strcpy(ip.m_class, class);
-       ip.m_addr = addr;
+       ipv6_addr_copy(&ip.m_addr, addr);
        ch = sunrpc_cache_lookup(&ip_map_cache, &ip.h,
                                 hash_str(class, IP_HASHBITS) ^
-                                hash_ip(addr.s_addr));
+                                hash_ip6(*addr));
 
        if (ch)
                return container_of(ch, struct ip_map, h);
@@ -319,14 +346,14 @@ static int ip_map_update(struct ip_map *ipm, struct unix_domain *udom, time_t ex
        ch = sunrpc_cache_update(&ip_map_cache,
                                 &ip.h, &ipm->h,
                                 hash_str(ipm->m_class, IP_HASHBITS) ^
-                                hash_ip(ipm->m_addr.s_addr));
+                                hash_ip6(ipm->m_addr));
        if (!ch)
                return -ENOMEM;
        cache_put(ch, &ip_map_cache);
        return 0;
 }
 
-int auth_unix_add_addr(struct in_addr addr, struct auth_domain *dom)
+int auth_unix_add_addr(struct in6_addr *addr, struct auth_domain *dom)
 {
        struct unix_domain *udom;
        struct ip_map *ipmp;
@@ -355,7 +382,7 @@ int auth_unix_forget_old(struct auth_domain *dom)
 }
 EXPORT_SYMBOL(auth_unix_forget_old);
 
-struct auth_domain *auth_unix_lookup(struct in_addr addr)
+struct auth_domain *auth_unix_lookup(struct in6_addr *addr)
 {
        struct ip_map *ipm;
        struct auth_domain *rv;
@@ -650,9 +677,24 @@ static int unix_gid_find(uid_t uid, struct group_info **gip,
 int
 svcauth_unix_set_client(struct svc_rqst *rqstp)
 {
-       struct sockaddr_in *sin = svc_addr_in(rqstp);
+       struct sockaddr_in *sin;
+       struct sockaddr_in6 *sin6, sin6_storage;
        struct ip_map *ipm;
 
+       switch (rqstp->rq_addr.ss_family) {
+       case AF_INET:
+               sin = svc_addr_in(rqstp);
+               sin6 = &sin6_storage;
+               ipv6_addr_set(&sin6->sin6_addr, 0, 0,
+                               htonl(0x0000FFFF), sin->sin_addr.s_addr);
+               break;
+       case AF_INET6:
+               sin6 = svc_addr_in6(rqstp);
+               break;
+       default:
+               BUG();
+       }
+
        rqstp->rq_client = NULL;
        if (rqstp->rq_proc == 0)
                return SVC_OK;
@@ -660,7 +702,7 @@ svcauth_unix_set_client(struct svc_rqst *rqstp)
        ipm = ip_map_cached_get(rqstp);
        if (ipm == NULL)
                ipm = ip_map_lookup(rqstp->rq_server->sv_program->pg_class,
-                                   sin->sin_addr);
+                                   &sin6->sin6_addr);
 
        if (ipm == NULL)
                return SVC_DENIED;
index c475977de05aa13240292e7ec16ab2fe9789f94a..3e65719f1ef698891d8e81ebea6c57e72b212717 100644 (file)
@@ -38,6 +38,7 @@
 #include <net/checksum.h>
 #include <net/ip.h>
 #include <net/ipv6.h>
+#include <net/tcp.h>
 #include <net/tcp_states.h>
 #include <asm/uaccess.h>
 #include <asm/ioctls.h>
@@ -45,6 +46,7 @@
 #include <linux/sunrpc/types.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/xdr.h>
+#include <linux/sunrpc/msg_prot.h>
 #include <linux/sunrpc/svcsock.h>
 #include <linux/sunrpc/stats.h>
 
@@ -822,8 +824,8 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp)
         * the next four bytes. Otherwise try to gobble up as much as
         * possible up to the complete record length.
         */
-       if (svsk->sk_tcplen < 4) {
-               unsigned long   want = 4 - svsk->sk_tcplen;
+       if (svsk->sk_tcplen < sizeof(rpc_fraghdr)) {
+               int             want = sizeof(rpc_fraghdr) - svsk->sk_tcplen;
                struct kvec     iov;
 
                iov.iov_base = ((char *) &svsk->sk_reclen) + svsk->sk_tcplen;
@@ -833,32 +835,31 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp)
                svsk->sk_tcplen += len;
 
                if (len < want) {
-                       dprintk("svc: short recvfrom while reading record length (%d of %lu)\n",
-                               len, want);
+                       dprintk("svc: short recvfrom while reading record "
+                               "length (%d of %d)\n", len, want);
                        svc_xprt_received(&svsk->sk_xprt);
                        return -EAGAIN; /* record header not complete */
                }
 
                svsk->sk_reclen = ntohl(svsk->sk_reclen);
-               if (!(svsk->sk_reclen & 0x80000000)) {
+               if (!(svsk->sk_reclen & RPC_LAST_STREAM_FRAGMENT)) {
                        /* FIXME: technically, a record can be fragmented,
                         *  and non-terminal fragments will not have the top
                         *  bit set in the fragment length header.
                         *  But apparently no known nfs clients send fragmented
                         *  records. */
                        if (net_ratelimit())
-                               printk(KERN_NOTICE "RPC: bad TCP reclen 0x%08lx"
-                                      " (non-terminal)\n",
-                                      (unsigned long) svsk->sk_reclen);
+                               printk(KERN_NOTICE "RPC: multiple fragments "
+                                       "per record not supported\n");
                        goto err_delete;
                }
-               svsk->sk_reclen &= 0x7fffffff;
+               svsk->sk_reclen &= RPC_FRAGMENT_SIZE_MASK;
                dprintk("svc: TCP record, %d bytes\n", svsk->sk_reclen);
                if (svsk->sk_reclen > serv->sv_max_mesg) {
                        if (net_ratelimit())
-                               printk(KERN_NOTICE "RPC: bad TCP reclen 0x%08lx"
-                                      " (large)\n",
-                                      (unsigned long) svsk->sk_reclen);
+                               printk(KERN_NOTICE "RPC: "
+                                       "fragment too large: 0x%08lx\n",
+                                       (unsigned long)svsk->sk_reclen);
                        goto err_delete;
                }
        }
@@ -1045,7 +1046,6 @@ void svc_cleanup_xprt_sock(void)
 static void svc_tcp_init(struct svc_sock *svsk, struct svc_serv *serv)
 {
        struct sock     *sk = svsk->sk_sk;
-       struct tcp_sock *tp = tcp_sk(sk);
 
        svc_xprt_init(&svc_tcp_class, &svsk->sk_xprt, serv);
        set_bit(XPT_CACHE_AUTH, &svsk->sk_xprt.xpt_flags);
@@ -1063,7 +1063,7 @@ static void svc_tcp_init(struct svc_sock *svsk, struct svc_serv *serv)
                svsk->sk_reclen = 0;
                svsk->sk_tcplen = 0;
 
-               tp->nonagle = 1;        /* disable Nagle's algorithm */
+               tcp_sk(sk)->nonagle |= TCP_NAGLE_OFF;
 
                /* initialise setting must have enough space to
                 * receive and respond to one request.
@@ -1101,6 +1101,7 @@ void svc_sock_update_bufs(struct svc_serv *serv)
        }
        spin_unlock_bh(&serv->sv_lock);
 }
+EXPORT_SYMBOL(svc_sock_update_bufs);
 
 /*
  * Initialize socket for RPC use and create svc_sock struct
index d5553b8179f91c98a94d98766876b14c1aab0e18..75d748eee0eb81d4339b8b258dccc8dd653d7d0f 100644 (file)
@@ -188,9 +188,9 @@ out_sleep:
        task->tk_timeout = 0;
        task->tk_status = -EAGAIN;
        if (req && req->rq_ntrans)
-               rpc_sleep_on(&xprt->resend, task, NULL, NULL);
+               rpc_sleep_on(&xprt->resend, task, NULL);
        else
-               rpc_sleep_on(&xprt->sending, task, NULL, NULL);
+               rpc_sleep_on(&xprt->sending, task, NULL);
        return 0;
 }
 EXPORT_SYMBOL_GPL(xprt_reserve_xprt);
@@ -238,9 +238,9 @@ out_sleep:
        task->tk_timeout = 0;
        task->tk_status = -EAGAIN;
        if (req && req->rq_ntrans)
-               rpc_sleep_on(&xprt->resend, task, NULL, NULL);
+               rpc_sleep_on(&xprt->resend, task, NULL);
        else
-               rpc_sleep_on(&xprt->sending, task, NULL, NULL);
+               rpc_sleep_on(&xprt->sending, task, NULL);
        return 0;
 }
 EXPORT_SYMBOL_GPL(xprt_reserve_xprt_cong);
@@ -447,13 +447,13 @@ EXPORT_SYMBOL_GPL(xprt_wake_pending_tasks);
  * @task: task to be put to sleep
  *
  */
-void xprt_wait_for_buffer_space(struct rpc_task *task)
+void xprt_wait_for_buffer_space(struct rpc_task *task, rpc_action action)
 {
        struct rpc_rqst *req = task->tk_rqstp;
        struct rpc_xprt *xprt = req->rq_xprt;
 
        task->tk_timeout = req->rq_timeout;
-       rpc_sleep_on(&xprt->pending, task, NULL, NULL);
+       rpc_sleep_on(&xprt->pending, task, action);
 }
 EXPORT_SYMBOL_GPL(xprt_wait_for_buffer_space);
 
@@ -472,7 +472,7 @@ void xprt_write_space(struct rpc_xprt *xprt)
        if (xprt->snd_task) {
                dprintk("RPC:       write space: waking waiting task on "
                                "xprt %p\n", xprt);
-               rpc_wake_up_task(xprt->snd_task);
+               rpc_wake_up_queued_task(&xprt->pending, xprt->snd_task);
        }
        spin_unlock_bh(&xprt->transport_lock);
 }
@@ -602,11 +602,37 @@ void xprt_force_disconnect(struct rpc_xprt *xprt)
        /* Try to schedule an autoclose RPC call */
        if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0)
                queue_work(rpciod_workqueue, &xprt->task_cleanup);
-       else if (xprt->snd_task != NULL)
-               rpc_wake_up_task(xprt->snd_task);
+       xprt_wake_pending_tasks(xprt, -ENOTCONN);
+       spin_unlock_bh(&xprt->transport_lock);
+}
+
+/**
+ * xprt_conditional_disconnect - force a transport to disconnect
+ * @xprt: transport to disconnect
+ * @cookie: 'connection cookie'
+ *
+ * This attempts to break the connection if and only if 'cookie' matches
+ * the current transport 'connection cookie'. It ensures that we don't
+ * try to break the connection more than once when we need to retransmit
+ * a batch of RPC requests.
+ *
+ */
+void xprt_conditional_disconnect(struct rpc_xprt *xprt, unsigned int cookie)
+{
+       /* Don't race with the test_bit() in xprt_clear_locked() */
+       spin_lock_bh(&xprt->transport_lock);
+       if (cookie != xprt->connect_cookie)
+               goto out;
+       if (test_bit(XPRT_CLOSING, &xprt->state) || !xprt_connected(xprt))
+               goto out;
+       set_bit(XPRT_CLOSE_WAIT, &xprt->state);
+       /* Try to schedule an autoclose RPC call */
+       if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0)
+               queue_work(rpciod_workqueue, &xprt->task_cleanup);
+       xprt_wake_pending_tasks(xprt, -ENOTCONN);
+out:
        spin_unlock_bh(&xprt->transport_lock);
 }
-EXPORT_SYMBOL_GPL(xprt_force_disconnect);
 
 static void
 xprt_init_autodisconnect(unsigned long data)
@@ -653,7 +679,7 @@ void xprt_connect(struct rpc_task *task)
                        task->tk_rqstp->rq_bytes_sent = 0;
 
                task->tk_timeout = xprt->connect_timeout;
-               rpc_sleep_on(&xprt->pending, task, xprt_connect_status, NULL);
+               rpc_sleep_on(&xprt->pending, task, xprt_connect_status);
                xprt->stat.connect_start = jiffies;
                xprt->ops->connect(task);
        }
@@ -749,18 +775,20 @@ EXPORT_SYMBOL_GPL(xprt_update_rtt);
 void xprt_complete_rqst(struct rpc_task *task, int copied)
 {
        struct rpc_rqst *req = task->tk_rqstp;
+       struct rpc_xprt *xprt = req->rq_xprt;
 
        dprintk("RPC: %5u xid %08x complete (%d bytes received)\n",
                        task->tk_pid, ntohl(req->rq_xid), copied);
 
-       task->tk_xprt->stat.recvs++;
+       xprt->stat.recvs++;
        task->tk_rtt = (long)jiffies - req->rq_xtime;
 
        list_del_init(&req->rq_list);
+       req->rq_private_buf.len = copied;
        /* Ensure all writes are done before we update req->rq_received */
        smp_wmb();
-       req->rq_received = req->rq_private_buf.len = copied;
-       rpc_wake_up_task(task);
+       req->rq_received = copied;
+       rpc_wake_up_queued_task(&xprt->pending, task);
 }
 EXPORT_SYMBOL_GPL(xprt_complete_rqst);
 
@@ -769,17 +797,17 @@ static void xprt_timer(struct rpc_task *task)
        struct rpc_rqst *req = task->tk_rqstp;
        struct rpc_xprt *xprt = req->rq_xprt;
 
+       if (task->tk_status != -ETIMEDOUT)
+               return;
        dprintk("RPC: %5u xprt_timer\n", task->tk_pid);
 
-       spin_lock(&xprt->transport_lock);
+       spin_lock_bh(&xprt->transport_lock);
        if (!req->rq_received) {
                if (xprt->ops->timer)
                        xprt->ops->timer(task);
-               task->tk_status = -ETIMEDOUT;
-       }
-       task->tk_timeout = 0;
-       rpc_wake_up_task(task);
-       spin_unlock(&xprt->transport_lock);
+       } else
+               task->tk_status = 0;
+       spin_unlock_bh(&xprt->transport_lock);
 }
 
 /**
@@ -849,6 +877,7 @@ void xprt_transmit(struct rpc_task *task)
        } else if (!req->rq_bytes_sent)
                return;
 
+       req->rq_connect_cookie = xprt->connect_cookie;
        status = xprt->ops->send_request(task);
        if (status == 0) {
                dprintk("RPC: %5u xmit complete\n", task->tk_pid);
@@ -864,7 +893,7 @@ void xprt_transmit(struct rpc_task *task)
                if (!xprt_connected(xprt))
                        task->tk_status = -ENOTCONN;
                else if (!req->rq_received)
-                       rpc_sleep_on(&xprt->pending, task, NULL, xprt_timer);
+                       rpc_sleep_on(&xprt->pending, task, xprt_timer);
                spin_unlock_bh(&xprt->transport_lock);
                return;
        }
@@ -875,7 +904,7 @@ void xprt_transmit(struct rpc_task *task)
         */
        task->tk_status = status;
        if (status == -ECONNREFUSED)
-               rpc_sleep_on(&xprt->sending, task, NULL, NULL);
+               rpc_sleep_on(&xprt->sending, task, NULL);
 }
 
 static inline void do_xprt_reserve(struct rpc_task *task)
@@ -895,7 +924,7 @@ static inline void do_xprt_reserve(struct rpc_task *task)
        dprintk("RPC:       waiting for request slot\n");
        task->tk_status = -EAGAIN;
        task->tk_timeout = 0;
-       rpc_sleep_on(&xprt->backlog, task, NULL, NULL);
+       rpc_sleep_on(&xprt->backlog, task, NULL);
 }
 
 /**
@@ -1052,6 +1081,11 @@ static void xprt_destroy(struct kref *kref)
        xprt->shutdown = 1;
        del_timer_sync(&xprt->timer);
 
+       rpc_destroy_wait_queue(&xprt->binding);
+       rpc_destroy_wait_queue(&xprt->pending);
+       rpc_destroy_wait_queue(&xprt->sending);
+       rpc_destroy_wait_queue(&xprt->resend);
+       rpc_destroy_wait_queue(&xprt->backlog);
        /*
         * Tear down transport state and free the rpc_xprt
         */
index 16fd3f6718ff55746168c732ec3f367ef9b61f9a..af408fc1263403beb37989bff89006fc7d42a669 100644 (file)
@@ -1036,6 +1036,8 @@ int svc_rdma_send(struct svcxprt_rdma *xprt, struct ib_send_wr *wr)
                        wait_event(xprt->sc_send_wait,
                                   atomic_read(&xprt->sc_sq_count) <
                                   xprt->sc_sq_depth);
+                       if (test_bit(XPT_CLOSE, &xprt->sc_xprt.xpt_flags))
+                               return 0;
                        continue;
                }
                /* Bumped used SQ WR count and post */
index 613daf8c1ff7a8ac309759b50133f504a2206952..ddbe981ab516a48e42ee289bf0e8ceca88ff7a7e 100644 (file)
@@ -135,12 +135,6 @@ static ctl_table sunrpc_table[] = {
 
 #endif
 
-/*
- * How many times to try sending a request on a socket before waiting
- * for the socket buffer to clear.
- */
-#define XS_SENDMSG_RETRY       (10U)
-
 /*
  * Time out for an RPC UDP socket connect.  UDP socket connects are
  * synchronous, but we set a timeout anyway in case of resource
@@ -516,6 +510,14 @@ out:
        return sent;
 }
 
+static void xs_nospace_callback(struct rpc_task *task)
+{
+       struct sock_xprt *transport = container_of(task->tk_rqstp->rq_xprt, struct sock_xprt, xprt);
+
+       transport->inet->sk_write_pending--;
+       clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags);
+}
+
 /**
  * xs_nospace - place task on wait queue if transmit was incomplete
  * @task: task to put to sleep
@@ -531,20 +533,27 @@ static void xs_nospace(struct rpc_task *task)
                        task->tk_pid, req->rq_slen - req->rq_bytes_sent,
                        req->rq_slen);
 
-       if (test_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags)) {
-               /* Protect against races with write_space */
-               spin_lock_bh(&xprt->transport_lock);
-
-               /* Don't race with disconnect */
-               if (!xprt_connected(xprt))
-                       task->tk_status = -ENOTCONN;
-               else if (test_bit(SOCK_NOSPACE, &transport->sock->flags))
-                       xprt_wait_for_buffer_space(task);
+       /* Protect against races with write_space */
+       spin_lock_bh(&xprt->transport_lock);
+
+       /* Don't race with disconnect */
+       if (xprt_connected(xprt)) {
+               if (test_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags)) {
+                       /*
+                        * Notify TCP that we're limited by the application
+                        * window size
+                        */
+                       set_bit(SOCK_NOSPACE, &transport->sock->flags);
+                       transport->inet->sk_write_pending++;
+                       /* ...and wait for more buffer space */
+                       xprt_wait_for_buffer_space(task, xs_nospace_callback);
+               }
+       } else {
+               clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags);
+               task->tk_status = -ENOTCONN;
+       }
 
-               spin_unlock_bh(&xprt->transport_lock);
-       } else
-               /* Keep holding the socket if it is blocked */
-               rpc_delay(task, HZ>>4);
+       spin_unlock_bh(&xprt->transport_lock);
 }
 
 /**
@@ -588,19 +597,20 @@ static int xs_udp_send_request(struct rpc_task *task)
        }
 
        switch (status) {
+       case -EAGAIN:
+               xs_nospace(task);
+               break;
        case -ENETUNREACH:
        case -EPIPE:
        case -ECONNREFUSED:
                /* When the server has died, an ICMP port unreachable message
                 * prompts ECONNREFUSED. */
-               break;
-       case -EAGAIN:
-               xs_nospace(task);
+               clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags);
                break;
        default:
+               clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags);
                dprintk("RPC:       sendmsg returned unrecognized error %d\n",
                        -status);
-               break;
        }
 
        return status;
@@ -650,7 +660,6 @@ static int xs_tcp_send_request(struct rpc_task *task)
        struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
        struct xdr_buf *xdr = &req->rq_snd_buf;
        int status;
-       unsigned int retry = 0;
 
        xs_encode_tcp_record_marker(&req->rq_snd_buf);
 
@@ -681,9 +690,10 @@ static int xs_tcp_send_request(struct rpc_task *task)
                        return 0;
                }
 
+               if (status != 0)
+                       continue;
                status = -EAGAIN;
-               if (retry++ > XS_SENDMSG_RETRY)
-                       break;
+               break;
        }
 
        switch (status) {
@@ -695,12 +705,13 @@ static int xs_tcp_send_request(struct rpc_task *task)
        case -ENOTCONN:
        case -EPIPE:
                status = -ENOTCONN;
+               clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags);
                break;
        default:
                dprintk("RPC:       sendmsg returned unrecognized error %d\n",
                        -status);
+               clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags);
                xs_tcp_shutdown(xprt);
-               break;
        }
 
        return status;
@@ -1073,6 +1084,7 @@ static void xs_tcp_data_ready(struct sock *sk, int bytes)
 {
        struct rpc_xprt *xprt;
        read_descriptor_t rd_desc;
+       int read;
 
        dprintk("RPC:       xs_tcp_data_ready...\n");
 
@@ -1084,8 +1096,10 @@ static void xs_tcp_data_ready(struct sock *sk, int bytes)
 
        /* We use rd_desc to pass struct xprt to xs_tcp_data_recv */
        rd_desc.arg.data = xprt;
-       rd_desc.count = 65536;
-       tcp_read_sock(sk, &rd_desc, xs_tcp_data_recv);
+       do {
+               rd_desc.count = 65536;
+               read = tcp_read_sock(sk, &rd_desc, xs_tcp_data_recv);
+       } while (read > 0);
 out:
        read_unlock(&sk->sk_callback_lock);
 }
@@ -1128,6 +1142,7 @@ static void xs_tcp_state_change(struct sock *sk)
                break;
        case TCP_FIN_WAIT1:
                /* The client initiated a shutdown of the socket */
+               xprt->connect_cookie++;
                xprt->reestablish_timeout = 0;
                set_bit(XPRT_CLOSING, &xprt->state);
                smp_mb__before_clear_bit();
@@ -1140,6 +1155,7 @@ static void xs_tcp_state_change(struct sock *sk)
                set_bit(XPRT_CLOSING, &xprt->state);
                xprt_force_disconnect(xprt);
        case TCP_SYN_SENT:
+               xprt->connect_cookie++;
        case TCP_CLOSING:
                /*
                 * If the server closed down the connection, make sure that
@@ -1186,9 +1202,11 @@ static void xs_udp_write_space(struct sock *sk)
 
                if (unlikely(!(sock = sk->sk_socket)))
                        goto out;
+               clear_bit(SOCK_NOSPACE, &sock->flags);
+
                if (unlikely(!(xprt = xprt_from_sock(sk))))
                        goto out;
-               if (unlikely(!test_and_clear_bit(SOCK_NOSPACE, &sock->flags)))
+               if (test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags) == 0)
                        goto out;
 
                xprt_write_space(xprt);
@@ -1219,9 +1237,11 @@ static void xs_tcp_write_space(struct sock *sk)
 
                if (unlikely(!(sock = sk->sk_socket)))
                        goto out;
+               clear_bit(SOCK_NOSPACE, &sock->flags);
+
                if (unlikely(!(xprt = xprt_from_sock(sk))))
                        goto out;
-               if (unlikely(!test_and_clear_bit(SOCK_NOSPACE, &sock->flags)))
+               if (test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags) == 0)
                        goto out;
 
                xprt_write_space(xprt);
index 1454afcc06c48e962298ac9934b3dfbe35965dcc..e18cd3628db4f7fe12ad6acc9fe6c0922d022a82 100644 (file)
@@ -2197,7 +2197,11 @@ static void __exit af_unix_exit(void)
        unregister_pernet_subsys(&unix_net_ops);
 }
 
-module_init(af_unix_init);
+/* Earlier than device_initcall() so that other drivers invoking
+   request_module() don't end up in a loop when modprobe tries
+   to use a UNIX socket. But later than subsys_initcall() because
+   we depend on stuff initialised there */
+fs_initcall(af_unix_init);
 module_exit(af_unix_exit);
 
 MODULE_LICENSE("GPL");
index 8704e2825b109f392c27d42ce532ab9cae5d6e82..5b3274b465eb5b22cdf525bc26d4855e4c371096 100644 (file)
@@ -72,7 +72,7 @@ static unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97, unsigned short reg
        if (wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1) <= 0 &&
            !((GSR | gsr_bits) & GSR_SDONE)) {
                printk(KERN_ERR "%s: read error (ac97_reg=%d GSR=%#lx)\n",
-                               __FUNCTION__, reg, GSR | gsr_bits);
+                               __func__, reg, GSR | gsr_bits);
                val = -1;
                goto out;
        }
@@ -104,7 +104,7 @@ static void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigne
        if (wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_CDONE, 1) <= 0 &&
            !((GSR | gsr_bits) & GSR_CDONE))
                printk(KERN_ERR "%s: write error (ac97_reg=%d GSR=%#lx)\n",
-                               __FUNCTION__, reg, GSR | gsr_bits);
+                               __func__, reg, GSR | gsr_bits);
 
        mutex_unlock(&car_mutex);
 }
@@ -112,6 +112,16 @@ static void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigne
 static void pxa2xx_ac97_reset(struct snd_ac97 *ac97)
 {
        /* First, try cold reset */
+#ifdef CONFIG_PXA3xx
+       int timeout;
+
+       /* Hold CLKBPB for 100us */
+       GCR = 0;
+       GCR = GCR_CLKBPB;
+       udelay(100);
+       GCR = 0;
+#endif
+
        GCR &=  GCR_COLD_RST;  /* clear everything but nCRST */
        GCR &= ~GCR_COLD_RST;  /* then assert nCRST */
 
@@ -123,6 +133,14 @@ static void pxa2xx_ac97_reset(struct snd_ac97 *ac97)
        clk_disable(ac97conf_clk);
        GCR = GCR_COLD_RST;
        udelay(50);
+#elif defined(CONFIG_PXA3xx)
+       timeout = 1000;
+       /* Can't use interrupts on PXA3xx */
+       GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);
+
+       GCR = GCR_WARM_RST | GCR_COLD_RST;
+       while (!(GSR & (GSR_PCR | GSR_SCR)) && timeout--)
+               mdelay(10);
 #else
        GCR = GCR_COLD_RST;
        GCR |= GCR_CDONE_IE|GCR_SDONE_IE;
@@ -131,7 +149,7 @@ static void pxa2xx_ac97_reset(struct snd_ac97 *ac97)
 
        if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR))) {
                printk(KERN_INFO "%s: cold reset timeout (GSR=%#lx)\n",
-                                __FUNCTION__, gsr_bits);
+                                __func__, gsr_bits);
 
                /* let's try warm reset */
                gsr_bits = 0;
@@ -143,6 +161,12 @@ static void pxa2xx_ac97_reset(struct snd_ac97 *ac97)
                GCR |= GCR_WARM_RST;
                pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
                udelay(500);
+#elif defined(CONFIG_PXA3xx)
+               timeout = 100;
+               /* Can't use interrupts */
+               GCR |= GCR_WARM_RST;
+               while (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)) && timeout--)
+                       mdelay(1);
 #else
                GCR |= GCR_WARM_RST|GCR_PRIRDY_IEN|GCR_SECRDY_IEN;
                wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1);
@@ -150,7 +174,7 @@ static void pxa2xx_ac97_reset(struct snd_ac97 *ac97)
 
                if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)))
                        printk(KERN_INFO "%s: warm reset timeout (GSR=%#lx)\n",
-                                        __FUNCTION__, gsr_bits);
+                                        __func__, gsr_bits);
        }
 
        GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);
@@ -424,6 +448,7 @@ static struct platform_driver pxa2xx_ac97_driver = {
        .resume         = pxa2xx_ac97_resume,
        .driver         = {
                .name   = "pxa2xx-ac97",
+               .owner  = THIS_MODULE,
        },
 };
 
@@ -443,3 +468,4 @@ module_exit(pxa2xx_ac97_exit);
 MODULE_AUTHOR("Nicolas Pitre");
 MODULE_DESCRIPTION("AC97 driver for the Intel PXA2xx chip");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pxa2xx-ac97");
index 829ca38b595e82d63eabb932506fb126eff723bf..a8d71c6c8e7593f1619733bc7c9635bf118d43ca 100644 (file)
@@ -181,3 +181,7 @@ config SND_PCM_XRUN_DEBUG
          It is usually not required, but if you have trouble with
          sound clicking when system is loaded, it may help to determine
          the process or driver which causes the scheduling gaps.
+
+config SND_VMASTER
+       bool
+       depends on SND
index 267039a97bd51e1beca02ba63de7cb70305e87f3..da8e685eef9c38b1af620acb1c25d403223fd0aa 100644 (file)
@@ -6,6 +6,7 @@
 snd-y     := sound.o init.o memory.o info.o control.o misc.o device.o
 snd-$(CONFIG_ISA_DMA_API) += isadma.o
 snd-$(CONFIG_SND_OSSEMUL) += sound_oss.o info_oss.o
+snd-$(CONFIG_SND_VMASTER) += vmaster.o
 
 snd-pcm-objs := pcm.o pcm_native.o pcm_lib.o pcm_timer.o pcm_misc.o \
                pcm_memory.o
index e3338d6071efb993ae9370bf634fdf28ebb27e42..ac0573416130d56b480caf2948a88f1017ad3bb8 100644 (file)
@@ -254,7 +254,7 @@ static int snd_disconnect_release(struct inode *inode, struct file *file)
        if (likely(df))
                return df->disconnected_f_op->release(inode, file);
 
-       panic("%s(%p, %p) failed!", __FUNCTION__, inode, file);
+       panic("%s(%p, %p) failed!", __func__, inode, file);
 }
 
 static unsigned int snd_disconnect_poll(struct file * file, poll_table * wait)
@@ -311,6 +311,9 @@ int snd_card_disconnect(struct snd_card *card)
        struct file *file;
        int err;
 
+       if (!card)
+               return -EINVAL;
+
        spin_lock(&card->files_lock);
        if (card->shutdown) {
                spin_unlock(&card->files_lock);
@@ -322,6 +325,7 @@ int snd_card_disconnect(struct snd_card *card)
        /* phase 1: disable fops (user space) operations for ALSA API */
        mutex_lock(&snd_card_mutex);
        snd_cards[card->number] = NULL;
+       snd_cards_lock &= ~(1 << card->number);
        mutex_unlock(&snd_card_mutex);
        
        /* phase 2: replace file->f_op with special dummy operations */
@@ -360,6 +364,15 @@ int snd_card_disconnect(struct snd_card *card)
                snd_printk(KERN_ERR "not all devices for card %i can be disconnected\n", card->number);
 
        snd_info_card_disconnect(card);
+#ifndef CONFIG_SYSFS_DEPRECATED
+       if (card->card_dev) {
+               device_unregister(card->card_dev);
+               card->card_dev = NULL;
+       }
+#endif
+#ifdef CONFIG_PM
+       wake_up(&card->power_sleep);
+#endif
        return 0;       
 }
 
@@ -401,33 +414,14 @@ static int snd_card_do_free(struct snd_card *card)
                snd_printk(KERN_WARNING "unable to free card info\n");
                /* Not fatal error */
        }
-#ifndef CONFIG_SYSFS_DEPRECATED
-       if (card->card_dev)
-               device_unregister(card->card_dev);
-#endif
        kfree(card);
        return 0;
 }
 
-static int snd_card_free_prepare(struct snd_card *card)
-{
-       if (card == NULL)
-               return -EINVAL;
-       (void) snd_card_disconnect(card);
-       mutex_lock(&snd_card_mutex);
-       snd_cards[card->number] = NULL;
-       snd_cards_lock &= ~(1 << card->number);
-       mutex_unlock(&snd_card_mutex);
-#ifdef CONFIG_PM
-       wake_up(&card->power_sleep);
-#endif
-       return 0;
-}
-
 int snd_card_free_when_closed(struct snd_card *card)
 {
        int free_now = 0;
-       int ret = snd_card_free_prepare(card);
+       int ret = snd_card_disconnect(card);
        if (ret)
                return ret;
 
@@ -447,7 +441,7 @@ EXPORT_SYMBOL(snd_card_free_when_closed);
 
 int snd_card_free(struct snd_card *card)
 {
-       int ret = snd_card_free_prepare(card);
+       int ret = snd_card_disconnect(card);
        if (ret)
                return ret;
 
index 102d1c36cf26a67386258e28022760b5669844c2..38524f615d9428fc5f8614e9e6b5752eb430fc14 100644 (file)
@@ -39,7 +39,7 @@ void snd_verbose_printk(const char *file, int line, const char *format, ...)
 {
        va_list args;
        
-       if (format[0] == '<' && format[1] >= '0' && format[1] <= '9' && format[2] == '>') {
+       if (format[0] == '<' && format[1] >= '0' && format[1] <= '7' && format[2] == '>') {
                char tmp[] = "<0>";
                tmp[1] = format[1];
                printk("%sALSA %s:%d: ", tmp, file, line);
@@ -60,7 +60,7 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...)
 {
        va_list args;
        
-       if (format[0] == '<' && format[1] >= '0' && format[1] <= '9' && format[2] == '>') {
+       if (format[0] == '<' && format[1] >= '0' && format[1] <= '7' && format[2] == '>') {
                char tmp[] = "<0>";
                tmp[1] = format[1];
                printk("%sALSA %s:%d: ", tmp, file, line);
index 75daed298a15a251fcf3a4af20b4651b905326ea..581aa2c60e6529fab85d27a3250151383e58f49f 100644 (file)
@@ -1257,6 +1257,8 @@ static void snd_mixer_oss_build(struct snd_mixer_oss *mixer)
                { SOUND_MIXER_DIGITAL3, "Digital",              2 },
                { SOUND_MIXER_PHONEIN,  "Phone",                0 },
                { SOUND_MIXER_PHONEOUT, "Master Mono",          0 },
+               { SOUND_MIXER_PHONEOUT, "Speaker",              0 }, /*fallback*/
+               { SOUND_MIXER_PHONEOUT, "Mono",                 0 }, /*fallback*/
                { SOUND_MIXER_PHONEOUT, "Phone",                0 }, /* fallback */
                { SOUND_MIXER_VIDEO,    "Video",                0 },
                { SOUND_MIXER_RADIO,    "Radio",                0 },
index ab570a0a6183650105021644c9e988bb2ccdf64d..558dadbf45f12e39387573ca5566b8d31b5be562 100644 (file)
@@ -245,8 +245,13 @@ snd_seq_oss_synth_setup(struct seq_oss_devinfo *dp)
                info->nr_voices = rec->nr_voices;
                if (info->nr_voices > 0) {
                        info->ch = kcalloc(info->nr_voices, sizeof(struct seq_oss_chinfo), GFP_KERNEL);
-                       if (!info->ch)
-                               BUG();
+                       if (!info->ch) {
+                               snd_printk(KERN_ERR "Cannot malloc\n");
+                               rec->oper.close(&info->arg);
+                               module_put(rec->oper.owner);
+                               snd_use_lock_free(&rec->use_lock);
+                               continue;
+                       }
                        reset_channels(info);
                }
                debug_printk(("synth %d assigned\n", i));
similarity index 97%
rename from sound/pci/hda/vmaster.c
rename to sound/core/vmaster.c
index 2da49d20a1fc65c9acb8ee2b845b9a7d332b282e..4cc57f902e2c9ac03f8b8e6216be27738430d385 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/control.h>
+#include <sound/tlv.h>
 
 /*
  * a subset of information returned via ctl info callback
@@ -34,6 +35,7 @@ struct link_master {
        struct list_head slaves;
        struct link_ctl_info info;
        int val;                /* the master value */
+       unsigned int tlv[4];
 };
 
 /*
@@ -253,6 +255,8 @@ int snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave)
        return 0;
 }
 
+EXPORT_SYMBOL(snd_ctl_add_slave);
+
 /*
  * ctl callbacks for master controls
  */
@@ -355,10 +359,13 @@ struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
        kctl->private_free = master_free;
 
        /* additional (constant) TLV read */
-       if (tlv) {
-               /* FIXME: this assumes that the max volume is 0 dB */
+       if (tlv && tlv[0] == SNDRV_CTL_TLVT_DB_SCALE) {
                kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
-               kctl->tlv.p = tlv;
+               memcpy(master->tlv, tlv, sizeof(master->tlv));
+               kctl->tlv.p = master->tlv;
        }
+
        return kctl;
 }
+
+EXPORT_SYMBOL(snd_ctl_make_virtual_master);
index 75d4fe09fdf363fc2a9fe7ee06439330150c397a..fe85af1c56934ab58ecbb0fda39d92b4f60753c8 100644 (file)
@@ -4,6 +4,24 @@ menu "Generic devices"
        depends on SND!=n
 
 
+config SND_PCSP
+       tristate "Internal PC speaker support"
+       depends on X86_PC && HIGH_RES_TIMERS
+       depends on INPUT
+       help
+         If you don't have a sound card in your computer, you can include a
+         driver for the PC speaker which allows it to act like a primitive
+         sound card.
+         This driver also replaces the pcspkr driver for beeps.
+
+         You can compile this as a module which will be called snd-pcsp.
+
+         You don't need this driver if you only want your pc-speaker to beep.
+         You don't need this driver if you have a tablet piezo beeper
+         in your PC instead of the real speaker.
+
+         It should not hurt to say Y or M here in all other cases.
+
 config SND_MPU401_UART
         tristate
         select SND_RAWMIDI
index 8e5530006e1fccb1d0704e0a35ee14a30105e064..d4a07f9ff2c7117f018971b37b07ea6950af875a 100644 (file)
@@ -20,4 +20,4 @@ obj-$(CONFIG_SND_MTS64) += snd-mts64.o
 obj-$(CONFIG_SND_PORTMAN2X4) += snd-portman2x4.o
 obj-$(CONFIG_SND_ML403_AC97CR) += snd-ml403-ac97cr.o
 
-obj-$(CONFIG_SND) += opl3/ opl4/ mpu401/ vx/
+obj-$(CONFIG_SND) += opl3/ opl4/ mpu401/ vx/ pcsp/
index a240eaeb5c620d754c81a23602e0b4809b4fe40f..4e4c69e6cb4c8e850c66c7a2530eab827d793803 100644 (file)
@@ -181,10 +181,10 @@ struct snd_dummy_pcm {
        struct snd_dummy *dummy;
        spinlock_t lock;
        struct timer_list timer;
-       unsigned int pcm_size;
-       unsigned int pcm_count;
+       unsigned int pcm_buffer_size;
+       unsigned int pcm_period_size;
        unsigned int pcm_bps;           /* bytes per second */
-       unsigned int pcm_jiffie;        /* bytes per one jiffie */
+       unsigned int pcm_hz;            /* HZ */
        unsigned int pcm_irq_pos;       /* IRQ position */
        unsigned int pcm_buf_pos;       /* position in buffer */
        struct snd_pcm_substream *substream;
@@ -230,19 +230,24 @@ static int snd_card_dummy_pcm_prepare(struct snd_pcm_substream *substream)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct snd_dummy_pcm *dpcm = runtime->private_data;
-       unsigned int bps;
+       int bps;
+
+       bps = snd_pcm_format_width(runtime->format) * runtime->rate *
+               runtime->channels / 8;
 
-       bps = runtime->rate * runtime->channels;
-       bps *= snd_pcm_format_width(runtime->format);
-       bps /= 8;
        if (bps <= 0)
                return -EINVAL;
+
        dpcm->pcm_bps = bps;
-       dpcm->pcm_jiffie = bps / HZ;
-       dpcm->pcm_size = snd_pcm_lib_buffer_bytes(substream);
-       dpcm->pcm_count = snd_pcm_lib_period_bytes(substream);
+       dpcm->pcm_hz = HZ;
+       dpcm->pcm_buffer_size = snd_pcm_lib_buffer_bytes(substream);
+       dpcm->pcm_period_size = snd_pcm_lib_period_bytes(substream);
        dpcm->pcm_irq_pos = 0;
        dpcm->pcm_buf_pos = 0;
+
+       snd_pcm_format_set_silence(runtime->format, runtime->dma_area,
+                       bytes_to_samples(runtime, runtime->dma_bytes));
+
        return 0;
 }
 
@@ -254,11 +259,11 @@ static void snd_card_dummy_pcm_timer_function(unsigned long data)
        spin_lock_irqsave(&dpcm->lock, flags);
        dpcm->timer.expires = 1 + jiffies;
        add_timer(&dpcm->timer);
-       dpcm->pcm_irq_pos += dpcm->pcm_jiffie;
-       dpcm->pcm_buf_pos += dpcm->pcm_jiffie;
-       dpcm->pcm_buf_pos %= dpcm->pcm_size;
-       if (dpcm->pcm_irq_pos >= dpcm->pcm_count) {
-               dpcm->pcm_irq_pos %= dpcm->pcm_count;
+       dpcm->pcm_irq_pos += dpcm->pcm_bps;
+       dpcm->pcm_buf_pos += dpcm->pcm_bps;
+       dpcm->pcm_buf_pos %= dpcm->pcm_buffer_size * dpcm->pcm_hz;
+       if (dpcm->pcm_irq_pos >= dpcm->pcm_period_size * dpcm->pcm_hz) {
+               dpcm->pcm_irq_pos %= dpcm->pcm_period_size * dpcm->pcm_hz;
                spin_unlock_irqrestore(&dpcm->lock, flags);
                snd_pcm_period_elapsed(dpcm->substream);
        } else
@@ -270,7 +275,7 @@ static snd_pcm_uframes_t snd_card_dummy_pcm_pointer(struct snd_pcm_substream *su
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct snd_dummy_pcm *dpcm = runtime->private_data;
 
-       return bytes_to_frames(runtime, dpcm->pcm_buf_pos);
+       return bytes_to_frames(runtime, dpcm->pcm_buf_pos / dpcm->pcm_hz);
 }
 
 static struct snd_pcm_hardware snd_card_dummy_playback =
index 05a871aa7b818fd45eed66d40ef396a5075eccc7..ecdbeb6d36033af8a9be9ee69dc0c9896f78cf82 100644 (file)
@@ -1191,8 +1191,6 @@ snd_ml403_ac97cr_create(struct snd_card *card, struct platform_device *pfdev,
                return err;
        }
 
-       snd_card_set_dev(card, &pfdev->dev);
-
        *rml403_ac97cr = ml403_ac97cr;
        return 0;
 }
@@ -1330,11 +1328,15 @@ static int snd_ml403_ac97cr_remove(struct platform_device *pfdev)
        return 0;
 }
 
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:" SND_ML403_AC97CR_DRIVER);
+
 static struct platform_driver snd_ml403_ac97cr_driver = {
        .probe = snd_ml403_ac97cr_probe,
        .remove = snd_ml403_ac97cr_remove,
        .driver = {
                .name = SND_ML403_AC97CR_DRIVER,
+               .owner = THIS_MODULE,
        },
 };
 
index 5993864acbd38ee163c9de45eb205455a5ea1df2..18cca2457d44c1164978cc2453531396d8b38b0a 100644 (file)
@@ -49,12 +49,10 @@ static void snd_mpu401_uart_output_write(struct snd_mpu401 * mpu);
 
  */
 
-#define snd_mpu401_input_avail(mpu)    (!(mpu->read(mpu, MPU401C(mpu)) & 0x80))
-#define snd_mpu401_output_ready(mpu)   (!(mpu->read(mpu, MPU401C(mpu)) & 0x40))
-
-#define MPU401_RESET           0xff
-#define MPU401_ENTER_UART      0x3f
-#define MPU401_ACK             0xfe
+#define snd_mpu401_input_avail(mpu) \
+       (!(mpu->read(mpu, MPU401C(mpu)) & MPU401_RX_EMPTY))
+#define snd_mpu401_output_ready(mpu) \
+       (!(mpu->read(mpu, MPU401C(mpu)) & MPU401_TX_FULL))
 
 /* Build in lowlevel io */
 static void mpu401_write_port(struct snd_mpu401 *mpu, unsigned char data,
@@ -425,16 +423,17 @@ static void snd_mpu401_uart_input_read(struct snd_mpu401 * mpu)
 static void snd_mpu401_uart_output_write(struct snd_mpu401 * mpu)
 {
        unsigned char byte;
-       int max = 256, timeout;
+       int max = 256;
 
        do {
                if (snd_rawmidi_transmit_peek(mpu->substream_output,
                                              &byte, 1) == 1) {
-                       for (timeout = 100; timeout > 0; timeout--) {
-                               if (snd_mpu401_output_ready(mpu))
-                                       break;
-                       }
-                       if (timeout == 0)
+                       /*
+                        * Try twice because there is hardware that insists on
+                        * setting the output busy bit after each write.
+                        */
+                       if (!snd_mpu401_output_ready(mpu) &&
+                           !snd_mpu401_output_ready(mpu))
                                break;  /* Tx FIFO full - try again later */
                        mpu->write(mpu, byte, MPU401D(mpu));
                        snd_rawmidi_transmit_ack(mpu->substream_output, 1);
diff --git a/sound/drivers/pcsp/Makefile b/sound/drivers/pcsp/Makefile
new file mode 100644 (file)
index 0000000..b19555b
--- /dev/null
@@ -0,0 +1,2 @@
+snd-pcsp-objs := pcsp.o pcsp_lib.o pcsp_mixer.o pcsp_input.o
+obj-$(CONFIG_SND_PCSP) += snd-pcsp.o
diff --git a/sound/drivers/pcsp/pcsp.c b/sound/drivers/pcsp/pcsp.c
new file mode 100644 (file)
index 0000000..5920351
--- /dev/null
@@ -0,0 +1,235 @@
+/*
+ * PC-Speaker driver for Linux
+ *
+ * Copyright (C) 1997-2001  David Woodhouse
+ * Copyright (C) 2001-2008  Stas Sergeev
+ */
+
+#include <linux/init.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/pcm.h>
+#include <linux/input.h>
+#include <linux/delay.h>
+#include <asm/bitops.h>
+#include "pcsp_input.h"
+#include "pcsp.h"
+
+MODULE_AUTHOR("Stas Sergeev <stsp@users.sourceforge.net>");
+MODULE_DESCRIPTION("PC-Speaker driver");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("{{PC-Speaker, pcsp}}");
+MODULE_ALIAS("platform:pcspkr");
+
+static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */
+static char *id = SNDRV_DEFAULT_STR1;  /* ID for this card */
+static int enable = SNDRV_DEFAULT_ENABLE1;     /* Enable this card */
+
+module_param(index, int, 0444);
+MODULE_PARM_DESC(index, "Index value for pcsp soundcard.");
+module_param(id, charp, 0444);
+MODULE_PARM_DESC(id, "ID string for pcsp soundcard.");
+module_param(enable, bool, 0444);
+MODULE_PARM_DESC(enable, "Enable PC-Speaker sound.");
+
+struct snd_pcsp pcsp_chip;
+
+static int __devinit snd_pcsp_create(struct snd_card *card)
+{
+       static struct snd_device_ops ops = { };
+       struct timespec tp;
+       int err;
+       int div, min_div, order;
+
+       hrtimer_get_res(CLOCK_MONOTONIC, &tp);
+       if (tp.tv_sec || tp.tv_nsec > PCSP_MAX_PERIOD_NS) {
+               printk(KERN_ERR "PCSP: Timer resolution is not sufficient "
+                      "(%linS)\n", tp.tv_nsec);
+               printk(KERN_ERR "PCSP: Make sure you have HPET and ACPI "
+                      "enabled.\n");
+               return -EIO;
+       }
+
+       if (loops_per_jiffy >= PCSP_MIN_LPJ && tp.tv_nsec <= PCSP_MIN_PERIOD_NS)
+               min_div = MIN_DIV;
+       else
+               min_div = MAX_DIV;
+#if PCSP_DEBUG
+       printk("PCSP: lpj=%li, min_div=%i, res=%li\n",
+              loops_per_jiffy, min_div, tp.tv_nsec);
+#endif
+
+       div = MAX_DIV / min_div;
+       order = fls(div) - 1;
+
+       pcsp_chip.max_treble = min(order, PCSP_MAX_TREBLE);
+       pcsp_chip.treble = min(pcsp_chip.max_treble, PCSP_DEFAULT_TREBLE);
+       pcsp_chip.playback_ptr = 0;
+       pcsp_chip.period_ptr = 0;
+       atomic_set(&pcsp_chip.timer_active, 0);
+       pcsp_chip.enable = 1;
+       pcsp_chip.pcspkr = 1;
+
+       spin_lock_init(&pcsp_chip.substream_lock);
+
+       pcsp_chip.card = card;
+       pcsp_chip.port = 0x61;
+       pcsp_chip.irq = -1;
+       pcsp_chip.dma = -1;
+
+       /* Register device */
+       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, &pcsp_chip, &ops);
+       if (err < 0)
+               return err;
+
+       return 0;
+}
+
+static int __devinit snd_card_pcsp_probe(int devnum, struct device *dev)
+{
+       struct snd_card *card;
+       int err;
+
+       if (devnum != 0)
+               return -EINVAL;
+
+       hrtimer_init(&pcsp_chip.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+       pcsp_chip.timer.cb_mode = HRTIMER_CB_IRQSAFE;
+       pcsp_chip.timer.function = pcsp_do_timer;
+
+       card = snd_card_new(index, id, THIS_MODULE, 0);
+       if (!card)
+               return -ENOMEM;
+
+       err = snd_pcsp_create(card);
+       if (err < 0) {
+               snd_card_free(card);
+               return err;
+       }
+       err = snd_pcsp_new_pcm(&pcsp_chip);
+       if (err < 0) {
+               snd_card_free(card);
+               return err;
+       }
+       err = snd_pcsp_new_mixer(&pcsp_chip);
+       if (err < 0) {
+               snd_card_free(card);
+               return err;
+       }
+
+       snd_card_set_dev(pcsp_chip.card, dev);
+
+       strcpy(card->driver, "PC-Speaker");
+       strcpy(card->shortname, "pcsp");
+       sprintf(card->longname, "Internal PC-Speaker at port 0x%x",
+               pcsp_chip.port);
+
+       err = snd_card_register(card);
+       if (err < 0) {
+               snd_card_free(card);
+               return err;
+       }
+
+       return 0;
+}
+
+static int __devinit alsa_card_pcsp_init(struct device *dev)
+{
+       int err;
+
+       err = snd_card_pcsp_probe(0, dev);
+       if (err) {
+               printk(KERN_ERR "PC-Speaker initialization failed.\n");
+               return err;
+       }
+
+#ifdef CONFIG_DEBUG_PAGEALLOC
+       /* Well, CONFIG_DEBUG_PAGEALLOC makes the sound horrible. Lets alert */
+       printk(KERN_WARNING "PCSP: CONFIG_DEBUG_PAGEALLOC is enabled, "
+              "which may make the sound noisy.\n");
+#endif
+
+       return 0;
+}
+
+static void __devexit alsa_card_pcsp_exit(struct snd_pcsp *chip)
+{
+       snd_card_free(chip->card);
+}
+
+static int __devinit pcsp_probe(struct platform_device *dev)
+{
+       int err;
+
+       err = pcspkr_input_init(&pcsp_chip.input_dev, &dev->dev);
+       if (err < 0)
+               return err;
+
+       err = alsa_card_pcsp_init(&dev->dev);
+       if (err < 0) {
+               pcspkr_input_remove(pcsp_chip.input_dev);
+               return err;
+       }
+
+       platform_set_drvdata(dev, &pcsp_chip);
+       return 0;
+}
+
+static int __devexit pcsp_remove(struct platform_device *dev)
+{
+       struct snd_pcsp *chip = platform_get_drvdata(dev);
+       alsa_card_pcsp_exit(chip);
+       pcspkr_input_remove(chip->input_dev);
+       platform_set_drvdata(dev, NULL);
+       return 0;
+}
+
+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);
+}
+
+static int pcsp_suspend(struct platform_device *dev, pm_message_t state)
+{
+       struct snd_pcsp *chip = platform_get_drvdata(dev);
+       pcsp_stop_beep(chip);
+       snd_pcm_suspend_all(chip->pcm);
+       return 0;
+}
+
+static void pcsp_shutdown(struct platform_device *dev)
+{
+       struct snd_pcsp *chip = platform_get_drvdata(dev);
+       pcsp_stop_beep(chip);
+}
+
+static struct platform_driver pcsp_platform_driver = {
+       .driver         = {
+               .name   = "pcspkr",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = pcsp_probe,
+       .remove         = __devexit_p(pcsp_remove),
+       .suspend        = pcsp_suspend,
+       .shutdown       = pcsp_shutdown,
+};
+
+static int __init pcsp_init(void)
+{
+       if (!enable)
+               return -ENODEV;
+       return platform_driver_register(&pcsp_platform_driver);
+}
+
+static void __exit pcsp_exit(void)
+{
+       platform_driver_unregister(&pcsp_platform_driver);
+}
+
+module_init(pcsp_init);
+module_exit(pcsp_exit);
diff --git a/sound/drivers/pcsp/pcsp.h b/sound/drivers/pcsp/pcsp.h
new file mode 100644 (file)
index 0000000..f07cc1e
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * PC-Speaker driver for Linux
+ *
+ * Copyright (C) 1993-1997  Michael Beck
+ * Copyright (C) 1997-2001  David Woodhouse
+ * Copyright (C) 2001-2008  Stas Sergeev
+ */
+
+#ifndef __PCSP_H__
+#define __PCSP_H__
+
+#include <linux/hrtimer.h>
+#if defined(CONFIG_MIPS) || defined(CONFIG_X86)
+/* Use the global PIT lock ! */
+#include <asm/i8253.h>
+#else
+#include <asm/8253pit.h>
+static DEFINE_SPINLOCK(i8253_lock);
+#endif
+
+#define PCSP_SOUND_VERSION 0x400       /* read 4.00 */
+#define PCSP_DEBUG 0
+
+/* default timer freq for PC-Speaker: 18643 Hz */
+#define DIV_18KHZ 64
+#define MAX_DIV DIV_18KHZ
+#define CUR_DIV() (MAX_DIV >> chip->treble)
+#define PCSP_MAX_TREBLE 1
+
+/* unfortunately, with hrtimers 37KHz does not work very well :( */
+#define PCSP_DEFAULT_TREBLE 0
+#define MIN_DIV (MAX_DIV >> PCSP_MAX_TREBLE)
+
+/* wild guess */
+#define PCSP_MIN_LPJ 1000000
+#define PCSP_DEFAULT_SDIV (DIV_18KHZ >> 1)
+#define PCSP_DEFAULT_SRATE (PIT_TICK_RATE / PCSP_DEFAULT_SDIV)
+#define PCSP_INDEX_INC() (1 << (PCSP_MAX_TREBLE - chip->treble))
+#define PCSP_RATE() (PIT_TICK_RATE / CUR_DIV())
+#define PCSP_MIN_RATE__1 MAX_DIV/PIT_TICK_RATE
+#define PCSP_MAX_RATE__1 MIN_DIV/PIT_TICK_RATE
+#define PCSP_MAX_PERIOD_NS (1000000000ULL * PCSP_MIN_RATE__1)
+#define PCSP_MIN_PERIOD_NS (1000000000ULL * PCSP_MAX_RATE__1)
+#define PCSP_CALC_NS(div) ({ \
+       u64 __val = 1000000000ULL * (div); \
+       do_div(__val, PIT_TICK_RATE); \
+       __val; \
+})
+#define PCSP_PERIOD_NS() PCSP_CALC_NS(CUR_DIV())
+
+#define PCSP_MAX_PERIOD_SIZE   (64*1024)
+#define PCSP_MAX_PERIODS       512
+#define PCSP_BUFFER_SIZE       (128*1024)
+
+struct snd_pcsp {
+       struct snd_card *card;
+       struct snd_pcm *pcm;
+       struct input_dev *input_dev;
+       struct hrtimer timer;
+       unsigned short port, irq, dma;
+       spinlock_t substream_lock;
+       struct snd_pcm_substream *playback_substream;
+       size_t playback_ptr;
+       size_t period_ptr;
+       atomic_t timer_active;
+       int thalf;
+       u64 ns_rem;
+       unsigned char val61;
+       int enable;
+       int max_treble;
+       int treble;
+       int pcspkr;
+};
+
+extern struct snd_pcsp pcsp_chip;
+
+extern enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle);
+
+extern int snd_pcsp_new_pcm(struct snd_pcsp *chip);
+extern int snd_pcsp_new_mixer(struct snd_pcsp *chip);
+
+#endif
diff --git a/sound/drivers/pcsp/pcsp_input.c b/sound/drivers/pcsp/pcsp_input.c
new file mode 100644 (file)
index 0000000..cd9b83e
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ *  PC Speaker beeper driver for Linux
+ *
+ *  Copyright (c) 2002 Vojtech Pavlik
+ *  Copyright (c) 1992 Orest Zborowski
+ *
+ */
+
+/*
+ * 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/init.h>
+#include <linux/input.h>
+#include <asm/io.h>
+#include "pcsp.h"
+
+static void pcspkr_do_sound(unsigned int count)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&i8253_lock, flags);
+
+       if (count) {
+               /* enable counter 2 */
+               outb_p(inb_p(0x61) | 3, 0x61);
+               /* set command for counter 2, 2 byte write */
+               outb_p(0xB6, 0x43);
+               /* select desired HZ */
+               outb_p(count & 0xff, 0x42);
+               outb((count >> 8) & 0xff, 0x42);
+       } else {
+               /* disable counter 2 */
+               outb(inb_p(0x61) & 0xFC, 0x61);
+       }
+
+       spin_unlock_irqrestore(&i8253_lock, flags);
+}
+
+void pcspkr_stop_sound(void)
+{
+       pcspkr_do_sound(0);
+}
+
+static int pcspkr_input_event(struct input_dev *dev, unsigned int type,
+                             unsigned int code, int value)
+{
+       unsigned int count = 0;
+
+       if (atomic_read(&pcsp_chip.timer_active) || !pcsp_chip.pcspkr)
+               return 0;
+
+       switch (type) {
+       case EV_SND:
+               switch (code) {
+               case SND_BELL:
+                       if (value)
+                               value = 1000;
+               case SND_TONE:
+                       break;
+               default:
+                       return -1;
+               }
+               break;
+
+       default:
+               return -1;
+       }
+
+       if (value > 20 && value < 32767)
+               count = PIT_TICK_RATE / value;
+
+       pcspkr_do_sound(count);
+
+       return 0;
+}
+
+int __devinit pcspkr_input_init(struct input_dev **rdev, struct device *dev)
+{
+       int err;
+
+       struct input_dev *input_dev = input_allocate_device();
+       if (!input_dev)
+               return -ENOMEM;
+
+       input_dev->name = "PC Speaker";
+       input_dev->phys = "isa0061/input0";
+       input_dev->id.bustype = BUS_ISA;
+       input_dev->id.vendor = 0x001f;
+       input_dev->id.product = 0x0001;
+       input_dev->id.version = 0x0100;
+       input_dev->dev.parent = dev;
+
+       input_dev->evbit[0] = BIT(EV_SND);
+       input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
+       input_dev->event = pcspkr_input_event;
+
+       err = input_register_device(input_dev);
+       if (err) {
+               input_free_device(input_dev);
+               return err;
+       }
+
+       *rdev = input_dev;
+       return 0;
+}
+
+int pcspkr_input_remove(struct input_dev *dev)
+{
+       pcspkr_stop_sound();
+       input_unregister_device(dev);   /* this also does kfree() */
+
+       return 0;
+}
diff --git a/sound/drivers/pcsp/pcsp_input.h b/sound/drivers/pcsp/pcsp_input.h
new file mode 100644 (file)
index 0000000..e66738c
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * PC-Speaker driver for Linux
+ *
+ * Copyright (C) 2001-2008  Stas Sergeev
+ */
+
+#ifndef __PCSP_INPUT_H__
+#define __PCSP_INPUT_H__
+
+int __devinit pcspkr_input_init(struct input_dev **rdev, struct device *dev);
+int pcspkr_input_remove(struct input_dev *dev);
+void pcspkr_stop_sound(void);
+
+#endif
diff --git a/sound/drivers/pcsp/pcsp_lib.c b/sound/drivers/pcsp/pcsp_lib.c
new file mode 100644 (file)
index 0000000..ac6238e
--- /dev/null
@@ -0,0 +1,338 @@
+/*
+ * PC-Speaker driver for Linux
+ *
+ * Copyright (C) 1993-1997  Michael Beck
+ * Copyright (C) 1997-2001  David Woodhouse
+ * Copyright (C) 2001-2008  Stas Sergeev
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <sound/pcm.h>
+#include <linux/interrupt.h>
+#include <asm/io.h>
+#include "pcsp.h"
+
+static int nforce_wa;
+module_param(nforce_wa, bool, 0444);
+MODULE_PARM_DESC(nforce_wa, "Apply NForce chipset workaround "
+               "(expect bad sound)");
+
+static void pcsp_start_timer(unsigned long dummy)
+{
+       hrtimer_start(&pcsp_chip.timer, ktime_set(0, 0), HRTIMER_MODE_REL);
+}
+
+/*
+ * We need the hrtimer_start as a tasklet to avoid
+ * the nasty locking problem. :(
+ * The problem:
+ * - The timer handler is called with the cpu_base->lock
+ *   already held by hrtimer code.
+ * - snd_pcm_period_elapsed() takes the
+ *   substream->self_group.lock.
+ * So far so good.
+ * But the snd_pcsp_trigger() is called with the
+ * substream->self_group.lock held, and it calls
+ * hrtimer_start(), which takes the cpu_base->lock.
+ * You see the problem. We have the code pathes
+ * which take two locks in a reverse order. This
+ * can deadlock and the lock validator complains.
+ * The only solution I could find was to move the
+ * hrtimer_start() into a tasklet. -stsp
+ */
+static DECLARE_TASKLET(pcsp_start_timer_tasklet, pcsp_start_timer, 0);
+
+enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle)
+{
+       unsigned long flags;
+       unsigned char timer_cnt, val;
+       int 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);
+
+       if (chip->thalf) {
+               outb(chip->val61, 0x61);
+               chip->thalf = 0;
+               if (!atomic_read(&chip->timer_active))
+                       return HRTIMER_NORESTART;
+               hrtimer_forward(&chip->timer, chip->timer.expires,
+                               ktime_set(0, chip->ns_rem));
+               return HRTIMER_RESTART;
+       }
+
+       /* hrtimer calls us from both hardirq and softirq contexts,
+        * so irqsave :( */
+       spin_lock_irqsave(&chip->substream_lock, flags);
+       /* 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;
+
+       runtime = substream->runtime;
+       /* assume it is u8 mono */
+       val = runtime->dma_area[chip->playback_ptr];
+       timer_cnt = val * CUR_DIV() / 256;
+
+       if (timer_cnt && chip->enable) {
+               spin_lock(&i8253_lock);
+               if (!nforce_wa) {
+                       outb_p(chip->val61, 0x61);
+                       outb_p(timer_cnt, 0x42);
+                       outb(chip->val61 ^ 1, 0x61);
+               } else {
+                       outb(chip->val61 ^ 2, 0x61);
+                       chip->thalf = 1;
+               }
+               spin_unlock(&i8253_lock);
+       }
+
+       period_bytes = snd_pcm_lib_period_bytes(substream);
+       buffer_bytes = snd_pcm_lib_buffer_bytes(substream);
+       chip->playback_ptr += PCSP_INDEX_INC();
+       periods_elapsed = chip->playback_ptr - chip->period_ptr;
+       if (periods_elapsed < 0) {
+               printk(KERN_WARNING "PCSP: playback_ptr inconsistent "
+                       "(%zi %zi %zi)\n",
+                       chip->playback_ptr, period_bytes, buffer_bytes);
+               periods_elapsed += buffer_bytes;
+       }
+       periods_elapsed /= period_bytes;
+       /* wrap the pointer _before_ calling snd_pcm_period_elapsed(),
+        * 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);
+
+       if (!atomic_read(&chip->timer_active))
+               return HRTIMER_NORESTART;
+
+       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, chip->timer.expires, ktime_set(0, ns));
+       return HRTIMER_RESTART;
+
+exit_nr_unlock2:
+       snd_pcm_stream_unlock(substream);
+exit_nr_unlock1:
+       spin_unlock_irqrestore(&chip->substream_lock, flags);
+       return HRTIMER_NORESTART;
+}
+
+static void pcsp_start_playing(struct snd_pcsp *chip)
+{
+#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;
+       }
+
+       spin_lock(&i8253_lock);
+       chip->val61 = inb(0x61) | 0x03;
+       outb_p(0x92, 0x43);     /* binary, mode 1, LSB only, ch 2 */
+       spin_unlock(&i8253_lock);
+       atomic_set(&chip->timer_active, 1);
+       chip->thalf = 0;
+
+       tasklet_schedule(&pcsp_start_timer_tasklet);
+}
+
+static void pcsp_stop_playing(struct snd_pcsp *chip)
+{
+#if PCSP_DEBUG
+       printk(KERN_INFO "PCSP: stop_playing called\n");
+#endif
+       if (!atomic_read(&chip->timer_active))
+               return;
+
+       atomic_set(&chip->timer_active, 0);
+       spin_lock(&i8253_lock);
+       /* restore the timer */
+       outb_p(0xb6, 0x43);     /* binary, mode 3, LSB/MSB, ch 2 */
+       outb(chip->val61 & 0xFC, 0x61);
+       spin_unlock(&i8253_lock);
+}
+
+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);
+       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)
+{
+       int err;
+       err = snd_pcm_lib_malloc_pages(substream,
+                                     params_buffer_bytes(hw_params));
+       if (err < 0)
+               return err;
+       return 0;
+}
+
+static int snd_pcsp_playback_hw_free(struct snd_pcm_substream *substream)
+{
+#if PCSP_DEBUG
+       printk(KERN_INFO "PCSP: hw_free called\n");
+#endif
+       return snd_pcm_lib_free_pages(substream);
+}
+
+static int snd_pcsp_playback_prepare(struct snd_pcm_substream *substream)
+{
+       struct snd_pcsp *chip = snd_pcm_substream_chip(substream);
+#if PCSP_DEBUG
+       printk(KERN_INFO "PCSP: prepare called, "
+                       "size=%zi psize=%zi f=%zi f1=%i\n",
+                       snd_pcm_lib_buffer_bytes(substream),
+                       snd_pcm_lib_period_bytes(substream),
+                       snd_pcm_lib_buffer_bytes(substream) /
+                       snd_pcm_lib_period_bytes(substream),
+                       substream->runtime->periods);
+#endif
+       chip->playback_ptr = 0;
+       chip->period_ptr = 0;
+       return 0;
+}
+
+static int snd_pcsp_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+       struct snd_pcsp *chip = snd_pcm_substream_chip(substream);
+#if PCSP_DEBUG
+       printk(KERN_INFO "PCSP: trigger called\n");
+#endif
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+               pcsp_start_playing(chip);
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+               pcsp_stop_playing(chip);
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+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);
+}
+
+static struct snd_pcm_hardware snd_pcsp_playback = {
+       .info = (SNDRV_PCM_INFO_INTERLEAVED |
+                SNDRV_PCM_INFO_HALF_DUPLEX |
+                SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID),
+       .formats = SNDRV_PCM_FMTBIT_U8,
+       .rates = SNDRV_PCM_RATE_KNOT,
+       .rate_min = PCSP_DEFAULT_SRATE,
+       .rate_max = PCSP_DEFAULT_SRATE,
+       .channels_min = 1,
+       .channels_max = 1,
+       .buffer_bytes_max = PCSP_BUFFER_SIZE,
+       .period_bytes_min = 64,
+       .period_bytes_max = PCSP_MAX_PERIOD_SIZE,
+       .periods_min = 2,
+       .periods_max = PCSP_MAX_PERIODS,
+       .fifo_size = 0,
+};
+
+static int snd_pcsp_playback_open(struct snd_pcm_substream *substream)
+{
+       struct snd_pcsp *chip = snd_pcm_substream_chip(substream);
+       struct snd_pcm_runtime *runtime = substream->runtime;
+#if PCSP_DEBUG
+       printk(KERN_INFO "PCSP: open called\n");
+#endif
+       if (atomic_read(&chip->timer_active)) {
+               printk(KERN_ERR "PCSP: still active!!\n");
+               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;
+}
+
+static struct snd_pcm_ops snd_pcsp_playback_ops = {
+       .open = snd_pcsp_playback_open,
+       .close = snd_pcsp_playback_close,
+       .ioctl = snd_pcm_lib_ioctl,
+       .hw_params = snd_pcsp_playback_hw_params,
+       .hw_free = snd_pcsp_playback_hw_free,
+       .prepare = snd_pcsp_playback_prepare,
+       .trigger = snd_pcsp_trigger,
+       .pointer = snd_pcsp_playback_pointer,
+};
+
+int __devinit snd_pcsp_new_pcm(struct snd_pcsp *chip)
+{
+       int err;
+
+       err = snd_pcm_new(chip->card, "pcspeaker", 0, 1, 0, &chip->pcm);
+       if (err < 0)
+               return err;
+
+       snd_pcm_set_ops(chip->pcm, SNDRV_PCM_STREAM_PLAYBACK,
+                       &snd_pcsp_playback_ops);
+
+       chip->pcm->private_data = chip;
+       chip->pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX;
+       strcpy(chip->pcm->name, "pcsp");
+
+       snd_pcm_lib_preallocate_pages_for_all(chip->pcm,
+                                             SNDRV_DMA_TYPE_CONTINUOUS,
+                                             snd_dma_continuous_data
+                                             (GFP_KERNEL), PCSP_BUFFER_SIZE,
+                                             PCSP_BUFFER_SIZE);
+
+       return 0;
+}
diff --git a/sound/drivers/pcsp/pcsp_mixer.c b/sound/drivers/pcsp/pcsp_mixer.c
new file mode 100644 (file)
index 0000000..64a695f
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * PC-Speaker driver for Linux
+ *
+ * Mixer implementation.
+ * Copyright (C) 2001-2008  Stas Sergeev
+ */
+
+#include <sound/core.h>
+#include <sound/control.h>
+#include "pcsp.h"
+
+
+static int pcsp_enable_info(struct snd_kcontrol *kcontrol,
+                           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 pcsp_enable_get(struct snd_kcontrol *kcontrol,
+                          struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol);
+       ucontrol->value.integer.value[0] = chip->enable;
+       return 0;
+}
+
+static int pcsp_enable_put(struct snd_kcontrol *kcontrol,
+                          struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol);
+       int changed = 0;
+       int enab = ucontrol->value.integer.value[0];
+       if (enab != chip->enable) {
+               chip->enable = enab;
+               changed = 1;
+       }
+       return changed;
+}
+
+static int pcsp_treble_info(struct snd_kcontrol *kcontrol,
+                           struct snd_ctl_elem_info *uinfo)
+{
+       struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol);
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+       uinfo->count = 1;
+       uinfo->value.enumerated.items = chip->max_treble + 1;
+       if (uinfo->value.enumerated.item > chip->max_treble)
+               uinfo->value.enumerated.item = chip->max_treble;
+       sprintf(uinfo->value.enumerated.name, "%d", PCSP_RATE());
+       return 0;
+}
+
+static int pcsp_treble_get(struct snd_kcontrol *kcontrol,
+                          struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol);
+       ucontrol->value.enumerated.item[0] = chip->treble;
+       return 0;
+}
+
+static int pcsp_treble_put(struct snd_kcontrol *kcontrol,
+                          struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol);
+       int changed = 0;
+       int treble = ucontrol->value.enumerated.item[0];
+       if (treble != chip->treble) {
+               chip->treble = treble;
+#if PCSP_DEBUG
+               printk(KERN_INFO "PCSP: rate set to %i\n", PCSP_RATE());
+#endif
+               changed = 1;
+       }
+       return changed;
+}
+
+static int pcsp_pcspkr_info(struct snd_kcontrol *kcontrol,
+                           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 pcsp_pcspkr_get(struct snd_kcontrol *kcontrol,
+                          struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol);
+       ucontrol->value.integer.value[0] = chip->pcspkr;
+       return 0;
+}
+
+static int pcsp_pcspkr_put(struct snd_kcontrol *kcontrol,
+                          struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol);
+       int changed = 0;
+       int spkr = ucontrol->value.integer.value[0];
+       if (spkr != chip->pcspkr) {
+               chip->pcspkr = spkr;
+               changed = 1;
+       }
+       return changed;
+}
+
+#define PCSP_MIXER_CONTROL(ctl_type, ctl_name) \
+{ \
+       .iface =        SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name =         ctl_name, \
+       .info =         pcsp_##ctl_type##_info, \
+       .get =          pcsp_##ctl_type##_get, \
+       .put =          pcsp_##ctl_type##_put, \
+}
+
+static struct snd_kcontrol_new __devinitdata snd_pcsp_controls[] = {
+       PCSP_MIXER_CONTROL(enable, "Master Playback Switch"),
+       PCSP_MIXER_CONTROL(treble, "BaseFRQ Playback Volume"),
+       PCSP_MIXER_CONTROL(pcspkr, "PC Speaker Playback Switch"),
+};
+
+int __devinit snd_pcsp_new_mixer(struct snd_pcsp *chip)
+{
+       struct snd_card *card = chip->card;
+       int i, err;
+
+       for (i = 0; i < ARRAY_SIZE(snd_pcsp_controls); i++) {
+               err = snd_ctl_add(card,
+                                snd_ctl_new1(snd_pcsp_controls + i,
+                                             chip));
+               if (err < 0)
+                       return err;
+       }
+
+       strcpy(card->mixername, "PC-Speaker");
+
+       return 0;
+}
index 15061bd72776a0eacbb418d7abb1125bda5398cf..d20d893b3b60c1308694224c56c8838126a6f215 100644 (file)
@@ -27,6 +27,7 @@
 #include <sound/pcm.h>
 #include <sound/ak4114.h>
 #include <sound/asoundef.h>
+#include <sound/info.h>
 
 MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
 MODULE_DESCRIPTION("AK4114 IEC958 (S/PDIF) receiver by Asahi Kasei");
@@ -446,6 +447,26 @@ static struct snd_kcontrol_new snd_ak4114_iec958_controls[] = {
 }
 };
 
+
+static void snd_ak4114_proc_regs_read(struct snd_info_entry *entry,
+               struct snd_info_buffer *buffer)
+{
+       struct ak4114 *ak4114 = entry->private_data;
+       int reg, val;
+       /* all ak4114 registers 0x00 - 0x1f */
+       for (reg = 0; reg < 0x20; reg++) {
+               val = reg_read(ak4114, reg);
+               snd_iprintf(buffer, "0x%02x = 0x%02x\n", reg, val);
+       }
+}
+
+static void snd_ak4114_proc_init(struct ak4114 *ak4114)
+{
+       struct snd_info_entry *entry;
+       if (!snd_card_proc_new(ak4114->card, "ak4114", &entry))
+               snd_info_set_text_ops(entry, ak4114, snd_ak4114_proc_regs_read);
+}
+
 int snd_ak4114_build(struct ak4114 *ak4114,
                     struct snd_pcm_substream *ply_substream,
                     struct snd_pcm_substream *cap_substream)
@@ -478,6 +499,7 @@ int snd_ak4114_build(struct ak4114 *ak4114,
                        return err;
                ak4114->kctls[idx] = kctl;
        }
+       snd_ak4114_proc_init(ak4114);
        /* trigger workq */
        schedule_delayed_work(&ak4114->work, HZ / 10);
        return 0;
@@ -590,7 +612,7 @@ static void ak4114_stats(struct work_struct *work)
        struct ak4114 *chip = container_of(work, struct ak4114, work.work);
 
        if (!chip->init)
-               snd_ak4114_check_rate_and_errors(chip, 0);
+               snd_ak4114_check_rate_and_errors(chip, chip->check_flags);
 
        schedule_delayed_work(&chip->work, HZ / 10);
 }
index 35fbbf2cb9fa84bb47241c2de5ce7c9c9941e323..288926d2e2054b2706d8749b6be8ff8290bd1911 100644 (file)
@@ -70,7 +70,8 @@ static void ak4524_reset(struct snd_akm4xxx *ak, int state)
 }
 
 /* reset procedure for AK4355 and AK4358 */
-static void ak4355_reset(struct snd_akm4xxx *ak, int state)
+static void ak435X_reset(struct snd_akm4xxx *ak, int state,
+               unsigned char total_regs)
 {
        unsigned char reg;
 
@@ -78,7 +79,7 @@ static void ak4355_reset(struct snd_akm4xxx *ak, int state)
                snd_akm4xxx_write(ak, 0, 0x01, 0x02); /* reset and soft-mute */
                return;
        }
-       for (reg = 0x00; reg < 0x0b; reg++)
+       for (reg = 0x00; reg < total_regs; reg++)
                if (reg != 0x01)
                        snd_akm4xxx_write(ak, 0, reg,
                                          snd_akm4xxx_get(ak, 0, reg));
@@ -118,8 +119,10 @@ void snd_akm4xxx_reset(struct snd_akm4xxx *ak, int state)
                /* FIXME: needed for ak4529? */
                break;
        case SND_AK4355:
+               ak435X_reset(ak, state, 0x0b);
+               break;
        case SND_AK4358:
-               ak4355_reset(ak, state);
+               ak435X_reset(ak, state, 0x10);
                break;
        case SND_AK4381:
                ak4381_reset(ak, state);
@@ -292,11 +295,6 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak)
        case SND_AK5365:
                /* FIXME: any init sequence? */
                return;
-       case NON_AKM:
-               /* fake value for non-akm codecs using akm infrastructure
-                * (e.g. of ice1724) - certainly FIXME
-                */
-               return;
        default:
                snd_BUG();
                return;
@@ -374,6 +372,8 @@ static int put_ak_reg(struct snd_kcontrol *kcontrol, int addr,
                nval = mask - nval;
        if (AK_GET_NEEDSMSB(kcontrol->private_value))
                nval |= 0x80;
+       /* printk(KERN_DEBUG "DEBUG - AK writing reg: chip %x addr %x,
+          nval %x\n", chip, addr, nval); */
        snd_akm4xxx_write(ak, chip, addr, nval);
        return 1;
 }
index bed29ca22239edd7f1f47335da7797a100ffec6f..f3fd7b4f46683d30b059b6808861b6ea2e303c31 100644 (file)
@@ -331,7 +331,7 @@ static int snd_sb_csp_riff_load(struct snd_sb_csp * p,
                return -EFAULT;
        if ((file_h.name != RIFF_HEADER) ||
            (le32_to_cpu(file_h.len) >= SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE - sizeof(file_h))) {
-               snd_printd("%s: Invalid RIFF header\n", __FUNCTION__);
+               snd_printd("%s: Invalid RIFF header\n", __func__);
                return -EINVAL;
        }
        data_ptr += sizeof(file_h);
@@ -340,7 +340,7 @@ static int snd_sb_csp_riff_load(struct snd_sb_csp * p,
        if (copy_from_user(&item_type, data_ptr, sizeof(item_type)))
                return -EFAULT;
        if (item_type != CSP__HEADER) {
-               snd_printd("%s: Invalid RIFF file type\n", __FUNCTION__);
+               snd_printd("%s: Invalid RIFF file type\n", __func__);
                return -EINVAL;
        }
        data_ptr += sizeof (item_type);
@@ -395,7 +395,7 @@ static int snd_sb_csp_riff_load(struct snd_sb_csp * p,
                                return -EFAULT;
 
                        if (code_h.name != MAIN_HEADER) {
-                               snd_printd("%s: Missing 'main' microcode\n", __FUNCTION__);
+                               snd_printd("%s: Missing 'main' microcode\n", __func__);
                                return -EINVAL;
                        }
                        data_ptr += sizeof(code_h);
@@ -439,7 +439,7 @@ static int snd_sb_csp_riff_load(struct snd_sb_csp * p,
                                p->acc_format = p->acc_width = p->acc_rates = 0;
                                p->mode = 0;
                                snd_printd("%s: Unsupported CSP codec type: 0x%04x\n",
-                                          __FUNCTION__,
+                                          __func__,
                                           le16_to_cpu(funcdesc_h.VOC_type));
                                return -EINVAL;
                        }
@@ -458,7 +458,7 @@ static int snd_sb_csp_riff_load(struct snd_sb_csp * p,
                        return 0;
                }
        }
-       snd_printd("%s: Function #%d not found\n", __FUNCTION__, info.func_req);
+       snd_printd("%s: Function #%d not found\n", __func__, info.func_req);
        return -EINVAL;
 }
 
@@ -612,7 +612,7 @@ static int get_version(struct snd_sb *chip)
 static int snd_sb_csp_check_version(struct snd_sb_csp * p)
 {
        if (p->version < 0x10 || p->version > 0x1f) {
-               snd_printd("%s: Invalid CSP version: 0x%x\n", __FUNCTION__, p->version);
+               snd_printd("%s: Invalid CSP version: 0x%x\n", __func__, p->version);
                return 1;
        }
        return 0;
@@ -631,7 +631,7 @@ static int snd_sb_csp_load(struct snd_sb_csp * p, const unsigned char *buf, int
        spin_lock_irqsave(&p->chip->reg_lock, flags);
        snd_sbdsp_command(p->chip, 0x01);       /* CSP download command */
        if (snd_sbdsp_get_byte(p->chip)) {
-               snd_printd("%s: Download command failed\n", __FUNCTION__);
+               snd_printd("%s: Download command failed\n", __func__);
                goto __fail;
        }
        /* Send CSP low byte (size - 1) */
@@ -658,7 +658,7 @@ static int snd_sb_csp_load(struct snd_sb_csp * p, const unsigned char *buf, int
                        udelay (10);
                }
                if (status != 0x55) {
-                       snd_printd("%s: Microcode initialization failed\n", __FUNCTION__);
+                       snd_printd("%s: Microcode initialization failed\n", __func__);
                        goto __fail;
                }
        } else {
@@ -824,19 +824,19 @@ static int snd_sb_csp_start(struct snd_sb_csp * p, int sample_width, int channel
        unsigned long flags;
 
        if (!(p->running & (SNDRV_SB_CSP_ST_LOADED | SNDRV_SB_CSP_ST_AUTO))) {
-               snd_printd("%s: Microcode not loaded\n", __FUNCTION__);
+               snd_printd("%s: Microcode not loaded\n", __func__);
                return -ENXIO;
        }
        if (p->running & SNDRV_SB_CSP_ST_RUNNING) {
-               snd_printd("%s: CSP already running\n", __FUNCTION__);
+               snd_printd("%s: CSP already running\n", __func__);
                return -EBUSY;
        }
        if (!(sample_width & p->acc_width)) {
-               snd_printd("%s: Unsupported PCM sample width\n", __FUNCTION__);
+               snd_printd("%s: Unsupported PCM sample width\n", __func__);
                return -EINVAL;
        }
        if (!(channels & p->acc_channels)) {
-               snd_printd("%s: Invalid number of channels\n", __FUNCTION__);
+               snd_printd("%s: Invalid number of channels\n", __func__);
                return -EINVAL;
        }
 
@@ -858,11 +858,11 @@ static int snd_sb_csp_start(struct snd_sb_csp * p, int sample_width, int channel
                s_type |= 0x22; /* 00dX 00dX    (d = 1 if 8 bit samples) */
 
        if (set_codec_parameter(p->chip, 0x81, s_type)) {
-               snd_printd("%s: Set sample type command failed\n", __FUNCTION__);
+               snd_printd("%s: Set sample type command failed\n", __func__);
                goto __fail;
        }
        if (set_codec_parameter(p->chip, 0x80, 0x00)) {
-               snd_printd("%s: Codec start command failed\n", __FUNCTION__);
+               snd_printd("%s: Codec start command failed\n", __func__);
                goto __fail;
        }
        p->run_width = sample_width;
index d63c1af550de5789949b7df6e11bd78082e71fa1..b432d9ae874baba6b52d837b8886eff2dd02fc22 100644 (file)
@@ -51,7 +51,7 @@ int snd_sbdsp_command(struct snd_sb *chip, unsigned char val)
                        outb(val, SBP(chip, COMMAND));
                        return 1;
                }
-       snd_printd("%s [0x%lx]: timeout (0x%x)\n", __FUNCTION__, chip->port, val);
+       snd_printd("%s [0x%lx]: timeout (0x%x)\n", __func__, chip->port, val);
        return 0;
 }
 
@@ -68,7 +68,7 @@ int snd_sbdsp_get_byte(struct snd_sb *chip)
                        return val;
                }
        }
-       snd_printd("%s [0x%lx]: timeout\n", __FUNCTION__, chip->port);
+       snd_printd("%s [0x%lx]: timeout\n", __func__, chip->port);
        return -ENODEV;
 }
 
@@ -87,7 +87,7 @@ int snd_sbdsp_reset(struct snd_sb *chip)
                        else
                                break;
                }
-       snd_printdd("%s [0x%lx] failed...\n", __FUNCTION__, chip->port);
+       snd_printdd("%s [0x%lx] failed...\n", __func__, chip->port);
        return -ENODEV;
 }
 
index eaf69971bf92d5d5b54306dd2109d37ee5bffd07..1e90d769b62e3ef63181f809a5ccd36e819d126b 100644 (file)
@@ -795,9 +795,9 @@ static int find_output_space(int dev, char **buf, int *size)
 #ifdef BE_CONSERVATIVE
        active_offs = dmap->byte_counter + dmap->qhead * dmap->fragment_size;
 #else
-       active_offs = DMAbuf_get_buffer_pointer(dev, dmap, DMODE_OUTPUT);
+       active_offs = max(DMAbuf_get_buffer_pointer(dev, dmap, DMODE_OUTPUT), 0);
        /* Check for pointer wrapping situation */
-       if (active_offs < 0 || active_offs >= dmap->bytes_in_use)
+       if (active_offs >= dmap->bytes_in_use)
                active_offs = 0;
        active_offs += dmap->byte_counter;
 #endif
index d6af9065d1c0287b7e40452b21c9b63153194b43..f43f91ef86c74577c57f037e7331485fc9cea9b1 100644 (file)
@@ -3076,8 +3076,7 @@ ali_ac97_get(struct trident_card *card, int secondary, u8 reg)
        u16 wcontrol;
        unsigned long flags;
 
-       if (!card)
-               BUG();
+       BUG_ON(!card);
 
        address = ALI_AC97_READ;
        if (card->revision == ALI_5451_V02) {
@@ -3148,8 +3147,7 @@ ali_ac97_set(struct trident_card *card, int secondary, u8 reg, u16 val)
 
        data = ((u32) val) << 16;
 
-       if (!card)
-               BUG();
+       BUG_ON(!card);
 
        address = ALI_AC97_WRITE;
        mask = ALI_AC97_WRITE_ACTION | ALI_AC97_AUDIO_BUSY;
@@ -3213,8 +3211,7 @@ ali_ac97_read(struct ac97_codec *codec, u8 reg)
        struct trident_card *card = NULL;
 
        /* Added by Matt Wu */
-       if (!codec)
-               BUG();
+       BUG_ON(!codec);
 
        card = (struct trident_card *) codec->private_data;
 
@@ -3240,8 +3237,7 @@ ali_ac97_write(struct ac97_codec *codec, u8 reg, u16 val)
        struct trident_card *card;
 
        /*  Added by Matt Wu */
-       if (!codec)
-               BUG();
+       BUG_ON(!codec);
 
        card = (struct trident_card *) codec->private_data;
 
index 4713b49fc91da62e21db1dc299658c0c86df3831..ff30a1d7c2f1aa3ea79d0e70e448528669b08b58 100644 (file)
@@ -322,7 +322,7 @@ enum miscint_bits {
 #define VALIDATE_MAGIC(FOO,MAG)                                \
 ({                                                     \
        if (!(FOO) || (FOO)->magic != MAG) {            \
-               printk(invalid_magic,__FUNCTION__);     \
+               printk(invalid_magic,__func__); \
                return -ENXIO;                          \
        }                                               \
 })
index d25249a932bfa48abe544bfa7dac49ba0a3e17e7..2c5aaa58046d8895bc25c48d7171706596f464a8 100644 (file)
@@ -194,11 +194,11 @@ static void dbgassert(const char *fcn, int line, const char *expr)
  *     DBGRV   - debug print function return when verbose
  */
 
-#define ASSERT(e)      ((e) ? (void) 0 : dbgassert(__FUNCTION__, __LINE__, #e))
+#define ASSERT(e)      ((e) ? (void) 0 : dbgassert(__func__, __LINE__, #e))
 #define DBGDO(x)            x
 #define DBGX(fmt, args...)  (in_interrupt() ? 0 : printk(KERN_ERR fmt, ##args))
-#define DBGP(fmt, args...)  (DBGX("%s: " fmt, __FUNCTION__ , ##args))
-#define DBGE(fmt, args...)  (DBGX("%s" fmt, __FUNCTION__ , ##args))
+#define DBGP(fmt, args...)  (DBGX("%s: " fmt, __func__ , ##args))
+#define DBGE(fmt, args...)  (DBGX("%s" fmt, __func__ , ##args))
 #define DBGC(rtn)           (DBGP("calling %s\n", rtn))
 #define DBGR()              (DBGP("returning\n"))
 #define DBGXV(fmt, args...) (shut_up ? 0 : DBGX(fmt, ##args))
index 812085d521f12405867dd4c70096b49b8ef79212..581debf37dcb711d9f996a52f5b36cb05fdad5cd 100644 (file)
@@ -122,6 +122,21 @@ config SND_AU8830
          To compile this driver as a module, choose M here: the module
          will be called snd-au8830.
 
+config SND_AW2
+       tristate "Emagic Audiowerk 2"
+       depends on SND
+       help
+         Say Y here to include support for Emagic Audiowerk 2 soundcards.
+
+         Supported features: Analog and SPDIF output. Analog or SPDIF input.
+         Note: Switch between analog and digital input does not always work.
+         It can produce continuous noise. The workaround is to switch again
+         (and again) between digital and analog input until it works.
+
+         To compile this driver as a module, choose M here: the module
+         will be called snd-aw2.
+
+
 config SND_AZT3328
        tristate "Aztech AZF3328 / PCI168 (EXPERIMENTAL)"
        depends on SND && EXPERIMENTAL
@@ -162,6 +177,7 @@ config SND_CA0106
        depends on SND
        select SND_AC97_CODEC
        select SND_RAWMIDI
+       select SND_VMASTER
        help
          Say Y here to include support for the Sound Blaster Audigy LS
          and Live 24bit.
@@ -517,6 +533,7 @@ config SND_HDA_INTEL
        tristate "Intel HD Audio"
        depends on SND
        select SND_PCM
+       select SND_VMASTER
        help
          Say Y here to include support for Intel "High Definition
          Audio" (Azalia) motherboard devices.
@@ -680,6 +697,7 @@ config SND_ICE1724
        depends on SND
        select SND_MPU401_UART
        select SND_AC97_CODEC
+       select SND_VMASTER
        help
          Say Y here to include support for soundcards based on
          ICE/VT1724/1720 (Envy24HT/PT) chips.
@@ -896,12 +914,12 @@ config SND_VIA82XX_MODEM
          will be called snd-via82xx-modem.
 
 config SND_VIRTUOSO
-       tristate "Asus Virtuoso 200 (Xonar)"
+       tristate "Asus Virtuoso 100/200 (Xonar)"
        depends on SND
        select SND_OXYGEN_LIB
        help
          Say Y here to include support for sound cards based on the
-         Asus AV200 chip, i.e., Xonar D2 and Xonar D2X.
+         Asus AV100/AV200 chips, i.e., Xonar D2, DX and D2X.
 
          To compile this driver as a module, choose M here: the module
          will be called snd-virtuoso.
index 2d42fd28f4e7950305d80d930569dfd759818b56..85ef14bc805649611b51873d8ff7de6de9ba4d6c 100644 (file)
@@ -58,6 +58,7 @@ obj-$(CONFIG_SND) += \
        ac97/ \
        ali5451/ \
        au88x0/ \
+       aw2/ \
        ca0106/ \
        cs46xx/ \
        cs5535audio/ \
index 50c637e55ffa63ef544646fae65e62a29b049c7b..39198e505b12aabacd6842389647da8dff2c7c68 100644 (file)
@@ -114,10 +114,9 @@ static int ac97_surround_jack_mode_put(struct snd_kcontrol *kcontrol, struct snd
 
 static int ac97_channel_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 {
-       static const char *texts[] = { "2ch", "4ch", "6ch" };
-       if (kcontrol->private_value)
-               return ac97_enum_text_info(kcontrol, uinfo, texts, 2); /* 4ch only */
-       return ac97_enum_text_info(kcontrol, uinfo, texts, 3);
+       static const char *texts[] = { "2ch", "4ch", "6ch", "8ch" };
+       return ac97_enum_text_info(kcontrol, uinfo, texts,
+               kcontrol->private_value);
 }
 
 static int ac97_channel_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
@@ -133,13 +132,8 @@ static int ac97_channel_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
        struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
        unsigned char mode = ucontrol->value.enumerated.item[0];
 
-       if (kcontrol->private_value) {
-               if (mode >= 2)
-                       return -EINVAL;
-       } else {
-               if (mode >= 3)
-                       return -EINVAL;
-       }
+       if (mode >= kcontrol->private_value)
+               return -EINVAL;
 
        if (mode != ac97->channel_mode) {
                ac97->channel_mode = mode;
@@ -158,6 +152,7 @@ static int ac97_channel_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
                .get = ac97_surround_jack_mode_get, \
                .put = ac97_surround_jack_mode_put, \
        }
+/* 6ch */
 #define AC97_CHANNEL_MODE_CTL \
        { \
                .iface  = SNDRV_CTL_ELEM_IFACE_MIXER, \
@@ -165,7 +160,9 @@ static int ac97_channel_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
                .info = ac97_channel_mode_info, \
                .get = ac97_channel_mode_get, \
                .put = ac97_channel_mode_put, \
+               .private_value = 3, \
        }
+/* 4ch */
 #define AC97_CHANNEL_MODE_4CH_CTL \
        { \
                .iface  = SNDRV_CTL_ELEM_IFACE_MIXER, \
@@ -173,7 +170,17 @@ static int ac97_channel_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
                .info = ac97_channel_mode_info, \
                .get = ac97_channel_mode_get, \
                .put = ac97_channel_mode_put, \
-               .private_value = 1, \
+               .private_value = 2, \
+       }
+/* 8ch */
+#define AC97_CHANNEL_MODE_8CH_CTL \
+       { \
+               .iface  = SNDRV_CTL_ELEM_IFACE_MIXER, \
+               .name   = "Channel Mode", \
+               .info = ac97_channel_mode_info, \
+               .get = ac97_channel_mode_get, \
+               .put = ac97_channel_mode_put, \
+               .private_value = 4, \
        }
 
 static inline int is_surround_on(struct snd_ac97 *ac97)
@@ -210,6 +217,10 @@ static inline int is_shared_micin(struct snd_ac97 *ac97)
        return !ac97->indep_surround && !is_clfe_on(ac97);
 }
 
+static inline int alc850_is_aux_back_surround(struct snd_ac97 *ac97)
+{
+       return is_surround_on(ac97);
+}
 
 /* The following snd_ac97_ymf753_... items added by David Shust (dshust@shustring.com) */
 /* Modified for YMF743 by Keita Maehara <maehara@debian.org> */
@@ -2816,10 +2827,12 @@ static int patch_alc655(struct snd_ac97 * ac97)
 
 #define AC97_ALC850_JACK_SELECT        0x76
 #define AC97_ALC850_MISC1      0x7a
+#define AC97_ALC850_MULTICH    0x6a
 
 static void alc850_update_jacks(struct snd_ac97 *ac97)
 {
        int shared;
+       int aux_is_back_surround;
        
        /* shared Line-In / Surround Out */
        shared = is_shared_surrout(ac97);
@@ -2837,13 +2850,18 @@ static void alc850_update_jacks(struct snd_ac97 *ac97)
        /* MIC-IN = 1, CENTER-LFE = 5 */
        snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 4,
                             shared ? (5<<4) : (1<<4));
+
+       aux_is_back_surround = alc850_is_aux_back_surround(ac97);
+       /* Aux is Back Surround */
+       snd_ac97_update_bits(ac97, AC97_ALC850_MULTICH, 1 << 10,
+                                aux_is_back_surround ? (1<<10) : (0<<10));
 }
 
 static const struct snd_kcontrol_new snd_ac97_controls_alc850[] = {
        AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0),
        AC97_SINGLE("Mic Front Input Switch", AC97_ALC850_JACK_SELECT, 15, 1, 1),
        AC97_SURROUND_JACK_MODE_CTL,
-       AC97_CHANNEL_MODE_CTL,
+       AC97_CHANNEL_MODE_8CH_CTL,
 };
 
 static int patch_alc850_specific(struct snd_ac97 *ac97)
@@ -2869,6 +2887,7 @@ static int patch_alc850(struct snd_ac97 *ac97)
        ac97->build_ops = &patch_alc850_ops;
 
        ac97->spec.dev_flags = 0; /* for IEC958 playback route - ALC655 compatible */
+       ac97->flags |= AC97_HAS_8CH;
 
        /* assume only page 0 for writing cache */
        snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR);
@@ -2878,6 +2897,7 @@ static int patch_alc850(struct snd_ac97 *ac97)
           spdif-in monitor off, spdif-in PCM off
           center on mic off, surround on line-in off
           duplicate front off
+          NB default bit 10=0 = Aux is Capture, not Back Surround
        */
        snd_ac97_write_cache(ac97, AC97_ALC650_MULTICH, 1<<15);
        /* SURR_OUT: on, Surr 1kOhm: on, Surr Amp: off, Front 1kOhm: off
index 3674f35c4a791eaf04a6d2ae86b79e82978d028b..48cbda9378c5fc2ed4b295f7731c44ae1a11e58c 100644 (file)
@@ -574,7 +574,6 @@ int snd_ac97_pcm_open(struct ac97_pcm *pcm, unsigned int rate,
        r = rate > 48000;
        bus = pcm->bus;
        if (cfg == AC97_PCM_CFG_SPDIF) {
-               int err;
                for (cidx = 0; cidx < 4; cidx++)
                        if (bus->codec[cidx] && (bus->codec[cidx]->ext_id & AC97_EI_SPDIF)) {
                                err = set_spdif_rate(bus->codec[cidx], rate);
index a66d5150bb7ac3ddf437588cf99ff726b5adbca2..39ec55b57b1e808ffef72e96cbea23bc9095cabd 100644 (file)
@@ -264,10 +264,10 @@ snd_ad1889_ac97_ready(struct snd_ad1889 *chip)
                mdelay(1);
        if (!retry) {
                snd_printk(KERN_ERR PFX "[%s] Link is not ready.\n",
-                      __FUNCTION__);
+                      __func__);
                return -EIO;
        }
-       ad1889_debug("[%s] ready after %d ms\n", __FUNCTION__, 400 - retry);
+       ad1889_debug("[%s] ready after %d ms\n", __func__, 400 - retry);
 
        return 0;
 }
@@ -854,8 +854,6 @@ snd_ad1889_free(struct snd_ad1889 *chip)
 
        spin_unlock_irq(&chip->lock);
 
-       synchronize_irq(chip->irq);
-       
        if (chip->irq >= 0)
                free_irq(chip->irq, chip);
 
index 6a905ed9cbd6e6f964db82cf2816888508624b5f..1a0fd65ec2809478d71f037f310f6a3f36a1823b 100644 (file)
@@ -1809,26 +1809,26 @@ static int snd_ali5451_spdif_get(struct snd_kcontrol *kcontrol,
                                 struct snd_ctl_elem_value *ucontrol)
 {
        struct snd_ali *codec = kcontrol->private_data;
-       unsigned int enable;
+       unsigned int spdif_enable;
 
-       enable = ucontrol->value.integer.value[0] ? 1 : 0;
+       spdif_enable = ucontrol->value.integer.value[0] ? 1 : 0;
 
        spin_lock_irq(&codec->reg_lock);
        switch (kcontrol->private_value) {
        case 0:
-               enable = (codec->spdif_mask & 0x02) ? 1 : 0;
+               spdif_enable = (codec->spdif_mask & 0x02) ? 1 : 0;
                break;
        case 1:
-               enable = ((codec->spdif_mask & 0x02) &&
+               spdif_enable = ((codec->spdif_mask & 0x02) &&
                          (codec->spdif_mask & 0x04)) ? 1 : 0;
                break;
        case 2:
-               enable = (codec->spdif_mask & 0x01) ? 1 : 0;
+               spdif_enable = (codec->spdif_mask & 0x01) ? 1 : 0;
                break;
        default:
                break;
        }
-       ucontrol->value.integer.value[0] = enable;
+       ucontrol->value.integer.value[0] = spdif_enable;
        spin_unlock_irq(&codec->reg_lock);
        return 0;
 }
@@ -1837,17 +1837,17 @@ static int snd_ali5451_spdif_put(struct snd_kcontrol *kcontrol,
                                 struct snd_ctl_elem_value *ucontrol)
 {
        struct snd_ali *codec = kcontrol->private_data;
-       unsigned int change = 0, enable = 0;
+       unsigned int change = 0, spdif_enable = 0;
 
-       enable = ucontrol->value.integer.value[0] ? 1 : 0;
+       spdif_enable = ucontrol->value.integer.value[0] ? 1 : 0;
 
        spin_lock_irq(&codec->reg_lock);
        switch (kcontrol->private_value) {
        case 0:
                change = (codec->spdif_mask & 0x02) ? 1 : 0;
-               change = change ^ enable;
+               change = change ^ spdif_enable;
                if (change) {
-                       if (enable) {
+                       if (spdif_enable) {
                                codec->spdif_mask |= 0x02;
                                snd_ali_enable_spdif_out(codec);
                        } else {
@@ -1859,9 +1859,9 @@ static int snd_ali5451_spdif_put(struct snd_kcontrol *kcontrol,
                break;
        case 1: 
                change = (codec->spdif_mask & 0x04) ? 1 : 0;
-               change = change ^ enable;
+               change = change ^ spdif_enable;
                if (change && (codec->spdif_mask & 0x02)) {
-                       if (enable) {
+                       if (spdif_enable) {
                                codec->spdif_mask |= 0x04;
                                snd_ali_enable_spdif_chnout(codec);
                        } else {
@@ -1872,9 +1872,9 @@ static int snd_ali5451_spdif_put(struct snd_kcontrol *kcontrol,
                break;
        case 2:
                change = (codec->spdif_mask & 0x01) ? 1 : 0;
-               change = change ^ enable;
+               change = change ^ spdif_enable;
                if (change) {
-                       if (enable) {
+                       if (spdif_enable) {
                                codec->spdif_mask |= 0x01;
                                snd_ali_enable_spdif_in(codec);
                        } else {
@@ -2047,10 +2047,8 @@ static int snd_ali_free(struct snd_ali * codec)
 {
        if (codec->hw_initialized)
                snd_ali_disable_address_interrupt(codec);
-       if (codec->irq >= 0) {
-               synchronize_irq(codec->irq);
+       if (codec->irq >= 0)
                free_irq(codec->irq, codec);
-       }
        if (codec->port)
                pci_release_regions(codec->pci);
        pci_disable_device(codec->pci);
index 0e990a7358211f4e80af8e376f0e76899bb0c326..8df6824b51cda258d2627d6eb30cbba1824e50b8 100644 (file)
@@ -92,8 +92,8 @@
 
 #if DEBUG_CALLS
 #define snd_als300_dbgcalls(format, args...) printk(format, ##args)
-#define snd_als300_dbgcallenter() printk(KERN_ERR "--> %s\n", __FUNCTION__)
-#define snd_als300_dbgcallleave() printk(KERN_ERR "<-- %s\n", __FUNCTION__)
+#define snd_als300_dbgcallenter() printk(KERN_ERR "--> %s\n", __func__)
+#define snd_als300_dbgcallleave() printk(KERN_ERR "<-- %s\n", __func__)
 #else
 #define snd_als300_dbgcalls(format, args...)
 #define snd_als300_dbgcallenter()
index 4594186b83ee7bfb4b157b6eff9e2aba79aa0916..457228fb22aad76dee9fafb9950d85c80acfd73c 100644 (file)
@@ -1553,7 +1553,7 @@ static int snd_atiixp_free(struct atiixp *chip)
        if (chip->irq < 0)
                goto __hw_end;
        snd_atiixp_chip_stop(chip);
-       synchronize_irq(chip->irq);
+
       __hw_end:
        if (chip->irq >= 0)
                free_irq(chip->irq, chip);
index a67a869180d4f572739be0de81063c45fe31948c..d457a32a7939fffb7987af0709a3bb353ce647c3 100644 (file)
@@ -1197,7 +1197,7 @@ static int snd_atiixp_free(struct atiixp_modem *chip)
        if (chip->irq < 0)
                goto __hw_end;
        snd_atiixp_chip_stop(chip);
-       synchronize_irq(chip->irq);
+
       __hw_end:
        if (chip->irq >= 0)
                free_irq(chip->irq, chip);
index 26819e2f5761810eeb3346c1224f740c4d00b276..68368e490074c21b6a0bd312d8c2a3b2e089f65d 100644 (file)
@@ -126,7 +126,6 @@ static int snd_vortex_dev_free(struct snd_device *device)
        vortex_gameport_unregister(vortex);
        vortex_core_shutdown(vortex);
        // Take down PCI interface.
-       synchronize_irq(vortex->irq);
        free_irq(vortex->irq, vortex);
        iounmap(vortex->mmio);
        pci_release_regions(vortex->pci_dev);
@@ -220,7 +219,6 @@ snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip)
        return 0;
 
       alloc_out:
-       synchronize_irq(chip->irq);
        free_irq(chip->irq, chip);
       irq_out:
        vortex_core_shutdown(chip);
index 526c6c5ecf7b658f7e1acb9d011ff437f9919c61..f9a58b4a30ebb2f8411c5439db8b6175e619c8ab 100644 (file)
@@ -498,14 +498,14 @@ static struct snd_kcontrol_new snd_vortex_mixer_spdif[] __devinitdata = {
 };
 
 /* create a pcm device */
-static int __devinit snd_vortex_new_pcm(vortex_t * chip, int idx, int nr)
+static int __devinit snd_vortex_new_pcm(vortex_t *chip, int idx, int nr)
 {
        struct snd_pcm *pcm;
        struct snd_kcontrol *kctl;
        int i;
        int err, nr_capt;
 
-       if ((chip == 0) || (idx < 0) || (idx >= VORTEX_PCM_LAST))
+       if (!chip || idx < 0 || idx >= VORTEX_PCM_LAST)
                return -ENODEV;
 
        /* idx indicates which kind of PCM device. ADB, SPDIF, I2S and A3D share the 
@@ -514,9 +514,9 @@ static int __devinit snd_vortex_new_pcm(vortex_t * chip, int idx, int nr)
                nr_capt = nr;
        else
                nr_capt = 0;
-       if ((err =
-            snd_pcm_new(chip->card, vortex_pcm_prettyname[idx], idx, nr,
-                        nr_capt, &pcm)) < 0)
+       err = snd_pcm_new(chip->card, vortex_pcm_prettyname[idx], idx, nr,
+                         nr_capt, &pcm);
+       if (err < 0)
                return err;
        strcpy(pcm->name, vortex_pcm_name[idx]);
        chip->pcm[idx] = pcm;
diff --git a/sound/pci/aw2/Makefile b/sound/pci/aw2/Makefile
new file mode 100644 (file)
index 0000000..842335d
--- /dev/null
@@ -0,0 +1,3 @@
+snd-aw2-objs := aw2-alsa.o aw2-saa7146.o
+
+obj-$(CONFIG_SND_AW2) += snd-aw2.o
diff --git a/sound/pci/aw2/aw2-alsa.c b/sound/pci/aw2/aw2-alsa.c
new file mode 100644 (file)
index 0000000..56f87cd
--- /dev/null
@@ -0,0 +1,794 @@
+/*****************************************************************************
+ *
+ * Copyright (C) 2008 Cedric Bregardis <cedric.bregardis@free.fr> and
+ * Jean-Christian Hassler <jhassler@free.fr>
+ *
+ * This file is part of the Audiowerk2 ALSA driver
+ *
+ * The Audiowerk2 ALSA 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; version 2.
+ *
+ * The Audiowerk2 ALSA 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 the Audiowerk2 ALSA driver; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
+ * USA.
+ *
+ *****************************************************************************/
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/control.h>
+
+#include "saa7146.h"
+#include "aw2-saa7146.h"
+
+MODULE_AUTHOR("Cedric Bregardis <cedric.bregardis@free.fr>, "
+             "Jean-Christian Hassler <jhassler@free.fr>");
+MODULE_DESCRIPTION("Emagic Audiowerk 2 sound driver");
+MODULE_LICENSE("GPL");
+
+/*********************************
+ * DEFINES
+ ********************************/
+#define PCI_VENDOR_ID_SAA7146            0x1131
+#define PCI_DEVICE_ID_SAA7146            0x7146
+
+#define CTL_ROUTE_ANALOG 0
+#define CTL_ROUTE_DIGITAL 1
+
+/*********************************
+ * TYPEDEFS
+ ********************************/
+  /* hardware definition */
+static struct snd_pcm_hardware snd_aw2_playback_hw = {
+       .info = (SNDRV_PCM_INFO_MMAP |
+                SNDRV_PCM_INFO_INTERLEAVED |
+                SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID),
+       .formats = SNDRV_PCM_FMTBIT_S16_LE,
+       .rates = SNDRV_PCM_RATE_44100,
+       .rate_min = 44100,
+       .rate_max = 44100,
+       .channels_min = 2,
+       .channels_max = 4,
+       .buffer_bytes_max = 32768,
+       .period_bytes_min = 4096,
+       .period_bytes_max = 32768,
+       .periods_min = 1,
+       .periods_max = 1024,
+};
+
+static struct snd_pcm_hardware snd_aw2_capture_hw = {
+       .info = (SNDRV_PCM_INFO_MMAP |
+                SNDRV_PCM_INFO_INTERLEAVED |
+                SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID),
+       .formats = SNDRV_PCM_FMTBIT_S16_LE,
+       .rates = SNDRV_PCM_RATE_44100,
+       .rate_min = 44100,
+       .rate_max = 44100,
+       .channels_min = 2,
+       .channels_max = 2,
+       .buffer_bytes_max = 32768,
+       .period_bytes_min = 4096,
+       .period_bytes_max = 32768,
+       .periods_min = 1,
+       .periods_max = 1024,
+};
+
+struct aw2_pcm_device {
+       struct snd_pcm *pcm;
+       unsigned int stream_number;
+       struct aw2 *chip;
+};
+
+struct aw2 {
+       struct snd_aw2_saa7146 saa7146;
+
+       struct pci_dev *pci;
+       int irq;
+       spinlock_t reg_lock;
+       struct mutex mtx;
+
+       unsigned long iobase_phys;
+       void __iomem *iobase_virt;
+
+       struct snd_card *card;
+
+       struct aw2_pcm_device device_playback[NB_STREAM_PLAYBACK];
+       struct aw2_pcm_device device_capture[NB_STREAM_CAPTURE];
+};
+
+/*********************************
+ * FUNCTION DECLARATIONS
+ ********************************/
+static int __init alsa_card_aw2_init(void);
+static void __exit alsa_card_aw2_exit(void);
+static int snd_aw2_dev_free(struct snd_device *device);
+static int __devinit snd_aw2_create(struct snd_card *card,
+                                   struct pci_dev *pci, struct aw2 **rchip);
+static int __devinit snd_aw2_probe(struct pci_dev *pci,
+                                  const struct pci_device_id *pci_id);
+static void __devexit snd_aw2_remove(struct pci_dev *pci);
+static int snd_aw2_pcm_playback_open(struct snd_pcm_substream *substream);
+static int snd_aw2_pcm_playback_close(struct snd_pcm_substream *substream);
+static int snd_aw2_pcm_capture_open(struct snd_pcm_substream *substream);
+static int snd_aw2_pcm_capture_close(struct snd_pcm_substream *substream);
+static int snd_aw2_pcm_hw_params(struct snd_pcm_substream *substream,
+                                struct snd_pcm_hw_params *hw_params);
+static int snd_aw2_pcm_hw_free(struct snd_pcm_substream *substream);
+static int snd_aw2_pcm_prepare_playback(struct snd_pcm_substream *substream);
+static int snd_aw2_pcm_prepare_capture(struct snd_pcm_substream *substream);
+static int snd_aw2_pcm_trigger_playback(struct snd_pcm_substream *substream,
+                                       int cmd);
+static int snd_aw2_pcm_trigger_capture(struct snd_pcm_substream *substream,
+                                      int cmd);
+static snd_pcm_uframes_t snd_aw2_pcm_pointer_playback(struct snd_pcm_substream
+                                                     *substream);
+static snd_pcm_uframes_t snd_aw2_pcm_pointer_capture(struct snd_pcm_substream
+                                                    *substream);
+static int __devinit snd_aw2_new_pcm(struct aw2 *chip);
+
+static int snd_aw2_control_switch_capture_info(struct snd_kcontrol *kcontrol,
+                                              struct snd_ctl_elem_info *uinfo);
+static int snd_aw2_control_switch_capture_get(struct snd_kcontrol *kcontrol,
+                                             struct snd_ctl_elem_value
+                                             *ucontrol);
+static int snd_aw2_control_switch_capture_put(struct snd_kcontrol *kcontrol,
+                                             struct snd_ctl_elem_value
+                                             *ucontrol);
+
+/*********************************
+ * VARIABLES
+ ********************************/
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for Audiowerk2 soundcard.");
+module_param_array(id, charp, NULL, 0444);
+MODULE_PARM_DESC(id, "ID string for the Audiowerk2 soundcard.");
+module_param_array(enable, bool, NULL, 0444);
+MODULE_PARM_DESC(enable, "Enable Audiowerk2 soundcard.");
+
+static struct pci_device_id snd_aw2_ids[] = {
+       {PCI_VENDOR_ID_SAA7146, PCI_DEVICE_ID_SAA7146, PCI_ANY_ID, PCI_ANY_ID,
+        0, 0, 0},
+       {0}
+};
+
+MODULE_DEVICE_TABLE(pci, snd_aw2_ids);
+
+/* pci_driver definition */
+static struct pci_driver driver = {
+       .name = "Emagic Audiowerk 2",
+       .id_table = snd_aw2_ids,
+       .probe = snd_aw2_probe,
+       .remove = __devexit_p(snd_aw2_remove),
+};
+
+/* operators for playback PCM alsa interface */
+static struct snd_pcm_ops snd_aw2_playback_ops = {
+       .open = snd_aw2_pcm_playback_open,
+       .close = snd_aw2_pcm_playback_close,
+       .ioctl = snd_pcm_lib_ioctl,
+       .hw_params = snd_aw2_pcm_hw_params,
+       .hw_free = snd_aw2_pcm_hw_free,
+       .prepare = snd_aw2_pcm_prepare_playback,
+       .trigger = snd_aw2_pcm_trigger_playback,
+       .pointer = snd_aw2_pcm_pointer_playback,
+};
+
+/* operators for capture PCM alsa interface */
+static struct snd_pcm_ops snd_aw2_capture_ops = {
+       .open = snd_aw2_pcm_capture_open,
+       .close = snd_aw2_pcm_capture_close,
+       .ioctl = snd_pcm_lib_ioctl,
+       .hw_params = snd_aw2_pcm_hw_params,
+       .hw_free = snd_aw2_pcm_hw_free,
+       .prepare = snd_aw2_pcm_prepare_capture,
+       .trigger = snd_aw2_pcm_trigger_capture,
+       .pointer = snd_aw2_pcm_pointer_capture,
+};
+
+static struct snd_kcontrol_new aw2_control __devinitdata = {
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name = "PCM Capture Route",
+       .index = 0,
+       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+       .private_value = 0xffff,
+       .info = snd_aw2_control_switch_capture_info,
+       .get = snd_aw2_control_switch_capture_get,
+       .put = snd_aw2_control_switch_capture_put
+};
+
+/*********************************
+ * FUNCTION IMPLEMENTATIONS
+ ********************************/
+
+/* initialization of the module */
+static int __init alsa_card_aw2_init(void)
+{
+       snd_printdd(KERN_DEBUG "aw2: Load aw2 module\n");
+       return pci_register_driver(&driver);
+}
+
+/* clean up the module */
+static void __exit alsa_card_aw2_exit(void)
+{
+       snd_printdd(KERN_DEBUG "aw2: Unload aw2 module\n");
+       pci_unregister_driver(&driver);
+}
+
+module_init(alsa_card_aw2_init);
+module_exit(alsa_card_aw2_exit);
+
+/* component-destructor */
+static int snd_aw2_dev_free(struct snd_device *device)
+{
+       struct aw2 *chip = device->device_data;
+
+       /* Free hardware */
+       snd_aw2_saa7146_free(&chip->saa7146);
+
+       /* release the irq */
+       if (chip->irq >= 0)
+               free_irq(chip->irq, (void *)chip);
+       /* release the i/o ports & memory */
+       if (chip->iobase_virt)
+               iounmap(chip->iobase_virt);
+
+       pci_release_regions(chip->pci);
+       /* disable the PCI entry */
+       pci_disable_device(chip->pci);
+       /* release the data */
+       kfree(chip);
+
+       return 0;
+}
+
+/* chip-specific constructor */
+static int __devinit snd_aw2_create(struct snd_card *card,
+                                   struct pci_dev *pci, struct aw2 **rchip)
+{
+       struct aw2 *chip;
+       int err;
+       static struct snd_device_ops ops = {
+               .dev_free = snd_aw2_dev_free,
+       };
+
+       *rchip = NULL;
+
+       /* initialize the PCI entry */
+       err = pci_enable_device(pci);
+       if (err < 0)
+               return err;
+       pci_set_master(pci);
+
+       /* check PCI availability (32bit DMA) */
+       if ((pci_set_dma_mask(pci, DMA_32BIT_MASK) < 0) ||
+           (pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK) < 0)) {
+               printk(KERN_ERR "aw2: Impossible 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;
+       }
+
+       /* initialize the stuff */
+       chip->card = card;
+       chip->pci = pci;
+       chip->irq = -1;
+
+       /* (1) PCI resource allocation */
+       err = pci_request_regions(pci, "Audiowerk2");
+       if (err < 0) {
+               pci_disable_device(pci);
+               kfree(chip);
+               return err;
+       }
+       chip->iobase_phys = pci_resource_start(pci, 0);
+       chip->iobase_virt =
+               ioremap_nocache(chip->iobase_phys,
+                               pci_resource_len(pci, 0));
+
+       if (chip->iobase_virt == NULL) {
+               printk(KERN_ERR "aw2: unable to remap memory region");
+               pci_release_regions(pci);
+               pci_disable_device(pci);
+               kfree(chip);
+               return -ENOMEM;
+       }
+
+
+       if (request_irq(pci->irq, snd_aw2_saa7146_interrupt,
+                       IRQF_SHARED, "Audiowerk2", chip)) {
+               printk(KERN_ERR "aw2: Cannot grab irq %d\n", pci->irq);
+
+               iounmap(chip->iobase_virt);
+               pci_release_regions(chip->pci);
+               pci_disable_device(chip->pci);
+               kfree(chip);
+               return -EBUSY;
+       }
+       chip->irq = pci->irq;
+
+       /* (2) initialization of the chip hardware */
+       snd_aw2_saa7146_setup(&chip->saa7146, chip->iobase_virt);
+       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
+       if (err < 0) {
+               free_irq(chip->irq, (void *)chip);
+               iounmap(chip->iobase_virt);
+               pci_release_regions(chip->pci);
+               pci_disable_device(chip->pci);
+               kfree(chip);
+               return err;
+       }
+
+       snd_card_set_dev(card, &pci->dev);
+       *rchip = chip;
+
+       printk(KERN_INFO
+              "Audiowerk 2 sound card (saa7146 chipset) detected and "
+              "managed\n");
+       return 0;
+}
+
+/* constructor */
+static int __devinit snd_aw2_probe(struct pci_dev *pci,
+                                  const struct pci_device_id *pci_id)
+{
+       static int dev;
+       struct snd_card *card;
+       struct aw2 *chip;
+       int err;
+
+       /* (1) Continue if device is not enabled, else inc dev */
+       if (dev >= SNDRV_CARDS)
+               return -ENODEV;
+       if (!enable[dev]) {
+               dev++;
+               return -ENOENT;
+       }
+
+       /* (2) Create card instance */
+       card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
+       if (card == NULL)
+               return -ENOMEM;
+
+       /* (3) Create main component */
+       err = snd_aw2_create(card, pci, &chip);
+       if (err < 0) {
+               snd_card_free(card);
+               return err;
+       }
+
+       /* initialize mutex */
+       mutex_init(&chip->mtx);
+       /* init spinlock */
+       spin_lock_init(&chip->reg_lock);
+       /* (4) Define driver ID and name string */
+       strcpy(card->driver, "aw2");
+       strcpy(card->shortname, "Audiowerk2");
+
+       sprintf(card->longname, "%s with SAA7146 irq %i",
+               card->shortname, chip->irq);
+
+       /* (5) Create other components */
+       snd_aw2_new_pcm(chip);
+
+       /* (6) Register card instance */
+       err = snd_card_register(card);
+       if (err < 0) {
+               snd_card_free(card);
+               return err;
+       }
+
+       /* (7) Set PCI driver data */
+       pci_set_drvdata(pci, card);
+
+       dev++;
+       return 0;
+}
+
+/* destructor */
+static void __devexit snd_aw2_remove(struct pci_dev *pci)
+{
+       snd_card_free(pci_get_drvdata(pci));
+       pci_set_drvdata(pci, NULL);
+}
+
+/* open callback */
+static int snd_aw2_pcm_playback_open(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+
+       snd_printdd(KERN_DEBUG "aw2: Playback_open \n");
+       runtime->hw = snd_aw2_playback_hw;
+       return 0;
+}
+
+/* close callback */
+static int snd_aw2_pcm_playback_close(struct snd_pcm_substream *substream)
+{
+       return 0;
+
+}
+
+static int snd_aw2_pcm_capture_open(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+
+       snd_printdd(KERN_DEBUG "aw2: Capture_open \n");
+       runtime->hw = snd_aw2_capture_hw;
+       return 0;
+}
+
+/* close callback */
+static int snd_aw2_pcm_capture_close(struct snd_pcm_substream *substream)
+{
+       /* TODO: something to do ? */
+       return 0;
+}
+
+ /* hw_params callback */
+static int snd_aw2_pcm_hw_params(struct snd_pcm_substream *substream,
+                                struct snd_pcm_hw_params *hw_params)
+{
+       return snd_pcm_lib_malloc_pages(substream,
+                                       params_buffer_bytes(hw_params));
+}
+
+/* hw_free callback */
+static int snd_aw2_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+       return snd_pcm_lib_free_pages(substream);
+}
+
+/* prepare callback for playback */
+static int snd_aw2_pcm_prepare_playback(struct snd_pcm_substream *substream)
+{
+       struct aw2_pcm_device *pcm_device = snd_pcm_substream_chip(substream);
+       struct aw2 *chip = pcm_device->chip;
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       unsigned long period_size, buffer_size;
+
+       mutex_lock(&chip->mtx);
+
+       period_size = snd_pcm_lib_period_bytes(substream);
+       buffer_size = snd_pcm_lib_buffer_bytes(substream);
+
+       snd_aw2_saa7146_pcm_init_playback(&chip->saa7146,
+                                         pcm_device->stream_number,
+                                         runtime->dma_addr, period_size,
+                                         buffer_size);
+
+       /* Define Interrupt callback */
+       snd_aw2_saa7146_define_it_playback_callback(pcm_device->stream_number,
+                                                   (snd_aw2_saa7146_it_cb)
+                                                   snd_pcm_period_elapsed,
+                                                   (void *)substream);
+
+       mutex_unlock(&chip->mtx);
+
+       return 0;
+}
+
+/* prepare callback for capture */
+static int snd_aw2_pcm_prepare_capture(struct snd_pcm_substream *substream)
+{
+       struct aw2_pcm_device *pcm_device = snd_pcm_substream_chip(substream);
+       struct aw2 *chip = pcm_device->chip;
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       unsigned long period_size, buffer_size;
+
+       mutex_lock(&chip->mtx);
+
+       period_size = snd_pcm_lib_period_bytes(substream);
+       buffer_size = snd_pcm_lib_buffer_bytes(substream);
+
+       snd_aw2_saa7146_pcm_init_capture(&chip->saa7146,
+                                        pcm_device->stream_number,
+                                        runtime->dma_addr, period_size,
+                                        buffer_size);
+
+       /* Define Interrupt callback */
+       snd_aw2_saa7146_define_it_capture_callback(pcm_device->stream_number,
+                                                  (snd_aw2_saa7146_it_cb)
+                                                  snd_pcm_period_elapsed,
+                                                  (void *)substream);
+
+       mutex_unlock(&chip->mtx);
+
+       return 0;
+}
+
+/* playback trigger callback */
+static int snd_aw2_pcm_trigger_playback(struct snd_pcm_substream *substream,
+                                       int cmd)
+{
+       int status = 0;
+       struct aw2_pcm_device *pcm_device = snd_pcm_substream_chip(substream);
+       struct aw2 *chip = pcm_device->chip;
+       spin_lock(&chip->reg_lock);
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+               snd_aw2_saa7146_pcm_trigger_start_playback(&chip->saa7146,
+                                                          pcm_device->
+                                                          stream_number);
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+               snd_aw2_saa7146_pcm_trigger_stop_playback(&chip->saa7146,
+                                                         pcm_device->
+                                                         stream_number);
+               break;
+       default:
+               status = -EINVAL;
+       }
+       spin_unlock(&chip->reg_lock);
+       return status;
+}
+
+/* capture trigger callback */
+static int snd_aw2_pcm_trigger_capture(struct snd_pcm_substream *substream,
+                                      int cmd)
+{
+       int status = 0;
+       struct aw2_pcm_device *pcm_device = snd_pcm_substream_chip(substream);
+       struct aw2 *chip = pcm_device->chip;
+       spin_lock(&chip->reg_lock);
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+               snd_aw2_saa7146_pcm_trigger_start_capture(&chip->saa7146,
+                                                         pcm_device->
+                                                         stream_number);
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+               snd_aw2_saa7146_pcm_trigger_stop_capture(&chip->saa7146,
+                                                        pcm_device->
+                                                        stream_number);
+               break;
+       default:
+               status = -EINVAL;
+       }
+       spin_unlock(&chip->reg_lock);
+       return status;
+}
+
+/* playback pointer callback */
+static snd_pcm_uframes_t snd_aw2_pcm_pointer_playback(struct snd_pcm_substream
+                                                     *substream)
+{
+       struct aw2_pcm_device *pcm_device = snd_pcm_substream_chip(substream);
+       struct aw2 *chip = pcm_device->chip;
+       unsigned int current_ptr;
+
+       /* get the current hardware pointer */
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       current_ptr =
+               snd_aw2_saa7146_get_hw_ptr_playback(&chip->saa7146,
+                                                   pcm_device->stream_number,
+                                                   runtime->dma_area,
+                                                   runtime->buffer_size);
+
+       return bytes_to_frames(substream->runtime, current_ptr);
+}
+
+/* capture pointer callback */
+static snd_pcm_uframes_t snd_aw2_pcm_pointer_capture(struct snd_pcm_substream
+                                                    *substream)
+{
+       struct aw2_pcm_device *pcm_device = snd_pcm_substream_chip(substream);
+       struct aw2 *chip = pcm_device->chip;
+       unsigned int current_ptr;
+
+       /* get the current hardware pointer */
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       current_ptr =
+               snd_aw2_saa7146_get_hw_ptr_capture(&chip->saa7146,
+                                                  pcm_device->stream_number,
+                                                  runtime->dma_area,
+                                                  runtime->buffer_size);
+
+       return bytes_to_frames(substream->runtime, current_ptr);
+}
+
+/* create a pcm device */
+static int __devinit snd_aw2_new_pcm(struct aw2 *chip)
+{
+       struct snd_pcm *pcm_playback_ana;
+       struct snd_pcm *pcm_playback_num;
+       struct snd_pcm *pcm_capture;
+       struct aw2_pcm_device *pcm_device;
+       int err = 0;
+
+       /* Create new Alsa PCM device */
+
+       err = snd_pcm_new(chip->card, "Audiowerk2 analog playback", 0, 1, 0,
+                         &pcm_playback_ana);
+       if (err < 0) {
+               printk(KERN_ERR "aw2: snd_pcm_new error (0x%X)\n", err);
+               return err;
+       }
+
+       /* Creation ok */
+       pcm_device = &chip->device_playback[NUM_STREAM_PLAYBACK_ANA];
+
+       /* Set PCM device name */
+       strcpy(pcm_playback_ana->name, "Analog playback");
+       /* Associate private data to PCM device */
+       pcm_playback_ana->private_data = pcm_device;
+       /* set operators of PCM device */
+       snd_pcm_set_ops(pcm_playback_ana, SNDRV_PCM_STREAM_PLAYBACK,
+                       &snd_aw2_playback_ops);
+       /* store PCM device */
+       pcm_device->pcm = pcm_playback_ana;
+       /* give base chip pointer to our internal pcm device
+          structure */
+       pcm_device->chip = chip;
+       /* Give stream number to PCM device */
+       pcm_device->stream_number = NUM_STREAM_PLAYBACK_ANA;
+
+       /* pre-allocation of buffers */
+       /* Preallocate continuous pages. */
+       err = snd_pcm_lib_preallocate_pages_for_all(pcm_playback_ana,
+                                                   SNDRV_DMA_TYPE_DEV,
+                                                   snd_dma_pci_data
+                                                   (chip->pci),
+                                                   64 * 1024, 64 * 1024);
+       if (err)
+               printk(KERN_ERR "aw2: snd_pcm_lib_preallocate_pages_for_all "
+                      "error (0x%X)\n", err);
+
+       err = snd_pcm_new(chip->card, "Audiowerk2 digital playback", 1, 1, 0,
+                         &pcm_playback_num);
+
+       if (err < 0) {
+               printk(KERN_ERR "aw2: snd_pcm_new error (0x%X)\n", err);
+               return err;
+       }
+       /* Creation ok */
+       pcm_device = &chip->device_playback[NUM_STREAM_PLAYBACK_DIG];
+
+       /* Set PCM device name */
+       strcpy(pcm_playback_num->name, "Digital playback");
+       /* Associate private data to PCM device */
+       pcm_playback_num->private_data = pcm_device;
+       /* set operators of PCM device */
+       snd_pcm_set_ops(pcm_playback_num, SNDRV_PCM_STREAM_PLAYBACK,
+                       &snd_aw2_playback_ops);
+       /* store PCM device */
+       pcm_device->pcm = pcm_playback_num;
+       /* give base chip pointer to our internal pcm device
+          structure */
+       pcm_device->chip = chip;
+       /* Give stream number to PCM device */
+       pcm_device->stream_number = NUM_STREAM_PLAYBACK_DIG;
+
+       /* pre-allocation of buffers */
+       /* Preallocate continuous pages. */
+       err = snd_pcm_lib_preallocate_pages_for_all(pcm_playback_num,
+                                                   SNDRV_DMA_TYPE_DEV,
+                                                   snd_dma_pci_data
+                                                   (chip->pci),
+                                                   64 * 1024, 64 * 1024);
+       if (err)
+               printk(KERN_ERR
+                      "aw2: snd_pcm_lib_preallocate_pages_for_all error "
+                      "(0x%X)\n", err);
+
+
+
+       err = snd_pcm_new(chip->card, "Audiowerk2 capture", 2, 0, 1,
+                         &pcm_capture);
+
+       if (err < 0) {
+               printk(KERN_ERR "aw2: snd_pcm_new error (0x%X)\n", err);
+               return err;
+       }
+
+       /* Creation ok */
+       pcm_device = &chip->device_capture[NUM_STREAM_CAPTURE_ANA];
+
+       /* Set PCM device name */
+       strcpy(pcm_capture->name, "Capture");
+       /* Associate private data to PCM device */
+       pcm_capture->private_data = pcm_device;
+       /* set operators of PCM device */
+       snd_pcm_set_ops(pcm_capture, SNDRV_PCM_STREAM_CAPTURE,
+                       &snd_aw2_capture_ops);
+       /* store PCM device */
+       pcm_device->pcm = pcm_capture;
+       /* give base chip pointer to our internal pcm device
+          structure */
+       pcm_device->chip = chip;
+       /* Give stream number to PCM device */
+       pcm_device->stream_number = NUM_STREAM_CAPTURE_ANA;
+
+       /* pre-allocation of buffers */
+       /* Preallocate continuous pages. */
+       err = snd_pcm_lib_preallocate_pages_for_all(pcm_capture,
+                                                   SNDRV_DMA_TYPE_DEV,
+                                                   snd_dma_pci_data
+                                                   (chip->pci),
+                                                   64 * 1024, 64 * 1024);
+       if (err)
+               printk(KERN_ERR
+                      "aw2: snd_pcm_lib_preallocate_pages_for_all error "
+                      "(0x%X)\n", err);
+
+
+       /* Create control */
+       err = snd_ctl_add(chip->card, snd_ctl_new1(&aw2_control, chip));
+       if (err < 0) {
+               printk(KERN_ERR "aw2: snd_ctl_add error (0x%X)\n", err);
+               return err;
+       }
+
+       return 0;
+}
+
+static int snd_aw2_control_switch_capture_info(struct snd_kcontrol *kcontrol,
+                                              struct snd_ctl_elem_info *uinfo)
+{
+       static char *texts[2] = {
+               "Analog", "Digital"
+       };
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+       uinfo->count = 1;
+       uinfo->value.enumerated.items = 2;
+       if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) {
+               uinfo->value.enumerated.item =
+                   uinfo->value.enumerated.items - 1;
+       }
+       strcpy(uinfo->value.enumerated.name,
+              texts[uinfo->value.enumerated.item]);
+       return 0;
+}
+
+static int snd_aw2_control_switch_capture_get(struct snd_kcontrol *kcontrol,
+                                             struct snd_ctl_elem_value
+                                             *ucontrol)
+{
+       struct aw2 *chip = snd_kcontrol_chip(kcontrol);
+       if (snd_aw2_saa7146_is_using_digital_input(&chip->saa7146))
+               ucontrol->value.enumerated.item[0] = CTL_ROUTE_DIGITAL;
+       else
+               ucontrol->value.enumerated.item[0] = CTL_ROUTE_ANALOG;
+       return 0;
+}
+
+static int snd_aw2_control_switch_capture_put(struct snd_kcontrol *kcontrol,
+                                             struct snd_ctl_elem_value
+                                             *ucontrol)
+{
+       struct aw2 *chip = snd_kcontrol_chip(kcontrol);
+       int changed = 0;
+       int is_disgital =
+           snd_aw2_saa7146_is_using_digital_input(&chip->saa7146);
+
+       if (((ucontrol->value.integer.value[0] == CTL_ROUTE_DIGITAL)
+            && !is_disgital)
+           || ((ucontrol->value.integer.value[0] == CTL_ROUTE_ANALOG)
+               && is_disgital)) {
+               snd_aw2_saa7146_use_digital_input(&chip->saa7146, !is_disgital);
+               changed = 1;
+       }
+       return changed;
+}
diff --git a/sound/pci/aw2/aw2-saa7146.c b/sound/pci/aw2/aw2-saa7146.c
new file mode 100644 (file)
index 0000000..6a3891a
--- /dev/null
@@ -0,0 +1,465 @@
+/*****************************************************************************
+ *
+ * Copyright (C) 2008 Cedric Bregardis <cedric.bregardis@free.fr> and
+ * Jean-Christian Hassler <jhassler@free.fr>
+ *
+ * This file is part of the Audiowerk2 ALSA driver
+ *
+ * The Audiowerk2 ALSA 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; version 2.
+ *
+ * The Audiowerk2 ALSA 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 the Audiowerk2 ALSA driver; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
+ * USA.
+ *
+ *****************************************************************************/
+
+#define AW2_SAA7146_M
+
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+
+#include "saa7146.h"
+#include "aw2-saa7146.h"
+
+#include "aw2-tsl.c"
+
+#define WRITEREG(value, addr) writel((value), chip->base_addr + (addr))
+#define READREG(addr) readl(chip->base_addr + (addr))
+
+static struct snd_aw2_saa7146_cb_param
+ arr_substream_it_playback_cb[NB_STREAM_PLAYBACK];
+static struct snd_aw2_saa7146_cb_param
+ arr_substream_it_capture_cb[NB_STREAM_CAPTURE];
+
+static int snd_aw2_saa7146_get_limit(int size);
+
+/* chip-specific destructor */
+int snd_aw2_saa7146_free(struct snd_aw2_saa7146 *chip)
+{
+       /* disable all irqs */
+       WRITEREG(0, IER);
+
+       /* reset saa7146 */
+       WRITEREG((MRST_N << 16), MC1);
+
+       /* Unset base addr */
+       chip->base_addr = NULL;
+
+       return 0;
+}
+
+void snd_aw2_saa7146_setup(struct snd_aw2_saa7146 *chip,
+                          void __iomem *pci_base_addr)
+{
+       /* set PCI burst/threshold
+
+          Burst length definition
+          VALUE    BURST LENGTH
+          000      1 Dword
+          001      2 Dwords
+          010      4 Dwords
+          011      8 Dwords
+          100      16 Dwords
+          101      32 Dwords
+          110      64 Dwords
+          111      128 Dwords
+
+          Threshold definition
+          VALUE    WRITE MODE              READ MODE
+          00       1 Dword of valid data   1 empty Dword
+          01       4 Dwords of valid data  4 empty Dwords
+          10       8 Dwords of valid data  8 empty Dwords
+          11       16 Dwords of valid data 16 empty Dwords */
+
+       unsigned int acon2;
+       unsigned int acon1 = 0;
+       int i;
+
+       /* Set base addr */
+       chip->base_addr = pci_base_addr;
+
+       /* disable all irqs */
+       WRITEREG(0, IER);
+
+       /* reset saa7146 */
+       WRITEREG((MRST_N << 16), MC1);
+
+       /* enable audio interface */
+#ifdef __BIG_ENDIAN
+       acon1 |= A1_SWAP;
+       acon1 |= A2_SWAP;
+#endif
+       /* WS0_CTRL, WS0_SYNC: input TSL1, I2S */
+
+       /* At initialization WS1 and WS2 are disbaled (configured as input */
+       acon1 |= 0 * WS1_CTRL;
+       acon1 |= 0 * WS2_CTRL;
+
+       /* WS4 is not used. So it must not restart A2.
+          This is why it is configured as output (force to low) */
+       acon1 |= 3 * WS4_CTRL;
+
+       /* WS3_CTRL, WS3_SYNC: output TSL2, I2S */
+       acon1 |= 2 * WS3_CTRL;
+
+       /* A1 and A2 are active and asynchronous */
+       acon1 |= 3 * AUDIO_MODE;
+       WRITEREG(acon1, ACON1);
+
+       /* The following comes from original windows driver.
+          It is needed to have a correct behavior of input and output
+          simultenously, but I don't know why ! */
+       WRITEREG(3 * (BurstA1_in) + 3 * (ThreshA1_in) +
+                3 * (BurstA1_out) + 3 * (ThreshA1_out) +
+                3 * (BurstA2_out) + 3 * (ThreshA2_out), PCI_BT_A);
+
+       /* enable audio port pins */
+       WRITEREG((EAP << 16) | EAP, MC1);
+
+       /* enable I2C */
+       WRITEREG((EI2C << 16) | EI2C, MC1);
+       /* enable interrupts */
+       WRITEREG(A1_out | A2_out | A1_in | IIC_S | IIC_E, IER);
+
+       /* audio configuration */
+       acon2 = A2_CLKSRC | BCLK1_OEN;
+       WRITEREG(acon2, ACON2);
+
+       /* By default use analog input */
+       snd_aw2_saa7146_use_digital_input(chip, 0);
+
+       /* TSL setup */
+       for (i = 0; i < 8; ++i) {
+               WRITEREG(tsl1[i], TSL1 + (i * 4));
+               WRITEREG(tsl2[i], TSL2 + (i * 4));
+       }
+
+}
+
+void snd_aw2_saa7146_pcm_init_playback(struct snd_aw2_saa7146 *chip,
+                                      int stream_number,
+                                      unsigned long dma_addr,
+                                      unsigned long period_size,
+                                      unsigned long buffer_size)
+{
+       unsigned long dw_page, dw_limit;
+
+       /* Configure DMA for substream
+          Configuration informations: ALSA has allocated continuous memory
+          pages. So we don't need to use MMU of saa7146.
+        */
+
+       /* No MMU -> nothing to do with PageA1, we only configure the limit of
+          PageAx_out register */
+       /* Disable MMU */
+       dw_page = (0L << 11);
+
+       /* Configure Limit for DMA access.
+          The limit register defines an address limit, which generates
+          an interrupt if passed by the actual PCI address pointer.
+          '0001' means an interrupt will be generated if the lower
+          6 bits (64 bytes) of the PCI address are zero. '0010'
+          defines a limit of 128 bytes, '0011' one of 256 bytes, and
+          so on up to 1 Mbyte defined by '1111'. This interrupt range
+          can be calculated as follows:
+          Range = 2^(5 + Limit) bytes.
+        */
+       dw_limit = snd_aw2_saa7146_get_limit(period_size);
+       dw_page |= (dw_limit << 4);
+
+       if (stream_number == 0) {
+               WRITEREG(dw_page, PageA2_out);
+
+               /* Base address for DMA transfert. */
+               /* This address has been reserved by ALSA. */
+               /* This is a physical address */
+               WRITEREG(dma_addr, BaseA2_out);
+
+               /* Define upper limit for DMA access */
+               WRITEREG(dma_addr + buffer_size, ProtA2_out);
+
+       } else if (stream_number == 1) {
+               WRITEREG(dw_page, PageA1_out);
+
+               /* Base address for DMA transfert. */
+               /* This address has been reserved by ALSA. */
+               /* This is a physical address */
+               WRITEREG(dma_addr, BaseA1_out);
+
+               /* Define upper limit for DMA access */
+               WRITEREG(dma_addr + buffer_size, ProtA1_out);
+       } else {
+               printk(KERN_ERR
+                      "aw2: snd_aw2_saa7146_pcm_init_playback: "
+                      "Substream number is not 0 or 1 -> not managed\n");
+       }
+}
+
+void snd_aw2_saa7146_pcm_init_capture(struct snd_aw2_saa7146 *chip,
+                                     int stream_number, unsigned long dma_addr,
+                                     unsigned long period_size,
+                                     unsigned long buffer_size)
+{
+       unsigned long dw_page, dw_limit;
+
+       /* Configure DMA for substream
+          Configuration informations: ALSA has allocated continuous memory
+          pages. So we don't need to use MMU of saa7146.
+        */
+
+       /* No MMU -> nothing to do with PageA1, we only configure the limit of
+          PageAx_out register */
+       /* Disable MMU */
+       dw_page = (0L << 11);
+
+       /* Configure Limit for DMA access.
+          The limit register defines an address limit, which generates
+          an interrupt if passed by the actual PCI address pointer.
+          '0001' means an interrupt will be generated if the lower
+          6 bits (64 bytes) of the PCI address are zero. '0010'
+          defines a limit of 128 bytes, '0011' one of 256 bytes, and
+          so on up to 1 Mbyte defined by '1111'. This interrupt range
+          can be calculated as follows:
+          Range = 2^(5 + Limit) bytes.
+        */
+       dw_limit = snd_aw2_saa7146_get_limit(period_size);
+       dw_page |= (dw_limit << 4);
+
+       if (stream_number == 0) {
+               WRITEREG(dw_page, PageA1_in);
+
+               /* Base address for DMA transfert. */
+               /* This address has been reserved by ALSA. */
+               /* This is a physical address */
+               WRITEREG(dma_addr, BaseA1_in);
+
+               /* Define upper limit for DMA access  */
+               WRITEREG(dma_addr + buffer_size, ProtA1_in);
+       } else {
+               printk(KERN_ERR
+                      "aw2: snd_aw2_saa7146_pcm_init_capture: "
+                      "Substream number is not 0 -> not managed\n");
+       }
+}
+
+void snd_aw2_saa7146_define_it_playback_callback(unsigned int stream_number,
+                                                snd_aw2_saa7146_it_cb
+                                                p_it_callback,
+                                                void *p_callback_param)
+{
+       if (stream_number < NB_STREAM_PLAYBACK) {
+               arr_substream_it_playback_cb[stream_number].p_it_callback =
+                   (snd_aw2_saa7146_it_cb) p_it_callback;
+               arr_substream_it_playback_cb[stream_number].p_callback_param =
+                   (void *)p_callback_param;
+       }
+}
+
+void snd_aw2_saa7146_define_it_capture_callback(unsigned int stream_number,
+                                               snd_aw2_saa7146_it_cb
+                                               p_it_callback,
+                                               void *p_callback_param)
+{
+       if (stream_number < NB_STREAM_CAPTURE) {
+               arr_substream_it_capture_cb[stream_number].p_it_callback =
+                   (snd_aw2_saa7146_it_cb) p_it_callback;
+               arr_substream_it_capture_cb[stream_number].p_callback_param =
+                   (void *)p_callback_param;
+       }
+}
+
+void snd_aw2_saa7146_pcm_trigger_start_playback(struct snd_aw2_saa7146 *chip,
+                                               int stream_number)
+{
+       unsigned int acon1 = 0;
+       /* In aw8 driver, dma transfert is always active. It is
+          started and stopped in a larger "space" */
+       acon1 = READREG(ACON1);
+       if (stream_number == 0) {
+               WRITEREG((TR_E_A2_OUT << 16) | TR_E_A2_OUT, MC1);
+
+               /* WS2_CTRL, WS2_SYNC: output TSL2, I2S */
+               acon1 |= 2 * WS2_CTRL;
+               WRITEREG(acon1, ACON1);
+
+       } else if (stream_number == 1) {
+               WRITEREG((TR_E_A1_OUT << 16) | TR_E_A1_OUT, MC1);
+
+               /* WS1_CTRL, WS1_SYNC: output TSL1, I2S */
+               acon1 |= 1 * WS1_CTRL;
+               WRITEREG(acon1, ACON1);
+       }
+}
+
+void snd_aw2_saa7146_pcm_trigger_stop_playback(struct snd_aw2_saa7146 *chip,
+                                              int stream_number)
+{
+       unsigned int acon1 = 0;
+       acon1 = READREG(ACON1);
+       if (stream_number == 0) {
+               /* WS2_CTRL, WS2_SYNC: output TSL2, I2S */
+               acon1 &= ~(3 * WS2_CTRL);
+               WRITEREG(acon1, ACON1);
+
+               WRITEREG((TR_E_A2_OUT << 16), MC1);
+       } else if (stream_number == 1) {
+               /* WS1_CTRL, WS1_SYNC: output TSL1, I2S */
+               acon1 &= ~(3 * WS1_CTRL);
+               WRITEREG(acon1, ACON1);
+
+               WRITEREG((TR_E_A1_OUT << 16), MC1);
+       }
+}
+
+void snd_aw2_saa7146_pcm_trigger_start_capture(struct snd_aw2_saa7146 *chip,
+                                              int stream_number)
+{
+       /* In aw8 driver, dma transfert is always active. It is
+          started and stopped in a larger "space" */
+       if (stream_number == 0)
+               WRITEREG((TR_E_A1_IN << 16) | TR_E_A1_IN, MC1);
+}
+
+void snd_aw2_saa7146_pcm_trigger_stop_capture(struct snd_aw2_saa7146 *chip,
+                                             int stream_number)
+{
+       if (stream_number == 0)
+               WRITEREG((TR_E_A1_IN << 16), MC1);
+}
+
+irqreturn_t snd_aw2_saa7146_interrupt(int irq, void *dev_id)
+{
+       unsigned int isr;
+       unsigned int iicsta;
+       struct snd_aw2_saa7146 *chip = dev_id;
+
+       isr = READREG(ISR);
+       if (!isr)
+               return IRQ_NONE;
+
+       WRITEREG(isr, ISR);
+
+       if (isr & (IIC_S | IIC_E)) {
+               iicsta = READREG(IICSTA);
+               WRITEREG(0x100, IICSTA);
+       }
+
+       if (isr & A1_out) {
+               if (arr_substream_it_playback_cb[1].p_it_callback != NULL) {
+                       arr_substream_it_playback_cb[1].
+                           p_it_callback(arr_substream_it_playback_cb[1].
+                                         p_callback_param);
+               }
+       }
+       if (isr & A2_out) {
+               if (arr_substream_it_playback_cb[0].p_it_callback != NULL) {
+                       arr_substream_it_playback_cb[0].
+                           p_it_callback(arr_substream_it_playback_cb[0].
+                                         p_callback_param);
+               }
+
+       }
+       if (isr & A1_in) {
+               if (arr_substream_it_capture_cb[0].p_it_callback != NULL) {
+                       arr_substream_it_capture_cb[0].
+                           p_it_callback(arr_substream_it_capture_cb[0].
+                                         p_callback_param);
+               }
+       }
+       return IRQ_HANDLED;
+}
+
+unsigned int snd_aw2_saa7146_get_hw_ptr_playback(struct snd_aw2_saa7146 *chip,
+                                                int stream_number,
+                                                unsigned char *start_addr,
+                                                unsigned int buffer_size)
+{
+       long pci_adp = 0;
+       size_t ptr = 0;
+
+       if (stream_number == 0) {
+               pci_adp = READREG(PCI_ADP3);
+               ptr = pci_adp - (long)start_addr;
+
+               if (ptr == buffer_size)
+                       ptr = 0;
+       }
+       if (stream_number == 1) {
+               pci_adp = READREG(PCI_ADP1);
+               ptr = pci_adp - (size_t) start_addr;
+
+               if (ptr == buffer_size)
+                       ptr = 0;
+       }
+       return ptr;
+}
+
+unsigned int snd_aw2_saa7146_get_hw_ptr_capture(struct snd_aw2_saa7146 *chip,
+                                               int stream_number,
+                                               unsigned char *start_addr,
+                                               unsigned int buffer_size)
+{
+       size_t pci_adp = 0;
+       size_t ptr = 0;
+       if (stream_number == 0) {
+               pci_adp = READREG(PCI_ADP2);
+               ptr = pci_adp - (size_t) start_addr;
+
+               if (ptr == buffer_size)
+                       ptr = 0;
+       }
+       return ptr;
+}
+
+void snd_aw2_saa7146_use_digital_input(struct snd_aw2_saa7146 *chip,
+                                      int use_digital)
+{
+       /* FIXME: switch between analog and digital input does not always work.
+          It can produce a kind of white noise. It seams that received data
+          are inverted sometime (endian inversion). Why ? I don't know, maybe
+          a problem of synchronization... However for the time being I have
+          not found the problem. Workaround: switch again (and again) between
+          digital and analog input until it works. */
+       if (use_digital)
+               WRITEREG(0x40, GPIO_CTRL);
+       else
+               WRITEREG(0x50, GPIO_CTRL);
+}
+
+int snd_aw2_saa7146_is_using_digital_input(struct snd_aw2_saa7146 *chip)
+{
+       unsigned int reg_val = READREG(GPIO_CTRL);
+       if ((reg_val & 0xFF) == 0x40)
+               return 1;
+       else
+               return 0;
+}
+
+
+static int snd_aw2_saa7146_get_limit(int size)
+{
+       int limitsize = 32;
+       int limit = 0;
+       while (limitsize < size) {
+               limitsize *= 2;
+               limit++;
+       }
+       return limit;
+}
diff --git a/sound/pci/aw2/aw2-saa7146.h b/sound/pci/aw2/aw2-saa7146.h
new file mode 100644 (file)
index 0000000..5b35e35
--- /dev/null
@@ -0,0 +1,105 @@
+/*****************************************************************************
+ *
+ * Copyright (C) 2008 Cedric Bregardis <cedric.bregardis@free.fr> and
+ * Jean-Christian Hassler <jhassler@free.fr>
+ *
+ * This file is part of the Audiowerk2 ALSA driver
+ *
+ * The Audiowerk2 ALSA 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; version 2.
+ *
+ * The Audiowerk2 ALSA 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 the Audiowerk2 ALSA driver; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
+ * USA.
+ *
+ *****************************************************************************/
+
+#ifndef AW2_SAA7146_H
+#define AW2_SAA7146_H
+
+#define NB_STREAM_PLAYBACK 2
+#define NB_STREAM_CAPTURE 1
+
+#define NUM_STREAM_PLAYBACK_ANA 0
+#define NUM_STREAM_PLAYBACK_DIG 1
+
+#define NUM_STREAM_CAPTURE_ANA 0
+
+typedef void (*snd_aw2_saa7146_it_cb) (void *);
+
+struct snd_aw2_saa7146_cb_param {
+       snd_aw2_saa7146_it_cb p_it_callback;
+       void *p_callback_param;
+};
+
+/* definition of the chip-specific record */
+
+struct snd_aw2_saa7146 {
+       void __iomem *base_addr;
+};
+
+extern void snd_aw2_saa7146_setup(struct snd_aw2_saa7146 *chip,
+                                 void __iomem *pci_base_addr);
+extern int snd_aw2_saa7146_free(struct snd_aw2_saa7146 *chip);
+
+extern void snd_aw2_saa7146_pcm_init_playback(struct snd_aw2_saa7146 *chip,
+                                             int stream_number,
+                                             unsigned long dma_addr,
+                                             unsigned long period_size,
+                                             unsigned long buffer_size);
+extern void snd_aw2_saa7146_pcm_init_capture(struct snd_aw2_saa7146 *chip,
+                                            int stream_number,
+                                            unsigned long dma_addr,
+                                            unsigned long period_size,
+                                            unsigned long buffer_size);
+extern void snd_aw2_saa7146_define_it_playback_callback(unsigned int
+                                                       stream_number,
+                                                       snd_aw2_saa7146_it_cb
+                                                       p_it_callback,
+                                                       void *p_callback_param);
+extern void snd_aw2_saa7146_define_it_capture_callback(unsigned int
+                                                      stream_number,
+                                                      snd_aw2_saa7146_it_cb
+                                                      p_it_callback,
+                                                      void *p_callback_param);
+extern void snd_aw2_saa7146_pcm_trigger_start_capture(struct snd_aw2_saa7146
+                                                     *chip, int stream_number);
+extern void snd_aw2_saa7146_pcm_trigger_stop_capture(struct snd_aw2_saa7146
+                                                    *chip, int stream_number);
+
+extern void snd_aw2_saa7146_pcm_trigger_start_playback(struct snd_aw2_saa7146
+                                                      *chip,
+                                                      int stream_number);
+extern void snd_aw2_saa7146_pcm_trigger_stop_playback(struct snd_aw2_saa7146
+                                                     *chip, int stream_number);
+
+extern irqreturn_t snd_aw2_saa7146_interrupt(int irq, void *dev_id);
+extern unsigned int snd_aw2_saa7146_get_hw_ptr_playback(struct snd_aw2_saa7146
+                                                       *chip,
+                                                       int stream_number,
+                                                       unsigned char
+                                                       *start_addr,
+                                                       unsigned int
+                                                       buffer_size);
+extern unsigned int snd_aw2_saa7146_get_hw_ptr_capture(struct snd_aw2_saa7146
+                                                      *chip,
+                                                      int stream_number,
+                                                      unsigned char
+                                                      *start_addr,
+                                                      unsigned int
+                                                      buffer_size);
+
+extern void snd_aw2_saa7146_use_digital_input(struct snd_aw2_saa7146 *chip,
+                                             int use_digital);
+
+extern int snd_aw2_saa7146_is_using_digital_input(struct snd_aw2_saa7146
+                                                 *chip);
+
+#endif
diff --git a/sound/pci/aw2/aw2-tsl.c b/sound/pci/aw2/aw2-tsl.c
new file mode 100644 (file)
index 0000000..459b031
--- /dev/null
@@ -0,0 +1,110 @@
+/*****************************************************************************
+ *
+ * Copyright (C) 2008 Cedric Bregardis <cedric.bregardis@free.fr> and
+ * Jean-Christian Hassler <jhassler@free.fr>
+ * Copyright 1998 Emagic Soft- und Hardware GmbH
+ * Copyright 2002 Martijn Sipkema
+ *
+ * This file is part of the Audiowerk2 ALSA driver
+ *
+ * The Audiowerk2 ALSA 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; version 2.
+ *
+ * The Audiowerk2 ALSA 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 the Audiowerk2 ALSA driver; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
+ * USA.
+ *
+ *****************************************************************************/
+
+#define TSL_WS0                (1UL << 31)
+#define        TSL_WS1         (1UL << 30)
+#define        TSL_WS2         (1UL << 29)
+#define TSL_WS3                (1UL << 28)
+#define TSL_WS4                (1UL << 27)
+#define        TSL_DIS_A1      (1UL << 24)
+#define TSL_SDW_A1     (1UL << 23)
+#define TSL_SIB_A1     (1UL << 22)
+#define TSL_SF_A1      (1UL << 21)
+#define        TSL_LF_A1       (1UL << 20)
+#define TSL_BSEL_A1    (1UL << 17)
+#define TSL_DOD_A1     (1UL << 15)
+#define TSL_LOW_A1     (1UL << 14)
+#define TSL_DIS_A2     (1UL << 11)
+#define TSL_SDW_A2     (1UL << 10)
+#define TSL_SIB_A2     (1UL << 9)
+#define TSL_SF_A2      (1UL << 8)
+#define TSL_LF_A2      (1UL << 7)
+#define TSL_BSEL_A2    (1UL << 4)
+#define TSL_DOD_A2     (1UL << 2)
+#define TSL_LOW_A2     (1UL << 1)
+#define TSL_EOS                (1UL << 0)
+
+    /* Audiowerk8 hardware setup: */
+    /*      WS0, SD4, TSL1  - Analog/ digital in */
+    /*      WS1, SD0, TSL1  - Analog out #1, digital out */
+    /*      WS2, SD2, TSL1  - Analog out #2 */
+    /*      WS3, SD1, TSL2  - Analog out #3 */
+    /*      WS4, SD3, TSL2  - Analog out #4 */
+
+    /* Audiowerk8 timing: */
+    /*      Timeslot:     | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | ... */
+
+    /*      A1_INPUT: */
+    /*      SD4:          <_ADC-L_>-------<_ADC-R_>-------< */
+    /*      WS0:          _______________/---------------\_ */
+
+    /*      A1_OUTPUT: */
+    /*      SD0:          <_1-L___>-------<_1-R___>-------< */
+    /*      WS1:          _______________/---------------\_ */
+    /*      SD2:          >-------<_2-L___>-------<_2-R___> */
+    /*      WS2:          -------\_______________/--------- */
+
+    /*      A2_OUTPUT: */
+    /*      SD1:          <_3-L___>-------<_3-R___>-------< */
+    /*      WS3:          _______________/---------------\_ */
+    /*      SD3:          >-------<_4-L___>-------<_4-R___> */
+    /*      WS4:          -------\_______________/--------- */
+
+static int tsl1[8] = {
+       1 * TSL_SDW_A1 | 3 * TSL_BSEL_A1 |
+       0 * TSL_DIS_A1 | 0 * TSL_DOD_A1 | TSL_LF_A1,
+
+       1 * TSL_SDW_A1 | 2 * TSL_BSEL_A1 |
+       0 * TSL_DIS_A1 | 0 * TSL_DOD_A1,
+
+       0 * TSL_SDW_A1 | 3 * TSL_BSEL_A1 |
+       0 * TSL_DIS_A1 | 0 * TSL_DOD_A1,
+
+       0 * TSL_SDW_A1 | 2 * TSL_BSEL_A1 |
+       0 * TSL_DIS_A1 | 0 * TSL_DOD_A1,
+
+       1 * TSL_SDW_A1 | 1 * TSL_BSEL_A1 |
+       0 * TSL_DIS_A1 | 0 * TSL_DOD_A1 | TSL_WS1 | TSL_WS0,
+
+       1 * TSL_SDW_A1 | 0 * TSL_BSEL_A1 |
+       0 * TSL_DIS_A1 | 0 * TSL_DOD_A1 | TSL_WS1 | TSL_WS0,
+
+       0 * TSL_SDW_A1 | 1 * TSL_BSEL_A1 |
+       0 * TSL_DIS_A1 | 0 * TSL_DOD_A1 | TSL_WS1 | TSL_WS0,
+
+       0 * TSL_SDW_A1 | 0 * TSL_BSEL_A1 | 0 * TSL_DIS_A1 |
+       0 * TSL_DOD_A1 | TSL_WS1 | TSL_WS0 | TSL_SF_A1 | TSL_EOS,
+};
+
+static int tsl2[8] = {
+       0 * TSL_SDW_A2 | 3 * TSL_BSEL_A2 | 2 * TSL_DOD_A2 | TSL_LF_A2,
+       0 * TSL_SDW_A2 | 2 * TSL_BSEL_A2 | 2 * TSL_DOD_A2,
+       0 * TSL_SDW_A2 | 3 * TSL_BSEL_A2 | 2 * TSL_DOD_A2,
+       0 * TSL_SDW_A2 | 2 * TSL_BSEL_A2 | 2 * TSL_DOD_A2,
+       0 * TSL_SDW_A2 | 1 * TSL_BSEL_A2 | 2 * TSL_DOD_A2 | TSL_WS2,
+       0 * TSL_SDW_A2 | 0 * TSL_BSEL_A2 | 2 * TSL_DOD_A2 | TSL_WS2,
+       0 * TSL_SDW_A2 | 1 * TSL_BSEL_A2 | 2 * TSL_DOD_A2 | TSL_WS2,
+       0 * TSL_SDW_A2 | 0 * TSL_BSEL_A2 | 2 * TSL_DOD_A2 | TSL_WS2 | TSL_EOS
+};
diff --git a/sound/pci/aw2/saa7146.h b/sound/pci/aw2/saa7146.h
new file mode 100644 (file)
index 0000000..ce0ab5f
--- /dev/null
@@ -0,0 +1,168 @@
+/*****************************************************************************
+ *
+ * Copyright (C) 2008 Cedric Bregardis <cedric.bregardis@free.fr> and
+ * Jean-Christian Hassler <jhassler@free.fr>
+ *
+ * This file is part of the Audiowerk2 ALSA driver
+ *
+ * The Audiowerk2 ALSA 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; version 2.
+ *
+ * The Audiowerk2 ALSA 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 the Audiowerk2 ALSA driver; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
+ * USA.
+ *
+ *****************************************************************************/
+
+/* SAA7146 registers */
+#define PCI_BT_A       0x4C
+#define IICTFR         0x8C
+#define IICSTA         0x90
+#define BaseA1_in      0x94
+#define ProtA1_in      0x98
+#define PageA1_in      0x9C
+#define BaseA1_out     0xA0
+#define ProtA1_out     0xA4
+#define PageA1_out     0xA8
+#define BaseA2_in      0xAC
+#define ProtA2_in      0xB0
+#define PageA2_in      0xB4
+#define BaseA2_out     0xB8
+#define ProtA2_out     0xBC
+#define PageA2_out     0xC0
+#define IER            0xDC
+#define GPIO_CTRL      0xE0
+#define ACON1          0xF4
+#define ACON2          0xF8
+#define MC1            0xFC
+#define MC2            0x100
+#define ISR            0x10C
+#define PSR            0x110
+#define SSR            0x114
+#define PCI_ADP1       0x12C
+#define PCI_ADP2       0x130
+#define PCI_ADP3       0x134
+#define PCI_ADP4       0x138
+#define LEVEL_REP      0x140
+#define FB_BUFFER1     0x144
+#define FB_BUFFER2     0x148
+#define TSL1           0x180
+#define TSL2           0x1C0
+
+#define ME     (1UL << 11)
+#define LIMIT  (1UL << 4)
+#define PV     (1UL << 3)
+
+/* PSR/ISR/IER */
+#define PPEF           (1UL << 31)
+#define PABO           (1UL << 30)
+#define IIC_S          (1UL << 17)
+#define IIC_E          (1UL << 16)
+#define A2_in          (1UL << 15)
+#define A2_out         (1UL << 14)
+#define A1_in          (1UL << 13)
+#define A1_out         (1UL << 12)
+#define AFOU           (1UL << 11)
+#define PIN3           (1UL << 6)
+#define PIN2           (1UL << 5)
+#define PIN1           (1UL << 4)
+#define PIN0           (1UL << 3)
+#define ECS            (1UL << 2)
+#define EC3S           (1UL << 1)
+#define EC0S           (1UL << 0)
+
+/* SSR */
+#define PRQ            (1UL << 31)
+#define PMA            (1UL << 30)
+#define IIC_EA         (1UL << 21)
+#define IIC_EW         (1UL << 20)
+#define IIC_ER         (1UL << 19)
+#define IIC_EL         (1UL << 18)
+#define IIC_EF         (1UL << 17)
+#define AF2_in         (1UL << 10)
+#define AF2_out                (1UL << 9)
+#define AF1_in         (1UL << 8)
+#define AF1_out                (1UL << 7)
+#define EC5S           (1UL << 3)
+#define EC4S           (1UL << 2)
+#define EC2S           (1UL << 1)
+#define EC1S           (1UL << 0)
+
+/* PCI_BT_A */
+#define BurstA1_in     (1UL << 26)
+#define ThreshA1_in    (1UL << 24)
+#define BurstA1_out    (1UL << 18)
+#define ThreshA1_out   (1UL << 16)
+#define BurstA2_in     (1UL << 10)
+#define ThreshA2_in    (1UL << 8)
+#define BurstA2_out    (1UL << 2)
+#define ThreshA2_out   (1UL << 0)
+
+/* MC1 */
+#define MRST_N         (1UL << 15)
+#define EAP            (1UL << 9)
+#define EI2C           (1UL << 8)
+#define TR_E_A2_OUT    (1UL << 3)
+#define TR_E_A2_IN     (1UL << 2)
+#define TR_E_A1_OUT    (1UL << 1)
+#define TR_E_A1_IN     (1UL << 0)
+
+/* MC2 */
+#define UPLD_IIC       (1UL << 0)
+
+/* ACON1 */
+#define AUDIO_MODE     (1UL << 29)
+#define MAXLEVEL       (1UL << 22)
+#define A1_SWAP                (1UL << 21)
+#define A2_SWAP                (1UL << 20)
+#define WS0_CTRL       (1UL << 18)
+#define WS0_SYNC       (1UL << 16)
+#define WS1_CTRL       (1UL << 14)
+#define WS1_SYNC       (1UL << 12)
+#define WS2_CTRL       (1UL << 10)
+#define WS2_SYNC       (1UL << 8)
+#define WS3_CTRL       (1UL << 6)
+#define WS3_SYNC       (1UL << 4)
+#define WS4_CTRL       (1UL << 2)
+#define WS4_SYNC       (1UL << 0)
+
+/* ACON2 */
+#define A1_CLKSRC      (1UL << 27)
+#define A2_CLKSRC      (1UL << 22)
+#define INVERT_BCLK1   (1UL << 21)
+#define INVERT_BCLK2   (1UL << 20)
+#define BCLK1_OEN      (1UL << 19)
+#define BCLK2_OEN      (1UL << 18)
+
+/* IICSTA */
+#define IICCC          (1UL << 8)
+#define ABORT          (1UL << 7)
+#define SPERR          (1UL << 6)
+#define APERR          (1UL << 5)
+#define DTERR          (1UL << 4)
+#define DRERR          (1UL << 3)
+#define AL             (1UL << 2)
+#define ERR            (1UL << 1)
+#define BUSY           (1UL << 0)
+
+/* IICTFR */
+#define BYTE2          (1UL << 24)
+#define BYTE1          (1UL << 16)
+#define BYTE0          (1UL << 8)
+#define ATRR2          (1UL << 6)
+#define ATRR1          (1UL << 4)
+#define ATRR0          (1UL << 2)
+#define ERR            (1UL << 1)
+#define BUSY           (1UL << 0)
+
+#define START  3
+#define CONT   2
+#define STOP   1
+#define NOP    0
index 4e71a55120a05ff014a7504e1c472114ee963314..5f63af6b88a29d35c1c906b6e1e34d88f07780a8 100644 (file)
@@ -157,8 +157,8 @@ MODULE_SUPPORTED_DEVICE("{{Aztech,AZF3328}}");
 
 #if DEBUG_CALLS
 #define snd_azf3328_dbgcalls(format, args...) printk(format, ##args)
-#define snd_azf3328_dbgcallenter() printk(KERN_ERR "--> %s\n", __FUNCTION__)
-#define snd_azf3328_dbgcallleave() printk(KERN_ERR "<-- %s\n", __FUNCTION__)
+#define snd_azf3328_dbgcallenter() printk(KERN_ERR "--> %s\n", __func__)
+#define snd_azf3328_dbgcallleave() printk(KERN_ERR "<-- %s\n", __func__)
 #else
 #define snd_azf3328_dbgcalls(format, args...)
 #define snd_azf3328_dbgcallenter()
@@ -1514,7 +1514,8 @@ snd_azf3328_free(struct snd_azf3328 *chip)
        /* well, at least we know how to disable the timer IRQ */
        snd_azf3328_codec_outb(chip, IDX_IO_TIMER_VALUE + 3, 0x00);
 
-        synchronize_irq(chip->irq);
+       if (chip->irq >= 0)
+               synchronize_irq(chip->irq);
 __end_hw:
        snd_azf3328_free_joystick(chip);
         if (chip->irq >= 0)
index 176e0f0e80585739e37789b1e54e47df68a97e42..ecbe79b67e437c0d94018e67e1a15f12984a2dbd 100644 (file)
@@ -435,22 +435,22 @@ int snd_ca0106_i2c_write(struct snd_ca0106 *emu,
 static void snd_ca0106_intr_enable(struct snd_ca0106 *emu, unsigned int intrenb)
 {
        unsigned long flags;
-       unsigned int enable;
-  
+       unsigned int intr_enable;
+
        spin_lock_irqsave(&emu->emu_lock, flags);
-       enable = inl(emu->port + INTE) | intrenb;
-       outl(enable, emu->port + INTE);
+       intr_enable = inl(emu->port + INTE) | intrenb;
+       outl(intr_enable, emu->port + INTE);
        spin_unlock_irqrestore(&emu->emu_lock, flags);
 }
 
 static void snd_ca0106_intr_disable(struct snd_ca0106 *emu, unsigned int intrenb)
 {
        unsigned long flags;
-       unsigned int enable;
-  
+       unsigned int intr_enable;
+
        spin_lock_irqsave(&emu->emu_lock, flags);
-       enable = inl(emu->port + INTE) & ~intrenb;
-       outl(enable, emu->port + INTE);
+       intr_enable = inl(emu->port + INTE) & ~intrenb;
+       outl(intr_enable, emu->port + INTE);
        spin_unlock_irqrestore(&emu->emu_lock, flags);
 }
 
@@ -1114,6 +1114,8 @@ static int snd_ca0106_free(struct snd_ca0106 *chip)
                 * So we can fix: snd-malloc: Memory leak?  pages not freed = 8
                 */
        }
+       if (chip->irq >= 0)
+               free_irq(chip->irq, chip);
        // release the data
 #if 1
        if (chip->buffer.area)
@@ -1123,9 +1125,6 @@ static int snd_ca0106_free(struct snd_ca0106 *chip)
        // release the i/o port
        release_and_free_resource(chip->res_port);
 
-       // release the irq
-       if (chip->irq >= 0)
-               free_irq(chip->irq, chip);
        pci_disable_device(chip->pci);
        kfree(chip);
        return 0;
index af736869d9b1959e0802c4e105476c898d901526..3025ed1b6e1efd1444ccf5d3403d4ca7ab36627c 100644 (file)
@@ -650,19 +650,55 @@ static int __devinit rename_ctl(struct snd_card *card, const char *src, const ch
 
 #define ADD_CTLS(emu, ctls)                                            \
        do {                                                            \
-               int i, err;                                             \
+               int i, _err;                                            \
                for (i = 0; i < ARRAY_SIZE(ctls); i++) {                \
-                       err = snd_ctl_add(card, snd_ctl_new1(&ctls[i], emu)); \
-                       if (err < 0)                                    \
-                               return err;                             \
+                       _err = snd_ctl_add(card, snd_ctl_new1(&ctls[i], emu)); \
+                       if (_err < 0)                                   \
+                               return _err;                            \
                }                                                       \
        } while (0)
 
+static __devinitdata
+DECLARE_TLV_DB_SCALE(snd_ca0106_master_db_scale, -6375, 50, 1);
+
+static char *slave_vols[] __devinitdata = {
+       "Analog Front Playback Volume",
+        "Analog Rear Playback Volume",
+       "Analog Center/LFE Playback Volume",
+        "Analog Side Playback Volume",
+        "IEC958 Front Playback Volume",
+       "IEC958 Rear Playback Volume",
+       "IEC958 Center/LFE Playback Volume",
+       "IEC958 Unknown Playback Volume",
+        "CAPTURE feedback Playback Volume",
+       NULL
+};
+
+static char *slave_sws[] __devinitdata = {
+       "Analog Front Playback Switch",
+       "Analog Rear Playback Switch",
+       "Analog Center/LFE Playback Switch",
+       "Analog Side Playback Switch",
+       "IEC958 Playback Switch",
+       NULL
+};
+
+static void __devinit add_slaves(struct snd_card *card,
+                                struct snd_kcontrol *master, char **list)
+{
+       for (; *list; list++) {
+               struct snd_kcontrol *slave = ctl_find(card, *list);
+               if (slave)
+                       snd_ctl_add_slave(master, slave);
+       }
+}
+
 int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu)
 {
        int err;
         struct snd_card *card = emu->card;
        char **c;
+       struct snd_kcontrol *vmaster;
        static char *ca0106_remove_ctls[] = {
                "Master Mono Playback Switch",
                "Master Mono Playback Volume",
@@ -719,6 +755,21 @@ int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu)
        }
        if (emu->details->spi_dac == 1)
                ADD_CTLS(emu, snd_ca0106_volume_spi_dac_ctls);
+
+       /* Create virtual master controls */
+       vmaster = snd_ctl_make_virtual_master("Master Playback Volume",
+                                             snd_ca0106_master_db_scale);
+       if (!vmaster)
+               return -ENOMEM;
+       add_slaves(card, vmaster, slave_vols);
+
+       if (emu->details->spi_dac == 1) {
+               vmaster = snd_ctl_make_virtual_master("Master Playback Switch",
+                                                     NULL);
+               if (!vmaster)
+                       return -ENOMEM;
+               add_slaves(card, vmaster, slave_sws);
+       }
         return 0;
 }
 
index 135f308607535594b95c5afd74964a378ab079db..9971b5b7735b5620599fb83df460b973355cbb89 100644 (file)
@@ -2744,12 +2744,13 @@ static int __devinit snd_cmipci_mixer_new(struct cmipci *cm, int pcm_spdif_devic
        }
 
        for (idx = 0; idx < CM_SAVED_MIXERS; idx++) {
-               struct snd_ctl_elem_id id;
+               struct snd_ctl_elem_id elem_id;
                struct snd_kcontrol *ctl;
-               memset(&id, 0, sizeof(id));
-               id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
-               strcpy(id.name, cm_saved_mixer[idx].name);
-               if ((ctl = snd_ctl_find_id(cm->card, &id)) != NULL)
+               memset(&elem_id, 0, sizeof(elem_id));
+               elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+               strcpy(elem_id.name, cm_saved_mixer[idx].name);
+               ctl = snd_ctl_find_id(cm->card, &elem_id);
+               if (ctl)
                        cm->mixer_res_ctl[idx] = ctl;
        }
 
@@ -2932,8 +2933,6 @@ static int snd_cmipci_free(struct cmipci *cm)
                /* reset mixer */
                snd_cmipci_mixer_write(cm, 0, 0);
 
-               synchronize_irq(cm->irq);
-
                free_irq(cm->irq, cm);
        }
 
index 87ddffcd9d89d7a6dafee80f9a0e03e6a1983f9c..e214e567dec894074568b48205d5a6c139ac6224 100644 (file)
@@ -2772,6 +2772,9 @@ static int snd_cs46xx_free(struct snd_cs46xx *chip)
        if (chip->irq >= 0)
                free_irq(chip->irq, chip);
 
+       if (chip->active_ctrl)
+               chip->active_ctrl(chip, -chip->amplifier);
+
        for (idx = 0; idx < 5; idx++) {
                struct snd_cs46xx_region *region = &chip->region.idx[idx];
                if (region->remap_addr)
@@ -2779,9 +2782,6 @@ static int snd_cs46xx_free(struct snd_cs46xx *chip)
                release_and_free_resource(region->resource);
        }
 
-       if (chip->active_ctrl)
-               chip->active_ctrl(chip, -chip->amplifier);
-       
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
        if (chip->dsp_spos_instance) {
                cs46xx_dsp_spos_destroy(chip);
index 90ec090792ba12c4c22eecb4378744dd14549868..e16dc92e82fb4359e5ae92b11300fce4dd9e9c9c 100644 (file)
@@ -1852,15 +1852,16 @@ static irqreturn_t snd_echo_interrupt(int irq, void *dev_id)
 static int snd_echo_free(struct echoaudio *chip)
 {
        DE_INIT(("Stop DSP...\n"));
-       if (chip->comm_page) {
+       if (chip->comm_page)
                rest_in_peace(chip);
-               snd_dma_free_pages(&chip->commpage_dma_buf);
-       }
        DE_INIT(("Stopped.\n"));
 
        if (chip->irq >= 0)
                free_irq(chip->irq, chip);
 
+       if (chip->comm_page)
+               snd_dma_free_pages(&chip->commpage_dma_buf);
+
        if (chip->dsp_registers)
                iounmap(chip->dsp_registers);
 
index 9a9b977d3cf1c00173a76128a29be00dc51e683a..abde5b9018842923c88c6f41eca4c456f0d4768b 100644 (file)
@@ -1249,11 +1249,6 @@ 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_done(emu);
-               /* remove reserved page */
-               if (emu->reserved_page) {
-                       snd_emu10k1_synth_free(emu, (struct snd_util_memblk *)emu->reserved_page);
-                       emu->reserved_page = NULL;
-               }
                snd_emu10k1_free_efx(emu);
                }
        if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1010) {
@@ -1262,6 +1257,14 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu)
        }
        if (emu->emu1010.firmware_thread)
                kthread_stop(emu->emu1010.firmware_thread);
+       if (emu->irq >= 0)
+               free_irq(emu->irq, emu);
+       /* remove reserved page */
+       if (emu->reserved_page) {
+               snd_emu10k1_synth_free(emu,
+                       (struct snd_util_memblk *)emu->reserved_page);
+               emu->reserved_page = NULL;
+       }
        if (emu->memhdr)
                snd_util_memhdr_free(emu->memhdr);
        if (emu->silent_page.area)
@@ -1273,8 +1276,6 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu)
 #ifdef CONFIG_PM
        free_pm_buffer(emu);
 #endif
-       if (emu->irq >= 0)
-               free_irq(emu->irq, emu);
        if (emu->port)
                pci_release_regions(emu->pci);
        if (emu->card_capabilities->ca0151_chip) /* P16V */     
index 5512abd98bd93f3f69370f792e592145b3c3b92e..491a4a50f869c3dca9887bb9347ca6af64eb5d9b 100644 (file)
@@ -327,22 +327,22 @@ static void snd_emu10k1x_ptr_write(struct emu10k1x *emu,
 static void snd_emu10k1x_intr_enable(struct emu10k1x *emu, unsigned int intrenb)
 {
        unsigned long flags;
-       unsigned int enable;
-  
+       unsigned int intr_enable;
+
        spin_lock_irqsave(&emu->emu_lock, flags);
-       enable = inl(emu->port + INTE) | intrenb;
-       outl(enable, emu->port + INTE);
+       intr_enable = inl(emu->port + INTE) | intrenb;
+       outl(intr_enable, emu->port + INTE);
        spin_unlock_irqrestore(&emu->emu_lock, flags);
 }
 
 static void snd_emu10k1x_intr_disable(struct emu10k1x *emu, unsigned int intrenb)
 {
        unsigned long flags;
-       unsigned int enable;
-  
+       unsigned int intr_enable;
+
        spin_lock_irqsave(&emu->emu_lock, flags);
-       enable = inl(emu->port + INTE) & ~intrenb;
-       outl(enable, emu->port + INTE);
+       intr_enable = inl(emu->port + INTE) & ~intrenb;
+       outl(intr_enable, emu->port + INTE);
        spin_unlock_irqrestore(&emu->emu_lock, flags);
 }
 
@@ -754,13 +754,13 @@ static int snd_emu10k1x_free(struct emu10k1x *chip)
        // disable audio
        outl(HCFG_LOCKSOUNDCACHE, chip->port + HCFG);
 
-       // release the i/o port
-       release_and_free_resource(chip->res_port);
-
-       // release the irq
+       /* release the irq */
        if (chip->irq >= 0)
                free_irq(chip->irq, chip);
 
+       // release the i/o port
+       release_and_free_resource(chip->res_port);
+
        // release the DMA
        if (chip->dma_buffer.area) {
                snd_dma_free_pages(&chip->dma_buffer);
@@ -795,9 +795,9 @@ static irqreturn_t snd_emu10k1x_interrupt(int irq, void *dev_id)
 
        // capture interrupt
        if (status & (IPR_CAP_0_LOOP | IPR_CAP_0_HALF_LOOP)) {
-               struct emu10k1x_voice *pvoice = &chip->capture_voice;
-               if (pvoice->use)
-                       snd_emu10k1x_pcm_interrupt(chip, pvoice);
+               struct emu10k1x_voice *cap_voice = &chip->capture_voice;
+               if (cap_voice->use)
+                       snd_emu10k1x_pcm_interrupt(chip, cap_voice);
                else
                        snd_emu10k1x_intr_disable(chip, 
                                                  INTE_CAP_0_LOOP |
index f3caa3f890c6cdd5fc3b237afa4c5c75269af1d5..216f9748aff5b00e70ee943a1e4c55e368b76d6d 100644 (file)
@@ -412,7 +412,7 @@ static void snd_emu_proc_emu1010_reg_read(struct snd_info_entry *entry,
                                     struct snd_info_buffer *buffer)
 {
        struct snd_emu10k1 *emu = entry->private_data;
-       int value;
+       u32 value;
        unsigned long flags;
        int i;
        snd_iprintf(buffer, "EMU1010 Registers:\n\n");
index 72d85a5ae6a090f53b7a8b9983306d710be65d9d..fbf1124f7c79d1609f594fdb786e0ec0e0b676ac 100644 (file)
@@ -1635,20 +1635,20 @@ static int __devinit snd_ensoniq_1371_mixer(struct ensoniq *ensoniq,
        if (has_spdif > 0 ||
            (!has_spdif && es1371_quirk_lookup(ensoniq, es1371_spdif_present))) {
                struct snd_kcontrol *kctl;
-               int i, index = 0;
+               int i, is_spdif = 0;
 
                ensoniq->spdif_default = ensoniq->spdif_stream =
                        SNDRV_PCM_DEFAULT_CON_SPDIF;
                outl(ensoniq->spdif_default, ES_REG(ensoniq, CHANNEL_STATUS));
 
                if (ensoniq->u.es1371.ac97->ext_id & AC97_EI_SPDIF)
-                       index++;
+                       is_spdif++;
 
                for (i = 0; i < ARRAY_SIZE(snd_es1371_mixer_spdif); i++) {
                        kctl = snd_ctl_new1(&snd_es1371_mixer_spdif[i], ensoniq);
                        if (!kctl)
                                return -ENOMEM;
-                       kctl->id.index = index;
+                       kctl->id.index = is_spdif;
                        err = snd_ctl_add(card, kctl);
                        if (err < 0)
                                return err;
@@ -1910,7 +1910,8 @@ static int snd_ensoniq_free(struct ensoniq *ensoniq)
        outl(0, ES_REG(ensoniq, CONTROL));      /* switch everything off */
        outl(0, ES_REG(ensoniq, SERIAL));       /* clear serial interface */
 #endif
-       synchronize_irq(ensoniq->irq);
+       if (ensoniq->irq >= 0)
+               synchronize_irq(ensoniq->irq);
        pci_set_power_state(ensoniq->pci, 3);
       __hw_end:
 #ifdef CHIP1370
index 1a314fa99c45889148c07b3d95609496b2e19c76..84fac1fbf10399bf9a3c0008945e78e9ad8c1d0f 100644 (file)
@@ -1488,7 +1488,6 @@ static int es1938_suspend(struct pci_dev *pci, pm_message_t state)
 
        outb(0x00, SLIO_REG(chip, IRQCONTROL)); /* disable irqs */
        if (chip->irq >= 0) {
-               synchronize_irq(chip->irq);
                free_irq(chip->irq, chip);
                chip->irq = -1;
        }
@@ -1578,10 +1577,8 @@ static int snd_es1938_free(struct es1938 *chip)
 
        snd_es1938_free_gameport(chip);
 
-       if (chip->irq >= 0) {
-               synchronize_irq(chip->irq);
+       if (chip->irq >= 0)
                free_irq(chip->irq, chip);
-       }
        pci_release_regions(chip->pci);
        pci_disable_device(chip->pci);
        kfree(chip);
index 7d911a18c082ffbbbfab7293693ec070ca5db224..1bf298d214b90462cfe7b5253c7d4d0f6c097fd1 100644 (file)
@@ -1827,6 +1827,22 @@ snd_es1968_pcm(struct es1968 *chip, int device)
 
        return 0;
 }
+/*
+ * suppress jitter on some maestros when playing stereo
+ */
+static void snd_es1968_suppress_jitter(struct es1968 *chip, struct esschan *es)
+{
+       unsigned int cp1;
+       unsigned int cp2;
+       unsigned int diff;
+
+       cp1 = __apu_get_register(chip, 0, 5);
+       cp2 = __apu_get_register(chip, 1, 5);
+       diff = (cp1 > cp2 ? cp1 - cp2 : cp2 - cp1);
+
+       if (diff > 1)
+               __maestro_write(chip, IDR0_DATA_PORT, cp1);
+}
 
 /*
  * update pointer
@@ -1948,8 +1964,11 @@ static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id)
                struct esschan *es;
                spin_lock(&chip->substream_lock);
                list_for_each_entry(es, &chip->substream_list, list) {
-                       if (es->running)
+                       if (es->running) {
                                snd_es1968_update_pcm(chip, es);
+                               if (es->fmt & ESS_FMT_STEREO)
+                                       snd_es1968_suppress_jitter(chip, es);
+                       }
                }
                spin_unlock(&chip->substream_lock);
                if (chip->in_measurement) {
@@ -1972,7 +1991,7 @@ snd_es1968_mixer(struct es1968 *chip)
 {
        struct snd_ac97_bus *pbus;
        struct snd_ac97_template ac97;
-       struct snd_ctl_elem_id id;
+       struct snd_ctl_elem_id elem_id;
        int err;
        static struct snd_ac97_bus_ops ops = {
                .write = snd_es1968_ac97_write,
@@ -1989,14 +2008,14 @@ snd_es1968_mixer(struct es1968 *chip)
                return err;
 
        /* attach master switch / volumes for h/w volume control */
-       memset(&id, 0, sizeof(id));
-       id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
-       strcpy(id.name, "Master Playback Switch");
-       chip->master_switch = snd_ctl_find_id(chip->card, &id);
-       memset(&id, 0, sizeof(id));
-       id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
-       strcpy(id.name, "Master Playback Volume");
-       chip->master_volume = snd_ctl_find_id(chip->card, &id);
+       memset(&elem_id, 0, sizeof(elem_id));
+       elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+       strcpy(elem_id.name, "Master Playback Switch");
+       chip->master_switch = snd_ctl_find_id(chip->card, &elem_id);
+       memset(&elem_id, 0, sizeof(elem_id));
+       elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+       strcpy(elem_id.name, "Master Playback Volume");
+       chip->master_volume = snd_ctl_find_id(chip->card, &elem_id);
 
        return 0;
 }
@@ -2456,7 +2475,8 @@ static inline void snd_es1968_free_gameport(struct es1968 *chip) { }
 static int snd_es1968_free(struct es1968 *chip)
 {
        if (chip->io_port) {
-               synchronize_irq(chip->irq);
+               if (chip->irq >= 0)
+                       synchronize_irq(chip->irq);
                outw(1, chip->io_port + 0x04); /* clear WP interrupts */
                outw(0, chip->io_port + ESM_PORT_HOST_IRQ); /* disable IRQ */
        }
index 4c300e6149fca554891ae85eb2685caf36d0b23b..c129f9e2072cb6970a1d5e83ad7b7f3950a4160b 100644 (file)
@@ -1285,7 +1285,6 @@ static int wait_for_codec(struct fm801 *chip, unsigned int codec_id,
 
 static int snd_fm801_chip_init(struct fm801 *chip, int resume)
 {
-       int id;
        unsigned short cmdw;
 
        if (chip->tea575x_tuner & 0x0010)
@@ -1310,13 +1309,14 @@ static int snd_fm801_chip_init(struct fm801 *chip, int resume)
                } else {
                        /* my card has the secondary codec */
                        /* at address #3, so the loop is inverted */
-                       for (id = 3; id > 0; id--) {
-                               if (! wait_for_codec(chip, id, AC97_VENDOR_ID1,
+                       int i;
+                       for (i = 3; i > 0; i--) {
+                               if (!wait_for_codec(chip, i, AC97_VENDOR_ID1,
                                                     msecs_to_jiffies(50))) {
                                        cmdw = inw(FM801_REG(chip, AC97_DATA));
                                        if (cmdw != 0xffff && cmdw != 0) {
                                                chip->secondary = 1;
-                                               chip->secondary_addr = id;
+                                               chip->secondary_addr = i;
                                                break;
                                        }
                                }
index 9e0d8a1268aa4400cca30e5c881576ccb0ca28d9..ab0c726d648e77e2ea4477b285407bce37b8a7d3 100644 (file)
@@ -2,7 +2,7 @@ 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 vmaster.o
+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_GENERIC) += hda_generic.o
index 37c413923db8a4762da4e7af66989af1e5e3d1a4..a6be6e3e8716026b8a8e129f5e7bc9d9ec31b37f 100644 (file)
@@ -31,6 +31,7 @@
 #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 */
@@ -51,21 +52,50 @@ struct hda_vendor_id {
 
 /* codec vendor labels */
 static struct hda_vendor_id hda_vendor_ids[] = {
-       { 0x10ec, "Realtek" },
+       { 0x1002, "ATI" },
        { 0x1057, "Motorola" },
+       { 0x1095, "Silicon Image" },
+       { 0x10ec, "Realtek" },
        { 0x1106, "VIA" },
        { 0x111d, "IDT" },
+       { 0x11c1, "LSI" },
        { 0x11d4, "Analog Devices" },
        { 0x13f6, "C-Media" },
        { 0x14f1, "Conexant" },
+       { 0x17e8, "Chrontel" },
+       { 0x1854, "LG" },
        { 0x434d, "C-Media" },
        { 0x8384, "SigmaTel" },
        {} /* terminator */
 };
 
-/* codec presets */
-#include "hda_patch.h"
-
+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
+       NULL
+};
 
 #ifdef CONFIG_SND_HDA_POWER_SAVE
 static void hda_power_work(struct work_struct *work);
@@ -690,6 +720,19 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
        snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, format);
 }
 
+void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid)
+{
+       if (!nid)
+               return;
+
+       snd_printdd("hda_codec_cleanup_stream: NID=0x%x\n", nid);
+       snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0);
+#if 0 /* keep the format */
+       msleep(1);
+       snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0);
+#endif
+}
+
 /*
  * amp access functions
  */
@@ -1037,16 +1080,24 @@ void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,
 }
 
 /* find a mixer control element with the given name */
-struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
-                                           const char *name)
+static struct snd_kcontrol *
+_snd_hda_find_mixer_ctl(struct hda_codec *codec,
+                       const char *name, int idx)
 {
        struct snd_ctl_elem_id id;
        memset(&id, 0, sizeof(id));
        id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+       id.index = idx;
        strcpy(id.name, name);
        return snd_ctl_find_id(codec->bus->card, &id);
 }
 
+struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
+                                           const char *name)
+{
+       return _snd_hda_find_mixer_ctl(codec, name, 0);
+}
+
 /* create a virtual master control and add slaves */
 int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
                        unsigned int *tlv, const char **slaves)
@@ -1481,6 +1532,8 @@ static struct snd_kcontrol_new dig_mixes[] = {
        { } /* end */
 };
 
+#define SPDIF_MAX_IDX  4       /* 4 instances should be enough to probe */
+
 /**
  * snd_hda_create_spdif_out_ctls - create Output SPDIF-related controls
  * @codec: the HDA codec
@@ -1496,9 +1549,20 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
        int err;
        struct snd_kcontrol *kctl;
        struct snd_kcontrol_new *dig_mix;
+       int idx;
 
+       for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
+               if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Playback Switch",
+                                            idx))
+                       break;
+       }
+       if (idx >= SPDIF_MAX_IDX) {
+               printk(KERN_ERR "hda_codec: too many IEC958 outputs\n");
+               return -EBUSY;
+       }
        for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) {
                kctl = snd_ctl_new1(dig_mix, codec);
+               kctl->id.index = idx;
                kctl->private_value = nid;
                err = snd_ctl_add(codec->bus->card, kctl);
                if (err < 0)
@@ -1511,6 +1575,43 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
        return 0;
 }
 
+/*
+ * SPDIF sharing with analog output
+ */
+static int spdif_share_sw_get(struct snd_kcontrol *kcontrol,
+                             struct snd_ctl_elem_value *ucontrol)
+{
+       struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
+       ucontrol->value.integer.value[0] = mout->share_spdif;
+       return 0;
+}
+
+static int spdif_share_sw_put(struct snd_kcontrol *kcontrol,
+                             struct snd_ctl_elem_value *ucontrol)
+{
+       struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
+       mout->share_spdif = !!ucontrol->value.integer.value[0];
+       return 0;
+}
+
+static struct snd_kcontrol_new spdif_share_sw = {
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name = "IEC958 Default PCM Playback Switch",
+       .info = snd_ctl_boolean_mono_info,
+       .get = spdif_share_sw_get,
+       .put = spdif_share_sw_put,
+};
+
+int snd_hda_create_spdif_share_sw(struct hda_codec *codec,
+                                 struct hda_multi_out *mout)
+{
+       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,
+                          snd_ctl_new1(&spdif_share_sw, mout));
+}
+
 /*
  * SPDIF input
  */
@@ -1595,7 +1696,17 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
        int err;
        struct snd_kcontrol *kctl;
        struct snd_kcontrol_new *dig_mix;
+       int idx;
 
+       for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
+               if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Capture Switch",
+                                            idx))
+                       break;
+       }
+       if (idx >= SPDIF_MAX_IDX) {
+               printk(KERN_ERR "hda_codec: too many IEC958 inputs\n");
+               return -EBUSY;
+       }
        for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) {
                kctl = snd_ctl_new1(dig_mix, codec);
                kctl->private_value = nid;
@@ -2106,7 +2217,7 @@ static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo,
                                   struct hda_codec *codec,
                                   struct snd_pcm_substream *substream)
 {
-       snd_hda_codec_setup_stream(codec, hinfo->nid, 0, 0, 0);
+       snd_hda_codec_cleanup_stream(codec, hinfo->nid);
        return 0;
 }
 
@@ -2491,7 +2602,7 @@ int snd_hda_multi_out_dig_open(struct hda_codec *codec,
        mutex_lock(&codec->spdif_mutex);
        if (mout->dig_out_used == HDA_DIG_ANALOG_DUP)
                /* already opened as analog dup; reset it once */
-               snd_hda_codec_setup_stream(codec, mout->dig_out_nid, 0, 0, 0);
+               snd_hda_codec_cleanup_stream(codec, mout->dig_out_nid);
        mout->dig_out_used = HDA_DIG_EXCLUSIVE;
        mutex_unlock(&codec->spdif_mutex);
        return 0;
@@ -2526,9 +2637,36 @@ int snd_hda_multi_out_dig_close(struct hda_codec *codec,
  */
 int snd_hda_multi_out_analog_open(struct hda_codec *codec,
                                  struct hda_multi_out *mout,
-                                 struct snd_pcm_substream *substream)
-{
-       substream->runtime->hw.channels_max = mout->max_channels;
+                                 struct snd_pcm_substream *substream,
+                                 struct hda_pcm_stream *hinfo)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       runtime->hw.channels_max = mout->max_channels;
+       if (mout->dig_out_nid) {
+               if (!mout->analog_rates) {
+                       mout->analog_rates = hinfo->rates;
+                       mout->analog_formats = hinfo->formats;
+                       mout->analog_maxbps = hinfo->maxbps;
+               } else {
+                       runtime->hw.rates = mout->analog_rates;
+                       runtime->hw.formats = mout->analog_formats;
+                       hinfo->maxbps = mout->analog_maxbps;
+               }
+               if (!mout->spdif_rates) {
+                       snd_hda_query_supported_pcm(codec, mout->dig_out_nid,
+                                                   &mout->spdif_rates,
+                                                   &mout->spdif_formats,
+                                                   &mout->spdif_maxbps);
+               }
+               mutex_lock(&codec->spdif_mutex);
+               if (mout->share_spdif) {
+                       runtime->hw.rates &= mout->spdif_rates;
+                       runtime->hw.formats &= mout->spdif_formats;
+                       if (mout->spdif_maxbps < hinfo->maxbps)
+                               hinfo->maxbps = mout->spdif_maxbps;
+               }
+               mutex_unlock(&codec->spdif_mutex);
+       }
        return snd_pcm_hw_constraint_step(substream->runtime, 0,
                                          SNDRV_PCM_HW_PARAM_CHANNELS, 2);
 }
@@ -2548,7 +2686,8 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
        int i;
 
        mutex_lock(&codec->spdif_mutex);
-       if (mout->dig_out_nid && mout->dig_out_used != HDA_DIG_EXCLUSIVE) {
+       if (mout->dig_out_nid && mout->share_spdif &&
+           mout->dig_out_used != HDA_DIG_EXCLUSIVE) {
                if (chs == 2 &&
                    snd_hda_is_supported_format(codec, mout->dig_out_nid,
                                                format) &&
@@ -2558,8 +2697,7 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
                                             stream_tag, format);
                } else {
                        mout->dig_out_used = 0;
-                       snd_hda_codec_setup_stream(codec, mout->dig_out_nid,
-                                                  0, 0, 0);
+                       snd_hda_codec_cleanup_stream(codec, mout->dig_out_nid);
                }
        }
        mutex_unlock(&codec->spdif_mutex);
@@ -2601,17 +2739,16 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
        int i;
 
        for (i = 0; i < mout->num_dacs; i++)
-               snd_hda_codec_setup_stream(codec, nids[i], 0, 0, 0);
+               snd_hda_codec_cleanup_stream(codec, nids[i]);
        if (mout->hp_nid)
-               snd_hda_codec_setup_stream(codec, mout->hp_nid, 0, 0, 0);
+               snd_hda_codec_cleanup_stream(codec, mout->hp_nid);
        for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
                if (mout->extra_out_nid[i])
-                       snd_hda_codec_setup_stream(codec,
-                                                  mout->extra_out_nid[i],
-                                                  0, 0, 0);
+                       snd_hda_codec_cleanup_stream(codec,
+                                                    mout->extra_out_nid[i]);
        mutex_lock(&codec->spdif_mutex);
        if (mout->dig_out_nid && mout->dig_out_used == HDA_DIG_ANALOG_DUP) {
-               snd_hda_codec_setup_stream(codec, mout->dig_out_nid, 0, 0, 0);
+               snd_hda_codec_cleanup_stream(codec, mout->dig_out_nid);
                mout->dig_out_used = 0;
        }
        mutex_unlock(&codec->spdif_mutex);
@@ -2790,6 +2927,30 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
                }
        }
 
+       /* FIX-UP:
+        * If no line-out is defined but multiple HPs are found,
+        * some of them might be the real line-outs.
+        */
+       if (!cfg->line_outs && cfg->hp_outs > 1) {
+               int i = 0;
+               while (i < cfg->hp_outs) {
+                       /* The real HPs should have the sequence 0x0f */
+                       if ((sequences_hp[i] & 0x0f) == 0x0f) {
+                               i++;
+                               continue;
+                       }
+                       /* Move it to the line-out table */
+                       cfg->line_out_pins[cfg->line_outs] = cfg->hp_pins[i];
+                       sequences_line_out[cfg->line_outs] = sequences_hp[i];
+                       cfg->line_outs++;
+                       cfg->hp_outs--;
+                       memmove(cfg->hp_pins + i, cfg->hp_pins + i + 1,
+                               sizeof(cfg->hp_pins[0]) * (cfg->hp_outs - i));
+                       memmove(sequences_hp + i - 1, sequences_hp + i,
+                               sizeof(sequences_hp[0]) * (cfg->hp_outs - i));
+               }
+       }
+
        /* sort by sequence */
        sort_pins_by_sequence(cfg->line_out_pins, sequences_line_out,
                              cfg->line_outs);
index f14871151be983a307330ec9c61009895a22f944..dcd390b2bbaad8b031c8a7fc49ca5aa91f0b6356 100644 (file)
@@ -590,11 +590,21 @@ struct hda_pcm_stream {
        struct hda_pcm_ops ops;
 };
 
+/* PCM types */
+enum {
+       HDA_PCM_TYPE_AUDIO,
+       HDA_PCM_TYPE_SPDIF,
+       HDA_PCM_TYPE_HDMI,
+       HDA_PCM_TYPE_MODEM,
+       HDA_PCM_NTYPES
+};
+
 /* for PCM creation */
 struct hda_pcm {
        char *name;
        struct hda_pcm_stream stream[2];
-       unsigned int is_modem;  /* modem codec? */
+       unsigned int pcm_type;  /* HDA_PCM_TYPE_XXX */
+       int device;     /* assigned device number */
 };
 
 /* codec information */
@@ -712,6 +722,7 @@ int snd_hda_build_pcms(struct hda_bus *bus);
 void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
                                u32 stream_tag,
                                int channel_id, int format);
+void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid);
 unsigned int snd_hda_calc_stream_format(unsigned int rate,
                                        unsigned int channels,
                                        unsigned int format,
index f9de7c467c2552ad56b73568fa07caae203f7e85..59e4389c94a4bb87b1aa85075d2d127e5ae542da 100644 (file)
@@ -1007,8 +1007,8 @@ static int generic_pcm2_cleanup(struct hda_pcm_stream *hinfo,
 {
        struct hda_gspec *spec = codec->spec;
 
-       snd_hda_codec_setup_stream(codec, hinfo->nid, 0, 0, 0);
-       snd_hda_codec_setup_stream(codec, spec->dac_node[1]->nid, 0, 0, 0);
+       snd_hda_codec_cleanup_stream(codec, hinfo->nid);
+       snd_hda_codec_cleanup_stream(codec, spec->dac_node[1]->nid);
        return 0;
 }
 
index 4be36c84b36c7c8354a707d9956430602de45e73..b3a618eb42cdf5b4a45bc861312b974b7ce00581 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/dma-mapping.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -185,35 +186,28 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
 
 /* max number of SDs */
 /* ICH, ATI and VIA have 4 playback and 4 capture */
-#define ICH6_CAPTURE_INDEX     0
 #define ICH6_NUM_CAPTURE       4
-#define ICH6_PLAYBACK_INDEX    4
 #define ICH6_NUM_PLAYBACK      4
 
 /* ULI has 6 playback and 5 capture */
-#define ULI_CAPTURE_INDEX      0
 #define ULI_NUM_CAPTURE                5
-#define ULI_PLAYBACK_INDEX     5
 #define ULI_NUM_PLAYBACK       6
 
 /* ATI HDMI has 1 playback and 0 capture */
-#define ATIHDMI_CAPTURE_INDEX  0
 #define ATIHDMI_NUM_CAPTURE    0
-#define ATIHDMI_PLAYBACK_INDEX 0
 #define ATIHDMI_NUM_PLAYBACK   1
 
 /* this number is statically defined for simplicity */
 #define MAX_AZX_DEV            16
 
 /* max number of fragments - we may use more if allocating more pages for BDL */
-#define BDL_SIZE               PAGE_ALIGN(8192)
-#define AZX_MAX_FRAG           (BDL_SIZE / (MAX_AZX_DEV * 16))
+#define BDL_SIZE               4096
+#define AZX_MAX_BDL_ENTRIES    (BDL_SIZE / 16)
+#define AZX_MAX_FRAG           32
 /* max buffer size - no h/w limit, you can increase as you like */
 #define AZX_MAX_BUF_SIZE       (1024*1024*1024)
 /* max number of PCM devics per card */
-#define AZX_MAX_AUDIO_PCMS     6
-#define AZX_MAX_MODEM_PCMS     2
-#define AZX_MAX_PCMS           (AZX_MAX_AUDIO_PCMS + AZX_MAX_MODEM_PCMS)
+#define AZX_MAX_PCMS           8
 
 /* RIRB int mask: overrun[2], response[0] */
 #define RIRB_INT_RESPONSE      0x01
@@ -227,6 +221,9 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
 /* SD_CTL bits */
 #define SD_CTL_STREAM_RESET    0x01    /* stream reset bit */
 #define SD_CTL_DMA_START       0x02    /* stream DMA start bit */
+#define SD_CTL_STRIPE          (3 << 16)       /* stripe control */
+#define SD_CTL_TRAFFIC_PRIO    (1 << 18)       /* traffic priority */
+#define SD_CTL_DIR             (1 << 19)       /* bi-directional stream */
 #define SD_CTL_STREAM_TAG_MASK (0xf << 20)
 #define SD_CTL_STREAM_TAG_SHIFT        20
 
@@ -284,12 +281,10 @@ enum {
  */
 
 struct azx_dev {
-       u32 *bdl;               /* virtual address of the BDL */
-       dma_addr_t bdl_addr;    /* physical address of the BDL */
+       struct snd_dma_buffer bdl; /* BDL buffer */
        u32 *posbuf;            /* position buffer pointer */
 
        unsigned int bufsize;   /* size of the play buffer in bytes */
-       unsigned int fragsize;  /* size of each period in bytes */
        unsigned int frags;     /* number for period in the play buffer */
        unsigned int fifo_size; /* FIFO size */
 
@@ -350,7 +345,6 @@ struct azx {
        struct azx_dev *azx_dev;
 
        /* PCM */
-       unsigned int pcm_devs;
        struct snd_pcm *pcm[AZX_MAX_PCMS];
 
        /* HD codec */
@@ -361,8 +355,7 @@ struct azx {
        struct azx_rb corb;
        struct azx_rb rirb;
 
-       /* BDL, CORB/RIRB and position buffers */
-       struct snd_dma_buffer bdl;
+       /* CORB/RIRB and position buffers */
        struct snd_dma_buffer rb;
        struct snd_dma_buffer posbuf;
 
@@ -546,8 +539,9 @@ static void azx_update_rirb(struct azx *chip)
                if (res_ex & ICH6_RIRB_EX_UNSOL_EV)
                        snd_hda_queue_unsol_event(chip->bus, res, res_ex);
                else if (chip->rirb.cmds) {
-                       chip->rirb.cmds--;
                        chip->rirb.res = res;
+                       smp_wmb();
+                       chip->rirb.cmds--;
                }
        }
 }
@@ -566,8 +560,10 @@ static unsigned int azx_rirb_get_response(struct hda_codec *codec)
                        azx_update_rirb(chip);
                        spin_unlock_irq(&chip->reg_lock);
                }
-               if (!chip->rirb.cmds)
+               if (!chip->rirb.cmds) {
+                       smp_rmb();
                        return chip->rirb.res; /* the last value */
+               }
                if (time_after(jiffies, timeout))
                        break;
                if (codec->bus->needs_damn_long_delay)
@@ -965,30 +961,57 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id)
 /*
  * set up BDL entries
  */
-static void azx_setup_periods(struct azx_dev *azx_dev)
+static int azx_setup_periods(struct snd_pcm_substream *substream,
+                            struct azx_dev *azx_dev)
 {
-       u32 *bdl = azx_dev->bdl;
-       dma_addr_t dma_addr = azx_dev->substream->runtime->dma_addr;
-       int idx;
+       struct snd_sg_buf *sgbuf = snd_pcm_substream_sgbuf(substream);
+       u32 *bdl;
+       int i, ofs, periods, period_bytes;
 
        /* reset BDL address */
        azx_sd_writel(azx_dev, SD_BDLPL, 0);
        azx_sd_writel(azx_dev, SD_BDLPU, 0);
 
+       period_bytes = snd_pcm_lib_period_bytes(substream);
+       periods = azx_dev->bufsize / period_bytes;
+
        /* program the initial BDL entries */
-       for (idx = 0; idx < azx_dev->frags; idx++) {
-               unsigned int off = idx << 2; /* 4 dword step */
-               dma_addr_t addr = dma_addr + idx * azx_dev->fragsize;
-               /* program the address field of the BDL entry */
-               bdl[off] = cpu_to_le32((u32)addr);
-               bdl[off+1] = cpu_to_le32(upper_32bit(addr));
-
-               /* program the size field of the BDL entry */
-               bdl[off+2] = cpu_to_le32(azx_dev->fragsize);
-
-               /* program the IOC to enable interrupt when buffer completes */
-               bdl[off+3] = cpu_to_le32(0x01);
+       bdl = (u32 *)azx_dev->bdl.area;
+       ofs = 0;
+       azx_dev->frags = 0;
+       for (i = 0; i < periods; i++) {
+               int size, rest;
+               if (i >= AZX_MAX_BDL_ENTRIES) {
+                       snd_printk(KERN_ERR "Too many BDL entries: "
+                                  "buffer=%d, period=%d\n",
+                                  azx_dev->bufsize, period_bytes);
+                       /* reset */
+                       azx_sd_writel(azx_dev, SD_BDLPL, 0);
+                       azx_sd_writel(azx_dev, SD_BDLPU, 0);
+                       return -EINVAL;
+               }
+               rest = period_bytes;
+               do {
+                       dma_addr_t addr = snd_pcm_sgbuf_get_addr(sgbuf, ofs);
+                       /* program the address field of the BDL entry */
+                       bdl[0] = cpu_to_le32((u32)addr);
+                       bdl[1] = cpu_to_le32(upper_32bit(addr));
+                       /* program the size field of the BDL entry */
+                       size = PAGE_SIZE - (ofs % PAGE_SIZE);
+                       if (rest < size)
+                               size = rest;
+                       bdl[2] = cpu_to_le32(size);
+                       /* program the IOC to enable interrupt
+                        * only when the whole fragment is processed
+                        */
+                       rest -= size;
+                       bdl[3] = rest ? 0 : cpu_to_le32(0x01);
+                       bdl += 4;
+                       azx_dev->frags++;
+                       ofs += size;
+               } while (rest > 0);
        }
+       return 0;
 }
 
 /*
@@ -1037,14 +1060,17 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
 
        /* program the BDL address */
        /* lower BDL address */
-       azx_sd_writel(azx_dev, SD_BDLPL, (u32)azx_dev->bdl_addr);
+       azx_sd_writel(azx_dev, SD_BDLPL, (u32)azx_dev->bdl.addr);
        /* upper BDL address */
-       azx_sd_writel(azx_dev, SD_BDLPU, upper_32bit(azx_dev->bdl_addr));
+       azx_sd_writel(azx_dev, SD_BDLPU, upper_32bit(azx_dev->bdl.addr));
 
        /* enable the position buffer */
-       if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE))
-               azx_writel(chip, DPLBASE,
-                          (u32)chip->posbuf.addr |ICH6_DPLBASE_ENABLE);
+       if (chip->position_fix == POS_FIX_POSBUF ||
+           chip->position_fix == POS_FIX_AUTO) {
+               if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE))
+                       azx_writel(chip, DPLBASE,
+                               (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE);
+       }
 
        /* set the interrupt enable bits in the descriptor control register */
        azx_sd_writel(azx_dev, SD_CTL,
@@ -1157,7 +1183,8 @@ static struct snd_pcm_hardware azx_pcm_hw = {
                                 SNDRV_PCM_INFO_MMAP_VALID |
                                 /* No full-resume yet implemented */
                                 /* SNDRV_PCM_INFO_RESUME |*/
-                                SNDRV_PCM_INFO_PAUSE),
+                                SNDRV_PCM_INFO_PAUSE |
+                                SNDRV_PCM_INFO_SYNC_START),
        .formats =              SNDRV_PCM_FMTBIT_S16_LE,
        .rates =                SNDRV_PCM_RATE_48000,
        .rate_min =             48000,
@@ -1219,6 +1246,7 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
        spin_unlock_irqrestore(&chip->reg_lock, flags);
 
        runtime->private_data = azx_dev;
+       snd_pcm_set_sync(substream);
        mutex_unlock(&chip->open_mutex);
        return 0;
 }
@@ -1275,8 +1303,6 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
        struct snd_pcm_runtime *runtime = substream->runtime;
 
        azx_dev->bufsize = snd_pcm_lib_buffer_bytes(substream);
-       azx_dev->fragsize = snd_pcm_lib_period_bytes(substream);
-       azx_dev->frags = azx_dev->bufsize / azx_dev->fragsize;
        azx_dev->format_val = snd_hda_calc_stream_format(runtime->rate,
                                                         runtime->channels,
                                                         runtime->format,
@@ -1288,10 +1314,10 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
                return -EINVAL;
        }
 
-       snd_printdd("azx_pcm_prepare: bufsize=0x%x, fragsize=0x%x, "
-                   "format=0x%x\n",
-                   azx_dev->bufsize, azx_dev->fragsize, azx_dev->format_val);
-       azx_setup_periods(azx_dev);
+       snd_printdd("azx_pcm_prepare: bufsize=0x%x, format=0x%x\n",
+                   azx_dev->bufsize, azx_dev->format_val);
+       if (azx_setup_periods(substream, azx_dev) < 0)
+               return -EINVAL;
        azx_setup_controller(chip, azx_dev);
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
                azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1;
@@ -1305,37 +1331,94 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
 static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 {
        struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
-       struct azx_dev *azx_dev = get_azx_dev(substream);
        struct azx *chip = apcm->chip;
-       int err = 0;
+       struct azx_dev *azx_dev;
+       struct snd_pcm_substream *s;
+       int start, nsync = 0, sbits = 0;
+       int nwait, timeout;
 
-       spin_lock(&chip->reg_lock);
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
        case SNDRV_PCM_TRIGGER_RESUME:
        case SNDRV_PCM_TRIGGER_START:
-               azx_stream_start(chip, azx_dev);
-               azx_dev->running = 1;
+               start = 1;
                break;
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
        case SNDRV_PCM_TRIGGER_SUSPEND:
        case SNDRV_PCM_TRIGGER_STOP:
-               azx_stream_stop(chip, azx_dev);
-               azx_dev->running = 0;
+               start = 0;
                break;
        default:
-               err = -EINVAL;
+               return -EINVAL;
+       }
+
+       snd_pcm_group_for_each_entry(s, substream) {
+               if (s->pcm->card != substream->pcm->card)
+                       continue;
+               azx_dev = get_azx_dev(s);
+               sbits |= 1 << azx_dev->index;
+               nsync++;
+               snd_pcm_trigger_done(s, substream);
+       }
+
+       spin_lock(&chip->reg_lock);
+       if (nsync > 1) {
+               /* first, set SYNC bits of corresponding streams */
+               azx_writel(chip, SYNC, azx_readl(chip, SYNC) | sbits);
+       }
+       snd_pcm_group_for_each_entry(s, substream) {
+               if (s->pcm->card != substream->pcm->card)
+                       continue;
+               azx_dev = get_azx_dev(s);
+               if (start)
+                       azx_stream_start(chip, azx_dev);
+               else
+                       azx_stream_stop(chip, azx_dev);
+               azx_dev->running = start;
        }
        spin_unlock(&chip->reg_lock);
-       if (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH ||
-           cmd == SNDRV_PCM_TRIGGER_SUSPEND ||
-           cmd == SNDRV_PCM_TRIGGER_STOP) {
-               int timeout = 5000;
-               while ((azx_sd_readb(azx_dev, SD_CTL) & SD_CTL_DMA_START) &&
-                      --timeout)
-                       ;
+       if (start) {
+               if (nsync == 1)
+                       return 0;
+               /* wait until all FIFOs get ready */
+               for (timeout = 5000; timeout; timeout--) {
+                       nwait = 0;
+                       snd_pcm_group_for_each_entry(s, substream) {
+                               if (s->pcm->card != substream->pcm->card)
+                                       continue;
+                               azx_dev = get_azx_dev(s);
+                               if (!(azx_sd_readb(azx_dev, SD_STS) &
+                                     SD_STS_FIFO_READY))
+                                       nwait++;
+                       }
+                       if (!nwait)
+                               break;
+                       cpu_relax();
+               }
+       } else {
+               /* wait until all RUN bits are cleared */
+               for (timeout = 5000; timeout; timeout--) {
+                       nwait = 0;
+                       snd_pcm_group_for_each_entry(s, substream) {
+                               if (s->pcm->card != substream->pcm->card)
+                                       continue;
+                               azx_dev = get_azx_dev(s);
+                               if (azx_sd_readb(azx_dev, SD_CTL) &
+                                   SD_CTL_DMA_START)
+                                       nwait++;
+                       }
+                       if (!nwait)
+                               break;
+                       cpu_relax();
+               }
        }
-       return err;
+       if (nsync > 1) {
+               spin_lock(&chip->reg_lock);
+               /* reset SYNC bits */
+               azx_writel(chip, SYNC, azx_readl(chip, SYNC) & ~sbits);
+               spin_unlock(&chip->reg_lock);
+       }
+       return 0;
 }
 
 static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream)
@@ -1378,6 +1461,7 @@ static struct snd_pcm_ops azx_pcm_ops = {
        .prepare = azx_pcm_prepare,
        .trigger = azx_pcm_trigger,
        .pointer = azx_pcm_pointer,
+       .page = snd_pcm_sgbuf_ops_page,
 };
 
 static void azx_pcm_free(struct snd_pcm *pcm)
@@ -1386,7 +1470,7 @@ static void azx_pcm_free(struct snd_pcm *pcm)
 }
 
 static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec,
-                                     struct hda_pcm *cpcm, int pcm_dev)
+                                     struct hda_pcm *cpcm)
 {
        int err;
        struct snd_pcm *pcm;
@@ -1400,7 +1484,7 @@ static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec,
 
        snd_assert(cpcm->name, return -EINVAL);
 
-       err = snd_pcm_new(chip->card, cpcm->name, pcm_dev,
+       err = snd_pcm_new(chip->card, cpcm->name, cpcm->device,
                          cpcm->stream[0].substreams,
                          cpcm->stream[1].substreams,
                          &pcm);
@@ -1420,62 +1504,70 @@ static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec,
                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);
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
                                              snd_dma_pci_data(chip->pci),
                                              1024 * 64, 1024 * 1024);
-       chip->pcm[pcm_dev] = pcm;
-       if (chip->pcm_devs < pcm_dev + 1)
-               chip->pcm_devs = pcm_dev + 1;
-
+       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 pcm_dev;
+       int num_devs[HDA_PCM_NTYPES];
 
        err = snd_hda_build_pcms(chip->bus);
        if (err < 0)
                return err;
 
        /* create audio PCMs */
-       pcm_dev = 0;
-       list_for_each_entry(codec, &chip->bus->codec_list, list) {
-               for (c = 0; c < codec->num_pcms; c++) {
-                       if (codec->pcm_info[c].is_modem)
-                               continue; /* create later */
-                       if (pcm_dev >= AZX_MAX_AUDIO_PCMS) {
-                               snd_printk(KERN_ERR SFX
-                                          "Too many audio PCMs\n");
-                               return -EINVAL;
-                       }
-                       err = create_codec_pcm(chip, codec,
-                                              &codec->pcm_info[c], pcm_dev);
-                       if (err < 0)
-                               return err;
-                       pcm_dev++;
-               }
-       }
-
-       /* create modem PCMs */
-       pcm_dev = AZX_MAX_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++) {
-                       if (!codec->pcm_info[c].is_modem)
-                               continue; /* already created */
-                       if (pcm_dev >= AZX_MAX_PCMS) {
-                               snd_printk(KERN_ERR SFX
-                                          "Too many modem PCMs\n");
-                               return -EINVAL;
+                       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;
                        }
-                       err = create_codec_pcm(chip, codec,
-                                              &codec->pcm_info[c], pcm_dev);
+                       num_devs[type]++;
+                       err = create_codec_pcm(chip, codec, cpcm);
                        if (err < 0)
                                return err;
-                       chip->pcm[pcm_dev]->dev_class = SNDRV_PCM_CLASS_MODEM;
-                       pcm_dev++;
                }
        }
        return 0;
@@ -1502,10 +1594,7 @@ static int __devinit azx_init_stream(struct azx *chip)
         * and initialize
         */
        for (i = 0; i < chip->num_streams; i++) {
-               unsigned int off = sizeof(u32) * (i * AZX_MAX_FRAG * 4);
                struct azx_dev *azx_dev = &chip->azx_dev[i];
-               azx_dev->bdl = (u32 *)(chip->bdl.area + off);
-               azx_dev->bdl_addr = chip->bdl.addr + off;
                azx_dev->posbuf = (u32 __iomem *)(chip->posbuf.area + i * 8);
                /* offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */
                azx_dev->sd_addr = chip->remap_addr + (0x20 * i + 0x80);
@@ -1587,13 +1676,12 @@ static int azx_suspend(struct pci_dev *pci, pm_message_t state)
        int i;
 
        snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
-       for (i = 0; i < chip->pcm_devs; i++)
+       for (i = 0; i < AZX_MAX_PCMS; i++)
                snd_pcm_suspend_all(chip->pcm[i]);
        if (chip->initialized)
                snd_hda_suspend(chip->bus, state);
        azx_stop_chip(chip);
        if (chip->irq >= 0) {
-               synchronize_irq(chip->irq);
                free_irq(chip->irq, chip);
                chip->irq = -1;
        }
@@ -1641,24 +1729,26 @@ static int azx_resume(struct pci_dev *pci)
  */
 static int azx_free(struct azx *chip)
 {
+       int i;
+
        if (chip->initialized) {
-               int i;
                for (i = 0; i < chip->num_streams; i++)
                        azx_stream_stop(chip, &chip->azx_dev[i]);
                azx_stop_chip(chip);
        }
 
-       if (chip->irq >= 0) {
-               synchronize_irq(chip->irq);
+       if (chip->irq >= 0)
                free_irq(chip->irq, (void*)chip);
-       }
        if (chip->msi)
                pci_disable_msi(chip->pci);
        if (chip->remap_addr)
                iounmap(chip->remap_addr);
 
-       if (chip->bdl.area)
-               snd_dma_free_pages(&chip->bdl);
+       if (chip->azx_dev) {
+               for (i = 0; i < chip->num_streams; i++)
+                       if (chip->azx_dev[i].bdl.area)
+                               snd_dma_free_pages(&chip->azx_dev[i].bdl);
+       }
        if (chip->rb.area)
                snd_dma_free_pages(&chip->rb);
        if (chip->posbuf.area)
@@ -1682,6 +1772,7 @@ static int azx_dev_free(struct snd_device *device)
 static struct snd_pci_quirk position_fix_list[] __devinitdata = {
        SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_NONE),
        SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_NONE),
+       SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_NONE),
        {}
 };
 
@@ -1740,7 +1831,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
                                struct azx **rchip)
 {
        struct azx *chip;
-       int err;
+       int i, err;
        unsigned short gcap;
        static struct snd_device_ops ops = {
                .dev_free = azx_dev_free,
@@ -1812,38 +1903,35 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
        gcap = azx_readw(chip, GCAP);
        snd_printdd("chipset global capabilities = 0x%x\n", gcap);
 
-       if (gcap) {
-               /* read number of streams from GCAP register instead of using
-                * hardcoded value
-                */
-               chip->playback_streams = (gcap & (0xF << 12)) >> 12;
-               chip->capture_streams = (gcap & (0xF << 8)) >> 8;
-               chip->playback_index_offset = chip->capture_streams;
-               chip->capture_index_offset = 0;
-       } else {
+       /* allow 64bit DMA address if supported by H/W */
+       if ((gcap & 0x01) && !pci_set_dma_mask(pci, DMA_64BIT_MASK))
+               pci_set_consistent_dma_mask(pci, DMA_64BIT_MASK);
+
+       /* read number of streams from GCAP register instead of using
+        * hardcoded value
+        */
+       chip->capture_streams = (gcap >> 8) & 0x0f;
+       chip->playback_streams = (gcap >> 12) & 0x0f;
+       if (!chip->playback_streams && !chip->capture_streams) {
                /* gcap didn't give any info, switching to old method */
 
                switch (chip->driver_type) {
                case AZX_DRIVER_ULI:
                        chip->playback_streams = ULI_NUM_PLAYBACK;
                        chip->capture_streams = ULI_NUM_CAPTURE;
-                       chip->playback_index_offset = ULI_PLAYBACK_INDEX;
-                       chip->capture_index_offset = ULI_CAPTURE_INDEX;
                        break;
                case AZX_DRIVER_ATIHDMI:
                        chip->playback_streams = ATIHDMI_NUM_PLAYBACK;
                        chip->capture_streams = ATIHDMI_NUM_CAPTURE;
-                       chip->playback_index_offset = ATIHDMI_PLAYBACK_INDEX;
-                       chip->capture_index_offset = ATIHDMI_CAPTURE_INDEX;
                        break;
                default:
                        chip->playback_streams = ICH6_NUM_PLAYBACK;
                        chip->capture_streams = ICH6_NUM_CAPTURE;
-                       chip->playback_index_offset = ICH6_PLAYBACK_INDEX;
-                       chip->capture_index_offset = ICH6_CAPTURE_INDEX;
                        break;
                }
        }
+       chip->capture_index_offset = 0;
+       chip->playback_index_offset = chip->capture_streams;
        chip->num_streams = chip->playback_streams + chip->capture_streams;
        chip->azx_dev = kcalloc(chip->num_streams, sizeof(*chip->azx_dev),
                                GFP_KERNEL);
@@ -1852,13 +1940,15 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
                goto errout;
        }
 
-       /* allocate memory for the BDL for each stream */
-       err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
-                                 snd_dma_pci_data(chip->pci),
-                                 BDL_SIZE, &chip->bdl);
-       if (err < 0) {
-               snd_printk(KERN_ERR SFX "cannot allocate BDL\n");
-               goto errout;
+       for (i = 0; i < chip->num_streams; i++) {
+               /* allocate memory for the BDL for each stream */
+               err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
+                                         snd_dma_pci_data(chip->pci),
+                                         BDL_SIZE, &chip->azx_dev[i].bdl);
+               if (err < 0) {
+                       snd_printk(KERN_ERR SFX "cannot allocate BDL\n");
+                       goto errout;
+               }
        }
        /* allocate memory for the position buffer */
        err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
@@ -1994,48 +2084,63 @@ static void __devexit azx_remove(struct pci_dev *pci)
 
 /* PCI IDs */
 static struct pci_device_id azx_ids[] = {
-       { 0x8086, 0x2668, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH6 */
-       { 0x8086, 0x27d8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH7 */
-       { 0x8086, 0x269a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ESB2 */
-       { 0x8086, 0x284b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH8 */
-       { 0x8086, 0x293e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH9 */
-       { 0x8086, 0x293f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH9 */
-       { 0x8086, 0x3a3e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH10 */
-       { 0x8086, 0x3a6e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH10 */
-       { 0x8086, 0x811b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_SCH }, /* SCH*/
-       { 0x1002, 0x437b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB450 */
-       { 0x1002, 0x4383, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB600 */
-       { 0x1002, 0x793b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RS600 HDMI */
-       { 0x1002, 0x7919, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RS690 HDMI */
-       { 0x1002, 0x960f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RS780 HDMI */
-       { 0x1002, 0xaa00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI R600 HDMI */
-       { 0x1002, 0xaa08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RV630 HDMI */
-       { 0x1002, 0xaa10, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RV610 HDMI */
-       { 0x1002, 0xaa18, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RV670 HDMI */
-       { 0x1002, 0xaa20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RV635 HDMI */
-       { 0x1002, 0xaa28, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RV620 HDMI */
-       { 0x1002, 0xaa30, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RV770 HDMI */
-       { 0x1106, 0x3288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_VIA }, /* VIA VT8251/VT8237A */
-       { 0x1039, 0x7502, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_SIS }, /* SIS966 */
-       { 0x10b9, 0x5461, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ULI }, /* ULI M5461 */
-       { 0x10de, 0x026c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP51 */
-       { 0x10de, 0x0371, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP55 */
-       { 0x10de, 0x03e4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP61 */
-       { 0x10de, 0x03f0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP61 */
-       { 0x10de, 0x044a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP65 */
-       { 0x10de, 0x044b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP65 */
-       { 0x10de, 0x055c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP67 */
-       { 0x10de, 0x055d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP67 */
-       { 0x10de, 0x07fc, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP73 */
-       { 0x10de, 0x07fd, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP73 */
-       { 0x10de, 0x0774, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP77 */
-       { 0x10de, 0x0775, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP77 */
-       { 0x10de, 0x0776, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP77 */
-       { 0x10de, 0x0777, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP77 */
-       { 0x10de, 0x0ac0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP79 */
-       { 0x10de, 0x0ac1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP79 */
-       { 0x10de, 0x0ac2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP79 */
-       { 0x10de, 0x0ac3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP79 */
+       /* ICH 6..10 */
+       { PCI_DEVICE(0x8086, 0x2668), .driver_data = AZX_DRIVER_ICH },
+       { PCI_DEVICE(0x8086, 0x27d8), .driver_data = AZX_DRIVER_ICH },
+       { PCI_DEVICE(0x8086, 0x269a), .driver_data = AZX_DRIVER_ICH },
+       { PCI_DEVICE(0x8086, 0x284b), .driver_data = AZX_DRIVER_ICH },
+       { PCI_DEVICE(0x8086, 0x293e), .driver_data = AZX_DRIVER_ICH },
+       { PCI_DEVICE(0x8086, 0x293f), .driver_data = AZX_DRIVER_ICH },
+       { PCI_DEVICE(0x8086, 0x3a3e), .driver_data = AZX_DRIVER_ICH },
+       { PCI_DEVICE(0x8086, 0x3a6e), .driver_data = AZX_DRIVER_ICH },
+       /* SCH */
+       { PCI_DEVICE(0x8086, 0x811b), .driver_data = AZX_DRIVER_SCH },
+       /* ATI SB 450/600 */
+       { PCI_DEVICE(0x1002, 0x437b), .driver_data = AZX_DRIVER_ATI },
+       { PCI_DEVICE(0x1002, 0x4383), .driver_data = AZX_DRIVER_ATI },
+       /* ATI HDMI */
+       { PCI_DEVICE(0x1002, 0x793b), .driver_data = AZX_DRIVER_ATIHDMI },
+       { PCI_DEVICE(0x1002, 0x7919), .driver_data = AZX_DRIVER_ATIHDMI },
+       { PCI_DEVICE(0x1002, 0x960f), .driver_data = AZX_DRIVER_ATIHDMI },
+       { PCI_DEVICE(0x1002, 0xaa00), .driver_data = AZX_DRIVER_ATIHDMI },
+       { PCI_DEVICE(0x1002, 0xaa08), .driver_data = AZX_DRIVER_ATIHDMI },
+       { PCI_DEVICE(0x1002, 0xaa10), .driver_data = AZX_DRIVER_ATIHDMI },
+       { PCI_DEVICE(0x1002, 0xaa18), .driver_data = AZX_DRIVER_ATIHDMI },
+       { PCI_DEVICE(0x1002, 0xaa20), .driver_data = AZX_DRIVER_ATIHDMI },
+       { PCI_DEVICE(0x1002, 0xaa28), .driver_data = AZX_DRIVER_ATIHDMI },
+       { PCI_DEVICE(0x1002, 0xaa30), .driver_data = AZX_DRIVER_ATIHDMI },
+       { PCI_DEVICE(0x1002, 0xaa38), .driver_data = AZX_DRIVER_ATIHDMI },
+       { PCI_DEVICE(0x1002, 0xaa40), .driver_data = AZX_DRIVER_ATIHDMI },
+       { PCI_DEVICE(0x1002, 0xaa48), .driver_data = AZX_DRIVER_ATIHDMI },
+       /* VIA VT8251/VT8237A */
+       { PCI_DEVICE(0x1106, 0x3288), .driver_data = AZX_DRIVER_VIA },
+       /* SIS966 */
+       { PCI_DEVICE(0x1039, 0x7502), .driver_data = AZX_DRIVER_SIS },
+       /* ULI M5461 */
+       { PCI_DEVICE(0x10b9, 0x5461), .driver_data = AZX_DRIVER_ULI },
+       /* NVIDIA MCP */
+       { PCI_DEVICE(0x10de, 0x026c), .driver_data = AZX_DRIVER_NVIDIA },
+       { PCI_DEVICE(0x10de, 0x0371), .driver_data = AZX_DRIVER_NVIDIA },
+       { PCI_DEVICE(0x10de, 0x03e4), .driver_data = AZX_DRIVER_NVIDIA },
+       { PCI_DEVICE(0x10de, 0x03f0), .driver_data = AZX_DRIVER_NVIDIA },
+       { PCI_DEVICE(0x10de, 0x044a), .driver_data = AZX_DRIVER_NVIDIA },
+       { PCI_DEVICE(0x10de, 0x044b), .driver_data = AZX_DRIVER_NVIDIA },
+       { PCI_DEVICE(0x10de, 0x055c), .driver_data = AZX_DRIVER_NVIDIA },
+       { PCI_DEVICE(0x10de, 0x055d), .driver_data = AZX_DRIVER_NVIDIA },
+       { PCI_DEVICE(0x10de, 0x0774), .driver_data = AZX_DRIVER_NVIDIA },
+       { PCI_DEVICE(0x10de, 0x0775), .driver_data = AZX_DRIVER_NVIDIA },
+       { PCI_DEVICE(0x10de, 0x0776), .driver_data = AZX_DRIVER_NVIDIA },
+       { PCI_DEVICE(0x10de, 0x0777), .driver_data = AZX_DRIVER_NVIDIA },
+       { PCI_DEVICE(0x10de, 0x07fc), .driver_data = AZX_DRIVER_NVIDIA },
+       { PCI_DEVICE(0x10de, 0x07fd), .driver_data = AZX_DRIVER_NVIDIA },
+       { PCI_DEVICE(0x10de, 0x0ac0), .driver_data = AZX_DRIVER_NVIDIA },
+       { PCI_DEVICE(0x10de, 0x0ac1), .driver_data = AZX_DRIVER_NVIDIA },
+       { PCI_DEVICE(0x10de, 0x0ac2), .driver_data = AZX_DRIVER_NVIDIA },
+       { PCI_DEVICE(0x10de, 0x0ac3), .driver_data = AZX_DRIVER_NVIDIA },
+       { PCI_DEVICE(0x10de, 0x0bd4), .driver_data = AZX_DRIVER_NVIDIA },
+       { PCI_DEVICE(0x10de, 0x0bd5), .driver_data = AZX_DRIVER_NVIDIA },
+       { PCI_DEVICE(0x10de, 0x0bd6), .driver_data = AZX_DRIVER_NVIDIA },
+       { PCI_DEVICE(0x10de, 0x0bd7), .driver_data = AZX_DRIVER_NVIDIA },
        { 0, }
 };
 MODULE_DEVICE_TABLE(pci, azx_ids);
index ad0014ab71f9e0388ead79f283a7867ca4542c39..5c9e578f7f2dd89b745d87594711ed3bec01ec3b 100644 (file)
@@ -228,8 +228,18 @@ struct hda_multi_out {
        int max_channels;       /* currently supported analog channels */
        int dig_out_used;       /* current usage of digital out (HDA_DIG_XXX) */
        int no_share_stream;    /* don't share a stream with multiple pins */
+       int share_spdif;        /* share SPDIF pin */
+       /* PCM information for both analog and SPDIF DACs */
+       unsigned int analog_rates;
+       unsigned int analog_maxbps;
+       u64 analog_formats;
+       unsigned int spdif_rates;
+       unsigned int spdif_maxbps;
+       u64 spdif_formats;
 };
 
+int snd_hda_create_spdif_share_sw(struct hda_codec *codec,
+                                 struct hda_multi_out *mout);
 int snd_hda_multi_out_dig_open(struct hda_codec *codec,
                               struct hda_multi_out *mout);
 int snd_hda_multi_out_dig_close(struct hda_codec *codec,
@@ -241,7 +251,8 @@ int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
                                  struct snd_pcm_substream *substream);
 int snd_hda_multi_out_analog_open(struct hda_codec *codec,
                                  struct hda_multi_out *mout,
-                                 struct snd_pcm_substream *substream);
+                                 struct snd_pcm_substream *substream,
+                                 struct hda_pcm_stream *hinfo);
 int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
                                     struct hda_multi_out *mout,
                                     unsigned int stream_tag,
@@ -407,11 +418,4 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec,
                                 hda_nid_t nid);
 #endif /* CONFIG_SND_HDA_POWER_SAVE */
 
-/*
- * virtual master control
- */
-struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
-                                                const unsigned int *tlv);
-int snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave);
-                     
 #endif /* __SOUND_HDA_LOCAL_H */
index f5c23bb16d7eb79f1137053a047e986c15c0a762..2fdf2358dbc2aee3281bfd074ec883d545fa33af 100644 (file)
@@ -18,31 +18,3 @@ extern struct hda_codec_preset snd_hda_preset_atihdmi[];
 extern struct hda_codec_preset snd_hda_preset_conexant[];
 /* VIA codecs */
 extern struct hda_codec_preset snd_hda_preset_via[];
-
-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
-       NULL
-};
index c8649282c2cfec54b191468f52b98bc18b82e385..e0a605adde422e76b5b4b036887346099a49c822 100644 (file)
@@ -28,6 +28,7 @@
 #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];
@@ -80,7 +81,6 @@ struct ad198x_spec {
 #endif
        /* for virtual master */
        hda_nid_t vmaster_nid;
-       u32 vmaster_tlv[4];
        const char **slave_vols;
        const char **slave_sws;
 };
@@ -171,6 +171,11 @@ static int ad198x_build_controls(struct hda_codec *codec)
                err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
                if (err < 0)
                        return err;
+               err = snd_hda_create_spdif_share_sw(codec,
+                                                   &spec->multiout);
+               if (err < 0)
+                       return err;
+               spec->multiout.share_spdif = 1;
        } 
        if (spec->dig_in_nid) {
                err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
@@ -180,10 +185,11 @@ static int ad198x_build_controls(struct hda_codec *codec)
 
        /* if we have no master control, let's create it */
        if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
+               unsigned int vmaster_tlv[4];
                snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
-                                       HDA_OUTPUT, spec->vmaster_tlv);
+                                       HDA_OUTPUT, vmaster_tlv);
                err = snd_hda_add_vmaster(codec, "Master Playback Volume",
-                                         spec->vmaster_tlv,
+                                         vmaster_tlv,
                                          (spec->slave_vols ?
                                           spec->slave_vols : ad_slave_vols));
                if (err < 0)
@@ -217,7 +223,8 @@ static int ad198x_playback_pcm_open(struct hda_pcm_stream *hinfo,
                                    struct snd_pcm_substream *substream)
 {
        struct ad198x_spec *spec = codec->spec;
-       return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
+       return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
+                                            hinfo);
 }
 
 static int ad198x_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
@@ -289,8 +296,7 @@ static int ad198x_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
                                      struct snd_pcm_substream *substream)
 {
        struct ad198x_spec *spec = codec->spec;
-       snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
-                                  0, 0, 0);
+       snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
        return 0;
 }
 
@@ -359,6 +365,7 @@ static int ad198x_build_pcms(struct hda_codec *codec)
                info++;
                codec->num_pcms++;
                info->name = "AD198x Digital";
+               info->pcm_type = HDA_PCM_TYPE_SPDIF;
                info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback;
                info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
                if (spec->dig_in_nid) {
@@ -611,13 +618,19 @@ static struct hda_input_mux ad1986a_laptop_eapd_capture_source = {
        },
 };
 
+static struct hda_input_mux ad1986a_automic_capture_source = {
+       .num_items = 2,
+       .items = {
+               { "Mic", 0x0 },
+               { "Mix", 0x5 },
+       },
+};
+
 static struct snd_kcontrol_new ad1986a_laptop_eapd_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("Internal Mic Playback Volume", 0x17, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 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),
@@ -641,6 +654,33 @@ static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = {
        { } /* end */
 };
 
+/* re-connect the mic boost input according to the jack sensing */
+static void ad1986a_automic(struct hda_codec *codec)
+{
+       unsigned int present;
+       present = snd_hda_codec_read(codec, 0x1f, 0, AC_VERB_GET_PIN_SENSE, 0);
+       /* 0 = 0x1f, 2 = 0x1d, 4 = mixed */
+       snd_hda_codec_write(codec, 0x0f, 0, AC_VERB_SET_CONNECT_SEL,
+                           (present & AC_PINSENSE_PRESENCE) ? 0 : 2);
+}
+
+#define AD1986A_MIC_EVENT              0x36
+
+static void ad1986a_automic_unsol_event(struct hda_codec *codec,
+                                           unsigned int res)
+{
+       if ((res >> 26) != AD1986A_MIC_EVENT)
+               return;
+       ad1986a_automic(codec);
+}
+
+static int ad1986a_automic_init(struct hda_codec *codec)
+{
+       ad198x_init(codec);
+       ad1986a_automic(codec);
+       return 0;
+}
+
 /* laptop-automute - 2ch only */
 
 static void ad1986a_update_hp(struct hda_codec *codec)
@@ -844,6 +884,15 @@ static struct hda_verb ad1986a_eapd_init_verbs[] = {
        {}
 };
 
+static struct hda_verb ad1986a_automic_verbs[] = {
+       {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+       {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+       /*{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},*/
+       {0x0f, AC_VERB_SET_CONNECT_SEL, 0x0},
+       {0x1f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_MIC_EVENT},
+       {}
+};
+
 /* Ultra initialization */
 static struct hda_verb ad1986a_ultra_init[] = {
        /* eapd initialization */
@@ -986,14 +1035,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->num_init_verbs = 3;
                spec->init_verbs[1] = ad1986a_eapd_init_verbs;
+               spec->init_verbs[2] = ad1986a_automic_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;
+               spec->input_mux = &ad1986a_automic_capture_source;
+               codec->patch_ops.unsol_event = ad1986a_automic_unsol_event;
+               codec->patch_ops.init = ad1986a_automic_init;
                break;
        case AD1986A_LAPTOP_AUTOMUTE:
                spec->mixers[0] = ad1986a_laptop_automute_mixers;
@@ -1365,7 +1417,10 @@ static int ad1981_hp_master_sw_put(struct snd_kcontrol *kcontrol,
 
        if (! ad198x_eapd_put(kcontrol, ucontrol))
                return 0;
-
+       /* change speaker pin appropriately */
+       snd_hda_codec_write(codec, 0x05, 0,
+                           AC_VERB_SET_PIN_WIDGET_CONTROL,
+                           spec->cur_eapd ? PIN_OUT : 0);
        /* toggle HP mute appropriately */
        snd_hda_codec_amp_stereo(codec, 0x06, HDA_OUTPUT, 0,
                                 HDA_AMP_MUTE,
@@ -2087,6 +2142,10 @@ static struct snd_kcontrol_new ad1988_spdif_in_mixers[] = {
        { } /* end */
 };
 
+static struct snd_kcontrol_new ad1989_spdif_out_mixers[] = {
+       HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
+       { } /* end */
+};
 
 /*
  * initialization verbs
@@ -2187,6 +2246,13 @@ static struct hda_verb ad1988_spdif_init_verbs[] = {
        { }
 };
 
+/* AD1989 has no ADC -> SPDIF route */
+static struct hda_verb ad1989_spdif_init_verbs[] = {
+       /* SPDIF out pin */
+       {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
+       { }
+};
+
 /*
  * verbs for 3stack (+dig)
  */
@@ -2894,10 +2960,19 @@ static int patch_ad1988(struct hda_codec *codec)
        spec->mixers[spec->num_mixers++] = ad1988_capture_mixers;
        spec->init_verbs[spec->num_init_verbs++] = ad1988_capture_init_verbs;
        if (spec->multiout.dig_out_nid) {
-               spec->mixers[spec->num_mixers++] = ad1988_spdif_out_mixers;
-               spec->init_verbs[spec->num_init_verbs++] = ad1988_spdif_init_verbs;
+               if (codec->vendor_id >= 0x11d4989a) {
+                       spec->mixers[spec->num_mixers++] =
+                               ad1989_spdif_out_mixers;
+                       spec->init_verbs[spec->num_init_verbs++] =
+                               ad1989_spdif_init_verbs;
+               } else {
+                       spec->mixers[spec->num_mixers++] =
+                               ad1988_spdif_out_mixers;
+                       spec->init_verbs[spec->num_init_verbs++] =
+                               ad1988_spdif_init_verbs;
+               }
        }
-       if (spec->dig_in_nid)
+       if (spec->dig_in_nid && codec->vendor_id < 0x11d4989a)
                spec->mixers[spec->num_mixers++] = ad1988_spdif_in_mixers;
 
        codec->patch_ops = ad198x_patch_ops;
@@ -3133,11 +3208,12 @@ static int patch_ad1884(struct hda_codec *codec)
  * Lenovo Thinkpad T61/X61
  */
 static struct hda_input_mux ad1984_thinkpad_capture_source = {
-       .num_items = 3,
+       .num_items = 4,
        .items = {
                { "Mic", 0x0 },
                { "Internal Mic", 0x1 },
                { "Mix", 0x3 },
+               { "Docking-Station", 0x4 },
        },
 };
 
@@ -3268,8 +3344,7 @@ static int ad1984_pcm_dmic_cleanup(struct hda_pcm_stream *hinfo,
                                   struct hda_codec *codec,
                                   struct snd_pcm_substream *substream)
 {
-       snd_hda_codec_setup_stream(codec, 0x05 + substream->number,
-                                  0, 0, 0);
+       snd_hda_codec_cleanup_stream(codec, 0x05 + substream->number);
        return 0;
 }
 
@@ -3355,6 +3430,472 @@ static int patch_ad1984(struct hda_codec *codec)
 }
 
 
+/*
+ * AD1883 / AD1884A / AD1984A / AD1984B
+ *
+ * port-B (0x14) - front mic-in
+ * port-E (0x1c) - rear mic-in
+ * port-F (0x16) - CD / ext out
+ * port-C (0x15) - rear line-in
+ * port-D (0x12) - rear line-out
+ * port-A (0x11) - front hp-out
+ *
+ * AD1984A = AD1884A + digital-mic
+ * AD1883 = equivalent with AD1984A
+ * AD1984B = AD1984A + extra SPDIF-out
+ *
+ * FIXME:
+ * We share the single DAC for both HP and line-outs (see AD1884/1984).
+ */
+
+static hda_nid_t ad1884a_dac_nids[1] = {
+       0x03,
+};
+
+#define ad1884a_adc_nids       ad1884_adc_nids
+#define ad1884a_capsrc_nids    ad1884_capsrc_nids
+
+#define AD1884A_SPDIF_OUT      0x02
+
+static struct hda_input_mux ad1884a_capture_source = {
+       .num_items = 5,
+       .items = {
+               { "Front Mic", 0x0 },
+               { "Mic", 0x4 },
+               { "Line", 0x1 },
+               { "CD", 0x2 },
+               { "Mix", 0x3 },
+       },
+};
+
+static struct snd_kcontrol_new ad1884a_base_mixers[] = {
+       HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
+       HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
+       HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
+       HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
+       HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT),
+       HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT),
+       HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
+       HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
+       HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT),
+       HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT),
+       HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
+       HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT),
+       HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
+       HDA_CODEC_VOLUME("Line Boost", 0x15, 0x0, HDA_INPUT),
+       HDA_CODEC_VOLUME("Mic Boost", 0x25, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
+       {
+               .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 = ad198x_mux_enum_info,
+               .get = ad198x_mux_enum_get,
+               .put = ad198x_mux_enum_put,
+       },
+       /* SPDIF controls */
+       HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
+               /* identical with ad1983 */
+               .info = ad1983_spdif_route_info,
+               .get = ad1983_spdif_route_get,
+               .put = ad1983_spdif_route_put,
+       },
+       { } /* end */
+};
+
+/*
+ * initialization verbs
+ */
+static struct hda_verb ad1884a_init_verbs[] = {
+       /* DACs; unmute as default */
+       {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
+       {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
+       /* Port-A (HP) mixer - route only from analog mixer */
+       {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+       {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+       /* Port-A pin */
+       {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+       {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+       /* Port-D (Line-out) mixer - route only from analog mixer */
+       {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+       {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+       /* Port-D pin */
+       {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+       {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+       /* Mono-out mixer - route only from analog mixer */
+       {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+       {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+       /* Mono-out pin */
+       {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+       {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+       /* Port-B (front mic) pin */
+       {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+       {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+       /* Port-C (rear line-in) pin */
+       {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+       {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+       /* Port-E (rear mic) pin */
+       {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+       {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+       {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* no boost */
+       /* Port-F (CD) pin */
+       {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+       {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+       /* Analog mixer; mute as default */
+       {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+       {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+       {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+       {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+       {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, /* aux */
+       {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
+       /* Analog Mix output amp */
+       {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+       /* capture sources */
+       {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
+       {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+       {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
+       {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+       /* SPDIF output amp */
+       {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
+       { } /* end */
+};
+
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+static struct hda_amp_list ad1884a_loopbacks[] = {
+       { 0x20, HDA_INPUT, 0 }, /* Front Mic */
+       { 0x20, HDA_INPUT, 1 }, /* Mic */
+       { 0x20, HDA_INPUT, 2 }, /* CD */
+       { 0x20, HDA_INPUT, 4 }, /* Docking */
+       { } /* end */
+};
+#endif
+
+/*
+ * Laptop model
+ *
+ * Port A: Headphone jack
+ * Port B: MIC jack
+ * Port C: Internal MIC
+ * Port D: Dock Line Out (if enabled)
+ * Port E: Dock Line In (if enabled)
+ * Port F: Internal speakers
+ */
+
+static struct hda_input_mux ad1884a_laptop_capture_source = {
+       .num_items = 4,
+       .items = {
+               { "Mic", 0x0 },         /* port-B */
+               { "Internal Mic", 0x1 }, /* port-C */
+               { "Dock Mic", 0x4 },    /* port-E */
+               { "Mix", 0x3 },
+       },
+};
+
+static struct snd_kcontrol_new ad1884a_laptop_mixers[] = {
+       HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Dock Playback Switch", 0x12, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
+       HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
+       HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
+       HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
+       HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
+       HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
+       HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
+       HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
+       HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
+       HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT),
+       HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
+       HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT),
+       HDA_CODEC_VOLUME("Dock Mic Boost", 0x25, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
+       {
+               .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 = ad198x_mux_enum_info,
+               .get = ad198x_mux_enum_get,
+               .put = ad198x_mux_enum_put,
+       },
+       { } /* end */
+};
+
+static struct hda_input_mux ad1884a_mobile_capture_source = {
+       .num_items = 2,
+       .items = {
+               { "Mic", 0x1 }, /* port-C */
+               { "Mix", 0x3 },
+       },
+};
+
+static struct snd_kcontrol_new ad1884a_mobile_mixers[] = {
+       HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
+       HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
+       HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
+       HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
+       HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
+       HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT),
+       HDA_CODEC_VOLUME("Mic Boost", 0x15, 0x0, HDA_INPUT),
+       HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Capture Switch", 0x0c, 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,
+       },
+       { } /* end */
+};
+
+/* mute internal speaker if HP is plugged */
+static void ad1884a_hp_automute(struct hda_codec *codec)
+{
+       unsigned int present;
+
+       present = snd_hda_codec_read(codec, 0x11, 0,
+                                    AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+       snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
+                                HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
+       snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE,
+                           present ? 0x00 : 0x02);
+}
+
+#define AD1884A_HP_EVENT               0x37
+
+/* unsolicited event for HP jack sensing */
+static void ad1884a_hp_unsol_event(struct hda_codec *codec, unsigned int res)
+{
+       if ((res >> 26) != AD1884A_HP_EVENT)
+               return;
+       ad1884a_hp_automute(codec);
+}
+
+/* initialize jack-sensing, too */
+static int ad1884a_hp_init(struct hda_codec *codec)
+{
+       ad198x_init(codec);
+       ad1884a_hp_automute(codec);
+       return 0;
+}
+
+/* additional verbs for laptop model */
+static struct hda_verb ad1884a_laptop_verbs[] = {
+       /* Port-A (HP) pin - always unmuted */
+       {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       /* Port-F (int speaker) mixer - route only from analog mixer */
+       {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+       {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+       /* Port-F pin */
+       {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+       {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+       /* analog mix */
+       {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+       /* unsolicited event for pin-sense */
+       {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
+       { } /* end */
+};
+
+/*
+ * Thinkpad X300
+ * 0x11 - HP
+ * 0x12 - speaker
+ * 0x14 - mic-in
+ * 0x17 - built-in mic
+ */
+
+static struct hda_verb ad1984a_thinkpad_verbs[] = {
+       /* HP unmute */
+       {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       /* analog mix */
+       {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+       /* turn on EAPD */
+       {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
+       /* unsolicited event for pin-sense */
+       {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
+       /* internal mic - dmic */
+       {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+       /* set magic COEFs for dmic */
+       {0x01, AC_VERB_SET_COEF_INDEX, 0x13f7},
+       {0x01, AC_VERB_SET_PROC_COEF, 0x08},
+       { } /* end */
+};
+
+static struct snd_kcontrol_new ad1984a_thinkpad_mixers[] = {
+       HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
+       HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
+       HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
+       HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
+       HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
+       HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT),
+       HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
+       HDA_CODEC_VOLUME("Internal Mic Boost", 0x17, 0x0, HDA_INPUT),
+       HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Capture Switch", 0x0c, 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,
+       },
+       { } /* end */
+};
+
+static struct hda_input_mux ad1984a_thinkpad_capture_source = {
+       .num_items = 3,
+       .items = {
+               { "Mic", 0x0 },
+               { "Internal Mic", 0x5 },
+               { "Mix", 0x3 },
+       },
+};
+
+/* mute internal speaker if HP is plugged */
+static void ad1984a_thinkpad_automute(struct hda_codec *codec)
+{
+       unsigned int present;
+
+       present = snd_hda_codec_read(codec, 0x11, 0, AC_VERB_GET_PIN_SENSE, 0)
+               & AC_PINSENSE_PRESENCE;
+       snd_hda_codec_amp_stereo(codec, 0x12, HDA_OUTPUT, 0,
+                                HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
+}
+
+/* unsolicited event for HP jack sensing */
+static void ad1984a_thinkpad_unsol_event(struct hda_codec *codec,
+                                        unsigned int res)
+{
+       if ((res >> 26) != AD1884A_HP_EVENT)
+               return;
+       ad1984a_thinkpad_automute(codec);
+}
+
+/* initialize jack-sensing, too */
+static int ad1984a_thinkpad_init(struct hda_codec *codec)
+{
+       ad198x_init(codec);
+       ad1984a_thinkpad_automute(codec);
+       return 0;
+}
+
+/*
+ */
+
+enum {
+       AD1884A_DESKTOP,
+       AD1884A_LAPTOP,
+       AD1884A_MOBILE,
+       AD1884A_THINKPAD,
+       AD1884A_MODELS
+};
+
+static const char *ad1884a_models[AD1884A_MODELS] = {
+       [AD1884A_DESKTOP]       = "desktop",
+       [AD1884A_LAPTOP]        = "laptop",
+       [AD1884A_MOBILE]        = "mobile",
+       [AD1884A_THINKPAD]      = "thinkpad",
+};
+
+static struct snd_pci_quirk ad1884a_cfg_tbl[] = {
+       SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE),
+       SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD),
+       {}
+};
+
+static int patch_ad1884a(struct hda_codec *codec)
+{
+       struct ad198x_spec *spec;
+       int board_config;
+
+       spec = kzalloc(sizeof(*spec), GFP_KERNEL);
+       if (spec == NULL)
+               return -ENOMEM;
+
+       mutex_init(&spec->amp_mutex);
+       codec->spec = spec;
+
+       spec->multiout.max_channels = 2;
+       spec->multiout.num_dacs = ARRAY_SIZE(ad1884a_dac_nids);
+       spec->multiout.dac_nids = ad1884a_dac_nids;
+       spec->multiout.dig_out_nid = AD1884A_SPDIF_OUT;
+       spec->num_adc_nids = ARRAY_SIZE(ad1884a_adc_nids);
+       spec->adc_nids = ad1884a_adc_nids;
+       spec->capsrc_nids = ad1884a_capsrc_nids;
+       spec->input_mux = &ad1884a_capture_source;
+       spec->num_mixers = 1;
+       spec->mixers[0] = ad1884a_base_mixers;
+       spec->num_init_verbs = 1;
+       spec->init_verbs[0] = ad1884a_init_verbs;
+       spec->spdif_route = 0;
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+       spec->loopback.amplist = ad1884a_loopbacks;
+#endif
+       codec->patch_ops = ad198x_patch_ops;
+
+       /* override some parameters */
+       board_config = snd_hda_check_board_config(codec, AD1884A_MODELS,
+                                                 ad1884a_models,
+                                                 ad1884a_cfg_tbl);
+       switch (board_config) {
+       case AD1884A_LAPTOP:
+               spec->mixers[0] = ad1884a_laptop_mixers;
+               spec->init_verbs[spec->num_init_verbs++] = ad1884a_laptop_verbs;
+               spec->multiout.dig_out_nid = 0;
+               spec->input_mux = &ad1884a_laptop_capture_source;
+               codec->patch_ops.unsol_event = ad1884a_hp_unsol_event;
+               codec->patch_ops.init = ad1884a_hp_init;
+               break;
+       case AD1884A_MOBILE:
+               spec->mixers[0] = ad1884a_mobile_mixers;
+               spec->init_verbs[spec->num_init_verbs++] = ad1884a_laptop_verbs;
+               spec->multiout.dig_out_nid = 0;
+               spec->input_mux = &ad1884a_mobile_capture_source;
+               codec->patch_ops.unsol_event = ad1884a_hp_unsol_event;
+               codec->patch_ops.init = ad1884a_hp_init;
+               break;
+       case AD1884A_THINKPAD:
+               spec->mixers[0] = ad1984a_thinkpad_mixers;
+               spec->init_verbs[spec->num_init_verbs++] =
+                       ad1984a_thinkpad_verbs;
+               spec->multiout.dig_out_nid = 0;
+               spec->input_mux = &ad1984a_thinkpad_capture_source;
+               codec->patch_ops.unsol_event = ad1984a_thinkpad_unsol_event;
+               codec->patch_ops.init = ad1984a_thinkpad_init;
+               break;
+       }
+
+       return 0;
+}
+
+
 /*
  * AD1882
  *
@@ -3654,13 +4195,19 @@ static int patch_ad1882(struct hda_codec *codec)
  * patch entries
  */
 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 },
        { .id = 0x11d41884, .name = "AD1884", .patch = patch_ad1884 },
+       { .id = 0x11d4194a, .name = "AD1984A", .patch = patch_ad1884a },
+       { .id = 0x11d4194b, .name = "AD1984B", .patch = patch_ad1884a },
        { .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 },
        { .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 },
        { .id = 0x11d41984, .name = "AD1984", .patch = patch_ad1984 },
        { .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a },
        { .id = 0x11d41988, .name = "AD1988", .patch = patch_ad1988 },
        { .id = 0x11d4198b, .name = "AD1988B", .patch = patch_ad1988 },
+       { .id = 0x11d4989a, .name = "AD1989A", .patch = patch_ad1988 },
+       { .id = 0x11d4989b, .name = "AD1989B", .patch = patch_ad1988 },
        {} /* terminator */
 };
index 9a8bb4ce3f8da103847a7dce8e1bb8c01d13316e..12272508b1124abebcb68fdcc06458727cbe86da 100644 (file)
@@ -27,6 +27,7 @@
 #include <sound/core.h>
 #include "hda_codec.h"
 #include "hda_local.h"
+#include "hda_patch.h"
 
 struct atihdmi_spec {
        struct hda_multi_out multiout;
@@ -58,6 +59,10 @@ static int atihdmi_build_controls(struct hda_codec *codec)
 static int atihdmi_init(struct hda_codec *codec)
 {
        snd_hda_sequence_write(codec, atihdmi_basic_init);
+       /* SI codec requires to unmute the pin */
+       if (get_wcaps(codec, 0x03) & AC_WCAP_OUT_AMP)
+               snd_hda_codec_write(codec, 0x03, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+                                   AMP_OUT_UNMUTE);
        return 0;
 }
 
@@ -112,6 +117,7 @@ static int atihdmi_build_pcms(struct hda_codec *codec)
        codec->pcm_info = info;
 
        info->name = "ATI HDMI";
+       info->pcm_type = HDA_PCM_TYPE_HDMI;
        info->stream[SNDRV_PCM_STREAM_PLAYBACK] = atihdmi_pcm_digital_playback;
 
        return 0;
@@ -158,5 +164,7 @@ struct hda_codec_preset snd_hda_preset_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 },
+       { .id = 0x10951392, .name = "SiI1392 HDMI", .patch = patch_atihdmi },
+       { .id = 0x17e80047, .name = "Chrontel HDMI",  .patch = patch_atihdmi },
        {} /* terminator */
 };
index 3d6097ba1d68fb98f851fe1668effd6fe1d0a4ba..c73ce074a6ea91a38d879b7cb65ae1d49025b892 100644 (file)
@@ -28,6 +28,7 @@
 #include <sound/core.h>
 #include "hda_codec.h"
 #include "hda_local.h"
+#include "hda_patch.h"
 #define NUM_PINS       11
 
 
@@ -329,6 +330,11 @@ static int cmi9880_build_controls(struct hda_codec *codec)
                err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
                if (err < 0)
                        return err;
+               err = snd_hda_create_spdif_share_sw(codec,
+                                                   &spec->multiout);
+               if (err < 0)
+                       return err;
+               spec->multiout.share_spdif = 1;
        }
        if (spec->dig_in_nid) {
                err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
@@ -432,7 +438,8 @@ static int cmi9880_playback_pcm_open(struct hda_pcm_stream *hinfo,
                                     struct snd_pcm_substream *substream)
 {
        struct cmi_spec *spec = codec->spec;
-       return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
+       return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
+                                            hinfo);
 }
 
 static int cmi9880_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
@@ -506,7 +513,7 @@ static int cmi9880_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
 {
        struct cmi_spec *spec = codec->spec;
 
-       snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 0, 0, 0);
+       snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
        return 0;
 }
 
@@ -571,6 +578,7 @@ static int cmi9880_build_pcms(struct hda_codec *codec)
                codec->num_pcms++;
                info++;
                info->name = "CMI9880 Digital";
+               info->pcm_type = HDA_PCM_TYPE_SPDIF;
                if (spec->multiout.dig_out_nid) {
                        info->stream[SNDRV_PCM_STREAM_PLAYBACK] = cmi9880_pcm_digital_playback;
                        info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
@@ -603,6 +611,7 @@ static const char *cmi9880_models[CMI_MODELS] = {
 
 static struct snd_pci_quirk cmi9880_cfg_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", CMI_FULL_DIG),
+       SND_PCI_QUIRK(0x1854, 0x0032, "LG", CMI_FULL_DIG),
        {} /* terminator */
 };
 
index 7206b30cbf9454c30e19f0c2c49e9dbe9684df2f..36fd852600352244c17e10f6b49c72e284840ea0 100644 (file)
@@ -27,6 +27,7 @@
 #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
@@ -98,7 +99,8 @@ static int conexant_playback_pcm_open(struct hda_pcm_stream *hinfo,
                                      struct snd_pcm_substream *substream)
 {
        struct conexant_spec *spec = codec->spec;
-       return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
+       return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
+                                            hinfo);
 }
 
 static int conexant_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
@@ -172,8 +174,7 @@ static int conexant_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
                                      struct snd_pcm_substream *substream)
 {
        struct conexant_spec *spec = codec->spec;
-       snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
-                                  0, 0, 0);
+       snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
        return 0;
 }
 
@@ -241,7 +242,7 @@ static int cx5051_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
                                      struct snd_pcm_substream *substream)
 {
        struct conexant_spec *spec = codec->spec;
-       snd_hda_codec_setup_stream(codec, spec->cur_adc, 0, 0, 0);
+       snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
        spec->cur_adc = 0;
        return 0;
 }
@@ -284,6 +285,7 @@ static int conexant_build_pcms(struct hda_codec *codec)
                info++;
                codec->num_pcms++;
                info->name = "Conexant Digital";
+               info->pcm_type = HDA_PCM_TYPE_SPDIF;
                info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
                        conexant_pcm_digital_playback;
                info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
@@ -371,6 +373,11 @@ static int conexant_build_controls(struct hda_codec *codec)
                                                    spec->multiout.dig_out_nid);
                if (err < 0)
                        return err;
+               err = snd_hda_create_spdif_share_sw(codec,
+                                                   &spec->multiout);
+               if (err < 0)
+                       return err;
+               spec->multiout.share_spdif = 1;
        } 
        if (spec->dig_in_nid) {
                err = snd_hda_create_spdif_in_ctls(codec,spec->dig_in_nid);
@@ -511,6 +518,14 @@ static struct hda_input_mux cxt5045_capture_source_benq = {
        }
 };
 
+static struct hda_input_mux cxt5045_capture_source_hp530 = {
+       .num_items = 2,
+       .items = {
+               { "ExtMic", 0x1 },
+               { "IntMic", 0x2 },
+       }
+};
+
 /* turn on/off EAPD (+ mute HP) as a master switch */
 static int cxt5045_hp_master_sw_put(struct snd_kcontrol *kcontrol,
                                    struct snd_ctl_elem_value *ucontrol)
@@ -639,6 +654,37 @@ static struct snd_kcontrol_new cxt5045_benq_mixers[] = {
        {}
 };
 
+static struct snd_kcontrol_new cxt5045_mixers_hp530[] = {
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "Capture Source",
+               .info = conexant_mux_enum_info,
+               .get = conexant_mux_enum_get,
+               .put = conexant_mux_enum_put
+       },
+       HDA_CODEC_VOLUME("Int Mic Capture Volume", 0x1a, 0x02, HDA_INPUT),
+       HDA_CODEC_MUTE("Int Mic Capture Switch", 0x1a, 0x02, HDA_INPUT),
+       HDA_CODEC_VOLUME("Ext Mic Capture Volume", 0x1a, 0x01, HDA_INPUT),
+       HDA_CODEC_MUTE("Ext Mic Capture Switch", 0x1a, 0x01, HDA_INPUT),
+       HDA_CODEC_VOLUME("PCM Playback Volume", 0x17, 0x0, HDA_INPUT),
+       HDA_CODEC_MUTE("PCM Playback Switch", 0x17, 0x0, HDA_INPUT),
+       HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x17, 0x2, HDA_INPUT),
+       HDA_CODEC_MUTE("Int Mic Playback Switch", 0x17, 0x2, HDA_INPUT),
+       HDA_CODEC_VOLUME("Ext Mic Playback Volume", 0x17, 0x1, HDA_INPUT),
+       HDA_CODEC_MUTE("Ext Mic Playback Switch", 0x17, 0x1, HDA_INPUT),
+       HDA_BIND_VOL("Master Playback Volume", &cxt5045_hp_bind_master_vol),
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "Master Playback Switch",
+               .info = cxt_eapd_info,
+               .get = cxt_eapd_get,
+               .put = cxt5045_hp_master_sw_put,
+               .private_value = 0x10,
+       },
+
+       {}
+};
+
 static struct hda_verb cxt5045_init_verbs[] = {
        /* Line in, Mic */
        {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
@@ -833,6 +879,7 @@ enum {
        CXT5045_LAPTOP_MICSENSE,
        CXT5045_LAPTOP_HPMICSENSE,
        CXT5045_BENQ,
+       CXT5045_LAPTOP_HP530,
 #ifdef CONFIG_SND_DEBUG
        CXT5045_TEST,
 #endif
@@ -844,6 +891,7 @@ static const char *cxt5045_models[CXT5045_MODELS] = {
        [CXT5045_LAPTOP_MICSENSE]       = "laptop-micsense",
        [CXT5045_LAPTOP_HPMICSENSE]     = "laptop-hpmicsense",
        [CXT5045_BENQ]                  = "benq",
+       [CXT5045_LAPTOP_HP530]          = "laptop-hp530",
 #ifdef CONFIG_SND_DEBUG
        [CXT5045_TEST]          = "test",
 #endif
@@ -857,7 +905,7 @@ static struct snd_pci_quirk cxt5045_cfg_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x30bb, "HP DV8000", CXT5045_LAPTOP_HPSENSE),
        SND_PCI_QUIRK(0x103c, 0x30cd, "HP DV Series", CXT5045_LAPTOP_HPSENSE),
        SND_PCI_QUIRK(0x103c, 0x30cf, "HP DV9533EG", CXT5045_LAPTOP_HPSENSE),
-       SND_PCI_QUIRK(0x103c, 0x30d5, "HP 530", CXT5045_LAPTOP_HPSENSE),
+       SND_PCI_QUIRK(0x103c, 0x30d5, "HP 530", CXT5045_LAPTOP_HP530),
        SND_PCI_QUIRK(0x103c, 0x30d9, "HP Spartan", CXT5045_LAPTOP_HPSENSE),
        SND_PCI_QUIRK(0x152d, 0x0753, "Benq R55E", CXT5045_BENQ),
        SND_PCI_QUIRK(0x1734, 0x10ad, "Fujitsu Si1520", CXT5045_LAPTOP_MICSENSE),
@@ -941,6 +989,14 @@ static int patch_cxt5045(struct hda_codec *codec)
                spec->num_mixers = 2;
                codec->patch_ops.init = cxt5045_init;
                break;
+       case CXT5045_LAPTOP_HP530:
+               codec->patch_ops.unsol_event = cxt5045_hp_unsol_event;
+               spec->input_mux = &cxt5045_capture_source_hp530;
+               spec->num_init_verbs = 2;
+               spec->init_verbs[1] = cxt5045_hp_sense_init_verbs;
+               spec->mixers[0] = cxt5045_mixers_hp530;
+               codec->patch_ops.init = cxt5045_init;
+               break;
 #ifdef CONFIG_SND_DEBUG
        case CXT5045_TEST:
                spec->input_mux = &cxt5045_test_capture_source;
@@ -1537,7 +1593,7 @@ static void cxt5051_portc_automic(struct hda_codec *codec)
        new_adc = spec->adc_nids[spec->cur_adc_idx];
        if (spec->cur_adc && spec->cur_adc != new_adc) {
                /* stream is running, let's swap the current ADC */
-               snd_hda_codec_setup_stream(codec, spec->cur_adc, 0, 0, 0);
+               snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
                spec->cur_adc = new_adc;
                snd_hda_codec_setup_stream(codec, new_adc,
                                           spec->cur_adc_stream_tag, 0,
index 33282f9c01c7f9a586038243ea50695a3572a982..cdda64b02f4688c638f09b169bf0aefb1799a156 100644 (file)
@@ -30,6 +30,7 @@
 #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
@@ -97,16 +98,19 @@ enum {
        ALC262_SONY_ASSAMD,
        ALC262_BENQ_T31,
        ALC262_ULTRA,
+       ALC262_LENOVO_3000,
        ALC262_AUTO,
        ALC262_MODEL_LAST /* last tag */
 };
 
 /* ALC268 models */
 enum {
+       ALC267_QUANTA_IL1,
        ALC268_3ST,
        ALC268_TOSHIBA,
        ALC268_ACER,
        ALC268_DELL,
+       ALC268_ZEPTO,
 #ifdef CONFIG_SND_DEBUG
        ALC268_TEST,
 #endif
@@ -195,10 +199,11 @@ enum {
        ALC883_LENOVO_NB0763,
        ALC888_LENOVO_MS7195_DIG,
        ALC883_HAIER_W66,               
-       ALC888_6ST_HP,
        ALC888_3ST_HP,
        ALC888_6ST_DELL,
        ALC883_MITAC,
+       ALC883_CLEVO_M720,
+       ALC883_FUJITSU_PI2515,
        ALC883_AUTO,
        ALC883_MODEL_LAST,
 };
@@ -237,6 +242,7 @@ struct alc_spec {
        /* capture */
        unsigned int num_adc_nids;
        hda_nid_t *adc_nids;
+       hda_nid_t *capsrc_nids;
        hda_nid_t dig_in_nid;           /* digital-in NID; optional */
 
        /* capture source */
@@ -270,7 +276,6 @@ struct alc_spec {
 
        /* for virtual master */
        hda_nid_t vmaster_nid;
-       u32 vmaster_tlv[4];
 #ifdef CONFIG_SND_HDA_POWER_SAVE
        struct hda_loopback_check loopback;
 #endif
@@ -290,6 +295,7 @@ struct alc_config_preset {
        hda_nid_t hp_nid;               /* optional */
        unsigned int num_adc_nids;
        hda_nid_t *adc_nids;
+       hda_nid_t *capsrc_nids;
        hda_nid_t dig_in_nid;
        unsigned int num_channel_mode;
        const struct hda_channel_mode *channel_mode;
@@ -336,9 +342,10 @@ static int alc_mux_enum_put(struct snd_kcontrol *kcontrol,
        struct alc_spec *spec = codec->spec;
        unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
        unsigned int mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_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,
-                                    spec->adc_nids[adc_idx],
-                                    &spec->cur_mux[adc_idx]);
+                                    nid, &spec->cur_mux[adc_idx]);
 }
 
 
@@ -707,6 +714,7 @@ static void setup_preset(struct alc_spec *spec,
 
        spec->num_adc_nids = preset->num_adc_nids;
        spec->adc_nids = preset->adc_nids;
+       spec->capsrc_nids = preset->capsrc_nids;
        spec->dig_in_nid = preset->dig_in_nid;
 
        spec->unsol_event = preset->unsol_event;
@@ -741,7 +749,6 @@ static struct hda_verb alc_gpio3_init_verbs[] = {
 static void alc_sku_automute(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       unsigned int mute;
        unsigned int present;
        unsigned int hp_nid = spec->autocfg.hp_pins[0];
        unsigned int sp_nid = spec->autocfg.speaker_pins[0];
@@ -751,16 +758,8 @@ static void alc_sku_automute(struct hda_codec *codec)
        present = snd_hda_codec_read(codec, hp_nid, 0,
                                     AC_VERB_GET_PIN_SENSE, 0);
        spec->jack_present = (present & 0x80000000) != 0;
-       if (spec->jack_present) {
-               /* mute internal speaker */
-               snd_hda_codec_amp_stereo(codec, sp_nid, HDA_OUTPUT, 0,
-                                        HDA_AMP_MUTE, HDA_AMP_MUTE);
-       } else {
-               /* unmute internal speaker if necessary */
-               mute = snd_hda_codec_amp_read(codec, hp_nid, 0, HDA_OUTPUT, 0);
-               snd_hda_codec_amp_stereo(codec, sp_nid, HDA_OUTPUT, 0,
-                                        HDA_AMP_MUTE, mute);
-       }
+       snd_hda_codec_write(codec, sp_nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
+                           spec->jack_present ? 0 : PIN_OUT);
 }
 
 /* unsolicited event for HP jack sensing */
@@ -1319,11 +1318,19 @@ static struct snd_kcontrol_new alc880_f1734_mixer[] = {
        HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 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("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-       HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+       HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+       HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
        { } /* end */
 };
 
+static struct hda_input_mux alc880_f1734_capture_source = {
+       .num_items = 2,
+       .items = {
+               { "Mic", 0x1 },
+               { "CD", 0x4 },
+       },
+};
+
 
 /*
  * ALC880 ASUS model
@@ -1516,6 +1523,11 @@ static int alc_build_controls(struct hda_codec *codec)
                                                    spec->multiout.dig_out_nid);
                if (err < 0)
                        return err;
+               err = snd_hda_create_spdif_share_sw(codec,
+                                                   &spec->multiout);
+               if (err < 0)
+                       return err;
+               spec->multiout.share_spdif = 1;
        }
        if (spec->dig_in_nid) {
                err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
@@ -1525,10 +1537,11 @@ static int alc_build_controls(struct hda_codec *codec)
 
        /* if we have no master control, let's create it */
        if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
+               unsigned int vmaster_tlv[4];
                snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
-                                       HDA_OUTPUT, spec->vmaster_tlv);
+                                       HDA_OUTPUT, vmaster_tlv);
                err = snd_hda_add_vmaster(codec, "Master Playback Volume",
-                                         spec->vmaster_tlv, alc_slave_vols);
+                                         vmaster_tlv, alc_slave_vols);
                if (err < 0)
                        return err;
        }
@@ -1882,7 +1895,7 @@ static void alc880_uniwill_p53_hp_automute(struct hda_codec *codec)
        present = snd_hda_codec_read(codec, 0x14, 0,
                                     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
        bits = present ? HDA_AMP_MUTE : 0;
-       snd_hda_codec_amp_stereo(codec, 0x15, HDA_INPUT, 0, HDA_AMP_MUTE, bits);
+       snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, HDA_AMP_MUTE, bits);
 }
 
 static void alc880_uniwill_p53_dcvol_automute(struct hda_codec *codec)
@@ -1915,6 +1928,7 @@ static void alc880_uniwill_p53_unsol_event(struct hda_codec *codec,
  * HP = 0x14, speaker-out = 0x15, mic = 0x18
  */
 static struct hda_verb alc880_pin_f1734_init_verbs[] = {
+       {0x07, AC_VERB_SET_CONNECT_SEL, 0x01},
        {0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
        {0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
        {0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
@@ -1927,7 +1941,7 @@ static struct hda_verb alc880_pin_f1734_init_verbs[] = {
 
        {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
        {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-       {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+       {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
        {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
        {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
        {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
@@ -1935,6 +1949,9 @@ static struct hda_verb alc880_pin_f1734_init_verbs[] = {
        {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
        {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
 
+       {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT},
+       {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_DCVOL_EVENT},
+
        { }
 };
 
@@ -2318,7 +2335,8 @@ static int alc880_playback_pcm_open(struct hda_pcm_stream *hinfo,
                                    struct snd_pcm_substream *substream)
 {
        struct alc_spec *spec = codec->spec;
-       return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
+       return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
+                                            hinfo);
 }
 
 static int alc880_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
@@ -2392,8 +2410,8 @@ static int alc880_alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
 {
        struct alc_spec *spec = codec->spec;
 
-       snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1],
-                                  0, 0, 0);
+       snd_hda_codec_cleanup_stream(codec,
+                                    spec->adc_nids[substream->number + 1]);
        return 0;
 }
 
@@ -2498,6 +2516,7 @@ static int alc_build_pcms(struct hda_codec *codec)
                codec->num_pcms = 2;
                info = spec->pcm_rec + 1;
                info->name = spec->stream_name_digital;
+               info->pcm_type = HDA_PCM_TYPE_SPDIF;
                if (spec->multiout.dig_out_nid &&
                    spec->stream_digital_playback) {
                        info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_digital_playback);
@@ -2560,6 +2579,7 @@ static void alc_free(struct hda_codec *codec)
                kfree(spec->kctl_alloc);
        }
        kfree(spec);
+       codec->spec = NULL; /* to be sure */
 }
 
 /*
@@ -3057,7 +3077,9 @@ static struct alc_config_preset alc880_presets[] = {
                .hp_nid = 0x02,
                .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
                .channel_mode = alc880_2_jack_modes,
-               .input_mux = &alc880_capture_source,
+               .input_mux = &alc880_f1734_capture_source,
+               .unsol_event = alc880_uniwill_p53_unsol_event,
+               .init_hook = alc880_uniwill_p53_hp_automute,
        },
        [ALC880_ASUS] = {
                .mixers = { alc880_asus_mixer },
@@ -3467,15 +3489,21 @@ static int alc880_auto_create_analog_input_ctls(struct alc_spec *spec,
        return 0;
 }
 
-static void alc880_auto_set_output_and_unmute(struct hda_codec *codec,
-                                             hda_nid_t nid, int pin_type,
-                                             int dac_idx)
+static void alc_set_pin_output(struct hda_codec *codec, hda_nid_t nid,
+                              unsigned int pin_type)
 {
-       /* set as output */
        snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
                            pin_type);
+       /* unmute pin */
        snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
                            AMP_OUT_UNMUTE);
+}
+
+static void alc880_auto_set_output_and_unmute(struct hda_codec *codec,
+                                             hda_nid_t nid, int pin_type,
+                                             int dac_idx)
+{
+       alc_set_pin_output(codec, nid, pin_type);
        /* need the manual connection? */
        if (alc880_is_multi_pin(nid)) {
                struct alc_spec *spec = codec->spec;
@@ -3597,9 +3625,12 @@ static int alc880_parse_auto_config(struct hda_codec *codec)
 /* additional initialization for auto-configuration model */
 static void alc880_auto_init(struct hda_codec *codec)
 {
+       struct alc_spec *spec = codec->spec;
        alc880_auto_init_multi_out(codec);
        alc880_auto_init_extra_out(codec);
        alc880_auto_init_analog_input(codec);
+       if (spec->unsol_event)
+               alc_sku_automute(codec);
 }
 
 /*
@@ -4795,11 +4826,7 @@ static void alc260_auto_set_output_and_unmute(struct hda_codec *codec,
                                              hda_nid_t nid, int pin_type,
                                              int sel_idx)
 {
-       /* set as output */
-       snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
-                           pin_type);
-       snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
-                           AMP_OUT_UNMUTE);
+       alc_set_pin_output(codec, nid, pin_type);
        /* need the manual connection? */
        if (nid >= 0x12) {
                int idx = nid - 0x12;
@@ -4929,7 +4956,7 @@ static int alc260_parse_auto_config(struct hda_codec *codec)
        /* 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) {
+       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;
@@ -4946,8 +4973,11 @@ static int alc260_parse_auto_config(struct hda_codec *codec)
 /* additional initialization for auto-configuration model */
 static void alc260_auto_init(struct hda_codec *codec)
 {
+       struct alc_spec *spec = codec->spec;
        alc260_auto_init_multi_out(codec);
        alc260_auto_init_analog_input(codec);
+       if (spec->unsol_event)
+               alc_sku_automute(codec);
 }
 
 #ifdef CONFIG_SND_HDA_POWER_SAVE
@@ -5204,6 +5234,9 @@ static hda_nid_t alc882_dac_nids[4] = {
 #define alc882_adc_nids                alc880_adc_nids
 #define alc882_adc_nids_alt    alc880_adc_nids_alt
 
+static hda_nid_t alc882_capsrc_nids[3] = { 0x24, 0x23, 0x22 };
+static hda_nid_t alc882_capsrc_nids_alt[2] = { 0x23, 0x22 };
+
 /* input MUX */
 /* FIXME: should be a matrix-type input source selection */
 
@@ -5226,15 +5259,11 @@ static int alc882_mux_enum_put(struct snd_kcontrol *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);
-       static hda_nid_t capture_mixers[3] = { 0x24, 0x23, 0x22 };
-       hda_nid_t nid;
+       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;
 
-       if (spec->num_adc_nids < 3)
-               nid = capture_mixers[adc_idx + 1];
-       else
-               nid = capture_mixers[adc_idx];
        idx = ucontrol->value.enumerated.item[0];
        if (idx >= imux->num_items)
                idx = imux->num_items - 1;
@@ -6111,6 +6140,7 @@ static struct alc_config_preset alc882_presets[] = {
                .dig_out_nid = ALC882_DIGOUT_NID,
                .num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
                .adc_nids = alc882_adc_nids,
+               .capsrc_nids = alc882_capsrc_nids,
                .num_channel_mode = ARRAY_SIZE(alc882_3ST_6ch_modes),
                .channel_mode = alc882_3ST_6ch_modes,
                .need_dac_fix = 1,
@@ -6127,6 +6157,7 @@ static struct alc_config_preset alc882_presets[] = {
                .dig_out_nid = ALC882_DIGOUT_NID,
                .num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
                .adc_nids = alc882_adc_nids,
+               .capsrc_nids = alc882_capsrc_nids,
                .num_channel_mode = ARRAY_SIZE(alc882_3ST_6ch_modes),
                .channel_mode = alc882_3ST_6ch_modes,
                .need_dac_fix = 1,
@@ -6182,15 +6213,11 @@ static void alc882_auto_set_output_and_unmute(struct hda_codec *codec,
        struct alc_spec *spec = codec->spec;
        int idx;
 
+       alc_set_pin_output(codec, nid, pin_type);
        if (spec->multiout.dac_nids[dac_idx] == 0x25)
                idx = 4;
        else
                idx = spec->multiout.dac_nids[dac_idx] - 2;
-
-       snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
-                           pin_type);
-       snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
-                           AMP_OUT_UNMUTE);
        snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx);
 
 }
@@ -6219,6 +6246,9 @@ static void alc882_auto_init_hp_out(struct hda_codec *codec)
        if (pin) /* connect to front */
                /* use dac 0 */
                alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
+       pin = spec->autocfg.speaker_pins[0];
+       if (pin)
+               alc882_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
 }
 
 #define alc882_is_input_pin(nid)       alc880_is_input_pin(nid)
@@ -6231,16 +6261,21 @@ static void alc882_auto_init_analog_input(struct hda_codec *codec)
 
        for (i = 0; i < AUTO_PIN_LAST; i++) {
                hda_nid_t nid = spec->autocfg.input_pins[i];
-               if (alc882_is_input_pin(nid)) {
-                       snd_hda_codec_write(codec, nid, 0,
-                                           AC_VERB_SET_PIN_WIDGET_CONTROL,
-                                           i <= AUTO_PIN_FRONT_MIC ?
-                                           PIN_VREF80 : PIN_IN);
-                       if (nid != ALC882_PIN_CD_NID)
-                               snd_hda_codec_write(codec, nid, 0,
-                                                   AC_VERB_SET_AMP_GAIN_MUTE,
-                                                   AMP_OUT_MUTE);
+               unsigned int vref;
+               if (!nid)
+                       continue;
+               vref = PIN_IN;
+               if (1 /*i <= AUTO_PIN_FRONT_MIC*/) {
+                       if (snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP) &
+                           AC_PINCAP_VREF_80)
+                               vref = PIN_VREF80;
                }
+               snd_hda_codec_write(codec, nid, 0,
+                                   AC_VERB_SET_PIN_WIDGET_CONTROL, vref);
+               if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
+                       snd_hda_codec_write(codec, nid, 0,
+                                           AC_VERB_SET_AMP_GAIN_MUTE,
+                                           AMP_OUT_MUTE);
        }
 }
 
@@ -6294,11 +6329,16 @@ static int alc882_parse_auto_config(struct hda_codec *codec)
 /* additional initialization for auto-configuration model */
 static void alc882_auto_init(struct hda_codec *codec)
 {
+       struct alc_spec *spec = codec->spec;
        alc882_auto_init_multi_out(codec);
        alc882_auto_init_hp_out(codec);
        alc882_auto_init_analog_input(codec);
+       if (spec->unsol_event)
+               alc_sku_automute(codec);
 }
 
+static int patch_alc883(struct hda_codec *codec); /* called in patch_alc882() */
+
 static int patch_alc882(struct hda_codec *codec)
 {
        struct alc_spec *spec;
@@ -6328,6 +6368,11 @@ static int patch_alc882(struct hda_codec *codec)
                        board_config = ALC885_MBP3;
                        break;
                default:
+                       /* ALC889A is handled better as ALC888-compatible */
+                       if (codec->revision_id == 0x100103) {
+                               alc_free(codec);
+                               return patch_alc883(codec);
+                       }
                        printk(KERN_INFO "hda_codec: Unknown model for ALC882, "
                                         "trying auto-probe from BIOS...\n");
                        board_config = ALC882_AUTO;
@@ -6372,12 +6417,14 @@ static int patch_alc882(struct hda_codec *codec)
                if (wcap != AC_WID_AUD_IN) {
                        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++;
                }
@@ -6412,7 +6459,7 @@ static int patch_alc882(struct hda_codec *codec)
 
 static hda_nid_t alc883_dac_nids[4] = {
        /* front, rear, clfe, rear_surr */
-       0x02, 0x04, 0x03, 0x05
+       0x02, 0x03, 0x04, 0x05
 };
 
 static hda_nid_t alc883_adc_nids[2] = {
@@ -6420,6 +6467,8 @@ static hda_nid_t alc883_adc_nids[2] = {
        0x08, 0x09,
 };
 
+static hda_nid_t alc883_capsrc_nids[2] = { 0x23, 0x22 };
+
 /* input MUX */
 /* FIXME: should be a matrix-type input source selection */
 
@@ -6451,35 +6500,18 @@ static struct hda_input_mux alc883_lenovo_nb0763_capture_source = {
        },
 };
 
+static struct hda_input_mux alc883_fujitsu_pi2515_capture_source = {
+       .num_items = 2,
+       .items = {
+               { "Mic", 0x0 },
+               { "Int Mic", 0x1 },
+       },
+};
+
 #define alc883_mux_enum_info alc_mux_enum_info
 #define alc883_mux_enum_get alc_mux_enum_get
-
-static int alc883_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);
-       static hda_nid_t capture_mixers[2] = { 0x23, 0x22 };
-       hda_nid_t nid = capture_mixers[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;
-}
+/* ALC883 has the ALC882-type input selection */
+#define alc883_mux_enum_put alc882_mux_enum_put
 
 /*
  * 2ch mode
@@ -6638,6 +6670,60 @@ static struct snd_kcontrol_new alc883_mitac_mixer[] = {
        { } /* end */
 };
 
+static struct snd_kcontrol_new alc883_clevo_m720_mixer[] = {
+       HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+       HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
+       HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+       HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, 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("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 */
+};
+
+static struct snd_kcontrol_new alc883_2ch_fujitsu_pi2515_mixer[] = {
+       HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+       HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
+       HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+       HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, 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("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 */
+};
+
 static struct snd_kcontrol_new alc883_3ST_2ch_mixer[] = {
        HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
        HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
@@ -6787,6 +6873,9 @@ static struct snd_kcontrol_new alc883_tagra_2ch_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("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),
@@ -6878,68 +6967,15 @@ static struct snd_kcontrol_new alc883_medion_md2_mixer[] = {
        { } /* end */
 };     
 
-static struct snd_kcontrol_new alc888_6st_hp_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", 0x0e, 0x0, HDA_OUTPUT),
-       HDA_BIND_MUTE("Surround Playback Switch", 0x0e, 2, HDA_INPUT),
-       HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT),
-       HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT),
-       HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT),
-       HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 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_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
-       HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-       HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-       HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-       HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-       HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-       HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
-       HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-       HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-       HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
-       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 */
-};
-
-static struct snd_kcontrol_new alc888_3st_hp_mixer[] = {
+static struct snd_kcontrol_new alc883_acer_aspire_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", 0x0e, 0x0, HDA_OUTPUT),
-       HDA_BIND_MUTE("Surround Playback Switch", 0x0e, 2, HDA_INPUT),
-       HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT),
-       HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT),
-       HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT),
-       HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT),
-       HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
-       HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-       HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+       HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
        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("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("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),
@@ -6956,78 +6992,13 @@ static struct snd_kcontrol_new alc888_3st_hp_mixer[] = {
        { } /* end */
 };
 
-static struct snd_kcontrol_new alc888_6st_dell_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", 0x0e, 0x0, HDA_OUTPUT),
-       HDA_BIND_MUTE("Surround Playback Switch", 0x0e, 2, HDA_INPUT),
-       HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT),
-       HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT),
-       HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT),
-       HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 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_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
-       HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-       HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-       HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-       HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-       HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-       HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
-       HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-       HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-       HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
-       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),
+static struct snd_kcontrol_new alc883_chmode_mixer[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-               /* .name = "Capture Source", */
-               .name = "Input Source",
-               .count = 2,
-               .info = alc883_mux_enum_info,
-               .get = alc883_mux_enum_get,
-               .put = alc883_mux_enum_put,
-       },
-       { } /* end */
-};
-
-static struct snd_kcontrol_new alc883_acer_aspire_mixer[] = {
-       HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-       HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-       HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
-       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("Capture Volume", 0x08, 0x0, HDA_INPUT),
-       HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
-       HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
-       HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
-       {
-               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-               /* .name = "Capture Source", */
-               .name = "Input Source",
-               .count = 2,
-               .info = alc883_mux_enum_info,
-               .get = alc883_mux_enum_get,
-               .put = alc883_mux_enum_put,
-       },
-       { } /* end */
-};
-
-static struct snd_kcontrol_new alc883_chmode_mixer[] = {
-       {
-               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-               .name = "Channel Mode",
-               .info = alc_ch_mode_info,
-               .get = alc_ch_mode_get,
-               .put = alc_ch_mode_put,
+               .name = "Channel Mode",
+               .info = alc_ch_mode_info,
+               .get = alc_ch_mode_get,
+               .put = alc_ch_mode_put,
        },
        { } /* end */
 };
@@ -7171,6 +7142,35 @@ static struct hda_verb alc883_mitac_verbs[] = {
        { } /* end */
 };
 
+static struct hda_verb alc883_clevo_m720_verbs[] = {
+       /* HP */
+       {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
+       {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+       /* Int speaker */
+       {0x14, AC_VERB_SET_CONNECT_SEL, 0x01},
+       {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+
+       /* enable unsolicited event */
+       {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
+       {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
+
+       { } /* end */
+};
+
+static struct hda_verb alc883_2ch_fujitsu_pi2515_verbs[] = {
+       /* HP */
+       {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
+       {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+       /* Subwoofer */
+       {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
+       {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+
+       /* enable unsolicited event */
+       {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
+
+       { } /* end */
+};
+
 static struct hda_verb alc883_tagra_verbs[] = {
        {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
        {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
@@ -7227,26 +7227,14 @@ static struct hda_verb alc883_haier_w66_verbs[] = {
        { } /* end */
 };
 
-static struct hda_verb alc888_6st_hp_verbs[] = {
-       {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},  /* Front: output 0 (0x0c) */
-       {0x15, AC_VERB_SET_CONNECT_SEL, 0x02},  /* Rear : output 2 (0x0e) */
-       {0x16, AC_VERB_SET_CONNECT_SEL, 0x01},  /* CLFE : output 1 (0x0d) */
-       {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},  /* Side : output 3 (0x0f) */
-       { }
-};
-
 static struct hda_verb alc888_3st_hp_verbs[] = {
        {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},  /* Front: output 0 (0x0c) */
-       {0x18, AC_VERB_SET_CONNECT_SEL, 0x01},  /* Rear : output 1 (0x0d) */
-       {0x16, AC_VERB_SET_CONNECT_SEL, 0x02},  /* CLFE : output 2 (0x0e) */
+       {0x16, AC_VERB_SET_CONNECT_SEL, 0x01},  /* Rear : output 1 (0x0d) */
+       {0x18, AC_VERB_SET_CONNECT_SEL, 0x02},  /* CLFE : output 2 (0x0e) */
        { }
 };
 
 static struct hda_verb alc888_6st_dell_verbs[] = {
-       {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},  /* Front: output 0 (0x0c) */
-       {0x15, AC_VERB_SET_CONNECT_SEL, 0x02},  /* Rear : output 1 (0x0e) */
-       {0x16, AC_VERB_SET_CONNECT_SEL, 0x01},  /* CLFE : output 2 (0x0d) */
-       {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},  /* Side : output 3 (0x0f) */
        {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
        { }
 };
@@ -7354,6 +7342,68 @@ static void alc883_tagra_unsol_event(struct hda_codec *codec, unsigned int res)
                alc883_tagra_automute(codec);
 }
 
+/* toggle speaker-output according to the hp-jack state */
+static void alc883_clevo_m720_hp_automute(struct hda_codec *codec)
+{
+       unsigned int present;
+       unsigned char bits;
+
+       present = snd_hda_codec_read(codec, 0x15, 0, AC_VERB_GET_PIN_SENSE, 0)
+               & AC_PINSENSE_PRESENCE;
+       bits = present ? HDA_AMP_MUTE : 0;
+       snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
+                                HDA_AMP_MUTE, bits);
+}
+
+static void alc883_clevo_m720_mic_automute(struct hda_codec *codec)
+{
+       unsigned int present;
+
+       present = snd_hda_codec_read(codec, 0x18, 0,
+                                    AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+       snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1,
+                                HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
+}
+
+static void alc883_clevo_m720_automute(struct hda_codec *codec)
+{
+       alc883_clevo_m720_hp_automute(codec);
+       alc883_clevo_m720_mic_automute(codec);
+}
+
+static void alc883_clevo_m720_unsol_event(struct hda_codec *codec,
+                                          unsigned int res)
+{
+       switch (res >> 26) {
+       case ALC880_HP_EVENT:
+               alc883_clevo_m720_hp_automute(codec);
+               break;
+       case ALC880_MIC_EVENT:
+               alc883_clevo_m720_mic_automute(codec);
+               break;
+       }
+}
+
+/* toggle speaker-output according to the hp-jack state */
+static void alc883_2ch_fujitsu_pi2515_automute(struct hda_codec *codec)
+{
+       unsigned int present;
+       unsigned char bits;
+
+       present = snd_hda_codec_read(codec, 0x14, 0, AC_VERB_GET_PIN_SENSE, 0)
+               & AC_PINSENSE_PRESENCE;
+       bits = present ? HDA_AMP_MUTE : 0;
+       snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
+                                HDA_AMP_MUTE, bits);
+}
+
+static void alc883_2ch_fujitsu_pi2515_unsol_event(struct hda_codec *codec,
+                                                 unsigned int res)
+{
+       if ((res >> 26) == ALC880_HP_EVENT)
+               alc883_2ch_fujitsu_pi2515_automute(codec);
+}
+
 static void alc883_haier_w66_automute(struct hda_codec *codec)
 {
        unsigned int present;
@@ -7587,10 +7637,11 @@ static const char *alc883_models[ALC883_MODEL_LAST] = {
        [ALC883_LENOVO_NB0763]  = "lenovo-nb0763",
        [ALC888_LENOVO_MS7195_DIG] = "lenovo-ms7195-dig",
        [ALC883_HAIER_W66]      = "haier-w66",
-       [ALC888_6ST_HP]         = "6stack-hp",
        [ALC888_3ST_HP]         = "3stack-hp",
        [ALC888_6ST_DELL]       = "6stack-dell",
        [ALC883_MITAC]          = "mitac",
+       [ALC883_CLEVO_M720]     = "clevo-m720",
+       [ALC883_FUJITSU_PI2515] = "fujitsu-pi2515",
        [ALC883_AUTO]           = "auto",
 };
 
@@ -7604,7 +7655,7 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x2a3d, "HP Pavillion", ALC883_6ST_DIG),
        SND_PCI_QUIRK(0x103c, 0x2a4f, "HP Samba", ALC888_3ST_HP),
        SND_PCI_QUIRK(0x103c, 0x2a60, "HP Lucknow", ALC888_3ST_HP),
-       SND_PCI_QUIRK(0x103c, 0x2a61, "HP Nettle", ALC888_6ST_HP),
+       SND_PCI_QUIRK(0x103c, 0x2a61, "HP Nettle", ALC883_6ST_DIG),
        SND_PCI_QUIRK(0x1043, 0x8249, "Asus M2A-VM HDMI", ALC883_3ST_6ch_DIG),
        SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC883_6ST_DIG),
        SND_PCI_QUIRK(0x1071, 0x8253, "Mitac 8252d", ALC883_MITAC),
@@ -7614,7 +7665,9 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
        SND_PCI_QUIRK(0x1462, 0x0349, "MSI", ALC883_TARGA_2ch_DIG),
        SND_PCI_QUIRK(0x1462, 0x040d, "MSI", ALC883_TARGA_2ch_DIG),
        SND_PCI_QUIRK(0x1462, 0x0579, "MSI", ALC883_TARGA_2ch_DIG),
+       SND_PCI_QUIRK(0x1462, 0x2fb3, "MSI", ALC883_TARGA_2ch_DIG),
        SND_PCI_QUIRK(0x1462, 0x3729, "MSI S420", ALC883_TARGA_DIG),
+       SND_PCI_QUIRK(0x1462, 0x3783, "NEC S970", ALC883_TARGA_DIG),
        SND_PCI_QUIRK(0x1462, 0x3b7f, "MSI", ALC883_TARGA_2ch_DIG),
        SND_PCI_QUIRK(0x1462, 0x3ef9, "MSI", ALC883_TARGA_DIG),
        SND_PCI_QUIRK(0x1462, 0x3fc1, "MSI", ALC883_TARGA_DIG),
@@ -7627,13 +7680,17 @@ 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, 0x7267, "MSI", ALC883_3ST_6ch_DIG),
        SND_PCI_QUIRK(0x1462, 0x7280, "MSI", ALC883_6ST_DIG),
        SND_PCI_QUIRK(0x1462, 0x7327, "MSI", ALC883_6ST_DIG),
        SND_PCI_QUIRK(0x1462, 0xa422, "MSI", ALC883_TARGA_2ch_DIG),
        SND_PCI_QUIRK(0x147b, 0x1083, "Abit IP35-PRO", ALC883_6ST_DIG),
+       SND_PCI_QUIRK(0x1558, 0x0721, "Clevo laptop M720R", ALC883_CLEVO_M720),
+       SND_PCI_QUIRK(0x1558, 0x0722, "Clevo laptop M720SR", ALC883_CLEVO_M720),
        SND_PCI_QUIRK(0x1558, 0, "Clevo laptop", ALC883_LAPTOP_EAPD),
        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(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),
@@ -7652,8 +7709,6 @@ static struct alc_config_preset alc883_presets[] = {
                .num_dacs = ARRAY_SIZE(alc883_dac_nids),
                .dac_nids = alc883_dac_nids,
                .dig_out_nid = ALC883_DIGOUT_NID,
-               .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-               .adc_nids = alc883_adc_nids,
                .dig_in_nid = ALC883_DIGIN_NID,
                .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
                .channel_mode = alc883_3ST_2ch_modes,
@@ -7665,8 +7720,6 @@ static struct alc_config_preset alc883_presets[] = {
                .num_dacs = ARRAY_SIZE(alc883_dac_nids),
                .dac_nids = alc883_dac_nids,
                .dig_out_nid = ALC883_DIGOUT_NID,
-               .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-               .adc_nids = alc883_adc_nids,
                .dig_in_nid = ALC883_DIGIN_NID,
                .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
                .channel_mode = alc883_3ST_6ch_modes,
@@ -7678,8 +7731,6 @@ static struct alc_config_preset alc883_presets[] = {
                .init_verbs = { alc883_init_verbs },
                .num_dacs = ARRAY_SIZE(alc883_dac_nids),
                .dac_nids = alc883_dac_nids,
-               .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-               .adc_nids = alc883_adc_nids,
                .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
                .channel_mode = alc883_3ST_6ch_modes,
                .need_dac_fix = 1,
@@ -7691,8 +7742,6 @@ static struct alc_config_preset alc883_presets[] = {
                .num_dacs = ARRAY_SIZE(alc883_dac_nids),
                .dac_nids = alc883_dac_nids,
                .dig_out_nid = ALC883_DIGOUT_NID,
-               .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-               .adc_nids = alc883_adc_nids,
                .dig_in_nid = ALC883_DIGIN_NID,
                .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
                .channel_mode = alc883_sixstack_modes,
@@ -7704,8 +7753,6 @@ static struct alc_config_preset alc883_presets[] = {
                .num_dacs = ARRAY_SIZE(alc883_dac_nids),
                .dac_nids = alc883_dac_nids,
                .dig_out_nid = ALC883_DIGOUT_NID,
-               .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-               .adc_nids = alc883_adc_nids,
                .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
                .channel_mode = alc883_3ST_6ch_modes,
                .need_dac_fix = 1,
@@ -7719,8 +7766,6 @@ static struct alc_config_preset alc883_presets[] = {
                .num_dacs = ARRAY_SIZE(alc883_dac_nids),
                .dac_nids = alc883_dac_nids,
                .dig_out_nid = ALC883_DIGOUT_NID,
-               .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-               .adc_nids = alc883_adc_nids,
                .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
                .channel_mode = alc883_3ST_2ch_modes,
                .input_mux = &alc883_capture_source,
@@ -7737,8 +7782,6 @@ static struct alc_config_preset alc883_presets[] = {
                .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs },
                .num_dacs = ARRAY_SIZE(alc883_dac_nids),
                .dac_nids = alc883_dac_nids,
-               .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-               .adc_nids = alc883_adc_nids,
                .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
                .channel_mode = alc883_3ST_2ch_modes,
                .input_mux = &alc883_capture_source,
@@ -7749,8 +7792,6 @@ static struct alc_config_preset alc883_presets[] = {
                .num_dacs = ARRAY_SIZE(alc883_dac_nids),
                .dac_nids = alc883_dac_nids,
                .dig_out_nid = ALC883_DIGOUT_NID,
-               .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-               .adc_nids = alc883_adc_nids,
                .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
                .channel_mode = alc883_3ST_2ch_modes,
                .input_mux = &alc883_capture_source,
@@ -7764,8 +7805,6 @@ static struct alc_config_preset alc883_presets[] = {
                                alc883_medion_eapd_verbs },
                .num_dacs = ARRAY_SIZE(alc883_dac_nids),
                .dac_nids = alc883_dac_nids,
-               .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-               .adc_nids = alc883_adc_nids,
                .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
                .channel_mode = alc883_sixstack_modes,
                .input_mux = &alc883_capture_source,
@@ -7776,8 +7815,6 @@ static struct alc_config_preset alc883_presets[] = {
                .num_dacs = ARRAY_SIZE(alc883_dac_nids),
                .dac_nids = alc883_dac_nids,
                .dig_out_nid = ALC883_DIGOUT_NID,
-               .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-               .adc_nids = alc883_adc_nids,
                .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
                .channel_mode = alc883_3ST_2ch_modes,
                .input_mux = &alc883_capture_source,
@@ -7789,19 +7826,27 @@ static struct alc_config_preset alc883_presets[] = {
                .init_verbs = { alc883_init_verbs, alc882_eapd_verbs },
                .num_dacs = ARRAY_SIZE(alc883_dac_nids),
                .dac_nids = alc883_dac_nids,
-               .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-               .adc_nids = alc883_adc_nids,
                .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
                .channel_mode = alc883_3ST_2ch_modes,
                .input_mux = &alc883_capture_source,
        },
+       [ALC883_CLEVO_M720] = {
+               .mixers = { alc883_clevo_m720_mixer },
+               .init_verbs = { alc883_init_verbs, alc883_clevo_m720_verbs },
+               .num_dacs = ARRAY_SIZE(alc883_dac_nids),
+               .dac_nids = alc883_dac_nids,
+               .dig_out_nid = ALC883_DIGOUT_NID,
+               .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+               .channel_mode = alc883_3ST_2ch_modes,
+               .input_mux = &alc883_capture_source,
+               .unsol_event = alc883_clevo_m720_unsol_event,
+               .init_hook = alc883_clevo_m720_automute,
+       },
        [ALC883_LENOVO_101E_2ch] = {
                .mixers = { alc883_lenovo_101e_2ch_mixer},
                .init_verbs = { alc883_init_verbs, alc883_lenovo_101e_verbs},
                .num_dacs = ARRAY_SIZE(alc883_dac_nids),
                .dac_nids = alc883_dac_nids,
-               .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-               .adc_nids = alc883_adc_nids,
                .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
                .channel_mode = alc883_3ST_2ch_modes,
                .input_mux = &alc883_lenovo_101e_capture_source,
@@ -7813,8 +7858,6 @@ static struct alc_config_preset alc883_presets[] = {
                .init_verbs = { alc883_init_verbs, alc883_lenovo_nb0763_verbs},
                .num_dacs = ARRAY_SIZE(alc883_dac_nids),
                .dac_nids = alc883_dac_nids,
-               .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-               .adc_nids = alc883_adc_nids,
                .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
                .channel_mode = alc883_3ST_2ch_modes,
                .need_dac_fix = 1,
@@ -7828,8 +7871,6 @@ static struct alc_config_preset alc883_presets[] = {
                .num_dacs = ARRAY_SIZE(alc883_dac_nids),
                .dac_nids = alc883_dac_nids,
                .dig_out_nid = ALC883_DIGOUT_NID,
-               .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-               .adc_nids = alc883_adc_nids,
                .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
                .channel_mode = alc883_3ST_6ch_modes,
                .need_dac_fix = 1,
@@ -7843,47 +7884,28 @@ static struct alc_config_preset alc883_presets[] = {
                .num_dacs = ARRAY_SIZE(alc883_dac_nids),
                .dac_nids = alc883_dac_nids,
                .dig_out_nid = ALC883_DIGOUT_NID,
-               .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-               .adc_nids = alc883_adc_nids,
                .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
                .channel_mode = alc883_3ST_2ch_modes,
                .input_mux = &alc883_capture_source,
                .unsol_event = alc883_haier_w66_unsol_event,
                .init_hook = alc883_haier_w66_automute,
-       },      
-       [ALC888_6ST_HP] = {
-               .mixers = { alc888_6st_hp_mixer, alc883_chmode_mixer },
-               .init_verbs = { alc883_init_verbs, alc888_6st_hp_verbs },
-               .num_dacs = ARRAY_SIZE(alc883_dac_nids),
-               .dac_nids = alc883_dac_nids,
-               .dig_out_nid = ALC883_DIGOUT_NID,
-               .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-               .adc_nids = alc883_adc_nids,
-               .dig_in_nid = ALC883_DIGIN_NID,
-               .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
-               .channel_mode = alc883_sixstack_modes,
-               .input_mux = &alc883_capture_source,
        },
        [ALC888_3ST_HP] = {
-               .mixers = { alc888_3st_hp_mixer, alc883_chmode_mixer },
+               .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
                .init_verbs = { alc883_init_verbs, alc888_3st_hp_verbs },
                .num_dacs = ARRAY_SIZE(alc883_dac_nids),
                .dac_nids = alc883_dac_nids,
-               .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-               .adc_nids = alc883_adc_nids,
                .num_channel_mode = ARRAY_SIZE(alc888_3st_hp_modes),
                .channel_mode = alc888_3st_hp_modes,
                .need_dac_fix = 1,
                .input_mux = &alc883_capture_source,
        },
        [ALC888_6ST_DELL] = {
-               .mixers = { alc888_6st_dell_mixer, alc883_chmode_mixer },
+               .mixers = { alc883_base_mixer, alc883_chmode_mixer },
                .init_verbs = { alc883_init_verbs, alc888_6st_dell_verbs },
                .num_dacs = ARRAY_SIZE(alc883_dac_nids),
                .dac_nids = alc883_dac_nids,
                .dig_out_nid = ALC883_DIGOUT_NID,
-               .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-               .adc_nids = alc883_adc_nids,
                .dig_in_nid = ALC883_DIGIN_NID,
                .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
                .channel_mode = alc883_sixstack_modes,
@@ -7896,14 +7918,25 @@ static struct alc_config_preset alc883_presets[] = {
                .init_verbs = { alc883_init_verbs, alc883_mitac_verbs },
                .num_dacs = ARRAY_SIZE(alc883_dac_nids),
                .dac_nids = alc883_dac_nids,
-               .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-               .adc_nids = alc883_adc_nids,
                .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
                .channel_mode = alc883_3ST_2ch_modes,
                .input_mux = &alc883_capture_source,
                .unsol_event = alc883_mitac_unsol_event,
                .init_hook = alc883_mitac_automute,
        },
+       [ALC883_FUJITSU_PI2515] = {
+               .mixers = { alc883_2ch_fujitsu_pi2515_mixer },
+               .init_verbs = { alc883_init_verbs,
+                               alc883_2ch_fujitsu_pi2515_verbs},
+               .num_dacs = ARRAY_SIZE(alc883_dac_nids),
+               .dac_nids = alc883_dac_nids,
+               .dig_out_nid = ALC883_DIGOUT_NID,
+               .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+               .channel_mode = alc883_3ST_2ch_modes,
+               .input_mux = &alc883_fujitsu_pi2515_capture_source,
+               .unsol_event = alc883_2ch_fujitsu_pi2515_unsol_event,
+               .init_hook = alc883_2ch_fujitsu_pi2515_automute,
+       },
 };
 
 
@@ -7918,15 +7951,11 @@ static void alc883_auto_set_output_and_unmute(struct hda_codec *codec,
        struct alc_spec *spec = codec->spec;
        int idx;
 
+       alc_set_pin_output(codec, nid, pin_type);
        if (spec->multiout.dac_nids[dac_idx] == 0x25)
                idx = 4;
        else
                idx = spec->multiout.dac_nids[dac_idx] - 2;
-
-       snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
-                           pin_type);
-       snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
-                           AMP_OUT_UNMUTE);
        snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx);
 
 }
@@ -7955,6 +7984,9 @@ static void alc883_auto_init_hp_out(struct hda_codec *codec)
        if (pin) /* connect to front */
                /* use dac 0 */
                alc883_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
+       pin = spec->autocfg.speaker_pins[0];
+       if (pin)
+               alc883_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
 }
 
 #define alc883_is_input_pin(nid)       alc880_is_input_pin(nid)
@@ -8006,9 +8038,12 @@ static int alc883_parse_auto_config(struct hda_codec *codec)
 /* additional initialization for auto-configuration model */
 static void alc883_auto_init(struct hda_codec *codec)
 {
+       struct alc_spec *spec = codec->spec;
        alc883_auto_init_multi_out(codec);
        alc883_auto_init_hp_out(codec);
        alc883_auto_init_analog_input(codec);
+       if (spec->unsol_event)
+               alc_sku_automute(codec);
 }
 
 static int patch_alc883(struct hda_codec *codec)
@@ -8057,10 +8092,9 @@ static int patch_alc883(struct hda_codec *codec)
        spec->stream_digital_playback = &alc883_pcm_digital_playback;
        spec->stream_digital_capture = &alc883_pcm_digital_capture;
 
-       if (!spec->adc_nids && spec->input_mux) {
-               spec->adc_nids = alc883_adc_nids;
-               spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids);
-       }
+       spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids);
+       spec->adc_nids = alc883_adc_nids;
+       spec->capsrc_nids = alc883_capsrc_nids;
 
        spec->vmaster_nid = 0x0c;
 
@@ -8085,6 +8119,8 @@ static int patch_alc883(struct hda_codec *codec)
 #define alc262_dac_nids                alc260_dac_nids
 #define alc262_adc_nids                alc882_adc_nids
 #define alc262_adc_nids_alt    alc882_adc_nids_alt
+#define alc262_capsrc_nids     alc882_capsrc_nids
+#define alc262_capsrc_nids_alt alc882_capsrc_nids_alt
 
 #define alc262_modes           alc260_modes
 #define alc262_capture_source  alc882_capture_source
@@ -8585,7 +8621,8 @@ static void alc262_hippo1_unsol_event(struct hda_codec *codec,
 
 /*
  * fujitsu model
- *  0x14 = headphone/spdif-out, 0x15 = internal speaker
+ *  0x14 = headphone/spdif-out, 0x15 = internal speaker,
+ *  0x1b = port replicator headphone out
  */
 
 #define ALC_HP_EVENT   0x37
@@ -8593,6 +8630,14 @@ static void alc262_hippo1_unsol_event(struct hda_codec *codec,
 static struct hda_verb alc262_fujitsu_unsol_verbs[] = {
        {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
        {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+       {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+       {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+       {}
+};
+
+static struct hda_verb alc262_lenovo_3000_unsol_verbs[] = {
+       {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+       {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
        {}
 };
 
@@ -8633,12 +8678,16 @@ static void alc262_fujitsu_automute(struct hda_codec *codec, int force)
        unsigned int mute;
 
        if (force || !spec->sense_updated) {
-               unsigned int present;
+               unsigned int present_int_hp, present_dock_hp;
                /* need to execute and sync at first */
                snd_hda_codec_read(codec, 0x14, 0, AC_VERB_SET_PIN_SENSE, 0);
-               present = snd_hda_codec_read(codec, 0x14, 0,
-                                        AC_VERB_GET_PIN_SENSE, 0);
-               spec->jack_present = (present & 0x80000000) != 0;
+               present_int_hp = snd_hda_codec_read(codec, 0x14, 0,
+                                       AC_VERB_GET_PIN_SENSE, 0);
+               snd_hda_codec_read(codec, 0x1B, 0, AC_VERB_SET_PIN_SENSE, 0);
+               present_dock_hp = snd_hda_codec_read(codec, 0x1b, 0,
+                                       AC_VERB_GET_PIN_SENSE, 0);
+               spec->jack_present = (present_int_hp & 0x80000000) != 0;
+               spec->jack_present |= (present_dock_hp & 0x80000000) != 0;
                spec->sense_updated = 1;
        }
        if (spec->jack_present) {
@@ -8672,6 +8721,46 @@ static struct hda_bind_ctls alc262_fujitsu_bind_master_vol = {
        },
 };
 
+/* mute/unmute internal speaker according to the hp jack and mute state */
+static void alc262_lenovo_3000_automute(struct hda_codec *codec, int force)
+{
+       struct alc_spec *spec = codec->spec;
+       unsigned int mute;
+
+       if (force || !spec->sense_updated) {
+               unsigned int present_int_hp;
+               /* need to execute and sync at first */
+               snd_hda_codec_read(codec, 0x1b, 0, AC_VERB_SET_PIN_SENSE, 0);
+               present_int_hp = snd_hda_codec_read(codec, 0x1b, 0,
+                                       AC_VERB_GET_PIN_SENSE, 0);
+               spec->jack_present = (present_int_hp & 0x80000000) != 0;
+               spec->sense_updated = 1;
+       }
+       if (spec->jack_present) {
+               /* mute internal speaker */
+               snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
+                                        HDA_AMP_MUTE, HDA_AMP_MUTE);
+               snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
+                                        HDA_AMP_MUTE, HDA_AMP_MUTE);
+       } else {
+               /* unmute internal speaker if necessary */
+               mute = snd_hda_codec_amp_read(codec, 0x1b, 0, HDA_OUTPUT, 0);
+               snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
+                                        HDA_AMP_MUTE, mute);
+               snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
+                                        HDA_AMP_MUTE, mute);
+       }
+}
+
+/* unsolicited event for HP jack sensing */
+static void alc262_lenovo_3000_unsol_event(struct hda_codec *codec,
+                                      unsigned int res)
+{
+       if ((res >> 26) != ALC_HP_EVENT)
+               return;
+       alc262_lenovo_3000_automute(codec, 1);
+}
+
 /* bind hp and internal speaker mute (with plug check) */
 static int alc262_fujitsu_master_sw_put(struct snd_kcontrol *kcontrol,
                                         struct snd_ctl_elem_value *ucontrol)
@@ -8680,12 +8769,13 @@ static int alc262_fujitsu_master_sw_put(struct snd_kcontrol *kcontrol,
        long *valp = ucontrol->value.integer.value;
        int change;
 
-       change = snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
-                                         HDA_AMP_MUTE,
-                                         valp[0] ? 0 : HDA_AMP_MUTE);
-       change |= snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
-                                          HDA_AMP_MUTE,
-                                          valp[1] ? 0 : HDA_AMP_MUTE);
+       change = snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
+                                                HDA_AMP_MUTE,
+                                                valp ? 0 : HDA_AMP_MUTE);
+       change |= snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,
+                                                HDA_AMP_MUTE,
+                                                valp ? 0 : HDA_AMP_MUTE);
+
        if (change)
                alc262_fujitsu_automute(codec, 0);
        return change;
@@ -8703,6 +8793,46 @@ static struct snd_kcontrol_new alc262_fujitsu_mixer[] = {
        },
        HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
        HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+       HDA_CODEC_VOLUME("PC Speaker Volume", 0x0b, 0x05, HDA_INPUT),
+       HDA_CODEC_MUTE("PC Speaker Switch", 0x0b, 0x05, HDA_INPUT),
+       HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
+       HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+       HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+       HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
+       HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+       HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+       { } /* end */
+};
+
+/* bind hp and internal speaker mute (with plug check) */
+static int alc262_lenovo_3000_master_sw_put(struct snd_kcontrol *kcontrol,
+                                        struct snd_ctl_elem_value *ucontrol)
+{
+       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+       long *valp = ucontrol->value.integer.value;
+       int change;
+
+       change = snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,
+                                                HDA_AMP_MUTE,
+                                                valp ? 0 : HDA_AMP_MUTE);
+
+       if (change)
+               alc262_lenovo_3000_automute(codec, 0);
+       return change;
+}
+
+static struct snd_kcontrol_new alc262_lenovo_3000_mixer[] = {
+       HDA_BIND_VOL("Master Playback Volume", &alc262_fujitsu_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 = alc262_lenovo_3000_master_sw_put,
+               .private_value = HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
+       },
+       HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+       HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
        HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
        HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
        HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
@@ -8730,59 +8860,72 @@ static struct hda_verb alc262_benq_t31_EAPD_verbs[] = {
 
 /* Samsung Q1 Ultra Vista model setup */
 static struct snd_kcontrol_new alc262_ultra_mixer[] = {
-       HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+       HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT),
        HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
        HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
        HDA_CODEC_VOLUME("Mic Boost", 0x19, 0, HDA_INPUT),
+       HDA_CODEC_VOLUME("Headphone Mic Boost", 0x15, 0, HDA_INPUT),
        { } /* end */
 };
 
 static struct hda_verb alc262_ultra_verbs[] = {
-       {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
+       /* output mixer */
+       {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+       {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+       {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+       /* speaker */
+       {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+       {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+       {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+       {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
+       /* HP */
        {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-       {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
-       /* Mic is on Node 0x19 */
-       {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
-       {0x22, AC_VERB_SET_CONNECT_SEL, 0x01},
-       {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
-       {0x23, AC_VERB_SET_CONNECT_SEL, 0x01},
-       {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
-       {0x24, AC_VERB_SET_CONNECT_SEL, 0x01},
-       {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+       {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+       {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+       {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
+       {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
+       /* internal mic */
+       {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+       {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+       /* ADC, choose mic */
+       {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+       {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+       {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+       {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+       {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+       {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+       {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
+       {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
+       {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
+       {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(8)},
        {}
 };
 
-static struct hda_input_mux alc262_ultra_capture_source = {
-       .num_items = 1,
-       .items = {
-               { "Mic", 0x1 },
-       },
-};
-
 /* mute/unmute internal speaker according to the hp jack and mute state */
 static void alc262_ultra_automute(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
        unsigned int mute;
-       unsigned int present;
 
-       /* need to execute and sync at first */
-       snd_hda_codec_read(codec, 0x15, 0, AC_VERB_SET_PIN_SENSE, 0);
-       present = snd_hda_codec_read(codec, 0x15, 0,
-                                    AC_VERB_GET_PIN_SENSE, 0);
-       spec->jack_present = (present & 0x80000000) != 0;
-       if (spec->jack_present) {
-               /* mute internal speaker */
-               snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
-                                        HDA_AMP_MUTE, HDA_AMP_MUTE);
-       } else {
-               /* unmute internal speaker if necessary */
-               mute = snd_hda_codec_amp_read(codec, 0x15, 0, HDA_OUTPUT, 0);
-               snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
-                                        HDA_AMP_MUTE, mute);
+       mute = 0;
+       /* auto-mute only when HP is used as HP */
+       if (!spec->cur_mux[0]) {
+               unsigned int present;
+               /* need to execute and sync at first */
+               snd_hda_codec_read(codec, 0x15, 0, AC_VERB_SET_PIN_SENSE, 0);
+               present = snd_hda_codec_read(codec, 0x15, 0,
+                                            AC_VERB_GET_PIN_SENSE, 0);
+               spec->jack_present = (present & AC_PINSENSE_PRESENCE) != 0;
+               if (spec->jack_present)
+                       mute = HDA_AMP_MUTE;
        }
+       /* mute/unmute internal speaker */
+       snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
+                                HDA_AMP_MUTE, mute);
+       /* mute/unmute HP */
+       snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
+                                HDA_AMP_MUTE, mute ? 0 : HDA_AMP_MUTE);
 }
 
 /* unsolicited event for HP jack sensing */
@@ -8794,6 +8937,45 @@ static void alc262_ultra_unsol_event(struct hda_codec *codec,
        alc262_ultra_automute(codec);
 }
 
+static struct hda_input_mux alc262_ultra_capture_source = {
+       .num_items = 2,
+       .items = {
+               { "Mic", 0x1 },
+               { "Headphone", 0x7 },
+       },
+};
+
+static int alc262_ultra_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;
+       int ret;
+
+       ret = alc882_mux_enum_put(kcontrol, ucontrol);
+       if (!ret)
+               return 0;
+       /* reprogram the HP pin as mic or HP according to the input source */
+       snd_hda_codec_write_cache(codec, 0x15, 0,
+                                 AC_VERB_SET_PIN_WIDGET_CONTROL,
+                                 spec->cur_mux[0] ? PIN_VREF80 : PIN_HP);
+       alc262_ultra_automute(codec); /* mute/unmute HP */
+       return ret;
+}
+
+static struct snd_kcontrol_new alc262_ultra_capture_mixer[] = {
+       HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
+       HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "Capture Source",
+               .info = alc882_mux_enum_info,
+               .get = alc882_mux_enum_get,
+               .put = alc262_ultra_mux_enum_put,
+       },
+       { } /* end */
+};
+
 /* add playback controls from the parsed DAC table */
 static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec,
                                             const struct auto_pin_cfg *cfg)
@@ -9185,9 +9367,12 @@ static int alc262_parse_auto_config(struct hda_codec *codec)
 /* init callback for auto-configuration model -- overriding the default init */
 static void alc262_auto_init(struct hda_codec *codec)
 {
+       struct alc_spec *spec = codec->spec;
        alc262_auto_init_multi_out(codec);
        alc262_auto_init_hp_out(codec);
        alc262_auto_init_analog_input(codec);
+       if (spec->unsol_event)
+               alc_sku_automute(codec);
 }
 
 /*
@@ -9206,6 +9391,7 @@ static const char *alc262_models[ALC262_MODEL_LAST] = {
        [ALC262_BENQ_T31]       = "benq-t31",
        [ALC262_SONY_ASSAMD]    = "sony-assamd",
        [ALC262_ULTRA]          = "ultra",
+       [ALC262_LENOVO_3000]    = "lenovo-3000",
        [ALC262_AUTO]           = "auto",
 };
 
@@ -9241,6 +9427,8 @@ static struct snd_pci_quirk alc262_cfg_tbl[] = {
        SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FUJITSU),
        SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FUJITSU),
        SND_PCI_QUIRK(0x144d, 0xc032, "Samsung Q1 Ultra", ALC262_ULTRA),
+       SND_PCI_QUIRK(0x144d, 0xc039, "Samsung Q1U EL", ALC262_ULTRA),
+       SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000 y410", ALC262_LENOVO_3000),
        SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_BENQ_ED8),
        SND_PCI_QUIRK(0x17ff, 0x058d, "Benq T31-16", ALC262_BENQ_T31),
        SND_PCI_QUIRK(0x17ff, 0x058f, "Benq Hippo", ALC262_HIPPO_1),
@@ -9390,18 +9578,32 @@ static struct alc_config_preset alc262_presets[] = {
                .init_hook = alc262_hippo_automute,
        },      
        [ALC262_ULTRA] = {
-               .mixers = { alc262_ultra_mixer },
-               .init_verbs = { alc262_init_verbs, alc262_ultra_verbs },
+               .mixers = { alc262_ultra_mixer, alc262_ultra_capture_mixer },
+               .init_verbs = { alc262_ultra_verbs },
                .num_dacs = ARRAY_SIZE(alc262_dac_nids),
                .dac_nids = alc262_dac_nids,
-               .hp_nid = 0x03,
-               .dig_out_nid = ALC262_DIGOUT_NID,
                .num_channel_mode = ARRAY_SIZE(alc262_modes),
                .channel_mode = alc262_modes,
                .input_mux = &alc262_ultra_capture_source,
+               .adc_nids = alc262_adc_nids, /* ADC0 */
+               .capsrc_nids = alc262_capsrc_nids,
+               .num_adc_nids = 1, /* single ADC */
                .unsol_event = alc262_ultra_unsol_event,
                .init_hook = alc262_ultra_automute,
        },
+       [ALC262_LENOVO_3000] = {
+               .mixers = { alc262_lenovo_3000_mixer },
+               .init_verbs = { alc262_init_verbs, alc262_EAPD_verbs,
+                               alc262_lenovo_3000_unsol_verbs },
+               .num_dacs = ARRAY_SIZE(alc262_dac_nids),
+               .dac_nids = alc262_dac_nids,
+               .hp_nid = 0x03,
+               .dig_out_nid = ALC262_DIGOUT_NID,
+               .num_channel_mode = ARRAY_SIZE(alc262_modes),
+               .channel_mode = alc262_modes,
+               .input_mux = &alc262_fujitsu_capture_source,
+               .unsol_event = alc262_lenovo_3000_unsol_event,
+       },
 };
 
 static int patch_alc262(struct hda_codec *codec)
@@ -9472,12 +9674,14 @@ static int patch_alc262(struct hda_codec *codec)
                if (wcap != AC_WID_AUD_IN) {
                        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++;
                }
@@ -9517,6 +9721,8 @@ static hda_nid_t alc268_adc_nids_alt[1] = {
        0x08
 };
 
+static hda_nid_t alc268_capsrc_nids[2] = { 0x23, 0x24 };
+
 static struct snd_kcontrol_new alc268_base_mixer[] = {
        /* output mixer control */
        HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
@@ -9529,6 +9735,22 @@ static struct snd_kcontrol_new alc268_base_mixer[] = {
        { }
 };
 
+/* bind Beep switches of both NID 0x0f and 0x10 */
+static struct hda_bind_ctls alc268_bind_beep_sw = {
+       .ops = &snd_hda_bind_sw,
+       .values = {
+               HDA_COMPOSE_AMP_VAL(0x0f, 3, 1, HDA_INPUT),
+               HDA_COMPOSE_AMP_VAL(0x10, 3, 1, HDA_INPUT),
+               0
+       },
+};
+
+static struct snd_kcontrol_new alc268_beep_mixer[] = {
+       HDA_CODEC_VOLUME("Beep Playback Volume", 0x1d, 0x0, HDA_INPUT),
+       HDA_BIND_SW("Beep Playback Switch", &alc268_bind_beep_sw),
+       { }
+};
+
 static struct hda_verb alc268_eapd_verbs[] = {
        {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
        {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
@@ -9613,8 +9835,12 @@ static struct snd_kcontrol_new alc268_acer_mixer[] = {
 };
 
 static struct hda_verb alc268_acer_verbs[] = {
+       {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* internal dmic? */
+       {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
        {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
        {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+       {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+       {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
 
        {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
        { }
@@ -9685,6 +9911,64 @@ static void alc268_dell_unsol_event(struct hda_codec *codec,
 
 #define alc268_dell_init_hook  alc268_dell_automute
 
+static struct snd_kcontrol_new alc267_quanta_il1_mixer[] = {
+       HDA_CODEC_VOLUME("Speaker Playback Volume", 0x2, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("Mic Capture Volume", 0x23, 0x0, HDA_OUTPUT),
+       HDA_BIND_MUTE("Mic Capture Switch", 0x23, 2, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("Ext Mic Boost", 0x18, 0, HDA_INPUT),
+       HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
+       { }
+};
+
+static struct hda_verb alc267_quanta_il1_verbs[] = {
+       {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
+       {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
+       { }
+};
+
+static void alc267_quanta_il1_hp_automute(struct hda_codec *codec)
+{
+       unsigned int present;
+
+       present = snd_hda_codec_read(codec, 0x15, 0, AC_VERB_GET_PIN_SENSE, 0)
+               & AC_PINSENSE_PRESENCE;
+       snd_hda_codec_write(codec, 0x14, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
+                           present ? 0 : PIN_OUT);
+}
+
+static void alc267_quanta_il1_mic_automute(struct hda_codec *codec)
+{
+       unsigned int present;
+
+       present = snd_hda_codec_read(codec, 0x18, 0,
+                                    AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+       snd_hda_codec_write(codec, 0x23, 0,
+                           AC_VERB_SET_CONNECT_SEL,
+                           present ? 0x00 : 0x01);
+}
+
+static void alc267_quanta_il1_automute(struct hda_codec *codec)
+{
+       alc267_quanta_il1_hp_automute(codec);
+       alc267_quanta_il1_mic_automute(codec);
+}
+
+static void alc267_quanta_il1_unsol_event(struct hda_codec *codec,
+                                          unsigned int res)
+{
+       switch (res >> 26) {
+       case ALC880_HP_EVENT:
+               alc267_quanta_il1_hp_automute(codec);
+               break;
+       case ALC880_MIC_EVENT:
+               alc267_quanta_il1_mic_automute(codec);
+               break;
+       }
+}
+
 /*
  * generic initialization of ADC, input mixers and output mixers
  */
@@ -9725,7 +10009,11 @@ static struct hda_verb alc268_base_init_verbs[] = {
        {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
        {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
        {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-       {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+
+       /* set PCBEEP vol = 0, mute connections */
+       {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+       {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+       {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
 
        /* Unmute Selector 23h,24h and set the default input to mic-in */
        
@@ -9764,29 +10052,17 @@ static struct hda_verb alc268_volume_init_verbs[] = {
        {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
        {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
 
-       /* set PCBEEP vol = 0 */
-       {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, (0xb000 | (0x00 << 8))},
+       /* set PCBEEP vol = 0, mute connections */
+       {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+       {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+       {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
 
        { }
 };
 
 #define alc268_mux_enum_info alc_mux_enum_info
 #define alc268_mux_enum_get alc_mux_enum_get
-
-static int alc268_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;
-
-       unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
-       static hda_nid_t capture_mixers[3] = { 0x23, 0x24 };
-       hda_nid_t nid = capture_mixers[adc_idx];
-
-       return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
-                                    nid,
-                                    &spec->cur_mux[adc_idx]);
-}
+#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),
@@ -9836,13 +10112,17 @@ static struct hda_input_mux alc268_capture_source = {
        },
 };
 
+static struct hda_input_mux alc268_acer_capture_source = {
+       .num_items = 3,
+       .items = {
+               { "Mic", 0x0 },
+               { "Internal Mic", 0x6 },
+               { "Line", 0x2 },
+       },
+};
+
 #ifdef CONFIG_SND_DEBUG
 static struct snd_kcontrol_new alc268_test_mixer[] = {
-       HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
-       HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
-
        /* Volume widgets */
        HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x02, 0x0, HDA_OUTPUT),
        HDA_CODEC_VOLUME("LOUT2 Playback Volume", 0x03, 0x0, HDA_OUTPUT),
@@ -9981,6 +10261,10 @@ static int alc268_auto_create_analog_input_ctls(struct alc_spec *spec,
                case 0x1c:      
                        idx1 = 3;       /* CD */
                        break;
+               case 0x12:
+               case 0x13:
+                       idx1 = 6;       /* digital mics */
+                       break;
                default:
                        continue;
                }
@@ -10073,6 +10357,9 @@ static int alc268_parse_auto_config(struct hda_codec *codec)
        if (spec->kctl_alloc)
                spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
 
+       if (spec->autocfg.speaker_pins[0] != 0x1d)
+               spec->mixers[spec->num_mixers++] = alc268_beep_mixer;
+
        spec->init_verbs[spec->num_init_verbs++] = alc268_volume_init_verbs;
        spec->num_mux_defs = 1;
        spec->input_mux = &spec->private_imux;
@@ -10091,20 +10378,25 @@ static int alc268_parse_auto_config(struct hda_codec *codec)
 /* init callback for auto-configuration model -- overriding the default init */
 static void alc268_auto_init(struct hda_codec *codec)
 {
+       struct alc_spec *spec = codec->spec;
        alc268_auto_init_multi_out(codec);
        alc268_auto_init_hp_out(codec);
        alc268_auto_init_mono_speaker_out(codec);
        alc268_auto_init_analog_input(codec);
+       if (spec->unsol_event)
+               alc_sku_automute(codec);
 }
 
 /*
  * configuration and preset
  */
 static const char *alc268_models[ALC268_MODEL_LAST] = {
+       [ALC267_QUANTA_IL1]     = "quanta-il1",
        [ALC268_3ST]            = "3stack",
        [ALC268_TOSHIBA]        = "toshiba",
        [ALC268_ACER]           = "acer",
        [ALC268_DELL]           = "dell",
+       [ALC268_ZEPTO]          = "zepto",
 #ifdef CONFIG_SND_DEBUG
        [ALC268_TEST]           = "test",
 #endif
@@ -10112,6 +10404,7 @@ static const char *alc268_models[ALC268_MODEL_LAST] = {
 };
 
 static struct snd_pci_quirk alc268_cfg_tbl[] = {
+       SND_PCI_QUIRK(0x1025, 0x011e, "Acer Aspire 5720z", ALC268_ACER),
        SND_PCI_QUIRK(0x1025, 0x0126, "Acer", ALC268_ACER),
        SND_PCI_QUIRK(0x1025, 0x012e, "Acer Aspire 5310", ALC268_ACER),
        SND_PCI_QUIRK(0x1025, 0x0130, "Acer Extensa 5210", ALC268_ACER),
@@ -10122,17 +10415,36 @@ static struct snd_pci_quirk alc268_cfg_tbl[] = {
        SND_PCI_QUIRK(0x1179, 0xff10, "TOSHIBA A205", ALC268_TOSHIBA),
        SND_PCI_QUIRK(0x1179, 0xff50, "TOSHIBA A305", ALC268_TOSHIBA),
        SND_PCI_QUIRK(0x152d, 0x0763, "Diverse (CPR2000)", ALC268_ACER),
+       SND_PCI_QUIRK(0x152d, 0x0771, "Quanta IL1", ALC267_QUANTA_IL1),
+       SND_PCI_QUIRK(0x1170, 0x0040, "ZEPTO", ALC268_ZEPTO),
        {}
 };
 
 static struct alc_config_preset alc268_presets[] = {
+       [ALC267_QUANTA_IL1] = {
+               .mixers = { alc267_quanta_il1_mixer },
+               .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
+                               alc267_quanta_il1_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,
+               .hp_nid = 0x03,
+               .num_channel_mode = ARRAY_SIZE(alc268_modes),
+               .channel_mode = alc268_modes,
+               .input_mux = &alc268_capture_source,
+               .unsol_event = alc267_quanta_il1_unsol_event,
+               .init_hook = alc267_quanta_il1_automute,
+       },
        [ALC268_3ST] = {
-               .mixers = { alc268_base_mixer, alc268_capture_alt_mixer },
+               .mixers = { alc268_base_mixer, alc268_capture_alt_mixer,
+                           alc268_beep_mixer },
                .init_verbs = { alc268_base_init_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 = 0x03,
                .dig_out_nid = ALC268_DIGOUT_NID,
                .num_channel_mode = ARRAY_SIZE(alc268_modes),
@@ -10140,13 +10452,15 @@ static struct alc_config_preset alc268_presets[] = {
                .input_mux = &alc268_capture_source,
        },
        [ALC268_TOSHIBA] = {
-               .mixers = { alc268_base_mixer, alc268_capture_alt_mixer },
+               .mixers = { alc268_base_mixer, alc268_capture_alt_mixer,
+                           alc268_beep_mixer },
                .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
                                alc268_toshiba_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 = 0x03,
                .num_channel_mode = ARRAY_SIZE(alc268_modes),
                .channel_mode = alc268_modes,
@@ -10155,22 +10469,24 @@ static struct alc_config_preset alc268_presets[] = {
                .init_hook = alc268_toshiba_automute,
        },
        [ALC268_ACER] = {
-               .mixers = { alc268_acer_mixer, alc268_capture_alt_mixer },
+               .mixers = { alc268_acer_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_capture_source,
+               .input_mux = &alc268_acer_capture_source,
                .unsol_event = alc268_acer_unsol_event,
                .init_hook = alc268_acer_init_hook,
        },
        [ALC268_DELL] = {
-               .mixers = { alc268_dell_mixer },
+               .mixers = { alc268_dell_mixer, alc268_beep_mixer },
                .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
                                alc268_dell_verbs },
                .num_dacs = ARRAY_SIZE(alc268_dac_nids),
@@ -10182,6 +10498,24 @@ static struct alc_config_preset alc268_presets[] = {
                .init_hook = alc268_dell_init_hook,
                .input_mux = &alc268_capture_source,
        },
+       [ALC268_ZEPTO] = {
+               .mixers = { alc268_base_mixer, alc268_capture_alt_mixer,
+                           alc268_beep_mixer },
+               .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
+                               alc268_toshiba_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 = 0x03,
+               .dig_out_nid = ALC268_DIGOUT_NID,
+               .num_channel_mode = ARRAY_SIZE(alc268_modes),
+               .channel_mode = alc268_modes,
+               .input_mux = &alc268_capture_source,
+               .unsol_event = alc268_toshiba_unsol_event,
+               .init_hook = alc268_toshiba_automute
+       },
 #ifdef CONFIG_SND_DEBUG
        [ALC268_TEST] = {
                .mixers = { alc268_test_mixer, alc268_capture_mixer },
@@ -10191,6 +10525,7 @@ static struct alc_config_preset alc268_presets[] = {
                .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 = 0x03,
                .dig_out_nid = ALC268_DIGOUT_NID,
                .num_channel_mode = ARRAY_SIZE(alc268_modes),
@@ -10247,13 +10582,22 @@ static int patch_alc268(struct hda_codec *codec)
        spec->stream_name_digital = "ALC268 Digital";
        spec->stream_digital_playback = &alc268_pcm_digital_playback;
 
+       if (!query_amp_caps(codec, 0x1d, HDA_INPUT))
+               /* override the amp caps for beep generator */
+               snd_hda_override_amp_caps(codec, 0x1d, HDA_INPUT,
+                                         (0x0c << AC_AMPCAP_OFFSET_SHIFT) |
+                                         (0x0c << AC_AMPCAP_NUM_STEPS_SHIFT) |
+                                         (0x07 << AC_AMPCAP_STEP_SIZE_SHIFT) |
+                                         (0 << AC_AMPCAP_MUTE_SHIFT));
+
        if (!spec->adc_nids && spec->input_mux) {
                /* check whether NID 0x07 is valid */
                unsigned int wcap = get_wcaps(codec, 0x07);
+               int i;
 
                /* get type */
                wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
-               if (wcap != AC_WID_AUD_IN) {
+               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] =
@@ -10266,6 +10610,12 @@ static int patch_alc268(struct hda_codec *codec)
                                alc268_capture_mixer;
                        spec->num_mixers++;
                }
+               spec->capsrc_nids = alc268_capsrc_nids;
+               /* set default input source */
+               for (i = 0; i < spec->num_adc_nids; i++)
+                       snd_hda_codec_write_cache(codec, alc268_capsrc_nids[i],
+                               0, AC_VERB_SET_CONNECT_SEL,
+                               spec->input_mux->items[0].index);
        }
 
        spec->vmaster_nid = 0x02;
@@ -10539,9 +10889,12 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
 /* init callback for auto-configuration model -- overriding the default init */
 static void alc269_auto_init(struct hda_codec *codec)
 {
+       struct alc_spec *spec = codec->spec;
        alc269_auto_init_multi_out(codec);
        alc269_auto_init_hp_out(codec);
        alc269_auto_init_analog_input(codec);
+       if (spec->unsol_event)
+               alc_sku_automute(codec);
 }
 
 /*
@@ -11463,13 +11816,7 @@ static void alc861_auto_set_output_and_unmute(struct hda_codec *codec,
                                              hda_nid_t nid,
                                              int pin_type, int dac_idx)
 {
-       /* set as output */
-
-       snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
-                           pin_type);
-       snd_hda_codec_write(codec, dac_idx, 0, AC_VERB_SET_AMP_GAIN_MUTE,
-                           AMP_OUT_UNMUTE);
-
+       alc_set_pin_output(codec, nid, pin_type);
 }
 
 static void alc861_auto_init_multi_out(struct hda_codec *codec)
@@ -11496,6 +11843,9 @@ static void alc861_auto_init_hp_out(struct hda_codec *codec)
        if (pin) /* connect to front */
                alc861_auto_set_output_and_unmute(codec, pin, PIN_HP,
                                                  spec->multiout.dac_nids[0]);
+       pin = spec->autocfg.speaker_pins[0];
+       if (pin)
+               alc861_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
 }
 
 static void alc861_auto_init_analog_input(struct hda_codec *codec)
@@ -11568,9 +11918,12 @@ static int alc861_parse_auto_config(struct hda_codec *codec)
 /* additional initialization for auto-configuration model */
 static void alc861_auto_init(struct hda_codec *codec)
 {
+       struct alc_spec *spec = codec->spec;
        alc861_auto_init_multi_out(codec);
        alc861_auto_init_hp_out(codec);
        alc861_auto_init_analog_input(codec);
+       if (spec->unsol_event)
+               alc_sku_automute(codec);
 }
 
 #ifdef CONFIG_SND_HDA_POWER_SAVE
@@ -11822,6 +12175,8 @@ static hda_nid_t alc861vd_adc_nids[1] = {
        0x09,
 };
 
+static hda_nid_t alc861vd_capsrc_nids[1] = { 0x22 };
+
 /* input MUX */
 /* FIXME: should be a matrix-type input source selection */
 static struct hda_input_mux alc861vd_capture_source = {
@@ -11835,11 +12190,10 @@ static struct hda_input_mux alc861vd_capture_source = {
 };
 
 static struct hda_input_mux alc861vd_dallas_capture_source = {
-       .num_items = 3,
+       .num_items = 2,
        .items = {
-               { "Front Mic", 0x0 },
-               { "ATAPI Mic", 0x1 },
-               { "Line In", 0x5 },
+               { "Ext Mic", 0x0 },
+               { "Int Mic", 0x1 },
        },
 };
 
@@ -11853,33 +12207,8 @@ 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
-
-static int alc861vd_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);
-       static hda_nid_t capture_mixers[1] = { 0x22 };
-       hda_nid_t nid = capture_mixers[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;
-}
+/* ALC861VD has the ALC882-type input selection (but has only one ADC) */
+#define alc861vd_mux_enum_put alc882_mux_enum_put
 
 /*
  * 2ch mode
@@ -12034,20 +12363,22 @@ static struct snd_kcontrol_new alc861vd_lenovo_mixer[] = {
        { } /* end */
 };
 
-/* Pin assignment: Front=0x14, HP = 0x15,
- *                 Front Mic=0x18, ATAPI Mic = 0x19, Line In = 0x1d
+/* Pin assignment: Speaker=0x14, HP = 0x15,
+ *                 Ext Mic=0x18, Int Mic = 0x19, CD = 0x1c, PC Beep = 0x1d
  */
 static struct snd_kcontrol_new alc861vd_dallas_mixer[] = {
-       HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
-       HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+       HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
+       HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 2, HDA_INPUT),
        HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
        HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),
-       HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-       HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-       HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-       HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-       HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x05, HDA_INPUT),
-       HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x05, HDA_INPUT),
+       HDA_CODEC_VOLUME("Ext Mic Boost", 0x18, 0, HDA_INPUT),
+       HDA_CODEC_VOLUME("Ext Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+       HDA_CODEC_MUTE("Ext Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+       HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
+       HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+       HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+       HDA_CODEC_VOLUME("PC Beep Volume", 0x0b, 0x05, HDA_INPUT),
+       HDA_CODEC_MUTE("PC Beep Switch", 0x0b, 0x05, HDA_INPUT),
        { } /* end */
 };
 
@@ -12348,6 +12679,7 @@ static struct snd_pci_quirk alc861vd_cfg_tbl[] = {
        /*SND_PCI_QUIRK(0x1179, 0xff00, "DALLAS", ALC861VD_DALLAS),*/ /*lenovo*/
        SND_PCI_QUIRK(0x1179, 0xff01, "DALLAS", ALC861VD_DALLAS),
        SND_PCI_QUIRK(0x1179, 0xff03, "Toshiba P205", ALC861VD_LENOVO),
+       SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba L30-149", ALC861VD_DALLAS),
        SND_PCI_QUIRK(0x1565, 0x820d, "Biostar NF61S SE", ALC861VD_6ST_DIG),
        SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo", ALC861VD_LENOVO),
        SND_PCI_QUIRK(0x17aa, 0x3802, "Lenovo 3000 C200", ALC861VD_LENOVO),
@@ -12362,8 +12694,6 @@ static struct alc_config_preset alc861vd_presets[] = {
                                 alc861vd_3stack_init_verbs },
                .num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
                .dac_nids = alc660vd_dac_nids,
-               .num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids),
-               .adc_nids = alc861vd_adc_nids,
                .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
                .channel_mode = alc861vd_3stack_2ch_modes,
                .input_mux = &alc861vd_capture_source,
@@ -12375,8 +12705,6 @@ static struct alc_config_preset alc861vd_presets[] = {
                .num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
                .dac_nids = alc660vd_dac_nids,
                .dig_out_nid = ALC861VD_DIGOUT_NID,
-               .num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids),
-               .adc_nids = alc861vd_adc_nids,
                .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
                .channel_mode = alc861vd_3stack_2ch_modes,
                .input_mux = &alc861vd_capture_source,
@@ -12421,8 +12749,6 @@ static struct alc_config_preset alc861vd_presets[] = {
                                alc861vd_lenovo_unsol_verbs },
                .num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
                .dac_nids = alc660vd_dac_nids,
-               .num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids),
-               .adc_nids = alc861vd_adc_nids,
                .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
                .channel_mode = alc861vd_3stack_2ch_modes,
                .input_mux = &alc861vd_capture_source,
@@ -12434,8 +12760,6 @@ static struct alc_config_preset alc861vd_presets[] = {
                .init_verbs = { alc861vd_dallas_verbs },
                .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
                .dac_nids = alc861vd_dac_nids,
-               .num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids),
-               .adc_nids = alc861vd_adc_nids,
                .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
                .channel_mode = alc861vd_3stack_2ch_modes,
                .input_mux = &alc861vd_dallas_capture_source,
@@ -12447,9 +12771,7 @@ static struct alc_config_preset alc861vd_presets[] = {
                .init_verbs = { alc861vd_dallas_verbs, alc861vd_eapd_verbs },
                .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
                .dac_nids = alc861vd_dac_nids,
-               .num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids),
                .dig_out_nid = ALC861VD_DIGOUT_NID,
-               .adc_nids = alc861vd_adc_nids,
                .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
                .channel_mode = alc861vd_3stack_2ch_modes,
                .input_mux = &alc861vd_hp_capture_source,
@@ -12464,11 +12786,7 @@ static struct alc_config_preset alc861vd_presets[] = {
 static void alc861vd_auto_set_output_and_unmute(struct hda_codec *codec,
                                hda_nid_t nid, int pin_type, int dac_idx)
 {
-       /* set as output */
-       snd_hda_codec_write(codec, nid, 0,
-                               AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
-       snd_hda_codec_write(codec, nid, 0,
-                               AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
+       alc_set_pin_output(codec, nid, pin_type);
 }
 
 static void alc861vd_auto_init_multi_out(struct hda_codec *codec)
@@ -12495,6 +12813,9 @@ static void alc861vd_auto_init_hp_out(struct hda_codec *codec)
        pin = spec->autocfg.hp_pins[0];
        if (pin) /* connect to front and  use dac 0 */
                alc861vd_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
+       pin = spec->autocfg.speaker_pins[0];
+       if (pin)
+               alc861vd_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
 }
 
 #define alc861vd_is_input_pin(nid)     alc880_is_input_pin(nid)
@@ -12698,9 +13019,12 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec)
 /* additional initialization for auto-configuration model */
 static void alc861vd_auto_init(struct hda_codec *codec)
 {
+       struct alc_spec *spec = codec->spec;
        alc861vd_auto_init_multi_out(codec);
        alc861vd_auto_init_hp_out(codec);
        alc861vd_auto_init_analog_input(codec);
+       if (spec->unsol_event)
+               alc_sku_automute(codec);
 }
 
 static int patch_alc861vd(struct hda_codec *codec)
@@ -12751,6 +13075,7 @@ 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->mixers[spec->num_mixers] = alc861vd_capture_mixer;
        spec->num_mixers++;
@@ -12792,9 +13117,11 @@ static hda_nid_t alc662_adc_nids[1] = {
        /* ADC1-2 */
        0x09,
 };
+
+static hda_nid_t alc662_capsrc_nids[1] = { 0x22 };
+
 /* input MUX */
 /* FIXME: should be a matrix-type input source selection */
-
 static struct hda_input_mux alc662_capture_source = {
        .num_items = 4,
        .items = {
@@ -12823,33 +13150,8 @@ static struct hda_input_mux alc662_eeepc_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
 
-static int alc662_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);
-       static hda_nid_t capture_mixers[2] = { 0x23, 0x22 };
-       hda_nid_t nid = capture_mixers[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
  */
@@ -12918,13 +13220,13 @@ static struct hda_channel_mode alc662_5stack_modes[2] = {
 static struct snd_kcontrol_new alc662_base_mixer[] = {
        /* output mixer control */
        HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE("Front Playback Switch", 0x02, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Front Playback Switch", 0x0c, 0x0, HDA_INPUT),
        HDA_CODEC_VOLUME("Surround Playback Volume", 0x3, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE("Surround Playback Switch", 0x03, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Surround Playback Switch", 0x0d, 0x0, HDA_INPUT),
        HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT),
        HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT),
-       HDA_BIND_MUTE_MONO("Center Playback Switch", 0x04, 1, 2, HDA_INPUT),
-       HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x04, 2, 2, HDA_INPUT),
+       HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x0e, 1, 0x0, HDA_INPUT),
+       HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 0x0, HDA_INPUT),
        HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
 
        /*Input mixer control */
@@ -12941,7 +13243,7 @@ static struct snd_kcontrol_new alc662_base_mixer[] = {
 
 static struct snd_kcontrol_new alc662_3ST_2ch_mixer[] = {
        HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
-       HDA_BIND_MUTE("Front Playback Switch", 0x02, 2, HDA_INPUT),
+       HDA_CODEC_MUTE("Front Playback Switch", 0x0c, 0x0, HDA_INPUT),
        HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
        HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
        HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
@@ -12958,13 +13260,13 @@ static struct snd_kcontrol_new alc662_3ST_2ch_mixer[] = {
 
 static struct snd_kcontrol_new alc662_3ST_6ch_mixer[] = {
        HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
-       HDA_BIND_MUTE("Front Playback Switch", 0x02, 2, HDA_INPUT),
+       HDA_CODEC_MUTE("Front Playback Switch", 0x0c, 0x0, HDA_INPUT),
        HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
-       HDA_BIND_MUTE("Surround Playback Switch", 0x03, 2, HDA_INPUT),
+       HDA_CODEC_MUTE("Surround Playback Switch", 0x0d, 0x0, HDA_INPUT),
        HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT),
        HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT),
-       HDA_BIND_MUTE_MONO("Center Playback Switch", 0x04, 1, 2, HDA_INPUT),
-       HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x04, 2, 2, HDA_INPUT),
+       HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x0e, 1, 0x0, HDA_INPUT),
+       HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 0x0, HDA_INPUT),
        HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
        HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
        HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
@@ -13313,6 +13615,7 @@ static const char *alc662_models[ALC662_MODEL_LAST] = {
 };
 
 static struct snd_pci_quirk alc662_cfg_tbl[] = {
+       SND_PCI_QUIRK(0x1043, 0x8290, "ASUS P5GC-MX", ALC662_3ST_6ch_DIG),
        SND_PCI_QUIRK(0x1043, 0x82a1, "ASUS Eeepc", ALC662_ASUS_EEEPC_P701),
        SND_PCI_QUIRK(0x1043, 0x82d1, "ASUS Eeepc EP20", ALC662_ASUS_EEEPC_EP20),
        SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E),
@@ -13326,8 +13629,6 @@ static struct alc_config_preset alc662_presets[] = {
                .num_dacs = ARRAY_SIZE(alc662_dac_nids),
                .dac_nids = alc662_dac_nids,
                .dig_out_nid = ALC662_DIGOUT_NID,
-               .num_adc_nids = ARRAY_SIZE(alc662_adc_nids),
-               .adc_nids = alc662_adc_nids,
                .dig_in_nid = ALC662_DIGIN_NID,
                .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
                .channel_mode = alc662_3ST_2ch_modes,
@@ -13340,8 +13641,6 @@ static struct alc_config_preset alc662_presets[] = {
                .num_dacs = ARRAY_SIZE(alc662_dac_nids),
                .dac_nids = alc662_dac_nids,
                .dig_out_nid = ALC662_DIGOUT_NID,
-               .num_adc_nids = ARRAY_SIZE(alc662_adc_nids),
-               .adc_nids = alc662_adc_nids,
                .dig_in_nid = ALC662_DIGIN_NID,
                .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
                .channel_mode = alc662_3ST_6ch_modes,
@@ -13354,8 +13653,6 @@ static struct alc_config_preset alc662_presets[] = {
                .init_verbs = { alc662_init_verbs },
                .num_dacs = ARRAY_SIZE(alc662_dac_nids),
                .dac_nids = alc662_dac_nids,
-               .num_adc_nids = ARRAY_SIZE(alc662_adc_nids),
-               .adc_nids = alc662_adc_nids,
                .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
                .channel_mode = alc662_3ST_6ch_modes,
                .need_dac_fix = 1,
@@ -13368,8 +13665,6 @@ static struct alc_config_preset alc662_presets[] = {
                .num_dacs = ARRAY_SIZE(alc662_dac_nids),
                .dac_nids = alc662_dac_nids,
                .dig_out_nid = ALC662_DIGOUT_NID,
-               .num_adc_nids = ARRAY_SIZE(alc662_adc_nids),
-               .adc_nids = alc662_adc_nids,
                .dig_in_nid = ALC662_DIGIN_NID,
                .num_channel_mode = ARRAY_SIZE(alc662_5stack_modes),
                .channel_mode = alc662_5stack_modes,
@@ -13380,8 +13675,6 @@ static struct alc_config_preset alc662_presets[] = {
                .init_verbs = { alc662_init_verbs, alc662_sue_init_verbs },
                .num_dacs = ARRAY_SIZE(alc662_dac_nids),
                .dac_nids = alc662_dac_nids,
-               .num_adc_nids = ARRAY_SIZE(alc662_adc_nids),
-               .adc_nids = alc662_adc_nids,
                .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
                .channel_mode = alc662_3ST_2ch_modes,
                .input_mux = &alc662_lenovo_101e_capture_source,
@@ -13394,8 +13687,6 @@ static struct alc_config_preset alc662_presets[] = {
                                alc662_eeepc_sue_init_verbs },
                .num_dacs = ARRAY_SIZE(alc662_dac_nids),
                .dac_nids = alc662_dac_nids,
-               .num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids),
-               .adc_nids = alc662_adc_nids,
                .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
                .channel_mode = alc662_3ST_2ch_modes,
                .input_mux = &alc662_eeepc_capture_source,
@@ -13409,8 +13700,6 @@ static struct alc_config_preset alc662_presets[] = {
                                alc662_eeepc_ep20_sue_init_verbs },
                .num_dacs = ARRAY_SIZE(alc662_dac_nids),
                .dac_nids = alc662_dac_nids,
-               .num_adc_nids = ARRAY_SIZE(alc662_adc_nids),
-               .adc_nids = alc662_adc_nids,
                .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
                .channel_mode = alc662_3ST_6ch_modes,
                .input_mux = &alc662_lenovo_101e_capture_source,
@@ -13556,11 +13845,7 @@ static void alc662_auto_set_output_and_unmute(struct hda_codec *codec,
                                              hda_nid_t nid, int pin_type,
                                              int dac_idx)
 {
-       /* set as output */
-       snd_hda_codec_write(codec, nid, 0,
-                           AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
-       snd_hda_codec_write(codec, nid, 0,
-                           AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
+       alc_set_pin_output(codec, nid, pin_type);
        /* need the manual connection? */
        if (alc880_is_multi_pin(nid)) {
                struct alc_spec *spec = codec->spec;
@@ -13595,6 +13880,9 @@ static void alc662_auto_init_hp_out(struct hda_codec *codec)
        if (pin) /* connect to front */
                /* use dac 0 */
                alc662_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
+       pin = spec->autocfg.speaker_pins[0];
+       if (pin)
+               alc662_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
 }
 
 #define alc662_is_input_pin(nid)       alc880_is_input_pin(nid)
@@ -13672,9 +13960,12 @@ static int alc662_parse_auto_config(struct hda_codec *codec)
 /* additional initialization for auto-configuration model */
 static void alc662_auto_init(struct hda_codec *codec)
 {
+       struct alc_spec *spec = codec->spec;
        alc662_auto_init_multi_out(codec);
        alc662_auto_init_hp_out(codec);
        alc662_auto_init_analog_input(codec);
+       if (spec->unsol_event)
+               alc_sku_automute(codec);
 }
 
 static int patch_alc662(struct hda_codec *codec)
@@ -13722,10 +14013,9 @@ static int patch_alc662(struct hda_codec *codec)
        spec->stream_digital_playback = &alc662_pcm_digital_playback;
        spec->stream_digital_capture = &alc662_pcm_digital_capture;
 
-       if (!spec->adc_nids && spec->input_mux) {
-               spec->adc_nids = alc662_adc_nids;
-               spec->num_adc_nids = ARRAY_SIZE(alc662_adc_nids);
-       }
+       spec->adc_nids = alc662_adc_nids;
+       spec->num_adc_nids = ARRAY_SIZE(alc662_adc_nids);
+       spec->capsrc_nids = alc662_capsrc_nids;
 
        spec->vmaster_nid = 0x02;
 
@@ -13761,6 +14051,8 @@ struct hda_codec_preset snd_hda_preset_realtek[] = {
        { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
        { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
        { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc883 },
+       { .id = 0x10ec0885, .rev = 0x100103, .name = "ALC889A",
+         .patch = patch_alc882 }, /* should be patch_alc883() in future */
        { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },
        { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc883 },
        { .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc883 },
index d22f5a6b850f2b82d3f39060a57a13bb769a3d6e..9332b63e406cc963dfab355011b254493808db2f 100644 (file)
@@ -28,7 +28,7 @@
 #include <sound/core.h>
 #include "hda_codec.h"
 #include "hda_local.h"
-
+#include "hda_patch.h"
 
 /* si3054 verbs */
 #define SI3054_VERB_READ_NODE  0x900
@@ -206,7 +206,7 @@ static int si3054_build_pcms(struct hda_codec *codec)
        info->name = "Si3054 Modem";
        info->stream[SNDRV_PCM_STREAM_PLAYBACK] = si3054_pcm;
        info->stream[SNDRV_PCM_STREAM_CAPTURE]  = si3054_pcm;
-       info->is_modem = 1;
+       info->pcm_type = HDA_PCM_TYPE_MODEM;
        return 0;
 }
 
index caf48edaa921f629870b5e39bc4e83a94d56c52d..b3a15d616873f42df941a87b941c239e635f1b4a 100644 (file)
@@ -32,6 +32,7 @@
 #include <sound/asoundef.h>
 #include "hda_codec.h"
 #include "hda_local.h"
+#include "hda_patch.h"
 
 #define NUM_CONTROL_ALLOC      32
 #define STAC_PWR_EVENT         0x20
@@ -39,6 +40,7 @@
 
 enum {
        STAC_REF,
+       STAC_9200_OQO,
        STAC_9200_DELL_D21,
        STAC_9200_DELL_D22,
        STAC_9200_DELL_D23,
@@ -50,6 +52,7 @@ enum {
        STAC_9200_DELL_M26,
        STAC_9200_DELL_M27,
        STAC_9200_GATEWAY,
+       STAC_9200_PANASONIC,
        STAC_9200_MODELS
 };
 
@@ -63,11 +66,14 @@ enum {
 
 enum {
        STAC_92HD73XX_REF,
+       STAC_DELL_M6,
        STAC_92HD73XX_MODELS
 };
 
 enum {
        STAC_92HD71BXX_REF,
+       STAC_DELL_M4_1,
+       STAC_DELL_M4_2,
        STAC_92HD71BXX_MODELS
 };
 
@@ -123,6 +129,7 @@ struct sigmatel_spec {
        unsigned int hp_detect: 1;
 
        /* gpio lines */
+       unsigned int eapd_mask;
        unsigned int gpio_mask;
        unsigned int gpio_dir;
        unsigned int gpio_data;
@@ -135,6 +142,7 @@ struct sigmatel_spec {
        /* power management */
        unsigned int num_pwrs;
        hda_nid_t *pwr_nids;
+       hda_nid_t *dac_list;
 
        /* playback */
        struct hda_input_mux *mono_mux;
@@ -173,6 +181,7 @@ struct sigmatel_spec {
        /* i/o switches */
        unsigned int io_switch[2];
        unsigned int clfe_swap;
+       unsigned int hp_switch;
        unsigned int aloopback;
 
        struct hda_pcm pcm_rec[2];      /* PCM information */
@@ -184,9 +193,6 @@ struct sigmatel_spec {
        struct hda_input_mux private_dimux;
        struct hda_input_mux private_imux;
        struct hda_input_mux private_mono_mux;
-
-       /* virtual master */
-       unsigned int vmaster_tlv[4];
 };
 
 static hda_nid_t stac9200_adc_nids[1] = {
@@ -244,7 +250,7 @@ static hda_nid_t stac92hd71bxx_dmux_nids[1] = {
        0x1c,
 };
 
-static hda_nid_t stac92hd71bxx_dac_nids[2] = {
+static hda_nid_t stac92hd71bxx_dac_nids[1] = {
        0x10, /*0x11, */
 };
 
@@ -290,6 +296,10 @@ static hda_nid_t stac927x_mux_nids[3] = {
         0x15, 0x16, 0x17
 };
 
+static hda_nid_t stac927x_dac_nids[6] = {
+       0x02, 0x03, 0x04, 0x05, 0x06, 0
+};
+
 static hda_nid_t stac927x_dmux_nids[1] = {
        0x1b,
 };
@@ -331,10 +341,10 @@ static hda_nid_t stac922x_pin_nids[10] = {
        0x0f, 0x10, 0x11, 0x15, 0x1b,
 };
 
-static hda_nid_t stac92hd73xx_pin_nids[12] = {
+static hda_nid_t stac92hd73xx_pin_nids[13] = {
        0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
        0x0f, 0x10, 0x11, 0x12, 0x13,
-       0x14, 0x22
+       0x14, 0x1e, 0x22
 };
 
 static hda_nid_t stac92hd71bxx_pin_nids[10] = {
@@ -527,6 +537,43 @@ static struct hda_verb stac92hd73xx_6ch_core_init[] = {
        {}
 };
 
+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, 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},
+       /* setup import muxs */
+       { 0x28, AC_VERB_SET_CONNECT_SEL, 0x01},
+       { 0x29, AC_VERB_SET_CONNECT_SEL, 0x01},
+       { 0x2a, AC_VERB_SET_CONNECT_SEL, 0x01},
+       { 0x2b, AC_VERB_SET_CONNECT_SEL, 0x00},
+       {}
+};
+
+static struct hda_verb dell_m6_core_init[] = {
+       /* set master volume and direct control */
+       { 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},
+       /* setup import muxs */
+       { 0x28, AC_VERB_SET_CONNECT_SEL, 0x01},
+       { 0x29, AC_VERB_SET_CONNECT_SEL, 0x01},
+       { 0x2a, AC_VERB_SET_CONNECT_SEL, 0x01},
+       { 0x2b, AC_VERB_SET_CONNECT_SEL, 0x00},
+       {}
+};
+
 static struct hda_verb stac92hd73xx_8ch_core_init[] = {
        /* set master volume and direct control */
        { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
@@ -910,6 +957,11 @@ static int stac92xx_build_controls(struct hda_codec *codec)
                err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
                if (err < 0)
                        return err;
+               err = snd_hda_create_spdif_share_sw(codec,
+                                                   &spec->multiout);
+               if (err < 0)
+                       return err;
+               spec->multiout.share_spdif = 1;
        }
        if (spec->dig_in_nid) {
                err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
@@ -919,10 +971,11 @@ static int stac92xx_build_controls(struct hda_codec *codec)
 
        /* if we have no master control, let's create it */
        if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
+               unsigned int vmaster_tlv[4];
                snd_hda_set_vmaster_tlv(codec, spec->multiout.dac_nids[0],
-                                       HDA_OUTPUT, spec->vmaster_tlv);
+                                       HDA_OUTPUT, vmaster_tlv);
                err = snd_hda_add_vmaster(codec, "Master Playback Volume",
-                                         spec->vmaster_tlv, slave_vols);
+                                         vmaster_tlv, slave_vols);
                if (err < 0)
                        return err;
        }
@@ -1052,9 +1105,15 @@ static unsigned int dell9200_m27_pin_configs[8] = {
        0x90170310, 0x04a11020, 0x90170310, 0x40f003fc,
 };
 
+static unsigned int oqo9200_pin_configs[8] = {
+       0x40c000f0, 0x404000f1, 0x0221121f, 0x02211210,
+       0x90170111, 0x90a70120, 0x400000f2, 0x400000f3,
+};
+
 
 static unsigned int *stac9200_brd_tbl[STAC_9200_MODELS] = {
        [STAC_REF] = ref9200_pin_configs,
+       [STAC_9200_OQO] = oqo9200_pin_configs,
        [STAC_9200_DELL_D21] = dell9200_d21_pin_configs,
        [STAC_9200_DELL_D22] = dell9200_d22_pin_configs,
        [STAC_9200_DELL_D23] = dell9200_d23_pin_configs,
@@ -1065,10 +1124,12 @@ static unsigned int *stac9200_brd_tbl[STAC_9200_MODELS] = {
        [STAC_9200_DELL_M25] = dell9200_m25_pin_configs,
        [STAC_9200_DELL_M26] = dell9200_m26_pin_configs,
        [STAC_9200_DELL_M27] = dell9200_m27_pin_configs,
+       [STAC_9200_PANASONIC] = ref9200_pin_configs,
 };
 
 static const char *stac9200_models[STAC_9200_MODELS] = {
        [STAC_REF] = "ref",
+       [STAC_9200_OQO] = "oqo",
        [STAC_9200_DELL_D21] = "dell-d21",
        [STAC_9200_DELL_D22] = "dell-d22",
        [STAC_9200_DELL_D23] = "dell-d23",
@@ -1080,6 +1141,7 @@ static const char *stac9200_models[STAC_9200_MODELS] = {
        [STAC_9200_DELL_M26] = "dell-m26",
        [STAC_9200_DELL_M27] = "dell-m27",
        [STAC_9200_GATEWAY] = "gateway",
+       [STAC_9200_PANASONIC] = "panasonic",
 };
 
 static struct snd_pci_quirk stac9200_cfg_tbl[] = {
@@ -1146,13 +1208,15 @@ static struct snd_pci_quirk stac9200_cfg_tbl[] = {
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f6,
                      "unknown Dell", STAC_9200_DELL_M26),
        /* Panasonic */
-       SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-74", STAC_REF),
+       SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-74", STAC_9200_PANASONIC),
        /* Gateway machines needs EAPD to be set on resume */
        SND_PCI_QUIRK(0x107b, 0x0205, "Gateway S-7110M", STAC_9200_GATEWAY),
        SND_PCI_QUIRK(0x107b, 0x0317, "Gateway MT3423, MX341*",
                      STAC_9200_GATEWAY),
        SND_PCI_QUIRK(0x107b, 0x0318, "Gateway ML3019, MT3707",
                      STAC_9200_GATEWAY),
+       /* OQO Mobile */
+       SND_PCI_QUIRK(0x1106, 0x3288, "OQO Model 2", STAC_9200_OQO),
        {} /* terminator */
 };
 
@@ -1202,24 +1266,48 @@ static struct snd_pci_quirk stac925x_cfg_tbl[] = {
        {} /* terminator */
 };
 
-static unsigned int ref92hd73xx_pin_configs[12] = {
+static unsigned int ref92hd73xx_pin_configs[13] = {
        0x02214030, 0x02a19040, 0x01a19020, 0x02214030,
        0x0181302e, 0x01014010, 0x01014020, 0x01014030,
        0x02319040, 0x90a000f0, 0x90a000f0, 0x01452050,
+       0x01452050,
+};
+
+static unsigned int dell_m6_pin_configs[13] = {
+       0x0321101f, 0x4f00000f, 0x4f0000f0, 0x90170110,
+       0x03a11020, 0x0321101f, 0x4f0000f0, 0x4f0000f0,
+       0x4f0000f0, 0x90a60160, 0x4f0000f0, 0x4f0000f0,
+       0x4f0000f0,
 };
 
 static unsigned int *stac92hd73xx_brd_tbl[STAC_92HD73XX_MODELS] = {
-       [STAC_92HD73XX_REF] = ref92hd73xx_pin_configs,
+       [STAC_92HD73XX_REF]     = ref92hd73xx_pin_configs,
+       [STAC_DELL_M6]  = dell_m6_pin_configs,
 };
 
 static const char *stac92hd73xx_models[STAC_92HD73XX_MODELS] = {
        [STAC_92HD73XX_REF] = "ref",
+       [STAC_DELL_M6] = "dell-m6",
 };
 
 static struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = {
        /* SigmaTel reference board */
        SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
-                     "DFI LanParty", STAC_92HD73XX_REF),
+                               "DFI LanParty", STAC_92HD73XX_REF),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0254,
+                               "unknown Dell", STAC_DELL_M6),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0255,
+                               "unknown Dell", STAC_DELL_M6),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0256,
+                               "unknown Dell", STAC_DELL_M6),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0257,
+                               "unknown Dell", STAC_DELL_M6),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x025e,
+                               "unknown Dell", STAC_DELL_M6),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x025f,
+                               "unknown Dell", STAC_DELL_M6),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0271,
+                               "unknown Dell", STAC_DELL_M6),
        {} /* terminator */
 };
 
@@ -1229,18 +1317,56 @@ static unsigned int ref92hd71bxx_pin_configs[10] = {
        0x90a000f0, 0x01452050,
 };
 
+static unsigned int dell_m4_1_pin_configs[13] = {
+       0x0421101f, 0x04a11221, 0x40f000f0, 0x90170110,
+       0x23a1902e, 0x23014250, 0x40f000f0, 0x90a000f0,
+       0x40f000f0, 0x4f0000f0,
+};
+
+static unsigned int dell_m4_2_pin_configs[13] = {
+       0x0421101f, 0x04a11221, 0x90a70330, 0x90170110,
+       0x23a1902e, 0x23014250, 0x40f000f0, 0x40f000f0,
+       0x40f000f0, 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,
 };
 
 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",
 };
 
 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_DELL, 0x0233,
+                               "unknown Dell", STAC_DELL_M4_1),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0234,
+                               "unknown Dell", STAC_DELL_M4_1),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0250,
+                               "unknown Dell", STAC_DELL_M4_1),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x024f,
+                               "unknown Dell", STAC_DELL_M4_1),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x024d,
+                               "unknown Dell", STAC_DELL_M4_1),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0251,
+                               "unknown Dell", STAC_DELL_M4_1),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0277,
+                               "unknown Dell", STAC_DELL_M4_1),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0263,
+                               "unknown Dell", STAC_DELL_M4_2),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0265,
+                               "unknown Dell", STAC_DELL_M4_2),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0262,
+                               "unknown Dell", STAC_DELL_M4_2),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0264,
+                               "unknown Dell", STAC_DELL_M4_2),
        {} /* terminator */
 };
 
@@ -1733,7 +1859,8 @@ static int stac92xx_playback_pcm_open(struct hda_pcm_stream *hinfo,
                                      struct snd_pcm_substream *substream)
 {
        struct sigmatel_spec *spec = codec->spec;
-       return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
+       return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
+                                            hinfo);
 }
 
 static int stac92xx_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
@@ -1807,7 +1934,7 @@ static int stac92xx_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
 {
        struct sigmatel_spec *spec = codec->spec;
 
-       snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 0, 0, 0);
+       snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
        return 0;
 }
 
@@ -1889,6 +2016,7 @@ static int stac92xx_build_pcms(struct hda_codec *codec)
                codec->num_pcms++;
                info++;
                info->name = "STAC92xx Digital";
+               info->pcm_type = HDA_PCM_TYPE_SPDIF;
                if (spec->multiout.dig_out_nid) {
                        info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_digital_playback;
                        info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
@@ -1925,6 +2053,34 @@ static void stac92xx_auto_set_pinctl(struct hda_codec *codec, hda_nid_t nid, int
                                  AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
 }
 
+#define stac92xx_hp_switch_info                snd_ctl_boolean_mono_info
+
+static int stac92xx_hp_switch_get(struct snd_kcontrol *kcontrol,
+                       struct snd_ctl_elem_value *ucontrol)
+{
+       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct sigmatel_spec *spec = codec->spec;
+
+       ucontrol->value.integer.value[0] = spec->hp_switch;
+       return 0;
+}
+
+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];
+
+       /* check to be sure that the ports are upto date with
+        * switch changes
+        */
+       codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26);
+
+       return 1;
+}
+
 #define stac92xx_io_switch_info                snd_ctl_boolean_mono_info
 
 static int stac92xx_io_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
@@ -1996,6 +2152,15 @@ static int stac92xx_clfe_switch_put(struct snd_kcontrol *kcontrol,
        return 1;
 }
 
+#define STAC_CODEC_HP_SWITCH(xname) \
+       { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+         .name = xname, \
+         .index = 0, \
+         .info = stac92xx_hp_switch_info, \
+         .get = stac92xx_hp_switch_get, \
+         .put = stac92xx_hp_switch_put, \
+       }
+
 #define STAC_CODEC_IO_SWITCH(xname, xpval) \
        { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
          .name = xname, \
@@ -2020,6 +2185,7 @@ enum {
        STAC_CTL_WIDGET_VOL,
        STAC_CTL_WIDGET_MUTE,
        STAC_CTL_WIDGET_MONO_MUX,
+       STAC_CTL_WIDGET_HP_SWITCH,
        STAC_CTL_WIDGET_IO_SWITCH,
        STAC_CTL_WIDGET_CLFE_SWITCH
 };
@@ -2028,6 +2194,7 @@ static struct snd_kcontrol_new stac92xx_control_templates[] = {
        HDA_CODEC_VOLUME(NULL, 0, 0, 0),
        HDA_CODEC_MUTE(NULL, 0, 0, 0),
        STAC_MONO_MUX,
+       STAC_CODEC_HP_SWITCH(NULL),
        STAC_CODEC_IO_SWITCH(NULL, 0),
        STAC_CODEC_CLFE_SWITCH(NULL, 0),
 };
@@ -2222,6 +2389,29 @@ static int create_controls(struct sigmatel_spec *spec, const char *pfx, hda_nid_
        return 0;
 }
 
+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) {
+               printk(KERN_WARNING "stac92xx: No space for DAC 0x%x\n", nid);
+               return 1;
+       } else {
+               spec->multiout.dac_nids[spec->multiout.num_dacs] = nid;
+               spec->multiout.num_dacs++;
+       }
+       return 0;
+}
+
+static int check_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid)
+{
+       if (is_in_dac_nids(spec, nid))
+               return 1;
+       if (spec->multiout.hp_nid == nid)
+               return 1;
+       return 0;
+}
+
 /* 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)
@@ -2236,7 +2426,7 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
        unsigned int wid_caps, pincap;
 
 
-       for (i = 0; i < cfg->line_outs; i++) {
+       for (i = 0; i < cfg->line_outs && i < spec->multiout.num_dacs; i++) {
                if (!spec->multiout.dac_nids[i])
                        continue;
 
@@ -2269,6 +2459,14 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
                }
        }
 
+       if (cfg->hp_outs > 1) {
+               err = stac92xx_add_control(spec,
+                       STAC_CTL_WIDGET_HP_SWITCH,
+                       "Headphone as Line Out Switch", 0);
+               if (err < 0)
+                       return err;
+       }
+
        if (spec->line_switch) {
                nid = cfg->input_pins[AUTO_PIN_LINE];
                pincap = snd_hda_param_read(codec, nid,
@@ -2284,10 +2482,11 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
 
        if (spec->mic_switch) {
                unsigned int def_conf;
-               nid = cfg->input_pins[AUTO_PIN_MIC];
+               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) {
@@ -2297,38 +2496,22 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
                                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;
                }
        }
 
        return 0;
 }
 
-static int check_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid)
-{
-       if (is_in_dac_nids(spec, nid))
-               return 1;
-       if (spec->multiout.hp_nid == nid)
-               return 1;
-       return 0;
-}
-
-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) {
-               printk(KERN_WARNING "stac92xx: No space for DAC 0x%x\n", nid);
-               return 1;
-       } else {
-               spec->multiout.dac_nids[spec->multiout.num_dacs] = nid;
-               spec->multiout.num_dacs++;
-       }
-       return 0;
-}
-
 /* add playback controls for Speaker and HP outputs */
 static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec,
                                        struct auto_pin_cfg *cfg)
@@ -2378,12 +2561,8 @@ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec,
                        return err;
        }
        if (spec->multiout.hp_nid) {
-               const char *pfx;
-               if (old_num_dacs == spec->multiout.num_dacs)
-                       pfx = "Master";
-               else
-                       pfx = "Headphone";
-               err = create_controls(spec, pfx, spec->multiout.hp_nid, 3);
+               err = create_controls(spec, "Headphone",
+                                     spec->multiout.hp_nid, 3);
                if (err < 0)
                        return err;
        }
@@ -2745,7 +2924,7 @@ static int stac9200_auto_create_lfe_ctls(struct hda_codec *codec,
         */
        for (i = 0; i < spec->autocfg.speaker_outs && lfe_pin == 0x0; i++) {
                hda_nid_t pin = spec->autocfg.speaker_pins[i];
-               unsigned long wcaps = get_wcaps(codec, pin);
+               unsigned int wcaps = get_wcaps(codec, pin);
                wcaps &= (AC_WCAP_STEREO | AC_WCAP_OUT_AMP);
                if (wcaps == AC_WCAP_OUT_AMP)
                        /* found a mono speaker with an amp, must be lfe */
@@ -2756,12 +2935,12 @@ static int stac9200_auto_create_lfe_ctls(struct hda_codec *codec,
        if (lfe_pin == 0 && spec->autocfg.speaker_outs == 0) {
                for (i = 0; i < spec->autocfg.line_outs && lfe_pin == 0x0; i++) {
                        hda_nid_t pin = spec->autocfg.line_out_pins[i];
-                       unsigned long cfg;
-                       cfg = snd_hda_codec_read(codec, pin, 0,
+                       unsigned int defcfg;
+                       defcfg = snd_hda_codec_read(codec, pin, 0,
                                                 AC_VERB_GET_CONFIG_DEFAULT,
                                                 0x00);
-                       if (get_defcfg_device(cfg) == AC_JACK_SPEAKER) {
-                               unsigned long wcaps = get_wcaps(codec, pin);
+                       if (get_defcfg_device(defcfg) == AC_JACK_SPEAKER) {
+                               unsigned int wcaps = get_wcaps(codec, pin);
                                wcaps &= (AC_WCAP_STEREO | AC_WCAP_OUT_AMP);
                                if (wcaps == AC_WCAP_OUT_AMP)
                                        /* found a mono speaker with an amp,
@@ -2866,6 +3045,19 @@ static int is_nid_hp_pin(struct auto_pin_cfg *cfg, hda_nid_t nid)
        return 0; /* nid is not a HP-Out */
 };
 
+static void stac92xx_power_down(struct hda_codec *codec)
+{
+       struct sigmatel_spec *spec = codec->spec;
+
+       /* 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,
+                                       AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+}
+
 static int stac92xx_init(struct hda_codec *codec)
 {
        struct sigmatel_spec *spec = codec->spec;
@@ -2909,16 +3101,21 @@ static int stac92xx_init(struct hda_codec *codec)
                                        ? 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);
                /* 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)
                        continue;
+               if (get_defcfg_connect(def_conf) != AC_JACK_PORT_FIXED)
+                       continue;
                enable_pin_detect(codec, spec->pwr_nids[i], event | i);
                codec->patch_ops.unsol_event(codec, (event | i) << 26);
        }
-
+       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);
@@ -3014,6 +3211,7 @@ static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res)
 {
        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;
@@ -3024,26 +3222,42 @@ 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 (presence) {
                /* disable lineouts, enable hp */
+               if (spec->hp_switch)
+                       stac92xx_reset_pinctl(codec, nid, 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)
+                       stac_gpio_set(codec, spec->gpio_mask,
+                               spec->gpio_dir, spec->gpio_data &
+                               ~spec->eapd_mask);
        } else {
                /* enable lineouts, disable hp */
+               if (spec->hp_switch)
+                       stac92xx_set_pinctl(codec, nid, 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)
+                       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);
 } 
 
 static void stac92xx_pin_sense(struct hda_codec *codec, int idx)
@@ -3091,6 +3305,9 @@ static int stac92xx_resume(struct hda_codec *codec)
                spec->gpio_dir, spec->gpio_data);
        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 */
        if (spec->hp_detect)
                codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26);
@@ -3147,12 +3364,18 @@ static int patch_stac9200(struct hda_codec *codec)
        spec->num_adcs = 1;
        spec->num_pwrs = 0;
 
-       if (spec->board_config == STAC_9200_GATEWAY)
+       if (spec->board_config == STAC_9200_GATEWAY ||
+           spec->board_config == STAC_9200_OQO)
                spec->init = stac9200_eapd_init;
        else
                spec->init = stac9200_core_init;
        spec->mixer = stac9200_mixer;
 
+       if (spec->board_config == STAC_9200_PANASONIC) {
+               spec->gpio_mask = spec->gpio_dir = 0x09;
+               spec->gpio_data = 0x00;
+       }
+
        err = stac9200_parse_auto_config(codec);
        if (err < 0) {
                stac92xx_free(codec);
@@ -3293,6 +3516,7 @@ again:
 
        switch (spec->multiout.num_dacs) {
        case 0x3: /* 6 Channel */
+               spec->multiout.hp_nid = 0x17;
                spec->mixer = stac92hd73xx_6ch_mixer;
                spec->init = stac92hd73xx_6ch_core_init;
                break;
@@ -3318,13 +3542,42 @@ again:
 
        spec->num_muxes = ARRAY_SIZE(stac92hd73xx_mux_nids);
        spec->num_adcs = ARRAY_SIZE(stac92hd73xx_adc_nids);
-       spec->num_dmics = STAC92HD73XX_NUM_DMICS;
        spec->num_dmuxes = ARRAY_SIZE(stac92hd73xx_dmux_nids);
        spec->dinput_mux = &stac92hd73xx_dmux;
        /* GPIO0 High = Enable EAPD */
-       spec->gpio_mask = spec->gpio_dir = 0x1;
+       spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x1;
        spec->gpio_data = 0x01;
 
+       switch (spec->board_config) {
+       case STAC_DELL_M6:
+               spec->init = dell_eq_core_init;
+               switch (codec->subsystem_id) {
+               case 0x1028025e: /* Analog Mics */
+               case 0x1028025f:
+                       stac92xx_set_config_reg(codec, 0x0b, 0x90A70170);
+                       spec->num_dmics = 0;
+                       break;
+               case 0x10280271: /* Digital Mics */
+               case 0x10280272:
+                       spec->init = dell_m6_core_init;
+                       /* fall-through */
+               case 0x10280254:
+               case 0x10280255:
+                       stac92xx_set_config_reg(codec, 0x13, 0x90A60160);
+                       spec->num_dmics = 1;
+                       break;
+               case 0x10280256: /* Both */
+               case 0x10280057:
+                       stac92xx_set_config_reg(codec, 0x0b, 0x90A70170);
+                       stac92xx_set_config_reg(codec, 0x13, 0x90A60160);
+                       spec->num_dmics = 1;
+                       break;
+               }
+               break;
+       default:
+               spec->num_dmics = STAC92HD73XX_NUM_DMICS;
+       }
+
        spec->num_pwrs = ARRAY_SIZE(stac92hd73xx_pwr_nids);
        spec->pwr_nids = stac92hd73xx_pwr_nids;
 
@@ -3398,7 +3651,10 @@ again:
        spec->aloopback_shift = 0;
 
        /* GPIO0 High = EAPD */
-       spec->gpio_mask = spec->gpio_dir = spec->gpio_data = 0x1;
+       spec->gpio_mask = 0x01;
+       spec->gpio_dir = 0x01;
+       spec->gpio_mask = 0x01;
+       spec->gpio_data = 0x01;
 
        spec->mux_nids = stac92hd71bxx_mux_nids;
        spec->adc_nids = stac92hd71bxx_adc_nids;
@@ -3413,7 +3669,7 @@ again:
        spec->num_pwrs = ARRAY_SIZE(stac92hd71bxx_pwr_nids);
        spec->pwr_nids = stac92hd71bxx_pwr_nids;
 
-       spec->multiout.num_dacs = 2;
+       spec->multiout.num_dacs = 1;
        spec->multiout.hp_nid = 0x11;
        spec->multiout.dac_nids = stac92hd71bxx_dac_nids;
 
@@ -3577,13 +3833,14 @@ static int patch_stac927x(struct hda_codec *codec)
        spec->num_adcs = ARRAY_SIZE(stac927x_adc_nids);
        spec->mux_nids = stac927x_mux_nids;
        spec->num_muxes = ARRAY_SIZE(stac927x_mux_nids);
+       spec->dac_list = stac927x_dac_nids;
        spec->multiout.dac_nids = spec->dac_nids;
 
        switch (spec->board_config) {
        case STAC_D965_3ST:
        case STAC_D965_5ST:
                /* GPIO0 High = Enable EAPD */
-               spec->gpio_mask = spec->gpio_dir = 0x01;
+               spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x01;
                spec->gpio_data = 0x01;
                spec->num_dmics = 0;
 
@@ -3591,14 +3848,23 @@ static int patch_stac927x(struct hda_codec *codec)
                spec->mixer = stac927x_mixer;
                break;
        case STAC_DELL_BIOS:
+               switch (codec->subsystem_id) {
+               case 0x10280209:
+               case 0x1028022e:
+                       /* correct the device field to SPDIF out */
+                       stac92xx_set_config_reg(codec, 0x21, 0x01442070);
+                       break;
+               };
+               /* configure the analog microphone on some laptops */
+               stac92xx_set_config_reg(codec, 0x0c, 0x90a79130);
                /* correct the front output jack as a hp out */
-               stac92xx_set_config_reg(codec, 0x0f, 0x02270110);
+               stac92xx_set_config_reg(codec, 0x0f, 0x0227011f);
                /* correct the front input jack as a mic */
                stac92xx_set_config_reg(codec, 0x0e, 0x02a79130);
                /* fallthru */
        case STAC_DELL_3ST:
                /* GPIO2 High = Enable EAPD */
-               spec->gpio_mask = spec->gpio_dir = 0x04;
+               spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x04;
                spec->gpio_data = 0x04;
                spec->dmic_nids = stac927x_dmic_nids;
                spec->num_dmics = STAC927X_NUM_DMICS;
@@ -3610,7 +3876,7 @@ static int patch_stac927x(struct hda_codec *codec)
                break;
        default:
                /* GPIO0 High = Enable EAPD */
-               spec->gpio_mask = spec->gpio_dir = 0x1;
+               spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x1;
                spec->gpio_data = 0x01;
                spec->num_dmics = 0;
 
@@ -3714,6 +3980,7 @@ static int patch_stac9205(struct hda_codec *codec)
                                          (AC_USRSP_EN | STAC_HP_EVENT));
 
                spec->gpio_dir = 0x0b;
+               spec->eapd_mask = 0x01;
                spec->gpio_mask = 0x1b;
                spec->gpio_mute = 0x10;
                /* GPIO0 High = EAPD, GPIO1 Low = Headphone Mute,
@@ -3723,7 +3990,7 @@ static int patch_stac9205(struct hda_codec *codec)
                break;
        default:
                /* GPIO0 High = EAPD */
-               spec->gpio_mask = spec->gpio_dir = 0x1;
+               spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x1;
                spec->gpio_data = 0x01;
                break;
        }
index 4e5dd4cf36f5f6404852e9ef70a0fc7110fc5730..52b1d81a26f78a983bc99a5d7da05a5fbef89ac6 100644 (file)
@@ -39,7 +39,7 @@
 #include <sound/core.h>
 #include "hda_codec.h"
 #include "hda_local.h"
-
+#include "hda_patch.h"
 
 /* amp values */
 #define AMP_VAL_IDX_SHIFT      19
@@ -357,7 +357,8 @@ static int via_playback_pcm_open(struct hda_pcm_stream *hinfo,
                                 struct snd_pcm_substream *substream)
 {
        struct via_spec *spec = codec->spec;
-       return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
+       return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
+                                            hinfo);
 }
 
 static int via_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
@@ -430,8 +431,7 @@ static int via_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
                                   struct snd_pcm_substream *substream)
 {
        struct via_spec *spec = codec->spec;
-       snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
-                                  0, 0, 0);
+       snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
        return 0;
 }
 
@@ -493,6 +493,11 @@ static int via_build_controls(struct hda_codec *codec)
                                                    spec->multiout.dig_out_nid);
                if (err < 0)
                        return err;
+               err = snd_hda_create_spdif_share_sw(codec,
+                                                   &spec->multiout);
+               if (err < 0)
+                       return err;
+               spec->multiout.share_spdif = 1;
        }
        if (spec->dig_in_nid) {
                err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
@@ -523,6 +528,7 @@ static int via_build_pcms(struct hda_codec *codec)
                codec->num_pcms++;
                info++;
                info->name = spec->stream_name_digital;
+               info->pcm_type = HDA_PCM_TYPE_SPDIF;
                if (spec->multiout.dig_out_nid) {
                        info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
                                *(spec->stream_digital_playback);
index efd180b40e56382b308fb61c48ffad383193114b..0ed96c1780593f7d9e1f3efab180d4cbb2bcc022 100644 (file)
@@ -1,8 +1,8 @@
 /*
  *   ALSA driver for ICEnsemble ICE1712 (Envy24)
  *
- *   Lowlevel functions for M-Audio Delta 1010, 44, 66, Dio2496, Audiophile
- *                          Digigram VX442
+ *   Lowlevel functions for M-Audio Delta 1010, 1010E, 44, 66, 66E, Dio2496,
+ *                         Audiophile, Digigram VX442
  *
  *     Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz>
  *
@@ -86,6 +86,7 @@ static unsigned char ap_cs8427_codec_select(struct snd_ice1712 *ice)
        unsigned char tmp;
        tmp = snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA);
        switch (ice->eeprom.subvendor) {
+       case ICE1712_SUBDEVICE_DELTA1010E:
        case ICE1712_SUBDEVICE_DELTA1010LT:
                tmp &= ~ICE1712_DELTA_1010LT_CS;
                tmp |= ICE1712_DELTA_1010LT_CCLK | ICE1712_DELTA_1010LT_CS_CS8427;
@@ -109,6 +110,7 @@ static unsigned char ap_cs8427_codec_select(struct snd_ice1712 *ice)
 static void ap_cs8427_codec_deassert(struct snd_ice1712 *ice, unsigned char tmp)
 {
        switch (ice->eeprom.subvendor) {
+       case ICE1712_SUBDEVICE_DELTA1010E:
        case ICE1712_SUBDEVICE_DELTA1010LT:
                tmp &= ~ICE1712_DELTA_1010LT_CS;
                tmp |= ICE1712_DELTA_1010LT_CS_NONE;
@@ -534,6 +536,14 @@ static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice)
        int err;
        struct snd_akm4xxx *ak;
 
+       if (ice->eeprom.subvendor == ICE1712_SUBDEVICE_DELTA1010 &&
+           ice->eeprom.gpiodir == 0x7b)
+               ice->eeprom.subvendor = ICE1712_SUBDEVICE_DELTA1010E;
+
+       if (ice->eeprom.subvendor == ICE1712_SUBDEVICE_DELTA66 &&
+           ice->eeprom.gpiodir == 0xfb)
+               ice->eeprom.subvendor = ICE1712_SUBDEVICE_DELTA66E;
+
        /* determine I2C, DACs and ADCs */
        switch (ice->eeprom.subvendor) {
        case ICE1712_SUBDEVICE_AUDIOPHILE:
@@ -550,6 +560,7 @@ static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice)
                ice->num_total_adcs = ice->omni ? 8 : 4;
                break;
        case ICE1712_SUBDEVICE_DELTA1010:
+       case ICE1712_SUBDEVICE_DELTA1010E:
        case ICE1712_SUBDEVICE_DELTA1010LT:
        case ICE1712_SUBDEVICE_MEDIASTATION:
                ice->num_total_dacs = 8;
@@ -559,6 +570,7 @@ static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice)
                ice->num_total_dacs = 4;        /* two AK4324 codecs */
                break;
        case ICE1712_SUBDEVICE_VX442:
+       case ICE1712_SUBDEVICE_DELTA66E:        /* omni not suported yet */
                ice->num_total_dacs = 4;
                ice->num_total_adcs = 4;
                break;
@@ -568,8 +580,10 @@ static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice)
        switch (ice->eeprom.subvendor) {
        case ICE1712_SUBDEVICE_AUDIOPHILE:
        case ICE1712_SUBDEVICE_DELTA410:
+       case ICE1712_SUBDEVICE_DELTA1010E:
        case ICE1712_SUBDEVICE_DELTA1010LT:
        case ICE1712_SUBDEVICE_VX442:
+       case ICE1712_SUBDEVICE_DELTA66E:
                if ((err = snd_i2c_bus_create(ice->card, "ICE1712 GPIO 1", NULL, &ice->i2c)) < 0) {
                        snd_printk(KERN_ERR "unable to create I2C bus\n");
                        return err;
@@ -601,6 +615,7 @@ static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice)
        /* no analog? */
        switch (ice->eeprom.subvendor) {
        case ICE1712_SUBDEVICE_DELTA1010:
+       case ICE1712_SUBDEVICE_DELTA1010E:
        case ICE1712_SUBDEVICE_DELTADIO2496:
        case ICE1712_SUBDEVICE_MEDIASTATION:
                return 0;
@@ -627,6 +642,7 @@ static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice)
                err = snd_ice1712_akm4xxx_init(ak, &akm_delta44, &akm_delta44_priv, ice);
                break;
        case ICE1712_SUBDEVICE_VX442:
+       case ICE1712_SUBDEVICE_DELTA66E:
                err = snd_ice1712_akm4xxx_init(ak, &akm_vx442, &akm_vx442_priv, ice);
                break;
        default:
@@ -674,6 +690,7 @@ static int __devinit snd_ice1712_delta_add_controls(struct snd_ice1712 *ice)
                if (err < 0)
                        return err;
                break;
+       case ICE1712_SUBDEVICE_DELTA1010E:
        case ICE1712_SUBDEVICE_DELTA1010LT:
                err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_delta1010lt_wordclock_select, ice));
                if (err < 0)
@@ -716,6 +733,7 @@ static int __devinit snd_ice1712_delta_add_controls(struct snd_ice1712 *ice)
        case ICE1712_SUBDEVICE_DELTA44:
        case ICE1712_SUBDEVICE_DELTA66:
        case ICE1712_SUBDEVICE_VX442:
+       case ICE1712_SUBDEVICE_DELTA66E:
                err = snd_ice1712_akm4xxx_build_controls(ice);
                if (err < 0)
                        return err;
index 26ea05a32f56bb1a1cc8b9d6f41ea9f11546a501..ea7116c304c04bce4635ce308b422cf33f6674c4 100644 (file)
                "{Lionstracs,Mediastation},"
 
 #define ICE1712_SUBDEVICE_DELTA1010    0x121430d6
+#define ICE1712_SUBDEVICE_DELTA1010E   0xff1430d6
 #define ICE1712_SUBDEVICE_DELTADIO2496 0x121431d6
 #define ICE1712_SUBDEVICE_DELTA66      0x121432d6
+#define ICE1712_SUBDEVICE_DELTA66E     0xff1432d6
 #define ICE1712_SUBDEVICE_DELTA44      0x121433d6
 #define ICE1712_SUBDEVICE_AUDIOPHILE   0x121434d6
 #define ICE1712_SUBDEVICE_DELTA410     0x121438d6
index 064760d2a0278596d415a252399f7c366fdad462..013fc4f0482282fce0fb25da5a0a63b2012c6956 100644 (file)
@@ -238,6 +238,7 @@ static void snd_ice1712_ews_cs8404_spdif_write(struct snd_ice1712 *ice, unsigned
        case ICE1712_SUBDEVICE_EWS88MT:
        case ICE1712_SUBDEVICE_EWS88MT_NEW:
        case ICE1712_SUBDEVICE_PHASE88:
+       case ICE1712_SUBDEVICE_TS88:
                if (snd_i2c_sendbytes(spec->i2cdevs[EWS_I2C_CS8404], &bits, 1)
                    != 1)
                        goto _error;
@@ -433,6 +434,7 @@ static int __devinit snd_ice1712_ews_init(struct snd_ice1712 *ice)
        case ICE1712_SUBDEVICE_EWS88MT:
        case ICE1712_SUBDEVICE_EWS88MT_NEW:
        case ICE1712_SUBDEVICE_PHASE88:
+       case ICE1712_SUBDEVICE_TS88:
                ice->num_total_dacs = 8;
                ice->num_total_adcs = 8;
                break;
@@ -475,6 +477,8 @@ static int __devinit snd_ice1712_ews_init(struct snd_ice1712 *ice)
        case ICE1712_SUBDEVICE_EWS88MT:
        case ICE1712_SUBDEVICE_EWS88MT_NEW:
        case ICE1712_SUBDEVICE_PHASE88:
+       case ICE1712_SUBDEVICE_TS88:
+
                err = snd_i2c_device_create(ice->i2c, "CS8404",
                                            ICE1712_EWS88MT_CS8404_ADDR,
                                            &spec->i2cdevs[EWS_I2C_CS8404]);
@@ -518,6 +522,7 @@ static int __devinit snd_ice1712_ews_init(struct snd_ice1712 *ice)
        case ICE1712_SUBDEVICE_EWS88MT:
        case ICE1712_SUBDEVICE_EWS88MT_NEW:
        case ICE1712_SUBDEVICE_PHASE88:
+       case ICE1712_SUBDEVICE_TS88:
        case ICE1712_SUBDEVICE_EWS88D:
                /* set up CS8404 */
                ice->spdif.ops.open = ews88_open_spdif;
@@ -547,6 +552,7 @@ static int __devinit snd_ice1712_ews_init(struct snd_ice1712 *ice)
        case ICE1712_SUBDEVICE_EWS88MT:
        case ICE1712_SUBDEVICE_EWS88MT_NEW:
        case ICE1712_SUBDEVICE_PHASE88:
+       case ICE1712_SUBDEVICE_TS88:
                err = snd_ice1712_akm4xxx_init(ak, &akm_ews88mt, &akm_ews88mt_priv, ice);
                break;
        case ICE1712_SUBDEVICE_EWX2496:
@@ -973,6 +979,7 @@ static int __devinit snd_ice1712_ews_add_controls(struct snd_ice1712 *ice)
        case ICE1712_SUBDEVICE_EWS88MT:
        case ICE1712_SUBDEVICE_EWS88MT_NEW:
        case ICE1712_SUBDEVICE_PHASE88:
+       case ICE1712_SUBDEVICE_TS88:
        case ICE1712_SUBDEVICE_DMX6FIRE:
                err = snd_ice1712_akm4xxx_build_controls(ice);
                if (err < 0)
@@ -992,6 +999,7 @@ static int __devinit snd_ice1712_ews_add_controls(struct snd_ice1712 *ice)
        case ICE1712_SUBDEVICE_EWS88MT:
        case ICE1712_SUBDEVICE_EWS88MT_NEW:
        case ICE1712_SUBDEVICE_PHASE88:
+       case ICE1712_SUBDEVICE_TS88:
                err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_ews88mt_input_sense, ice));
                if (err < 0)
                        return err;
@@ -1048,6 +1056,13 @@ struct snd_ice1712_card_info snd_ice1712_ews_cards[] __devinitdata = {
                .chip_init = snd_ice1712_ews_init,
                .build_controls = snd_ice1712_ews_add_controls,
        },
+       {
+               .subvendor = ICE1712_SUBDEVICE_TS88,
+               .name = "terrasoniq TS88",
+               .model = "phase88",
+               .chip_init = snd_ice1712_ews_init,
+               .build_controls = snd_ice1712_ews_add_controls,
+       },
        {
                .subvendor = ICE1712_SUBDEVICE_EWS88D,
                .name = "TerraTec EWS88D",
index e4ed1b475b08fc4ab340815008c7b4fad2a71d5c..1c443718af03e1c781afbeefe96909ae89be8d20 100644 (file)
@@ -30,7 +30,8 @@
                "{TerraTec,EWS 88MT},"\
                "{TerraTec,EWS 88D},"\
                "{TerraTec,DMX 6Fire},"\
-               "{TerraTec,Phase 88},"
+               "{TerraTec,Phase 88}," \
+               "{terrasoniq,TS 88},"
 
 #define ICE1712_SUBDEVICE_EWX2496      0x3b153011
 #define ICE1712_SUBDEVICE_EWS88MT      0x3b151511
@@ -38,6 +39,7 @@
 #define ICE1712_SUBDEVICE_EWS88D       0x3b152b11
 #define ICE1712_SUBDEVICE_DMX6FIRE     0x3b153811
 #define ICE1712_SUBDEVICE_PHASE88      0x3b155111
+#define ICE1712_SUBDEVICE_TS88         0x3b157c11
 
 /* entry point */
 extern struct snd_ice1712_card_info snd_ice1712_ews_cards[];
index cf5c7c0898fd4e6c488321a55259f2855a23a3f4..6914189073a4d11ad81194e5cb7ad91c0a59e7da 100644 (file)
@@ -208,6 +208,19 @@ static int __devinit snd_ice1712_hoontech_init(struct snd_ice1712 *ice)
                            /* ICE1712_STDSP24_MUTE |
                               ICE1712_STDSP24_INSEL |
                               ICE1712_STDSP24_DAREAR; */
+       /*  These boxconfigs have caused problems in the past.
+        *  The code is not optimal, but should now enable a working config to
+        *  be achieved.
+        *  ** MIDI IN can only be configured on one box **
+        *  ICE1712_STDSP24_BOX_MIDI1 needs to be set for that box.
+        *  Tests on a ADAC2000 box suggest the box config flags do not
+        *  work as would be expected, and the inputs are crossed.
+        *  Setting ICE1712_STDSP24_BOX_MIDI1 and ICE1712_STDSP24_BOX_MIDI2
+        *  on the same box connects MIDI-In to both 401 uarts; both outputs
+        *  are then active on all boxes.
+        *  The default config here sets up everything on the first box.
+        *  Alan Horstmann  5.2.2008
+        */
        spec->boxconfig[0] = ICE1712_STDSP24_BOX_CHN1 |
                                     ICE1712_STDSP24_BOX_CHN2 |
                                     ICE1712_STDSP24_BOX_CHN3 |
@@ -223,14 +236,14 @@ static int __devinit snd_ice1712_hoontech_init(struct snd_ice1712 *ice)
                (spec->config & ICE1712_STDSP24_MUTE) ? 1 : 0);
        snd_ice1712_stdsp24_insel(ice,
                (spec->config & ICE1712_STDSP24_INSEL) ? 1 : 0);
-       for (box = 0; box < 1; box++) {
+       for (box = 0; box < 4; box++) {
                if (spec->boxconfig[box] & ICE1712_STDSP24_BOX_MIDI2)
                         snd_ice1712_stdsp24_midi2(ice, 1);
                for (chn = 0; chn < 4; chn++)
                        snd_ice1712_stdsp24_box_channel(ice, box, chn,
                                (spec->boxconfig[box] & (1 << chn)) ? 1 : 0);
-               snd_ice1712_stdsp24_box_midi(ice, box,
-                               (spec->boxconfig[box] & ICE1712_STDSP24_BOX_MIDI1) ? 1 : 0);
+               if (spec->boxconfig[box] & ICE1712_STDSP24_BOX_MIDI1)
+                       snd_ice1712_stdsp24_box_midi(ice, box, 1);
        }
 
        return 0;
@@ -322,6 +335,8 @@ struct snd_ice1712_card_info snd_ice1712_hoontech_cards[] __devinitdata = {
                .name = "Hoontech SoundTrack Audio DSP24",
                .model = "dsp24",
                .chip_init = snd_ice1712_hoontech_init,
+               .mpu401_1_name = "MIDI-1 Hoontech/STA DSP24",
+               .mpu401_2_name = "MIDI-2 Hoontech/STA DSP24",
        },
        {
                .subvendor = ICE1712_SUBDEVICE_STDSP24_VALUE,   /* a dummy id */
index df292af6738197976e05899c7c4e5f0d4e439b86..29d449d73c9864132d15ea0e4cd3313634870231 100644 (file)
@@ -1297,11 +1297,14 @@ static void snd_ice1712_update_volume(struct snd_ice1712 *ice, int index)
 static int snd_ice1712_pro_mixer_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 {
        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
-       int index = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + kcontrol->private_value;
+       int priv_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) +
+               kcontrol->private_value;
        
        spin_lock_irq(&ice->reg_lock);
-       ucontrol->value.integer.value[0] = !((ice->pro_volumes[index] >> 15) & 1);
-       ucontrol->value.integer.value[1] = !((ice->pro_volumes[index] >> 31) & 1);
+       ucontrol->value.integer.value[0] =
+               !((ice->pro_volumes[priv_idx] >> 15) & 1);
+       ucontrol->value.integer.value[1] =
+               !((ice->pro_volumes[priv_idx] >> 31) & 1);
        spin_unlock_irq(&ice->reg_lock);
        return 0;
 }
@@ -1309,16 +1312,17 @@ static int snd_ice1712_pro_mixer_switch_get(struct snd_kcontrol *kcontrol, struc
 static int snd_ice1712_pro_mixer_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 {
        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
-       int index = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + kcontrol->private_value;
+       int priv_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) +
+               kcontrol->private_value;
        unsigned int nval, change;
 
        nval = (ucontrol->value.integer.value[0] ? 0 : 0x00008000) |
               (ucontrol->value.integer.value[1] ? 0 : 0x80000000);
        spin_lock_irq(&ice->reg_lock);
-       nval |= ice->pro_volumes[index] & ~0x80008000;
-       change = nval != ice->pro_volumes[index];
-       ice->pro_volumes[index] = nval;
-       snd_ice1712_update_volume(ice, index);
+       nval |= ice->pro_volumes[priv_idx] & ~0x80008000;
+       change = nval != ice->pro_volumes[priv_idx];
+       ice->pro_volumes[priv_idx] = nval;
+       snd_ice1712_update_volume(ice, priv_idx);
        spin_unlock_irq(&ice->reg_lock);
        return change;
 }
@@ -1335,11 +1339,14 @@ static int snd_ice1712_pro_mixer_volume_info(struct snd_kcontrol *kcontrol, stru
 static int snd_ice1712_pro_mixer_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 {
        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
-       int index = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + kcontrol->private_value;
+       int priv_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) +
+               kcontrol->private_value;
        
        spin_lock_irq(&ice->reg_lock);
-       ucontrol->value.integer.value[0] = (ice->pro_volumes[index] >> 0) & 127;
-       ucontrol->value.integer.value[1] = (ice->pro_volumes[index] >> 16) & 127;
+       ucontrol->value.integer.value[0] =
+               (ice->pro_volumes[priv_idx] >> 0) & 127;
+       ucontrol->value.integer.value[1] =
+               (ice->pro_volumes[priv_idx] >> 16) & 127;
        spin_unlock_irq(&ice->reg_lock);
        return 0;
 }
@@ -1347,16 +1354,17 @@ static int snd_ice1712_pro_mixer_volume_get(struct snd_kcontrol *kcontrol, struc
 static int snd_ice1712_pro_mixer_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 {
        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
-       int index = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + kcontrol->private_value;
+       int priv_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) +
+               kcontrol->private_value;
        unsigned int nval, change;
 
        nval = (ucontrol->value.integer.value[0] & 127) |
               ((ucontrol->value.integer.value[1] & 127) << 16);
        spin_lock_irq(&ice->reg_lock);
-       nval |= ice->pro_volumes[index] & ~0x007f007f;
-       change = nval != ice->pro_volumes[index];
-       ice->pro_volumes[index] = nval;
-       snd_ice1712_update_volume(ice, index);
+       nval |= ice->pro_volumes[priv_idx] & ~0x007f007f;
+       change = nval != ice->pro_volumes[priv_idx];
+       ice->pro_volumes[priv_idx] = nval;
+       snd_ice1712_update_volume(ice, priv_idx);
        spin_unlock_irq(&ice->reg_lock);
        return change;
 }
@@ -2482,10 +2490,9 @@ static int snd_ice1712_free(struct snd_ice1712 *ice)
        outb(0xff, ICEREG(ice, IRQMASK));
        /* --- */
       __hw_end:
-       if (ice->irq >= 0) {
-               synchronize_irq(ice->irq);
+       if (ice->irq >= 0)
                free_irq(ice->irq, ice);
-       }
+
        if (ice->port)
                pci_release_regions(ice->pci);
        snd_ice1712_akm4xxx_free(ice);
index 303cffe08bd8a7abba006a95f3deb3124d92cf3b..3208901c740e075166f95bc1b8d51406ab88ba56 100644 (file)
@@ -367,6 +367,15 @@ struct snd_ice1712 {
 
        /* other board-specific data */
        void *spec;
+
+       /* VT172x specific */
+       int pro_rate_default;
+       int (*is_spdif_master)(struct snd_ice1712 *ice);
+       unsigned int (*get_rate)(struct snd_ice1712 *ice);
+       void (*set_rate)(struct snd_ice1712 *ice, unsigned int rate);
+       unsigned char (*set_mclk)(struct snd_ice1712 *ice, unsigned int rate);
+       void (*set_spdif_clock)(struct snd_ice1712 *ice);
+
 };
 
 
@@ -429,10 +438,14 @@ int snd_ice1712_gpio_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu
 static inline void snd_ice1712_gpio_write_bits(struct snd_ice1712 *ice,
                                               unsigned int mask, unsigned int bits)
 {
+       unsigned val;
+
        ice->gpio.direction |= mask;
        snd_ice1712_gpio_set_dir(ice, ice->gpio.direction);
-       snd_ice1712_gpio_set_mask(ice, ~mask);
-       snd_ice1712_gpio_write(ice, mask & bits);
+       val = snd_ice1712_gpio_read(ice);
+       val &= ~mask;
+       val |= mask & bits;
+       snd_ice1712_gpio_write(ice, val);
 }
 
 static inline int snd_ice1712_gpio_read_bits(struct snd_ice1712 *ice,
index f533850ec6e776377bffd69dac936ae61f32d4bb..4490422fb930bc047af5df27cad62266e3a55689 100644 (file)
@@ -106,15 +106,19 @@ static unsigned int PRO_RATE_DEFAULT = 44100;
  *  Basic I/O
  */
  
+/*
+ *  default rates, default clock routines
+ */
+
 /* check whether the clock mode is spdif-in */
-static inline int is_spdif_master(struct snd_ice1712 *ice)
+static inline int stdclock_is_spdif_master(struct snd_ice1712 *ice)
 {
        return (inb(ICEMT1724(ice, RATE)) & VT1724_SPDIF_MASTER) ? 1 : 0;
 }
 
 static inline int is_pro_rate_locked(struct snd_ice1712 *ice)
 {
-       return is_spdif_master(ice) || PRO_RATE_LOCKED;
+       return ice->is_spdif_master(ice) || PRO_RATE_LOCKED;
 }
 
 /*
@@ -218,6 +222,32 @@ static unsigned int snd_vt1724_get_gpio_data(struct snd_ice1712 *ice)
        return data;
 }
 
+/*
+ * MPU401 accessor
+ */
+static unsigned char snd_vt1724_mpu401_read(struct snd_mpu401 *mpu,
+                                           unsigned long addr)
+{
+       /* fix status bits to the standard position */
+       /* only RX_EMPTY and TX_FULL are checked */
+       if (addr == MPU401C(mpu))
+               return (inb(addr) & 0x0c) << 4;
+       else
+               return inb(addr);
+}
+
+static void snd_vt1724_mpu401_write(struct snd_mpu401 *mpu,
+                                   unsigned char data, unsigned long addr)
+{
+       if (addr == MPU401C(mpu)) {
+               if (data == MPU401_ENTER_UART)
+                       outb(0x01, addr);
+               /* what else? */
+       } else
+               outb(data, addr);
+}
+
+
 /*
  *  Interrupt handler
  */
@@ -226,24 +256,53 @@ static irqreturn_t snd_vt1724_interrupt(int irq, void *dev_id)
 {
        struct snd_ice1712 *ice = dev_id;
        unsigned char status;
+       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);
+                       break;
+               }
+#endif
                handled = 1;            
-               /* these should probably be separated at some point, 
-                * but as we don't currently have MPU support on the board
-                * I will leave it
-                */
-               if ((status & VT1724_IRQ_MPU_RX)||(status & VT1724_IRQ_MPU_TX)) {
+               if (status & VT1724_IRQ_MPU_TX) {
+                       if (ice->rmidi[0])
+                               snd_mpu401_uart_interrupt_tx(irq,
+                                       ice->rmidi[0]->private_data);
+                       else /* disable TX to be sure */
+                               outb(inb(ICEREG1724(ice, IRQMASK)) |
+                                    VT1724_IRQ_MPU_TX,
+                                    ICEREG1724(ice, IRQMASK));
+                       /* Due to mysterical reasons, MPU_TX is always
+                        * generated (and can't be cleared) when a PCM
+                        * playback is going.  So let's ignore at the
+                        * next loop.
+                        */
+                       status_mask &= ~VT1724_IRQ_MPU_TX;
+               }
+               if (status & VT1724_IRQ_MPU_RX) {
                        if (ice->rmidi[0])
-                               snd_mpu401_uart_interrupt(irq, ice->rmidi[0]->private_data);
-                       outb(status & (VT1724_IRQ_MPU_RX|VT1724_IRQ_MPU_TX), ICEREG1724(ice, IRQSTAT));
-                       status &= ~(VT1724_IRQ_MPU_RX|VT1724_IRQ_MPU_TX);
+                               snd_mpu401_uart_interrupt(irq,
+                                       ice->rmidi[0]->private_data);
+                       else /* disable RX to be sure */
+                               outb(inb(ICEREG1724(ice, IRQMASK)) |
+                                    VT1724_IRQ_MPU_RX,
+                                    ICEREG1724(ice, IRQMASK));
                }
+               /* ack MPU irq */
+               outb(status, ICEREG1724(ice, IRQSTAT));
                if (status & VT1724_IRQ_MTPCM) {
                        /*
                         * Multi-track PCM
@@ -391,51 +450,61 @@ static int snd_vt1724_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 #define DMA_PAUSES     (VT1724_RDMA0_PAUSE|VT1724_PDMA0_PAUSE|VT1724_RDMA1_PAUSE|\
        VT1724_PDMA1_PAUSE|VT1724_PDMA2_PAUSE|VT1724_PDMA3_PAUSE|VT1724_PDMA4_PAUSE)
 
-static int get_max_rate(struct snd_ice1712 *ice)
+static const unsigned int stdclock_rate_list[16] = {
+       48000, 24000, 12000, 9600, 32000, 16000, 8000, 96000, 44100,
+       22050, 11025, 88200, 176400, 0, 192000, 64000
+};
+
+static unsigned int stdclock_get_rate(struct snd_ice1712 *ice)
 {
+       unsigned int rate;
+       rate = stdclock_rate_list[inb(ICEMT1724(ice, RATE)) & 15];
+       return rate;
+}
+
+static void stdclock_set_rate(struct snd_ice1712 *ice, unsigned int rate)
+{
+       int i;
+       for (i = 0; i < ARRAY_SIZE(stdclock_rate_list); i++) {
+               if (stdclock_rate_list[i] == rate) {
+                       outb(i, ICEMT1724(ice, RATE));
+                       return;
+               }
+       }
+}
+
+static unsigned char stdclock_set_mclk(struct snd_ice1712 *ice,
+                                      unsigned int rate)
+{
+       unsigned char val, old;
+       /* check MT02 */
        if (ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S) {
-               if ((ice->eeprom.data[ICE_EEP2_I2S] & 0x08) && !ice->vt1720)
-                       return 192000;
+               val = old = inb(ICEMT1724(ice, I2S_FORMAT));
+               if (rate > 96000)
+                       val |= VT1724_MT_I2S_MCLK_128X; /* 128x MCLK */
                else
-                       return 96000;
-       } else
-               return 48000;
+                       val &= ~VT1724_MT_I2S_MCLK_128X; /* 256x MCLK */
+               if (val != old) {
+                       outb(val, ICEMT1724(ice, I2S_FORMAT));
+                       /* master clock changed */
+                       return 1;
+               }
+       }
+       /* no change in master clock */
+       return 0;
 }
 
 static void snd_vt1724_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate,
                                    int force)
 {
        unsigned long flags;
-       unsigned char val, old;
-       unsigned int i, mclk_change;
+       unsigned char mclk_change;
+       unsigned int i, old_rate;
 
-       if (rate > get_max_rate(ice))
+       if (rate > ice->hw_rates->list[ice->hw_rates->count - 1])
                return;
-
-       switch (rate) {
-       case 8000: val = 6; break;
-       case 9600: val = 3; break;
-       case 11025: val = 10; break;
-       case 12000: val = 2; break;
-       case 16000: val = 5; break;
-       case 22050: val = 9; break;
-       case 24000: val = 1; break;
-       case 32000: val = 4; break;
-       case 44100: val = 8; break;
-       case 48000: val = 0; break;
-       case 64000: val = 15; break;
-       case 88200: val = 11; break;
-       case 96000: val = 7; break;
-       case 176400: val = 12; break;
-       case 192000: val = 14; break;
-       default:
-               snd_BUG();
-               val = 0;
-               break;
-       }
-
        spin_lock_irqsave(&ice->reg_lock, flags);
-       if ((inb(ICEMT1724(ice, DMA_CONTROL)) & DMA_STARTS) || 
+       if ((inb(ICEMT1724(ice, DMA_CONTROL)) & DMA_STARTS) ||
            (inb(ICEMT1724(ice, DMA_PAUSE)) & DMA_PAUSES)) {
                /* running? we cannot change the rate now... */
                spin_unlock_irqrestore(&ice->reg_lock, flags);
@@ -446,9 +515,9 @@ static void snd_vt1724_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate,
                return;
        }
 
-       old = inb(ICEMT1724(ice, RATE));
-       if (force || old != val)
-               outb(val, ICEMT1724(ice, RATE));
+       old_rate = ice->get_rate(ice);
+       if (force || (old_rate != rate))
+               ice->set_rate(ice, rate);
        else if (rate == ice->cur_rate) {
                spin_unlock_irqrestore(&ice->reg_lock, flags);
                return;
@@ -456,19 +525,9 @@ static void snd_vt1724_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate,
 
        ice->cur_rate = rate;
 
-       /* check MT02 */
-       mclk_change = 0;
-       if (ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S) {
-               val = old = inb(ICEMT1724(ice, I2S_FORMAT));
-               if (rate > 96000)
-                       val |= VT1724_MT_I2S_MCLK_128X; /* 128x MCLK */
-               else
-                       val &= ~VT1724_MT_I2S_MCLK_128X; /* 256x MCLK */
-               if (val != old) {
-                       outb(val, ICEMT1724(ice, I2S_FORMAT));
-                       mclk_change = 1;
-               }
-       }
+       /* setting master clock */
+       mclk_change = ice->set_mclk(ice, rate);
+
        spin_unlock_irqrestore(&ice->reg_lock, flags);
 
        if (mclk_change && ice->gpio.i2s_mclk_changed)
@@ -727,43 +786,32 @@ static const struct snd_pcm_hardware snd_vt1724_2ch_stereo =
 /*
  * set rate constraints
  */
-static int set_rate_constraints(struct snd_ice1712 *ice,
-                               struct snd_pcm_substream *substream)
+static void set_std_hw_rates(struct snd_ice1712 *ice)
 {
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       if (ice->hw_rates) {
-               /* hardware specific */
-               runtime->hw.rate_min = ice->hw_rates->list[0];
-               runtime->hw.rate_max = ice->hw_rates->list[ice->hw_rates->count - 1];
-               runtime->hw.rates = SNDRV_PCM_RATE_KNOT;
-               return snd_pcm_hw_constraint_list(runtime, 0,
-                                                 SNDRV_PCM_HW_PARAM_RATE,
-                                                 ice->hw_rates);
-       }
        if (ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S) {
                /* I2S */
                /* VT1720 doesn't support more than 96kHz */
                if ((ice->eeprom.data[ICE_EEP2_I2S] & 0x08) && !ice->vt1720)
-                       return snd_pcm_hw_constraint_list(runtime, 0,
-                                                         SNDRV_PCM_HW_PARAM_RATE,
-                                                         &hw_constraints_rates_192);
-               else {
-                       runtime->hw.rates = SNDRV_PCM_RATE_KNOT |
-                               SNDRV_PCM_RATE_8000_96000;
-                       runtime->hw.rate_max = 96000;
-                       return snd_pcm_hw_constraint_list(runtime, 0,
-                                                         SNDRV_PCM_HW_PARAM_RATE,
-                                                         &hw_constraints_rates_96);
-               }
-       } else if (ice->ac97) {
+                       ice->hw_rates = &hw_constraints_rates_192;
+               else
+                       ice->hw_rates = &hw_constraints_rates_96;
+       } else {
                /* ACLINK */
-               runtime->hw.rate_max = 48000;
-               runtime->hw.rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000;
-               return snd_pcm_hw_constraint_list(runtime, 0,
-                                                 SNDRV_PCM_HW_PARAM_RATE,
-                                                 &hw_constraints_rates_48);
+               ice->hw_rates = &hw_constraints_rates_48;
        }
-       return 0;
+}
+
+static int set_rate_constraints(struct snd_ice1712 *ice,
+                               struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+
+       runtime->hw.rate_min = ice->hw_rates->list[0];
+       runtime->hw.rate_max = ice->hw_rates->list[ice->hw_rates->count - 1];
+       runtime->hw.rates = SNDRV_PCM_RATE_KNOT;
+       return snd_pcm_hw_constraint_list(runtime, 0,
+                                         SNDRV_PCM_HW_PARAM_RATE,
+                                         ice->hw_rates);
 }
 
 /* multi-channel playback needs alignment 8x32bit regardless of the channels
@@ -824,7 +872,7 @@ static int snd_vt1724_playback_pro_close(struct snd_pcm_substream *substream)
        struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
 
        if (PRO_RATE_RESET)
-               snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 0);
+               snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 0);
        ice->playback_pro_substream = NULL;
 
        return 0;
@@ -835,7 +883,7 @@ static int snd_vt1724_capture_pro_close(struct snd_pcm_substream *substream)
        struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
 
        if (PRO_RATE_RESET)
-               snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 0);
+               snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 0);
        ice->capture_pro_substream = NULL;
        return 0;
 }
@@ -970,6 +1018,8 @@ static int snd_vt1724_playback_spdif_open(struct snd_pcm_substream *substream)
                                   VT1724_BUFFER_ALIGN);
        snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
                                   VT1724_BUFFER_ALIGN);
+       if (ice->spdif.ops.open)
+               ice->spdif.ops.open(ice, substream);
        return 0;
 }
 
@@ -978,8 +1028,10 @@ static int snd_vt1724_playback_spdif_close(struct snd_pcm_substream *substream)
        struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
 
        if (PRO_RATE_RESET)
-               snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 0);
+               snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 0);
        ice->playback_con_substream = NULL;
+       if (ice->spdif.ops.close)
+               ice->spdif.ops.close(ice, substream);
 
        return 0;
 }
@@ -1002,6 +1054,8 @@ static int snd_vt1724_capture_spdif_open(struct snd_pcm_substream *substream)
                                   VT1724_BUFFER_ALIGN);
        snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
                                   VT1724_BUFFER_ALIGN);
+       if (ice->spdif.ops.open)
+               ice->spdif.ops.open(ice, substream);
        return 0;
 }
 
@@ -1010,8 +1064,10 @@ static int snd_vt1724_capture_spdif_close(struct snd_pcm_substream *substream)
        struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
 
        if (PRO_RATE_RESET)
-               snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 0);
+               snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 0);
        ice->capture_con_substream = NULL;
+       if (ice->spdif.ops.close)
+               ice->spdif.ops.close(ice, substream);
 
        return 0;
 }
@@ -1154,7 +1210,7 @@ static int snd_vt1724_playback_indep_close(struct snd_pcm_substream *substream)
        struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
 
        if (PRO_RATE_RESET)
-               snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 0);
+               snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 0);
        ice->playback_con_substream_ds[substream->number] = NULL;
        ice->pcm_reserved[substream->number] = NULL;
 
@@ -1572,50 +1628,18 @@ int snd_ice1712_gpio_put(struct snd_kcontrol *kcontrol,
 static int snd_vt1724_pro_internal_clock_info(struct snd_kcontrol *kcontrol,
                                              struct snd_ctl_elem_info *uinfo)
 {
-       static const char * const texts_1724[] = {
-               "8000",         /* 0: 6 */
-               "9600",         /* 1: 3 */
-               "11025",        /* 2: 10 */
-               "12000",        /* 3: 2 */
-               "16000",        /* 4: 5 */
-               "22050",        /* 5: 9 */
-               "24000",        /* 6: 1 */
-               "32000",        /* 7: 4 */
-               "44100",        /* 8: 8 */
-               "48000",        /* 9: 0 */
-               "64000",        /* 10: 15 */
-               "88200",        /* 11: 11 */
-               "96000",        /* 12: 7 */
-               "176400",       /* 13: 12 */
-               "192000",       /* 14: 14 */
-               "IEC958 Input", /* 15: -- */
-       };
-       static const char * const texts_1720[] = {
-               "8000",         /* 0: 6 */
-               "9600",         /* 1: 3 */
-               "11025",        /* 2: 10 */
-               "12000",        /* 3: 2 */
-               "16000",        /* 4: 5 */
-               "22050",        /* 5: 9 */
-               "24000",        /* 6: 1 */
-               "32000",        /* 7: 4 */
-               "44100",        /* 8: 8 */
-               "48000",        /* 9: 0 */
-               "64000",        /* 10: 15 */
-               "88200",        /* 11: 11 */
-               "96000",        /* 12: 7 */
-               "IEC958 Input", /* 13: -- */
-       };
        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 
        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
        uinfo->count = 1;
-       uinfo->value.enumerated.items = ice->vt1720 ? 14 : 16;
+       uinfo->value.enumerated.items = ice->hw_rates->count + 1;
        if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
                uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
-       strcpy(uinfo->value.enumerated.name,
-              ice->vt1720 ? texts_1720[uinfo->value.enumerated.item] :
-              texts_1724[uinfo->value.enumerated.item]);
+       if (uinfo->value.enumerated.item == uinfo->value.enumerated.items - 1)
+               strcpy(uinfo->value.enumerated.name, "IEC958 Input");
+       else
+               sprintf(uinfo->value.enumerated.name, "%d",
+                       ice->hw_rates->list[uinfo->value.enumerated.item]);
        return 0;
 }
 
@@ -1623,68 +1647,79 @@ static int snd_vt1724_pro_internal_clock_get(struct snd_kcontrol *kcontrol,
                                             struct snd_ctl_elem_value *ucontrol)
 {
        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
-       static const unsigned char xlate[16] = {
-               9, 6, 3, 1, 7, 4, 0, 12, 8, 5, 2, 11, 13, 255, 14, 10
-       };
-       unsigned char val;
+       unsigned int i, rate;
        
        spin_lock_irq(&ice->reg_lock);
-       if (is_spdif_master(ice)) {
-               ucontrol->value.enumerated.item[0] = ice->vt1720 ? 13 : 15;
+       if (ice->is_spdif_master(ice)) {
+               ucontrol->value.enumerated.item[0] = ice->hw_rates->count;
        } else {
-               val = xlate[inb(ICEMT1724(ice, RATE)) & 15];
-               if (val == 255) {
-                       snd_BUG();
-                       val = 0;
+               rate = ice->get_rate(ice);
+               ucontrol->value.enumerated.item[0] = 0;
+               for (i = 0; i < ice->hw_rates->count; i++) {
+                       if (ice->hw_rates->list[i] == rate) {
+                               ucontrol->value.enumerated.item[0] = i;
+                               break;
+                       }
                }
-               ucontrol->value.enumerated.item[0] = val;
        }
        spin_unlock_irq(&ice->reg_lock);
        return 0;
 }
 
+/* setting clock to external - SPDIF */
+static void stdclock_set_spdif_clock(struct snd_ice1712 *ice)
+{
+       unsigned char oval;
+       unsigned char i2s_oval;
+       oval = inb(ICEMT1724(ice, RATE));
+       outb(oval | VT1724_SPDIF_MASTER, ICEMT1724(ice, RATE));
+       /* setting 256fs */
+       i2s_oval = inb(ICEMT1724(ice, I2S_FORMAT));
+       outb(i2s_oval & ~VT1724_MT_I2S_MCLK_128X, ICEMT1724(ice, I2S_FORMAT));
+}
+
 static int snd_vt1724_pro_internal_clock_put(struct snd_kcontrol *kcontrol,
                                             struct snd_ctl_elem_value *ucontrol)
 {
        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
-       unsigned char oval;
-       int rate;
-       int change = 0;
-       int spdif = ice->vt1720 ? 13 : 15;
+       unsigned int old_rate, new_rate;
+       unsigned int item = ucontrol->value.enumerated.item[0];
+       unsigned int spdif = ice->hw_rates->count;
+
+       if (item > spdif)
+               return -EINVAL;
 
        spin_lock_irq(&ice->reg_lock);
-       oval = inb(ICEMT1724(ice, RATE));
-       if (ucontrol->value.enumerated.item[0] == spdif) {
-               unsigned char i2s_oval;
-               outb(oval | VT1724_SPDIF_MASTER, ICEMT1724(ice, RATE));
-               /* setting 256fs */
-               i2s_oval = inb(ICEMT1724(ice, I2S_FORMAT));
-               outb(i2s_oval & ~VT1724_MT_I2S_MCLK_128X,
-                    ICEMT1724(ice, I2S_FORMAT));
+       if (ice->is_spdif_master(ice))
+               old_rate = 0;
+       else
+               old_rate = ice->get_rate(ice);
+       if (item == spdif) {
+               /* switching to external clock via SPDIF */
+               ice->set_spdif_clock(ice);
+               new_rate = 0;
        } else {
-               rate = rates[ucontrol->value.integer.value[0] % 15];
-               if (rate <= get_max_rate(ice)) {
-                       PRO_RATE_DEFAULT = rate;
-                       spin_unlock_irq(&ice->reg_lock);
-                       snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 1);
-                       spin_lock_irq(&ice->reg_lock);
-               }
+               /* internal on-card clock */
+               new_rate = ice->hw_rates->list[item];
+               ice->pro_rate_default = new_rate;
+               spin_unlock_irq(&ice->reg_lock);
+               snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 1);
+               spin_lock_irq(&ice->reg_lock);
        }
-       change = inb(ICEMT1724(ice, RATE)) != oval;
        spin_unlock_irq(&ice->reg_lock);
 
-       if ((oval & VT1724_SPDIF_MASTER) !=
-           (inb(ICEMT1724(ice, RATE)) & VT1724_SPDIF_MASTER)) {
+       /* the first reset to the SPDIF master mode? */
+       if (old_rate != new_rate && !new_rate) {
                /* notify akm chips as well */
-               if (is_spdif_master(ice)) {
-                       unsigned int i;
-                       for (i = 0; i < ice->akm_codecs; i++) {
-                               if (ice->akm[i].ops.set_rate_val)
-                                       ice->akm[i].ops.set_rate_val(&ice->akm[i], 0);
-                       }
+               unsigned int i;
+               if (ice->gpio.set_pro_rate)
+                       ice->gpio.set_pro_rate(ice, 0);
+               for (i = 0; i < ice->akm_codecs; i++) {
+                       if (ice->akm[i].ops.set_rate_val)
+                               ice->akm[i].ops.set_rate_val(&ice->akm[i], 0);
                }
        }
-       return change;
+       return old_rate != new_rate;
 }
 
 static struct snd_kcontrol_new snd_vt1724_pro_internal_clock __devinitdata = {
@@ -2065,12 +2100,16 @@ static int __devinit snd_vt1724_read_eeprom(struct snd_ice1712 *ice,
 
 
 
-static int __devinit snd_vt1724_chip_init(struct snd_ice1712 *ice)
+static void __devinit snd_vt1724_chip_reset(struct snd_ice1712 *ice)
 {
        outb(VT1724_RESET , ICEREG1724(ice, CONTROL));
-       udelay(200);
+       msleep(10);
        outb(0, ICEREG1724(ice, CONTROL));
-       udelay(200);
+       msleep(10);
+}
+
+static int __devinit snd_vt1724_chip_init(struct snd_ice1712 *ice)
+{
        outb(ice->eeprom.data[ICE_EEP2_SYSCONF], ICEREG1724(ice, SYS_CFG));
        outb(ice->eeprom.data[ICE_EEP2_ACLINK], ICEREG1724(ice, AC97_CFG));
        outb(ice->eeprom.data[ICE_EEP2_I2S], ICEREG1724(ice, I2S_FEATURES));
@@ -2169,10 +2208,8 @@ static int snd_vt1724_free(struct snd_ice1712 *ice)
        outb(0xff, ICEREG1724(ice, IRQMASK));
        /* --- */
       __hw_end:
-       if (ice->irq >= 0) {
-               synchronize_irq(ice->irq);
+       if (ice->irq >= 0)
                free_irq(ice->irq, ice);
-       }
        pci_release_regions(ice->pci);
        snd_ice1712_akm4xxx_free(ice);
        pci_disable_device(ice->pci);
@@ -2243,6 +2280,7 @@ static int __devinit snd_vt1724_create(struct snd_card *card,
 
        ice->irq = pci->irq;
 
+       snd_vt1724_chip_reset(ice);
        if (snd_vt1724_read_eeprom(ice, modelname) < 0) {
                snd_vt1724_free(ice);
                return -EIO;
@@ -2253,10 +2291,7 @@ static int __devinit snd_vt1724_create(struct snd_card *card,
        }
 
        /* unmask used interrupts */
-       if (! (ice->eeprom.data[ICE_EEP2_SYSCONF] & VT1724_CFG_MPU401))
-               mask = VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX;
-       else
-               mask = 0;
+       mask = VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX;
        outb(mask, ICEREG1724(ice, IRQMASK));
        /* don't handle FIFO overrun/underruns (just yet),
         * since they cause machine lockups
@@ -2335,6 +2370,19 @@ static int __devinit snd_vt1724_probe(struct pci_dev *pci,
         * was called so in ice1712 driver, and vt1724 driver is derived from
         * ice1712 driver.
         */
+       ice->pro_rate_default = PRO_RATE_DEFAULT;
+       if (!ice->is_spdif_master)
+               ice->is_spdif_master = stdclock_is_spdif_master;
+       if (!ice->get_rate)
+               ice->get_rate = stdclock_get_rate;
+       if (!ice->set_rate)
+               ice->set_rate = stdclock_set_rate;
+       if (!ice->set_mclk)
+               ice->set_mclk = stdclock_set_mclk;
+       if (!ice->set_spdif_clock)
+               ice->set_spdif_clock = stdclock_set_spdif_clock;
+       if (!ice->hw_rates)
+               set_std_hw_rates(ice);
 
        if ((err = snd_vt1724_pcm_profi(ice, pcm_dev++)) < 0) {
                snd_card_free(card);
@@ -2377,14 +2425,29 @@ static int __devinit snd_vt1724_probe(struct pci_dev *pci,
 
        if (! c->no_mpu401) {
                if (ice->eeprom.data[ICE_EEP2_SYSCONF] & VT1724_CFG_MPU401) {
+                       struct snd_mpu401 *mpu;
                        if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_ICE1712,
                                                       ICEREG1724(ice, MPU_CTRL),
-                                                      MPU401_INFO_INTEGRATED,
+                                                      (MPU401_INFO_INTEGRATED |
+                                                       MPU401_INFO_TX_IRQ),
                                                       ice->irq, 0,
                                                       &ice->rmidi[0])) < 0) {
                                snd_card_free(card);
                                return err;
                        }
+                       mpu = ice->rmidi[0]->private_data;
+                       mpu->read = snd_vt1724_mpu401_read;
+                       mpu->write = snd_vt1724_mpu401_write;
+                       /* unmask MPU RX/TX irqs */
+                       outb(inb(ICEREG1724(ice, IRQMASK)) &
+                            ~(VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX),
+                            ICEREG1724(ice, IRQMASK));
+#if 0 /* for testing */
+                       /* set watermarks */
+                       outb(VT1724_MPU_RX_FIFO | 0x1,
+                            ICEREG1724(ice, MPU_FIFO_WM));
+                       outb(0x1, ICEREG1724(ice, MPU_FIFO_WM));
+#endif
                }
        }
 
index e8038c0ceb721a0f9a3d881814f3bc40dcee34e2..b4e0c16852a6a07ab4b35fe28c14d92466160ba2 100644 (file)
@@ -4,6 +4,8 @@
  *   Lowlevel functions for ESI Juli@ cards
  *
  *     Copyright (c) 2004 Jaroslav Kysela <perex@perex.cz>
+ *                   2008 Pavel Hofman <dustin@seznam.cz>
+ *
  *
  *   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
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <sound/core.h>
+#include <sound/tlv.h>
 
 #include "ice1712.h"
 #include "envy24ht.h"
 #include "juli.h"
-
 struct juli_spec {
        struct ak4114 *ak4114;
        unsigned int analog: 1;
@@ -43,6 +45,32 @@ struct juli_spec {
 #define AK4114_ADDR            0x20            /* S/PDIF receiver */
 #define AK4358_ADDR            0x22            /* DAC */
 
+/*
+ * Juli does not use the standard ICE1724 clock scheme. Juli's ice1724 chip is
+ * supplied by external clock provided by Xilinx array and MK73-1 PLL frequency
+ * multiplier. Actual frequency is set by ice1724 GPIOs hooked to the Xilinx.
+ *
+ * The clock circuitry is supplied by the two ice1724 crystals. This
+ * arrangement allows to generate independent clock signal for AK4114's input
+ * rate detection circuit. As a result, Juli, unlike most other
+ * ice1724+ak4114-based cards, detects spdif input rate correctly.
+ * This fact is applied in the driver, allowing to modify PCM stream rate
+ * parameter according to the actual input rate.
+ *
+ * Juli uses the remaining three stereo-channels of its DAC to optionally
+ * monitor analog input, digital input, and digital output. The corresponding
+ * I2S signals are routed by Xilinx, controlled by GPIOs.
+ *
+ * The master mute is implemented using output muting transistors (GPIO) in
+ * combination with smuting the DAC.
+ *
+ * The card itself has no HW master volume control, implemented using the
+ * vmaster control.
+ *
+ * TODO:
+ * researching and fixing the input monitors
+ */
+
 /*
  * GPIO pins
  */
@@ -55,17 +83,82 @@ struct juli_spec {
 #define GPIO_MULTI_2X          (1<<2)
 #define GPIO_MULTI_1X          (2<<2)          /* also external */
 #define GPIO_MULTI_HALF                (3<<2)
-#define GPIO_INTERNAL_CLOCK    (1<<4)
+#define GPIO_INTERNAL_CLOCK    (1<<4)          /* 0 = external, 1 = internal */
+#define GPIO_CLOCK_MASK                (1<<4)
 #define GPIO_ANALOG_PRESENT    (1<<5)          /* RO only: 0 = present */
 #define GPIO_RXMCLK_SEL                (1<<7)          /* must be 0 */
 #define GPIO_AK5385A_CKS0      (1<<8)
-#define GPIO_AK5385A_DFS0      (1<<9)          /* swapped with DFS1 according doc? */
-#define GPIO_AK5385A_DFS1      (1<<10)
+#define GPIO_AK5385A_DFS1      (1<<9)
+#define GPIO_AK5385A_DFS0      (1<<10)
 #define GPIO_DIGOUT_MONITOR    (1<<11)         /* 1 = active */
 #define GPIO_DIGIN_MONITOR     (1<<12)         /* 1 = active */
 #define GPIO_ANAIN_MONITOR     (1<<13)         /* 1 = active */
-#define GPIO_AK5385A_MCLK      (1<<14)         /* must be 0 */
-#define GPIO_MUTE_CONTROL      (1<<15)         /* 0 = off, 1 = on */
+#define GPIO_AK5385A_CKS1      (1<<14)         /* must be 0 */
+#define GPIO_MUTE_CONTROL      (1<<15)         /* output mute, 1 = muted */
+
+#define GPIO_RATE_MASK         (GPIO_FREQ_MASK | GPIO_MULTI_MASK | \
+               GPIO_CLOCK_MASK)
+#define GPIO_AK5385A_MASK      (GPIO_AK5385A_CKS0 | GPIO_AK5385A_DFS0 | \
+               GPIO_AK5385A_DFS1 | GPIO_AK5385A_CKS1)
+
+#define JULI_PCM_RATE  (SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \
+               SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
+               SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 | \
+               SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | \
+               SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000)
+
+#define GPIO_RATE_16000                (GPIO_FREQ_32KHZ | GPIO_MULTI_HALF | \
+               GPIO_INTERNAL_CLOCK)
+#define GPIO_RATE_22050                (GPIO_FREQ_44KHZ | GPIO_MULTI_HALF | \
+               GPIO_INTERNAL_CLOCK)
+#define GPIO_RATE_24000                (GPIO_FREQ_48KHZ | GPIO_MULTI_HALF | \
+               GPIO_INTERNAL_CLOCK)
+#define GPIO_RATE_32000                (GPIO_FREQ_32KHZ | GPIO_MULTI_1X | \
+               GPIO_INTERNAL_CLOCK)
+#define GPIO_RATE_44100                (GPIO_FREQ_44KHZ | GPIO_MULTI_1X | \
+               GPIO_INTERNAL_CLOCK)
+#define GPIO_RATE_48000                (GPIO_FREQ_48KHZ | GPIO_MULTI_1X | \
+               GPIO_INTERNAL_CLOCK)
+#define GPIO_RATE_64000                (GPIO_FREQ_32KHZ | GPIO_MULTI_2X | \
+               GPIO_INTERNAL_CLOCK)
+#define GPIO_RATE_88200                (GPIO_FREQ_44KHZ | GPIO_MULTI_2X | \
+               GPIO_INTERNAL_CLOCK)
+#define GPIO_RATE_96000                (GPIO_FREQ_48KHZ | GPIO_MULTI_2X | \
+               GPIO_INTERNAL_CLOCK)
+#define GPIO_RATE_176400       (GPIO_FREQ_44KHZ | GPIO_MULTI_4X | \
+               GPIO_INTERNAL_CLOCK)
+#define GPIO_RATE_192000       (GPIO_FREQ_48KHZ | GPIO_MULTI_4X | \
+               GPIO_INTERNAL_CLOCK)
+
+/*
+ * Initial setup of the conversion array GPIO <-> rate
+ */
+static unsigned int juli_rates[] = {
+       16000, 22050, 24000, 32000,
+       44100, 48000, 64000, 88200,
+       96000, 176400, 192000,
+};
+
+static unsigned int gpio_vals[] = {
+       GPIO_RATE_16000, GPIO_RATE_22050, GPIO_RATE_24000, GPIO_RATE_32000,
+       GPIO_RATE_44100, GPIO_RATE_48000, GPIO_RATE_64000, GPIO_RATE_88200,
+       GPIO_RATE_96000, GPIO_RATE_176400, GPIO_RATE_192000,
+};
+
+static struct snd_pcm_hw_constraint_list juli_rates_info = {
+       .count = ARRAY_SIZE(juli_rates),
+       .list = juli_rates,
+       .mask = 0,
+};
+
+static int get_gpio_val(int rate)
+{
+       int i;
+       for (i = 0; i < ARRAY_SIZE(juli_rates); i++)
+               if (juli_rates[i] == rate)
+                       return gpio_vals[i];
+       return 0;
+}
 
 static void juli_ak4114_write(void *private_data, unsigned char reg, unsigned char val)
 {
@@ -77,6 +170,27 @@ static unsigned char juli_ak4114_read(void *private_data, unsigned char reg)
        return snd_vt1724_read_i2c((struct snd_ice1712 *)private_data, AK4114_ADDR, reg);
 }
 
+/*
+ * If SPDIF capture and slaved to SPDIF-IN, setting runtime rate
+ * to the external rate
+ */
+static void juli_spdif_in_open(struct snd_ice1712 *ice,
+                              struct snd_pcm_substream *substream)
+{
+       struct juli_spec *spec = ice->spec;
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       int rate;
+
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ||
+                       !ice->is_spdif_master(ice))
+               return;
+       rate = snd_ak4114_external_rate(spec->ak4114);
+       if (rate >= runtime->hw.rate_min && rate <= runtime->hw.rate_max) {
+               runtime->hw.rate_min = rate;
+               runtime->hw.rate_max = rate;
+       }
+}
+
 /*
  * AK4358 section
  */
@@ -99,57 +213,285 @@ static void juli_akm_write(struct snd_akm4xxx *ak, int chip,
 }
 
 /*
- * change the rate of envy24HT, AK4358
+ * change the rate of envy24HT, AK4358, AK5385
  */
 static void juli_akm_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate)
 {
-       unsigned char old, tmp, dfs;
+       unsigned char old, tmp, ak4358_dfs;
+       unsigned int ak5385_pins, old_gpio, new_gpio;
+       struct snd_ice1712 *ice = ak->private_data[0];
+       struct juli_spec *spec = ice->spec;
 
-       if (rate == 0)  /* no hint - S/PDIF input is master, simply return */
+       if (rate == 0)  /* no hint - S/PDIF input is master or the new spdif
+                          input rate undetected, simply return */
                return;
-       
+
        /* adjust DFS on codecs */
-       if (rate > 96000) 
-               dfs = 2;
-       else if (rate > 48000)
-               dfs = 1;
-       else
-               dfs = 0;
-       
+       if (rate > 96000)  {
+               ak4358_dfs = 2;
+               ak5385_pins = GPIO_AK5385A_DFS1 | GPIO_AK5385A_CKS0;
+       } else if (rate > 48000) {
+               ak4358_dfs = 1;
+               ak5385_pins = GPIO_AK5385A_DFS0;
+       } else {
+               ak4358_dfs = 0;
+               ak5385_pins = 0;
+       }
+       /* AK5385 first, since it requires cold reset affecting both codecs */
+       old_gpio = ice->gpio.get_data(ice);
+       new_gpio =  (old_gpio & ~GPIO_AK5385A_MASK) | ak5385_pins;
+       /* printk(KERN_DEBUG "JULI - ak5385 set_rate_val: new gpio 0x%x\n",
+               new_gpio); */
+       ice->gpio.set_data(ice, new_gpio);
+
+       /* cold reset */
+       old = inb(ICEMT1724(ice, AC97_CMD));
+       outb(old | VT1724_AC97_COLD, ICEMT1724(ice, AC97_CMD));
+       udelay(1);
+       outb(old & ~VT1724_AC97_COLD, ICEMT1724(ice, AC97_CMD));
+
+       /* AK4358 */
+       /* set new value, reset DFS */
        tmp = snd_akm4xxx_get(ak, 0, 2);
-       old = (tmp >> 4) & 0x03;
-       if (old == dfs)
-               return;
-       /* reset DFS */
        snd_akm4xxx_reset(ak, 1);
        tmp = snd_akm4xxx_get(ak, 0, 2);
        tmp &= ~(0x03 << 4);
-       tmp |= dfs << 4;
+       tmp |= ak4358_dfs << 4;
        snd_akm4xxx_set(ak, 0, 2, tmp);
        snd_akm4xxx_reset(ak, 0);
+
+       /* reinit ak4114 */
+       snd_ak4114_reinit(spec->ak4114);
 }
 
+#define AK_DAC(xname, xch)     { .name = xname, .num_channels = xch }
+#define PCM_VOLUME             "PCM Playback Volume"
+#define MONITOR_AN_IN_VOLUME   "Monitor Analog In Volume"
+#define MONITOR_DIG_IN_VOLUME  "Monitor Digital In Volume"
+#define MONITOR_DIG_OUT_VOLUME "Monitor Digital Out Volume"
+
+static const struct snd_akm4xxx_dac_channel juli_dac[] = {
+       AK_DAC(PCM_VOLUME, 2),
+       AK_DAC(MONITOR_AN_IN_VOLUME, 2),
+       AK_DAC(MONITOR_DIG_OUT_VOLUME, 2),
+       AK_DAC(MONITOR_DIG_IN_VOLUME, 2),
+};
+
+
 static struct snd_akm4xxx akm_juli_dac __devinitdata = {
        .type = SND_AK4358,
-       .num_dacs = 2,
+       .num_dacs = 8,  /* DAC1 - analog out
+                          DAC2 - analog in monitor
+                          DAC3 - digital out monitor
+                          DAC4 - digital in monitor
+                        */
        .ops = {
                .lock = juli_akm_lock,
                .unlock = juli_akm_unlock,
                .write = juli_akm_write,
                .set_rate_val = juli_akm_set_rate_val
+       },
+       .dac_info = juli_dac,
+};
+
+#define juli_mute_info         snd_ctl_boolean_mono_info
+
+static int juli_mute_get(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+       unsigned int val;
+       val = ice->gpio.get_data(ice) & (unsigned int) kcontrol->private_value;
+       if (kcontrol->private_value == GPIO_MUTE_CONTROL)
+               /* val 0 = signal on */
+               ucontrol->value.integer.value[0] = (val) ? 0 : 1;
+       else
+               /* val 1 = signal on */
+               ucontrol->value.integer.value[0] = (val) ? 1 : 0;
+       return 0;
+}
+
+static int juli_mute_put(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+       unsigned int old_gpio, new_gpio;
+       old_gpio = ice->gpio.get_data(ice);
+       if (ucontrol->value.integer.value[0]) {
+               /* unmute */
+               if (kcontrol->private_value == GPIO_MUTE_CONTROL) {
+                       /* 0 = signal on */
+                       new_gpio = old_gpio & ~GPIO_MUTE_CONTROL;
+                       /* un-smuting DAC */
+                       snd_akm4xxx_write(ice->akm, 0, 0x01, 0x01);
+               } else
+                       /* 1 = signal on */
+                       new_gpio =  old_gpio |
+                               (unsigned int) kcontrol->private_value;
+       } else {
+               /* mute */
+               if (kcontrol->private_value == GPIO_MUTE_CONTROL) {
+                       /* 1 = signal off */
+                       new_gpio = old_gpio | GPIO_MUTE_CONTROL;
+                       /* smuting DAC */
+                       snd_akm4xxx_write(ice->akm, 0, 0x01, 0x03);
+               } else
+                       /* 0 = signal off */
+                       new_gpio =  old_gpio &
+                               ~((unsigned int) kcontrol->private_value);
+       }
+       /* printk("JULI - mute/unmute: control_value: 0x%x, old_gpio: 0x%x, \
+               new_gpio 0x%x\n",
+               (unsigned int)ucontrol->value.integer.value[0], old_gpio,
+               new_gpio); */
+       if (old_gpio != new_gpio) {
+               ice->gpio.set_data(ice, new_gpio);
+               return 1;
+       }
+       /* no change */
+       return 0;
+}
+
+static struct snd_kcontrol_new juli_mute_controls[] __devinitdata = {
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "Master Playback Switch",
+               .info = juli_mute_info,
+               .get = juli_mute_get,
+               .put = juli_mute_put,
+               .private_value = GPIO_MUTE_CONTROL,
+       },
+       /* Although the following functionality respects the succint NDA'd
+        * documentation from the card manufacturer, and the same way of
+        * operation is coded in OSS Juli driver, only Digital Out monitor
+        * seems to work. Surprisingly, Analog input monitor outputs Digital
+        * output data. The two are independent, as enabling both doubles
+        * volume of the monitor sound.
+        *
+        * Checking traces on the board suggests the functionality described
+        * by the manufacturer is correct - I2S from ADC and AK4114
+        * go to ICE as well as to Xilinx, I2S inputs of DAC2,3,4 (the monitor
+        * inputs) are fed from Xilinx.
+        *
+        * I even checked traces on board and coded a support in driver for
+        * an alternative possiblity - the unused I2S ICE output channels
+        * switched to HW-IN/SPDIF-IN and providing the monitoring signal to
+        * the DAC - to no avail. The I2S outputs seem to be unconnected.
+        *
+        * The windows driver supports the monitoring correctly.
+        */
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "Monitor Analog In Switch",
+               .info = juli_mute_info,
+               .get = juli_mute_get,
+               .put = juli_mute_put,
+               .private_value = GPIO_ANAIN_MONITOR,
+       },
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "Monitor Digital Out Switch",
+               .info = juli_mute_info,
+               .get = juli_mute_get,
+               .put = juli_mute_put,
+               .private_value = GPIO_DIGOUT_MONITOR,
+       },
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "Monitor Digital In Switch",
+               .info = juli_mute_info,
+               .get = juli_mute_get,
+               .put = juli_mute_put,
+               .private_value = GPIO_DIGIN_MONITOR,
+       },
+};
+
+
+static void ak4358_proc_regs_read(struct snd_info_entry *entry,
+               struct snd_info_buffer *buffer)
+{
+       struct snd_ice1712 *ice = (struct snd_ice1712 *)entry->private_data;
+       int reg, val;
+       for (reg = 0; reg <= 0xf; reg++) {
+               val =  snd_akm4xxx_get(ice->akm, 0, reg);
+               snd_iprintf(buffer, "0x%02x = 0x%02x\n", reg, val);
        }
+}
+
+static void ak4358_proc_init(struct snd_ice1712 *ice)
+{
+       struct snd_info_entry *entry;
+       if (!snd_card_proc_new(ice->card, "ak4358_codec", &entry))
+               snd_info_set_text_ops(entry, ice, ak4358_proc_regs_read);
+}
+
+static char *slave_vols[] __devinitdata = {
+       PCM_VOLUME,
+       MONITOR_AN_IN_VOLUME,
+       MONITOR_DIG_IN_VOLUME,
+       MONITOR_DIG_OUT_VOLUME,
+       NULL
 };
 
+static __devinitdata
+DECLARE_TLV_DB_SCALE(juli_master_db_scale, -6350, 50, 1);
+
+static struct snd_kcontrol __devinit *ctl_find(struct snd_card *card,
+               const char *name)
+{
+       struct snd_ctl_elem_id sid;
+       memset(&sid, 0, sizeof(sid));
+       /* FIXME: strcpy is bad. */
+       strcpy(sid.name, name);
+       sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+       return snd_ctl_find_id(card, &sid);
+}
+
+static void __devinit add_slaves(struct snd_card *card,
+                                struct snd_kcontrol *master, char **list)
+{
+       for (; *list; list++) {
+               struct snd_kcontrol *slave = ctl_find(card, *list);
+               /* printk(KERN_DEBUG "add_slaves - %s\n", *list); */
+               if (slave) {
+                       /* printk(KERN_DEBUG "slave %s found\n", *list); */
+                       snd_ctl_add_slave(master, slave);
+               }
+       }
+}
+
 static int __devinit juli_add_controls(struct snd_ice1712 *ice)
 {
        struct juli_spec *spec = ice->spec;
        int err;
+       unsigned int i;
+       struct snd_kcontrol *vmaster;
+
        err = snd_ice1712_akm4xxx_build_controls(ice);
        if (err < 0)
                return err;
+
+       for (i = 0; i < ARRAY_SIZE(juli_mute_controls); i++) {
+               err = snd_ctl_add(ice->card,
+                               snd_ctl_new1(&juli_mute_controls[i], ice));
+               if (err < 0)
+                       return err;
+       }
+       /* Create virtual master control */
+       vmaster = snd_ctl_make_virtual_master("Master Playback Volume",
+                                             juli_master_db_scale);
+       if (!vmaster)
+               return -ENOMEM;
+       add_slaves(ice->card, vmaster, slave_vols);
+       err = snd_ctl_add(ice->card, vmaster);
+       if (err < 0)
+               return err;
+
        /* only capture SPDIF over AK4114 */
        err = snd_ak4114_build(spec->ak4114, NULL,
-                              ice->pcm_pro->streams[SNDRV_PCM_STREAM_CAPTURE].substream);
+                       ice->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream);
+
+       ak4358_proc_init(ice);
        if (err < 0)
                return err;
        return 0;
@@ -158,6 +500,74 @@ static int __devinit juli_add_controls(struct snd_ice1712 *ice)
 /*
  * initialize the chip
  */
+
+static inline int juli_is_spdif_master(struct snd_ice1712 *ice)
+{
+       return (ice->gpio.get_data(ice) & GPIO_INTERNAL_CLOCK) ? 0 : 1;
+}
+
+static unsigned int juli_get_rate(struct snd_ice1712 *ice)
+{
+       int i;
+       unsigned char result;
+
+       result =  ice->gpio.get_data(ice) & GPIO_RATE_MASK;
+       for (i = 0; i < ARRAY_SIZE(gpio_vals); i++)
+               if (gpio_vals[i] == result)
+                       return juli_rates[i];
+       return 0;
+}
+
+/* setting new rate */
+static void juli_set_rate(struct snd_ice1712 *ice, unsigned int rate)
+{
+       unsigned int old, new;
+       unsigned char val;
+
+       old = ice->gpio.get_data(ice);
+       new =  (old & ~GPIO_RATE_MASK) | get_gpio_val(rate);
+       /* printk(KERN_DEBUG "JULI - set_rate: old %x, new %x\n",
+                       old & GPIO_RATE_MASK,
+                       new & GPIO_RATE_MASK); */
+
+       ice->gpio.set_data(ice, new);
+       /* switching to external clock - supplied by external circuits */
+       val = inb(ICEMT1724(ice, RATE));
+       outb(val | VT1724_SPDIF_MASTER, ICEMT1724(ice, RATE));
+}
+
+static inline unsigned char juli_set_mclk(struct snd_ice1712 *ice,
+                                         unsigned int rate)
+{
+       /* no change in master clock */
+       return 0;
+}
+
+/* setting clock to external - SPDIF */
+static void juli_set_spdif_clock(struct snd_ice1712 *ice)
+{
+       unsigned int old;
+       old = ice->gpio.get_data(ice);
+       /* external clock (= 0), multiply 1x, 48kHz */
+       ice->gpio.set_data(ice, (old & ~GPIO_RATE_MASK) | GPIO_MULTI_1X |
+                       GPIO_FREQ_48KHZ);
+}
+
+/* Called when ak4114 detects change in the input SPDIF stream */
+static void juli_ak4114_change(struct ak4114 *ak4114, unsigned char c0,
+                              unsigned char c1)
+{
+       struct snd_ice1712 *ice = ak4114->change_callback_private;
+       int rate;
+       if (ice->is_spdif_master(ice) && c1) {
+               /* only for SPDIF master mode, rate was changed */
+               rate = snd_ak4114_external_rate(ak4114);
+               /* printk(KERN_DEBUG "ak4114 - input rate changed to %d\n",
+                               rate); */
+               juli_akm_set_rate_val(ice->akm, rate);
+       }
+}
+
 static int __devinit juli_init(struct snd_ice1712 *ice)
 {
        static const unsigned char ak4114_init_vals[] = {
@@ -187,6 +597,11 @@ static int __devinit juli_init(struct snd_ice1712 *ice)
                                ice, &spec->ak4114);
        if (err < 0)
                return err;
+       /* callback for codecs rate setting */
+       spec->ak4114->change_callback = juli_ak4114_change;
+       spec->ak4114->change_callback_private = ice;
+       /* AK4114 in Juli can detect external rate correctly */
+       spec->ak4114->check_flags = 0;
 
 #if 0
         /* it seems that the analog doughter board detection does not work
@@ -210,6 +625,15 @@ static int __devinit juli_init(struct snd_ice1712 *ice)
                        return err;
        }
        
+       /* juli is clocked by Xilinx array */
+       ice->hw_rates = &juli_rates_info;
+       ice->is_spdif_master = juli_is_spdif_master;
+       ice->get_rate = juli_get_rate;
+       ice->set_rate = juli_set_rate;
+       ice->set_mclk = juli_set_mclk;
+       ice->set_spdif_clock = juli_set_spdif_clock;
+
+       ice->spdif.ops.open = juli_spdif_in_open;
        return 0;
 }
 
@@ -220,18 +644,20 @@ static int __devinit juli_init(struct snd_ice1712 *ice)
  */
 
 static unsigned char juli_eeprom[] __devinitdata = {
-       [ICE_EEP2_SYSCONF]     = 0x20,  /* clock 512, mpu401, 1xADC, 1xDACs */
+       [ICE_EEP2_SYSCONF]     = 0x2b,  /* clock 512, mpu401, 1xADC, 1xDACs,
+                                          SPDIF in */
        [ICE_EEP2_ACLINK]      = 0x80,  /* I2S */
        [ICE_EEP2_I2S]         = 0xf8,  /* vol, 96k, 24bit, 192k */
        [ICE_EEP2_SPDIF]       = 0xc3,  /* out-en, out-int, spdif-in */
-       [ICE_EEP2_GPIO_DIR]    = 0x9f,
+       [ICE_EEP2_GPIO_DIR]    = 0x9f,  /* 5, 6:inputs; 7, 4-0 outputs*/
        [ICE_EEP2_GPIO_DIR1]   = 0xff,
        [ICE_EEP2_GPIO_DIR2]   = 0x7f,
-       [ICE_EEP2_GPIO_MASK]   = 0x9f,
-       [ICE_EEP2_GPIO_MASK1]  = 0xff,
+       [ICE_EEP2_GPIO_MASK]   = 0x60,  /* 5, 6: locked; 7, 4-0 writable */
+       [ICE_EEP2_GPIO_MASK1]  = 0x00,  /* 0-7 writable */
        [ICE_EEP2_GPIO_MASK2]  = 0x7f,
-       [ICE_EEP2_GPIO_STATE]  = 0x16,  /* internal clock, multiple 1x, 48kHz */
-       [ICE_EEP2_GPIO_STATE1] = 0x80,  /* mute */
+       [ICE_EEP2_GPIO_STATE]  = GPIO_FREQ_48KHZ | GPIO_MULTI_1X |
+              GPIO_INTERNAL_CLOCK,     /* internal clock, multiple 1x, 48kHz*/
+       [ICE_EEP2_GPIO_STATE1] = 0x00,  /* unmuted */
        [ICE_EEP2_GPIO_STATE2] = 0x00,
 };
 
index 4945c81e8a96094d2c3bb73f9555a9d5ee6cd8b5..203cdc1bf8da3d99d3f1b6e23668c59049568ca6 100644 (file)
@@ -246,7 +246,7 @@ static int wm_adc_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val
                wm_put(ice, WM_ADC_MUX, nval);
        }
        mutex_unlock(&ice->gpio_mutex);
-       return 0;
+       return change;
 }
 
 /*
@@ -450,7 +450,7 @@ static int cs_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu
                change = 1;
        }
        mutex_unlock(&ice->gpio_mutex);
-       return 0;
+       return change;
 }
 
 
index 48cf40a8f32a1b0c0f9c763bdd31feb2e83f0bc9..48d3679292a7f81a4137e055a1724f2e21dbfd74 100644 (file)
@@ -319,12 +319,11 @@ static int stac9460_mic_sw_put(struct snd_kcontrol *kcontrol,
 /*
  * Handler for setting correct codec rate - called when rate change is detected
  */
-static void stac9460_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate)
+static void stac9460_set_rate_val(struct snd_ice1712 *ice, unsigned int rate)
 {
        unsigned char old, new;
        int idx;
        unsigned char changed[7];
-       struct snd_ice1712 *ice = ak->private_data[0];
        struct prodigy192_spec *spec = ice->spec;
 
        if (rate == 0)  /* no hint - S/PDIF input is master, simply return */
@@ -357,16 +356,6 @@ static void stac9460_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate)
        mutex_unlock(&spec->mute_mutex);
 }
 
-/* using akm infrastructure for setting rate of the codec */
-static struct snd_akm4xxx akmlike_stac9460 __devinitdata = {
-       .type = NON_AKM,        /* special value */
-       .num_adcs = 6,          /* not used in any way, just for completeness */
-       .num_dacs = 2,
-       .ops = {
-               .set_rate_val = stac9460_set_rate_val
-       }
-};
-
 
 static const DECLARE_TLV_DB_SCALE(db_scale_dac, -19125, 75, 0);
 static const DECLARE_TLV_DB_SCALE(db_scale_adc, 0, 150, 0);
@@ -642,12 +631,19 @@ static int prodigy192_ak4114_init(struct snd_ice1712 *ice)
                0x41, 0x02, 0x2c, 0x00, 0x00
        };
        struct prodigy192_spec *spec = ice->spec;
+       int err;
 
-       return snd_ak4114_create(ice->card,
+       err = snd_ak4114_create(ice->card,
                                 prodigy192_ak4114_read,
                                 prodigy192_ak4114_write,
                                 ak4114_init_vals, ak4114_init_txcsb,
                                 ice, &spec->ak4114);
+       if (err < 0)
+               return err;
+       /* AK4114 in Prodigy192 cannot detect external rate correctly.
+        * No reason to stop capture stream due to incorrect checks */
+       spec->ak4114->check_flags = AK4114_CHECK_NO_RATE;
+       return 0;
 }
 
 static void stac9460_proc_regs_read(struct snd_info_entry *entry,
@@ -743,7 +739,6 @@ static int __devinit prodigy192_init(struct snd_ice1712 *ice)
        };
        const unsigned short *p;
        int err = 0;
-       struct snd_akm4xxx *ak;
        struct prodigy192_spec *spec;
 
        /* prodigy 192 */
@@ -761,15 +756,7 @@ static int __devinit prodigy192_init(struct snd_ice1712 *ice)
        p = stac_inits_prodigy;
        for (; *p != (unsigned short)-1; p += 2)
                stac9460_put(ice, p[0], p[1]);
-       /* reusing the akm codecs infrastructure,
-        * for setting rate on stac9460 */
-       ak = ice->akm = kmalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
-       if (!ak)
-               return -ENOMEM;
-       ice->akm_codecs = 1;
-       err = snd_ice1712_akm4xxx_init(ak, &akmlike_stac9460, NULL, ice);
-       if (err < 0)
-               return err;
+       ice->gpio.set_pro_rate = stac9460_set_rate_val;
 
        /* MI/ODI/O add on card with AK4114 */
        if (prodigy192_miodio_exists(ice)) {
@@ -825,10 +812,6 @@ struct snd_ice1712_card_info snd_vt1724_prodigy192_cards[] __devinitdata = {
                .build_controls = prodigy192_add_controls,
                .eeprom_size = sizeof(prodigy71_eeprom),
                .eeprom_data = prodigy71_eeprom,
-               /* the current MPU401 code loops infinitely
-                * when opening midi device
-                */
-               .no_mpu401 = 1,
        },
        { } /* terminator */
 };
index 301bf929acd9018310fe96b94c1c37ce521f05e2..4d2631434dc81bdb83720ea717c1d6a613fdc51d 100644 (file)
@@ -322,17 +322,23 @@ static struct snd_pt2258 ptc_revo51_volume;
 static void ap192_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate)
 {
        struct snd_ice1712 *ice = ak->private_data[0];
+       int dfs;
 
        revo_set_rate_val(ak, rate);
 
-#if 1 /* FIXME: do we need this procedure? */
-       /* reset DFS pin of AK5385A for ADC, too */
-       /* DFS0 (pin 18) -- GPIO10 pin 77 */
-       snd_ice1712_save_gpio_status(ice);
-       snd_ice1712_gpio_write_bits(ice, 1 << 10,
-                                   rate > 48000 ? (1 << 10) : 0);
-       snd_ice1712_restore_gpio_status(ice);
-#endif
+       /* reset CKS */
+       snd_ice1712_gpio_write_bits(ice, 1 << 8, rate > 96000 ? 1 << 8 : 0);
+       /* reset DFS pins of AK5385A for ADC, too */
+       if (rate > 96000)
+               dfs = 2;
+       else if (rate > 48000)
+               dfs = 1;
+       else
+               dfs = 0;
+       snd_ice1712_gpio_write_bits(ice, 3 << 9, dfs << 9);
+       /* reset ADC */
+       snd_ice1712_gpio_write_bits(ice, 1 << 11, 0);
+       snd_ice1712_gpio_write_bits(ice, 1 << 11, 1 << 11);
 }
 
 static const struct snd_akm4xxx_dac_channel ap192_dac[] = {
@@ -353,28 +359,20 @@ static struct snd_ak4xxx_private akm_ap192_priv __devinitdata = {
        .cif = 0,
        .data_mask = VT1724_REVO_CDOUT,
        .clk_mask = VT1724_REVO_CCLK,
-       .cs_mask = VT1724_REVO_CS0 | VT1724_REVO_CS3,
-       .cs_addr = VT1724_REVO_CS3,
-       .cs_none = VT1724_REVO_CS0 | VT1724_REVO_CS3,
+       .cs_mask = VT1724_REVO_CS0 | VT1724_REVO_CS1,
+       .cs_addr = VT1724_REVO_CS1,
+       .cs_none = VT1724_REVO_CS0 | VT1724_REVO_CS1,
        .add_flags = VT1724_REVO_CCLK, /* high at init */
        .mask_flags = 0,
 };
 
-#if 0
-/* FIXME: ak4114 makes the sound much lower due to some confliction,
- *        so let's disable it right now...
- */
-#define BUILD_AK4114_AP192
-#endif
-
-#ifdef BUILD_AK4114_AP192
 /* AK4114 support on Audiophile 192 */
 /* CDTO (pin 32) -- GPIO2 pin 52
  * CDTI (pin 33) -- GPIO3 pin 53 (shared with AK4358)
  * CCLK (pin 34) -- GPIO1 pin 51 (shared with AK4358)
  * CSN  (pin 35) -- GPIO7 pin 59
  */
-#define AK4114_ADDR    0x00
+#define AK4114_ADDR    0x02
 
 static void write_data(struct snd_ice1712 *ice, unsigned int gpio,
                       unsigned int data, int idx)
@@ -428,7 +426,7 @@ static unsigned int ap192_4wire_start(struct snd_ice1712 *ice)
        tmp = snd_ice1712_gpio_read(ice);
        tmp |= VT1724_REVO_CCLK; /* high at init */
        tmp |= VT1724_REVO_CS0;
-       tmp &= ~VT1724_REVO_CS3;
+       tmp &= ~VT1724_REVO_CS1;
        snd_ice1712_gpio_write(ice, tmp);
        udelay(1);
        return tmp;
@@ -436,7 +434,7 @@ static unsigned int ap192_4wire_start(struct snd_ice1712 *ice)
 
 static void ap192_4wire_finish(struct snd_ice1712 *ice, unsigned int tmp)
 {
-       tmp |= VT1724_REVO_CS3;
+       tmp |= VT1724_REVO_CS1;
        tmp |= VT1724_REVO_CS0;
        snd_ice1712_gpio_write(ice, tmp);
        udelay(1);
@@ -485,13 +483,17 @@ static int __devinit ap192_ak4114_init(struct snd_ice1712 *ice)
        struct ak4114 *ak;
        int err;
 
-       return snd_ak4114_create(ice->card,
+       err = snd_ak4114_create(ice->card,
                                 ap192_ak4114_read,
                                 ap192_ak4114_write,
                                 ak4114_init_vals, ak4114_init_txcsb,
                                 ice, &ak);
+       /* AK4114 in Revo cannot detect external rate correctly.
+        * No reason to stop capture stream due to incorrect checks */
+       ak->check_flags = AK4114_CHECK_NO_RATE;
+
+       return 0; /* error ignored; it's no fatal error */
 }
-#endif /* BUILD_AK4114_AP192 */
 
 static int __devinit revo_init(struct snd_ice1712 *ice)
 {
@@ -557,6 +559,9 @@ static int __devinit revo_init(struct snd_ice1712 *ice)
                if (err < 0)
                        return err;
                
+               /* unmute all codecs */
+               snd_ice1712_gpio_write_bits(ice, VT1724_REVO_MUTE,
+                                           VT1724_REVO_MUTE);
                break;
        }
 
@@ -588,11 +593,9 @@ static int __devinit revo_add_controls(struct snd_ice1712 *ice)
                err = snd_ice1712_akm4xxx_build_controls(ice);
                if (err < 0)
                        return err;
-#ifdef BUILD_AK4114_AP192
                err = ap192_ak4114_init(ice);
                if (err < 0)
                        return err;
-#endif
                break;
        }
        return 0;
index c52abd0bf22e3026b03274851f71c15d1fbf947b..048d99e25ab0f0010ea1f4c7a7a06b553e1449d6 100644 (file)
@@ -155,7 +155,8 @@ DEFINE_REGSET(SP, 0x60);    /* SPDIF out */
 #define   ICH_PCM_SPDIF_69     0x80000000      /* s/pdif pcm on slots 6&9 */
 #define   ICH_PCM_SPDIF_1011   0xc0000000      /* s/pdif pcm on slots 10&11 */
 #define   ICH_PCM_20BIT                0x00400000      /* 20-bit samples (ICH4) */
-#define   ICH_PCM_246_MASK     0x00300000      /* 6 channels (not all chips) */
+#define   ICH_PCM_246_MASK     0x00300000      /* chan mask (not all chips) */
+#define   ICH_PCM_8            0x00300000      /* 8 channels (not all chips) */
 #define   ICH_PCM_6            0x00200000      /* 6 channels (not all chips) */
 #define   ICH_PCM_4            0x00100000      /* 4 channels (not all chips) */
 #define   ICH_PCM_2            0x00000000      /* 2 channels (stereo) */
@@ -382,6 +383,7 @@ struct intel8x0 {
 
        unsigned multi4: 1,
                 multi6: 1,
+                multi8 :1,
                 dra: 1,
                 smp20bit: 1;
        unsigned in_ac97_init: 1,
@@ -997,6 +999,8 @@ static void snd_intel8x0_setup_pcm_out(struct intel8x0 *chip,
                        cnt |= ICH_PCM_4;
                else if (runtime->channels == 6)
                        cnt |= ICH_PCM_6;
+               else if (runtime->channels == 8)
+                       cnt |= ICH_PCM_8;
                if (chip->device_type == DEVICE_NFORCE) {
                        /* reset to 2ch once to keep the 6 channel data in alignment,
                         * to start from Front Left always
@@ -1106,6 +1110,16 @@ static struct snd_pcm_hw_constraint_list hw_constraints_channels6 = {
        .mask = 0,
 };
 
+static unsigned int channels8[] = {
+       2, 4, 6, 8,
+};
+
+static struct snd_pcm_hw_constraint_list hw_constraints_channels8 = {
+       .count = ARRAY_SIZE(channels8),
+       .list = channels8,
+       .mask = 0,
+};
+
 static int snd_intel8x0_pcm_open(struct snd_pcm_substream *substream, struct ichdev *ichdev)
 {
        struct intel8x0 *chip = snd_pcm_substream_chip(substream);
@@ -1136,7 +1150,12 @@ static int snd_intel8x0_playback_open(struct snd_pcm_substream *substream)
        if (err < 0)
                return err;
 
-       if (chip->multi6) {
+       if (chip->multi8) {
+               runtime->hw.channels_max = 8;
+               snd_pcm_hw_constraint_list(runtime, 0,
+                                               SNDRV_PCM_HW_PARAM_CHANNELS,
+                                               &hw_constraints_channels8);
+       } else if (chip->multi6) {
                runtime->hw.channels_max = 6;
                snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
                                           &hw_constraints_channels6);
@@ -2203,8 +2222,11 @@ static int __devinit snd_intel8x0_mixer(struct intel8x0 *chip, int ac97_clock,
        }
        if (pbus->pcms[0].r[0].slots & (1 << AC97_SLOT_PCM_SLEFT)) {
                chip->multi4 = 1;
-               if (pbus->pcms[0].r[0].slots & (1 << AC97_SLOT_LFE))
+               if (pbus->pcms[0].r[0].slots & (1 << AC97_SLOT_LFE)) {
                        chip->multi6 = 1;
+                       if (chip->ac97[0]->flags & AC97_HAS_8CH)
+                               chip->multi8 = 1;
+               }
        }
        if (pbus->pcms[0].r[1].rslots[0]) {
                chip->dra = 1;
@@ -2446,7 +2468,7 @@ static int snd_intel8x0_free(struct intel8x0 *chip)
                pci_write_config_dword(chip->pci, 0x4c, val);
        }
        /* --- */
-       synchronize_irq(chip->irq);
+
       __hw_end:
        if (chip->irq >= 0)
                free_irq(chip->irq, chip);
@@ -2495,7 +2517,6 @@ static int intel8x0_suspend(struct pci_dev *pci, pm_message_t state)
                chip->sdm_saved = igetbyte(chip, ICHREG(SDM));
 
        if (chip->irq >= 0) {
-               synchronize_irq(chip->irq);
                free_irq(chip->irq, chip);
                chip->irq = -1;
        }
@@ -2648,7 +2669,7 @@ static void __devinit intel8x0_measure_ac97_clock(struct intel8x0 *chip)
        t = stop_time.tv_sec - start_time.tv_sec;
        t *= 1000000;
        t += stop_time.tv_usec - start_time.tv_usec;
-       printk(KERN_INFO "%s: measured %lu usecs\n", __FUNCTION__, t);
+       printk(KERN_INFO "%s: measured %lu usecs\n", __func__, t);
        if (t == 0) {
                snd_printk(KERN_ERR "?? calculation error..\n");
                return;
index cadda8d6b70f8a00a01748c633c7116329868a6c..faf674e671aca3c1432cf4d04860bb69f210d5df 100644 (file)
@@ -985,17 +985,15 @@ static int snd_intel8x0_free(struct intel8x0m *chip)
        /* reset channels */
        for (i = 0; i < chip->bdbars_count; i++)
                iputbyte(chip, ICH_REG_OFF_CR + chip->ichd[i].reg_offset, ICH_RESETREGS);
-       /* --- */
-       synchronize_irq(chip->irq);
-      __hw_end:
+ __hw_end:
+       if (chip->irq >= 0)
+               free_irq(chip->irq, chip);
        if (chip->bdbars.area)
                snd_dma_free_pages(&chip->bdbars);
        if (chip->addr)
                pci_iounmap(chip->pci, chip->addr);
        if (chip->bmaddr)
                pci_iounmap(chip->pci, chip->bmaddr);
-       if (chip->irq >= 0)
-               free_irq(chip->irq, chip);
        pci_release_regions(chip->pci);
        pci_disable_device(chip->pci);
        kfree(chip);
@@ -1017,7 +1015,6 @@ static int intel8x0m_suspend(struct pci_dev *pci, pm_message_t state)
                snd_pcm_suspend_all(chip->pcm[i]);
        snd_ac97_suspend(chip->ac97);
        if (chip->irq >= 0) {
-               synchronize_irq(chip->irq);
                free_irq(chip->irq, chip);
                chip->irq = -1;
        }
index 10c713d9ac49aa1a151b0093dfa17cce82cfd6ff..f4c85b52bde33ff47c0e53c78a9ac533601c4281 100644 (file)
@@ -2102,7 +2102,6 @@ snd_korg1212_free(struct snd_korg1212 *korg1212)
         snd_korg1212_TurnOffIdleMonitor(korg1212);
 
         if (korg1212->irq >= 0) {
-                synchronize_irq(korg1212->irq);                
                 snd_korg1212_DisableCardInterrupts(korg1212);
                 free_irq(korg1212->irq, korg1212);
                 korg1212->irq = -1;
index 04fa0a68416cf9e16e7ef6697eb13141f2e4b81c..a536c59fbea1e4faed5155ce579ac0ac800e572b 100644 (file)
@@ -2068,7 +2068,7 @@ static int __devinit snd_m3_mixer(struct snd_m3 *chip)
 {
        struct snd_ac97_bus *pbus;
        struct snd_ac97_template ac97;
-       struct snd_ctl_elem_id id;
+       struct snd_ctl_elem_id elem_id;
        int err;
        static struct snd_ac97_bus_ops ops = {
                .write = snd_m3_ac97_write,
@@ -2088,14 +2088,14 @@ static int __devinit snd_m3_mixer(struct snd_m3 *chip)
        schedule_timeout_uninterruptible(msecs_to_jiffies(100));
        snd_ac97_write(chip->ac97, AC97_PCM, 0);
 
-       memset(&id, 0, sizeof(id));
-       id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
-       strcpy(id.name, "Master Playback Switch");
-       chip->master_switch = snd_ctl_find_id(chip->card, &id);
-       memset(&id, 0, sizeof(id));
-       id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
-       strcpy(id.name, "Master Playback Volume");
-       chip->master_volume = snd_ctl_find_id(chip->card, &id);
+       memset(&elem_id, 0, sizeof(elem_id));
+       elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+       strcpy(elem_id.name, "Master Playback Switch");
+       chip->master_switch = snd_ctl_find_id(chip->card, &elem_id);
+       memset(&elem_id, 0, sizeof(elem_id));
+       elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+       strcpy(elem_id.name, "Master Playback Volume");
+       chip->master_volume = snd_ctl_find_id(chip->card, &elem_id);
 
        return 0;
 }
@@ -2542,10 +2542,8 @@ static int snd_m3_free(struct snd_m3 *chip)
        vfree(chip->suspend_mem);
 #endif
 
-       if (chip->irq >= 0) {
-               synchronize_irq(chip->irq);
+       if (chip->irq >= 0)
                free_irq(chip->irq, chip);
-       }
 
        if (chip->iobase)
                pci_release_regions(chip->pci);
@@ -2569,7 +2567,7 @@ static int m3_suspend(struct pci_dev *pci, pm_message_t state)
 {
        struct snd_card *card = pci_get_drvdata(pci);
        struct snd_m3 *chip = card->private_data;
-       int i, index;
+       int i, dsp_index;
 
        if (chip->suspend_mem == NULL)
                return 0;
@@ -2583,12 +2581,12 @@ static int m3_suspend(struct pci_dev *pci, pm_message_t state)
        snd_m3_assp_halt(chip);
 
        /* save dsp image */
-       index = 0;
+       dsp_index = 0;
        for (i = REV_B_CODE_MEMORY_BEGIN; i <= REV_B_CODE_MEMORY_END; i++)
-               chip->suspend_mem[index++] = 
+               chip->suspend_mem[dsp_index++] =
                        snd_m3_assp_read(chip, MEMTYPE_INTERNAL_CODE, i);
        for (i = REV_B_DATA_MEMORY_BEGIN ; i <= REV_B_DATA_MEMORY_END; i++)
-               chip->suspend_mem[index++] = 
+               chip->suspend_mem[dsp_index++] =
                        snd_m3_assp_read(chip, MEMTYPE_INTERNAL_DATA, i);
 
        pci_disable_device(pci);
@@ -2601,7 +2599,7 @@ static int m3_resume(struct pci_dev *pci)
 {
        struct snd_card *card = pci_get_drvdata(pci);
        struct snd_m3 *chip = card->private_data;
-       int i, index;
+       int i, dsp_index;
 
        if (chip->suspend_mem == NULL)
                return 0;
@@ -2625,13 +2623,13 @@ static int m3_resume(struct pci_dev *pci)
        snd_m3_ac97_reset(chip);
 
        /* restore dsp image */
-       index = 0;
+       dsp_index = 0;
        for (i = REV_B_CODE_MEMORY_BEGIN; i <= REV_B_CODE_MEMORY_END; i++)
                snd_m3_assp_write(chip, MEMTYPE_INTERNAL_CODE, i, 
-                                 chip->suspend_mem[index++]);
+                                 chip->suspend_mem[dsp_index++]);
        for (i = REV_B_DATA_MEMORY_BEGIN ; i <= REV_B_DATA_MEMORY_END; i++)
                snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, i, 
-                                 chip->suspend_mem[index++]);
+                                 chip->suspend_mem[dsp_index++]);
 
        /* tell the dma engine to restart itself */
        snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, 
index 7ac654e381dacc951bd7947c7341721d863cdeae..7efb838d18a6b3e78c0b5ceedeccc85887187b2c 100644 (file)
@@ -1439,7 +1439,7 @@ static int snd_nm256_free(struct nm256 *chip)
                snd_nm256_capture_stop(chip);
 
        if (chip->irq >= 0)
-               synchronize_irq(chip->irq);
+               free_irq(chip->irq, chip);
 
        if (chip->cport)
                iounmap(chip->cport);
@@ -1447,8 +1447,6 @@ static int snd_nm256_free(struct nm256 *chip)
                iounmap(chip->buffer);
        release_and_free_resource(chip->res_cport);
        release_and_free_resource(chip->res_buffer);
-       if (chip->irq >= 0)
-               free_irq(chip->irq, chip);
 
        pci_disable_device(chip->pci);
        kfree(chip->ac97_regs);
diff --git a/sound/pci/oxygen/cs4362a.h b/sound/pci/oxygen/cs4362a.h
new file mode 100644 (file)
index 0000000..6a4fedf
--- /dev/null
@@ -0,0 +1,69 @@
+/* register 01h */
+#define CS4362A_PDN            0x01
+#define CS4362A_DAC1_DIS       0x02
+#define CS4362A_DAC2_DIS       0x04
+#define CS4362A_DAC3_DIS       0x08
+#define CS4362A_MCLKDIV                0x20
+#define CS4362A_FREEZE         0x40
+#define CS4362A_CPEN           0x80
+/* register 02h */
+#define CS4362A_DIF_MASK       0x70
+#define CS4362A_DIF_LJUST      0x00
+#define CS4362A_DIF_I2S                0x10
+#define CS4362A_DIF_RJUST_16   0x20
+#define CS4362A_DIF_RJUST_24   0x30
+#define CS4362A_DIF_RJUST_20   0x40
+#define CS4362A_DIF_RJUST_18   0x50
+/* register 03h */
+#define CS4362A_MUTEC_MASK     0x03
+#define CS4362A_MUTEC_6                0x00
+#define CS4362A_MUTEC_1                0x01
+#define CS4362A_MUTEC_3                0x03
+#define CS4362A_AMUTE          0x04
+#define CS4362A_MUTEC_POL      0x08
+#define CS4362A_RMP_UP         0x10
+#define CS4362A_SNGLVOL                0x20
+#define CS4362A_ZERO_CROSS     0x40
+#define CS4362A_SOFT_RAMP      0x80
+/* register 04h */
+#define CS4362A_RMP_DN         0x01
+#define CS4362A_DEM_MASK       0x06
+#define CS4362A_DEM_NONE       0x00
+#define CS4362A_DEM_44100      0x02
+#define CS4362A_DEM_48000      0x04
+#define CS4362A_DEM_32000      0x06
+#define CS4362A_FILT_SEL       0x10
+/* register 05h */
+#define CS4362A_INV_A1         0x01
+#define CS4362A_INV_B1         0x02
+#define CS4362A_INV_A2         0x04
+#define CS4362A_INV_B2         0x08
+#define CS4362A_INV_A3         0x10
+#define CS4362A_INV_B3         0x20
+/* register 06h */
+#define CS4362A_FM_MASK                0x03
+#define CS4362A_FM_SINGLE      0x00
+#define CS4362A_FM_DOUBLE      0x01
+#define CS4362A_FM_QUAD                0x02
+#define CS4362A_FM_DSD         0x03
+#define CS4362A_ATAPI_MASK     0x7c
+#define CS4362A_ATAPI_B_MUTE   0x00
+#define CS4362A_ATAPI_B_R      0x04
+#define CS4362A_ATAPI_B_L      0x08
+#define CS4362A_ATAPI_B_LR     0x0c
+#define CS4362A_ATAPI_A_MUTE   0x00
+#define CS4362A_ATAPI_A_R      0x10
+#define CS4362A_ATAPI_A_L      0x20
+#define CS4362A_ATAPI_A_LR     0x30
+#define CS4362A_ATAPI_MIX_LR_VOL 0x40
+#define CS4362A_A_EQ_B         0x80
+/* register 07h */
+#define CS4362A_VOL_MASK               0x7f
+#define CS4362A_MUTE                   0x80
+/* register 08h: like 07h */
+/* registers 09h..0Bh: like 06h..08h */
+/* registers 0Ch..0Eh: like 06h..08h */
+/* register 12h */
+#define CS4362A_REV_MASK       0x07
+#define CS4362A_PART_MASK      0xf8
+#define CS4362A_PART_CS4362A   0x50
diff --git a/sound/pci/oxygen/cs4398.h b/sound/pci/oxygen/cs4398.h
new file mode 100644 (file)
index 0000000..5faf5ef
--- /dev/null
@@ -0,0 +1,69 @@
+/* register 1 */
+#define CS4398_REV_MASK                0x07
+#define CS4398_PART_MASK       0xf8
+#define CS4398_PART_CS4398     0x70
+/* register 2 */
+#define CS4398_FM_MASK         0x03
+#define CS4398_FM_SINGLE       0x00
+#define CS4398_FM_DOUBLE       0x01
+#define CS4398_FM_QUAD         0x02
+#define CS4398_FM_DSD          0x03
+#define CS4398_DEM_MASK                0x0c
+#define CS4398_DEM_NONE                0x00
+#define CS4398_DEM_44100       0x04
+#define CS4398_DEM_48000       0x08
+#define CS4398_DEM_32000       0x0c
+#define CS4398_DIF_MASK                0x70
+#define CS4398_DIF_LJUST       0x00
+#define CS4398_DIF_I2S         0x10
+#define CS4398_DIF_RJUST_16    0x20
+#define CS4398_DIF_RJUST_24    0x30
+#define CS4398_DIF_RJUST_20    0x40
+#define CS4398_DIF_RJUST_18    0x50
+#define CS4398_DSD_SRC         0x80
+/* register 3 */
+#define CS4398_ATAPI_MASK      0x1f
+#define CS4398_ATAPI_B_MUTE    0x00
+#define CS4398_ATAPI_B_R       0x01
+#define CS4398_ATAPI_B_L       0x02
+#define CS4398_ATAPI_B_LR      0x03
+#define CS4398_ATAPI_A_MUTE    0x00
+#define CS4398_ATAPI_A_R       0x04
+#define CS4398_ATAPI_A_L       0x08
+#define CS4398_ATAPI_A_LR      0x0c
+#define CS4398_ATAPI_MIX_LR_VOL        0x10
+#define CS4398_INVERT_B                0x20
+#define CS4398_INVERT_A                0x40
+#define CS4398_VOL_B_EQ_A      0x80
+/* register 4 */
+#define CS4398_MUTEP_MASK      0x03
+#define CS4398_MUTEP_AUTO      0x00
+#define CS4398_MUTEP_LOW       0x02
+#define CS4398_MUTEP_HIGH      0x03
+#define CS4398_MUTE_B          0x08
+#define CS4398_MUTE_A          0x10
+#define CS4398_MUTEC_A_EQ_B    0x20
+#define CS4398_DAMUTE          0x40
+#define CS4398_PAMUTE          0x80
+/* register 5 */
+#define CS4398_VOL_A_MASK      0xff
+/* register 6 */
+#define CS4398_VOL_B_MASK      0xff
+/* register 7 */
+#define CS4398_DIR_DSD         0x01
+#define CS4398_FILT_SEL                0x04
+#define CS4398_RMP_DN          0x10
+#define CS4398_RMP_UP          0x20
+#define CS4398_ZERO_CROSS      0x40
+#define CS4398_SOFT_RAMP       0x80
+/* register 8 */
+#define CS4398_MCLKDIV3                0x08
+#define CS4398_MCLKDIV2                0x10
+#define CS4398_FREEZE          0x20
+#define CS4398_CPEN            0x40
+#define CS4398_PDN             0x80
+/* register 9 */
+#define CS4398_DSD_PM_EN       0x01
+#define CS4398_DSD_PM_MODE     0x02
+#define CS4398_INVALID_DSD     0x04
+#define CS4398_STATIC_DSD      0x08
index 666f69a3312e9a3c08cd90ac91008105f482fa3d..090dd4354a2838fa2e818265270965c829460c34 100644 (file)
@@ -66,12 +66,12 @@ static void hifier_init(struct oxygen *chip)
 {
        struct hifier_data *data = chip->model_data;
 
-       data->ak4396_ctl2 = AK4396_DEM_OFF | AK4396_DFS_NORMAL;
+       data->ak4396_ctl2 = AK4396_SMUTE | AK4396_DEM_OFF | AK4396_DFS_NORMAL;
        ak4396_write(chip, AK4396_CONTROL_1, AK4396_DIF_24_MSB | AK4396_RSTN);
        ak4396_write(chip, AK4396_CONTROL_2, data->ak4396_ctl2);
        ak4396_write(chip, AK4396_CONTROL_3, AK4396_PCM);
-       ak4396_write(chip, AK4396_LCH_ATT, 0xff);
-       ak4396_write(chip, AK4396_RCH_ATT, 0xff);
+       ak4396_write(chip, AK4396_LCH_ATT, 0);
+       ak4396_write(chip, AK4396_RCH_ATT, 0);
 
        snd_component_add(chip->card, "AK4396");
        snd_component_add(chip->card, "CS5340");
@@ -127,22 +127,8 @@ static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0);
 
 static int hifier_control_filter(struct snd_kcontrol_new *template)
 {
-       if (!strcmp(template->name, "Master Playback Volume")) {
-               template->access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
-               template->tlv.p = ak4396_db_scale;
-       } else if (!strcmp(template->name, "Stereo Upmixing")) {
+       if (!strcmp(template->name, "Stereo Upmixing"))
                return 1; /* stereo only - we don't need upmixing */
-       } else if (!strcmp(template->name,
-                          SNDRV_CTL_NAME_IEC958("", CAPTURE, MASK)) ||
-                  !strcmp(template->name,
-                          SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT))) {
-               return 1; /* no digital input */
-       }
-       return 0;
-}
-
-static int hifier_mixer_init(struct oxygen *chip)
-{
        return 0;
 }
 
@@ -153,18 +139,20 @@ static const struct oxygen_model model_hifier = {
        .owner = THIS_MODULE,
        .init = hifier_init,
        .control_filter = hifier_control_filter,
-       .mixer_init = hifier_mixer_init,
        .cleanup = hifier_cleanup,
        .set_dac_params = set_ak4396_params,
        .set_adc_params = set_cs5340_params,
        .update_dac_volume = update_ak4396_volume,
        .update_dac_mute = update_ak4396_mute,
+       .dac_tlv = ak4396_db_scale,
        .model_data_size = sizeof(struct hifier_data),
+       .pcm_dev_cfg = PLAYBACK_0_TO_I2S |
+                      PLAYBACK_1_TO_SPDIF |
+                      CAPTURE_0_FROM_I2S_1,
        .dac_channels = 2,
-       .used_channels = OXYGEN_CHANNEL_A |
-                        OXYGEN_CHANNEL_SPDIF |
-                        OXYGEN_CHANNEL_MULTICH,
-       .function_flags = 0,
+       .dac_volume_min = 0,
+       .dac_volume_max = 255,
+       .function_flags = OXYGEN_FUNCTION_SPI,
        .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
        .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
 };
@@ -181,7 +169,7 @@ static int __devinit hifier_probe(struct pci_dev *pci,
                ++dev;
                return -ENOENT;
        }
-       err = oxygen_pci_probe(pci, index[dev], id[dev], 0, &model_hifier);
+       err = oxygen_pci_probe(pci, index[dev], id[dev], &model_hifier);
        if (err >= 0)
                ++dev;
        return err;
index 9a9941bb0460c08575385c9f1aa8d4a33cf5ac17..63f185c1ed1ed899a0af6786d4092731a87f0c26 100644 (file)
@@ -39,7 +39,7 @@
 #include <sound/tlv.h>
 #include "oxygen.h"
 #include "ak4396.h"
-#include "cm9780.h"
+#include "wm8785.h"
 
 MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
 MODULE_DESCRIPTION("C-Media CMI8788 driver");
@@ -78,49 +78,6 @@ MODULE_DEVICE_TABLE(pci, oxygen_ids);
 #define GPIO_AK5385_DFS_DOUBLE 0x0001
 #define GPIO_AK5385_DFS_QUAD   0x0002
 
-#define GPIO_LINE_MUTE         CM9780_GPO0
-
-#define WM8785_R0      0
-#define WM8785_R1      1
-#define WM8785_R2      2
-#define WM8785_R7      7
-
-/* R0 */
-#define WM8785_MCR_MASK                0x007
-#define WM8785_MCR_SLAVE       0x000
-#define WM8785_MCR_MASTER_128  0x001
-#define WM8785_MCR_MASTER_192  0x002
-#define WM8785_MCR_MASTER_256  0x003
-#define WM8785_MCR_MASTER_384  0x004
-#define WM8785_MCR_MASTER_512  0x005
-#define WM8785_MCR_MASTER_768  0x006
-#define WM8785_OSR_MASK                0x018
-#define WM8785_OSR_SINGLE      0x000
-#define WM8785_OSR_DOUBLE      0x008
-#define WM8785_OSR_QUAD                0x010
-#define WM8785_FORMAT_MASK     0x060
-#define WM8785_FORMAT_RJUST    0x000
-#define WM8785_FORMAT_LJUST    0x020
-#define WM8785_FORMAT_I2S      0x040
-#define WM8785_FORMAT_DSP      0x060
-/* R1 */
-#define WM8785_WL_MASK         0x003
-#define WM8785_WL_16           0x000
-#define WM8785_WL_20           0x001
-#define WM8785_WL_24           0x002
-#define WM8785_WL_32           0x003
-#define WM8785_LRP             0x004
-#define WM8785_BCLKINV         0x008
-#define WM8785_LRSWAP          0x010
-#define WM8785_DEVNO_MASK      0x0e0
-/* R2 */
-#define WM8785_HPFR            0x001
-#define WM8785_HPFL            0x002
-#define WM8785_SDODIS          0x004
-#define WM8785_PWRDNR          0x008
-#define WM8785_PWRDNL          0x010
-#define WM8785_TDM_MASK                0x1c0
-
 struct generic_data {
        u8 ak4396_ctl2;
 };
@@ -155,7 +112,7 @@ static void ak4396_init(struct oxygen *chip)
        struct generic_data *data = chip->model_data;
        unsigned int i;
 
-       data->ak4396_ctl2 = AK4396_DEM_OFF | AK4396_DFS_NORMAL;
+       data->ak4396_ctl2 = AK4396_SMUTE | AK4396_DEM_OFF | AK4396_DFS_NORMAL;
        for (i = 0; i < 4; ++i) {
                ak4396_write(chip, i,
                             AK4396_CONTROL_1, AK4396_DIF_24_MSB | AK4396_RSTN);
@@ -163,8 +120,8 @@ static void ak4396_init(struct oxygen *chip)
                             AK4396_CONTROL_2, data->ak4396_ctl2);
                ak4396_write(chip, i,
                             AK4396_CONTROL_3, AK4396_PCM);
-               ak4396_write(chip, i, AK4396_LCH_ATT, 0xff);
-               ak4396_write(chip, i, AK4396_RCH_ATT, 0xff);
+               ak4396_write(chip, i, AK4396_LCH_ATT, 0);
+               ak4396_write(chip, i, AK4396_RCH_ATT, 0);
        }
        snd_component_add(chip->card, "AK4396");
 }
@@ -185,23 +142,16 @@ static void wm8785_init(struct oxygen *chip)
        snd_component_add(chip->card, "WM8785");
 }
 
-static void cmi9780_init(struct oxygen *chip)
-{
-       oxygen_ac97_clear_bits(chip, 0, CM9780_GPIO_STATUS, GPIO_LINE_MUTE);
-}
-
 static void generic_init(struct oxygen *chip)
 {
        ak4396_init(chip);
        wm8785_init(chip);
-       cmi9780_init(chip);
 }
 
 static void meridian_init(struct oxygen *chip)
 {
        ak4396_init(chip);
        ak5385_init(chip);
-       cmi9780_init(chip);
 }
 
 static void generic_cleanup(struct oxygen *chip)
@@ -297,59 +247,32 @@ static void set_ak5385_params(struct oxygen *chip,
                              value, GPIO_AK5385_DFS_MASK);
 }
 
-static void cmi9780_switch_hook(struct oxygen *chip, unsigned int codec,
-                               unsigned int reg, int mute)
-{
-       if (codec != 0)
-               return;
-       switch (reg) {
-       case AC97_LINE:
-               oxygen_write_ac97_masked(chip, 0, CM9780_GPIO_STATUS,
-                                        mute ? GPIO_LINE_MUTE : 0,
-                                        GPIO_LINE_MUTE);
-               break;
-       case AC97_MIC:
-       case AC97_CD:
-       case AC97_AUX:
-               if (!mute)
-                       oxygen_ac97_set_bits(chip, 0, CM9780_GPIO_STATUS,
-                                            GPIO_LINE_MUTE);
-               break;
-       }
-}
-
 static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0);
 
-static int ak4396_control_filter(struct snd_kcontrol_new *template)
-{
-       if (!strcmp(template->name, "Master Playback Volume")) {
-               template->access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
-               template->tlv.p = ak4396_db_scale;
-       }
-       return 0;
-}
-
 static const struct oxygen_model model_generic = {
        .shortname = "C-Media CMI8788",
        .longname = "C-Media Oxygen HD Audio",
        .chip = "CMI8788",
        .owner = THIS_MODULE,
        .init = generic_init,
-       .control_filter = ak4396_control_filter,
        .cleanup = generic_cleanup,
        .set_dac_params = set_ak4396_params,
        .set_adc_params = set_wm8785_params,
        .update_dac_volume = update_ak4396_volume,
        .update_dac_mute = update_ak4396_mute,
-       .ac97_switch_hook = cmi9780_switch_hook,
+       .dac_tlv = ak4396_db_scale,
        .model_data_size = sizeof(struct generic_data),
+       .pcm_dev_cfg = PLAYBACK_0_TO_I2S |
+                      PLAYBACK_1_TO_SPDIF |
+                      PLAYBACK_2_TO_AC97_1 |
+                      CAPTURE_0_FROM_I2S_1 |
+                      CAPTURE_1_FROM_SPDIF |
+                      CAPTURE_2_FROM_AC97_1,
        .dac_channels = 8,
-       .used_channels = OXYGEN_CHANNEL_A |
-                        OXYGEN_CHANNEL_C |
-                        OXYGEN_CHANNEL_SPDIF |
-                        OXYGEN_CHANNEL_MULTICH |
-                        OXYGEN_CHANNEL_AC97,
-       .function_flags = OXYGEN_FUNCTION_ENABLE_SPI_4_5,
+       .dac_volume_min = 0,
+       .dac_volume_max = 255,
+       .function_flags = OXYGEN_FUNCTION_SPI |
+                         OXYGEN_FUNCTION_ENABLE_SPI_4_5,
        .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
        .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
 };
@@ -359,21 +282,25 @@ static const struct oxygen_model model_meridian = {
        .chip = "CMI8788",
        .owner = THIS_MODULE,
        .init = meridian_init,
-       .control_filter = ak4396_control_filter,
        .cleanup = generic_cleanup,
        .set_dac_params = set_ak4396_params,
        .set_adc_params = set_ak5385_params,
        .update_dac_volume = update_ak4396_volume,
        .update_dac_mute = update_ak4396_mute,
-       .ac97_switch_hook = cmi9780_switch_hook,
+       .dac_tlv = ak4396_db_scale,
        .model_data_size = sizeof(struct generic_data),
+       .pcm_dev_cfg = PLAYBACK_0_TO_I2S |
+                      PLAYBACK_1_TO_SPDIF |
+                      PLAYBACK_2_TO_AC97_1 |
+                      CAPTURE_0_FROM_I2S_2 |
+                      CAPTURE_1_FROM_SPDIF |
+                      CAPTURE_2_FROM_AC97_1,
        .dac_channels = 8,
-       .used_channels = OXYGEN_CHANNEL_B |
-                        OXYGEN_CHANNEL_C |
-                        OXYGEN_CHANNEL_SPDIF |
-                        OXYGEN_CHANNEL_MULTICH |
-                        OXYGEN_CHANNEL_AC97,
-       .function_flags = OXYGEN_FUNCTION_ENABLE_SPI_4_5,
+       .dac_volume_min = 0,
+       .dac_volume_max = 255,
+       .misc_flags = OXYGEN_MISC_MIDI,
+       .function_flags = OXYGEN_FUNCTION_SPI |
+                         OXYGEN_FUNCTION_ENABLE_SPI_4_5,
        .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
        .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
 };
@@ -392,7 +319,7 @@ static int __devinit generic_oxygen_probe(struct pci_dev *pci,
                return -ENOENT;
        }
        is_meridian = pci_id->driver_data;
-       err = oxygen_pci_probe(pci, index[dev], id[dev], is_meridian,
+       err = oxygen_pci_probe(pci, index[dev], id[dev],
                               is_meridian ? &model_meridian : &model_generic);
        if (err >= 0)
                ++dev;
index ad50fb8b206b5a356c082682db51e8e13be25640..a71c6e059260543c08b172f4fd71e3bdd0f5eef8 100644 (file)
 #define PCM_AC97       5
 #define PCM_COUNT      6
 
+/* model-specific configuration of outputs/inputs */
+#define PLAYBACK_0_TO_I2S      0x001
+#define PLAYBACK_1_TO_SPDIF    0x004
+#define PLAYBACK_2_TO_AC97_1   0x008
+#define CAPTURE_0_FROM_I2S_1   0x010
+#define CAPTURE_0_FROM_I2S_2   0x020
+#define CAPTURE_1_FROM_SPDIF   0x080
+#define CAPTURE_2_FROM_I2S_2   0x100
+#define CAPTURE_2_FROM_AC97_1  0x200
+
 enum {
        CONTROL_SPDIF_PCM,
        CONTROL_SPDIF_INPUT_BITS,
@@ -87,12 +97,16 @@ struct oxygen_model {
                               struct snd_pcm_hw_params *params);
        void (*update_dac_volume)(struct oxygen *chip);
        void (*update_dac_mute)(struct oxygen *chip);
-       void (*ac97_switch_hook)(struct oxygen *chip, unsigned int codec,
-                                unsigned int reg, int mute);
        void (*gpio_changed)(struct oxygen *chip);
+       void (*ac97_switch)(struct oxygen *chip,
+                           unsigned int reg, unsigned int mute);
+       const unsigned int *dac_tlv;
        size_t model_data_size;
+       unsigned int pcm_dev_cfg;
        u8 dac_channels;
-       u8 used_channels;
+       u8 dac_volume_min;
+       u8 dac_volume_max;
+       u8 misc_flags;
        u8 function_flags;
        u16 dac_i2s_format;
        u16 adc_i2s_format;
@@ -100,7 +114,7 @@ struct oxygen_model {
 
 /* oxygen_lib.c */
 
-int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, int midi,
+int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
                     const struct oxygen_model *model);
 void oxygen_pci_remove(struct pci_dev *pci);
 
@@ -137,6 +151,7 @@ void oxygen_write_ac97_masked(struct oxygen *chip, unsigned int codec,
                              unsigned int index, u16 data, u16 mask);
 
 void oxygen_write_spi(struct oxygen *chip, u8 control, unsigned int data);
+void oxygen_write_i2c(struct oxygen *chip, u8 device, u8 map, u8 data);
 
 static inline void oxygen_set_bits8(struct oxygen *chip,
                                    unsigned int reg, u8 value)
index 74e23ef9c9467aaf3a54bacb2beb7315a4d36ea8..5569606ee87ff22bfb0ac9b9a15e9635e7bd4ed4 100644 (file)
@@ -190,12 +190,31 @@ void oxygen_write_spi(struct oxygen *chip, u8 control, unsigned int data)
                --count;
        }
 
-       spin_lock_irq(&chip->reg_lock);
        oxygen_write8(chip, OXYGEN_SPI_DATA1, data);
        oxygen_write8(chip, OXYGEN_SPI_DATA2, data >> 8);
        if (control & OXYGEN_SPI_DATA_LENGTH_3)
                oxygen_write8(chip, OXYGEN_SPI_DATA3, data >> 16);
        oxygen_write8(chip, OXYGEN_SPI_CONTROL, control);
-       spin_unlock_irq(&chip->reg_lock);
 }
 EXPORT_SYMBOL(oxygen_write_spi);
+
+void oxygen_write_i2c(struct oxygen *chip, u8 device, u8 map, u8 data)
+{
+       unsigned long timeout;
+
+       /* should not need more than about 300 us */
+       timeout = jiffies + msecs_to_jiffies(1);
+       do {
+               if (!(oxygen_read16(chip, OXYGEN_2WIRE_BUS_STATUS)
+                     & OXYGEN_2WIRE_BUSY))
+                       break;
+               udelay(1);
+               cond_resched();
+       } while (time_after_eq(timeout, jiffies));
+
+       oxygen_write8(chip, OXYGEN_2WIRE_MAP, map);
+       oxygen_write8(chip, OXYGEN_2WIRE_DATA, data);
+       oxygen_write8(chip, OXYGEN_2WIRE_CONTROL,
+                     device | OXYGEN_2WIRE_DIR_WRITE);
+}
+EXPORT_SYMBOL(oxygen_write_i2c);
index 78c21155218ecb761a4055fbed2b1756a297d1a3..897697d43506d2354b2ffc954f58232d97b3c556 100644 (file)
@@ -221,7 +221,8 @@ static void oxygen_init(struct oxygen *chip)
 
        chip->dac_routing = 1;
        for (i = 0; i < 8; ++i)
-               chip->dac_volume[i] = 0xff;
+               chip->dac_volume[i] = chip->model->dac_volume_min;
+       chip->dac_mute = 1;
        chip->spdif_playback_enable = 1;
        chip->spdif_bits = OXYGEN_SPDIF_C | OXYGEN_SPDIF_ORIGINAL |
                (IEC958_AES1_CON_PCM_CODER << OXYGEN_SPDIF_CATEGORY_SHIFT);
@@ -240,12 +241,12 @@ static void oxygen_init(struct oxygen *chip)
        chip->has_ac97_0 = (i & OXYGEN_AC97_CODEC_0) != 0;
        chip->has_ac97_1 = (i & OXYGEN_AC97_CODEC_1) != 0;
 
-       oxygen_set_bits8(chip, OXYGEN_FUNCTION,
-                        OXYGEN_FUNCTION_RESET_CODEC |
-                        chip->model->function_flags);
        oxygen_write8_masked(chip, OXYGEN_FUNCTION,
-                            OXYGEN_FUNCTION_SPI,
-                            OXYGEN_FUNCTION_2WIRE_SPI_MASK);
+                            OXYGEN_FUNCTION_RESET_CODEC |
+                            chip->model->function_flags,
+                            OXYGEN_FUNCTION_RESET_CODEC |
+                            OXYGEN_FUNCTION_2WIRE_SPI_MASK |
+                            OXYGEN_FUNCTION_ENABLE_SPI_4_5);
        oxygen_write8(chip, OXYGEN_DMA_STATUS, 0);
        oxygen_write8(chip, OXYGEN_DMA_PAUSE, 0);
        oxygen_write8(chip, OXYGEN_PLAY_CHANNELS,
@@ -253,11 +254,13 @@ static void oxygen_init(struct oxygen *chip)
                      OXYGEN_DMA_A_BURST_8 |
                      OXYGEN_DMA_MULTICH_BURST_8);
        oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, 0);
-       oxygen_write8_masked(chip, OXYGEN_MISC, 0,
+       oxygen_write8_masked(chip, OXYGEN_MISC,
+                            chip->model->misc_flags,
                             OXYGEN_MISC_WRITE_PCI_SUBID |
                             OXYGEN_MISC_REC_C_FROM_SPDIF |
                             OXYGEN_MISC_REC_B_FROM_AC97 |
-                            OXYGEN_MISC_REC_A_FROM_MULTICH);
+                            OXYGEN_MISC_REC_A_FROM_MULTICH |
+                            OXYGEN_MISC_MIDI);
        oxygen_write8(chip, OXYGEN_REC_FORMAT,
                      (OXYGEN_FORMAT_16 << OXYGEN_REC_FORMAT_A_SHIFT) |
                      (OXYGEN_FORMAT_16 << OXYGEN_REC_FORMAT_B_SHIFT) |
@@ -267,35 +270,49 @@ static void oxygen_init(struct oxygen *chip)
                      (OXYGEN_FORMAT_16 << OXYGEN_MULTICH_FORMAT_SHIFT));
        oxygen_write8(chip, OXYGEN_REC_CHANNELS, OXYGEN_REC_CHANNELS_2_2_2);
        oxygen_write16(chip, OXYGEN_I2S_MULTICH_FORMAT,
-                      OXYGEN_RATE_48000 | OXYGEN_I2S_FORMAT_LJUST |
-                      OXYGEN_I2S_MCLK_128 | OXYGEN_I2S_BITS_16 |
-                      OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64);
-       oxygen_write16(chip, OXYGEN_I2S_A_FORMAT,
-                      OXYGEN_RATE_48000 | OXYGEN_I2S_FORMAT_LJUST |
-                      OXYGEN_I2S_MCLK_128 | OXYGEN_I2S_BITS_16 |
-                      OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64);
-       oxygen_write16(chip, OXYGEN_I2S_B_FORMAT,
-                      OXYGEN_RATE_48000 | OXYGEN_I2S_FORMAT_LJUST |
-                      OXYGEN_I2S_MCLK_128 | OXYGEN_I2S_BITS_16 |
+                      OXYGEN_RATE_48000 | chip->model->dac_i2s_format |
+                      OXYGEN_I2S_MCLK_256 | OXYGEN_I2S_BITS_16 |
                       OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64);
+       if (chip->model->pcm_dev_cfg & CAPTURE_0_FROM_I2S_1)
+               oxygen_write16(chip, OXYGEN_I2S_A_FORMAT,
+                              OXYGEN_RATE_48000 | chip->model->adc_i2s_format |
+                              OXYGEN_I2S_MCLK_256 | OXYGEN_I2S_BITS_16 |
+                              OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64);
+       else
+               oxygen_write16(chip, OXYGEN_I2S_A_FORMAT,
+                              OXYGEN_I2S_MASTER | OXYGEN_I2S_MUTE_MCLK);
+       if (chip->model->pcm_dev_cfg & (CAPTURE_0_FROM_I2S_2 |
+                                       CAPTURE_2_FROM_I2S_2))
+               oxygen_write16(chip, OXYGEN_I2S_B_FORMAT,
+                              OXYGEN_RATE_48000 | chip->model->adc_i2s_format |
+                              OXYGEN_I2S_MCLK_256 | OXYGEN_I2S_BITS_16 |
+                              OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64);
+       else
+               oxygen_write16(chip, OXYGEN_I2S_B_FORMAT,
+                              OXYGEN_I2S_MASTER | OXYGEN_I2S_MUTE_MCLK);
        oxygen_write16(chip, OXYGEN_I2S_C_FORMAT,
-                      OXYGEN_RATE_48000 | OXYGEN_I2S_FORMAT_LJUST |
-                      OXYGEN_I2S_MCLK_128 | OXYGEN_I2S_BITS_16 |
-                      OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64);
-       oxygen_write32_masked(chip, OXYGEN_SPDIF_CONTROL,
-                             OXYGEN_SPDIF_SENSE_MASK |
-                             OXYGEN_SPDIF_LOCK_MASK |
-                             OXYGEN_SPDIF_RATE_MASK |
-                             OXYGEN_SPDIF_LOCK_PAR |
-                             OXYGEN_SPDIF_IN_CLOCK_96,
-                             OXYGEN_SPDIF_OUT_ENABLE |
-                             OXYGEN_SPDIF_LOOPBACK |
-                             OXYGEN_SPDIF_SENSE_MASK |
-                             OXYGEN_SPDIF_LOCK_MASK |
-                             OXYGEN_SPDIF_RATE_MASK |
-                             OXYGEN_SPDIF_SENSE_PAR |
-                             OXYGEN_SPDIF_LOCK_PAR |
-                             OXYGEN_SPDIF_IN_CLOCK_MASK);
+                      OXYGEN_I2S_MASTER | OXYGEN_I2S_MUTE_MCLK);
+       oxygen_clear_bits32(chip, OXYGEN_SPDIF_CONTROL,
+                           OXYGEN_SPDIF_OUT_ENABLE |
+                           OXYGEN_SPDIF_LOOPBACK);
+       if (chip->model->pcm_dev_cfg & CAPTURE_1_FROM_SPDIF)
+               oxygen_write32_masked(chip, OXYGEN_SPDIF_CONTROL,
+                                     OXYGEN_SPDIF_SENSE_MASK |
+                                     OXYGEN_SPDIF_LOCK_MASK |
+                                     OXYGEN_SPDIF_RATE_MASK |
+                                     OXYGEN_SPDIF_LOCK_PAR |
+                                     OXYGEN_SPDIF_IN_CLOCK_96,
+                                     OXYGEN_SPDIF_SENSE_MASK |
+                                     OXYGEN_SPDIF_LOCK_MASK |
+                                     OXYGEN_SPDIF_RATE_MASK |
+                                     OXYGEN_SPDIF_SENSE_PAR |
+                                     OXYGEN_SPDIF_LOCK_PAR |
+                                     OXYGEN_SPDIF_IN_CLOCK_MASK);
+       else
+               oxygen_clear_bits32(chip, OXYGEN_SPDIF_CONTROL,
+                                   OXYGEN_SPDIF_SENSE_MASK |
+                                   OXYGEN_SPDIF_LOCK_MASK |
+                                   OXYGEN_SPDIF_RATE_MASK);
        oxygen_write32(chip, OXYGEN_SPDIF_OUTPUT_BITS, chip->spdif_bits);
        oxygen_clear_bits8(chip, OXYGEN_MPU401_CONTROL, OXYGEN_MPU401_LOOPBACK);
        oxygen_write8(chip, OXYGEN_GPI_INTERRUPT_MASK, 0);
@@ -318,9 +335,12 @@ static void oxygen_init(struct oxygen *chip)
                      (2 << OXYGEN_A_MONITOR_ROUTE_2_SHIFT) |
                      (3 << OXYGEN_A_MONITOR_ROUTE_3_SHIFT));
 
-       oxygen_write8(chip, OXYGEN_AC97_INTERRUPT_MASK,
-                     OXYGEN_AC97_INT_READ_DONE |
-                     OXYGEN_AC97_INT_WRITE_DONE);
+       if (chip->has_ac97_0 | chip->has_ac97_1)
+               oxygen_write8(chip, OXYGEN_AC97_INTERRUPT_MASK,
+                             OXYGEN_AC97_INT_READ_DONE |
+                             OXYGEN_AC97_INT_WRITE_DONE);
+       else
+               oxygen_write8(chip, OXYGEN_AC97_INTERRUPT_MASK, 0);
        oxygen_write32(chip, OXYGEN_AC97_OUT_CONFIG, 0);
        oxygen_write32(chip, OXYGEN_AC97_IN_CONFIG, 0);
        if (!(chip->has_ac97_0 | chip->has_ac97_1))
@@ -351,6 +371,8 @@ static void oxygen_init(struct oxygen *chip)
                oxygen_write_ac97(chip, 0, AC97_REC_GAIN, 0x8000);
                oxygen_write_ac97(chip, 0, AC97_CENTER_LFE_MASTER, 0x8080);
                oxygen_write_ac97(chip, 0, AC97_SURROUND_MASTER, 0x8080);
+               oxygen_ac97_clear_bits(chip, 0, CM9780_GPIO_STATUS,
+                                      CM9780_GPO0);
                /* power down unused ADCs and DACs */
                oxygen_ac97_set_bits(chip, 0, AC97_POWERDOWN,
                                     AC97_PD_PR0 | AC97_PD_PR1);
@@ -388,10 +410,8 @@ static void oxygen_card_free(struct snd_card *card)
        oxygen_write16(chip, OXYGEN_DMA_STATUS, 0);
        oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, 0);
        spin_unlock_irq(&chip->reg_lock);
-       if (chip->irq >= 0) {
+       if (chip->irq >= 0)
                free_irq(chip->irq, chip);
-               synchronize_irq(chip->irq);
-       }
        flush_scheduled_work();
        chip->model->cleanup(chip);
        mutex_destroy(&chip->mutex);
@@ -400,7 +420,7 @@ static void oxygen_card_free(struct snd_card *card)
 }
 
 int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
-                    int midi, const struct oxygen_model *model)
+                    const struct oxygen_model *model)
 {
        struct snd_card *card;
        struct oxygen *chip;
@@ -472,9 +492,7 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
        if (err < 0)
                goto err_card;
 
-       oxygen_write8_masked(chip, OXYGEN_MISC,
-                            midi ? OXYGEN_MISC_MIDI : 0, OXYGEN_MISC_MIDI);
-       if (midi) {
+       if (model->misc_flags & OXYGEN_MISC_MIDI) {
                err = snd_mpu401_uart_new(card, 0, MPU401_HW_CMIPCI,
                                          chip->addr + OXYGEN_MPU401,
                                          MPU401_INFO_INTEGRATED, 0, 0,
@@ -486,7 +504,10 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
        oxygen_proc_init(chip);
 
        spin_lock_irq(&chip->reg_lock);
-       chip->interrupt_mask |= OXYGEN_INT_SPDIF_IN_DETECT | OXYGEN_INT_AC97;
+       if (chip->model->pcm_dev_cfg & CAPTURE_1_FROM_SPDIF)
+               chip->interrupt_mask |= OXYGEN_INT_SPDIF_IN_DETECT;
+       if (chip->has_ac97_0 | chip->has_ac97_1)
+               chip->interrupt_mask |= OXYGEN_INT_AC97;
        oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, chip->interrupt_mask);
        spin_unlock_irq(&chip->reg_lock);
 
index a8e4623415d9a2e34f8e4539f849c14e30108caa..cc0cddadd589b259d0a4ff13334c70ce8f7e681f 100644 (file)
@@ -32,8 +32,8 @@ static int dac_volume_info(struct snd_kcontrol *ctl,
 
        info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
        info->count = chip->model->dac_channels;
-       info->value.integer.min = 0;
-       info->value.integer.max = 0xff;
+       info->value.integer.min = chip->model->dac_volume_min;
+       info->value.integer.max = chip->model->dac_volume_max;
        return 0;
 }
 
@@ -446,6 +446,50 @@ static int spdif_loopback_put(struct snd_kcontrol *ctl,
        return changed;
 }
 
+static int monitor_volume_info(struct snd_kcontrol *ctl,
+                              struct snd_ctl_elem_info *info)
+{
+       info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       info->count = 1;
+       info->value.integer.min = 0;
+       info->value.integer.max = 1;
+       return 0;
+}
+
+static int monitor_get(struct snd_kcontrol *ctl,
+                      struct snd_ctl_elem_value *value)
+{
+       struct oxygen *chip = ctl->private_data;
+       u8 bit = ctl->private_value;
+       int invert = ctl->private_value & (1 << 8);
+
+       value->value.integer.value[0] =
+               !!invert ^ !!(oxygen_read8(chip, OXYGEN_ADC_MONITOR) & bit);
+       return 0;
+}
+
+static int monitor_put(struct snd_kcontrol *ctl,
+                      struct snd_ctl_elem_value *value)
+{
+       struct oxygen *chip = ctl->private_data;
+       u8 bit = ctl->private_value;
+       int invert = ctl->private_value & (1 << 8);
+       u8 oldreg, newreg;
+       int changed;
+
+       spin_lock_irq(&chip->reg_lock);
+       oldreg = oxygen_read8(chip, OXYGEN_ADC_MONITOR);
+       if ((!!value->value.integer.value[0] ^ !!invert) != 0)
+               newreg = oldreg | bit;
+       else
+               newreg = oldreg & ~bit;
+       changed = newreg != oldreg;
+       if (changed)
+               oxygen_write8(chip, OXYGEN_ADC_MONITOR, newreg);
+       spin_unlock_irq(&chip->reg_lock);
+       return changed;
+}
+
 static int ac97_switch_get(struct snd_kcontrol *ctl,
                           struct snd_ctl_elem_value *value)
 {
@@ -466,6 +510,21 @@ static int ac97_switch_get(struct snd_kcontrol *ctl,
        return 0;
 }
 
+static void mute_ac97_ctl(struct oxygen *chip, unsigned int control)
+{
+       unsigned int priv_idx = chip->controls[control]->private_value & 0xff;
+       u16 value;
+
+       value = oxygen_read_ac97(chip, 0, priv_idx);
+       if (!(value & 0x8000)) {
+               oxygen_write_ac97(chip, 0, priv_idx, value | 0x8000);
+               if (chip->model->ac97_switch)
+                       chip->model->ac97_switch(chip, priv_idx, 0x8000);
+               snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
+                              &chip->controls[control]->id);
+       }
+}
+
 static int ac97_switch_put(struct snd_kcontrol *ctl,
                           struct snd_ctl_elem_value *value)
 {
@@ -487,9 +546,24 @@ static int ac97_switch_put(struct snd_kcontrol *ctl,
        change = newreg != oldreg;
        if (change) {
                oxygen_write_ac97(chip, codec, index, newreg);
-               if (bitnr == 15 && chip->model->ac97_switch_hook)
-                       chip->model->ac97_switch_hook(chip, codec, index,
-                                                     newreg & 0x8000);
+               if (codec == 0 && chip->model->ac97_switch)
+                       chip->model->ac97_switch(chip, index, newreg & 0x8000);
+               if (index == AC97_LINE) {
+                       oxygen_write_ac97_masked(chip, 0, CM9780_GPIO_STATUS,
+                                                newreg & 0x8000 ?
+                                                CM9780_GPO0 : 0, CM9780_GPO0);
+                       if (!(newreg & 0x8000)) {
+                               mute_ac97_ctl(chip, CONTROL_MIC_CAPTURE_SWITCH);
+                               mute_ac97_ctl(chip, CONTROL_CD_CAPTURE_SWITCH);
+                               mute_ac97_ctl(chip, CONTROL_AUX_CAPTURE_SWITCH);
+                       }
+               } else if ((index == AC97_MIC || index == AC97_CD ||
+                           index == AC97_VIDEO || index == AC97_AUX) &&
+                          bitnr == 15 && !(newreg & 0x8000)) {
+                       mute_ac97_ctl(chip, CONTROL_LINE_CAPTURE_SWITCH);
+                       oxygen_write_ac97_masked(chip, 0, CM9780_GPIO_STATUS,
+                                                CM9780_GPO0, CM9780_GPO0);
+               }
        }
        mutex_unlock(&chip->mutex);
        return change;
@@ -608,6 +682,7 @@ static int ac97_fp_rec_volume_put(struct snd_kcontrol *ctl,
                .private_value = ((codec) << 24) | (index), \
        }
 
+static DECLARE_TLV_DB_SCALE(monitor_db_scale, -1000, 1000, 0);
 static DECLARE_TLV_DB_SCALE(ac97_db_scale, -3450, 150, 0);
 static DECLARE_TLV_DB_SCALE(ac97_rec_db_scale, 0, 150, 0);
 
@@ -667,6 +742,9 @@ static const struct snd_kcontrol_new controls[] = {
                .get = spdif_pcm_get,
                .put = spdif_pcm_put,
        },
+};
+
+static const struct snd_kcontrol_new spdif_input_controls[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_PCM,
                .device = 1,
@@ -692,11 +770,118 @@ static const struct snd_kcontrol_new controls[] = {
        },
 };
 
+static const struct {
+       unsigned int pcm_dev;
+       struct snd_kcontrol_new controls[2];
+} monitor_controls[] = {
+       {
+               .pcm_dev = CAPTURE_0_FROM_I2S_1,
+               .controls = {
+                       {
+                               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+                               .name = "Analog Input Monitor Switch",
+                               .info = snd_ctl_boolean_mono_info,
+                               .get = monitor_get,
+                               .put = monitor_put,
+                               .private_value = OXYGEN_ADC_MONITOR_A,
+                       },
+                       {
+                               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+                               .name = "Analog Input Monitor Volume",
+                               .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+                                         SNDRV_CTL_ELEM_ACCESS_TLV_READ,
+                               .info = monitor_volume_info,
+                               .get = monitor_get,
+                               .put = monitor_put,
+                               .private_value = OXYGEN_ADC_MONITOR_A_HALF_VOL
+                                               | (1 << 8),
+                               .tlv = { .p = monitor_db_scale, },
+                       },
+               },
+       },
+       {
+               .pcm_dev = CAPTURE_0_FROM_I2S_2,
+               .controls = {
+                       {
+                               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+                               .name = "Analog Input Monitor Switch",
+                               .info = snd_ctl_boolean_mono_info,
+                               .get = monitor_get,
+                               .put = monitor_put,
+                               .private_value = OXYGEN_ADC_MONITOR_B,
+                       },
+                       {
+                               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+                               .name = "Analog Input Monitor Volume",
+                               .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+                                         SNDRV_CTL_ELEM_ACCESS_TLV_READ,
+                               .info = monitor_volume_info,
+                               .get = monitor_get,
+                               .put = monitor_put,
+                               .private_value = OXYGEN_ADC_MONITOR_B_HALF_VOL
+                                               | (1 << 8),
+                               .tlv = { .p = monitor_db_scale, },
+                       },
+               },
+       },
+       {
+               .pcm_dev = CAPTURE_2_FROM_I2S_2,
+               .controls = {
+                       {
+                               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+                               .name = "Analog Input Monitor Switch",
+                               .index = 1,
+                               .info = snd_ctl_boolean_mono_info,
+                               .get = monitor_get,
+                               .put = monitor_put,
+                               .private_value = OXYGEN_ADC_MONITOR_B,
+                       },
+                       {
+                               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+                               .name = "Analog Input Monitor Volume",
+                               .index = 1,
+                               .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+                                         SNDRV_CTL_ELEM_ACCESS_TLV_READ,
+                               .info = monitor_volume_info,
+                               .get = monitor_get,
+                               .put = monitor_put,
+                               .private_value = OXYGEN_ADC_MONITOR_B_HALF_VOL
+                                               | (1 << 8),
+                               .tlv = { .p = monitor_db_scale, },
+                       },
+               },
+       },
+       {
+               .pcm_dev = CAPTURE_1_FROM_SPDIF,
+               .controls = {
+                       {
+                               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+                               .name = "Digital Input Monitor Switch",
+                               .info = snd_ctl_boolean_mono_info,
+                               .get = monitor_get,
+                               .put = monitor_put,
+                               .private_value = OXYGEN_ADC_MONITOR_C,
+                       },
+                       {
+                               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+                               .name = "Digital Input Monitor Volume",
+                               .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+                                         SNDRV_CTL_ELEM_ACCESS_TLV_READ,
+                               .info = monitor_volume_info,
+                               .get = monitor_get,
+                               .put = monitor_put,
+                               .private_value = OXYGEN_ADC_MONITOR_C_HALF_VOL
+                                               | (1 << 8),
+                               .tlv = { .p = monitor_db_scale, },
+                       },
+               },
+       },
+};
+
 static const struct snd_kcontrol_new ac97_controls[] = {
        AC97_VOLUME("Mic Capture Volume", 0, AC97_MIC),
        AC97_SWITCH("Mic Capture Switch", 0, AC97_MIC, 15, 1),
        AC97_SWITCH("Mic Boost (+20dB)", 0, AC97_MIC, 6, 0),
-       AC97_VOLUME("Line Capture Volume", 0, AC97_LINE),
        AC97_SWITCH("Line Capture Switch", 0, AC97_LINE, 15, 1),
        AC97_VOLUME("CD Capture Volume", 0, AC97_CD),
        AC97_SWITCH("CD Capture Switch", 0, AC97_CD, 15, 1),
@@ -756,6 +941,11 @@ static int add_controls(struct oxygen *chip,
                        return err;
                if (err == 1)
                        continue;
+               if (!strcmp(template.name, "Master Playback Volume") &&
+                   chip->model->dac_tlv) {
+                       template.tlv.p = chip->model->dac_tlv;
+                       template.access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
+               }
                ctl = snd_ctl_new1(&template, chip);
                if (!ctl)
                        return -ENOMEM;
@@ -773,11 +963,26 @@ static int add_controls(struct oxygen *chip,
 
 int oxygen_mixer_init(struct oxygen *chip)
 {
+       unsigned int i;
        int err;
 
        err = add_controls(chip, controls, ARRAY_SIZE(controls));
        if (err < 0)
                return err;
+       if (chip->model->pcm_dev_cfg & CAPTURE_1_FROM_SPDIF) {
+               err = add_controls(chip, spdif_input_controls,
+                                  ARRAY_SIZE(spdif_input_controls));
+               if (err < 0)
+                       return err;
+       }
+       for (i = 0; i < ARRAY_SIZE(monitor_controls); ++i) {
+               if (!(chip->model->pcm_dev_cfg & monitor_controls[i].pcm_dev))
+                       continue;
+               err = add_controls(chip, monitor_controls[i].controls,
+                                  ARRAY_SIZE(monitor_controls[i].controls));
+               if (err < 0)
+                       return err;
+       }
        if (chip->has_ac97_0) {
                err = add_controls(chip, ac97_controls,
                                   ARRAY_SIZE(ac97_controls));
index b70046aca65764ac30b618d9c873b3b63ac4c909..b17c405e069df5349daceba5db00416de012eb1b 100644 (file)
@@ -119,7 +119,7 @@ static int oxygen_open(struct snd_pcm_substream *substream,
 
        runtime->private_data = (void *)(uintptr_t)channel;
        if (channel == PCM_B && chip->has_ac97_1 &&
-           (chip->model->used_channels & OXYGEN_CHANNEL_AC97))
+           (chip->model->pcm_dev_cfg & CAPTURE_2_FROM_AC97_1))
                runtime->hw = oxygen_ac97_hardware;
        else
                runtime->hw = *oxygen_hardware[channel];
@@ -365,7 +365,7 @@ static int oxygen_rec_b_hw_params(struct snd_pcm_substream *substream,
                return err;
 
        is_ac97 = chip->has_ac97_1 &&
-               (chip->model->used_channels & OXYGEN_CHANNEL_AC97);
+               (chip->model->pcm_dev_cfg & CAPTURE_2_FROM_AC97_1);
 
        spin_lock_irq(&chip->reg_lock);
        oxygen_write8_masked(chip, OXYGEN_REC_FORMAT,
@@ -640,34 +640,39 @@ int oxygen_pcm_init(struct oxygen *chip)
        int outs, ins;
        int err;
 
-       outs = 1; /* OXYGEN_CHANNEL_MULTICH is always used */
-       ins = !!(chip->model->used_channels & (OXYGEN_CHANNEL_A |
-                                              OXYGEN_CHANNEL_B));
-       err = snd_pcm_new(chip->card, "Analog", 0, outs, ins, &pcm);
-       if (err < 0)
-               return err;
-       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &oxygen_multich_ops);
-       if (chip->model->used_channels & OXYGEN_CHANNEL_A)
-               snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
-                               &oxygen_rec_a_ops);
-       else if (chip->model->used_channels & OXYGEN_CHANNEL_B)
-               snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
-                               &oxygen_rec_b_ops);
-       pcm->private_data = chip;
-       pcm->private_free = oxygen_pcm_free;
-       strcpy(pcm->name, "Analog");
-       snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream,
-                                     SNDRV_DMA_TYPE_DEV,
-                                     snd_dma_pci_data(chip->pci),
-                                     512 * 1024, 2048 * 1024);
-       if (ins)
-               snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,
-                                             SNDRV_DMA_TYPE_DEV,
-                                             snd_dma_pci_data(chip->pci),
-                                             128 * 1024, 256 * 1024);
-
-       outs = !!(chip->model->used_channels & OXYGEN_CHANNEL_SPDIF);
-       ins = !!(chip->model->used_channels & OXYGEN_CHANNEL_C);
+       outs = !!(chip->model->pcm_dev_cfg & PLAYBACK_0_TO_I2S);
+       ins = !!(chip->model->pcm_dev_cfg & (CAPTURE_0_FROM_I2S_1 |
+                                            CAPTURE_0_FROM_I2S_2));
+       if (outs | ins) {
+               err = snd_pcm_new(chip->card, "Analog", 0, outs, ins, &pcm);
+               if (err < 0)
+                       return err;
+               if (outs)
+                       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+                                       &oxygen_multich_ops);
+               if (chip->model->pcm_dev_cfg & CAPTURE_0_FROM_I2S_1)
+                       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+                                       &oxygen_rec_a_ops);
+               else if (chip->model->pcm_dev_cfg & CAPTURE_0_FROM_I2S_2)
+                       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+                                       &oxygen_rec_b_ops);
+               pcm->private_data = chip;
+               pcm->private_free = oxygen_pcm_free;
+               strcpy(pcm->name, "Analog");
+               if (outs)
+                       snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream,
+                                                     SNDRV_DMA_TYPE_DEV,
+                                                     snd_dma_pci_data(chip->pci),
+                                                     512 * 1024, 2048 * 1024);
+               if (ins)
+                       snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,
+                                                     SNDRV_DMA_TYPE_DEV,
+                                                     snd_dma_pci_data(chip->pci),
+                                                     128 * 1024, 256 * 1024);
+       }
+
+       outs = !!(chip->model->pcm_dev_cfg & PLAYBACK_1_TO_SPDIF);
+       ins = !!(chip->model->pcm_dev_cfg & CAPTURE_1_FROM_SPDIF);
        if (outs | ins) {
                err = snd_pcm_new(chip->card, "Digital", 1, outs, ins, &pcm);
                if (err < 0)
@@ -686,12 +691,13 @@ int oxygen_pcm_init(struct oxygen *chip)
                                                      128 * 1024, 256 * 1024);
        }
 
-       outs = chip->has_ac97_1 &&
-               (chip->model->used_channels & OXYGEN_CHANNEL_AC97);
-       ins = outs ||
-               (chip->model->used_channels & (OXYGEN_CHANNEL_A |
-                                              OXYGEN_CHANNEL_B))
-               == (OXYGEN_CHANNEL_A | OXYGEN_CHANNEL_B);
+       if (chip->has_ac97_1) {
+               outs = !!(chip->model->pcm_dev_cfg & PLAYBACK_2_TO_AC97_1);
+               ins = !!(chip->model->pcm_dev_cfg & CAPTURE_2_FROM_AC97_1);
+       } else {
+               outs = 0;
+               ins = !!(chip->model->pcm_dev_cfg & CAPTURE_2_FROM_I2S_2);
+       }
        if (outs | ins) {
                err = snd_pcm_new(chip->card, outs ? "AC97" : "Analog2",
                                  2, outs, ins, &pcm);
diff --git a/sound/pci/oxygen/pcm1796.h b/sound/pci/oxygen/pcm1796.h
new file mode 100644 (file)
index 0000000..698bf46
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef PCM1796_H_INCLUDED
+#define PCM1796_H_INCLUDED
+
+/* register 16 */
+#define PCM1796_ATL_MASK       0xff
+/* register 17 */
+#define PCM1796_ATR_MASK       0xff
+/* register 18 */
+#define PCM1796_MUTE           0x01
+#define PCM1796_DME            0x02
+#define PCM1796_DMF_MASK       0x0c
+#define PCM1796_DMF_DISABLED   0x00
+#define PCM1796_DMF_48         0x04
+#define PCM1796_DMF_441                0x08
+#define PCM1796_DMF_32         0x0c
+#define PCM1796_FMT_MASK       0x70
+#define PCM1796_FMT_16_RJUST   0x00
+#define PCM1796_FMT_20_RJUST   0x10
+#define PCM1796_FMT_24_RJUST   0x20
+#define PCM1796_FMT_24_LJUST   0x30
+#define PCM1796_FMT_16_I2S     0x40
+#define PCM1796_FMT_24_I2S     0x50
+#define PCM1796_ATLD           0x80
+/* register 19 */
+#define PCM1796_INZD           0x01
+#define PCM1796_FLT_MASK       0x02
+#define PCM1796_FLT_SHARP      0x00
+#define PCM1796_FLT_SLOW       0x02
+#define PCM1796_DFMS           0x04
+#define PCM1796_OPE            0x10
+#define PCM1796_ATS_MASK       0x60
+#define PCM1796_ATS_1          0x00
+#define PCM1796_ATS_2          0x20
+#define PCM1796_ATS_4          0x40
+#define PCM1796_ATS_8          0x60
+#define PCM1796_REV            0x80
+/* register 20 */
+#define PCM1796_OS_MASK                0x03
+#define PCM1796_OS_64          0x00
+#define PCM1796_OS_32          0x01
+#define PCM1796_OS_128         0x02
+#define PCM1796_CHSL_MASK      0x04
+#define PCM1796_CHSL_LEFT      0x00
+#define PCM1796_CHSL_RIGHT     0x04
+#define PCM1796_MONO           0x08
+#define PCM1796_DFTH           0x10
+#define PCM1796_DSD            0x20
+#define PCM1796_SRST           0x40
+/* register 21 */
+#define PCM1796_PCMZ           0x01
+#define PCM1796_DZ_MASK                0x06
+/* register 22 */
+#define PCM1796_ZFGL           0x01
+#define PCM1796_ZFGR           0x02
+/* register 23 */
+#define PCM1796_ID_MASK                0x1f
+
+#endif
index d163397b85cc3d351cc60b1b3b187d191c0ae549..7f84fa5deca2864473c00d60ff07ed602235204c 100644 (file)
@@ -18,6 +18,9 @@
  */
 
 /*
+ * Xonar D2/D2X
+ * ------------
+ *
  * CMI8788:
  *
  * SPI 0 -> 1st PCM1796 (front)
  * GPIO 5 <- external power present (D2X only)
  * GPIO 7 -> ALT
  * GPIO 8 -> enable output to speakers
+ */
+
+/*
+ * Xonar DX
+ * --------
+ *
+ * CMI8788:
+ *
+ * I²C <-> CS4398 (front)
+ *     <-> CS4362A (surround, center/LFE, back)
+ *
+ * GPI 0 <- external power present
  *
- * CM9780:
+ * GPIO 0 -> enable output to speakers
+ * GPIO 1 -> enable front panel I/O
+ * GPIO 2 -> M0 of CS5361
+ * GPIO 3 -> M1 of CS5361
+ * GPIO 8 -> route input jack to line-in (0) or mic-in (1)
  *
- * GPIO 0 -> enable AC'97 bypass (line in -> ADC)
+ * CS4398:
+ *
+ * AD0 <- 1
+ * AD1 <- 1
+ *
+ * CS4362A:
+ *
+ * AD0 <- 0
  */
 
 #include <linux/pci.h>
 #include <sound/tlv.h>
 #include "oxygen.h"
 #include "cm9780.h"
+#include "pcm1796.h"
+#include "cs4398.h"
+#include "cs4362a.h"
 
 MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
-MODULE_DESCRIPTION("Asus AV200 driver");
+MODULE_DESCRIPTION("Asus AVx00 driver");
 MODULE_LICENSE("GPL");
-MODULE_SUPPORTED_DEVICE("{{Asus,AV200}}");
+MODULE_SUPPORTED_DEVICE("{{Asus,AV100},{Asus,AV200}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
@@ -64,80 +93,44 @@ MODULE_PARM_DESC(id, "ID string");
 module_param_array(enable, bool, NULL, 0444);
 MODULE_PARM_DESC(enable, "enable card");
 
+enum {
+       MODEL_D2,
+       MODEL_D2X,
+       MODEL_DX,
+};
+
 static struct pci_device_id xonar_ids[] __devinitdata = {
-       { OXYGEN_PCI_SUBID(0x1043, 0x8269) }, /* Asus Xonar D2 */
-       { OXYGEN_PCI_SUBID(0x1043, 0x82b7) }, /* Asus Xonar D2X */
+       { OXYGEN_PCI_SUBID(0x1043, 0x8269), .driver_data = MODEL_D2 },
+       { OXYGEN_PCI_SUBID(0x1043, 0x8275), .driver_data = MODEL_DX },
+       { OXYGEN_PCI_SUBID(0x1043, 0x82b7), .driver_data = MODEL_D2X },
        { }
 };
 MODULE_DEVICE_TABLE(pci, xonar_ids);
 
 
-#define GPIO_CS5381_M_MASK     0x000c
-#define GPIO_CS5381_M_SINGLE   0x0000
-#define GPIO_CS5381_M_DOUBLE   0x0004
-#define GPIO_CS5381_M_QUAD     0x0008
-#define GPIO_EXT_POWER         0x0020
-#define GPIO_ALT               0x0080
-#define GPIO_OUTPUT_ENABLE     0x0100
-
-#define GPIO_LINE_MUTE         CM9780_GPO0
-
-/* register 16 */
-#define PCM1796_ATL_MASK       0xff
-/* register 17 */
-#define PCM1796_ATR_MASK       0xff
-/* register 18 */
-#define PCM1796_MUTE           0x01
-#define PCM1796_DME            0x02
-#define PCM1796_DMF_MASK       0x0c
-#define PCM1796_DMF_DISABLED   0x00
-#define PCM1796_DMF_48         0x04
-#define PCM1796_DMF_441                0x08
-#define PCM1796_DMF_32         0x0c
-#define PCM1796_FMT_MASK       0x70
-#define PCM1796_FMT_16_RJUST   0x00
-#define PCM1796_FMT_20_RJUST   0x10
-#define PCM1796_FMT_24_RJUST   0x20
-#define PCM1796_FMT_24_LJUST   0x30
-#define PCM1796_FMT_16_I2S     0x40
-#define PCM1796_FMT_24_I2S     0x50
-#define PCM1796_ATLD           0x80
-/* register 19 */
-#define PCM1796_INZD           0x01
-#define PCM1796_FLT_MASK       0x02
-#define PCM1796_FLT_SHARP      0x00
-#define PCM1796_FLT_SLOW       0x02
-#define PCM1796_DFMS           0x04
-#define PCM1796_OPE            0x10
-#define PCM1796_ATS_MASK       0x60
-#define PCM1796_ATS_1          0x00
-#define PCM1796_ATS_2          0x20
-#define PCM1796_ATS_4          0x40
-#define PCM1796_ATS_8          0x60
-#define PCM1796_REV            0x80
-/* register 20 */
-#define PCM1796_OS_MASK                0x03
-#define PCM1796_OS_64          0x00
-#define PCM1796_OS_32          0x01
-#define PCM1796_OS_128         0x02
-#define PCM1796_CHSL_MASK      0x04
-#define PCM1796_CHSL_LEFT      0x00
-#define PCM1796_CHSL_RIGHT     0x04
-#define PCM1796_MONO           0x08
-#define PCM1796_DFTH           0x10
-#define PCM1796_DSD            0x20
-#define PCM1796_SRST           0x40
-/* register 21 */
-#define PCM1796_PCMZ           0x01
-#define PCM1796_DZ_MASK                0x06
-/* register 22 */
-#define PCM1796_ZFGL           0x01
-#define PCM1796_ZFGR           0x02
-/* register 23 */
-#define PCM1796_ID_MASK                0x1f
+#define GPIO_CS53x1_M_MASK     0x000c
+#define GPIO_CS53x1_M_SINGLE   0x0000
+#define GPIO_CS53x1_M_DOUBLE   0x0004
+#define GPIO_CS53x1_M_QUAD     0x0008
+
+#define GPIO_D2X_EXT_POWER     0x0020
+#define GPIO_D2_ALT            0x0080
+#define GPIO_D2_OUTPUT_ENABLE  0x0100
+
+#define GPI_DX_EXT_POWER       0x01
+#define GPIO_DX_OUTPUT_ENABLE  0x0001
+#define GPIO_DX_FRONT_PANEL    0x0002
+#define GPIO_DX_INPUT_ROUTE    0x0100
+
+#define I2C_DEVICE_CS4398      0x9e    /* 10011, AD1=1, AD0=1, /W=0 */
+#define I2C_DEVICE_CS4362A     0x30    /* 001100, AD0=0, /W=0 */
 
 struct xonar_data {
-       u8 is_d2x;
+       unsigned int anti_pop_delay;
+       u16 output_enable_bit;
+       u8 ext_power_reg;
+       u8 ext_power_int_reg;
+       u8 ext_power_bit;
        u8 has_power;
 };
 
@@ -156,62 +149,157 @@ static void pcm1796_write(struct oxygen *chip, unsigned int codec,
                         (reg << 8) | value);
 }
 
-static void xonar_init(struct oxygen *chip)
+static void cs4398_write(struct oxygen *chip, u8 reg, u8 value)
+{
+       oxygen_write_i2c(chip, I2C_DEVICE_CS4398, reg, value);
+}
+
+static void cs4362a_write(struct oxygen *chip, u8 reg, u8 value)
+{
+       oxygen_write_i2c(chip, I2C_DEVICE_CS4362A, reg, value);
+}
+
+static void xonar_common_init(struct oxygen *chip)
+{
+       struct xonar_data *data = chip->model_data;
+
+       if (data->ext_power_reg) {
+               oxygen_set_bits8(chip, data->ext_power_int_reg,
+                                data->ext_power_bit);
+               chip->interrupt_mask |= OXYGEN_INT_GPIO;
+               data->has_power = !!(oxygen_read8(chip, data->ext_power_reg)
+                                    & data->ext_power_bit);
+       }
+       oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_CS53x1_M_MASK);
+       oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
+                             GPIO_CS53x1_M_SINGLE, GPIO_CS53x1_M_MASK);
+       oxygen_ac97_set_bits(chip, 0, CM9780_JACK, CM9780_FMIC2MIC);
+       msleep(data->anti_pop_delay);
+       oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, data->output_enable_bit);
+       oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, data->output_enable_bit);
+}
+
+static void xonar_d2_init(struct oxygen *chip)
 {
        struct xonar_data *data = chip->model_data;
        unsigned int i;
 
-       data->is_d2x = chip->pci->subsystem_device == 0x82b7;
+       data->anti_pop_delay = 300;
+       data->output_enable_bit = GPIO_D2_OUTPUT_ENABLE;
 
        for (i = 0; i < 4; ++i) {
-               pcm1796_write(chip, i, 18, PCM1796_FMT_24_LJUST | PCM1796_ATLD);
+               pcm1796_write(chip, i, 18, PCM1796_MUTE | PCM1796_DMF_DISABLED |
+                             PCM1796_FMT_24_LJUST | PCM1796_ATLD);
                pcm1796_write(chip, i, 19, PCM1796_FLT_SHARP | PCM1796_ATS_1);
                pcm1796_write(chip, i, 20, PCM1796_OS_64);
                pcm1796_write(chip, i, 21, 0);
-               pcm1796_write(chip, i, 16, 0xff); /* set ATL/ATR after ATLD */
-               pcm1796_write(chip, i, 17, 0xff);
+               pcm1796_write(chip, i, 16, 0x0f); /* set ATL/ATR after ATLD */
+               pcm1796_write(chip, i, 17, 0x0f);
        }
 
-       oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL,
-                         GPIO_CS5381_M_MASK | GPIO_ALT);
-       oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
-                             GPIO_CS5381_M_SINGLE,
-                             GPIO_CS5381_M_MASK | GPIO_ALT);
-       if (data->is_d2x) {
-               oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL,
-                                   GPIO_EXT_POWER);
-               oxygen_set_bits16(chip, OXYGEN_GPIO_INTERRUPT_MASK,
-                                 GPIO_EXT_POWER);
-               chip->interrupt_mask |= OXYGEN_INT_GPIO;
-               data->has_power = !!(oxygen_read16(chip, OXYGEN_GPIO_DATA)
-                                    & GPIO_EXT_POWER);
-       }
-       oxygen_ac97_set_bits(chip, 0, CM9780_JACK, CM9780_FMIC2MIC);
-       oxygen_ac97_clear_bits(chip, 0, CM9780_GPIO_STATUS, GPIO_LINE_MUTE);
-       msleep(300);
-       oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_OUTPUT_ENABLE);
-       oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_OUTPUT_ENABLE);
+       oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_D2_ALT);
+       oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_D2_ALT);
+
+       xonar_common_init(chip);
 
        snd_component_add(chip->card, "PCM1796");
        snd_component_add(chip->card, "CS5381");
 }
 
+static void xonar_d2x_init(struct oxygen *chip)
+{
+       struct xonar_data *data = chip->model_data;
+
+       data->ext_power_reg = OXYGEN_GPIO_DATA;
+       data->ext_power_int_reg = OXYGEN_GPIO_INTERRUPT_MASK;
+       data->ext_power_bit = GPIO_D2X_EXT_POWER;
+       oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_D2X_EXT_POWER);
+       xonar_d2_init(chip);
+}
+
+static void xonar_dx_init(struct oxygen *chip)
+{
+       struct xonar_data *data = chip->model_data;
+
+       data->anti_pop_delay = 800;
+       data->output_enable_bit = GPIO_DX_OUTPUT_ENABLE;
+       data->ext_power_reg = OXYGEN_GPI_DATA;
+       data->ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK;
+       data->ext_power_bit = GPI_DX_EXT_POWER;
+
+       oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS,
+                      OXYGEN_2WIRE_LENGTH_8 |
+                      OXYGEN_2WIRE_INTERRUPT_MASK |
+                      OXYGEN_2WIRE_SPEED_FAST);
+
+       /* set CPEN (control port mode) and power down */
+       cs4398_write(chip, 8, CS4398_CPEN | CS4398_PDN);
+       cs4362a_write(chip, 0x01, CS4362A_PDN | CS4362A_CPEN);
+       /* configure */
+       cs4398_write(chip, 2, CS4398_FM_SINGLE |
+                    CS4398_DEM_NONE | CS4398_DIF_LJUST);
+       cs4398_write(chip, 3, CS4398_ATAPI_B_R | CS4398_ATAPI_A_L);
+       cs4398_write(chip, 4, CS4398_MUTEP_LOW | CS4398_PAMUTE);
+       cs4398_write(chip, 5, 0xfe);
+       cs4398_write(chip, 6, 0xfe);
+       cs4398_write(chip, 7, CS4398_RMP_DN | CS4398_RMP_UP |
+                    CS4398_ZERO_CROSS | CS4398_SOFT_RAMP);
+       cs4362a_write(chip, 0x02, CS4362A_DIF_LJUST);
+       cs4362a_write(chip, 0x03, CS4362A_MUTEC_6 | CS4362A_AMUTE |
+                     CS4362A_RMP_UP | CS4362A_ZERO_CROSS | CS4362A_SOFT_RAMP);
+       cs4362a_write(chip, 0x04, CS4362A_RMP_DN | CS4362A_DEM_NONE);
+       cs4362a_write(chip, 0x05, 0);
+       cs4362a_write(chip, 0x06, CS4362A_FM_SINGLE |
+                     CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L);
+       cs4362a_write(chip, 0x07, 0x7f | CS4362A_MUTE);
+       cs4362a_write(chip, 0x08, 0x7f | CS4362A_MUTE);
+       cs4362a_write(chip, 0x09, CS4362A_FM_SINGLE |
+                     CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L);
+       cs4362a_write(chip, 0x0a, 0x7f | CS4362A_MUTE);
+       cs4362a_write(chip, 0x0b, 0x7f | CS4362A_MUTE);
+       cs4362a_write(chip, 0x0c, CS4362A_FM_SINGLE |
+                     CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L);
+       cs4362a_write(chip, 0x0d, 0x7f | CS4362A_MUTE);
+       cs4362a_write(chip, 0x0e, 0x7f | CS4362A_MUTE);
+       /* clear power down */
+       cs4398_write(chip, 8, CS4398_CPEN);
+       cs4362a_write(chip, 0x01, CS4362A_CPEN);
+
+       oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL,
+                         GPIO_DX_FRONT_PANEL | GPIO_DX_INPUT_ROUTE);
+       oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA,
+                           GPIO_DX_FRONT_PANEL | GPIO_DX_INPUT_ROUTE);
+
+       xonar_common_init(chip);
+
+       snd_component_add(chip->card, "CS4398");
+       snd_component_add(chip->card, "CS4362A");
+       snd_component_add(chip->card, "CS5361");
+}
+
 static void xonar_cleanup(struct oxygen *chip)
 {
-       oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_OUTPUT_ENABLE);
+       struct xonar_data *data = chip->model_data;
+
+       oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, data->output_enable_bit);
+}
+
+static void xonar_dx_cleanup(struct oxygen *chip)
+{
+       xonar_cleanup(chip);
+       cs4362a_write(chip, 0x01, CS4362A_PDN | CS4362A_CPEN);
+       oxygen_clear_bits8(chip, OXYGEN_FUNCTION, OXYGEN_FUNCTION_RESET_CODEC);
 }
 
 static void set_pcm1796_params(struct oxygen *chip,
                               struct snd_pcm_hw_params *params)
 {
-#if 0
        unsigned int i;
        u8 value;
 
        value = params_rate(params) >= 96000 ? PCM1796_OS_32 : PCM1796_OS_64;
        for (i = 0; i < 4; ++i)
                pcm1796_write(chip, i, 20, value);
-#endif
 }
 
 static void update_pcm1796_volume(struct oxygen *chip)
@@ -236,19 +324,73 @@ static void update_pcm1796_mute(struct oxygen *chip)
                pcm1796_write(chip, i, 18, value);
 }
 
-static void set_cs5381_params(struct oxygen *chip,
+static void set_cs53x1_params(struct oxygen *chip,
                              struct snd_pcm_hw_params *params)
 {
        unsigned int value;
 
        if (params_rate(params) <= 54000)
-               value = GPIO_CS5381_M_SINGLE;
+               value = GPIO_CS53x1_M_SINGLE;
        else if (params_rate(params) <= 108000)
-               value = GPIO_CS5381_M_DOUBLE;
+               value = GPIO_CS53x1_M_DOUBLE;
        else
-               value = GPIO_CS5381_M_QUAD;
+               value = GPIO_CS53x1_M_QUAD;
        oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
-                             value, GPIO_CS5381_M_MASK);
+                             value, GPIO_CS53x1_M_MASK);
+}
+
+static void set_cs43xx_params(struct oxygen *chip,
+                             struct snd_pcm_hw_params *params)
+{
+       u8 fm_cs4398, fm_cs4362a;
+
+       fm_cs4398 = CS4398_DEM_NONE | CS4398_DIF_LJUST;
+       fm_cs4362a = CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L;
+       if (params_rate(params) <= 50000) {
+               fm_cs4398 |= CS4398_FM_SINGLE;
+               fm_cs4362a |= CS4362A_FM_SINGLE;
+       } else if (params_rate(params) <= 100000) {
+               fm_cs4398 |= CS4398_FM_DOUBLE;
+               fm_cs4362a |= CS4362A_FM_DOUBLE;
+       } else {
+               fm_cs4398 |= CS4398_FM_QUAD;
+               fm_cs4362a |= CS4362A_FM_QUAD;
+       }
+       cs4398_write(chip, 2, fm_cs4398);
+       cs4362a_write(chip, 0x06, fm_cs4362a);
+       cs4362a_write(chip, 0x09, fm_cs4362a);
+       cs4362a_write(chip, 0x0c, fm_cs4362a);
+}
+
+static void update_cs4362a_volumes(struct oxygen *chip)
+{
+       u8 mute;
+
+       mute = chip->dac_mute ? CS4362A_MUTE : 0;
+       cs4362a_write(chip, 7, (127 - chip->dac_volume[2]) | mute);
+       cs4362a_write(chip, 8, (127 - chip->dac_volume[3]) | mute);
+       cs4362a_write(chip, 10, (127 - chip->dac_volume[4]) | mute);
+       cs4362a_write(chip, 11, (127 - chip->dac_volume[5]) | mute);
+       cs4362a_write(chip, 13, (127 - chip->dac_volume[6]) | mute);
+       cs4362a_write(chip, 14, (127 - chip->dac_volume[7]) | mute);
+}
+
+static void update_cs43xx_volume(struct oxygen *chip)
+{
+       cs4398_write(chip, 5, (127 - chip->dac_volume[0]) * 2);
+       cs4398_write(chip, 6, (127 - chip->dac_volume[1]) * 2);
+       update_cs4362a_volumes(chip);
+}
+
+static void update_cs43xx_mute(struct oxygen *chip)
+{
+       u8 reg;
+
+       reg = CS4398_MUTEP_LOW | CS4398_PAMUTE;
+       if (chip->dac_mute)
+               reg |= CS4398_MUTE_B | CS4398_MUTE_A;
+       cs4398_write(chip, 4, reg);
+       update_cs4362a_volumes(chip);
 }
 
 static void xonar_gpio_changed(struct oxygen *chip)
@@ -256,10 +398,8 @@ static void xonar_gpio_changed(struct oxygen *chip)
        struct xonar_data *data = chip->model_data;
        u8 has_power;
 
-       if (!data->is_d2x)
-               return;
-       has_power = !!(oxygen_read16(chip, OXYGEN_GPIO_DATA)
-                      & GPIO_EXT_POWER);
+       has_power = !!(oxygen_read8(chip, data->ext_power_reg)
+                      & data->ext_power_bit);
        if (has_power != data->has_power) {
                data->has_power = has_power;
                if (has_power) {
@@ -272,66 +412,13 @@ static void xonar_gpio_changed(struct oxygen *chip)
        }
 }
 
-static void mute_ac97_ctl(struct oxygen *chip, unsigned int control)
-{
-       unsigned int index = chip->controls[control]->private_value & 0xff;
-       u16 value;
-
-       value = oxygen_read_ac97(chip, 0, index);
-       if (!(value & 0x8000)) {
-               oxygen_write_ac97(chip, 0, index, value | 0x8000);
-               snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
-                              &chip->controls[control]->id);
-       }
-}
-
-static void xonar_ac97_switch_hook(struct oxygen *chip, unsigned int codec,
-                                  unsigned int reg, int mute)
-{
-       if (codec != 0)
-               return;
-       /* line-in is exclusive */
-       switch (reg) {
-       case AC97_LINE:
-               oxygen_write_ac97_masked(chip, 0, CM9780_GPIO_STATUS,
-                                        mute ? GPIO_LINE_MUTE : 0,
-                                        GPIO_LINE_MUTE);
-               if (!mute) {
-                       mute_ac97_ctl(chip, CONTROL_MIC_CAPTURE_SWITCH);
-                       mute_ac97_ctl(chip, CONTROL_CD_CAPTURE_SWITCH);
-                       mute_ac97_ctl(chip, CONTROL_AUX_CAPTURE_SWITCH);
-               }
-               break;
-       case AC97_MIC:
-       case AC97_CD:
-       case AC97_VIDEO:
-       case AC97_AUX:
-               if (!mute) {
-                       oxygen_ac97_set_bits(chip, 0, CM9780_GPIO_STATUS,
-                                            GPIO_LINE_MUTE);
-                       mute_ac97_ctl(chip, CONTROL_LINE_CAPTURE_SWITCH);
-               }
-               break;
-       }
-}
-
-static int pcm1796_volume_info(struct snd_kcontrol *ctl,
-                              struct snd_ctl_elem_info *info)
-{
-       info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
-       info->count = 8;
-       info->value.integer.min = 0x0f;
-       info->value.integer.max = 0xff;
-       return 0;
-}
-
 static int alt_switch_get(struct snd_kcontrol *ctl,
                          struct snd_ctl_elem_value *value)
 {
        struct oxygen *chip = ctl->private_data;
 
        value->value.integer.value[0] =
-               !!(oxygen_read16(chip, OXYGEN_GPIO_DATA) & GPIO_ALT);
+               !!(oxygen_read16(chip, OXYGEN_GPIO_DATA) & GPIO_D2_ALT);
        return 0;
 }
 
@@ -345,9 +432,9 @@ static int alt_switch_put(struct snd_kcontrol *ctl,
        spin_lock_irq(&chip->reg_lock);
        old_bits = oxygen_read16(chip, OXYGEN_GPIO_DATA);
        if (value->value.integer.value[0])
-               new_bits = old_bits | GPIO_ALT;
+               new_bits = old_bits | GPIO_D2_ALT;
        else
-               new_bits = old_bits & ~GPIO_ALT;
+               new_bits = old_bits & ~GPIO_D2_ALT;
        changed = new_bits != old_bits;
        if (changed)
                oxygen_write16(chip, OXYGEN_GPIO_DATA, new_bits);
@@ -363,20 +450,68 @@ static const struct snd_kcontrol_new alt_switch = {
        .put = alt_switch_put,
 };
 
+static int front_panel_get(struct snd_kcontrol *ctl,
+                          struct snd_ctl_elem_value *value)
+{
+       struct oxygen *chip = ctl->private_data;
+
+       value->value.integer.value[0] =
+               !!(oxygen_read16(chip, OXYGEN_GPIO_DATA) & GPIO_DX_FRONT_PANEL);
+       return 0;
+}
+
+static int front_panel_put(struct snd_kcontrol *ctl,
+                          struct snd_ctl_elem_value *value)
+{
+       struct oxygen *chip = ctl->private_data;
+       u16 old_reg, new_reg;
+
+       spin_lock_irq(&chip->reg_lock);
+       old_reg = oxygen_read16(chip, OXYGEN_GPIO_DATA);
+       if (value->value.integer.value[0])
+               new_reg = old_reg | GPIO_DX_FRONT_PANEL;
+       else
+               new_reg = old_reg & ~GPIO_DX_FRONT_PANEL;
+       oxygen_write16(chip, OXYGEN_GPIO_DATA, new_reg);
+       spin_unlock_irq(&chip->reg_lock);
+       return old_reg != new_reg;
+}
+
+static const struct snd_kcontrol_new front_panel_switch = {
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name = "Front Panel Switch",
+       .info = snd_ctl_boolean_mono_info,
+       .get = front_panel_get,
+       .put = front_panel_put,
+};
+
+static void xonar_dx_ac97_switch(struct oxygen *chip,
+                                unsigned int reg, unsigned int mute)
+{
+       if (reg == AC97_LINE) {
+               spin_lock_irq(&chip->reg_lock);
+               oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
+                                     mute ? GPIO_DX_INPUT_ROUTE : 0,
+                                     GPIO_DX_INPUT_ROUTE);
+               spin_unlock_irq(&chip->reg_lock);
+       }
+}
+
 static const DECLARE_TLV_DB_SCALE(pcm1796_db_scale, -12000, 50, 0);
+static const DECLARE_TLV_DB_SCALE(cs4362a_db_scale, -12700, 100, 0);
 
-static int xonar_control_filter(struct snd_kcontrol_new *template)
+static int xonar_d2_control_filter(struct snd_kcontrol_new *template)
 {
-       if (!strcmp(template->name, "Master Playback Volume")) {
-               template->access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
-               template->info = pcm1796_volume_info,
-               template->tlv.p = pcm1796_db_scale;
-       } else if (!strncmp(template->name, "CD Capture ", 11)) {
+       if (!strncmp(template->name, "CD Capture ", 11))
                /* CD in is actually connected to the video in pin */
                template->private_value ^= AC97_CD ^ AC97_VIDEO;
-       } else if (!strcmp(template->name, "Line Capture Volume")) {
-               return 1; /* line-in bypasses the AC'97 mixer */
-       }
+       return 0;
+}
+
+static int xonar_dx_control_filter(struct snd_kcontrol_new *template)
+{
+       if (!strncmp(template->name, "CD Capture ", 11))
+               return 1; /* no CD input */
        return 0;
 }
 
@@ -385,30 +520,96 @@ static int xonar_mixer_init(struct oxygen *chip)
        return snd_ctl_add(chip->card, snd_ctl_new1(&alt_switch, chip));
 }
 
-static const struct oxygen_model model_xonar = {
-       .shortname = "Asus AV200",
-       .longname = "Asus Virtuoso 200",
-       .chip = "AV200",
-       .owner = THIS_MODULE,
-       .init = xonar_init,
-       .control_filter = xonar_control_filter,
-       .mixer_init = xonar_mixer_init,
-       .cleanup = xonar_cleanup,
-       .set_dac_params = set_pcm1796_params,
-       .set_adc_params = set_cs5381_params,
-       .update_dac_volume = update_pcm1796_volume,
-       .update_dac_mute = update_pcm1796_mute,
-       .ac97_switch_hook = xonar_ac97_switch_hook,
-       .gpio_changed = xonar_gpio_changed,
-       .model_data_size = sizeof(struct xonar_data),
-       .dac_channels = 8,
-       .used_channels = OXYGEN_CHANNEL_B |
-                        OXYGEN_CHANNEL_C |
-                        OXYGEN_CHANNEL_SPDIF |
-                        OXYGEN_CHANNEL_MULTICH,
-       .function_flags = OXYGEN_FUNCTION_ENABLE_SPI_4_5,
-       .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
-       .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
+static int xonar_dx_mixer_init(struct oxygen *chip)
+{
+       return snd_ctl_add(chip->card, snd_ctl_new1(&front_panel_switch, chip));
+}
+
+static const struct oxygen_model xonar_models[] = {
+       [MODEL_D2] = {
+               .shortname = "Xonar D2",
+               .longname = "Asus Virtuoso 200",
+               .chip = "AV200",
+               .owner = THIS_MODULE,
+               .init = xonar_d2_init,
+               .control_filter = xonar_d2_control_filter,
+               .mixer_init = xonar_mixer_init,
+               .cleanup = xonar_cleanup,
+               .set_dac_params = set_pcm1796_params,
+               .set_adc_params = set_cs53x1_params,
+               .update_dac_volume = update_pcm1796_volume,
+               .update_dac_mute = update_pcm1796_mute,
+               .dac_tlv = pcm1796_db_scale,
+               .model_data_size = sizeof(struct xonar_data),
+               .pcm_dev_cfg = PLAYBACK_0_TO_I2S |
+                              PLAYBACK_1_TO_SPDIF |
+                              CAPTURE_0_FROM_I2S_2 |
+                              CAPTURE_1_FROM_SPDIF,
+               .dac_channels = 8,
+               .dac_volume_min = 0x0f,
+               .dac_volume_max = 0xff,
+               .misc_flags = OXYGEN_MISC_MIDI,
+               .function_flags = OXYGEN_FUNCTION_SPI |
+                                 OXYGEN_FUNCTION_ENABLE_SPI_4_5,
+               .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
+               .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
+       },
+       [MODEL_D2X] = {
+               .shortname = "Xonar D2X",
+               .longname = "Asus Virtuoso 200",
+               .chip = "AV200",
+               .owner = THIS_MODULE,
+               .init = xonar_d2x_init,
+               .control_filter = xonar_d2_control_filter,
+               .mixer_init = xonar_mixer_init,
+               .cleanup = xonar_cleanup,
+               .set_dac_params = set_pcm1796_params,
+               .set_adc_params = set_cs53x1_params,
+               .update_dac_volume = update_pcm1796_volume,
+               .update_dac_mute = update_pcm1796_mute,
+               .gpio_changed = xonar_gpio_changed,
+               .dac_tlv = pcm1796_db_scale,
+               .model_data_size = sizeof(struct xonar_data),
+               .pcm_dev_cfg = PLAYBACK_0_TO_I2S |
+                              PLAYBACK_1_TO_SPDIF |
+                              CAPTURE_0_FROM_I2S_2 |
+                              CAPTURE_1_FROM_SPDIF,
+               .dac_channels = 8,
+               .dac_volume_min = 0x0f,
+               .dac_volume_max = 0xff,
+               .misc_flags = OXYGEN_MISC_MIDI,
+               .function_flags = OXYGEN_FUNCTION_SPI |
+                                 OXYGEN_FUNCTION_ENABLE_SPI_4_5,
+               .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
+               .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
+       },
+       [MODEL_DX] = {
+               .shortname = "Xonar DX",
+               .longname = "Asus Virtuoso 100",
+               .chip = "AV200",
+               .owner = THIS_MODULE,
+               .init = xonar_dx_init,
+               .control_filter = xonar_dx_control_filter,
+               .mixer_init = xonar_dx_mixer_init,
+               .cleanup = xonar_dx_cleanup,
+               .set_dac_params = set_cs43xx_params,
+               .set_adc_params = set_cs53x1_params,
+               .update_dac_volume = update_cs43xx_volume,
+               .update_dac_mute = update_cs43xx_mute,
+               .gpio_changed = xonar_gpio_changed,
+               .ac97_switch = xonar_dx_ac97_switch,
+               .dac_tlv = cs4362a_db_scale,
+               .model_data_size = sizeof(struct xonar_data),
+               .pcm_dev_cfg = PLAYBACK_0_TO_I2S |
+                              PLAYBACK_1_TO_SPDIF |
+                              CAPTURE_0_FROM_I2S_2,
+               .dac_channels = 8,
+               .dac_volume_min = 0,
+               .dac_volume_max = 127,
+               .function_flags = OXYGEN_FUNCTION_2WIRE,
+               .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
+               .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
+       },
 };
 
 static int __devinit xonar_probe(struct pci_dev *pci,
@@ -423,7 +624,8 @@ static int __devinit xonar_probe(struct pci_dev *pci,
                ++dev;
                return -ENOENT;
        }
-       err = oxygen_pci_probe(pci, index[dev], id[dev], 1, &model_xonar);
+       err = oxygen_pci_probe(pci, index[dev], id[dev],
+                              &xonar_models[pci_id->driver_data]);
        if (err >= 0)
                ++dev;
        return err;
diff --git a/sound/pci/oxygen/wm8785.h b/sound/pci/oxygen/wm8785.h
new file mode 100644 (file)
index 0000000..8c23e31
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef WM8785_H_INCLUDED
+#define WM8785_H_INCLUDED
+
+#define WM8785_R0      0
+#define WM8785_R1      1
+#define WM8785_R2      2
+#define WM8785_R7      7
+
+/* R0 */
+#define WM8785_MCR_MASK                0x007
+#define WM8785_MCR_SLAVE       0x000
+#define WM8785_MCR_MASTER_128  0x001
+#define WM8785_MCR_MASTER_192  0x002
+#define WM8785_MCR_MASTER_256  0x003
+#define WM8785_MCR_MASTER_384  0x004
+#define WM8785_MCR_MASTER_512  0x005
+#define WM8785_MCR_MASTER_768  0x006
+#define WM8785_OSR_MASK                0x018
+#define WM8785_OSR_SINGLE      0x000
+#define WM8785_OSR_DOUBLE      0x008
+#define WM8785_OSR_QUAD                0x010
+#define WM8785_FORMAT_MASK     0x060
+#define WM8785_FORMAT_RJUST    0x000
+#define WM8785_FORMAT_LJUST    0x020
+#define WM8785_FORMAT_I2S      0x040
+#define WM8785_FORMAT_DSP      0x060
+/* R1 */
+#define WM8785_WL_MASK         0x003
+#define WM8785_WL_16           0x000
+#define WM8785_WL_20           0x001
+#define WM8785_WL_24           0x002
+#define WM8785_WL_32           0x003
+#define WM8785_LRP             0x004
+#define WM8785_BCLKINV         0x008
+#define WM8785_LRSWAP          0x010
+#define WM8785_DEVNO_MASK      0x0e0
+/* R2 */
+#define WM8785_HPFR            0x001
+#define WM8785_HPFL            0x002
+#define WM8785_SDODIS          0x004
+#define WM8785_PWRDNR          0x008
+#define WM8785_PWRDNL          0x010
+#define WM8785_TDM_MASK                0x1c0
+
+#endif
index 9d5bb76229a8fc020eb0a9a869ed190b8e17ce87..7fdcdc8c6b6478bbce2fff1c3f784ed90fb51a37 100644 (file)
@@ -458,7 +458,7 @@ static int pcxhr_update_r_buffer(struct pcxhr_stream *stream)
 
        snd_printdd("pcxhr_update_r_buffer(pcm%c%d) : addr(%p) bytes(%zx) subs(%d)\n",
                    is_capture ? 'c' : 'p',
-                   chip->chip_idx, (void*)subs->runtime->dma_addr,
+                   chip->chip_idx, (void *)(long)subs->runtime->dma_addr,
                    subs->runtime->dma_bytes, subs->number);
 
        pcxhr_init_rmh(&rmh, CMD_UPDATE_R_BUFFERS);
@@ -626,7 +626,7 @@ static void pcxhr_trigger_tasklet(unsigned long arg)
 #ifdef CONFIG_SND_DEBUG_DETECT
        do_gettimeofday(&my_tv2);
        snd_printdd("***TRIGGER TASKLET*** TIME = %ld (err = %x)\n",
-                   my_tv2.tv_usec - my_tv1.tv_usec, err);
+                   (long)(my_tv2.tv_usec - my_tv1.tv_usec), err);
 #endif
 }
 
@@ -846,7 +846,6 @@ 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                 is_capture;
 
        mutex_lock(&mgr->setup_mutex);
 
@@ -856,12 +855,10 @@ static int pcxhr_open(struct snd_pcm_substream *subs)
        if( subs->stream == SNDRV_PCM_STREAM_PLAYBACK ) {
                snd_printdd("pcxhr_open playback chip%d subs%d\n",
                            chip->chip_idx, subs->number);
-               is_capture = 0;
                stream = &chip->playback_stream[subs->number];
        } else {
                snd_printdd("pcxhr_open capture chip%d subs%d\n",
                            chip->chip_idx, subs->number);
-               is_capture = 1;
                if (mgr->mono_capture)
                        runtime->hw.channels_max = 1;
                else
index c4e415d07380db810db6b3bd27a59ff89aeb76a3..78aa81feaa4a9edfccb8fde5444b580d3afbb1a6 100644 (file)
@@ -897,7 +897,7 @@ int pcxhr_set_pipe_state(struct pcxhr_mgr *mgr, int playback_mask, int capture_m
 #ifdef CONFIG_SND_DEBUG_DETECT
        do_gettimeofday(&my_tv2);
        snd_printdd("***SET PIPE STATE*** TIME = %ld (err = %x)\n",
-                   my_tv2.tv_usec - my_tv1.tv_usec, err);
+                   (long)(my_tv2.tv_usec - my_tv1.tv_usec), err);
 #endif
        return 0;
 }
@@ -1005,30 +1005,37 @@ void pcxhr_msg_tasklet(unsigned long arg)
                        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 err;
+                       u32 err2;
 
                        if (prmh->stat[i] & 0x800000) { /* if BIT_END */
                                snd_printdd("TASKLET : End%sPipe %d\n",
                                            is_capture ? "Record" : "Play", pipe);
                        }
                        i++;
-                       err = prmh->stat[i] ? prmh->stat[i] : prmh->stat[i+1];
-                       if (err)
-                               pcxhr_handle_async_err(mgr, err, PCXHR_ERR_PIPE,
+                       err2 = prmh->stat[i] ? prmh->stat[i] : prmh->stat[i+1];
+                       if (err2)
+                               pcxhr_handle_async_err(mgr, err2,
+                                                      PCXHR_ERR_PIPE,
                                                       pipe, is_capture);
                        i += 2;
                        for (j = 0; j < nb_stream; j++) {
-                               err = prmh->stat[i] ? prmh->stat[i] : prmh->stat[i+1];
-                               if (err)
-                                       pcxhr_handle_async_err(mgr, err, PCXHR_ERR_STREAM,
-                                                              pipe, is_capture);
+                               err2 = prmh->stat[i] ?
+                                       prmh->stat[i] : prmh->stat[i+1];
+                               if (err2)
+                                       pcxhr_handle_async_err(mgr, err2,
+                                                              PCXHR_ERR_STREAM,
+                                                              pipe,
+                                                              is_capture);
                                i += 2;
                        }
                        for (j = 0; j < nb_audio; j++) {
-                               err = prmh->stat[i] ? prmh->stat[i] : prmh->stat[i+1];
-                               if (err)
-                                       pcxhr_handle_async_err(mgr, err, PCXHR_ERR_AUDIO,
-                                                              pipe, is_capture);
+                               err2 = prmh->stat[i] ?
+                                       prmh->stat[i] : prmh->stat[i+1];
+                               if (err2)
+                                       pcxhr_handle_async_err(mgr, err2,
+                                                              PCXHR_ERR_AUDIO,
+                                                              pipe,
+                                                              is_capture);
                                i += 2;
                        }
                }
index 9408b1eeec40d551615334250d809d8aaf1acdc2..979f7da641ce28f0bc13e7c98f0664004e9bd5f6 100644 (file)
@@ -1630,14 +1630,14 @@ static int snd_riptide_playback_open(struct snd_pcm_substream *substream)
        struct snd_riptide *chip = snd_pcm_substream_chip(substream);
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct pcmhw *data;
-       int index = substream->number;
+       int sub_num = substream->number;
 
-       chip->playback_substream[index] = substream;
+       chip->playback_substream[sub_num] = substream;
        runtime->hw = snd_riptide_playback;
        data = kzalloc(sizeof(struct pcmhw), GFP_KERNEL);
-       data->paths = lbus_play_paths[index];
-       data->id = play_ids[index];
-       data->source = play_sources[index];
+       data->paths = lbus_play_paths[sub_num];
+       data->id = play_ids[sub_num];
+       data->source = play_sources[sub_num];
        data->intdec[0] = 0xff;
        data->intdec[1] = 0xff;
        data->state = ST_STOP;
@@ -1670,10 +1670,10 @@ static int snd_riptide_playback_close(struct snd_pcm_substream *substream)
 {
        struct snd_riptide *chip = snd_pcm_substream_chip(substream);
        struct pcmhw *data = get_pcmhwdev(substream);
-       int index = substream->number;
+       int sub_num = substream->number;
 
        substream->runtime->private_data = NULL;
-       chip->playback_substream[index] = NULL;
+       chip->playback_substream[sub_num] = NULL;
        kfree(data);
        return 0;
 }
index df184aabce846e3eb1611b50e3c2e7d92891dbb1..e7ef3a1a25a89a4643b85c888435f22cb28c34a1 100644 (file)
@@ -1350,7 +1350,8 @@ static int __devinit snd_rme32_create(struct rme32 * rme32)
                return err;
        rme32->port = pci_resource_start(rme32->pci, 0);
 
-       if ((rme32->iobase = ioremap_nocache(rme32->port, RME32_IO_SIZE)) == 0) {
+       rme32->iobase = ioremap_nocache(rme32->port, RME32_IO_SIZE);
+       if (!rme32->iobase) {
                snd_printk(KERN_ERR "unable to remap memory region 0x%lx-0x%lx\n",
                           rme32->port, rme32->port + RME32_IO_SIZE - 1);
                return -ENOMEM;
index fb0a4ee8bc02aaa0c9d3b7a341095a959a158f92..3fdd488d09759afca5389383c76590e57bb4dc63 100644 (file)
@@ -1559,7 +1559,8 @@ snd_rme96_create(struct rme96 *rme96)
                return err;
        rme96->port = pci_resource_start(rme96->pci, 0);
 
-       if ((rme96->iobase = ioremap_nocache(rme96->port, RME96_IO_SIZE)) == 0) {
+       rme96->iobase = ioremap_nocache(rme96->port, RME96_IO_SIZE);
+       if (!rme96->iobase) {
                snd_printk(KERN_ERR "unable to remap memory region 0x%lx-0x%lx\n", rme96->port, rme96->port + RME96_IO_SIZE - 1);
                return -ENOMEM;
        }
index 1be84f22d0de4cf82f3dd36a1ce6a6f910975e24..4d6fbb36ab8af1f2b7df881ff402402af28f8b53 100644 (file)
@@ -318,6 +318,10 @@ MODULE_FIRMWARE("digiface_firmware_rev11.bin");
 #define HDSP_midi1IRQPending    (1<<31)
 
 #define HDSP_spdifFrequencyMask    (HDSP_spdifFrequency0|HDSP_spdifFrequency1|HDSP_spdifFrequency2)
+#define HDSP_spdifFrequencyMask_9632 (HDSP_spdifFrequency0|\
+                                     HDSP_spdifFrequency1|\
+                                     HDSP_spdifFrequency2|\
+                                     HDSP_spdifFrequency3)
 
 #define HDSP_spdifFrequency32KHz   (HDSP_spdifFrequency0)
 #define HDSP_spdifFrequency44_1KHz (HDSP_spdifFrequency1)
@@ -328,7 +332,9 @@ MODULE_FIRMWARE("digiface_firmware_rev11.bin");
 #define HDSP_spdifFrequency96KHz   (HDSP_spdifFrequency2|HDSP_spdifFrequency1)
 
 /* This is for H9632 cards */
-#define HDSP_spdifFrequency128KHz   HDSP_spdifFrequencyMask
+#define HDSP_spdifFrequency128KHz   (HDSP_spdifFrequency0|\
+                                    HDSP_spdifFrequency1|\
+                                    HDSP_spdifFrequency2)
 #define HDSP_spdifFrequency176_4KHz HDSP_spdifFrequency3
 #define HDSP_spdifFrequency192KHz   (HDSP_spdifFrequency3|HDSP_spdifFrequency0)
 
@@ -885,28 +891,15 @@ static int snd_hdsp_use_is_exclusive(struct hdsp *hdsp)
        return ret;
 }
 
-static int hdsp_external_sample_rate (struct hdsp *hdsp)
-{
-       unsigned int status2 = hdsp_read(hdsp, HDSP_status2Register);
-       unsigned int rate_bits = status2 & HDSP_systemFrequencyMask;
-
-       switch (rate_bits) {
-       case HDSP_systemFrequency32:   return 32000;
-       case HDSP_systemFrequency44_1: return 44100;
-       case HDSP_systemFrequency48:   return 48000;
-       case HDSP_systemFrequency64:   return 64000;
-       case HDSP_systemFrequency88_2: return 88200;
-       case HDSP_systemFrequency96:   return 96000;
-       default:
-               return 0;
-       }
-}
-
 static int hdsp_spdif_sample_rate(struct hdsp *hdsp)
 {
        unsigned int status = hdsp_read(hdsp, HDSP_statusRegister);
        unsigned int rate_bits = (status & HDSP_spdifFrequencyMask);
 
+       /* For the 9632, the mask is different */
+       if (hdsp->io_type == H9632)
+                rate_bits = (status & HDSP_spdifFrequencyMask_9632);
+
        if (status & HDSP_SPDIFErrorFlag)
                return 0;
        
@@ -933,6 +926,31 @@ static int hdsp_spdif_sample_rate(struct hdsp *hdsp)
        return 0;
 }
 
+static int hdsp_external_sample_rate(struct hdsp *hdsp)
+{
+       unsigned int status2 = hdsp_read(hdsp, HDSP_status2Register);
+       unsigned int rate_bits = status2 & HDSP_systemFrequencyMask;
+
+       /* For the 9632 card, there seems to be no bit for indicating external
+        * sample rate greater than 96kHz. The card reports the corresponding
+        * single speed. So the best means seems to get spdif rate when
+        * autosync reference is spdif */
+       if (hdsp->io_type == H9632 &&
+           hdsp_autosync_ref(hdsp) == HDSP_AUTOSYNC_FROM_SPDIF)
+                return hdsp_spdif_sample_rate(hdsp);
+
+       switch (rate_bits) {
+       case HDSP_systemFrequency32:   return 32000;
+       case HDSP_systemFrequency44_1: return 44100;
+       case HDSP_systemFrequency48:   return 48000;
+       case HDSP_systemFrequency64:   return 64000;
+       case HDSP_systemFrequency88_2: return 88200;
+       case HDSP_systemFrequency96:   return 96000;
+       default:
+               return 0;
+       }
+}
+
 static void hdsp_compute_period_size(struct hdsp *hdsp)
 {
        hdsp->period_bytes = 1 << ((hdsp_decode_latency(hdsp->control_register) + 8));
index 9a19ae6a64d9a06f158a2da2f22a761edcd6c730..ab423bc823425834c108a3f84d060094324970ea 100644 (file)
@@ -540,7 +540,8 @@ static void hdspm_set_sgbuf(struct hdspm * hdspm, struct snd_sg_buf *sgbuf,
 
 static inline int HDSPM_bit2freq(int n)
 {
-       static int bit2freq_tab[] = { 0, 32000, 44100, 48000, 64000, 88200,
+       static const int bit2freq_tab[] = {
+               0, 32000, 44100, 48000, 64000, 88200,
                96000, 128000, 176400, 192000 };
        if (n < 1 || n > 9)
                return 0;
@@ -582,7 +583,7 @@ static inline int hdspm_read_pb_gain(struct hdspm * hdspm, unsigned int chan,
        return hdspm->mixer->ch[chan].pb[pb];
 }
 
-static inline int hdspm_write_in_gain(struct hdspm * hdspm, unsigned int chan,
+static int hdspm_write_in_gain(struct hdspm *hdspm, unsigned int chan,
                                      unsigned int in, unsigned short data)
 {
        if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)
@@ -595,7 +596,7 @@ static inline int hdspm_write_in_gain(struct hdspm * hdspm, unsigned int chan,
        return 0;
 }
 
-static inline int hdspm_write_pb_gain(struct hdspm * hdspm, unsigned int chan,
+static int hdspm_write_pb_gain(struct hdspm *hdspm, unsigned int chan,
                                      unsigned int pb, unsigned short data)
 {
        if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)
@@ -621,7 +622,7 @@ static inline void snd_hdspm_enable_out(struct hdspm * hdspm, int i, int v)
 }
 
 /* check if same process is writing and reading */
-static inline int snd_hdspm_use_is_exclusive(struct hdspm * hdspm)
+static int snd_hdspm_use_is_exclusive(struct hdspm *hdspm)
 {
        unsigned long flags;
        int ret = 1;
@@ -636,7 +637,7 @@ static inline int snd_hdspm_use_is_exclusive(struct hdspm * hdspm)
 }
 
 /* check for external sample rate */
-static inline int hdspm_external_sample_rate(struct hdspm * hdspm)
+static int hdspm_external_sample_rate(struct hdspm *hdspm)
 {
        if (hdspm->is_aes32) {
                unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
@@ -787,7 +788,7 @@ static inline void hdspm_stop_audio(struct hdspm * s)
 }
 
 /* should I silence all or only opened ones ? doit all for first even is 4MB*/
-static inline void hdspm_silence_playback(struct hdspm * hdspm)
+static void hdspm_silence_playback(struct hdspm *hdspm)
 {
        int i;
        int n = hdspm->period_bytes;
@@ -1028,9 +1029,9 @@ static inline void snd_hdspm_midi_write_byte (struct hdspm *hdspm, int id,
 {
        /* the hardware already does the relevant bit-mask with 0xff */
        if (id)
-               return hdspm_write(hdspm, HDSPM_midiDataOut1, val);
+               hdspm_write(hdspm, HDSPM_midiDataOut1, val);
        else
-               return hdspm_write(hdspm, HDSPM_midiDataOut0, val);
+               hdspm_write(hdspm, HDSPM_midiDataOut0, val);
 }
 
 static inline int snd_hdspm_midi_input_available (struct hdspm *hdspm, int id)
@@ -1057,7 +1058,7 @@ static inline int snd_hdspm_midi_output_possible (struct hdspm *hdspm, int id)
                return 0;
 }
 
-static inline void snd_hdspm_flush_midi_input (struct hdspm *hdspm, int id)
+static void snd_hdspm_flush_midi_input(struct hdspm *hdspm, int id)
 {
        while (snd_hdspm_midi_input_available (hdspm, id))
                snd_hdspm_midi_read_byte (hdspm, id);
index 742f1180c39e44ccdc65bb3214c0d7ebf8c2c4ec..df2007e3be7cbf63bb18f68c3ee144b6b5a1520b 100644 (file)
@@ -1194,7 +1194,6 @@ static int sis_suspend(struct pci_dev *pci, pm_message_t state)
        /* snd_pcm_suspend_all() stopped all channels, so we're quiescent.
         */
        if (sis->irq >= 0) {
-               synchronize_irq(sis->irq);
                free_irq(sis->irq, sis);
                sis->irq = -1;
        }
index 71138ff9b310237faedee66ea9a0445994bbb0a2..bbcee2c09ae42e15085cc91d0bcb1625b50118dd 100644 (file)
@@ -3676,6 +3676,8 @@ static int snd_trident_free(struct snd_trident *trident)
        else if (trident->device == TRIDENT_DEVICE_ID_SI7018) {
                outl(0, TRID_REG(trident, SI_SERIAL_INTF_CTRL));
        }
+       if (trident->irq >= 0)
+               free_irq(trident->irq, trident);
        if (trident->tlb.buffer.area) {
                outl(0, TRID_REG(trident, NX_TLBC));
                if (trident->tlb.memhdr)
@@ -3685,8 +3687,6 @@ static int snd_trident_free(struct snd_trident *trident)
                vfree(trident->tlb.shadow_entries);
                snd_dma_free_pages(&trident->tlb.buffer);
        }
-       if (trident->irq >= 0)
-               free_irq(trident->irq, trident);
        pci_release_regions(trident->pci);
        pci_disable_device(trident->pci);
        kfree(trident);
index a756be661f9aa94e1e1d4af3c77a666f02a25355..b585cc3e4c472eea6434e89d9ed463038f6a61c9 100644 (file)
@@ -2236,7 +2236,7 @@ static int snd_via82xx_free(struct via82xx *chip)
        /* disable interrupts */
        for (i = 0; i < chip->num_devs; i++)
                snd_via82xx_channel_reset(chip, &chip->devs[i]);
-       synchronize_irq(chip->irq);
+
        if (chip->irq >= 0)
                free_irq(chip->irq, chip);
  __end_hw:
index f5df1c79bee166594ade22aba607664e22a15f99..31f64ee398820c62ffb8c9b51318a2c4e122e9b0 100644 (file)
@@ -1075,7 +1075,7 @@ static int snd_via82xx_free(struct via82xx_modem *chip)
        /* disable interrupts */
        for (i = 0; i < chip->num_devs; i++)
                snd_via82xx_channel_reset(chip, &chip->devs[i]);
-       synchronize_irq(chip->irq);
+
       __end_hw:
        if (chip->irq >= 0)
                free_irq(chip->irq, chip);
index 42c1eb7d35f5d2b2e1811d32a3a893d705b1d2a8..29b3056c51098b708aaa6e860af148a011bae098 100644 (file)
@@ -2249,6 +2249,8 @@ static int snd_ymfpci_free(struct snd_ymfpci *chip)
 #ifdef CONFIG_PM
        vfree(chip->saved_regs);
 #endif
+       if (chip->irq >= 0)
+               free_irq(chip->irq, chip);
        release_and_free_resource(chip->mpu_res);
        release_and_free_resource(chip->fm_res);
        snd_ymfpci_free_gameport(chip);
@@ -2257,8 +2259,6 @@ static int snd_ymfpci_free(struct snd_ymfpci *chip)
        if (chip->work_ptr.area)
                snd_dma_free_pages(&chip->work_ptr);
        
-       if (chip->irq >= 0)
-               free_irq(chip->irq, chip);
        release_and_free_resource(chip->res_reg_area);
 
        pci_write_config_word(chip->pci, 0x40, chip->old_legacy_ctrl);
index 8441e780df0064254e1341e2d59c4fc9a79d32c5..566a6d0daf4a0161871305ac617ffa7b390975cc 100644 (file)
@@ -141,7 +141,7 @@ static int snd_pmac_awacs_info_volume(struct snd_kcontrol *kcontrol,
        uinfo->value.integer.max = 15;
        return 0;
 }
+
 static int snd_pmac_awacs_get_volume(struct snd_kcontrol *kcontrol,
                                     struct snd_ctl_elem_value *ucontrol)
 {
@@ -267,7 +267,8 @@ static int snd_pmac_awacs_put_switch(struct snd_kcontrol *kcontrol,
 static void awacs_set_cuda(int reg, int val)
 {
        struct adb_request req;
-       cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC, 0x8a, reg, val);
+       cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC, 0x8a,
+                       reg, val);
        while (! req.complete)
                cuda_poll();
 }
@@ -289,11 +290,11 @@ static void awacs_amp_set_tone(struct awacs_amp *amp, int bass, int treble)
 /*
  * vol = 0 - 31 (attenuation), 32 = mute bit, stereo
  */
-static int awacs_amp_set_vol(struct awacs_amp *amp, int index, int lvol, int rvol,
-                            int do_check)
+static int awacs_amp_set_vol(struct awacs_amp *amp, int index,
+                            int lvol, int rvol, int do_check)
 {
        if (do_check && amp->amp_vol[index][0] == lvol &&
-           amp->amp_vol[index][1] == rvol)
+                       amp->amp_vol[index][1] == rvol)
                return 0;
        awacs_set_cuda(3 + index, lvol);
        awacs_set_cuda(5 + index, rvol);
@@ -337,7 +338,7 @@ static int snd_pmac_awacs_info_volume_amp(struct snd_kcontrol *kcontrol,
        uinfo->value.integer.max = 31;
        return 0;
 }
+
 static int snd_pmac_awacs_get_volume_amp(struct snd_kcontrol *kcontrol,
                                         struct snd_ctl_elem_value *ucontrol)
 {
@@ -361,8 +362,10 @@ static int snd_pmac_awacs_put_volume_amp(struct snd_kcontrol *kcontrol,
        snd_assert(amp, return -EINVAL);
        snd_assert(index >= 0 && index <= 1, return -EINVAL);
 
-       vol[0] = (31 - (ucontrol->value.integer.value[0] & 31)) | (amp->amp_vol[index][0] & 32);
-       vol[1] = (31 - (ucontrol->value.integer.value[1] & 31)) | (amp->amp_vol[index][1] & 32);
+       vol[0] = (31 - (ucontrol->value.integer.value[0] & 31))
+               | (amp->amp_vol[index][0] & 32);
+       vol[1] = (31 - (ucontrol->value.integer.value[1] & 31))
+               | (amp->amp_vol[index][1] & 32);
        return awacs_amp_set_vol(amp, index, vol[0], vol[1], 1);
 }
 
@@ -374,8 +377,10 @@ static int snd_pmac_awacs_get_switch_amp(struct snd_kcontrol *kcontrol,
        struct awacs_amp *amp = chip->mixer_data;
        snd_assert(amp, return -EINVAL);
        snd_assert(index >= 0 && index <= 1, return -EINVAL);
-       ucontrol->value.integer.value[0] = (amp->amp_vol[index][0] & 32) ? 0 : 1;
-       ucontrol->value.integer.value[1] = (amp->amp_vol[index][1] & 32) ? 0 : 1;
+       ucontrol->value.integer.value[0] = (amp->amp_vol[index][0] & 32)
+                                       ? 0 : 1;
+       ucontrol->value.integer.value[1] = (amp->amp_vol[index][1] & 32)
+                                       ? 0 : 1;
        return 0;
 }
 
@@ -389,8 +394,10 @@ static int snd_pmac_awacs_put_switch_amp(struct snd_kcontrol *kcontrol,
        snd_assert(amp, return -EINVAL);
        snd_assert(index >= 0 && index <= 1, return -EINVAL);
 
-       vol[0] = (ucontrol->value.integer.value[0] ? 0 : 32) | (amp->amp_vol[index][0] & 31);
-       vol[1] = (ucontrol->value.integer.value[1] ? 0 : 32) | (amp->amp_vol[index][1] & 31);
+       vol[0] = (ucontrol->value.integer.value[0] ? 0 : 32)
+               | (amp->amp_vol[index][0] & 31);
+       vol[1] = (ucontrol->value.integer.value[1] ? 0 : 32)
+               | (amp->amp_vol[index][1] & 31);
        return awacs_amp_set_vol(amp, index, vol[0], vol[1], 1);
 }
 
@@ -403,7 +410,7 @@ static int snd_pmac_awacs_info_tone_amp(struct snd_kcontrol *kcontrol,
        uinfo->value.integer.max = 14;
        return 0;
 }
+
 static int snd_pmac_awacs_get_tone_amp(struct snd_kcontrol *kcontrol,
                                       struct snd_ctl_elem_value *ucontrol)
 {
@@ -445,7 +452,7 @@ static int snd_pmac_awacs_info_master_amp(struct snd_kcontrol *kcontrol,
        uinfo->value.integer.max = 99;
        return 0;
 }
+
 static int snd_pmac_awacs_get_master_amp(struct snd_kcontrol *kcontrol,
                                         struct snd_ctl_elem_value *ucontrol)
 {
@@ -544,7 +551,7 @@ static int snd_pmac_screamer_mic_boost_info(struct snd_kcontrol *kcontrol,
        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
        uinfo->count = 1;
        uinfo->value.integer.min = 0;
-       uinfo->value.integer.max = 2;
+       uinfo->value.integer.max = 3;
        return 0;
 }
 
@@ -552,16 +559,14 @@ static int snd_pmac_screamer_mic_boost_get(struct snd_kcontrol *kcontrol,
                                           struct snd_ctl_elem_value *ucontrol)
 {
        struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
-       int val;
+       int val = 0;
        unsigned long flags;
 
        spin_lock_irqsave(&chip->reg_lock, flags);
        if (chip->awacs_reg[6] & MASK_MIC_BOOST)
-               val = 2;
-       else if (chip->awacs_reg[0] & MASK_GAINLINE)
-               val = 1;
-       else
-               val = 0;
+               val |= 2;
+       if (chip->awacs_reg[0] & MASK_GAINLINE)
+               val |= 1;
        spin_unlock_irqrestore(&chip->reg_lock, flags);
        ucontrol->value.integer.value[0] = val;
        return 0;
@@ -578,11 +583,10 @@ static int snd_pmac_screamer_mic_boost_put(struct snd_kcontrol *kcontrol,
        spin_lock_irqsave(&chip->reg_lock, flags);
        val0 = chip->awacs_reg[0] & ~MASK_GAINLINE;
        val6 = chip->awacs_reg[6] & ~MASK_MIC_BOOST;
-       if (ucontrol->value.integer.value[0] > 0) {
+       if (ucontrol->value.integer.value[0] & 1)
                val0 |= MASK_GAINLINE;
-               if (ucontrol->value.integer.value[0] > 1)
-                       val6 |= MASK_MIC_BOOST;
-       }
+       if (ucontrol->value.integer.value[0] & 2)
+               val6 |= MASK_MIC_BOOST;
        if (val0 != chip->awacs_reg[0]) {
                snd_pmac_awacs_write_reg(chip, 0, val0);
                changed = 1;
@@ -599,9 +603,32 @@ static int snd_pmac_screamer_mic_boost_put(struct snd_kcontrol *kcontrol,
  * lists of mixer elements
  */
 static struct snd_kcontrol_new snd_pmac_awacs_mixers[] __initdata = {
-       AWACS_VOLUME("Master Playback Volume", 2, 6, 1),
        AWACS_SWITCH("Master Capture Switch", 1, SHIFT_LOOPTHRU, 0),
-       AWACS_VOLUME("Capture Volume", 0, 4, 0),
+       AWACS_VOLUME("Master Capture Volume", 0, 4, 0),
+/*     AWACS_SWITCH("Unknown Playback Switch", 6, SHIFT_PAROUT0, 0), */
+};
+
+static struct snd_kcontrol_new snd_pmac_screamer_mixers_beige[] __initdata = {
+       AWACS_VOLUME("Master Playback Volume", 2, 6, 1),
+       AWACS_VOLUME("Play-through Playback Volume", 5, 6, 1),
+       AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0),
+       AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_LINE, 0),
+};
+
+static struct snd_kcontrol_new snd_pmac_screamer_mixers_imac[] __initdata = {
+       AWACS_VOLUME("Line out Playback Volume", 2, 6, 1),
+       AWACS_VOLUME("Master Playback Volume", 5, 6, 1),
+       AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
+};
+
+static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac7500[] __initdata = {
+       AWACS_VOLUME("Line out Playback Volume", 2, 6, 1),
+       AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
+       AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0),
+};
+
+static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac[] __initdata = {
+       AWACS_VOLUME("Master Playback Volume", 2, 6, 1),
        AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
 };
 
@@ -621,35 +648,61 @@ static struct snd_kcontrol_new snd_pmac_screamer_mixers2[] __initdata = {
 static struct snd_kcontrol_new snd_pmac_awacs_master_sw __initdata =
 AWACS_SWITCH("Master Playback Switch", 1, SHIFT_HDMUTE, 1);
 
+static struct snd_kcontrol_new snd_pmac_awacs_master_sw_imac __initdata =
+AWACS_SWITCH("Line out Playback Switch", 1, SHIFT_HDMUTE, 1);
+
 static struct snd_kcontrol_new snd_pmac_awacs_mic_boost[] __initdata = {
-       AWACS_SWITCH("Mic Boost", 0, SHIFT_GAINLINE, 0),
+       AWACS_SWITCH("Mic Boost Capture Switch", 0, SHIFT_GAINLINE, 0),
 };
 
 static struct snd_kcontrol_new snd_pmac_screamer_mic_boost[] __initdata = {
        { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-         .name = "Mic Boost",
+         .name = "Mic Boost Capture Volume",
          .info = snd_pmac_screamer_mic_boost_info,
          .get = snd_pmac_screamer_mic_boost_get,
          .put = snd_pmac_screamer_mic_boost_put,
        },
 };
 
+static struct snd_kcontrol_new snd_pmac_awacs_mic_boost_pmac7500[] __initdata =
+{
+       AWACS_SWITCH("Line Boost Capture Switch", 0, SHIFT_GAINLINE, 0),
+};
+
+static struct snd_kcontrol_new snd_pmac_screamer_mic_boost_beige[] __initdata =
+{
+       AWACS_SWITCH("Line Boost Capture Switch", 0, SHIFT_GAINLINE, 0),
+       AWACS_SWITCH("CD Boost Capture Switch", 6, SHIFT_MIC_BOOST, 0),
+};
+
+static struct snd_kcontrol_new snd_pmac_screamer_mic_boost_imac[] __initdata =
+{
+       AWACS_SWITCH("Line Boost Capture Switch", 0, SHIFT_GAINLINE, 0),
+       AWACS_SWITCH("Mic Boost Capture Switch", 6, SHIFT_MIC_BOOST, 0),
+};
+
 static struct snd_kcontrol_new snd_pmac_awacs_speaker_vol[] __initdata = {
        AWACS_VOLUME("PC Speaker Playback Volume", 4, 6, 1),
 };
+
 static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw __initdata =
 AWACS_SWITCH("PC Speaker Playback Switch", 1, SHIFT_SPKMUTE, 1);
 
+static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw_imac __initdata =
+AWACS_SWITCH("PC Speaker Playback Switch", 1, SHIFT_PAROUT1, 0);
+
 
 /*
  * add new mixer elements to the card
  */
-static int build_mixers(struct snd_pmac *chip, int nums, struct snd_kcontrol_new *mixers)
+static int build_mixers(struct snd_pmac *chip, int nums,
+                       struct snd_kcontrol_new *mixers)
 {
        int i, err;
 
        for (i = 0; i < nums; i++) {
-               if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&mixers[i], chip))) < 0)
+               err = snd_ctl_add(chip->card, snd_ctl_new1(&mixers[i], chip));
+               if (err < 0)
                        return err;
        }
        return 0;
@@ -699,8 +752,10 @@ static void snd_pmac_awacs_resume(struct snd_pmac *chip)
 #ifdef PMAC_AMP_AVAIL
        if (chip->mixer_data) {
                struct awacs_amp *amp = chip->mixer_data;
-               awacs_amp_set_vol(amp, 0, amp->amp_vol[0][0], amp->amp_vol[0][1], 0);
-               awacs_amp_set_vol(amp, 1, amp->amp_vol[1][0], amp->amp_vol[1][1], 0);
+               awacs_amp_set_vol(amp, 0,
+                                 amp->amp_vol[0][0], amp->amp_vol[0][1], 0);
+               awacs_amp_set_vol(amp, 1,
+                                 amp->amp_vol[1][0], amp->amp_vol[1][1], 0);
                awacs_amp_set_tone(amp, amp->amp_tone[0], amp->amp_tone[1]);
                awacs_amp_set_master(amp, amp->amp_master);
        }
@@ -708,6 +763,14 @@ static void snd_pmac_awacs_resume(struct snd_pmac *chip)
 }
 #endif /* CONFIG_PM */
 
+#define IS_PM7500 (machine_is_compatible("AAPL,7500"))
+#define IS_BEIGE (machine_is_compatible("AAPL,Gossamer"))
+#define IS_IMAC (machine_is_compatible("PowerMac2,1") \
+               || machine_is_compatible("PowerMac2,2") \
+               || machine_is_compatible("PowerMac4,1"))
+
+static int imac;
+
 #ifdef PMAC_SUPPORT_AUTOMUTE
 /*
  * auto-mute stuffs
@@ -750,9 +813,16 @@ static void snd_pmac_awacs_update_automute(struct snd_pmac *chip, int do_notify)
                } else
 #endif
                {
-                       int reg = chip->awacs_reg[1] | (MASK_HDMUTE|MASK_SPKMUTE);
+                       int reg = chip->awacs_reg[1]
+                               | (MASK_HDMUTE | MASK_SPKMUTE);
+                       if (imac) {
+                               reg &= ~MASK_SPKMUTE;
+                               reg &= ~MASK_PAROUT1;
+                       }
                        if (snd_pmac_awacs_detect_headphone(chip))
                                reg &= ~MASK_HDMUTE;
+                       else if (imac)
+                               reg |= MASK_PAROUT1;
                        else
                                reg &= ~MASK_SPKMUTE;
                        if (do_notify && reg == chip->awacs_reg[1])
@@ -778,8 +848,11 @@ static void snd_pmac_awacs_update_automute(struct snd_pmac *chip, int do_notify)
 int __init
 snd_pmac_awacs_init(struct snd_pmac *chip)
 {
+       int pm7500 = IS_PM7500;
+       int beige = IS_BEIGE;
        int err, vol;
 
+       imac = IS_IMAC;
        /* looks like MASK_GAINLINE triggers something, so we set here
         * as start-up
         */
@@ -787,7 +860,7 @@ snd_pmac_awacs_init(struct snd_pmac *chip)
        chip->awacs_reg[1] = MASK_CMUTE | MASK_AMUTE;
        /* FIXME: Only machines with external SRS module need MASK_PAROUT */
        if (chip->has_iic || chip->device_id == 0x5 ||
-           /*chip->_device_id == 0x8 || */
+           /* chip->_device_id == 0x8 || */
            chip->device_id == 0xb)
                chip->awacs_reg[1] |= MASK_PAROUT;
        /* get default volume from nvram */
@@ -798,8 +871,10 @@ snd_pmac_awacs_init(struct snd_pmac *chip)
        chip->awacs_reg[2] = vol;
        chip->awacs_reg[4] = vol;
        if (chip->model == PMAC_SCREAMER) {
-               chip->awacs_reg[5] = vol; /* FIXME: screamer has loopthru vol control */
-               chip->awacs_reg[6] = MASK_MIC_BOOST; /* FIXME: maybe should be vol << 3 for PCMCIA speaker */
+               /* FIXME: screamer has loopthru vol control */
+               chip->awacs_reg[5] = vol;
+               /* FIXME: maybe should be vol << 3 for PCMCIA speaker */
+               chip->awacs_reg[6] = MASK_MIC_BOOST;
                chip->awacs_reg[7] = 0;
        }
 
@@ -815,7 +890,8 @@ snd_pmac_awacs_init(struct snd_pmac *chip)
                        return -ENOMEM;
                chip->mixer_data = amp;
                chip->mixer_free = awacs_amp_free;
-               awacs_amp_set_vol(amp, 0, 63, 63, 0); /* mute and zero vol */
+               /* mute and zero vol */
+               awacs_amp_set_vol(amp, 0, 63, 63, 0);
                awacs_amp_set_vol(amp, 1, 63, 63, 0);
                awacs_amp_set_tone(amp, 7, 7); /* 0 dB */
                awacs_amp_set_master(amp, 79); /* 0 dB */
@@ -826,20 +902,25 @@ snd_pmac_awacs_init(struct snd_pmac *chip)
                /* set headphone-jack detection bit */
                switch (chip->model) {
                case PMAC_AWACS:
-                       chip->hp_stat_mask = 0x04;
+                       chip->hp_stat_mask = pm7500 ? MASK_HDPCONN
+                               : MASK_LOCONN;
                        break;
                case PMAC_SCREAMER:
                        switch (chip->device_id) {
                        case 0x08:
-                               /* 1 = side jack, 2 = front jack */
-                               chip->hp_stat_mask = 0x03;
+                       case 0x0B:
+                               chip->hp_stat_mask = imac
+                                       ? MASK_LOCONN_IMAC |
+                                       MASK_HDPLCONN_IMAC |
+                                       MASK_HDPRCONN_IMAC
+                                       : MASK_HDPCONN;
                                break;
                        case 0x00:
                        case 0x05:
-                               chip->hp_stat_mask = 0x04;
+                               chip->hp_stat_mask = MASK_LOCONN;
                                break;
                        default:
-                               chip->hp_stat_mask = 0x08;
+                               chip->hp_stat_mask = MASK_HDPCONN;
                                break;
                        }
                        break;
@@ -854,19 +935,43 @@ snd_pmac_awacs_init(struct snd_pmac *chip)
         */
        strcpy(chip->card->mixername, "PowerMac AWACS");
 
-       if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mixers),
-                               snd_pmac_awacs_mixers)) < 0)
+       err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mixers),
+                               snd_pmac_awacs_mixers);
+       if (err < 0)
                return err;
-       if (chip->model == PMAC_SCREAMER)
+       if (beige)
+               ;
+       else if (chip->model == PMAC_SCREAMER)
                err = build_mixers(chip, ARRAY_SIZE(snd_pmac_screamer_mixers2),
                                   snd_pmac_screamer_mixers2);
-       else
+       else if (!pm7500)
                err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mixers2),
                                   snd_pmac_awacs_mixers2);
        if (err < 0)
                return err;
-       chip->master_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_master_sw, chip);
-       if ((err = snd_ctl_add(chip->card, chip->master_sw_ctl)) < 0)
+       if (pm7500)
+               err = build_mixers(chip,
+                                  ARRAY_SIZE(snd_pmac_awacs_mixers_pmac7500),
+                                  snd_pmac_awacs_mixers_pmac7500);
+       else if (beige)
+               err = build_mixers(chip,
+                                  ARRAY_SIZE(snd_pmac_screamer_mixers_beige),
+                                  snd_pmac_screamer_mixers_beige);
+       else if (imac)
+               err = build_mixers(chip,
+                                  ARRAY_SIZE(snd_pmac_screamer_mixers_imac),
+                                  snd_pmac_screamer_mixers_imac);
+       else
+               err = build_mixers(chip,
+                                  ARRAY_SIZE(snd_pmac_awacs_mixers_pmac),
+                                  snd_pmac_awacs_mixers_pmac);
+       if (err < 0)
+               return err;
+       chip->master_sw_ctl = snd_ctl_new1((pm7500 || imac)
+                       ? &snd_pmac_awacs_master_sw_imac
+                       : &snd_pmac_awacs_master_sw, chip);
+       err = snd_ctl_add(chip->card, chip->master_sw_ctl);
+       if (err < 0)
                return err;
 #ifdef PMAC_AMP_AVAIL
        if (chip->mixer_data) {
@@ -876,37 +981,58 @@ snd_pmac_awacs_init(struct snd_pmac *chip)
                 * screamer registers.
                 * in this case, it seems the route C is not used.
                 */
-               if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_amp_vol),
-                                       snd_pmac_awacs_amp_vol)) < 0)
+               err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_amp_vol),
+                                       snd_pmac_awacs_amp_vol);
+               if (err < 0)
                        return err;
                /* overwrite */
-               chip->master_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_amp_hp_sw, chip);
-               if ((err = snd_ctl_add(chip->card, chip->master_sw_ctl)) < 0)
+               chip->master_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_amp_hp_sw,
+                                                       chip);
+               err = snd_ctl_add(chip->card, chip->master_sw_ctl);
+               if (err < 0)
                        return err;
-               chip->speaker_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_amp_spk_sw, chip);
-               if ((err = snd_ctl_add(chip->card, chip->speaker_sw_ctl)) < 0)
+               chip->speaker_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_amp_spk_sw,
+                                                       chip);
+               err = snd_ctl_add(chip->card, chip->speaker_sw_ctl);
+               if (err < 0)
                        return err;
        } else
 #endif /* PMAC_AMP_AVAIL */
        {
                /* route A = headphone, route C = speaker */
-               if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_speaker_vol),
-                                       snd_pmac_awacs_speaker_vol)) < 0)
+               err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_speaker_vol),
+                                       snd_pmac_awacs_speaker_vol);
+               if (err < 0)
                        return err;
-               chip->speaker_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_speaker_sw, chip);
-               if ((err = snd_ctl_add(chip->card, chip->speaker_sw_ctl)) < 0)
+               chip->speaker_sw_ctl = snd_ctl_new1(imac
+                               ? &snd_pmac_awacs_speaker_sw_imac
+                               : &snd_pmac_awacs_speaker_sw, chip);
+               err = snd_ctl_add(chip->card, chip->speaker_sw_ctl);
+               if (err < 0)
                        return err;
        }
 
-       if (chip->model == PMAC_SCREAMER) {
-               if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_screamer_mic_boost),
-                                       snd_pmac_screamer_mic_boost)) < 0)
-                       return err;
-       } else {
-               if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mic_boost),
-                                       snd_pmac_awacs_mic_boost)) < 0)
-                       return err;
-       }
+       if (beige)
+               err = build_mixers(chip,
+                               ARRAY_SIZE(snd_pmac_screamer_mic_boost_beige),
+                               snd_pmac_screamer_mic_boost_beige);
+       else if (imac)
+               err = build_mixers(chip,
+                               ARRAY_SIZE(snd_pmac_screamer_mic_boost_imac),
+                               snd_pmac_screamer_mic_boost_imac);
+       else if (chip->model == PMAC_SCREAMER)
+               err = build_mixers(chip,
+                               ARRAY_SIZE(snd_pmac_screamer_mic_boost),
+                               snd_pmac_screamer_mic_boost);
+       else if (pm7500)
+               err = build_mixers(chip,
+                               ARRAY_SIZE(snd_pmac_awacs_mic_boost_pmac7500),
+                               snd_pmac_awacs_mic_boost_pmac7500);
+       else
+               err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mic_boost),
+                               snd_pmac_awacs_mic_boost);
+       if (err < 0)
+               return err;
 
        /*
         * set lowlevel callbacks
@@ -917,7 +1043,8 @@ snd_pmac_awacs_init(struct snd_pmac *chip)
        chip->resume = snd_pmac_awacs_resume;
 #endif
 #ifdef PMAC_SUPPORT_AUTOMUTE
-       if ((err = snd_pmac_add_automute(chip)) < 0)
+       err = snd_pmac_add_automute(chip);
+       if (err < 0)
                return err;
        chip->detect_headphone = snd_pmac_awacs_detect_headphone;
        chip->update_automute = snd_pmac_awacs_update_automute;
index 1b2cc44eda574030847d342e7b31aaaa73a5eb92..c33e6a531cf7a5b762e757f7c873dfa9581636d3 100644 (file)
@@ -116,6 +116,11 @@ struct awacs_regs {
 #define MASK_HDMUTE    MASK_AMUTE
 #define SHIFT_HDMUTE   9
 #define MASK_PAROUT    (0x3 << 10)     /* Parallel Out (???) */
+#define MASK_PAROUT0   (0x1 << 10)     /* Parallel Out (???) */
+#define MASK_PAROUT1   (0x1 << 11)     /* Parallel Out (enable speaker) */
+#define SHIFT_PAROUT   10
+#define SHIFT_PAROUT0  10
+#define SHIFT_PAROUT1  11
 
 #define SAMPLERATE_48000       (0x0 << 3)      /* 48 or 44.1 kHz */
 #define SAMPLERATE_32000       (0x1 << 3)      /* 32 or 29.4 kHz */
@@ -139,7 +144,7 @@ struct awacs_regs {
 #define VOLLEFT(x)     (((~(x)) << 6) & MASK_OUTVOLLEFT)
 
 /* address 6 */
-#define MASK_MIC_BOOST  (0x4)           /* screamer mic boost */
+#define MASK_MIC_BOOST  (0x4)          /* screamer mic boost */
 #define SHIFT_MIC_BOOST        2
 
 /* Audio Codec Status Reg Bit Masks */
@@ -152,8 +157,15 @@ struct awacs_regs {
 #define MASK_REVISION  (0xf << 12)     /* Revision Number */
 #define MASK_MFGID     (0xf << 8)      /* Mfg. ID */
 #define MASK_CODSTATRES        (0xf << 4)      /* bits 4 - 7 reserved */
-#define MASK_INPPORT   (0xf)           /* Input Port */
-#define MASK_HDPCONN   8               /* headphone plugged in */
+#define MASK_INSENSE   (0xf)           /* port sense bits: */
+#define MASK_HDPCONN           8       /* headphone plugged in */
+#define MASK_LOCONN            4       /* line-out plugged in */
+#define MASK_LICONN            2       /* line-in plugged in */
+#define MASK_MICCONN           1       /* microphone plugged in */
+#define MASK_LICONN_IMAC       8       /* line-in plugged in */
+#define MASK_HDPRCONN_IMAC     4       /* headphone right plugged in */
+#define MASK_HDPLCONN_IMAC     2       /* headphone left plugged in */
+#define MASK_LOCONN_IMAC       1       /* line-out plugged in */
 
 /* Clipping Count Reg Bit Masks */
 /* -------- ----- --- --- ----- */
@@ -163,7 +175,8 @@ struct awacs_regs {
 /* DBDMA ChannelStatus Bit Masks */
 /* ----- ------------- --- ----- */
 #define MASK_CSERR     (0x1 << 7)      /* Error */
-#define MASK_EOI       (0x1 << 6)      /* End of Input -- only for Input Channel */
+#define MASK_EOI       (0x1 << 6)      /* End of Input --
+                                          only for Input Channel */
 #define MASK_CSUNUSED  (0x1f << 1)     /* bits 1-5 not used */
 #define MASK_WAIT      (0x1)           /* Wait */
 
index 1a545ac0de04ee7634cee72db9f0e35cc7608a7f..f860d39af36b39e91fafe4ceb33be28b9d5b7167 100644 (file)
@@ -102,7 +102,8 @@ snd_pmac_burgundy_rcw(struct snd_pmac *chip, unsigned addr)
 }
 
 static void
-snd_pmac_burgundy_wcb(struct snd_pmac *chip, unsigned int addr, unsigned int val)
+snd_pmac_burgundy_wcb(struct snd_pmac *chip, unsigned int addr,
+                     unsigned int val)
 {
        out_le32(&chip->awacs->codec_ctrl, addr + 0x300000 + (val & 0xff));
        snd_pmac_burgundy_busy_wait(chip);
@@ -126,8 +127,11 @@ snd_pmac_burgundy_rcb(struct snd_pmac *chip, unsigned int addr)
        return val;
 }
 
+#define BASE2ADDR(base)        ((base) << 12)
+#define ADDR2BASE(addr)        ((addr) >> 12)
+
 /*
- * Burgundy volume: 0 - 100, stereo
+ * Burgundy volume: 0 - 100, stereo, word reg
  */
 static void
 snd_pmac_burgundy_write_volume(struct snd_pmac *chip, unsigned int address,
@@ -168,13 +172,6 @@ snd_pmac_burgundy_read_volume(struct snd_pmac *chip, unsigned int address,
                volume[1] = 0;
 }
 
-
-/*
- */
-
-#define BASE2ADDR(base)        ((base) << 12)
-#define ADDR2BASE(addr)        ((addr) >> 12)
-
 static int snd_pmac_burgundy_info_volume(struct snd_kcontrol *kcontrol,
                                         struct snd_ctl_elem_info *uinfo)
 {
@@ -191,8 +188,8 @@ static int snd_pmac_burgundy_get_volume(struct snd_kcontrol *kcontrol,
        struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
        unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
        int shift = (kcontrol->private_value >> 8) & 0xff;
-       snd_pmac_burgundy_read_volume(chip, addr, ucontrol->value.integer.value,
-                                     shift);
+       snd_pmac_burgundy_read_volume(chip, addr,
+                                     ucontrol->value.integer.value, shift);
        return 0;
 }
 
@@ -204,24 +201,163 @@ static int snd_pmac_burgundy_put_volume(struct snd_kcontrol *kcontrol,
        int shift = (kcontrol->private_value >> 8) & 0xff;
        long nvoices[2];
 
-       snd_pmac_burgundy_write_volume(chip, addr, ucontrol->value.integer.value,
-                                      shift);
+       snd_pmac_burgundy_write_volume(chip, addr,
+                                      ucontrol->value.integer.value, shift);
        snd_pmac_burgundy_read_volume(chip, addr, nvoices, shift);
        return (nvoices[0] != ucontrol->value.integer.value[0] ||
                nvoices[1] != ucontrol->value.integer.value[1]);
 }
 
-#define BURGUNDY_VOLUME(xname, xindex, addr, shift) \
+#define BURGUNDY_VOLUME_W(xname, xindex, addr, shift) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\
   .info = snd_pmac_burgundy_info_volume,\
   .get = snd_pmac_burgundy_get_volume,\
   .put = snd_pmac_burgundy_put_volume,\
   .private_value = ((ADDR2BASE(addr) & 0xff) | ((shift) << 8)) }
 
-/* lineout/speaker */
+/*
+ * Burgundy volume: 0 - 100, stereo, 2-byte reg
+ */
+static void
+snd_pmac_burgundy_write_volume_2b(struct snd_pmac *chip, unsigned int address,
+                                 long *volume, int off)
+{
+       int lvolume, rvolume;
 
-static int snd_pmac_burgundy_info_switch_out(struct snd_kcontrol *kcontrol,
-                                            struct snd_ctl_elem_info *uinfo)
+       off |= off << 2;
+       lvolume = volume[0] ? volume[0] + BURGUNDY_VOLUME_OFFSET : 0;
+       rvolume = volume[1] ? volume[1] + BURGUNDY_VOLUME_OFFSET : 0;
+
+       snd_pmac_burgundy_wcb(chip, address + off, lvolume);
+       snd_pmac_burgundy_wcb(chip, address + off + 0x500, rvolume);
+}
+
+static void
+snd_pmac_burgundy_read_volume_2b(struct snd_pmac *chip, unsigned int address,
+                                long *volume, int off)
+{
+       volume[0] = snd_pmac_burgundy_rcb(chip, address + off);
+       if (volume[0] >= BURGUNDY_VOLUME_OFFSET)
+               volume[0] -= BURGUNDY_VOLUME_OFFSET;
+       else
+               volume[0] = 0;
+       volume[1] = snd_pmac_burgundy_rcb(chip, address + off + 0x100);
+       if (volume[1] >= BURGUNDY_VOLUME_OFFSET)
+               volume[1] -= BURGUNDY_VOLUME_OFFSET;
+       else
+               volume[1] = 0;
+}
+
+static int snd_pmac_burgundy_info_volume_2b(struct snd_kcontrol *kcontrol,
+                                           struct snd_ctl_elem_info *uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = 2;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = 100;
+       return 0;
+}
+
+static int snd_pmac_burgundy_get_volume_2b(struct snd_kcontrol *kcontrol,
+                                          struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+       unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
+       int off = kcontrol->private_value & 0x300;
+       snd_pmac_burgundy_read_volume_2b(chip, addr,
+                       ucontrol->value.integer.value, off);
+       return 0;
+}
+
+static int snd_pmac_burgundy_put_volume_2b(struct snd_kcontrol *kcontrol,
+                                          struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+       unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
+       int off = kcontrol->private_value & 0x300;
+       long nvoices[2];
+
+       snd_pmac_burgundy_write_volume_2b(chip, addr,
+                       ucontrol->value.integer.value, off);
+       snd_pmac_burgundy_read_volume_2b(chip, addr, nvoices, off);
+       return (nvoices[0] != ucontrol->value.integer.value[0] ||
+               nvoices[1] != ucontrol->value.integer.value[1]);
+}
+
+#define BURGUNDY_VOLUME_2B(xname, xindex, addr, off) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\
+  .info = snd_pmac_burgundy_info_volume_2b,\
+  .get = snd_pmac_burgundy_get_volume_2b,\
+  .put = snd_pmac_burgundy_put_volume_2b,\
+  .private_value = ((ADDR2BASE(addr) & 0xff) | ((off) << 8)) }
+
+/*
+ * Burgundy gain/attenuation: 0 - 15, mono/stereo, byte reg
+ */
+static int snd_pmac_burgundy_info_gain(struct snd_kcontrol *kcontrol,
+                                      struct snd_ctl_elem_info *uinfo)
+{
+       int stereo = (kcontrol->private_value >> 24) & 1;
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = stereo + 1;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = 15;
+       return 0;
+}
+
+static int snd_pmac_burgundy_get_gain(struct snd_kcontrol *kcontrol,
+                                     struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+       unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
+       int stereo = (kcontrol->private_value >> 24) & 1;
+       int atten = (kcontrol->private_value >> 25) & 1;
+       int oval;
+
+       oval = snd_pmac_burgundy_rcb(chip, addr);
+       if (atten)
+               oval = ~oval & 0xff;
+       ucontrol->value.integer.value[0] = oval & 0xf;
+       if (stereo)
+               ucontrol->value.integer.value[1] = (oval >> 4) & 0xf;
+       return 0;
+}
+
+static int snd_pmac_burgundy_put_gain(struct snd_kcontrol *kcontrol,
+                                     struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+       unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
+       int stereo = (kcontrol->private_value >> 24) & 1;
+       int atten = (kcontrol->private_value >> 25) & 1;
+       int oval, val;
+
+       oval = snd_pmac_burgundy_rcb(chip, addr);
+       if (atten)
+               oval = ~oval & 0xff;
+       val = ucontrol->value.integer.value[0];
+       if (stereo)
+               val |= ucontrol->value.integer.value[1] << 4;
+       else
+               val |= ucontrol->value.integer.value[0] << 4;
+       if (atten)
+               val = ~val & 0xff;
+       snd_pmac_burgundy_wcb(chip, addr, val);
+       return val != oval;
+}
+
+#define BURGUNDY_VOLUME_B(xname, xindex, addr, stereo, atten) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\
+  .info = snd_pmac_burgundy_info_gain,\
+  .get = snd_pmac_burgundy_get_gain,\
+  .put = snd_pmac_burgundy_put_gain,\
+  .private_value = (ADDR2BASE(addr) | ((stereo) << 24) | ((atten) << 25)) }
+
+/*
+ * Burgundy switch: 0/1, mono/stereo, word reg
+ */
+static int snd_pmac_burgundy_info_switch_w(struct snd_kcontrol *kcontrol,
+                                          struct snd_ctl_elem_info *uinfo)
 {
        int stereo = (kcontrol->private_value >> 24) & 1;
        uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
@@ -231,111 +367,207 @@ static int snd_pmac_burgundy_info_switch_out(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-static int snd_pmac_burgundy_get_switch_out(struct snd_kcontrol *kcontrol,
-                                           struct snd_ctl_elem_value *ucontrol)
+static int snd_pmac_burgundy_get_switch_w(struct snd_kcontrol *kcontrol,
+                                         struct snd_ctl_elem_value *ucontrol)
 {
        struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
-       int lmask = kcontrol->private_value & 0xff;
-       int rmask = (kcontrol->private_value >> 8) & 0xff;
+       unsigned int addr = BASE2ADDR((kcontrol->private_value >> 16) & 0xff);
+       int lmask = 1 << (kcontrol->private_value & 0xff);
+       int rmask = 1 << ((kcontrol->private_value >> 8) & 0xff);
        int stereo = (kcontrol->private_value >> 24) & 1;
-       int val = snd_pmac_burgundy_rcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES);
+       int val = snd_pmac_burgundy_rcw(chip, addr);
        ucontrol->value.integer.value[0] = (val & lmask) ? 1 : 0;
        if (stereo)
                ucontrol->value.integer.value[1] = (val & rmask) ? 1 : 0;
        return 0;
 }
 
-static int snd_pmac_burgundy_put_switch_out(struct snd_kcontrol *kcontrol,
-                                           struct snd_ctl_elem_value *ucontrol)
+static int snd_pmac_burgundy_put_switch_w(struct snd_kcontrol *kcontrol,
+                                         struct snd_ctl_elem_value *ucontrol)
 {
        struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
-       int lmask = kcontrol->private_value & 0xff;
-       int rmask = (kcontrol->private_value >> 8) & 0xff;
+       unsigned int addr = BASE2ADDR((kcontrol->private_value >> 16) & 0xff);
+       int lmask = 1 << (kcontrol->private_value & 0xff);
+       int rmask = 1 << ((kcontrol->private_value >> 8) & 0xff);
        int stereo = (kcontrol->private_value >> 24) & 1;
        int val, oval;
-       oval = snd_pmac_burgundy_rcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES);
-       val = oval & ~(lmask | rmask);
+       oval = snd_pmac_burgundy_rcw(chip, addr);
+       val = oval & ~(lmask | (stereo ? rmask : 0));
        if (ucontrol->value.integer.value[0])
                val |= lmask;
        if (stereo && ucontrol->value.integer.value[1])
                val |= rmask;
-       snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, val);
+       snd_pmac_burgundy_wcw(chip, addr, val);
        return val != oval;
 }
 
-#define BURGUNDY_OUTPUT_SWITCH(xname, xindex, lmask, rmask, stereo) \
+#define BURGUNDY_SWITCH_W(xname, xindex, addr, lbit, rbit, stereo) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\
-  .info = snd_pmac_burgundy_info_switch_out,\
-  .get = snd_pmac_burgundy_get_switch_out,\
-  .put = snd_pmac_burgundy_put_switch_out,\
-  .private_value = ((lmask) | ((rmask) << 8) | ((stereo) << 24)) }
-
-/* line/speaker output volume */
-static int snd_pmac_burgundy_info_volume_out(struct snd_kcontrol *kcontrol,
-                                            struct snd_ctl_elem_info *uinfo)
+  .info = snd_pmac_burgundy_info_switch_w,\
+  .get = snd_pmac_burgundy_get_switch_w,\
+  .put = snd_pmac_burgundy_put_switch_w,\
+  .private_value = ((lbit) | ((rbit) << 8)\
+               | (ADDR2BASE(addr) << 16) | ((stereo) << 24)) }
+
+/*
+ * Burgundy switch: 0/1, mono/stereo, byte reg, bit mask
+ */
+static int snd_pmac_burgundy_info_switch_b(struct snd_kcontrol *kcontrol,
+                                          struct snd_ctl_elem_info *uinfo)
 {
        int stereo = (kcontrol->private_value >> 24) & 1;
-       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
        uinfo->count = stereo + 1;
        uinfo->value.integer.min = 0;
-       uinfo->value.integer.max = 15;
+       uinfo->value.integer.max = 1;
        return 0;
 }
 
-static int snd_pmac_burgundy_get_volume_out(struct snd_kcontrol *kcontrol,
-                                           struct snd_ctl_elem_value *ucontrol)
+static int snd_pmac_burgundy_get_switch_b(struct snd_kcontrol *kcontrol,
+                                         struct snd_ctl_elem_value *ucontrol)
 {
        struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
-       unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
+       unsigned int addr = BASE2ADDR((kcontrol->private_value >> 16) & 0xff);
+       int lmask = kcontrol->private_value & 0xff;
+       int rmask = (kcontrol->private_value >> 8) & 0xff;
        int stereo = (kcontrol->private_value >> 24) & 1;
-       int oval;
-
-       oval = ~snd_pmac_burgundy_rcb(chip, addr) & 0xff;
-       ucontrol->value.integer.value[0] = oval & 0xf;
+       int val = snd_pmac_burgundy_rcb(chip, addr);
+       ucontrol->value.integer.value[0] = (val & lmask) ? 1 : 0;
        if (stereo)
-               ucontrol->value.integer.value[1] = (oval >> 4) & 0xf;
+               ucontrol->value.integer.value[1] = (val & rmask) ? 1 : 0;
        return 0;
 }
 
-static int snd_pmac_burgundy_put_volume_out(struct snd_kcontrol *kcontrol,
-                                           struct snd_ctl_elem_value *ucontrol)
+static int snd_pmac_burgundy_put_switch_b(struct snd_kcontrol *kcontrol,
+                                         struct snd_ctl_elem_value *ucontrol)
 {
        struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
-       unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
+       unsigned int addr = BASE2ADDR((kcontrol->private_value >> 16) & 0xff);
+       int lmask = kcontrol->private_value & 0xff;
+       int rmask = (kcontrol->private_value >> 8) & 0xff;
        int stereo = (kcontrol->private_value >> 24) & 1;
-       unsigned int oval, val;
-
-       oval = ~snd_pmac_burgundy_rcb(chip, addr) & 0xff;
-       val = ucontrol->value.integer.value[0] & 15;
-       if (stereo)
-               val |= (ucontrol->value.integer.value[1] & 15) << 4;
-       else
-               val |= val << 4;
-       val = ~val & 0xff;
+       int val, oval;
+       oval = snd_pmac_burgundy_rcb(chip, addr);
+       val = oval & ~(lmask | rmask);
+       if (ucontrol->value.integer.value[0])
+               val |= lmask;
+       if (stereo && ucontrol->value.integer.value[1])
+               val |= rmask;
        snd_pmac_burgundy_wcb(chip, addr, val);
        return val != oval;
 }
 
-#define BURGUNDY_OUTPUT_VOLUME(xname, xindex, addr, stereo) \
+#define BURGUNDY_SWITCH_B(xname, xindex, addr, lmask, rmask, stereo) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\
-  .info = snd_pmac_burgundy_info_volume_out,\
-  .get = snd_pmac_burgundy_get_volume_out,\
-  .put = snd_pmac_burgundy_put_volume_out,\
-  .private_value = (ADDR2BASE(addr) | ((stereo) << 24)) }
+  .info = snd_pmac_burgundy_info_switch_b,\
+  .get = snd_pmac_burgundy_get_switch_b,\
+  .put = snd_pmac_burgundy_put_switch_b,\
+  .private_value = ((lmask) | ((rmask) << 8)\
+               | (ADDR2BASE(addr) << 16) | ((stereo) << 24)) }
 
+/*
+ * Burgundy mixers
+ */
 static struct snd_kcontrol_new snd_pmac_burgundy_mixers[] __initdata = {
-       BURGUNDY_VOLUME("Master Playback Volume", 0, MASK_ADDR_BURGUNDY_MASTER_VOLUME, 8),
-       BURGUNDY_VOLUME("Line Playback Volume", 0, MASK_ADDR_BURGUNDY_VOLLINE, 16),
-       BURGUNDY_VOLUME("CD Playback Volume", 0, MASK_ADDR_BURGUNDY_VOLCD, 16),
-       BURGUNDY_VOLUME("Mic Playback Volume", 0, MASK_ADDR_BURGUNDY_VOLMIC, 16),
-       BURGUNDY_OUTPUT_VOLUME("PC Speaker Playback Volume", 0, MASK_ADDR_BURGUNDY_ATTENHP, 0),
-       /*BURGUNDY_OUTPUT_VOLUME("PCM Playback Volume", 0, MASK_ADDR_BURGUNDY_ATTENLINEOUT, 1),*/
-       BURGUNDY_OUTPUT_VOLUME("Headphone Playback Volume", 0, MASK_ADDR_BURGUNDY_ATTENSPEAKER, 1),
-};     
-static struct snd_kcontrol_new snd_pmac_burgundy_master_sw __initdata = 
-BURGUNDY_OUTPUT_SWITCH("Headphone Playback Switch", 0, BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1);
-static struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw __initdata = 
-BURGUNDY_OUTPUT_SWITCH("PC Speaker Playback Switch", 0, BURGUNDY_OUTPUT_INTERN, 0, 0);
+       BURGUNDY_VOLUME_W("Master Playback Volume", 0,
+                       MASK_ADDR_BURGUNDY_MASTER_VOLUME, 8),
+       BURGUNDY_VOLUME_W("CD Capture Volume", 0,
+                       MASK_ADDR_BURGUNDY_VOLCD, 16),
+       BURGUNDY_VOLUME_2B("Input Capture Volume", 0,
+                       MASK_ADDR_BURGUNDY_VOLMIX01, 2),
+       BURGUNDY_VOLUME_2B("Mixer Playback Volume", 0,
+                       MASK_ADDR_BURGUNDY_VOLMIX23, 0),
+       BURGUNDY_VOLUME_B("CD Gain Capture Volume", 0,
+                       MASK_ADDR_BURGUNDY_GAINCD, 1, 0),
+       BURGUNDY_SWITCH_W("Master Capture Switch", 0,
+                       MASK_ADDR_BURGUNDY_OUTPUTENABLES, 24, 0, 0),
+       BURGUNDY_SWITCH_W("CD Capture Switch", 0,
+                       MASK_ADDR_BURGUNDY_CAPTURESELECTS, 0, 16, 1),
+       BURGUNDY_SWITCH_W("CD Playback Switch", 0,
+                       MASK_ADDR_BURGUNDY_OUTPUTSELECTS, 0, 16, 1),
+/*     BURGUNDY_SWITCH_W("Loop Capture Switch", 0,
+ *             MASK_ADDR_BURGUNDY_CAPTURESELECTS, 8, 24, 1),
+ *     BURGUNDY_SWITCH_B("Mixer out Capture Switch", 0,
+ *             MASK_ADDR_BURGUNDY_HOSTIFAD, 0x02, 0, 0),
+ *     BURGUNDY_SWITCH_B("Mixer Capture Switch", 0,
+ *             MASK_ADDR_BURGUNDY_HOSTIFAD, 0x01, 0, 0),
+ *     BURGUNDY_SWITCH_B("PCM out Capture Switch", 0,
+ *             MASK_ADDR_BURGUNDY_HOSTIFEH, 0x02, 0, 0),
+ */    BURGUNDY_SWITCH_B("PCM Capture Switch", 0,
+                       MASK_ADDR_BURGUNDY_HOSTIFEH, 0x01, 0, 0)
+};
+static struct snd_kcontrol_new snd_pmac_burgundy_mixers_imac[] __initdata = {
+       BURGUNDY_VOLUME_W("Line in Capture Volume", 0,
+                       MASK_ADDR_BURGUNDY_VOLLINE, 16),
+       BURGUNDY_VOLUME_W("Mic Capture Volume", 0,
+                       MASK_ADDR_BURGUNDY_VOLMIC, 16),
+       BURGUNDY_VOLUME_B("Line in Gain Capture Volume", 0,
+                       MASK_ADDR_BURGUNDY_GAINLINE, 1, 0),
+       BURGUNDY_VOLUME_B("Mic Gain Capture Volume", 0,
+                       MASK_ADDR_BURGUNDY_GAINMIC, 1, 0),
+       BURGUNDY_VOLUME_B("PC Speaker Playback Volume", 0,
+                       MASK_ADDR_BURGUNDY_ATTENSPEAKER, 1, 1),
+       BURGUNDY_VOLUME_B("Line out Playback Volume", 0,
+                       MASK_ADDR_BURGUNDY_ATTENLINEOUT, 1, 1),
+       BURGUNDY_VOLUME_B("Headphone Playback Volume", 0,
+                       MASK_ADDR_BURGUNDY_ATTENHP, 1, 1),
+       BURGUNDY_SWITCH_W("Line in Capture Switch", 0,
+                       MASK_ADDR_BURGUNDY_CAPTURESELECTS, 1, 17, 1),
+       BURGUNDY_SWITCH_W("Mic Capture Switch", 0,
+                       MASK_ADDR_BURGUNDY_CAPTURESELECTS, 2, 18, 1),
+       BURGUNDY_SWITCH_W("Line in Playback Switch", 0,
+                       MASK_ADDR_BURGUNDY_OUTPUTSELECTS, 1, 17, 1),
+       BURGUNDY_SWITCH_W("Mic Playback Switch", 0,
+                       MASK_ADDR_BURGUNDY_OUTPUTSELECTS, 2, 18, 1),
+       BURGUNDY_SWITCH_B("Mic Boost Capture Switch", 0,
+                       MASK_ADDR_BURGUNDY_INPBOOST, 0x40, 0x80, 1)
+};
+static struct snd_kcontrol_new snd_pmac_burgundy_mixers_pmac[] __initdata = {
+       BURGUNDY_VOLUME_W("Line in Capture Volume", 0,
+                       MASK_ADDR_BURGUNDY_VOLMIC, 16),
+       BURGUNDY_VOLUME_B("Line in Gain Capture Volume", 0,
+                       MASK_ADDR_BURGUNDY_GAINMIC, 1, 0),
+       BURGUNDY_VOLUME_B("PC Speaker Playback Volume", 0,
+                       MASK_ADDR_BURGUNDY_ATTENMONO, 0, 1),
+       BURGUNDY_VOLUME_B("Line out Playback Volume", 0,
+                       MASK_ADDR_BURGUNDY_ATTENSPEAKER, 1, 1),
+       BURGUNDY_SWITCH_W("Line in Capture Switch", 0,
+                       MASK_ADDR_BURGUNDY_CAPTURESELECTS, 2, 18, 1),
+       BURGUNDY_SWITCH_W("Line in Playback Switch", 0,
+                       MASK_ADDR_BURGUNDY_OUTPUTSELECTS, 2, 18, 1),
+/*     BURGUNDY_SWITCH_B("Line in Boost Capture Switch", 0,
+ *             MASK_ADDR_BURGUNDY_INPBOOST, 0x40, 0x80, 1) */
+};
+static struct snd_kcontrol_new snd_pmac_burgundy_master_sw_imac __initdata =
+BURGUNDY_SWITCH_B("Master Playback Switch", 0,
+       MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
+       BURGUNDY_OUTPUT_LEFT | BURGUNDY_LINEOUT_LEFT | BURGUNDY_HP_LEFT,
+       BURGUNDY_OUTPUT_RIGHT | BURGUNDY_LINEOUT_RIGHT | BURGUNDY_HP_RIGHT, 1);
+static struct snd_kcontrol_new snd_pmac_burgundy_master_sw_pmac __initdata =
+BURGUNDY_SWITCH_B("Master Playback Switch", 0,
+       MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
+       BURGUNDY_OUTPUT_INTERN
+       | BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1);
+static struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw_imac __initdata =
+BURGUNDY_SWITCH_B("PC Speaker Playback Switch", 0,
+       MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
+       BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1);
+static struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw_pmac __initdata =
+BURGUNDY_SWITCH_B("PC Speaker Playback Switch", 0,
+       MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
+       BURGUNDY_OUTPUT_INTERN, 0, 0);
+static struct snd_kcontrol_new snd_pmac_burgundy_line_sw_imac __initdata =
+BURGUNDY_SWITCH_B("Line out Playback Switch", 0,
+       MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
+       BURGUNDY_LINEOUT_LEFT, BURGUNDY_LINEOUT_RIGHT, 1);
+static struct snd_kcontrol_new snd_pmac_burgundy_line_sw_pmac __initdata =
+BURGUNDY_SWITCH_B("Line out Playback Switch", 0,
+       MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
+       BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1);
+static struct snd_kcontrol_new snd_pmac_burgundy_hp_sw_imac __initdata =
+BURGUNDY_SWITCH_B("Headphone Playback Switch", 0,
+       MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
+       BURGUNDY_HP_LEFT, BURGUNDY_HP_RIGHT, 1);
 
 
 #ifdef PMAC_SUPPORT_AUTOMUTE
@@ -350,16 +582,26 @@ static int snd_pmac_burgundy_detect_headphone(struct snd_pmac *chip)
 static void snd_pmac_burgundy_update_automute(struct snd_pmac *chip, int do_notify)
 {
        if (chip->auto_mute) {
+               int imac = machine_is_compatible("iMac");
                int reg, oreg;
-               reg = oreg = snd_pmac_burgundy_rcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES);
-               reg &= ~(BURGUNDY_OUTPUT_LEFT | BURGUNDY_OUTPUT_RIGHT | BURGUNDY_OUTPUT_INTERN);
+               reg = oreg = snd_pmac_burgundy_rcb(chip,
+                               MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES);
+               reg &= imac ? ~(BURGUNDY_OUTPUT_LEFT | BURGUNDY_OUTPUT_RIGHT
+                               | BURGUNDY_HP_LEFT | BURGUNDY_HP_RIGHT)
+                       : ~(BURGUNDY_OUTPUT_LEFT | BURGUNDY_OUTPUT_RIGHT
+                               | BURGUNDY_OUTPUT_INTERN);
                if (snd_pmac_burgundy_detect_headphone(chip))
-                       reg |= BURGUNDY_OUTPUT_LEFT | BURGUNDY_OUTPUT_RIGHT;
+                       reg |= imac ? (BURGUNDY_HP_LEFT | BURGUNDY_HP_RIGHT)
+                               : (BURGUNDY_OUTPUT_LEFT
+                                       | BURGUNDY_OUTPUT_RIGHT);
                else
-                       reg |= BURGUNDY_OUTPUT_INTERN;
+                       reg |= imac ? (BURGUNDY_OUTPUT_LEFT
+                                       | BURGUNDY_OUTPUT_RIGHT)
+                               : (BURGUNDY_OUTPUT_INTERN);
                if (do_notify && reg == oreg)
                        return;
-               snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, reg);
+               snd_pmac_burgundy_wcb(chip,
+                               MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, reg);
                if (do_notify) {
                        snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
                                       &chip->master_sw_ctl->id);
@@ -378,6 +620,7 @@ static void snd_pmac_burgundy_update_automute(struct snd_pmac *chip, int do_noti
  */
 int __init snd_pmac_burgundy_init(struct snd_pmac *chip)
 {
+       int imac = machine_is_compatible("iMac");
        int i, err;
 
        /* Checks to see the chip is alive and kicking */
@@ -386,7 +629,7 @@ int __init snd_pmac_burgundy_init(struct snd_pmac *chip)
                return 1;
        }
 
-       snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_OUTPUTENABLES,
+       snd_pmac_burgundy_wcw(chip, MASK_ADDR_BURGUNDY_OUTPUTENABLES,
                           DEF_BURGUNDY_OUTPUTENABLES);
        snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
                           DEF_BURGUNDY_MORE_OUTPUTENABLES);
@@ -396,7 +639,8 @@ int __init snd_pmac_burgundy_init(struct snd_pmac *chip)
        snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_INPSEL21,
                           DEF_BURGUNDY_INPSEL21);
        snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_INPSEL3,
-                          DEF_BURGUNDY_INPSEL3);
+                          imac ? DEF_BURGUNDY_INPSEL3_IMAC
+                          : DEF_BURGUNDY_INPSEL3_PMAC);
        snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_GAINCD,
                           DEF_BURGUNDY_GAINCD);
        snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_GAINLINE,
@@ -422,27 +666,62 @@ int __init snd_pmac_burgundy_init(struct snd_pmac *chip)
        snd_pmac_burgundy_wcw(chip, MASK_ADDR_BURGUNDY_VOLMIC,
                           DEF_BURGUNDY_VOLMIC);
 
-       if (chip->hp_stat_mask == 0)
+       if (chip->hp_stat_mask == 0) {
                /* set headphone-jack detection bit */
-               chip->hp_stat_mask = 0x04;
-
+               if (imac)
+                       chip->hp_stat_mask = BURGUNDY_HPDETECT_IMAC_UPPER
+                               | BURGUNDY_HPDETECT_IMAC_LOWER
+                               | BURGUNDY_HPDETECT_IMAC_SIDE;
+               else
+                       chip->hp_stat_mask = BURGUNDY_HPDETECT_PMAC_BACK;
+       }
        /*
         * build burgundy mixers
         */
        strcpy(chip->card->mixername, "PowerMac Burgundy");
 
        for (i = 0; i < ARRAY_SIZE(snd_pmac_burgundy_mixers); i++) {
-               if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_pmac_burgundy_mixers[i], chip))) < 0)
+               err = snd_ctl_add(chip->card,
+                   snd_ctl_new1(&snd_pmac_burgundy_mixers[i], chip));
+               if (err < 0)
+                       return err;
+       }
+       for (i = 0; i < (imac ? ARRAY_SIZE(snd_pmac_burgundy_mixers_imac)
+                       : ARRAY_SIZE(snd_pmac_burgundy_mixers_pmac)); i++) {
+               err = snd_ctl_add(chip->card,
+                   snd_ctl_new1(imac ? &snd_pmac_burgundy_mixers_imac[i]
+                   : &snd_pmac_burgundy_mixers_pmac[i], chip));
+               if (err < 0)
                        return err;
        }
-       chip->master_sw_ctl = snd_ctl_new1(&snd_pmac_burgundy_master_sw, chip);
-       if ((err = snd_ctl_add(chip->card, chip->master_sw_ctl)) < 0)
+       chip->master_sw_ctl = snd_ctl_new1(imac
+                       ? &snd_pmac_burgundy_master_sw_imac
+                       : &snd_pmac_burgundy_master_sw_pmac, chip);
+       err = snd_ctl_add(chip->card, chip->master_sw_ctl);
+       if (err < 0)
+               return err;
+       chip->master_sw_ctl = snd_ctl_new1(imac
+                       ? &snd_pmac_burgundy_line_sw_imac
+                       : &snd_pmac_burgundy_line_sw_pmac, chip);
+       err = snd_ctl_add(chip->card, chip->master_sw_ctl);
+       if (err < 0)
                return err;
-       chip->speaker_sw_ctl = snd_ctl_new1(&snd_pmac_burgundy_speaker_sw, chip);
-       if ((err = snd_ctl_add(chip->card, chip->speaker_sw_ctl)) < 0)
+       if (imac) {
+               chip->master_sw_ctl = snd_ctl_new1(
+                               &snd_pmac_burgundy_hp_sw_imac, chip);
+               err = snd_ctl_add(chip->card, chip->master_sw_ctl);
+               if (err < 0)
+                       return err;
+       }
+       chip->speaker_sw_ctl = snd_ctl_new1(imac
+                       ? &snd_pmac_burgundy_speaker_sw_imac
+                       : &snd_pmac_burgundy_speaker_sw_pmac, chip);
+       err = snd_ctl_add(chip->card, chip->speaker_sw_ctl);
+       if (err < 0)
                return err;
 #ifdef PMAC_SUPPORT_AUTOMUTE
-       if ((err = snd_pmac_add_automute(chip)) < 0)
+       err = snd_pmac_add_automute(chip);
+       if (err < 0)
                return err;
 
        chip->detect_headphone = snd_pmac_burgundy_detect_headphone;
index ebb457a8342c818aa8b4def01a5a0021c2a3dc3d..7a7f9cf3d2999314fa3b74f397c74832d1b94932 100644 (file)
@@ -22,6 +22,7 @@
 #ifndef __BURGUNDY_H
 #define __BURGUNDY_H
 
+#define MASK_ADDR_BURGUNDY_INPBOOST (0x10 << 12)
 #define MASK_ADDR_BURGUNDY_INPSEL21 (0x11 << 12)
 #define MASK_ADDR_BURGUNDY_INPSEL3 (0x12 << 12)
 
 #define MASK_ADDR_BURGUNDY_VOLCH3 (0x22 << 12)
 #define MASK_ADDR_BURGUNDY_VOLCH4 (0x23 << 12)
 
+#define MASK_ADDR_BURGUNDY_CAPTURESELECTS (0x2A << 12)
 #define MASK_ADDR_BURGUNDY_OUTPUTSELECTS (0x2B << 12)
+#define MASK_ADDR_BURGUNDY_VOLMIX01 (0x2D << 12)
+#define MASK_ADDR_BURGUNDY_VOLMIX23 (0x2E << 12)
 #define MASK_ADDR_BURGUNDY_OUTPUTENABLES (0x2F << 12)
 
 #define MASK_ADDR_BURGUNDY_MASTER_VOLUME (0x30 << 12)
 #define MASK_ADDR_BURGUNDY_ATTENSPEAKER (0x62 << 12)
 #define MASK_ADDR_BURGUNDY_ATTENLINEOUT (0x63 << 12)
 #define MASK_ADDR_BURGUNDY_ATTENHP (0x64 << 12)
+#define MASK_ADDR_BURGUNDY_ATTENMONO (0x65 << 12)
+
+#define MASK_ADDR_BURGUNDY_HOSTIFAD (0x78 << 12)
+#define MASK_ADDR_BURGUNDY_HOSTIFEH (0x79 << 12)
 
 #define MASK_ADDR_BURGUNDY_VOLCD (MASK_ADDR_BURGUNDY_VOLCH1)
 #define MASK_ADDR_BURGUNDY_VOLLINE (MASK_ADDR_BURGUNDY_VOLCH2)
 
 /* These are all default values for the burgundy */
 #define DEF_BURGUNDY_INPSEL21 (0xAA)
-#define DEF_BURGUNDY_INPSEL3 (0x0A)
+#define DEF_BURGUNDY_INPSEL3_IMAC (0x0A)
+#define DEF_BURGUNDY_INPSEL3_PMAC (0x05)
 
 #define DEF_BURGUNDY_GAINCD (0x33)
 #define DEF_BURGUNDY_GAINLINE (0x44)
 #define DEF_BURGUNDY_GAINMIC (0x44)
 #define DEF_BURGUNDY_GAINMODEM (0x06)
 
-/* Remember: lowest volume here is 0x9b */
+/* Remember: lowest volume here is 0x9B (155) */
 #define DEF_BURGUNDY_VOLCD (0xCCCCCCCC)
 #define DEF_BURGUNDY_VOLLINE (0x00000000)
 #define DEF_BURGUNDY_VOLMIC (0x00000000)
 #define DEF_BURGUNDY_VOLMODEM (0xCCCCCCCC)
 
-#define DEF_BURGUNDY_OUTPUTSELECTS (0x010f010f)
-#define DEF_BURGUNDY_OUTPUTENABLES (0x0A)
+#define DEF_BURGUNDY_OUTPUTSELECTS (0x010F010F)
+#define DEF_BURGUNDY_OUTPUTENABLES (0x0100000A)
 
 /* #define DEF_BURGUNDY_MASTER_VOLUME (0xFFFFFFFF) */ /* too loud */
 #define DEF_BURGUNDY_MASTER_VOLUME (0xDDDDDDDD)
 #define DEF_BURGUNDY_ATTENLINEOUT (0xCC)
 #define DEF_BURGUNDY_ATTENHP (0xCC)
 
-/* OUTPUTENABLES bits */
+/* MORE_OUTPUTENABLES bits */
 #define BURGUNDY_OUTPUT_LEFT   0x02
 #define BURGUNDY_OUTPUT_RIGHT  0x04
+#define BURGUNDY_LINEOUT_LEFT  0x08
+#define BURGUNDY_LINEOUT_RIGHT 0x10
+#define BURGUNDY_HP_LEFT       0x20
+#define BURGUNDY_HP_RIGHT      0x40
 #define BURGUNDY_OUTPUT_INTERN 0x80
 
-/* volume offset */
+/* Headphone detection bits */
+#define BURGUNDY_HPDETECT_PMAC_BACK    0x04
+#define BURGUNDY_HPDETECT_IMAC_SIDE    0x04
+#define BURGUNDY_HPDETECT_IMAC_UPPER   0x08
+#define BURGUNDY_HPDETECT_IMAC_LOWER   0x01
+
+/* Volume offset */
 #define BURGUNDY_VOLUME_OFFSET 155
 
 #endif /* __BURGUNDY_H */
index 613a565e04de896ba11253d776e94b0dabc80c7d..a38c0c790d2bb3ab6e4175477dbcf4a77e345a3d 100644 (file)
@@ -214,7 +214,7 @@ static int snd_pmac_pcm_prepare(struct snd_pmac *chip, struct pmac_stream *rec,
        int rate_index;
        long offset;
        struct pmac_stream *astr;
-       
+
        rec->dma_size = snd_pcm_lib_buffer_bytes(subs);
        rec->period_size = snd_pcm_lib_period_bytes(subs);
        rec->nperiods = rec->dma_size / rec->period_size;
@@ -643,7 +643,7 @@ static int snd_pmac_pcm_close(struct snd_pmac *chip, struct pmac_stream *rec,
        /* reset constraints */
        astr->cur_freqs = chip->freqs_ok;
        astr->cur_formats = chip->formats_ok;
-       
+
        return 0;
 }
 
@@ -1300,9 +1300,9 @@ int __init snd_pmac_new(struct snd_card *card, struct snd_pmac **chip_return)
 
        snd_pmac_sound_feature(chip, 1);
 
-       /* reset */
-       if (chip->model == PMAC_AWACS)
-               out_le32(&chip->awacs->control, 0x11);
+       /* reset & enable interrupts */
+       if (chip->model <= PMAC_BURGUNDY)
+               out_le32(&chip->awacs->control, chip->control_mask);
 
        /* Powerbooks have odd ways of enabling inputs such as
           an expansion-bay CD or sound from an internal modem
index 52e613e282ca3404dd3421480ec8d88f11417461..18f28ac4bfe82997733df97c1c1eaaf05dc41adb 100644 (file)
@@ -29,6 +29,7 @@ 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"
 
 # Supported codecs
index 148a84dde69ae8179b4699bbe84479ea35ebf46c..782db2127108fd26c19a0bb6bf2ee378cbd4d0ac 100644 (file)
@@ -1,4 +1,4 @@
 snd-soc-core-objs := soc-core.o soc-dapm.o
 
 obj-$(CONFIG_SND_SOC)  += snd-soc-core.o
-obj-$(CONFIG_SND_SOC)  += codecs/ at91/ pxa/ s3c24xx/ sh/ fsl/ omap/
+obj-$(CONFIG_SND_SOC)  += codecs/ at91/ pxa/ s3c24xx/ sh/ fsl/ davinci/ omap/
index 898a7d363284ad4f1f42f060daed8bfe08196106..3903ab7dfa4a78ea2e3eebcbf8526f832b5ebdc4 100644 (file)
@@ -18,6 +18,10 @@ config SND_SOC_WM9712
        tristate
        depends on SND_SOC
 
+config SND_SOC_WM9713
+       tristate
+       depends on SND_SOC
+
 # Cirrus Logic CS4270 Codec
 config SND_SOC_CS4270
        tristate
index c6e5338c2666938ea811b6ec44bd648ca200310f..4e1314c9d3ecc44bd8228d383a3d9688bcf9dc45 100644 (file)
@@ -3,6 +3,7 @@ snd-soc-wm8731-objs := wm8731.o
 snd-soc-wm8750-objs := wm8750.o
 snd-soc-wm8753-objs := wm8753.o
 snd-soc-wm9712-objs := wm9712.o
+snd-soc-wm9713-objs := wm9713.o
 snd-soc-cs4270-objs := cs4270.o
 snd-soc-tlv320aic3x-objs := tlv320aic3x.o
 
@@ -11,5 +12,6 @@ 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
 obj-$(CONFIG_SND_SOC_WM9712)   += snd-soc-wm9712.o
+obj-$(CONFIG_SND_SOC_WM9713)   += snd-soc-wm9713.o
 obj-$(CONFIG_SND_SOC_CS4270)   += snd-soc-cs4270.o
 obj-$(CONFIG_SND_SOC_TLV320AIC3X)      += snd-soc-tlv320aic3x.o
index 242130cf1abd2d0797f794f70d4937acefc159c6..2a1ffe39690887efcd9e5ea66628fca8e8d4d531 100644 (file)
@@ -40,7 +40,8 @@ static int ac97_prepare(struct snd_pcm_substream *substream)
 }
 
 #define STD_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
-               SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
+               SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 |\
+               SNDRV_PCM_RATE_48000)
 
 struct snd_soc_codec_dai ac97_dai = {
        .name = "AC97 HiFi",
@@ -86,7 +87,7 @@ static int ac97_soc_probe(struct platform_device *pdev)
        printk(KERN_INFO "AC97 SoC Audio Codec %s\n", AC97_VERSION);
 
        socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
-       if (socdev->codec == NULL)
+       if (!socdev->codec)
                return -ENOMEM;
        codec = socdev->codec;
        mutex_init(&codec->mutex);
@@ -102,17 +103,17 @@ static int ac97_soc_probe(struct platform_device *pdev)
 
        /* register pcms */
        ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
-       if(ret < 0)
+       if (ret < 0)
                goto err;
 
        /* add codec as bus device for standard ac97 */
        ret = snd_ac97_bus(codec->card, 0, &soc_ac97_ops, NULL, &ac97_bus);
-       if(ret < 0)
+       if (ret < 0)
                goto bus_err;
 
        memset(&ac97_template, 0, sizeof(struct snd_ac97_template));
        ret = snd_ac97_mixer(ac97_bus, &ac97_template, &codec->ac97);
-       if(ret < 0)
+       if (ret < 0)
                goto bus_err;
 
        ret = snd_soc_register_card(socdev);
@@ -135,7 +136,7 @@ static int ac97_soc_remove(struct platform_device *pdev)
        struct snd_soc_device *socdev = platform_get_drvdata(pdev);
        struct snd_soc_codec *codec = socdev->codec;
 
-       if(codec == NULL)
+       if (!codec)
                return 0;
 
        snd_soc_free_pcms(socdev);
@@ -145,11 +146,10 @@ static int ac97_soc_remove(struct platform_device *pdev)
        return 0;
 }
 
-struct snd_soc_codec_device soc_codec_dev_ac97= {
+struct snd_soc_codec_device soc_codec_dev_ac97 = {
        .probe =        ac97_soc_probe,
        .remove =       ac97_soc_remove,
 };
-
 EXPORT_SYMBOL_GPL(soc_codec_dev_ac97);
 
 MODULE_DESCRIPTION("Soc Generic AC97 driver");
index bf2ab72d49bf21488032258350b926b75ea000eb..e73fcfd9f5cd41638acbc8d3ad5e30f532fe829f 100644 (file)
@@ -372,7 +372,7 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream,
        struct snd_soc_device *socdev = rtd->socdev;
        struct snd_soc_codec *codec = socdev->codec;
        struct cs4270_private *cs4270 = codec->private_data;
-       unsigned int ret = 0;
+       int ret;
        unsigned int i;
        unsigned int rate;
        unsigned int ratio;
index 889a897d41ac3ed49a5baea9674fdf4d04fbb14b..630684f4a0bc5ec1c91741902d9b8d7d3bcc1fa9 100644 (file)
@@ -660,33 +660,53 @@ struct aic3x_rate_divs {
 /* AIC3X codec mclk clock divider coefficients */
 static const struct aic3x_rate_divs aic3x_divs[] = {
        /* 8k */
+       {12000000, 8000, 48000, 0xa, 16, 3840},
+       {19200000, 8000, 48000, 0xa, 10, 2400},
        {22579200, 8000, 48000, 0xa, 8, 7075},
        {33868800, 8000, 48000, 0xa, 5, 8049},
        /* 11.025k */
+       {12000000, 11025, 44100, 0x6, 15, 528},
+       {19200000, 11025, 44100, 0x6, 9, 4080},
        {22579200, 11025, 44100, 0x6, 8, 0},
        {33868800, 11025, 44100, 0x6, 5, 3333},
        /* 16k */
+       {12000000, 16000, 48000, 0x4, 16, 3840},
+       {19200000, 16000, 48000, 0x4, 10, 2400},
        {22579200, 16000, 48000, 0x4, 8, 7075},
        {33868800, 16000, 48000, 0x4, 5, 8049},
        /* 22.05k */
+       {12000000, 22050, 44100, 0x2, 15, 528},
+       {19200000, 22050, 44100, 0x2, 9, 4080},
        {22579200, 22050, 44100, 0x2, 8, 0},
        {33868800, 22050, 44100, 0x2, 5, 3333},
        /* 32k */
+       {12000000, 32000, 48000, 0x1, 16, 3840},
+       {19200000, 32000, 48000, 0x1, 10, 2400},
        {22579200, 32000, 48000, 0x1, 8, 7075},
        {33868800, 32000, 48000, 0x1, 5, 8049},
        /* 44.1k */
+       {12000000, 44100, 44100, 0x0, 15, 528},
+       {19200000, 44100, 44100, 0x0, 9, 4080},
        {22579200, 44100, 44100, 0x0, 8, 0},
        {33868800, 44100, 44100, 0x0, 5, 3333},
        /* 48k */
+       {12000000, 48000, 48000, 0x0, 16, 3840},
+       {19200000, 48000, 48000, 0x0, 10, 2400},
        {22579200, 48000, 48000, 0x0, 8, 7075},
        {33868800, 48000, 48000, 0x0, 5, 8049},
        /* 64k */
+       {12000000, 64000, 96000, 0x1, 16, 3840},
+       {19200000, 64000, 96000, 0x1, 10, 2400},
        {22579200, 64000, 96000, 0x1, 8, 7075},
        {33868800, 64000, 96000, 0x1, 5, 8049},
        /* 88.2k */
+       {12000000, 88200, 88200, 0x0, 15, 528},
+       {19200000, 88200, 88200, 0x0, 9, 4080},
        {22579200, 88200, 88200, 0x0, 8, 0},
        {33868800, 88200, 88200, 0x0, 5, 3333},
        /* 96k */
+       {12000000, 96000, 96000, 0x0, 16, 3840},
+       {19200000, 96000, 96000, 0x0, 10, 2400},
        {22579200, 96000, 96000, 0x0, 8, 7075},
        {33868800, 96000, 96000, 0x0, 5, 8049},
 };
@@ -807,6 +827,8 @@ static int aic3x_set_dai_sysclk(struct snd_soc_codec_dai *codec_dai,
        struct aic3x_priv *aic3x = codec->private_data;
 
        switch (freq) {
+       case 12000000:
+       case 19200000:
        case 22579200:
        case 33868800:
                aic3x->sysclk = freq;
index 9c33fe874928ec2ae746d112334a622e20d7dc14..0cf9265fca8fb54ef9c66d1704a896738b60d227 100644 (file)
@@ -110,7 +110,7 @@ static int wm8731_write(struct snd_soc_codec *codec, unsigned int reg,
        data[0] = (reg << 1) | ((value >> 8) & 0x0001);
        data[1] = value & 0x00ff;
 
-       wm8731_write_reg_cache (codec, reg, value);
+       wm8731_write_reg_cache(codec, reg, value);
        if (codec->hw_write(codec->control_data, data, 2) == 2)
                return 0;
        else
@@ -154,8 +154,10 @@ static int wm8731_add_controls(struct snd_soc_codec *codec)
        int err, i;
 
        for (i = 0; i < ARRAY_SIZE(wm8731_snd_controls); i++) {
-               if ((err = snd_ctl_add(codec->card,
-                               snd_soc_cnew(&wm8731_snd_controls[i],codec, NULL))) < 0)
+               err = snd_ctl_add(codec->card,
+                                 snd_soc_cnew(&wm8731_snd_controls[i],
+                                               codec, NULL));
+               if (err < 0)
                        return err;
        }
 
@@ -221,15 +223,13 @@ static int wm8731_add_widgets(struct snd_soc_codec *codec)
 {
        int i;
 
-       for(i = 0; i < ARRAY_SIZE(wm8731_dapm_widgets); i++) {
+       for (i = 0; i < ARRAY_SIZE(wm8731_dapm_widgets); i++)
                snd_soc_dapm_new_control(codec, &wm8731_dapm_widgets[i]);
-       }
 
        /* set up audio path interconnects */
-       for(i = 0; intercon[i][0] != NULL; i++) {
+       for (i = 0; intercon[i][0] != NULL; i++)
                snd_soc_dapm_connect_input(codec, intercon[i][0],
                        intercon[i][1], intercon[i][2]);
-       }
 
        snd_soc_dapm_new_widgets(codec);
        return 0;
@@ -589,7 +589,7 @@ pcm_err:
 
 static struct snd_soc_device *wm8731_socdev;
 
-#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 
 /*
  * WM8731 2 wire address is determined by GPIO5
@@ -651,7 +651,7 @@ err:
 
 static int wm8731_i2c_detach(struct i2c_client *client)
 {
-       struct snd_soc_codeccodec = i2c_get_clientdata(client);
+       struct snd_soc_codec *codec = i2c_get_clientdata(client);
        i2c_detach_client(client);
        kfree(codec->reg_cache);
        kfree(client);
@@ -709,7 +709,7 @@ static int wm8731_probe(struct platform_device *pdev)
        INIT_LIST_HEAD(&codec->dapm_paths);
 
        wm8731_socdev = socdev;
-#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
+#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;
@@ -734,7 +734,7 @@ static int wm8731_remove(struct platform_device *pdev)
 
        snd_soc_free_pcms(socdev);
        snd_soc_dapm_free(socdev);
-#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        i2c_del_driver(&wm8731_i2c_driver);
 #endif
        kfree(codec->private_data);
@@ -749,7 +749,6 @@ struct snd_soc_codec_device soc_codec_dev_wm8731 = {
        .suspend =      wm8731_suspend,
        .resume =       wm8731_resume,
 };
-
 EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731);
 
 MODULE_DESCRIPTION("ASoC WM8731 driver");
index 77a857b997a2288e28ca2bc993a446057112dbff..16cd5d4d5ad97108443d6bc1e51db727c282b5d4 100644 (file)
@@ -110,7 +110,7 @@ static int wm8750_write(struct snd_soc_codec *codec, unsigned int reg,
        data[0] = (reg << 1) | ((value >> 8) & 0x0001);
        data[1] = value & 0x00ff;
 
-       wm8750_write_reg_cache (codec, reg, value);
+       wm8750_write_reg_cache(codec, reg, value);
        if (codec->hw_write(codec->control_data, data, 2) == 2)
                return 0;
        else
@@ -257,7 +257,8 @@ static int wm8750_add_controls(struct snd_soc_codec *codec)
 
        for (i = 0; i < ARRAY_SIZE(wm8750_snd_controls); i++) {
                err = snd_ctl_add(codec->card,
-                               snd_soc_cnew(&wm8750_snd_controls[i],codec, NULL));
+                               snd_soc_cnew(&wm8750_snd_controls[i],
+                                               codec, NULL));
                if (err < 0)
                        return err;
        }
@@ -478,15 +479,13 @@ static int wm8750_add_widgets(struct snd_soc_codec *codec)
 {
        int i;
 
-       for(i = 0; i < ARRAY_SIZE(wm8750_dapm_widgets); i++) {
+       for (i = 0; i < ARRAY_SIZE(wm8750_dapm_widgets); i++)
                snd_soc_dapm_new_control(codec, &wm8750_dapm_widgets[i]);
-       }
 
        /* set up audio path audio_mapnects */
-       for(i = 0; audio_map[i][0] != NULL; i++) {
+       for (i = 0; audio_map[i][0] != NULL; i++)
                snd_soc_dapm_connect_input(codec, audio_map[i][0],
                        audio_map[i][1], audio_map[i][2]);
-       }
 
        snd_soc_dapm_new_widgets(codec);
        return 0;
@@ -714,8 +713,8 @@ static int wm8750_dapm_event(struct snd_soc_codec *codec, int event)
 }
 
 #define WM8750_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)
+       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 WM8750_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
        SNDRV_PCM_FMTBIT_S24_LE)
@@ -784,7 +783,8 @@ static int wm8750_resume(struct platform_device *pdev)
        if (codec->suspend_dapm_state == SNDRV_CTL_POWER_D0) {
                wm8750_dapm_event(codec, SNDRV_CTL_POWER_D2);
                codec->dapm_state = SNDRV_CTL_POWER_D0;
-               schedule_delayed_work(&codec->delayed_work, msecs_to_jiffies(1000));
+               schedule_delayed_work(&codec->delayed_work,
+                                       msecs_to_jiffies(1000));
        }
 
        return 0;
@@ -864,7 +864,7 @@ pcm_err:
    around */
 static struct snd_soc_device *wm8750_socdev;
 
-#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 
 /*
  * WM8731 2 wire address is determined by GPIO5
@@ -979,8 +979,8 @@ static int wm8750_probe(struct platform_device *pdev)
        INIT_LIST_HEAD(&codec->dapm_paths);
        wm8750_socdev = socdev;
        INIT_DELAYED_WORK(&codec->delayed_work, wm8750_work);
-       
-#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
+
+#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;
@@ -1025,7 +1025,7 @@ static int wm8750_remove(struct platform_device *pdev)
        run_delayed_work(&codec->delayed_work);
        snd_soc_free_pcms(socdev);
        snd_soc_dapm_free(socdev);
-#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        i2c_del_driver(&wm8750_i2c_driver);
 #endif
        kfree(codec->private_data);
@@ -1040,7 +1040,6 @@ struct snd_soc_codec_device soc_codec_dev_wm8750 = {
        .suspend =      wm8750_suspend,
        .resume =       wm8750_resume,
 };
-
 EXPORT_SYMBOL_GPL(soc_codec_dev_wm8750);
 
 MODULE_DESCRIPTION("ASoC WM8750 driver");
index ddd9c71b3fdec189b61a1cc31f872ef6223bee77..76a5c7b05dfbfdde7647d92af0f112816efb17f5 100644 (file)
@@ -198,6 +198,7 @@ static const char *wm8753_mic_sel[] = {"Mic 1", "Mic 2", "Mic 3"};
 static const char *wm8753_dai_mode[] = {"DAI 0", "DAI 1", "DAI 2", "DAI 3"};
 static const char *wm8753_dat_sel[] = {"Stereo", "Left ADC", "Right ADC",
        "Channel Swap"};
+static const char *wm8753_rout2_phase[] = {"Non Inverted", "Inverted"};
 
 static const struct soc_enum wm8753_enum[] = {
 SOC_ENUM_SINGLE(WM8753_BASS, 7, 2, wm8753_base),
@@ -228,6 +229,7 @@ SOC_ENUM_SINGLE(WM8753_ADC, 4, 2, wm8753_adc_filter),
 SOC_ENUM_SINGLE(WM8753_MICBIAS, 6, 3, wm8753_mic_sel),
 SOC_ENUM_SINGLE(WM8753_IOCTL, 2, 4, wm8753_dai_mode),
 SOC_ENUM_SINGLE(WM8753_ADC, 7, 4, wm8753_dat_sel),
+SOC_ENUM_SINGLE(WM8753_OUTCTL, 2, 2, wm8753_rout2_phase),
 };
 
 
@@ -279,7 +281,7 @@ SOC_DOUBLE_R("Speaker Playback ZC Switch", WM8753_LOUT2V, WM8753_ROUT2V, 7, 1, 0
 
 SOC_SINGLE("Mono Bypass Playback Volume", WM8753_MOUTM1, 4, 7, 1),
 SOC_SINGLE("Mono Sidetone Playback Volume", WM8753_MOUTM2, 4, 7, 1),
-SOC_SINGLE("Mono Voice Playback Volume", WM8753_MOUTM2, 4, 7, 1),
+SOC_SINGLE("Mono Voice Playback Volume", WM8753_MOUTM2, 0, 7, 1),
 SOC_SINGLE("Mono Playback ZC Switch", WM8753_MOUTV, 7, 1, 0),
 
 SOC_ENUM("Bass Boost", wm8753_enum[0]),
@@ -330,6 +332,7 @@ SOC_SINGLE("Mic1 Capture Volume", WM8753_INCTL1, 5, 3, 0),
 SOC_ENUM_EXT("DAI Mode", wm8753_enum[26], wm8753_get_dai, wm8753_set_dai),
 
 SOC_ENUM("ADC Data Select", wm8753_enum[27]),
+SOC_ENUM("ROUT2 Phase", wm8753_enum[28]),
 };
 
 /* add non dapm controls */
index 524f7450804f07cc506547618c17bdff96c925e6..d2d79e182a45b1bc44c79e6278043a0ae147a9cf 100644 (file)
@@ -581,22 +581,14 @@ static int wm9712_dapm_event(struct snd_soc_codec *codec, int event)
 
        switch (event) {
        case SNDRV_CTL_POWER_D0: /* full On */
-               /* liam - maybe enable thermal shutdown */
-               reg = ac97_read(codec, AC97_EXTENDED_MID) & 0xdfff;
-               ac97_write(codec, AC97_EXTENDED_MID, reg);
-               break;
        case SNDRV_CTL_POWER_D1: /* partial On */
        case SNDRV_CTL_POWER_D2: /* partial On */
                break;
        case SNDRV_CTL_POWER_D3hot: /* Off, with power */
-               /* enable master bias and vmid */
-               reg = ac97_read(codec, AC97_EXTENDED_MID) & 0xbbff;
-               ac97_write(codec, AC97_EXTENDED_MID, reg);
                ac97_write(codec, AC97_POWERDOWN, 0x0000);
                break;
        case SNDRV_CTL_POWER_D3cold: /* Off, without power */
                /* disable everything including AC link */
-               ac97_write(codec, AC97_EXTENDED_MID, 0xffff);
                ac97_write(codec, AC97_EXTENDED_MSTATUS, 0xffff);
                ac97_write(codec, AC97_POWERDOWN, 0xffff);
                break;
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
new file mode 100644 (file)
index 0000000..1f24116
--- /dev/null
@@ -0,0 +1,1300 @@
+/*
+ * wm9713.c  --  ALSA Soc WM9713 codec support
+ *
+ * Copyright 2006 Wolfson Microelectronics PLC.
+ * Author: Liam Girdwood
+ *         liam.girdwood@wolfsonmicro.com or 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.
+ *
+ *  Revision history
+ *    4th Feb 2006   Initial version.
+ *
+ *  Features:-
+ *
+ *   o Support for AC97 Codec, Voice DAC and Aux DAC
+ *   o Support for DAPM
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/ac97_codec.h>
+#include <sound/initval.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include "wm9713.h"
+
+#define WM9713_VERSION "0.15"
+
+struct wm9713_priv {
+       u32 pll_in; /* PLL input frequency */
+       u32 pll_out; /* PLL output frequency */
+};
+
+static unsigned int ac97_read(struct snd_soc_codec *codec,
+       unsigned int reg);
+static int ac97_write(struct snd_soc_codec *codec,
+       unsigned int reg, unsigned int val);
+
+/*
+ * WM9713 register cache
+ * Reg 0x3c bit 15 is used by touch driver.
+ */
+static const u16 wm9713_reg[] = {
+       0x6174, 0x8080, 0x8080, 0x8080,
+       0xc880, 0xe808, 0xe808, 0x0808,
+       0x00da, 0x8000, 0xd600, 0xaaa0,
+       0xaaa0, 0xaaa0, 0x0000, 0x0000,
+       0x0f0f, 0x0040, 0x0000, 0x7f00,
+       0x0405, 0x0410, 0xbb80, 0xbb80,
+       0x0000, 0xbb80, 0x0000, 0x4523,
+       0x0000, 0x2000, 0x7eff, 0xffff,
+       0x0000, 0x0000, 0x0080, 0x0000,
+       0x0000, 0x0000, 0xfffe, 0xffff,
+       0x0000, 0x0000, 0x0000, 0xfffe,
+       0x4000, 0x0000, 0x0000, 0x0000,
+       0xb032, 0x3e00, 0x0000, 0x0000,
+       0x0000, 0x0000, 0x0000, 0x0000,
+       0x0000, 0x0000, 0x0000, 0x0006,
+       0x0001, 0x0000, 0x574d, 0x4c13,
+       0x0000, 0x0000, 0x0000
+};
+
+/* virtual HP mixers regs */
+#define HPL_MIXER      0x80
+#define HPR_MIXER      0x82
+#define MICB_MUX       0x82
+
+static const char *wm9713_mic_mixer[] = {"Stereo", "Mic 1", "Mic 2", "Mute"};
+static const char *wm9713_rec_mux[] = {"Stereo", "Left", "Right", "Mute"};
+static const char *wm9713_rec_src[] =
+       {"Mic 1", "Mic 2", "Line", "Mono In", "Headphone", "Speaker",
+       "Mono Out", "Zh"};
+static const char *wm9713_rec_gain[] = {"+1.5dB Steps", "+0.75dB Steps"};
+static const char *wm9713_alc_select[] = {"None", "Left", "Right", "Stereo"};
+static const char *wm9713_mono_pga[] = {"Vmid", "Zh", "Mono", "Inv",
+       "Mono Vmid", "Inv Vmid"};
+static const char *wm9713_spk_pga[] =
+       {"Vmid", "Zh", "Headphone", "Speaker", "Inv", "Headphone Vmid",
+       "Speaker Vmid", "Inv Vmid"};
+static const char *wm9713_hp_pga[] = {"Vmid", "Zh", "Headphone",
+       "Headphone Vmid"};
+static const char *wm9713_out3_pga[] = {"Vmid", "Zh", "Inv 1", "Inv 1 Vmid"};
+static const char *wm9713_out4_pga[] = {"Vmid", "Zh", "Inv 2", "Inv 2 Vmid"};
+static const char *wm9713_dac_inv[] =
+       {"Off", "Mono", "Speaker", "Left Headphone", "Right Headphone",
+       "Headphone Mono", "NC", "Vmid"};
+static const char *wm9713_bass[] = {"Linear Control", "Adaptive Boost"};
+static const char *wm9713_ng_type[] = {"Constant Gain", "Mute"};
+static const char *wm9713_mic_select[] = {"Mic 1", "Mic 2 A", "Mic 2 B"};
+static const char *wm9713_micb_select[] = {"MPB", "MPA"};
+
+static const struct soc_enum wm9713_enum[] = {
+SOC_ENUM_SINGLE(AC97_LINE, 3, 4, wm9713_mic_mixer), /* record mic mixer 0 */
+SOC_ENUM_SINGLE(AC97_VIDEO, 14, 4, wm9713_rec_mux), /* record mux hp 1 */
+SOC_ENUM_SINGLE(AC97_VIDEO, 9, 4, wm9713_rec_mux),  /* record mux mono 2 */
+SOC_ENUM_SINGLE(AC97_VIDEO, 3, 8, wm9713_rec_src),  /* record mux left 3 */
+SOC_ENUM_SINGLE(AC97_VIDEO, 0, 8, wm9713_rec_src),  /* record mux right 4*/
+SOC_ENUM_DOUBLE(AC97_CD, 14, 6, 2, wm9713_rec_gain), /* record step size 5 */
+SOC_ENUM_SINGLE(AC97_PCI_SVID, 14, 4, wm9713_alc_select), /* alc source select 6*/
+SOC_ENUM_SINGLE(AC97_REC_GAIN, 14, 4, wm9713_mono_pga), /* mono input select 7 */
+SOC_ENUM_SINGLE(AC97_REC_GAIN, 11, 8, wm9713_spk_pga), /* speaker left input select 8 */
+SOC_ENUM_SINGLE(AC97_REC_GAIN, 8, 8, wm9713_spk_pga), /* speaker right input select 9 */
+SOC_ENUM_SINGLE(AC97_REC_GAIN, 6, 3, wm9713_hp_pga), /* headphone left input 10 */
+SOC_ENUM_SINGLE(AC97_REC_GAIN, 4, 3, wm9713_hp_pga), /* headphone right input 11 */
+SOC_ENUM_SINGLE(AC97_REC_GAIN, 2, 4, wm9713_out3_pga), /* out 3 source 12 */
+SOC_ENUM_SINGLE(AC97_REC_GAIN, 0, 4, wm9713_out4_pga), /* out 4 source 13 */
+SOC_ENUM_SINGLE(AC97_REC_GAIN_MIC, 13, 8, wm9713_dac_inv), /* dac invert 1 14 */
+SOC_ENUM_SINGLE(AC97_REC_GAIN_MIC, 10, 8, wm9713_dac_inv), /* dac invert 2 15 */
+SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 15, 2, wm9713_bass), /* bass control 16 */
+SOC_ENUM_SINGLE(AC97_PCI_SVID, 5, 2, wm9713_ng_type), /* noise gate type 17 */
+SOC_ENUM_SINGLE(AC97_3D_CONTROL, 12, 3, wm9713_mic_select), /* mic selection 18 */
+SOC_ENUM_SINGLE(MICB_MUX, 0, 2, wm9713_micb_select), /* mic selection 19 */
+};
+
+static const struct snd_kcontrol_new wm9713_snd_ac97_controls[] = {
+SOC_DOUBLE("Speaker Playback Volume", AC97_MASTER, 8, 0, 31, 1),
+SOC_DOUBLE("Speaker Playback Switch", AC97_MASTER, 15, 7, 1, 1),
+SOC_DOUBLE("Headphone Playback Volume", AC97_HEADPHONE, 8, 0, 31, 1),
+SOC_DOUBLE("Headphone Playback Switch", AC97_HEADPHONE, 15, 7, 1, 1),
+SOC_DOUBLE("Line In Volume", AC97_PC_BEEP, 8, 0, 31, 1),
+SOC_DOUBLE("PCM Playback Volume", AC97_PHONE, 8, 0, 31, 1),
+SOC_SINGLE("Mic 1 Volume", AC97_MIC, 8, 31, 1),
+SOC_SINGLE("Mic 2 Volume", AC97_MIC, 0, 31, 1),
+
+SOC_SINGLE("Mic Boost (+20dB) Switch", AC97_LINE, 5, 1, 0),
+SOC_SINGLE("Mic Headphone Mixer Volume", AC97_LINE, 0, 7, 1),
+
+SOC_SINGLE("Capture Switch", AC97_CD, 15, 1, 1),
+SOC_ENUM("Capture Volume Steps", wm9713_enum[5]),
+SOC_DOUBLE("Capture Volume", AC97_CD, 8, 0, 31, 0),
+SOC_SINGLE("Capture ZC Switch", AC97_CD, 7, 1, 0),
+
+SOC_SINGLE("Capture to Headphone Volume", AC97_VIDEO, 11, 7, 1),
+SOC_SINGLE("Capture to Mono Boost (+20dB) Switch", AC97_VIDEO, 8, 1, 0),
+SOC_SINGLE("Capture ADC Boost (+20dB) Switch", AC97_VIDEO, 6, 1, 0),
+
+SOC_SINGLE("ALC Target Volume", AC97_CODEC_CLASS_REV, 12, 15, 0),
+SOC_SINGLE("ALC Hold Time", AC97_CODEC_CLASS_REV, 8, 15, 0),
+SOC_SINGLE("ALC Decay Time ", AC97_CODEC_CLASS_REV, 4, 15, 0),
+SOC_SINGLE("ALC Attack Time", AC97_CODEC_CLASS_REV, 0, 15, 0),
+SOC_ENUM("ALC Function", wm9713_enum[6]),
+SOC_SINGLE("ALC Max Volume", AC97_PCI_SVID, 11, 7, 0),
+SOC_SINGLE("ALC ZC Timeout", AC97_PCI_SVID, 9, 3, 0),
+SOC_SINGLE("ALC ZC Switch", AC97_PCI_SVID, 8, 1, 0),
+SOC_SINGLE("ALC NG Switch", AC97_PCI_SVID, 7, 1, 0),
+SOC_ENUM("ALC NG Type", wm9713_enum[17]),
+SOC_SINGLE("ALC NG Threshold", AC97_PCI_SVID, 0, 31, 0),
+
+SOC_DOUBLE("Speaker Playback ZC Switch", AC97_MASTER, 14, 6, 1, 0),
+SOC_DOUBLE("Headphone Playback ZC Switch", AC97_HEADPHONE, 14, 6, 1, 0),
+
+SOC_SINGLE("Out4 Playback Switch", AC97_MASTER_MONO, 15, 1, 1),
+SOC_SINGLE("Out4 Playback ZC Switch", AC97_MASTER_MONO, 14, 1, 0),
+SOC_SINGLE("Out4 Playback Volume", AC97_MASTER_MONO, 8, 63, 1),
+
+SOC_SINGLE("Out3 Playback Switch", AC97_MASTER_MONO, 7, 1, 1),
+SOC_SINGLE("Out3 Playback ZC Switch", AC97_MASTER_MONO, 6, 1, 0),
+SOC_SINGLE("Out3 Playback Volume", AC97_MASTER_MONO, 0, 63, 1),
+
+SOC_SINGLE("Mono Capture Volume", AC97_MASTER_TONE, 8, 31, 1),
+SOC_SINGLE("Mono Playback Switch", AC97_MASTER_TONE, 7, 1, 1),
+SOC_SINGLE("Mono Playback ZC Switch", AC97_MASTER_TONE, 6, 1, 0),
+SOC_SINGLE("Mono Playback Volume", AC97_MASTER_TONE, 0, 31, 1),
+
+SOC_SINGLE("PC Beep Playback Headphone Volume", AC97_AUX, 12, 7, 1),
+SOC_SINGLE("PC Beep Playback Speaker Volume", AC97_AUX, 8, 7, 1),
+SOC_SINGLE("PC Beep Playback Mono Volume", AC97_AUX, 4, 7, 1),
+
+SOC_SINGLE("Voice Playback Headphone Volume", AC97_PCM, 12, 7, 1),
+SOC_SINGLE("Voice Playback Master Volume", AC97_PCM, 8, 7, 1),
+SOC_SINGLE("Voice Playback Mono Volume", AC97_PCM, 4, 7, 1),
+
+SOC_SINGLE("Aux Playback Headphone Volume", AC97_REC_SEL, 12, 7, 1),
+SOC_SINGLE("Aux Playback Master Volume", AC97_REC_SEL, 8, 7, 1),
+SOC_SINGLE("Aux Playback Mono Volume", AC97_REC_SEL, 4, 7, 1),
+
+SOC_ENUM("Bass Control", wm9713_enum[16]),
+SOC_SINGLE("Bass Cut-off Switch", AC97_GENERAL_PURPOSE, 12, 1, 1),
+SOC_SINGLE("Tone Cut-off Switch", AC97_GENERAL_PURPOSE, 4, 1, 1),
+SOC_SINGLE("Playback Attenuate (-6dB) Switch", AC97_GENERAL_PURPOSE, 6, 1, 0),
+SOC_SINGLE("Bass Volume", AC97_GENERAL_PURPOSE, 8, 15, 1),
+SOC_SINGLE("Tone Volume", AC97_GENERAL_PURPOSE, 0, 15, 1),
+
+SOC_SINGLE("3D Upper Cut-off Switch", AC97_REC_GAIN_MIC, 5, 1, 0),
+SOC_SINGLE("3D Lower Cut-off Switch", AC97_REC_GAIN_MIC, 4, 1, 0),
+SOC_SINGLE("3D Depth", AC97_REC_GAIN_MIC, 0, 15, 1),
+};
+
+/* add non dapm controls */
+static int wm9713_add_controls(struct snd_soc_codec *codec)
+{
+       int err, i;
+
+       for (i = 0; i < ARRAY_SIZE(wm9713_snd_ac97_controls); i++) {
+               err = snd_ctl_add(codec->card,
+                               snd_soc_cnew(&wm9713_snd_ac97_controls[i],
+                                       codec, NULL));
+               if (err < 0)
+                       return err;
+       }
+       return 0;
+}
+
+/* We have to create a fake left and right HP mixers because
+ * the codec only has a single control that is shared by both channels.
+ * This makes it impossible to determine the audio path using the current
+ * register map, thus we add a new (virtual) register to help determine the
+ * audio route within the device.
+ */
+static int mixer_event(struct snd_soc_dapm_widget *w,
+       struct snd_kcontrol *kcontrol, int event)
+{
+       u16 l, r, beep, tone, phone, rec, pcm, aux;
+
+       l = ac97_read(w->codec, HPL_MIXER);
+       r = ac97_read(w->codec, HPR_MIXER);
+       beep = ac97_read(w->codec, AC97_PC_BEEP);
+       tone = ac97_read(w->codec, AC97_MASTER_TONE);
+       phone = ac97_read(w->codec, AC97_PHONE);
+       rec = ac97_read(w->codec, AC97_REC_SEL);
+       pcm = ac97_read(w->codec, AC97_PCM);
+       aux = ac97_read(w->codec, AC97_AUX);
+
+       if (event & SND_SOC_DAPM_PRE_REG)
+               return 0;
+       if ((l & 0x1) || (r & 0x1))
+               ac97_write(w->codec, AC97_PC_BEEP, beep & 0x7fff);
+       else
+               ac97_write(w->codec, AC97_PC_BEEP, beep | 0x8000);
+
+       if ((l & 0x2) || (r & 0x2))
+               ac97_write(w->codec, AC97_MASTER_TONE, tone & 0x7fff);
+       else
+               ac97_write(w->codec, AC97_MASTER_TONE, tone | 0x8000);
+
+       if ((l & 0x4) || (r & 0x4))
+               ac97_write(w->codec, AC97_PHONE, phone & 0x7fff);
+       else
+               ac97_write(w->codec, AC97_PHONE, phone | 0x8000);
+
+       if ((l & 0x8) || (r & 0x8))
+               ac97_write(w->codec, AC97_REC_SEL, rec & 0x7fff);
+       else
+               ac97_write(w->codec, AC97_REC_SEL, rec | 0x8000);
+
+       if ((l & 0x10) || (r & 0x10))
+               ac97_write(w->codec, AC97_PCM, pcm & 0x7fff);
+       else
+               ac97_write(w->codec, AC97_PCM, pcm | 0x8000);
+
+       if ((l & 0x20) || (r & 0x20))
+               ac97_write(w->codec, AC97_AUX, aux & 0x7fff);
+       else
+               ac97_write(w->codec, AC97_AUX, aux | 0x8000);
+
+       return 0;
+}
+
+/* Left Headphone Mixers */
+static const struct snd_kcontrol_new wm9713_hpl_mixer_controls[] = {
+SOC_DAPM_SINGLE("PC Beep Playback Switch", HPL_MIXER, 5, 1, 0),
+SOC_DAPM_SINGLE("Voice Playback Switch", HPL_MIXER, 4, 1, 0),
+SOC_DAPM_SINGLE("Aux Playback Switch", HPL_MIXER, 3, 1, 0),
+SOC_DAPM_SINGLE("PCM Playback Switch", HPL_MIXER, 2, 1, 0),
+SOC_DAPM_SINGLE("MonoIn Playback Switch", HPL_MIXER, 1, 1, 0),
+SOC_DAPM_SINGLE("Bypass Playback Switch", HPL_MIXER, 0, 1, 0),
+};
+
+/* Right Headphone Mixers */
+static const struct snd_kcontrol_new wm9713_hpr_mixer_controls[] = {
+SOC_DAPM_SINGLE("PC Beep Playback Switch", HPR_MIXER, 5, 1, 0),
+SOC_DAPM_SINGLE("Voice Playback Switch", HPR_MIXER, 4, 1, 0),
+SOC_DAPM_SINGLE("Aux Playback Switch", HPR_MIXER, 3, 1, 0),
+SOC_DAPM_SINGLE("PCM Playback Switch", HPR_MIXER, 2, 1, 0),
+SOC_DAPM_SINGLE("MonoIn Playback Switch", HPR_MIXER, 1, 1, 0),
+SOC_DAPM_SINGLE("Bypass Playback Switch", HPR_MIXER, 0, 1, 0),
+};
+
+/* headphone capture mux */
+static const struct snd_kcontrol_new wm9713_hp_rec_mux_controls =
+SOC_DAPM_ENUM("Route", wm9713_enum[1]);
+
+/* headphone mic mux */
+static const struct snd_kcontrol_new wm9713_hp_mic_mux_controls =
+SOC_DAPM_ENUM("Route", wm9713_enum[0]);
+
+/* Speaker Mixer */
+static const struct snd_kcontrol_new wm9713_speaker_mixer_controls[] = {
+SOC_DAPM_SINGLE("PC Beep Playback Switch", AC97_AUX, 11, 1, 1),
+SOC_DAPM_SINGLE("Voice Playback Switch", AC97_PCM, 11, 1, 1),
+SOC_DAPM_SINGLE("Aux Playback Switch", AC97_REC_SEL, 11, 1, 1),
+SOC_DAPM_SINGLE("PCM Playback Switch", AC97_PHONE, 14, 1, 1),
+SOC_DAPM_SINGLE("MonoIn Playback Switch", AC97_MASTER_TONE, 14, 1, 1),
+SOC_DAPM_SINGLE("Bypass Playback Switch", AC97_PC_BEEP, 14, 1, 1),
+};
+
+/* Mono Mixer */
+static const struct snd_kcontrol_new wm9713_mono_mixer_controls[] = {
+SOC_DAPM_SINGLE("PC Beep Playback Switch", AC97_AUX, 7, 1, 1),
+SOC_DAPM_SINGLE("Voice Playback Switch", AC97_PCM, 7, 1, 1),
+SOC_DAPM_SINGLE("Aux Playback Switch", AC97_REC_SEL, 7, 1, 1),
+SOC_DAPM_SINGLE("PCM Playback Switch", AC97_PHONE, 13, 1, 1),
+SOC_DAPM_SINGLE("MonoIn Playback Switch", AC97_MASTER_TONE, 13, 1, 1),
+SOC_DAPM_SINGLE("Bypass Playback Switch", AC97_PC_BEEP, 13, 1, 1),
+SOC_DAPM_SINGLE("Mic 1 Sidetone Switch", AC97_LINE, 7, 1, 1),
+SOC_DAPM_SINGLE("Mic 2 Sidetone Switch", AC97_LINE, 6, 1, 1),
+};
+
+/* mono mic mux */
+static const struct snd_kcontrol_new wm9713_mono_mic_mux_controls =
+SOC_DAPM_ENUM("Route", wm9713_enum[2]);
+
+/* mono output mux */
+static const struct snd_kcontrol_new wm9713_mono_mux_controls =
+SOC_DAPM_ENUM("Route", wm9713_enum[7]);
+
+/* speaker left output mux */
+static const struct snd_kcontrol_new wm9713_hp_spkl_mux_controls =
+SOC_DAPM_ENUM("Route", wm9713_enum[8]);
+
+/* speaker right output mux */
+static const struct snd_kcontrol_new wm9713_hp_spkr_mux_controls =
+SOC_DAPM_ENUM("Route", wm9713_enum[9]);
+
+/* headphone left output mux */
+static const struct snd_kcontrol_new wm9713_hpl_out_mux_controls =
+SOC_DAPM_ENUM("Route", wm9713_enum[10]);
+
+/* headphone right output mux */
+static const struct snd_kcontrol_new wm9713_hpr_out_mux_controls =
+SOC_DAPM_ENUM("Route", wm9713_enum[11]);
+
+/* Out3 mux */
+static const struct snd_kcontrol_new wm9713_out3_mux_controls =
+SOC_DAPM_ENUM("Route", wm9713_enum[12]);
+
+/* Out4 mux */
+static const struct snd_kcontrol_new wm9713_out4_mux_controls =
+SOC_DAPM_ENUM("Route", wm9713_enum[13]);
+
+/* DAC inv mux 1 */
+static const struct snd_kcontrol_new wm9713_dac_inv1_mux_controls =
+SOC_DAPM_ENUM("Route", wm9713_enum[14]);
+
+/* DAC inv mux 2 */
+static const struct snd_kcontrol_new wm9713_dac_inv2_mux_controls =
+SOC_DAPM_ENUM("Route", wm9713_enum[15]);
+
+/* Capture source left */
+static const struct snd_kcontrol_new wm9713_rec_srcl_mux_controls =
+SOC_DAPM_ENUM("Route", wm9713_enum[3]);
+
+/* Capture source right */
+static const struct snd_kcontrol_new wm9713_rec_srcr_mux_controls =
+SOC_DAPM_ENUM("Route", wm9713_enum[4]);
+
+/* mic source */
+static const struct snd_kcontrol_new wm9713_mic_sel_mux_controls =
+SOC_DAPM_ENUM("Route", wm9713_enum[18]);
+
+/* mic source B virtual control */
+static const struct snd_kcontrol_new wm9713_micb_sel_mux_controls =
+SOC_DAPM_ENUM("Route", wm9713_enum[19]);
+
+static const struct snd_soc_dapm_widget wm9713_dapm_widgets[] = {
+SND_SOC_DAPM_MUX("Capture Headphone Mux", SND_SOC_NOPM, 0, 0,
+       &wm9713_hp_rec_mux_controls),
+SND_SOC_DAPM_MUX("Sidetone Mux", SND_SOC_NOPM, 0, 0,
+       &wm9713_hp_mic_mux_controls),
+SND_SOC_DAPM_MUX("Capture Mono Mux", SND_SOC_NOPM, 0, 0,
+       &wm9713_mono_mic_mux_controls),
+SND_SOC_DAPM_MUX("Mono Out Mux", SND_SOC_NOPM, 0, 0,
+       &wm9713_mono_mux_controls),
+SND_SOC_DAPM_MUX("Left Speaker Out Mux", SND_SOC_NOPM, 0, 0,
+       &wm9713_hp_spkl_mux_controls),
+SND_SOC_DAPM_MUX("Right Speaker Out Mux", SND_SOC_NOPM, 0, 0,
+       &wm9713_hp_spkr_mux_controls),
+SND_SOC_DAPM_MUX("Left Headphone Out Mux", SND_SOC_NOPM, 0, 0,
+       &wm9713_hpl_out_mux_controls),
+SND_SOC_DAPM_MUX("Right Headphone Out Mux", SND_SOC_NOPM, 0, 0,
+       &wm9713_hpr_out_mux_controls),
+SND_SOC_DAPM_MUX("Out 3 Mux", SND_SOC_NOPM, 0, 0,
+       &wm9713_out3_mux_controls),
+SND_SOC_DAPM_MUX("Out 4 Mux", SND_SOC_NOPM, 0, 0,
+       &wm9713_out4_mux_controls),
+SND_SOC_DAPM_MUX("DAC Inv Mux 1", SND_SOC_NOPM, 0, 0,
+       &wm9713_dac_inv1_mux_controls),
+SND_SOC_DAPM_MUX("DAC Inv Mux 2", SND_SOC_NOPM, 0, 0,
+       &wm9713_dac_inv2_mux_controls),
+SND_SOC_DAPM_MUX("Left Capture Source", SND_SOC_NOPM, 0, 0,
+       &wm9713_rec_srcl_mux_controls),
+SND_SOC_DAPM_MUX("Right Capture Source", SND_SOC_NOPM, 0, 0,
+       &wm9713_rec_srcr_mux_controls),
+SND_SOC_DAPM_MUX("Mic A Source", SND_SOC_NOPM, 0, 0,
+       &wm9713_mic_sel_mux_controls),
+SND_SOC_DAPM_MUX("Mic B Source", SND_SOC_NOPM, 0, 0,
+       &wm9713_micb_sel_mux_controls),
+SND_SOC_DAPM_MIXER_E("Left HP Mixer", AC97_EXTENDED_MID, 3, 1,
+       &wm9713_hpl_mixer_controls[0], ARRAY_SIZE(wm9713_hpl_mixer_controls),
+       mixer_event, SND_SOC_DAPM_POST_REG),
+SND_SOC_DAPM_MIXER_E("Right HP Mixer", AC97_EXTENDED_MID, 2, 1,
+       &wm9713_hpr_mixer_controls[0], ARRAY_SIZE(wm9713_hpr_mixer_controls),
+       mixer_event, SND_SOC_DAPM_POST_REG),
+SND_SOC_DAPM_MIXER("Mono Mixer", AC97_EXTENDED_MID, 0, 1,
+       &wm9713_mono_mixer_controls[0], ARRAY_SIZE(wm9713_mono_mixer_controls)),
+SND_SOC_DAPM_MIXER("Speaker Mixer", AC97_EXTENDED_MID, 1, 1,
+       &wm9713_speaker_mixer_controls[0],
+       ARRAY_SIZE(wm9713_speaker_mixer_controls)),
+SND_SOC_DAPM_DAC("Left DAC", "Left HiFi Playback", AC97_EXTENDED_MID, 7, 1),
+SND_SOC_DAPM_DAC("Right DAC", "Right HiFi Playback", AC97_EXTENDED_MID, 6, 1),
+SND_SOC_DAPM_MIXER("AC97 Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+SND_SOC_DAPM_MIXER("HP Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+SND_SOC_DAPM_MIXER("Line Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+SND_SOC_DAPM_MIXER("Capture Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+SND_SOC_DAPM_DAC("Voice DAC", "Voice Playback", AC97_EXTENDED_MID, 12, 1),
+SND_SOC_DAPM_DAC("Aux DAC", "Aux Playback", AC97_EXTENDED_MID, 11, 1),
+SND_SOC_DAPM_ADC("Left ADC", "Left HiFi Capture", AC97_EXTENDED_MID, 5, 1),
+SND_SOC_DAPM_ADC("Right ADC", "Right HiFi Capture", AC97_EXTENDED_MID, 4, 1),
+SND_SOC_DAPM_PGA("Left Headphone", AC97_EXTENDED_MSTATUS, 10, 1, NULL, 0),
+SND_SOC_DAPM_PGA("Right Headphone", AC97_EXTENDED_MSTATUS, 9, 1, NULL, 0),
+SND_SOC_DAPM_PGA("Left Speaker", AC97_EXTENDED_MSTATUS, 8, 1, NULL, 0),
+SND_SOC_DAPM_PGA("Right Speaker", AC97_EXTENDED_MSTATUS, 7, 1, NULL, 0),
+SND_SOC_DAPM_PGA("Out 3", AC97_EXTENDED_MSTATUS, 11, 1, NULL, 0),
+SND_SOC_DAPM_PGA("Out 4", AC97_EXTENDED_MSTATUS, 12, 1, NULL, 0),
+SND_SOC_DAPM_PGA("Mono Out", AC97_EXTENDED_MSTATUS, 13, 1, NULL, 0),
+SND_SOC_DAPM_PGA("Left Line In", AC97_EXTENDED_MSTATUS, 6, 1, NULL, 0),
+SND_SOC_DAPM_PGA("Right Line In", AC97_EXTENDED_MSTATUS, 5, 1, NULL, 0),
+SND_SOC_DAPM_PGA("Mono In", AC97_EXTENDED_MSTATUS, 4, 1, NULL, 0),
+SND_SOC_DAPM_PGA("Mic A PGA", AC97_EXTENDED_MSTATUS, 3, 1, NULL, 0),
+SND_SOC_DAPM_PGA("Mic B PGA", AC97_EXTENDED_MSTATUS, 2, 1, NULL, 0),
+SND_SOC_DAPM_PGA("Mic A Pre Amp", AC97_EXTENDED_MSTATUS, 1, 1, NULL, 0),
+SND_SOC_DAPM_PGA("Mic B Pre Amp", AC97_EXTENDED_MSTATUS, 0, 1, NULL, 0),
+SND_SOC_DAPM_MICBIAS("Mic Bias", AC97_EXTENDED_MSTATUS, 14, 1),
+SND_SOC_DAPM_OUTPUT("MONO"),
+SND_SOC_DAPM_OUTPUT("HPL"),
+SND_SOC_DAPM_OUTPUT("HPR"),
+SND_SOC_DAPM_OUTPUT("SPKL"),
+SND_SOC_DAPM_OUTPUT("SPKR"),
+SND_SOC_DAPM_OUTPUT("OUT3"),
+SND_SOC_DAPM_OUTPUT("OUT4"),
+SND_SOC_DAPM_INPUT("LINEL"),
+SND_SOC_DAPM_INPUT("LINER"),
+SND_SOC_DAPM_INPUT("MONOIN"),
+SND_SOC_DAPM_INPUT("PCBEEP"),
+SND_SOC_DAPM_INPUT("MIC1"),
+SND_SOC_DAPM_INPUT("MIC2A"),
+SND_SOC_DAPM_INPUT("MIC2B"),
+SND_SOC_DAPM_VMID("VMID"),
+};
+
+static const char *audio_map[][3] = {
+       /* left HP mixer */
+       {"Left HP Mixer", "PC Beep Playback Switch", "PCBEEP"},
+       {"Left HP Mixer", "Voice Playback Switch",   "Voice DAC"},
+       {"Left HP Mixer", "Aux Playback Switch",     "Aux DAC"},
+       {"Left HP Mixer", "Bypass Playback Switch",  "Left Line In"},
+       {"Left HP Mixer", "PCM Playback Switch",     "Left DAC"},
+       {"Left HP Mixer", "MonoIn Playback Switch",  "Mono In"},
+       {"Left HP Mixer", NULL,  "Capture Headphone Mux"},
+
+       /* right HP mixer */
+       {"Right HP Mixer", "PC Beep Playback Switch", "PCBEEP"},
+       {"Right HP Mixer", "Voice Playback Switch",   "Voice DAC"},
+       {"Right HP Mixer", "Aux Playback Switch",     "Aux DAC"},
+       {"Right HP Mixer", "Bypass Playback Switch",  "Right Line In"},
+       {"Right HP Mixer", "PCM Playback Switch",     "Right DAC"},
+       {"Right HP Mixer", "MonoIn Playback Switch",  "Mono In"},
+       {"Right HP Mixer", NULL,  "Capture Headphone Mux"},
+
+       /* virtual mixer - mixes left & right channels for spk and mono */
+       {"AC97 Mixer", NULL, "Left DAC"},
+       {"AC97 Mixer", NULL, "Right DAC"},
+       {"Line Mixer", NULL, "Right Line In"},
+       {"Line Mixer", NULL, "Left Line In"},
+       {"HP Mixer", NULL, "Left HP Mixer"},
+       {"HP Mixer", NULL, "Right HP Mixer"},
+       {"Capture Mixer", NULL, "Left Capture Source"},
+       {"Capture Mixer", NULL, "Right Capture Source"},
+
+       /* speaker mixer */
+       {"Speaker Mixer", "PC Beep Playback Switch", "PCBEEP"},
+       {"Speaker Mixer", "Voice Playback Switch",   "Voice DAC"},
+       {"Speaker Mixer", "Aux Playback Switch",     "Aux DAC"},
+       {"Speaker Mixer", "Bypass Playback Switch",  "Line Mixer"},
+       {"Speaker Mixer", "PCM Playback Switch",     "AC97 Mixer"},
+       {"Speaker Mixer", "MonoIn Playback Switch",  "Mono In"},
+
+       /* mono mixer */
+       {"Mono Mixer", "PC Beep Playback Switch", "PCBEEP"},
+       {"Mono Mixer", "Voice Playback Switch",   "Voice DAC"},
+       {"Mono Mixer", "Aux Playback Switch",     "Aux DAC"},
+       {"Mono Mixer", "Bypass Playback Switch",  "Line Mixer"},
+       {"Mono Mixer", "PCM Playback Switch",     "AC97 Mixer"},
+       {"Mono Mixer", "Mic 1 Sidetone Switch", "Mic A PGA"},
+       {"Mono Mixer", "Mic 2 Sidetone Switch", "Mic B PGA"},
+       {"Mono Mixer", NULL,  "Capture Mono Mux"},
+
+       /* DAC inv mux 1 */
+       {"DAC Inv Mux 1", "Mono", "Mono Mixer"},
+       {"DAC Inv Mux 1", "Speaker", "Speaker Mixer"},
+       {"DAC Inv Mux 1", "Left Headphone", "Left HP Mixer"},
+       {"DAC Inv Mux 1", "Right Headphone", "Right HP Mixer"},
+       {"DAC Inv Mux 1", "Headphone Mono", "HP Mixer"},
+
+       /* DAC inv mux 2 */
+       {"DAC Inv Mux 2", "Mono", "Mono Mixer"},
+       {"DAC Inv Mux 2", "Speaker", "Speaker Mixer"},
+       {"DAC Inv Mux 2", "Left Headphone", "Left HP Mixer"},
+       {"DAC Inv Mux 2", "Right Headphone", "Right HP Mixer"},
+       {"DAC Inv Mux 2", "Headphone Mono", "HP Mixer"},
+
+       /* headphone left mux */
+       {"Left Headphone Out Mux", "Headphone", "Left HP Mixer"},
+
+       /* headphone right mux */
+       {"Right Headphone Out Mux", "Headphone", "Right HP Mixer"},
+
+       /* speaker left mux */
+       {"Left Speaker Out Mux", "Headphone", "Left HP Mixer"},
+       {"Left Speaker Out Mux", "Speaker", "Speaker Mixer"},
+       {"Left Speaker Out Mux", "Inv", "DAC Inv Mux 1"},
+
+       /* speaker right mux */
+       {"Right Speaker Out Mux", "Headphone", "Right HP Mixer"},
+       {"Right Speaker Out Mux", "Speaker", "Speaker Mixer"},
+       {"Right Speaker Out Mux", "Inv", "DAC Inv Mux 2"},
+
+       /* mono mux */
+       {"Mono Out Mux", "Mono", "Mono Mixer"},
+       {"Mono Out Mux", "Inv", "DAC Inv Mux 1"},
+
+       /* out 3 mux */
+       {"Out 3 Mux", "Inv 1", "DAC Inv Mux 1"},
+
+       /* out 4 mux */
+       {"Out 4 Mux", "Inv 2", "DAC Inv Mux 2"},
+
+       /* output pga */
+       {"HPL", NULL, "Left Headphone"},
+       {"Left Headphone", NULL, "Left Headphone Out Mux"},
+       {"HPR", NULL, "Right Headphone"},
+       {"Right Headphone", NULL, "Right Headphone Out Mux"},
+       {"OUT3", NULL, "Out 3"},
+       {"Out 3", NULL, "Out 3 Mux"},
+       {"OUT4", NULL, "Out 4"},
+       {"Out 4", NULL, "Out 4 Mux"},
+       {"SPKL", NULL, "Left Speaker"},
+       {"Left Speaker", NULL, "Left Speaker Out Mux"},
+       {"SPKR", NULL, "Right Speaker"},
+       {"Right Speaker", NULL, "Right Speaker Out Mux"},
+       {"MONO", NULL, "Mono Out"},
+       {"Mono Out", NULL, "Mono Out Mux"},
+
+       /* input pga */
+       {"Left Line In", NULL, "LINEL"},
+       {"Right Line In", NULL, "LINER"},
+       {"Mono In", NULL, "MONOIN"},
+       {"Mic A PGA", NULL, "Mic A Pre Amp"},
+       {"Mic B PGA", NULL, "Mic B Pre Amp"},
+
+       /* left capture select */
+       {"Left Capture Source", "Mic 1", "Mic A Pre Amp"},
+       {"Left Capture Source", "Mic 2", "Mic B Pre Amp"},
+       {"Left Capture Source", "Line", "LINEL"},
+       {"Left Capture Source", "Mono In", "MONOIN"},
+       {"Left Capture Source", "Headphone", "Left HP Mixer"},
+       {"Left Capture Source", "Speaker", "Speaker Mixer"},
+       {"Left Capture Source", "Mono Out", "Mono Mixer"},
+
+       /* right capture select */
+       {"Right Capture Source", "Mic 1", "Mic A Pre Amp"},
+       {"Right Capture Source", "Mic 2", "Mic B Pre Amp"},
+       {"Right Capture Source", "Line", "LINER"},
+       {"Right Capture Source", "Mono In", "MONOIN"},
+       {"Right Capture Source", "Headphone", "Right HP Mixer"},
+       {"Right Capture Source", "Speaker", "Speaker Mixer"},
+       {"Right Capture Source", "Mono Out", "Mono Mixer"},
+
+       /* left ADC */
+       {"Left ADC", NULL, "Left Capture Source"},
+
+       /* right ADC */
+       {"Right ADC", NULL, "Right Capture Source"},
+
+       /* mic */
+       {"Mic A Pre Amp", NULL, "Mic A Source"},
+       {"Mic A Source", "Mic 1", "MIC1"},
+       {"Mic A Source", "Mic 2 A", "MIC2A"},
+       {"Mic A Source", "Mic 2 B", "Mic B Source"},
+       {"Mic B Pre Amp", "MPB", "Mic B Source"},
+       {"Mic B Source", NULL, "MIC2B"},
+
+       /* headphone capture */
+       {"Capture Headphone Mux", "Stereo", "Capture Mixer"},
+       {"Capture Headphone Mux", "Left", "Left Capture Source"},
+       {"Capture Headphone Mux", "Right", "Right Capture Source"},
+
+       /* mono capture */
+       {"Capture Mono Mux", "Stereo", "Capture Mixer"},
+       {"Capture Mono Mux", "Left", "Left Capture Source"},
+       {"Capture Mono Mux", "Right", "Right Capture Source"},
+
+       {NULL, NULL, NULL},
+};
+
+static int wm9713_add_widgets(struct snd_soc_codec *codec)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(wm9713_dapm_widgets); i++)
+               snd_soc_dapm_new_control(codec, &wm9713_dapm_widgets[i]);
+
+       /* set up audio path audio_mapnects */
+       for (i = 0; audio_map[i][0] != NULL; i++)
+               snd_soc_dapm_connect_input(codec, audio_map[i][0],
+                       audio_map[i][1], audio_map[i][2]);
+
+       snd_soc_dapm_new_widgets(codec);
+       return 0;
+}
+
+static unsigned int ac97_read(struct snd_soc_codec *codec,
+       unsigned int reg)
+{
+       u16 *cache = codec->reg_cache;
+
+       if (reg == AC97_RESET || reg == AC97_GPIO_STATUS ||
+               reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2 ||
+               reg == AC97_CD)
+               return soc_ac97_ops.read(codec->ac97, reg);
+       else {
+               reg = reg >> 1;
+
+               if (reg > (ARRAY_SIZE(wm9713_reg)))
+                       return -EIO;
+
+               return cache[reg];
+       }
+}
+
+static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
+       unsigned int val)
+{
+       u16 *cache = codec->reg_cache;
+       if (reg < 0x7c)
+               soc_ac97_ops.write(codec->ac97, reg, val);
+       reg = reg >> 1;
+       if (reg <= (ARRAY_SIZE(wm9713_reg)))
+               cache[reg] = val;
+
+       return 0;
+}
+
+/* PLL divisors */
+struct _pll_div {
+       u32 divsel:1;
+       u32 divctl:1;
+       u32 lf:1;
+       u32 n:4;
+       u32 k:24;
+};
+
+/* The size in bits of the PLL divide multiplied by 10
+ * to allow rounding later */
+#define FIXED_PLL_SIZE ((1 << 22) * 10)
+
+static void pll_factors(struct _pll_div *pll_div, unsigned int source)
+{
+       u64 Kpart;
+       unsigned int K, Ndiv, Nmod, target;
+
+       /* The the PLL output is always 98.304MHz. */
+       target = 98304000;
+
+       /* If the input frequency is over 14.4MHz then scale it down. */
+       if (source > 14400000) {
+               source >>= 1;
+               pll_div->divsel = 1;
+
+               if (source > 14400000) {
+                       source >>= 1;
+                       pll_div->divctl = 1;
+               } else
+                       pll_div->divctl = 0;
+
+       } else {
+               pll_div->divsel = 0;
+               pll_div->divctl = 0;
+       }
+
+       /* Low frequency sources require an additional divide in the
+        * loop.
+        */
+       if (source < 8192000) {
+               pll_div->lf = 1;
+               target >>= 2;
+       } else
+               pll_div->lf = 0;
+
+       Ndiv = target / source;
+       if ((Ndiv < 5) || (Ndiv > 12))
+               printk(KERN_WARNING
+                       "WM9713 PLL N value %d out of recommended range!\n",
+                       Ndiv);
+
+       pll_div->n = Ndiv;
+       Nmod = target % source;
+       Kpart = FIXED_PLL_SIZE * (long long)Nmod;
+
+       do_div(Kpart, source);
+
+       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;
+
+       pll_div->k = K;
+}
+
+/**
+ * Please note that changing the PLL input frequency may require
+ * resynchronisation with the AC97 controller.
+ */
+static int wm9713_set_pll(struct snd_soc_codec *codec,
+       int pll_id, unsigned int freq_in, unsigned int freq_out)
+{
+       struct wm9713_priv *wm9713 = codec->private_data;
+       u16 reg, reg2;
+       struct _pll_div pll_div;
+
+       /* turn PLL off ? */
+       if (freq_in == 0 || freq_out == 0) {
+               /* disable PLL power and select ext source */
+               reg = ac97_read(codec, AC97_HANDSET_RATE);
+               ac97_write(codec, AC97_HANDSET_RATE, reg | 0x0080);
+               reg = ac97_read(codec, AC97_EXTENDED_MID);
+               ac97_write(codec, AC97_EXTENDED_MID, reg | 0x0200);
+               wm9713->pll_out = 0;
+               return 0;
+       }
+
+       pll_factors(&pll_div, freq_in);
+
+       if (pll_div.k == 0) {
+               reg = (pll_div.n << 12) | (pll_div.lf << 11) |
+                       (pll_div.divsel << 9) | (pll_div.divctl << 8);
+               ac97_write(codec, AC97_LINE1_LEVEL, reg);
+       } else {
+               /* write the fractional k to the reg 0x46 pages */
+               reg2 = (pll_div.n << 12) | (pll_div.lf << 11) | (1 << 10) |
+                       (pll_div.divsel << 9) | (pll_div.divctl << 8);
+
+               /* K [21:20] */
+               reg = reg2 | (0x5 << 4) | (pll_div.k >> 20);
+               ac97_write(codec, AC97_LINE1_LEVEL, reg);
+
+               /* K [19:16] */
+               reg = reg2 | (0x4 << 4) | ((pll_div.k >> 16) & 0xf);
+               ac97_write(codec, AC97_LINE1_LEVEL, reg);
+
+               /* K [15:12] */
+               reg = reg2 | (0x3 << 4) | ((pll_div.k >> 12) & 0xf);
+               ac97_write(codec, AC97_LINE1_LEVEL, reg);
+
+               /* K [11:8] */
+               reg = reg2 | (0x2 << 4) | ((pll_div.k >> 8) & 0xf);
+               ac97_write(codec, AC97_LINE1_LEVEL, reg);
+
+               /* K [7:4] */
+               reg = reg2 | (0x1 << 4) | ((pll_div.k >> 4) & 0xf);
+               ac97_write(codec, AC97_LINE1_LEVEL, reg);
+
+               reg = reg2 | (0x0 << 4) | (pll_div.k & 0xf); /* K [3:0] */
+               ac97_write(codec, AC97_LINE1_LEVEL, reg);
+       }
+
+       /* turn PLL on and select as source */
+       reg = ac97_read(codec, AC97_EXTENDED_MID);
+       ac97_write(codec, AC97_EXTENDED_MID, reg & 0xfdff);
+       reg = ac97_read(codec, AC97_HANDSET_RATE);
+       ac97_write(codec, AC97_HANDSET_RATE, reg & 0xff7f);
+       wm9713->pll_out = freq_out;
+       wm9713->pll_in = freq_in;
+
+       /* wait 10ms AC97 link frames for the link to stabilise */
+       schedule_timeout_interruptible(msecs_to_jiffies(10));
+       return 0;
+}
+
+static int wm9713_set_dai_pll(struct snd_soc_codec_dai *codec_dai,
+               int pll_id, unsigned int freq_in, unsigned int freq_out)
+{
+       struct snd_soc_codec *codec = codec_dai->codec;
+       return wm9713_set_pll(codec, pll_id, freq_in, freq_out);
+}
+
+/*
+ * Tristate the PCM DAI lines, tristate can be disabled by calling
+ * wm9713_set_dai_fmt()
+ */
+static int wm9713_set_dai_tristate(struct snd_soc_codec_dai *codec_dai,
+       int tristate)
+{
+       struct snd_soc_codec *codec = codec_dai->codec;
+       u16 reg = ac97_read(codec, AC97_CENTER_LFE_MASTER) & 0x9fff;
+
+       if (tristate)
+               ac97_write(codec, AC97_CENTER_LFE_MASTER, reg);
+
+       return 0;
+}
+
+/*
+ * Configure WM9713 clock dividers.
+ * Voice DAC needs 256 FS
+ */
+static int wm9713_set_dai_clkdiv(struct snd_soc_codec_dai *codec_dai,
+               int div_id, int div)
+{
+       struct snd_soc_codec *codec = codec_dai->codec;
+       u16 reg;
+
+       switch (div_id) {
+       case WM9713_PCMCLK_DIV:
+               reg = ac97_read(codec, AC97_HANDSET_RATE) & 0xf0ff;
+               ac97_write(codec, AC97_HANDSET_RATE, reg | div);
+               break;
+       case WM9713_CLKA_MULT:
+               reg = ac97_read(codec, AC97_HANDSET_RATE) & 0xfffd;
+               ac97_write(codec, AC97_HANDSET_RATE, reg | div);
+               break;
+       case WM9713_CLKB_MULT:
+               reg = ac97_read(codec, AC97_HANDSET_RATE) & 0xfffb;
+               ac97_write(codec, AC97_HANDSET_RATE, reg | div);
+               break;
+       case WM9713_HIFI_DIV:
+               reg = ac97_read(codec, AC97_HANDSET_RATE) & 0x8fff;
+               ac97_write(codec, AC97_HANDSET_RATE, reg | div);
+               break;
+       case WM9713_PCMBCLK_DIV:
+               reg = ac97_read(codec, AC97_CENTER_LFE_MASTER) & 0xf1ff;
+               ac97_write(codec, AC97_CENTER_LFE_MASTER, reg | div);
+               break;
+       case WM9713_PCMCLK_PLL_DIV:
+               reg = ac97_read(codec, AC97_LINE1_LEVEL) & 0xff80;
+               ac97_write(codec, AC97_LINE1_LEVEL, reg | 0x60 | div);
+               break;
+       case WM9713_HIFI_PLL_DIV:
+               reg = ac97_read(codec, AC97_LINE1_LEVEL) & 0xff80;
+               ac97_write(codec, AC97_LINE1_LEVEL, reg | 0x70 | div);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int wm9713_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
+               unsigned int fmt)
+{
+       struct snd_soc_codec *codec = codec_dai->codec;
+       u16 gpio = ac97_read(codec, AC97_GPIO_CFG) & 0xffc5;
+       u16 reg = 0x8000;
+
+       /* clock masters */
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBM_CFM:
+               reg |= 0x4000;
+               gpio |= 0x0010;
+               break;
+       case SND_SOC_DAIFMT_CBM_CFS:
+               reg |= 0x6000;
+               gpio |= 0x0018;
+               break;
+       case SND_SOC_DAIFMT_CBS_CFS:
+               reg |= 0x0200;
+               gpio |= 0x001a;
+               break;
+       case SND_SOC_DAIFMT_CBS_CFM:
+               gpio |= 0x0012;
+               break;
+       }
+
+       /* clock inversion */
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+       case SND_SOC_DAIFMT_IB_IF:
+               reg |= 0x00c0;
+               break;
+       case SND_SOC_DAIFMT_IB_NF:
+               reg |= 0x0080;
+               break;
+       case SND_SOC_DAIFMT_NB_IF:
+               reg |= 0x0040;
+               break;
+       }
+
+       /* DAI format */
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_I2S:
+               reg |= 0x0002;
+               break;
+       case SND_SOC_DAIFMT_RIGHT_J:
+               break;
+       case SND_SOC_DAIFMT_LEFT_J:
+               reg |= 0x0001;
+               break;
+       case SND_SOC_DAIFMT_DSP_A:
+               reg |= 0x0003;
+               break;
+       case SND_SOC_DAIFMT_DSP_B:
+               reg |= 0x0043;
+               break;
+       }
+
+       ac97_write(codec, AC97_GPIO_CFG, gpio);
+       ac97_write(codec, AC97_CENTER_LFE_MASTER, reg);
+       return 0;
+}
+
+static int wm9713_pcm_hw_params(struct snd_pcm_substream *substream,
+       struct snd_pcm_hw_params *params)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_device *socdev = rtd->socdev;
+       struct snd_soc_codec *codec = socdev->codec;
+       u16 reg = ac97_read(codec, AC97_CENTER_LFE_MASTER) & 0xfff3;
+
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S16_LE:
+               break;
+       case SNDRV_PCM_FORMAT_S20_3LE:
+               reg |= 0x0004;
+               break;
+       case SNDRV_PCM_FORMAT_S24_LE:
+               reg |= 0x0008;
+               break;
+       case SNDRV_PCM_FORMAT_S32_LE:
+               reg |= 0x000c;
+               break;
+       }
+
+       /* enable PCM interface in master mode */
+       ac97_write(codec, AC97_CENTER_LFE_MASTER, reg);
+       return 0;
+}
+
+static void wm9713_voiceshutdown(struct snd_pcm_substream *substream)
+{
+    struct snd_soc_pcm_runtime *rtd = substream->private_data;
+    struct snd_soc_device *socdev = rtd->socdev;
+    struct snd_soc_codec *codec = socdev->codec;
+    u16 status;
+
+    /* Gracefully shut down the voice interface. */
+    status = ac97_read(codec, AC97_EXTENDED_STATUS) | 0x1000;
+    ac97_write(codec, AC97_HANDSET_RATE, 0x0280);
+    schedule_timeout_interruptible(msecs_to_jiffies(1));
+    ac97_write(codec, AC97_HANDSET_RATE, 0x0F80);
+    ac97_write(codec, AC97_EXTENDED_MID, status);
+}
+
+static int ac97_hifi_prepare(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_device *socdev = rtd->socdev;
+       struct snd_soc_codec *codec = socdev->codec;
+       int reg;
+       u16 vra;
+
+       vra = ac97_read(codec, AC97_EXTENDED_STATUS);
+       ac97_write(codec, AC97_EXTENDED_STATUS, vra | 0x1);
+
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               reg = AC97_PCM_FRONT_DAC_RATE;
+       else
+               reg = AC97_PCM_LR_ADC_RATE;
+
+       return ac97_write(codec, reg, runtime->rate);
+}
+
+static int ac97_aux_prepare(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_device *socdev = rtd->socdev;
+       struct snd_soc_codec *codec = socdev->codec;
+       u16 vra, xsle;
+
+       vra = ac97_read(codec, AC97_EXTENDED_STATUS);
+       ac97_write(codec, AC97_EXTENDED_STATUS, vra | 0x1);
+       xsle = ac97_read(codec, AC97_PCI_SID);
+       ac97_write(codec, AC97_PCI_SID, xsle | 0x8000);
+
+       if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
+               return -ENODEV;
+
+       return ac97_write(codec, AC97_PCM_SURR_DAC_RATE, runtime->rate);
+}
+
+#define WM9713_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
+               SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 |\
+               SNDRV_PCM_RATE_48000)
+
+#define WM9713_PCM_FORMATS \
+       (SNDRV_PCM_FORMAT_S16_LE | SNDRV_PCM_FORMAT_S20_3LE | \
+        SNDRV_PCM_FORMAT_S24_LE)
+
+struct snd_soc_codec_dai wm9713_dai[] = {
+{
+       .name = "AC97 HiFi",
+       .type = SND_SOC_DAI_AC97_BUS,
+       .playback = {
+               .stream_name = "HiFi Playback",
+               .channels_min = 1,
+               .channels_max = 2,
+               .rates = WM9713_RATES,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,},
+       .capture = {
+               .stream_name = "HiFi Capture",
+               .channels_min = 1,
+               .channels_max = 2,
+               .rates = WM9713_RATES,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,},
+       .ops = {
+               .prepare = ac97_hifi_prepare,},
+       .dai_ops = {
+               .set_clkdiv = wm9713_set_dai_clkdiv,
+               .set_pll = wm9713_set_dai_pll,},
+       },
+       {
+       .name = "AC97 Aux",
+       .playback = {
+               .stream_name = "Aux Playback",
+               .channels_min = 1,
+               .channels_max = 1,
+               .rates = WM9713_RATES,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,},
+       .ops = {
+               .prepare = ac97_aux_prepare,},
+       .dai_ops = {
+               .set_clkdiv = wm9713_set_dai_clkdiv,
+               .set_pll = wm9713_set_dai_pll,},
+       },
+       {
+       .name = "WM9713 Voice",
+       .playback = {
+               .stream_name = "Voice Playback",
+               .channels_min = 1,
+               .channels_max = 1,
+               .rates = WM9713_RATES,
+               .formats = WM9713_PCM_FORMATS,},
+       .capture = {
+               .stream_name = "Voice Capture",
+               .channels_min = 1,
+               .channels_max = 2,
+               .rates = WM9713_RATES,
+               .formats = WM9713_PCM_FORMATS,},
+       .ops = {
+               .hw_params = wm9713_pcm_hw_params,
+               .shutdown = wm9713_voiceshutdown,},
+       .dai_ops = {
+               .set_clkdiv = wm9713_set_dai_clkdiv,
+               .set_pll = wm9713_set_dai_pll,
+               .set_fmt = wm9713_set_dai_fmt,
+               .set_tristate = wm9713_set_dai_tristate,
+       },
+       },
+};
+EXPORT_SYMBOL_GPL(wm9713_dai);
+
+int wm9713_reset(struct snd_soc_codec *codec, int try_warm)
+{
+       if (try_warm && soc_ac97_ops.warm_reset) {
+               soc_ac97_ops.warm_reset(codec->ac97);
+               if (!(ac97_read(codec, 0) & 0x8000))
+                       return 1;
+       }
+
+       soc_ac97_ops.reset(codec->ac97);
+       if (ac97_read(codec, 0) & 0x8000)
+               return -EIO;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(wm9713_reset);
+
+static int wm9713_dapm_event(struct snd_soc_codec *codec, int event)
+{
+       u16 reg;
+
+       switch (event) {
+       case SNDRV_CTL_POWER_D0: /* full On */
+               /* enable thermal shutdown */
+               reg = ac97_read(codec, AC97_EXTENDED_MID) & 0x1bff;
+               ac97_write(codec, AC97_EXTENDED_MID, reg);
+               break;
+       case SNDRV_CTL_POWER_D1: /* partial On */
+       case SNDRV_CTL_POWER_D2: /* partial On */
+               break;
+       case SNDRV_CTL_POWER_D3hot: /* Off, with power */
+               /* enable master bias and vmid */
+               reg = ac97_read(codec, AC97_EXTENDED_MID) & 0x3bff;
+               ac97_write(codec, AC97_EXTENDED_MID, reg);
+               ac97_write(codec, AC97_POWERDOWN, 0x0000);
+               break;
+       case SNDRV_CTL_POWER_D3cold: /* Off, without power */
+               /* disable everything including AC link */
+               ac97_write(codec, AC97_EXTENDED_MID, 0xffff);
+               ac97_write(codec, AC97_EXTENDED_MSTATUS, 0xffff);
+               ac97_write(codec, AC97_POWERDOWN, 0xffff);
+               break;
+       }
+       codec->dapm_state = event;
+       return 0;
+}
+
+static int wm9713_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;
+       u16 reg;
+
+       /* Disable everything except touchpanel - that will be handled
+        * by the touch driver and left disabled if touch is not in
+        * use. */
+       reg = ac97_read(codec, AC97_EXTENDED_MID);
+       ac97_write(codec, AC97_EXTENDED_MID, reg | 0x7fff);
+       ac97_write(codec, AC97_EXTENDED_MSTATUS, 0xffff);
+       ac97_write(codec, AC97_POWERDOWN, 0x6f00);
+       ac97_write(codec, AC97_POWERDOWN, 0xffff);
+
+       return 0;
+}
+
+static int wm9713_soc_resume(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec = socdev->codec;
+       struct wm9713_priv *wm9713 = codec->private_data;
+       int i, ret;
+       u16 *cache = codec->reg_cache;
+
+       ret = wm9713_reset(codec, 1);
+       if (ret < 0) {
+               printk(KERN_ERR "could not reset AC97 codec\n");
+               return ret;
+       }
+
+       wm9713_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
+
+       /* do we need to re-start the PLL ? */
+       if (wm9713->pll_out)
+               wm9713_set_pll(codec, 0, wm9713->pll_in, wm9713->pll_out);
+
+       /* only synchronise the codec if warm reset failed */
+       if (ret == 0) {
+               for (i = 2; i < ARRAY_SIZE(wm9713_reg) << 1; i += 2) {
+                       if (i == AC97_POWERDOWN || i == AC97_EXTENDED_MID ||
+                               i == AC97_EXTENDED_MSTATUS || i > 0x66)
+                               continue;
+                       soc_ac97_ops.write(codec->ac97, i, cache[i>>1]);
+               }
+       }
+
+       if (codec->suspend_dapm_state == SNDRV_CTL_POWER_D0)
+               wm9713_dapm_event(codec, SNDRV_CTL_POWER_D0);
+
+       return ret;
+}
+
+static int wm9713_soc_probe(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec;
+       int ret = 0, reg;
+
+       printk(KERN_INFO "WM9713/WM9714 SoC Audio Codec %s\n", WM9713_VERSION);
+
+       socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
+       if (socdev->codec == NULL)
+               return -ENOMEM;
+       codec = socdev->codec;
+       mutex_init(&codec->mutex);
+
+       codec->reg_cache = kmemdup(wm9713_reg, sizeof(wm9713_reg), GFP_KERNEL);
+       if (codec->reg_cache == NULL) {
+               ret = -ENOMEM;
+               goto cache_err;
+       }
+       codec->reg_cache_size = sizeof(wm9713_reg);
+       codec->reg_cache_step = 2;
+
+       codec->private_data = kzalloc(sizeof(struct wm9713_priv), GFP_KERNEL);
+       if (codec->private_data == NULL) {
+               ret = -ENOMEM;
+               goto priv_err;
+       }
+
+       codec->name = "WM9713";
+       codec->owner = THIS_MODULE;
+       codec->dai = wm9713_dai;
+       codec->num_dai = ARRAY_SIZE(wm9713_dai);
+       codec->write = ac97_write;
+       codec->read = ac97_read;
+       codec->dapm_event = wm9713_dapm_event;
+       INIT_LIST_HEAD(&codec->dapm_widgets);
+       INIT_LIST_HEAD(&codec->dapm_paths);
+
+       ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);
+       if (ret < 0)
+               goto codec_err;
+
+       /* register pcms */
+       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+       if (ret < 0)
+               goto pcm_err;
+
+       /* do a cold reset for the controller and then try
+        * a warm reset followed by an optional cold reset for codec */
+       wm9713_reset(codec, 0);
+       ret = wm9713_reset(codec, 1);
+       if (ret < 0) {
+               printk(KERN_ERR "AC97 link error\n");
+               goto reset_err;
+       }
+
+       wm9713_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
+
+       /* unmute the adc - move to kcontrol */
+       reg = ac97_read(codec, AC97_CD) & 0x7fff;
+       ac97_write(codec, AC97_CD, reg);
+
+       wm9713_add_controls(codec);
+       wm9713_add_widgets(codec);
+       ret = snd_soc_register_card(socdev);
+       if (ret < 0)
+               goto reset_err;
+       return 0;
+
+reset_err:
+       snd_soc_free_pcms(socdev);
+
+pcm_err:
+       snd_soc_free_ac97_codec(codec);
+
+codec_err:
+       kfree(codec->private_data);
+
+priv_err:
+       kfree(codec->reg_cache);
+
+cache_err:
+       kfree(socdev->codec);
+       socdev->codec = NULL;
+       return ret;
+}
+
+static int wm9713_soc_remove(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec = socdev->codec;
+
+       if (codec == NULL)
+               return 0;
+
+       snd_soc_dapm_free(socdev);
+       snd_soc_free_pcms(socdev);
+       snd_soc_free_ac97_codec(codec);
+       kfree(codec->private_data);
+       kfree(codec->reg_cache);
+       kfree(codec->dai);
+       kfree(codec);
+       return 0;
+}
+
+struct snd_soc_codec_device soc_codec_dev_wm9713 = {
+       .probe =        wm9713_soc_probe,
+       .remove =       wm9713_soc_remove,
+       .suspend =      wm9713_soc_suspend,
+       .resume =       wm9713_soc_resume,
+};
+EXPORT_SYMBOL_GPL(soc_codec_dev_wm9713);
+
+MODULE_DESCRIPTION("ASoC WM9713/WM9714 driver");
+MODULE_AUTHOR("Liam Girdwood");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm9713.h b/sound/soc/codecs/wm9713.h
new file mode 100644 (file)
index 0000000..d357b6c
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * wm9713.h  --  WM9713 Soc Audio driver
+ */
+
+#ifndef _WM9713_H
+#define _WM9713_H
+
+/* clock inputs */
+#define WM9713_CLKA_PIN                        0
+#define WM9713_CLKB_PIN                        1
+
+/* clock divider ID's */
+#define WM9713_PCMCLK_DIV              0
+#define WM9713_CLKA_MULT               1
+#define WM9713_CLKB_MULT               2
+#define WM9713_HIFI_DIV                        3
+#define WM9713_PCMBCLK_DIV             4
+#define WM9713_PCMCLK_PLL_DIV           5
+#define WM9713_HIFI_PLL_DIV             6
+
+/* Calculate the appropriate bit mask for the external PCM clock divider */
+#define WM9713_PCMDIV(x)       ((x - 1) << 8)
+
+/* Calculate the appropriate bit mask for the external HiFi clock divider */
+#define WM9713_HIFIDIV(x)      ((x - 1) << 12)
+
+/* MCLK clock mulitipliers */
+#define WM9713_CLKA_X1         (0 << 1)
+#define WM9713_CLKA_X2         (1 << 1)
+#define WM9713_CLKB_X1         (0 << 2)
+#define WM9713_CLKB_X2         (1 << 2)
+
+/* MCLK clock MUX */
+#define WM9713_CLK_MUX_A               (0 << 0)
+#define WM9713_CLK_MUX_B               (1 << 0)
+
+/* Voice DAI BCLK divider */
+#define WM9713_PCMBCLK_DIV_1   (0 << 9)
+#define WM9713_PCMBCLK_DIV_2   (1 << 9)
+#define WM9713_PCMBCLK_DIV_4   (2 << 9)
+#define WM9713_PCMBCLK_DIV_8   (3 << 9)
+#define WM9713_PCMBCLK_DIV_16  (4 << 9)
+
+#define WM9713_DAI_AC97_HIFI   0
+#define WM9713_DAI_AC97_AUX            1
+#define WM9713_DAI_PCM_VOICE   2
+
+extern struct snd_soc_codec_device soc_codec_dev_wm9713;
+extern struct snd_soc_codec_dai wm9713_dai[3];
+
+int wm9713_reset(struct snd_soc_codec *codec,  int try_warm);
+
+#endif
diff --git a/sound/soc/davinci/Kconfig b/sound/soc/davinci/Kconfig
new file mode 100644 (file)
index 0000000..20680c5
--- /dev/null
@@ -0,0 +1,19 @@
+config SND_DAVINCI_SOC
+       tristate "SoC Audio for the TI DAVINCI chip"
+       depends on ARCH_DAVINCI && SND_SOC
+       help
+         Say Y or M if you want to add support for codecs attached to
+         the DAVINCI AC97 or I2S interface. You will also need
+         to select the audio interfaces to support below.
+
+config SND_DAVINCI_SOC_I2S
+       tristate
+
+config SND_DAVINCI_SOC_EVM
+       tristate "SoC Audio support for DaVinci EVM"
+       depends on SND_DAVINCI_SOC && MACH_DAVINCI_EVM
+       select SND_DAVINCI_SOC_I2S
+       select SND_SOC_TLV320AIC3X
+       help
+         Say Y if you want to add support for SoC audio on TI
+         DaVinci EVM platform.
diff --git a/sound/soc/davinci/Makefile b/sound/soc/davinci/Makefile
new file mode 100644 (file)
index 0000000..ca772e5
--- /dev/null
@@ -0,0 +1,11 @@
+# DAVINCI Platform Support
+snd-soc-davinci-objs := davinci-pcm.o
+snd-soc-davinci-i2s-objs := davinci-i2s.o
+
+obj-$(CONFIG_SND_DAVINCI_SOC) += snd-soc-davinci.o
+obj-$(CONFIG_SND_DAVINCI_SOC_I2S) += snd-soc-davinci-i2s.o
+
+# DAVINCI Machine Support
+snd-soc-evm-objs := davinci-evm.o
+
+obj-$(CONFIG_SND_DAVINCI_SOC_EVM) += snd-soc-evm.o
diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c
new file mode 100644 (file)
index 0000000..fcd1652
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * ASoC driver for TI DAVINCI EVM platform
+ *
+ * Author:      Vladimir Barinov, <vbarinov@ru.mvista.com>
+ * 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 <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <asm/mach-types.h>
+#include <asm/dma.h>
+#include <asm/arch/hardware.h>
+
+#include "../codecs/tlv320aic3x.h"
+#include "davinci-pcm.h"
+#include "davinci-i2s.h"
+
+#define EVM_CODEC_CLOCK 22579200
+
+static int evm_hw_params(struct snd_pcm_substream *substream,
+                        struct snd_pcm_hw_params *params)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;
+       struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
+       int ret = 0;
+
+       /* set codec DAI configuration */
+       ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
+                                        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_CBM_CFM |
+                                      SND_SOC_DAIFMT_IB_NF);
+       if (ret < 0)
+               return ret;
+
+       /* set the codec system clock */
+       ret = codec_dai->dai_ops.set_sysclk(codec_dai, 0, EVM_CODEC_CLOCK,
+                                           SND_SOC_CLOCK_OUT);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+static struct snd_soc_ops evm_ops = {
+       .hw_params = evm_hw_params,
+};
+
+/* davinci-evm machine dapm widgets */
+static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
+       SND_SOC_DAPM_HP("Headphone Jack", NULL),
+       SND_SOC_DAPM_LINE("Line Out", NULL),
+       SND_SOC_DAPM_MIC("Mic Jack", NULL),
+       SND_SOC_DAPM_LINE("Line In", NULL),
+};
+
+/* davinci-evm machine audio_mapnections to the codec pins */
+static const char *audio_map[][3] = {
+       /* Headphone connected to HPLOUT, HPROUT */
+       {"Headphone Jack", NULL, "HPLOUT"},
+       {"Headphone Jack", NULL, "HPROUT"},
+
+       /* Line Out connected to LLOUT, RLOUT */
+       {"Line Out", NULL, "LLOUT"},
+       {"Line Out", NULL, "RLOUT"},
+
+       /* Mic connected to (MIC3L | MIC3R) */
+       {"MIC3L", NULL, "Mic Bias 2V"},
+       {"MIC3R", NULL, "Mic Bias 2V"},
+       {"Mic Bias 2V", NULL, "Mic Jack"},
+
+       /* Line In connected to (LINE1L | LINE2L), (LINE1R | LINE2R) */
+       {"LINE1L", NULL, "Line In"},
+       {"LINE2L", NULL, "Line In"},
+       {"LINE1R", NULL, "Line In"},
+       {"LINE2R", NULL, "Line In"},
+
+       {NULL, NULL, NULL},
+};
+
+/* Logic for a aic3x as connected on a davinci-evm */
+static int evm_aic3x_init(struct snd_soc_codec *codec)
+{
+       int i;
+
+       /* Add davinci-evm specific widgets */
+       for (i = 0; i < ARRAY_SIZE(aic3x_dapm_widgets); i++)
+               snd_soc_dapm_new_control(codec, &aic3x_dapm_widgets[i]);
+
+       /* Set up davinci-evm specific audio path audio_map */
+       for (i = 0; audio_map[i][0] != NULL; i++)
+               snd_soc_dapm_connect_input(codec, audio_map[i][0],
+                                          audio_map[i][1], audio_map[i][2]);
+
+       /* not connected */
+       snd_soc_dapm_set_endpoint(codec, "MONO_LOUT", 0);
+       snd_soc_dapm_set_endpoint(codec, "HPLCOM", 0);
+       snd_soc_dapm_set_endpoint(codec, "HPRCOM", 0);
+
+       /* always connected */
+       snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 1);
+       snd_soc_dapm_set_endpoint(codec, "Line Out", 1);
+       snd_soc_dapm_set_endpoint(codec, "Mic Jack", 1);
+       snd_soc_dapm_set_endpoint(codec, "Line In", 1);
+
+       snd_soc_dapm_sync_endpoints(codec);
+
+       return 0;
+}
+
+/* davinci-evm digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link evm_dai = {
+       .name = "TLV320AIC3X",
+       .stream_name = "AIC3X",
+       .cpu_dai = &davinci_i2s_dai,
+       .codec_dai = &aic3x_dai,
+       .init = evm_aic3x_init,
+       .ops = &evm_ops,
+};
+
+/* davinci-evm audio machine driver */
+static struct snd_soc_machine snd_soc_machine_evm = {
+       .name = "DaVinci EVM",
+       .dai_link = &evm_dai,
+       .num_links = 1,
+};
+
+/* evm audio private data */
+static struct aic3x_setup_data evm_aic3x_setup = {
+       .i2c_address = 0x1b,
+};
+
+/* evm audio subsystem */
+static struct snd_soc_device evm_snd_devdata = {
+       .machine = &snd_soc_machine_evm,
+       .platform = &davinci_soc_platform,
+       .codec_dev = &soc_codec_dev_aic3x,
+       .codec_data = &evm_aic3x_setup,
+};
+
+static struct resource evm_snd_resources[] = {
+       {
+               .start = DAVINCI_MCBSP_BASE,
+               .end = DAVINCI_MCBSP_BASE + SZ_8K - 1,
+               .flags = IORESOURCE_MEM,
+       },
+};
+
+static struct evm_snd_platform_data evm_snd_data = {
+       .tx_dma_ch      = DM644X_DMACH_MCBSP_TX,
+       .rx_dma_ch      = DM644X_DMACH_MCBSP_RX,
+};
+
+static struct platform_device *evm_snd_device;
+
+static int __init evm_init(void)
+{
+       int ret;
+
+       evm_snd_device = platform_device_alloc("soc-audio", 0);
+       if (!evm_snd_device)
+               return -ENOMEM;
+
+       platform_set_drvdata(evm_snd_device, &evm_snd_devdata);
+       evm_snd_devdata.dev = &evm_snd_device->dev;
+       evm_snd_device->dev.platform_data = &evm_snd_data;
+
+       ret = platform_device_add_resources(evm_snd_device, evm_snd_resources,
+                                           ARRAY_SIZE(evm_snd_resources));
+       if (ret) {
+               platform_device_put(evm_snd_device);
+               return ret;
+       }
+
+       ret = platform_device_add(evm_snd_device);
+       if (ret)
+               platform_device_put(evm_snd_device);
+
+       return ret;
+}
+
+static void __exit evm_exit(void)
+{
+       platform_device_unregister(evm_snd_device);
+}
+
+module_init(evm_init);
+module_exit(evm_exit);
+
+MODULE_AUTHOR("Vladimir Barinov");
+MODULE_DESCRIPTION("TI DAVINCI EVM ASoC driver");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c
new file mode 100644 (file)
index 0000000..c421774
--- /dev/null
@@ -0,0 +1,407 @@
+/*
+ * ALSA SoC I2S (McBSP) Audio Layer for TI DAVINCI processor
+ *
+ * Author:      Vladimir Barinov, <vbarinov@ru.mvista.com>
+ * 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/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+
+#include "davinci-pcm.h"
+
+#define DAVINCI_MCBSP_DRR_REG  0x00
+#define DAVINCI_MCBSP_DXR_REG  0x04
+#define DAVINCI_MCBSP_SPCR_REG 0x08
+#define DAVINCI_MCBSP_RCR_REG  0x0c
+#define DAVINCI_MCBSP_XCR_REG  0x10
+#define DAVINCI_MCBSP_SRGR_REG 0x14
+#define DAVINCI_MCBSP_PCR_REG  0x24
+
+#define DAVINCI_MCBSP_SPCR_RRST                (1 << 0)
+#define DAVINCI_MCBSP_SPCR_RINTM(v)    ((v) << 4)
+#define DAVINCI_MCBSP_SPCR_XRST                (1 << 16)
+#define DAVINCI_MCBSP_SPCR_XINTM(v)    ((v) << 20)
+#define DAVINCI_MCBSP_SPCR_GRST                (1 << 22)
+#define DAVINCI_MCBSP_SPCR_FRST                (1 << 23)
+#define DAVINCI_MCBSP_SPCR_FREE                (1 << 25)
+
+#define DAVINCI_MCBSP_RCR_RWDLEN1(v)   ((v) << 5)
+#define DAVINCI_MCBSP_RCR_RFRLEN1(v)   ((v) << 8)
+#define DAVINCI_MCBSP_RCR_RDATDLY(v)   ((v) << 16)
+#define DAVINCI_MCBSP_RCR_RWDLEN2(v)   ((v) << 21)
+
+#define DAVINCI_MCBSP_XCR_XWDLEN1(v)   ((v) << 5)
+#define DAVINCI_MCBSP_XCR_XFRLEN1(v)   ((v) << 8)
+#define DAVINCI_MCBSP_XCR_XDATDLY(v)   ((v) << 16)
+#define DAVINCI_MCBSP_XCR_XFIG         (1 << 18)
+#define DAVINCI_MCBSP_XCR_XWDLEN2(v)   ((v) << 21)
+
+#define DAVINCI_MCBSP_SRGR_FWID(v)     ((v) << 8)
+#define DAVINCI_MCBSP_SRGR_FPER(v)     ((v) << 16)
+#define DAVINCI_MCBSP_SRGR_FSGM                (1 << 28)
+
+#define DAVINCI_MCBSP_PCR_CLKRP                (1 << 0)
+#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_CLKRM                (1 << 8)
+#define DAVINCI_MCBSP_PCR_CLKXM                (1 << 9)
+#define DAVINCI_MCBSP_PCR_FSRM         (1 << 10)
+#define DAVINCI_MCBSP_PCR_FSXM         (1 << 11)
+
+#define MOD_REG_BIT(val, mask, set) do { \
+       if (set) { \
+               val |= mask; \
+       } else { \
+               val &= ~mask; \
+       } \
+} while (0)
+
+enum {
+       DAVINCI_MCBSP_WORD_8 = 0,
+       DAVINCI_MCBSP_WORD_12,
+       DAVINCI_MCBSP_WORD_16,
+       DAVINCI_MCBSP_WORD_20,
+       DAVINCI_MCBSP_WORD_24,
+       DAVINCI_MCBSP_WORD_32,
+};
+
+static struct davinci_pcm_dma_params davinci_i2s_pcm_out = {
+       .name = "I2S PCM Stereo out",
+};
+
+static struct davinci_pcm_dma_params davinci_i2s_pcm_in = {
+       .name = "I2S PCM Stereo in",
+};
+
+struct davinci_mcbsp_dev {
+       void __iomem                    *base;
+       struct clk                      *clk;
+       struct davinci_pcm_dma_params   *dma_params[2];
+};
+
+static inline void davinci_mcbsp_write_reg(struct davinci_mcbsp_dev *dev,
+                                          int reg, u32 val)
+{
+       __raw_writel(val, dev->base + reg);
+}
+
+static inline u32 davinci_mcbsp_read_reg(struct davinci_mcbsp_dev *dev, int reg)
+{
+       return __raw_readl(dev->base + reg);
+}
+
+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;
+       u32 w;
+
+       /* 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)
+               MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 1);
+       else
+               MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_RRST, 1);
+       davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
+
+       /* Start frame sync */
+       w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
+       MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_FRST, 1);
+       davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
+}
+
+static void davinci_mcbsp_stop(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;
+       u32 w;
+
+       /* Reset transmitter/receiver and sample rate/frame sync generators */
+       w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
+       MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_GRST |
+                      DAVINCI_MCBSP_SPCR_FRST, 0);
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 0);
+       else
+               MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_RRST, 0);
+       davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
+}
+
+static int davinci_i2s_startup(struct snd_pcm_substream *substream)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
+       struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data;
+
+       cpu_dai->dma_data = dev->dma_params[substream->stream];
+
+       return 0;
+}
+
+static int davinci_i2s_set_dai_fmt(struct snd_soc_cpu_dai *cpu_dai,
+                                  unsigned int fmt)
+{
+       struct davinci_mcbsp_dev *dev = cpu_dai->private_data;
+       u32 w;
+
+       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);
+               break;
+       case SND_SOC_DAIFMT_CBM_CFM:
+               davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, 0);
+               break;
+       default:
+               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);
+               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);
+               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);
+               break;
+       case SND_SOC_DAIFMT_NB_NF:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
+                                struct snd_pcm_hw_params *params)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct davinci_pcm_dma_params *dma_params = rtd->dai->cpu_dai->dma_data;
+       struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data;
+       struct snd_interval *i = NULL;
+       int mcbsp_word_length;
+       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);
+
+       i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS);
+       w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SRGR_REG);
+       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);
+
+       /* Determine xfer data type */
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S8:
+               dma_params->data_type = 1;
+               mcbsp_word_length = DAVINCI_MCBSP_WORD_8;
+               break;
+       case SNDRV_PCM_FORMAT_S16_LE:
+               dma_params->data_type = 2;
+               mcbsp_word_length = DAVINCI_MCBSP_WORD_16;
+               break;
+       case SNDRV_PCM_FORMAT_S32_LE:
+               dma_params->data_type = 4;
+               mcbsp_word_length = DAVINCI_MCBSP_WORD_32;
+               break;
+       default:
+               printk(KERN_WARNING "davinci-i2s: unsupported PCM format");
+               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);
+
+       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)
+{
+       int ret = 0;
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+               davinci_mcbsp_start(substream);
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+               davinci_mcbsp_stop(substream);
+               break;
+       default:
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
+
+static int davinci_i2s_probe(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_machine *machine = socdev->machine;
+       struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[pdev->id].cpu_dai;
+       struct davinci_mcbsp_dev *dev;
+       struct resource *mem, *ioarea;
+       struct evm_snd_platform_data *pdata;
+       int ret;
+
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!mem) {
+               dev_err(&pdev->dev, "no mem resource?\n");
+               return -ENODEV;
+       }
+
+       ioarea = request_mem_region(mem->start, (mem->end - mem->start) + 1,
+                                   pdev->name);
+       if (!ioarea) {
+               dev_err(&pdev->dev, "McBSP region already claimed\n");
+               return -EBUSY;
+       }
+
+       dev = kzalloc(sizeof(struct davinci_mcbsp_dev), GFP_KERNEL);
+       if (!dev) {
+               ret = -ENOMEM;
+               goto err_release_region;
+       }
+
+       cpu_dai->private_data = dev;
+
+       dev->clk = clk_get(&pdev->dev, "McBSPCLK");
+       if (IS_ERR(dev->clk)) {
+               ret = -ENODEV;
+               goto err_free_mem;
+       }
+       clk_enable(dev->clk);
+
+       dev->base = (void __iomem *)IO_ADDRESS(mem->start);
+       pdata = pdev->dev.platform_data;
+
+       dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK] = &davinci_i2s_pcm_out;
+       dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]->channel = pdata->tx_dma_ch;
+       dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]->dma_addr =
+           (dma_addr_t)(io_v2p(dev->base) + DAVINCI_MCBSP_DXR_REG);
+
+       dev->dma_params[SNDRV_PCM_STREAM_CAPTURE] = &davinci_i2s_pcm_in;
+       dev->dma_params[SNDRV_PCM_STREAM_CAPTURE]->channel = pdata->rx_dma_ch;
+       dev->dma_params[SNDRV_PCM_STREAM_CAPTURE]->dma_addr =
+           (dma_addr_t)(io_v2p(dev->base) + DAVINCI_MCBSP_DRR_REG);
+
+       return 0;
+
+err_free_mem:
+       kfree(dev);
+err_release_region:
+       release_mem_region(mem->start, (mem->end - mem->start) + 1);
+
+       return ret;
+}
+
+static void davinci_i2s_remove(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_machine *machine = socdev->machine;
+       struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[pdev->id].cpu_dai;
+       struct davinci_mcbsp_dev *dev = cpu_dai->private_data;
+       struct resource *mem;
+
+       clk_disable(dev->clk);
+       clk_put(dev->clk);
+       dev->clk = NULL;
+
+       kfree(dev);
+
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       release_mem_region(mem->start, (mem->end - mem->start) + 1);
+}
+
+#define DAVINCI_I2S_RATES      SNDRV_PCM_RATE_8000_96000
+
+struct snd_soc_cpu_dai davinci_i2s_dai = {
+       .name = "davinci-i2s",
+       .id = 0,
+       .type = SND_SOC_DAI_I2S,
+       .probe = davinci_i2s_probe,
+       .remove = davinci_i2s_remove,
+       .playback = {
+               .channels_min = 2,
+               .channels_max = 2,
+               .rates = DAVINCI_I2S_RATES,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,},
+       .capture = {
+               .channels_min = 2,
+               .channels_max = 2,
+               .rates = DAVINCI_I2S_RATES,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,},
+       .ops = {
+               .startup = davinci_i2s_startup,
+               .trigger = davinci_i2s_trigger,
+               .hw_params = davinci_i2s_hw_params,},
+       .dai_ops = {
+               .set_fmt = davinci_i2s_set_dai_fmt,
+       },
+};
+EXPORT_SYMBOL_GPL(davinci_i2s_dai);
+
+MODULE_AUTHOR("Vladimir Barinov");
+MODULE_DESCRIPTION("TI DAVINCI I2S (McBSP) SoC Interface");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/davinci/davinci-i2s.h b/sound/soc/davinci/davinci-i2s.h
new file mode 100644 (file)
index 0000000..9592d17
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * ALSA SoC I2S (McBSP) Audio Layer for TI DAVINCI processor
+ *
+ * Author:      Vladimir Barinov, <vbarinov@ru.mvista.com>
+ * 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.
+ */
+
+#ifndef _DAVINCI_I2S_H
+#define _DAVINCI_I2S_H
+
+extern struct snd_soc_cpu_dai davinci_i2s_dai;
+
+#endif
diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c
new file mode 100644 (file)
index 0000000..6a76927
--- /dev/null
@@ -0,0 +1,389 @@
+/*
+ * ALSA PCM interface for the TI DAVINCI processor
+ *
+ * Author:      Vladimir Barinov, <vbarinov@ru.mvista.com>
+ * 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/init.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include <asm/dma.h>
+
+#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 |
+                SNDRV_PCM_INFO_PAUSE),
+       .formats = (SNDRV_PCM_FMTBIT_S16_LE),
+       .rates = (SNDRV_PCM_RATE_8000 | 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 |
+                 SNDRV_PCM_RATE_KNOT),
+       .rate_min = 8000,
+       .rate_max = 96000,
+       .channels_min = 2,
+       .channels_max = 2,
+       .buffer_bytes_max = 128 * 1024,
+       .period_bytes_min = 32,
+       .period_bytes_max = 8 * 1024,
+       .periods_min = 16,
+       .periods_max = 255,
+       .fifo_size = 0,
+};
+
+struct davinci_runtime_data {
+       spinlock_t lock;
+       int period;             /* current DMA period */
+       int master_lch;         /* Master DMA channel */
+       int slave_lch;          /* Slave DMA channel */
+       struct davinci_pcm_dma_params *params;  /* DMA params */
+};
+
+static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
+{
+       struct davinci_runtime_data *prtd = substream->runtime->private_data;
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       int lch = prtd->slave_lch;
+       unsigned int period_size;
+       unsigned int dma_offset;
+       dma_addr_t dma_pos;
+       dma_addr_t src, dst;
+       unsigned short src_bidx, dst_bidx;
+       unsigned int data_type;
+       unsigned int count;
+
+       period_size = snd_pcm_lib_period_bytes(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);
+
+       data_type = prtd->params->data_type;
+       count = period_size / data_type;
+
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               src = dma_pos;
+               dst = prtd->params->dma_addr;
+               src_bidx = data_type;
+               dst_bidx = 0;
+       } else {
+               src = prtd->params->dma_addr;
+               dst = dma_pos;
+               src_bidx = 0;
+               dst_bidx = data_type;
+       }
+
+       davinci_set_dma_src_params(lch, src, INCR, W8BIT);
+       davinci_set_dma_dest_params(lch, dst, INCR, W8BIT);
+       davinci_set_dma_src_index(lch, src_bidx, 0);
+       davinci_set_dma_dest_index(lch, dst_bidx, 0);
+       davinci_set_dma_transfer_params(lch, data_type, count, 1, 0, ASYNC);
+
+       prtd->period++;
+       if (unlikely(prtd->period >= runtime->periods))
+               prtd->period = 0;
+}
+
+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);
+
+       if (unlikely(ch_status != DMA_COMPLETE))
+               return;
+
+       if (snd_pcm_running(substream)) {
+               snd_pcm_period_elapsed(substream);
+
+               spin_lock(&prtd->lock);
+               davinci_pcm_enqueue_dma(substream);
+               spin_unlock(&prtd->lock);
+       }
+}
+
+static int davinci_pcm_dma_request(struct snd_pcm_substream *substream)
+{
+       struct davinci_runtime_data *prtd = substream->runtime->private_data;
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct davinci_pcm_dma_params *dma_data = rtd->dai->cpu_dai->dma_data;
+       int tcc = TCC_ANY;
+       int ret;
+
+       if (!dma_data)
+               return -ENODEV;
+
+       prtd->params = dma_data;
+
+       /* Request master DMA channel */
+       ret = davinci_request_dma(prtd->params->channel, prtd->params->name,
+                                 davinci_pcm_dma_irq, substream,
+                                 &prtd->master_lch, &tcc, EVENTQ_0);
+       if (ret)
+               return ret;
+
+       /* Request slave DMA channel */
+       ret = davinci_request_dma(PARAM_ANY, "Link",
+                                 NULL, NULL, &prtd->slave_lch, &tcc, EVENTQ_0);
+       if (ret) {
+               davinci_free_dma(prtd->master_lch);
+               return ret;
+       }
+
+       /* Link slave DMA channel in loopback */
+       davinci_dma_link_lch(prtd->slave_lch, prtd->slave_lch);
+
+       return 0;
+}
+
+static int davinci_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+       struct davinci_runtime_data *prtd = substream->runtime->private_data;
+       int ret = 0;
+
+       spin_lock(&prtd->lock);
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+               davinci_start_dma(prtd->master_lch);
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+               davinci_stop_dma(prtd->master_lch);
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+
+       spin_unlock(&prtd->lock);
+
+       return ret;
+}
+
+static int davinci_pcm_prepare(struct snd_pcm_substream *substream)
+{
+       struct davinci_runtime_data *prtd = substream->runtime->private_data;
+       struct paramentry_descriptor temp;
+
+       prtd->period = 0;
+       davinci_pcm_enqueue_dma(substream);
+
+       /* Get slave channel dma params for master channel startup */
+       davinci_get_dma_params(prtd->slave_lch, &temp);
+       davinci_set_dma_params(prtd->master_lch, &temp);
+
+       return 0;
+}
+
+static snd_pcm_uframes_t
+davinci_pcm_pointer(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct davinci_runtime_data *prtd = runtime->private_data;
+       unsigned int offset;
+       dma_addr_t count;
+       dma_addr_t src, dst;
+
+       spin_lock(&prtd->lock);
+
+       davinci_dma_getposition(prtd->master_lch, &src, &dst);
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               count = src - runtime->dma_addr;
+       else
+               count = dst - runtime->dma_addr;;
+
+       spin_unlock(&prtd->lock);
+
+       offset = bytes_to_frames(runtime, count);
+       if (offset >= runtime->buffer_size)
+               offset = 0;
+
+       return offset;
+}
+
+static int davinci_pcm_open(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct davinci_runtime_data *prtd;
+       int ret = 0;
+
+       snd_soc_set_runtime_hwparams(substream, &davinci_pcm_hardware);
+
+       prtd = kzalloc(sizeof(struct davinci_runtime_data), GFP_KERNEL);
+       if (prtd == NULL)
+               return -ENOMEM;
+
+       spin_lock_init(&prtd->lock);
+
+       runtime->private_data = prtd;
+
+       ret = davinci_pcm_dma_request(substream);
+       if (ret) {
+               printk(KERN_ERR "davinci_pcm: Failed to get dma channels\n");
+               kfree(prtd);
+       }
+
+       return ret;
+}
+
+static int davinci_pcm_close(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct davinci_runtime_data *prtd = runtime->private_data;
+
+       davinci_dma_unlink_lch(prtd->slave_lch, prtd->slave_lch);
+
+       davinci_free_dma(prtd->slave_lch);
+       davinci_free_dma(prtd->master_lch);
+
+       kfree(prtd);
+
+       return 0;
+}
+
+static int davinci_pcm_hw_params(struct snd_pcm_substream *substream,
+                                struct snd_pcm_hw_params *hw_params)
+{
+       return snd_pcm_lib_malloc_pages(substream,
+                                       params_buffer_bytes(hw_params));
+}
+
+static int davinci_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+       return snd_pcm_lib_free_pages(substream);
+}
+
+static int davinci_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 davinci_pcm_ops = {
+       .open =         davinci_pcm_open,
+       .close =        davinci_pcm_close,
+       .ioctl =        snd_pcm_lib_ioctl,
+       .hw_params =    davinci_pcm_hw_params,
+       .hw_free =      davinci_pcm_hw_free,
+       .prepare =      davinci_pcm_prepare,
+       .trigger =      davinci_pcm_trigger,
+       .pointer =      davinci_pcm_pointer,
+       .mmap =         davinci_pcm_mmap,
+};
+
+static int davinci_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 = davinci_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);
+
+       DPRINTK("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 void davinci_pcm_free(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;
+       }
+}
+
+static u64 davinci_pcm_dmamask = 0xffffffff;
+
+static int davinci_pcm_new(struct snd_card *card,
+                          struct snd_soc_codec_dai *dai, struct snd_pcm *pcm)
+{
+       int ret;
+
+       if (!card->dev->dma_mask)
+               card->dev->dma_mask = &davinci_pcm_dmamask;
+       if (!card->dev->coherent_dma_mask)
+               card->dev->coherent_dma_mask = 0xffffffff;
+
+       if (dai->playback.channels_min) {
+               ret = davinci_pcm_preallocate_dma_buffer(pcm,
+                       SNDRV_PCM_STREAM_PLAYBACK);
+               if (ret)
+                       return ret;
+       }
+
+       if (dai->capture.channels_min) {
+               ret = davinci_pcm_preallocate_dma_buffer(pcm,
+                       SNDRV_PCM_STREAM_CAPTURE);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+struct snd_soc_platform davinci_soc_platform = {
+       .name =         "davinci-audio",
+       .pcm_ops =      &davinci_pcm_ops,
+       .pcm_new =      davinci_pcm_new,
+       .pcm_free =     davinci_pcm_free,
+};
+EXPORT_SYMBOL_GPL(davinci_soc_platform);
+
+MODULE_AUTHOR("Vladimir Barinov");
+MODULE_DESCRIPTION("TI DAVINCI PCM DMA module");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/davinci/davinci-pcm.h b/sound/soc/davinci/davinci-pcm.h
new file mode 100644 (file)
index 0000000..8d6a45e
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * ALSA PCM interface for the TI DAVINCI processor
+ *
+ * Author:      Vladimir Barinov, <vbarinov@ru.mvista.com>
+ * 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.
+ */
+
+#ifndef _DAVINCI_PCM_H
+#define _DAVINCI_PCM_H
+
+struct davinci_pcm_dma_params {
+       char *name;             /* stream identifier */
+       int channel;            /* sync dma channel ID */
+       dma_addr_t dma_addr;    /* device physical address for DMA */
+       unsigned int data_type; /* xfer data type */
+};
+
+struct evm_snd_platform_data {
+       int tx_dma_ch;
+       int rx_dma_ch;
+};
+
+extern struct snd_soc_platform davinci_soc_platform;
+
+#endif
index 652514fc814206066dbd79c733d77791559241d2..78de7168d2ba506c767c397f6362ae0c248ef190 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 
-#include <sound/driver.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
index 145ad13d52d1cd5d504a55ec45cedc490718d400..b2a11b0d2e4c3b9cb6eb17c1dee1ec1743aec48a 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/device.h>
 #include <linux/delay.h>
 
-#include <sound/driver.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
index 1a70a6ac98ced1a2a9a5830e7a5678df8bea7b36..7f32a1167572c7cf67171a0468f0174cfb4da682 100644 (file)
@@ -297,21 +297,19 @@ static int corgi_wm8731_init(struct snd_soc_codec *codec)
        /* Add corgi specific controls */
        for (i = 0; i < ARRAY_SIZE(wm8731_corgi_controls); i++) {
                err = snd_ctl_add(codec->card,
-                       snd_soc_cnew(&wm8731_corgi_controls[i],codec, NULL));
+                       snd_soc_cnew(&wm8731_corgi_controls[i], codec, NULL));
                if (err < 0)
                        return err;
        }
 
        /* Add corgi specific widgets */
-       for(i = 0; i < ARRAY_SIZE(wm8731_dapm_widgets); i++) {
+       for (i = 0; i < ARRAY_SIZE(wm8731_dapm_widgets); i++)
                snd_soc_dapm_new_control(codec, &wm8731_dapm_widgets[i]);
-       }
 
        /* Set up corgi specific audio path audio_map */
-       for(i = 0; audio_map[i][0] != NULL; i++) {
+       for (i = 0; audio_map[i][0] != NULL; i++)
                snd_soc_dapm_connect_input(codec, audio_map[i][0],
                        audio_map[i][1], audio_map[i][2]);
-       }
 
        snd_soc_dapm_sync_endpoints(codec);
        return 0;
@@ -353,7 +351,8 @@ static int __init corgi_init(void)
 {
        int ret;
 
-       if (!(machine_is_corgi() || machine_is_shepherd() || machine_is_husky()))
+       if (!(machine_is_corgi() || machine_is_shepherd() ||
+             machine_is_husky()))
                return -ENODEV;
 
        corgi_snd_device = platform_device_alloc("soc-audio", -1);
index 4fbf8bba9627322cd628fb8d21d545ebe608c658..7e830b218943e90090cebddbedd4cc6ec511bba8 100644 (file)
@@ -257,21 +257,19 @@ static int poodle_wm8731_init(struct snd_soc_codec *codec)
        /* Add poodle specific controls */
        for (i = 0; i < ARRAY_SIZE(wm8731_poodle_controls); i++) {
                err = snd_ctl_add(codec->card,
-                       snd_soc_cnew(&wm8731_poodle_controls[i],codec, NULL));
+                       snd_soc_cnew(&wm8731_poodle_controls[i], codec, NULL));
                if (err < 0)
                        return err;
        }
 
        /* Add poodle specific widgets */
-       for (i = 0; i < ARRAY_SIZE(wm8731_dapm_widgets); i++) {
+       for (i = 0; i < ARRAY_SIZE(wm8731_dapm_widgets); i++)
                snd_soc_dapm_new_control(codec, &wm8731_dapm_widgets[i]);
-       }
 
        /* Set up poodle specific audio path audio_map */
-       for (i = 0; audio_map[i][0] != NULL; i++) {
+       for (i = 0; audio_map[i][0] != NULL; i++)
                snd_soc_dapm_connect_input(codec, audio_map[i][0],
                        audio_map[i][1], audio_map[i][2]);
-       }
 
        snd_soc_dapm_sync_endpoints(codec);
        return 0;
index e17379998802cf82c457062fdbf692a872e7eb24..97ec2d90547c30e64a177f9f250168d02073d6c0 100644 (file)
@@ -61,7 +61,7 @@ static unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97,
        mutex_lock(&car_mutex);
 
        /* set up primary or secondary codec/modem space */
-#ifdef CONFIG_PXA27x
+#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
        reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE;
 #else
        if (reg == AC97_GPIO_STATUS)
@@ -87,7 +87,7 @@ static unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97,
        wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1);
        if (!((GSR | gsr_bits) & GSR_SDONE)) {
                printk(KERN_ERR "%s: read error (ac97_reg=%x GSR=%#lx)\n",
-                               __FUNCTION__, reg, GSR | gsr_bits);
+                               __func__, reg, GSR | gsr_bits);
                val = -1;
                goto out;
        }
@@ -111,7 +111,7 @@ static void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
        mutex_lock(&car_mutex);
 
        /* set up primary or secondary codec/modem space */
-#ifdef CONFIG_PXA27x
+#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
        reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE;
 #else
        if (reg == AC97_GPIO_STATUS)
@@ -127,13 +127,16 @@ static void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
        wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_CDONE, 1);
        if (!((GSR | gsr_bits) & GSR_CDONE))
                printk(KERN_ERR "%s: write error (ac97_reg=%x GSR=%#lx)\n",
-                               __FUNCTION__, reg, GSR | gsr_bits);
+                               __func__, reg, GSR | gsr_bits);
 
        mutex_unlock(&car_mutex);
 }
 
 static void pxa2xx_ac97_warm_reset(struct snd_ac97 *ac97)
 {
+#ifdef CONFIG_PXA3xx
+       int timeout = 100;
+#endif
        gsr_bits = 0;
 
 #ifdef CONFIG_PXA27x
@@ -144,6 +147,11 @@ static void pxa2xx_ac97_warm_reset(struct snd_ac97 *ac97)
        GCR |= GCR_WARM_RST;
        pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
        udelay(500);
+#elif defined(CONFIG_PXA3xx)
+       /* Can't use interrupts */
+       GCR |= GCR_WARM_RST;
+       while (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)) && timeout--)
+               mdelay(1);
 #else
        GCR |= GCR_WARM_RST | GCR_PRIRDY_IEN | GCR_SECRDY_IEN;
        wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1);
@@ -151,7 +159,7 @@ static void pxa2xx_ac97_warm_reset(struct snd_ac97 *ac97)
 
        if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)))
                printk(KERN_INFO "%s: warm reset timeout (GSR=%#lx)\n",
-                                __FUNCTION__, gsr_bits);
+                                __func__, gsr_bits);
 
        GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);
        GCR |= GCR_SDONE_IE|GCR_CDONE_IE;
@@ -159,6 +167,16 @@ static void pxa2xx_ac97_warm_reset(struct snd_ac97 *ac97)
 
 static void pxa2xx_ac97_cold_reset(struct snd_ac97 *ac97)
 {
+#ifdef CONFIG_PXA3xx
+       int timeout = 1000;
+
+       /* Hold CLKBPB for 100us */
+       GCR = 0;
+       GCR = GCR_CLKBPB;
+       udelay(100);
+       GCR = 0;
+#endif
+
        GCR &=  GCR_COLD_RST;  /* clear everything but nCRST */
        GCR &= ~GCR_COLD_RST;  /* then assert nCRST */
 
@@ -170,6 +188,13 @@ static void pxa2xx_ac97_cold_reset(struct snd_ac97 *ac97)
        clk_disable(ac97conf_clk);
        GCR = GCR_COLD_RST;
        udelay(50);
+#elif defined(CONFIG_PXA3xx)
+       /* Can't use interrupts on PXA3xx */
+       GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);
+
+       GCR = GCR_WARM_RST | GCR_COLD_RST;
+       while (!(GSR & (GSR_PCR | GSR_SCR)) && timeout--)
+               mdelay(10);
 #else
        GCR = GCR_COLD_RST;
        GCR |= GCR_CDONE_IE|GCR_SDONE_IE;
@@ -178,7 +203,7 @@ static void pxa2xx_ac97_cold_reset(struct snd_ac97 *ac97)
 
        if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)))
                printk(KERN_INFO "%s: cold reset timeout (GSR=%#lx)\n",
-                                __FUNCTION__, gsr_bits);
+                                __func__, gsr_bits);
 
        GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);
        GCR |= GCR_SDONE_IE|GCR_CDONE_IE;
index daeaa4c8b876fc72b5441f0c662b220b1945081b..01ad7bf716b7b03f95f99157cabece01d16d67bd 100644 (file)
@@ -64,8 +64,8 @@ static void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id)
        if (dcsr & DCSR_ENDINTR) {
                snd_pcm_period_elapsed(substream);
        } else {
-               printk( KERN_ERR "%s: DMA error on channel %d (DCSR=%#x)\n",
-                       prtd->params->name, dma_ch, dcsr );
+               printk(KERN_ERR "%s: DMA error on channel %d (DCSR=%#x)\n",
+                       prtd->params->name, dma_ch, dcsr);
        }
 }
 
@@ -84,8 +84,8 @@ static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
 
        /* return if this is a bufferless transfer e.g.
         * codec <--> BT codec or GSM modem -- lg FIXME */
-        if (!dma)
-               return 0;
+       if (!dma)
+               return 0;
 
        /* this may get called several times by oss emulation
         * with different params */
@@ -363,7 +363,6 @@ struct snd_soc_platform pxa2xx_soc_platform = {
        .pcm_new        = pxa2xx_pcm_new,
        .pcm_free       = pxa2xx_pcm_free_dma_buffers,
 };
-
 EXPORT_SYMBOL_GPL(pxa2xx_soc_platform);
 
 MODULE_AUTHOR("Nicolas Pitre");
index ecca39033fcceff2ae449cec9c48ab3f17f3061f..d8b8372db00e76c9412364867025628f3b8d957e 100644 (file)
@@ -313,15 +313,13 @@ static int spitz_wm8750_init(struct snd_soc_codec *codec)
        }
 
        /* Add spitz specific widgets */
-       for (i = 0; i < ARRAY_SIZE(wm8750_dapm_widgets); i++) {
+       for (i = 0; i < ARRAY_SIZE(wm8750_dapm_widgets); i++)
                snd_soc_dapm_new_control(codec, &wm8750_dapm_widgets[i]);
-       }
 
        /* Set up spitz specific audio path audio_map */
-       for (i = 0; audio_map[i][0] != NULL; i++) {
+       for (i = 0; audio_map[i][0] != NULL; i++)
                snd_soc_dapm_connect_input(codec, audio_map[i][0],
                        audio_map[i][1], audio_map[i][2]);
-       }
 
        snd_soc_dapm_sync_endpoints(codec);
        return 0;
index 6ee115ceb011d22e207c5f33e43803d6a824f714..962cc20b1af5976e0ee109ca7072c05de240903c 100644 (file)
@@ -659,6 +659,7 @@ static int __init neo1973_init(void)
 
 static void __exit neo1973_exit(void)
 {
+       i2c_del_driver(&lm4857_i2c_driver);
        platform_device_unregister(neo1973_snd_device);
 }
 
index 0a3c630951bee11833fd349195f6a90e0cc8951b..4ebcd6a8bf2867d1963ba29deab52b98d2987e38 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/delay.h>
 #include <linux/clk.h>
 #include <linux/jiffies.h>
+#include <linux/io.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -32,7 +33,6 @@
 #include <sound/soc.h>
 
 #include <asm/hardware.h>
-#include <asm/io.h>
 #include <asm/arch/regs-gpio.h>
 #include <asm/arch/regs-clock.h>
 #include <asm/arch/audio.h>
@@ -46,7 +46,7 @@
 
 #define S3C24XX_I2S_DEBUG 0
 #if S3C24XX_I2S_DEBUG
-#define DBG(x...) printk(KERN_DEBUG x)
+#define DBG(x...) printk(KERN_DEBUG "s3c24xx-i2s: " x)
 #else
 #define DBG(x...)
 #endif
@@ -89,7 +89,7 @@ static void s3c24xx_snd_txctrl(int on)
        u32 iiscon;
        u32 iismod;
 
-       DBG("Entered %s\n", __FUNCTION__);
+       DBG("Entered %s\n", __func__);
 
        iisfcon = readl(s3c24xx_i2s.regs + S3C2410_IISFCON);
        iiscon  = readl(s3c24xx_i2s.regs + S3C2410_IISCON);
@@ -134,7 +134,7 @@ static void s3c24xx_snd_rxctrl(int on)
        u32 iiscon;
        u32 iismod;
 
-       DBG("Entered %s\n", __FUNCTION__);
+       DBG("Entered %s\n", __func__);
 
        iisfcon = readl(s3c24xx_i2s.regs + S3C2410_IISFCON);
        iiscon  = readl(s3c24xx_i2s.regs + S3C2410_IISCON);
@@ -159,10 +159,10 @@ static void s3c24xx_snd_rxctrl(int on)
                 * DMA engine will simply freeze randomly.
                 */
 
-        iisfcon &= ~S3C2410_IISFCON_RXENABLE;
-        iisfcon &= ~S3C2410_IISFCON_RXDMA;
-        iiscon  |= S3C2410_IISCON_RXIDLE;
-        iiscon  &= ~S3C2410_IISCON_RXDMAEN;
+               iisfcon &= ~S3C2410_IISFCON_RXENABLE;
+               iisfcon &= ~S3C2410_IISFCON_RXDMA;
+               iiscon  |= S3C2410_IISCON_RXIDLE;
+               iiscon  &= ~S3C2410_IISCON_RXDMAEN;
                iismod  &= ~S3C2410_IISMOD_RXMODE;
 
                writel(iisfcon, s3c24xx_i2s.regs + S3C2410_IISFCON);
@@ -182,7 +182,7 @@ static int s3c24xx_snd_lrsync(void)
        u32 iiscon;
        unsigned long timeout = jiffies + msecs_to_jiffies(5);
 
-       DBG("Entered %s\n", __FUNCTION__);
+       DBG("Entered %s\n", __func__);
 
        while (1) {
                iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON);
@@ -201,7 +201,7 @@ static int s3c24xx_snd_lrsync(void)
  */
 static inline int s3c24xx_snd_is_clkmaster(void)
 {
-       DBG("Entered %s\n", __FUNCTION__);
+       DBG("Entered %s\n", __func__);
 
        return (readl(s3c24xx_i2s.regs + S3C2410_IISMOD) & S3C2410_IISMOD_SLAVE) ? 0:1;
 }
@@ -214,7 +214,7 @@ static int s3c24xx_i2s_set_fmt(struct snd_soc_cpu_dai *cpu_dai,
 {
        u32 iismod;
 
-       DBG("Entered %s\n", __FUNCTION__);
+       DBG("Entered %s\n", __func__);
 
        iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD);
        DBG("hw_params r: IISMOD: %lx \n", iismod);
@@ -250,7 +250,7 @@ static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream,
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        u32 iismod;
 
-       DBG("Entered %s\n", __FUNCTION__);
+       DBG("Entered %s\n", __func__);
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
                rtd->dai->cpu_dai->dma_data = &s3c24xx_i2s_pcm_stereo_out;
@@ -278,7 +278,7 @@ static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd)
 {
        int ret = 0;
 
-       DBG("Entered %s\n", __FUNCTION__);
+       DBG("Entered %s\n", __func__);
 
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
@@ -320,7 +320,7 @@ static int s3c24xx_i2s_set_sysclk(struct snd_soc_cpu_dai *cpu_dai,
 {
        u32 iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD);
 
-       DBG("Entered %s\n", __FUNCTION__);
+       DBG("Entered %s\n", __func__);
 
        iismod &= ~S3C2440_IISMOD_MPLL;
 
@@ -346,7 +346,7 @@ static int s3c24xx_i2s_set_clkdiv(struct snd_soc_cpu_dai *cpu_dai,
 {
        u32 reg;
 
-       DBG("Entered %s\n", __FUNCTION__);
+       DBG("Entered %s\n", __func__);
 
        switch (div_id) {
        case S3C24XX_DIV_BCLK:
@@ -381,13 +381,13 @@ EXPORT_SYMBOL_GPL(s3c24xx_i2s_get_clockrate);
 
 static int s3c24xx_i2s_probe(struct platform_device *pdev)
 {
-       DBG("Entered %s\n", __FUNCTION__);
+       DBG("Entered %s\n", __func__);
 
        s3c24xx_i2s.regs = ioremap(S3C2410_PA_IIS, 0x100);
        if (s3c24xx_i2s.regs == NULL)
                return -ENXIO;
 
-       s3c24xx_i2s.iis_clk=clk_get(&pdev->dev, "iis");
+       s3c24xx_i2s.iis_clk = clk_get(&pdev->dev, "iis");
        if (s3c24xx_i2s.iis_clk == NULL) {
                DBG("failed to get iis_clock\n");
                iounmap(s3c24xx_i2s.regs);
@@ -411,9 +411,11 @@ static int s3c24xx_i2s_probe(struct platform_device *pdev)
 }
 
 #ifdef CONFIG_PM
-int s3c24xx_i2s_suspend(struct platform_device *pdev,
+static int s3c24xx_i2s_suspend(struct platform_device *pdev,
                struct snd_soc_cpu_dai *cpu_dai)
 {
+       DBG("Entered %s\n", __func__);
+
        s3c24xx_i2s.iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON);
        s3c24xx_i2s.iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD);
        s3c24xx_i2s.iisfcon = readl(s3c24xx_i2s.regs + S3C2410_IISFCON);
@@ -424,9 +426,10 @@ int s3c24xx_i2s_suspend(struct platform_device *pdev,
        return 0;
 }
 
-int s3c24xx_i2s_resume(struct platform_device *pdev,
+static int s3c24xx_i2s_resume(struct platform_device *pdev,
                struct snd_soc_cpu_dai *cpu_dai)
 {
+       DBG("Entered %s\n", __func__);
        clk_enable(s3c24xx_i2s.iis_clk);
 
        writel(s3c24xx_i2s.iiscon, s3c24xx_i2s.regs + S3C2410_IISCON);
index 29a6c82f873ac7c5f50def0470ef4d44e6fb5222..49580fb481d5d55916a92dc721b0cad96a4987aa 100644 (file)
@@ -39,7 +39,7 @@
 
 #define S3C24XX_PCM_DEBUG 0
 #if S3C24XX_PCM_DEBUG
-#define DBG(x...) printk(KERN_DEBUG x)
+#define DBG(x...) printk(KERN_DEBUG "s3c24xx-pcm: " x)
 #else
 #define DBG(x...)
 #endif
@@ -88,7 +88,7 @@ static void s3c24xx_pcm_enqueue(struct snd_pcm_substream *substream)
        dma_addr_t pos = prtd->dma_pos;
        int ret;
 
-       DBG("Entered %s\n", __FUNCTION__);
+       DBG("Entered %s\n", __func__);
 
        while (prtd->dma_loaded < prtd->dma_limit) {
                unsigned long len = prtd->dma_period;
@@ -98,7 +98,7 @@ static void s3c24xx_pcm_enqueue(struct snd_pcm_substream *substream)
                if ((pos + len) > prtd->dma_end) {
                        len  = prtd->dma_end - pos;
                        DBG(KERN_DEBUG "%s: corrected dma len %ld\n",
-                              __FUNCTION__, len);
+                              __func__, len);
                }
 
                ret = s3c2410_dma_enqueue(prtd->params->channel, 
@@ -123,7 +123,7 @@ static void s3c24xx_audio_buffdone(struct s3c2410_dma_chan *channel,
        struct snd_pcm_substream *substream = dev_id;
        struct s3c24xx_runtime_data *prtd;
 
-       DBG("Entered %s\n", __FUNCTION__);
+       DBG("Entered %s\n", __func__);
 
        if (result == S3C2410_RES_ABORT || result == S3C2410_RES_ERR)
                return;
@@ -152,7 +152,7 @@ static int s3c24xx_pcm_hw_params(struct snd_pcm_substream *substream,
        unsigned long totbytes = params_buffer_bytes(params);
        int ret=0;
 
-       DBG("Entered %s\n", __FUNCTION__);
+       DBG("Entered %s\n", __func__);
 
        /* return if this is a bufferless transfer e.g.
         * codec <--> BT codec or GSM modem -- lg FIXME */
@@ -200,7 +200,7 @@ static int s3c24xx_pcm_hw_free(struct snd_pcm_substream *substream)
 {
        struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;
 
-       DBG("Entered %s\n", __FUNCTION__);
+       DBG("Entered %s\n", __func__);
 
        /* TODO - do we need to ensure DMA flushed */
        snd_pcm_set_runtime_buffer(substream, NULL);
@@ -218,7 +218,7 @@ static int s3c24xx_pcm_prepare(struct snd_pcm_substream *substream)
        struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;
        int ret = 0;
 
-       DBG("Entered %s\n", __FUNCTION__);
+       DBG("Entered %s\n", __func__);
 
        /* return if this is a bufferless transfer e.g.
         * codec <--> BT codec or GSM modem -- lg FIXME */
@@ -263,7 +263,7 @@ static int s3c24xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
        struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;
        int ret = 0;
 
-       DBG("Entered %s\n", __FUNCTION__);
+       DBG("Entered %s\n", __func__);
 
        spin_lock(&prtd->lock);
 
@@ -301,7 +301,7 @@ static snd_pcm_uframes_t
        unsigned long res;
        dma_addr_t src, dst;
 
-       DBG("Entered %s\n", __FUNCTION__);
+       DBG("Entered %s\n", __func__);
 
        spin_lock(&prtd->lock);
        s3c2410_dma_getposition(prtd->params->channel, &src, &dst);
@@ -334,7 +334,7 @@ static int s3c24xx_pcm_open(struct snd_pcm_substream *substream)
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct s3c24xx_runtime_data *prtd;
 
-       DBG("Entered %s\n", __FUNCTION__);
+       DBG("Entered %s\n", __func__);
 
        snd_soc_set_runtime_hwparams(substream, &s3c24xx_pcm_hardware);
 
@@ -353,7 +353,7 @@ static int s3c24xx_pcm_close(struct snd_pcm_substream *substream)
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct s3c24xx_runtime_data *prtd = runtime->private_data;
 
-       DBG("Entered %s\n", __FUNCTION__);
+       DBG("Entered %s\n", __func__);
 
        if (prtd)
                kfree(prtd);
@@ -368,7 +368,7 @@ static int s3c24xx_pcm_mmap(struct snd_pcm_substream *substream,
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
 
-       DBG("Entered %s\n", __FUNCTION__);
+       DBG("Entered %s\n", __func__);
 
        return dma_mmap_writecombine(substream->pcm->card->dev, vma,
                                      runtime->dma_area,
@@ -394,7 +394,7 @@ static int s3c24xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
        struct snd_dma_buffer *buf = &substream->dma_buffer;
        size_t size = s3c24xx_pcm_hardware.buffer_bytes_max;
 
-       DBG("Entered %s\n", __FUNCTION__);
+       DBG("Entered %s\n", __func__);
 
        buf->dev.type = SNDRV_DMA_TYPE_DEV;
        buf->dev.dev = pcm->card->dev;
@@ -413,7 +413,7 @@ static void s3c24xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
        struct snd_dma_buffer *buf;
        int stream;
 
-       DBG("Entered %s\n", __FUNCTION__);
+       DBG("Entered %s\n", __func__);
 
        for (stream = 0; stream < 2; stream++) {
                substream = pcm->streams[stream].substream;
@@ -437,7 +437,7 @@ static int s3c24xx_pcm_new(struct snd_card *card,
 {
        int ret = 0;
 
-       DBG("Entered %s\n", __FUNCTION__);
+       DBG("Entered %s\n", __func__);
 
        if (!card->dev->dma_mask)
                card->dev->dma_mask = &s3c24xx_pcm_dmamask;
index f03220d23e73aa222b0172838958629a2b442ecc..4c1e013381c9dbc1f7a70a38527f302334db1d34 100644 (file)
@@ -1,4 +1,5 @@
 menu "SoC Audio support for SuperH"
+       depends on SUPERH
 
 config SND_SOC_PCM_SH7760
        tristate "SoC Audio support for Renesas SH7760"
index 9eb5479787c1d32203b17c1a037750a961c11f17..e148db940cfc77ecb4521df7191909f00e672761 100644 (file)
@@ -839,6 +839,7 @@ static int soc_remove(struct platform_device *pdev)
 static struct platform_driver soc_driver = {
        .driver         = {
                .name           = "soc-audio",
+               .owner          = THIS_MODULE,
        },
        .probe          = soc_probe,
        .remove         = soc_remove,
@@ -1601,3 +1602,4 @@ module_exit(snd_soc_exit);
 MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com");
 MODULE_DESCRIPTION("ALSA SoC Core");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:soc-audio");
index 620d7ea3c15ff56a10aba1e9402c98aa2c6940c8..af3326c635041da0c852ecc0ca11ea91212484f1 100644 (file)
@@ -226,7 +226,7 @@ static int dapm_update_bits(struct snd_soc_dapm_widget *widget)
                snd_soc_write(codec, widget->reg, new);
                pop_wait(POP_TIME);
        }
-       dbg("reg old %x new %x change %d\n", old, new, change);
+       dbg("reg %x old %x new %x change %d\n", widget->reg, old, new, change);
        return change;
 }
 
@@ -1288,7 +1288,7 @@ int snd_soc_dapm_stream_event(struct snd_soc_codec *codec,
        mutex_unlock(&codec->mutex);
 
        dapm_power_widgets(codec, event);
-       dump_dapm(codec, __FUNCTION__);
+       dump_dapm(codec, __func__);
        return 0;
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_stream_event);
@@ -1334,10 +1334,11 @@ int snd_soc_dapm_set_endpoint(struct snd_soc_codec *codec,
        list_for_each_entry(w, &codec->dapm_widgets, list) {
                if (!strcmp(w->name, endpoint)) {
                        w->connected = status;
+                       return 0;
                }
        }
 
-       return 0;
+       return -ENODEV;
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_set_endpoint);
 
index 89d6e9c351405c8d186176d7b80454d24153ad24..09802e8a6fb834419f8c752ac8edb7c68405de88 100644 (file)
@@ -118,7 +118,7 @@ static struct snd_pcm_hardware snd_at73c213_playback_hw = {
        .rates          = SNDRV_PCM_RATE_CONTINUOUS,
        .rate_min       = 8000,  /* Replaced by chip->bitrate later. */
        .rate_max       = 50000, /* Replaced by chip->bitrate later. */
-       .channels_min   = 2,
+       .channels_min   = 1,
        .channels_max   = 2,
        .buffer_bytes_max = 64 * 1024 - 1,
        .period_bytes_min = 512,
@@ -133,7 +133,8 @@ static struct snd_pcm_hardware snd_at73c213_playback_hw = {
 static int snd_at73c213_set_bitrate(struct snd_at73c213 *chip)
 {
        unsigned long ssc_rate = clk_get_rate(chip->ssc->clk);
-       unsigned long dac_rate_new, ssc_div, status;
+       unsigned long dac_rate_new, ssc_div;
+       int status;
        unsigned long ssc_div_max, ssc_div_min;
        int max_tries;
 
@@ -209,7 +210,13 @@ static int snd_at73c213_pcm_open(struct snd_pcm_substream *substream)
 {
        struct snd_at73c213 *chip = snd_pcm_substream_chip(substream);
        struct snd_pcm_runtime *runtime = substream->runtime;
+       int err;
 
+       /* ensure buffer_size is a multiple of period_size */
+       err = snd_pcm_hw_constraint_integer(runtime,
+                                       SNDRV_PCM_HW_PARAM_PERIODS);
+       if (err < 0)
+               return err;
        snd_at73c213_playback_hw.rate_min = chip->bitrate;
        snd_at73c213_playback_hw.rate_max = chip->bitrate;
        runtime->hw = snd_at73c213_playback_hw;
@@ -228,6 +235,14 @@ static int snd_at73c213_pcm_close(struct snd_pcm_substream *substream)
 static int snd_at73c213_pcm_hw_params(struct snd_pcm_substream *substream,
                                 struct snd_pcm_hw_params *hw_params)
 {
+       struct snd_at73c213 *chip = snd_pcm_substream_chip(substream);
+       int channels = params_channels(hw_params);
+       int val;
+
+       val = ssc_readl(chip->ssc->regs, TFMR);
+       val = SSC_BFINS(TFMR_DATNB, channels - 1, val);
+       ssc_writel(chip->ssc->regs, TFMR, val);
+
        return snd_pcm_lib_malloc_pages(substream,
                                        params_buffer_bytes(hw_params));
 }
@@ -249,10 +264,12 @@ static int snd_at73c213_pcm_prepare(struct snd_pcm_substream *substream)
 
        ssc_writel(chip->ssc->regs, PDC_TPR,
                        (long)runtime->dma_addr);
-       ssc_writel(chip->ssc->regs, PDC_TCR, runtime->period_size * 2);
+       ssc_writel(chip->ssc->regs, PDC_TCR,
+                       runtime->period_size * runtime->channels);
        ssc_writel(chip->ssc->regs, PDC_TNPR,
                        (long)runtime->dma_addr + block_size);
-       ssc_writel(chip->ssc->regs, PDC_TNCR, runtime->period_size * 2);
+       ssc_writel(chip->ssc->regs, PDC_TNCR,
+                       runtime->period_size * runtime->channels);
 
        return 0;
 }
@@ -314,15 +331,6 @@ static struct snd_pcm_ops at73c213_playback_ops = {
        .pointer        = snd_at73c213_pcm_pointer,
 };
 
-static void snd_at73c213_pcm_free(struct snd_pcm *pcm)
-{
-       struct snd_at73c213 *chip = snd_pcm_chip(pcm);
-       if (chip->pcm) {
-               snd_pcm_lib_preallocate_free_for_all(chip->pcm);
-               chip->pcm = NULL;
-       }
-}
-
 static int __devinit snd_at73c213_pcm_new(struct snd_at73c213 *chip, int device)
 {
        struct snd_pcm *pcm;
@@ -334,7 +342,6 @@ static int __devinit snd_at73c213_pcm_new(struct snd_at73c213 *chip, int device)
                goto out;
 
        pcm->private_data = chip;
-       pcm->private_free = snd_at73c213_pcm_free;
        pcm->info_flags = SNDRV_PCM_INFO_BLOCK_TRANSFER;
        strcpy(pcm->name, "at73c213");
        chip->pcm = pcm;
@@ -375,7 +382,8 @@ static irqreturn_t snd_at73c213_interrupt(int irq, void *dev_id)
 
                ssc_writel(chip->ssc->regs, PDC_TNPR,
                                (long)runtime->dma_addr + offset);
-               ssc_writel(chip->ssc->regs, PDC_TNCR, runtime->period_size * 2);
+               ssc_writel(chip->ssc->regs, PDC_TNCR,
+                               runtime->period_size * runtime->channels);
                retval = IRQ_HANDLED;
        }
 
@@ -737,7 +745,7 @@ cleanup:
 /*
  * Device functions
  */
-static int snd_at73c213_ssc_init(struct snd_at73c213 *chip)
+static int __devinit snd_at73c213_ssc_init(struct snd_at73c213 *chip)
 {
        /*
         * Continuous clock output.
@@ -767,7 +775,7 @@ static int snd_at73c213_ssc_init(struct snd_at73c213 *chip)
        return 0;
 }
 
-static int snd_at73c213_chip_init(struct snd_at73c213 *chip)
+static int __devinit snd_at73c213_chip_init(struct snd_at73c213 *chip)
 {
        int retval;
        unsigned char dac_ctrl = 0;
@@ -933,7 +941,7 @@ out:
        return retval;
 }
 
-static int snd_at73c213_probe(struct spi_device *spi)
+static int __devinit snd_at73c213_probe(struct spi_device *spi)
 {
        struct snd_card                 *card;
        struct snd_at73c213             *chip;
index 9cc4cd8283f91561d744641b0afbead6e8b0495a..24970a5c888f6e2f26453712a3b12cfd544b5355 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *   Copyright (c) 2006,2007 Daniel Mack, Karsten Wiese
+ *   Copyright (c) 2006-2008 Daniel Mack, Karsten Wiese
  *
  *   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
@@ -39,7 +39,8 @@
 #define BYTES_PER_SAMPLE       3
 #define BYTES_PER_SAMPLE_USB   4
 #define MAX_BUFFER_SIZE                (128*1024)
-                                
+#define MAX_ENDPOINT_SIZE      512
+
 #define ENDPOINT_CAPTURE       2
 #define ENDPOINT_PLAYBACK      6
 
@@ -77,10 +78,15 @@ static void
 deactivate_substream(struct snd_usb_caiaqdev *dev,
                     struct snd_pcm_substream *sub)
 {
+       unsigned long flags;
+       spin_lock_irqsave(&dev->spinlock, flags);
+
        if (sub->stream == SNDRV_PCM_STREAM_PLAYBACK)
                dev->sub_playback[sub->number] = NULL;
        else
                dev->sub_capture[sub->number] = NULL;
+
+       spin_unlock_irqrestore(&dev->spinlock, flags);
 }
 
 static int
@@ -97,13 +103,13 @@ static int stream_start(struct snd_usb_caiaqdev *dev)
 {
        int i, ret;
 
-       debug("stream_start(%p)\n", dev);
-       spin_lock_irq(&dev->spinlock);
-       if (dev->streaming) {
-               spin_unlock_irq(&dev->spinlock);
+       debug("%s(%p)\n", __func__, dev);
+
+       if (dev->streaming)
                return -EINVAL;
-       }
 
+       memset(dev->sub_playback, 0, sizeof(dev->sub_playback));
+       memset(dev->sub_capture, 0, sizeof(dev->sub_capture));
        dev->input_panic = 0;
        dev->output_panic = 0;
        dev->first_packet = 1;
@@ -112,37 +118,35 @@ static int stream_start(struct snd_usb_caiaqdev *dev)
        for (i = 0; i < N_URBS; i++) {
                ret = usb_submit_urb(dev->data_urbs_in[i], GFP_ATOMIC);
                if (ret) {
-                       log("unable to trigger initial read #%d! (ret = %d)\n",
-                               i, ret);
+                       log("unable to trigger read #%d! (ret %d)\n", i, ret);
                        dev->streaming = 0;
-                       spin_unlock_irq(&dev->spinlock);
                        return -EPIPE;
                }
        }
        
-       spin_unlock_irq(&dev->spinlock);
        return 0;
 }
 
 static void stream_stop(struct snd_usb_caiaqdev *dev)
 {
        int i;
-       
-       debug("stream_stop(%p)\n", dev);
+
+       debug("%s(%p)\n", __func__, dev);
        if (!dev->streaming)
                return;
        
        dev->streaming = 0;
+
        for (i = 0; i < N_URBS; i++) {
-               usb_unlink_urb(dev->data_urbs_in[i]);
-               usb_unlink_urb(dev->data_urbs_out[i]);
+               usb_kill_urb(dev->data_urbs_in[i]);
+               usb_kill_urb(dev->data_urbs_out[i]);
        }
 }
 
 static int snd_usb_caiaq_substream_open(struct snd_pcm_substream *substream)
 {
        struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(substream);
-       debug("snd_usb_caiaq_substream_open(%p)\n", substream);
+       debug("%s(%p)\n", __func__, substream);
        substream->runtime->hw = dev->pcm_info;
        snd_pcm_limit_hw_rates(substream->runtime);
        return 0;
@@ -152,7 +156,7 @@ static int snd_usb_caiaq_substream_close(struct snd_pcm_substream *substream)
 {
        struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(substream);
 
-       debug("snd_usb_caiaq_substream_close(%p)\n", substream);
+       debug("%s(%p)\n", __func__, substream);
        if (all_substreams_zero(dev->sub_playback) &&
            all_substreams_zero(dev->sub_capture)) {
                /* when the last client has stopped streaming, 
@@ -160,24 +164,22 @@ static int snd_usb_caiaq_substream_close(struct snd_pcm_substream *substream)
                stream_stop(dev);
                dev->pcm_info.rates = dev->samplerates;
        }
-       
+
        return 0;
 }
 
 static int snd_usb_caiaq_pcm_hw_params(struct snd_pcm_substream *sub,
                                        struct snd_pcm_hw_params *hw_params)
 {
-       debug("snd_usb_caiaq_pcm_hw_params(%p)\n", sub);
+       debug("%s(%p)\n", __func__, sub);
        return snd_pcm_lib_malloc_pages(sub, params_buffer_bytes(hw_params));
 }
 
 static int snd_usb_caiaq_pcm_hw_free(struct snd_pcm_substream *sub)
 {
        struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(sub);
-       debug("snd_usb_caiaq_pcm_hw_free(%p)\n", sub);
-       spin_lock_irq(&dev->spinlock);
+       debug("%s(%p)\n", __func__, sub);
        deactivate_substream(dev, sub);
-       spin_unlock_irq(&dev->spinlock);
        return snd_pcm_lib_free_pages(sub);
 }
 
@@ -196,12 +198,12 @@ static int snd_usb_caiaq_pcm_prepare(struct snd_pcm_substream *substream)
        struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(substream);
        struct snd_pcm_runtime *runtime = substream->runtime;
 
-       debug("snd_usb_caiaq_pcm_prepare(%p)\n", substream);
+       debug("%s(%p)\n", __func__, substream);
        
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
                dev->audio_out_buf_pos[index] = BYTES_PER_SAMPLE + 1;
        else
-               dev->audio_in_buf_pos[index] = 0;
+               dev->audio_in_buf_pos[index] = BYTES_PER_SAMPLE;
        
        if (dev->streaming)
                return 0;
@@ -220,7 +222,10 @@ static int snd_usb_caiaq_pcm_prepare(struct snd_pcm_substream *substream)
        
        bpp = ((runtime->rate / 8000) + CLOCK_DRIFT_TOLERANCE)
                * bytes_per_sample * CHANNELS_PER_STREAM * dev->n_streams;
-       
+
+       if (bpp > MAX_ENDPOINT_SIZE)
+               bpp = MAX_ENDPOINT_SIZE;
+
        ret = snd_usb_caiaq_set_audio_params(dev, runtime->rate,
                                             runtime->sample_bits, bpp);
        if (ret)
@@ -247,15 +252,11 @@ static int snd_usb_caiaq_pcm_trigger(struct snd_pcm_substream *sub, int cmd)
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-               spin_lock(&dev->spinlock);
                activate_substream(dev, sub);
-               spin_unlock(&dev->spinlock);
                break;
        case SNDRV_PCM_TRIGGER_STOP:
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-               spin_lock(&dev->spinlock);
                deactivate_substream(dev, sub);
-               spin_unlock(&dev->spinlock);
                break;
        default:
                return -EINVAL;
@@ -328,8 +329,6 @@ static void read_in_urb_mode0(struct snd_usb_caiaqdev *dev,
        if (all_substreams_zero(dev->sub_capture))
                return;
 
-       spin_lock(&dev->spinlock);
-       
        for (i = 0; i < iso->actual_length;) {
                for (stream = 0; stream < dev->n_streams; stream++, i++) {
                        sub = dev->sub_capture[stream];
@@ -345,8 +344,6 @@ static void read_in_urb_mode0(struct snd_usb_caiaqdev *dev,
                        }
                }
        }
-       
-       spin_unlock(&dev->spinlock);
 }
 
 static void read_in_urb_mode2(struct snd_usb_caiaqdev *dev,
@@ -358,8 +355,6 @@ static void read_in_urb_mode2(struct snd_usb_caiaqdev *dev,
        struct snd_pcm_substream *sub;
        int stream, i;
 
-       spin_lock(&dev->spinlock);
-       
        for (i = 0; i < iso->actual_length;) {
                if (i % (dev->n_streams * BYTES_PER_SAMPLE_USB) == 0) {
                        for (stream = 0; 
@@ -393,8 +388,6 @@ static void read_in_urb_mode2(struct snd_usb_caiaqdev *dev,
                        }
                }
        }
-
-       spin_unlock(&dev->spinlock);
 }
 
 static void read_in_urb(struct snd_usb_caiaqdev *dev,
@@ -418,8 +411,6 @@ static void read_in_urb(struct snd_usb_caiaqdev *dev,
                                dev->input_panic ? "(input)" : "",
                                dev->output_panic ? "(output)" : "");
        }
-
-       check_for_elapsed_periods(dev, dev->sub_capture);
 }
 
 static void fill_out_urb(struct snd_usb_caiaqdev *dev, 
@@ -429,8 +420,6 @@ static void fill_out_urb(struct snd_usb_caiaqdev *dev,
        unsigned char *usb_buf = urb->transfer_buffer + iso->offset;
        struct snd_pcm_substream *sub;
        int stream, i;
-
-       spin_lock(&dev->spinlock);
        
        for (i = 0; i < iso->length;) {
                for (stream = 0; stream < dev->n_streams; stream++, i++) {
@@ -456,9 +445,6 @@ static void fill_out_urb(struct snd_usb_caiaqdev *dev,
                    for (stream = 0; stream < dev->n_streams; stream++, i++)
                        usb_buf[i] = MAKE_CHECKBYTE(dev, stream, i);
        }
-
-       spin_unlock(&dev->spinlock);
-       check_for_elapsed_periods(dev, dev->sub_playback);
 }
 
 static void read_completed(struct urb *urb)
@@ -472,6 +458,7 @@ static void read_completed(struct urb *urb)
                return;
 
        dev = info->dev;
+
        if (!dev->streaming)
                return;
 
@@ -489,8 +476,12 @@ static void read_completed(struct urb *urb)
                out->iso_frame_desc[outframe].offset = BYTES_PER_FRAME * frame;
                
                if (len > 0) {
+                       spin_lock(&dev->spinlock);
                        fill_out_urb(dev, out, &out->iso_frame_desc[outframe]);
                        read_in_urb(dev, urb, &urb->iso_frame_desc[frame]);
+                       spin_unlock(&dev->spinlock);
+                       check_for_elapsed_periods(dev, dev->sub_playback);
+                       check_for_elapsed_periods(dev, dev->sub_capture);
                        send_it = 1;
                }
 
@@ -696,7 +687,7 @@ int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *dev)
 
 void snd_usb_caiaq_audio_free(struct snd_usb_caiaqdev *dev)
 {
-       debug("snd_usb_caiaq_audio_free (%p)\n", dev);
+       debug("%s(%p)\n", __func__, dev);
        stream_stop(dev);
        free_urbs(dev->data_urbs_in);
        free_urbs(dev->data_urbs_out);
index 7c44a2c7f96366d4e2eedbb408f6b6d5b8f360cb..e97d8b2ac16a052e83d41778afc26695d53eeec3 100644 (file)
@@ -42,7 +42,7 @@
 #endif
 
 MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
-MODULE_DESCRIPTION("caiaq USB audio, version 1.3.2");
+MODULE_DESCRIPTION("caiaq USB audio, version 1.3.6");
 MODULE_LICENSE("GPL");
 MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2},"
                         "{Native Instruments, RigKontrol3},"
@@ -456,7 +456,7 @@ static void snd_disconnect(struct usb_interface *intf)
        struct snd_usb_caiaqdev *dev;
        struct snd_card *card = dev_get_drvdata(&intf->dev);
 
-       debug("snd_disconnect(%p)\n", intf);
+       debug("%s(%p)\n", __func__, intf);
 
        if (!card)
                return;
index f48838a078cb718c050cb02dd71945be16eaa88c..410be4aff1baed739dac2d88fa178d58f640e993 100644 (file)
@@ -64,9 +64,10 @@ MODULE_SUPPORTED_DEVICE("{{Generic,USB Audio}}");
 
 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 vid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 }; /* Vendor ID for this card */
-static int pid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 }; /* Product ID for this card */
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */
+/* Vendor/product IDs for this card */
+static int vid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 };
+static int pid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 };
 static int nrpacks = 8;                /* max. number of packets per urb */
 static int async_unlink = 1;
 static int device_setup[SNDRV_CARDS]; /* device parameter for this card*/
@@ -687,7 +688,7 @@ static void snd_complete_urb(struct urb *urb)
        int err = 0;
 
        if ((subs->running && subs->ops.retire(subs, substream->runtime, urb)) ||
-           ! subs->running || /* can be stopped during retire callback */
+           !subs->running || /* can be stopped during retire callback */
            (err = subs->ops.prepare(subs, substream->runtime, urb)) < 0 ||
            (err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
                clear_bit(ctx->index, &subs->active_mask);
@@ -710,7 +711,7 @@ static void snd_complete_sync_urb(struct urb *urb)
        int err = 0;
 
        if ((subs->running && subs->ops.retire_sync(subs, substream->runtime, urb)) ||
-           ! subs->running || /* can be stopped during retire callback */
+           !subs->running || /* can be stopped during retire callback */
            (err = subs->ops.prepare_sync(subs, substream->runtime, urb)) < 0 ||
            (err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
                clear_bit(ctx->index + 16, &subs->active_mask);
@@ -740,7 +741,7 @@ static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs, size_t s
                vfree(runtime->dma_area);
        }
        runtime->dma_area = vmalloc(size);
-       if (! runtime->dma_area)
+       if (!runtime->dma_area)
                return -ENOMEM;
        runtime->dma_bytes = size;
        return 0;
@@ -772,12 +773,12 @@ static int deactivate_urbs(struct snd_usb_substream *subs, int force, int can_sl
 
        async = !can_sleep && async_unlink;
 
-       if (! async && in_interrupt())
+       if (!async && in_interrupt())
                return 0;
 
        for (i = 0; i < subs->nurbs; i++) {
                if (test_bit(i, &subs->active_mask)) {
-                       if (! test_and_set_bit(i, &subs->unlink_mask)) {
+                       if (!test_and_set_bit(i, &subs->unlink_mask)) {
                                struct urb *u = subs->dataurb[i].urb;
                                if (async)
                                        usb_unlink_urb(u);
@@ -789,7 +790,7 @@ static int deactivate_urbs(struct snd_usb_substream *subs, int force, int can_sl
        if (subs->syncpipe) {
                for (i = 0; i < SYNC_URBS; i++) {
                        if (test_bit(i+16, &subs->active_mask)) {
-                               if (! test_and_set_bit(i+16, &subs->unlink_mask)) {
+                               if (!test_and_set_bit(i+16, &subs->unlink_mask)) {
                                        struct urb *u = subs->syncurb[i].urb;
                                        if (async)
                                                usb_unlink_urb(u);
@@ -1137,12 +1138,12 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri
                if (subs->fmt_type == USB_FORMAT_TYPE_II)
                        u->packets++; /* for transfer delimiter */
                u->urb = usb_alloc_urb(u->packets, GFP_KERNEL);
-               if (! u->urb)
+               if (!u->urb)
                        goto out_of_memory;
                u->urb->transfer_buffer =
                        usb_buffer_alloc(subs->dev, u->buffer_size, GFP_KERNEL,
                                         &u->urb->transfer_dma);
-               if (! u->urb->transfer_buffer)
+               if (!u->urb->transfer_buffer)
                        goto out_of_memory;
                u->urb->pipe = subs->datapipe;
                u->urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
@@ -1155,7 +1156,7 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri
                /* allocate and initialize sync urbs */
                subs->syncbuf = usb_buffer_alloc(subs->dev, SYNC_URBS * 4,
                                                 GFP_KERNEL, &subs->sync_dma);
-               if (! subs->syncbuf)
+               if (!subs->syncbuf)
                        goto out_of_memory;
                for (i = 0; i < SYNC_URBS; i++) {
                        struct snd_urb_ctx *u = &subs->syncurb[i];
@@ -1163,7 +1164,7 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri
                        u->subs = subs;
                        u->packets = 1;
                        u->urb = usb_alloc_urb(1, GFP_KERNEL);
-                       if (! u->urb)
+                       if (!u->urb)
                                goto out_of_memory;
                        u->urb->transfer_buffer = subs->syncbuf + i * 4;
                        u->urb->transfer_dma = subs->sync_dma + i * 4;
@@ -1427,8 +1428,8 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
        subs->cur_audiofmt = fmt;
 
 #if 0
-       printk("setting done: format = %d, rate = %d, channels = %d\n",
-              fmt->format, fmt->rate, fmt->channels);
+       printk("setting done: format = %d, rate = %d..%d, channels = %d\n",
+              fmt->format, fmt->rate_min, fmt->rate_max, fmt->channels);
        printk("  datapipe = 0x%0x, syncpipe = 0x%0x\n",
               subs->datapipe, subs->syncpipe);
 #endif
@@ -1463,7 +1464,7 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
        rate = params_rate(hw_params);
        channels = params_channels(hw_params);
        fmt = find_format(subs, format, rate, channels);
-       if (! fmt) {
+       if (!fmt) {
                snd_printd(KERN_DEBUG "cannot set format: format = 0x%x, rate = %d, channels = %d\n",
                           format, rate, channels);
                return -EINVAL;
@@ -1584,7 +1585,7 @@ static int hw_check_valid_format(struct snd_pcm_hw_params *params, struct audiof
        struct snd_mask *fmts = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
 
        /* check the format */
-       if (! snd_mask_test(fmts, fp->format)) {
+       if (!snd_mask_test(fmts, fp->format)) {
                hwc_debug("   > check: no supported format %d\n", fp->format);
                return 0;
        }
@@ -1620,7 +1621,7 @@ static int hw_rule_rate(struct snd_pcm_hw_params *params,
        list_for_each(p, &subs->fmt_list) {
                struct audioformat *fp;
                fp = list_entry(p, struct audioformat, list);
-               if (! hw_check_valid_format(params, fp))
+               if (!hw_check_valid_format(params, fp))
                        continue;
                if (changed++) {
                        if (rmin > fp->rate_min)
@@ -1633,7 +1634,7 @@ static int hw_rule_rate(struct snd_pcm_hw_params *params,
                }
        }
 
-       if (! changed) {
+       if (!changed) {
                hwc_debug("  --> get empty\n");
                it->empty = 1;
                return -EINVAL;
@@ -1674,7 +1675,7 @@ static int hw_rule_channels(struct snd_pcm_hw_params *params,
        list_for_each(p, &subs->fmt_list) {
                struct audioformat *fp;
                fp = list_entry(p, struct audioformat, list);
-               if (! hw_check_valid_format(params, fp))
+               if (!hw_check_valid_format(params, fp))
                        continue;
                if (changed++) {
                        if (rmin > fp->channels)
@@ -1687,7 +1688,7 @@ static int hw_rule_channels(struct snd_pcm_hw_params *params,
                }
        }
 
-       if (! changed) {
+       if (!changed) {
                hwc_debug("  --> get empty\n");
                it->empty = 1;
                return -EINVAL;
@@ -1727,7 +1728,7 @@ static int hw_rule_format(struct snd_pcm_hw_params *params,
        list_for_each(p, &subs->fmt_list) {
                struct audioformat *fp;
                fp = list_entry(p, struct audioformat, list);
-               if (! hw_check_valid_format(params, fp))
+               if (!hw_check_valid_format(params, fp))
                        continue;
                fbits |= (1ULL << fp->format);
        }
@@ -1736,7 +1737,7 @@ static int hw_rule_format(struct snd_pcm_hw_params *params,
        oldbits[1] = fmt->bits[1];
        fmt->bits[0] &= (u32)fbits;
        fmt->bits[1] &= (u32)(fbits >> 32);
-       if (! fmt->bits[0] && ! fmt->bits[1]) {
+       if (!fmt->bits[0] && !fmt->bits[1]) {
                hwc_debug("  --> get empty\n");
                return -EINVAL;
        }
@@ -1762,8 +1763,10 @@ static int check_hw_params_convention(struct snd_usb_substream *subs)
 
        channels = kcalloc(MAX_MASK, sizeof(u32), GFP_KERNEL);
        rates = kcalloc(MAX_MASK, sizeof(u32), GFP_KERNEL);
-       if (!channels || !rates)
+       if (!channels || !rates) {
+               err = -ENOMEM;
                goto __out;
+       }
 
        list_for_each(p, &subs->fmt_list) {
                struct audioformat *f;
@@ -1916,7 +1919,10 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
                                     1000 * MIN_PACKS_URB,
                                     /*(nrpacks * MAX_URBS) * 1000*/ UINT_MAX);
 
-       if (check_hw_params_convention(subs)) {
+       err = check_hw_params_convention(subs);
+       if (err < 0)
+               return err;
+       else if (err) {
                hwc_debug("setting extra hw constraints...\n");
                if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
                                               hw_rule_rate, subs,
@@ -2222,7 +2228,7 @@ static void proc_pcm_format_add(struct snd_usb_stream *stream)
        struct snd_card *card = stream->chip->card;
 
        sprintf(name, "stream%d", stream->pcm_index);
-       if (! snd_card_proc_new(card, name, &entry))
+       if (!snd_card_proc_new(card, name, &entry))
                snd_info_set_text_ops(entry, stream, proc_pcm_format_read);
 }
 
@@ -2278,7 +2284,7 @@ static void free_substream(struct snd_usb_substream *subs)
 {
        struct list_head *p, *n;
 
-       if (! subs->num_formats)
+       if (!subs->num_formats)
                return; /* not initialized */
        list_for_each_safe(p, n, &subs->fmt_list) {
                struct audioformat *fp = list_entry(p, struct audioformat, list);
@@ -2328,7 +2334,7 @@ static int add_audio_endpoint(struct snd_usb_audio *chip, int stream, struct aud
                if (as->fmt_type != fp->fmt_type)
                        continue;
                subs = &as->substream[stream];
-               if (! subs->endpoint)
+               if (!subs->endpoint)
                        continue;
                if (subs->endpoint == fp->endpoint) {
                        list_add_tail(&fp->list, &subs->fmt_list);
@@ -2354,7 +2360,7 @@ static int add_audio_endpoint(struct snd_usb_audio *chip, int stream, struct aud
 
        /* create a new pcm */
        as = kzalloc(sizeof(*as), GFP_KERNEL);
-       if (! as)
+       if (!as)
                return -ENOMEM;
        as->pcm_index = chip->pcm_devs;
        as->chip = chip;
@@ -2463,11 +2469,12 @@ static int parse_audio_format_i_type(struct snd_usb_audio *chip, struct audiofor
                }
                break;
        case USB_AUDIO_FORMAT_PCM8:
-               /* Dallas DS4201 workaround */
+               pcm_format = SNDRV_PCM_FORMAT_U8;
+
+               /* Dallas DS4201 workaround: it advertises U8 format, but really
+                  supports S8. */
                if (chip->usb_id == USB_ID(0x04fa, 0x4201))
                        pcm_format = SNDRV_PCM_FORMAT_S8;
-               else
-                       pcm_format = SNDRV_PCM_FORMAT_U8;
                break;
        case USB_AUDIO_FORMAT_IEEE_FLOAT:
                pcm_format = SNDRV_PCM_FORMAT_FLOAT_LE;
@@ -2671,12 +2678,23 @@ static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
        int format;
        struct audioformat *fp;
        unsigned char *fmt, *csep;
+       int num;
 
        dev = chip->dev;
 
        /* parse the interface's altsettings */
        iface = usb_ifnum_to_if(dev, iface_no);
-       for (i = 0; i < iface->num_altsetting; i++) {
+
+       num = iface->num_altsetting;
+
+       /*
+        * Dallas DS4201 workaround: It presents 5 altsettings, but the last
+        * one misses syncpipe, and does not produce any sound.
+        */
+       if (chip->usb_id == USB_ID(0x04fa, 0x4201))
+               num = 4;
+
+       for (i = 0; i < num; i++) {
                alts = &iface->altsetting[i];
                altsd = get_iface_desc(alts);
                /* skip invalid one */
@@ -3375,14 +3393,14 @@ static int snd_usb_create_quirk(struct snd_usb_audio *chip,
 static void proc_audio_usbbus_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
 {
        struct snd_usb_audio *chip = entry->private_data;
-       if (! chip->shutdown)
+       if (!chip->shutdown)
                snd_iprintf(buffer, "%03d/%03d\n", chip->dev->bus->busnum, chip->dev->devnum);
 }
 
 static void proc_audio_usbid_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
 {
        struct snd_usb_audio *chip = entry->private_data;
-       if (! chip->shutdown)
+       if (!chip->shutdown)
                snd_iprintf(buffer, "%04x:%04x\n", 
                            USB_ID_VENDOR(chip->usb_id),
                            USB_ID_PRODUCT(chip->usb_id));
@@ -3391,9 +3409,9 @@ static void proc_audio_usbid_read(struct snd_info_entry *entry, struct snd_info_
 static void snd_usb_audio_create_proc(struct snd_usb_audio *chip)
 {
        struct snd_info_entry *entry;
-       if (! snd_card_proc_new(chip->card, "usbbus", &entry))
+       if (!snd_card_proc_new(chip->card, "usbbus", &entry))
                snd_info_set_text_ops(entry, chip, proc_audio_usbbus_read);
-       if (! snd_card_proc_new(chip->card, "usbid", &entry))
+       if (!snd_card_proc_new(chip->card, "usbid", &entry))
                snd_info_set_text_ops(entry, chip, proc_audio_usbid_read);
 }
 
@@ -3406,7 +3424,6 @@ static void snd_usb_audio_create_proc(struct snd_usb_audio *chip)
 
 static int snd_usb_audio_free(struct snd_usb_audio *chip)
 {
-       usb_chip[chip->index] = NULL;
        kfree(chip);
        return 0;
 }
@@ -3600,8 +3617,8 @@ static void *snd_usb_audio_probe(struct usb_device *dev,
                                snd_card_set_dev(chip->card, &intf->dev);
                                break;
                        }
-               if (! chip) {
-                       snd_printk(KERN_ERR "no available usb audio device\n");
+               if (!chip) {
+                       printk(KERN_ERR "no available usb audio device\n");
                        goto __error;
                }
        }
@@ -3671,6 +3688,7 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, void *ptr)
                list_for_each(p, &chip->mixer_list) {
                        snd_usb_mixer_disconnect(p);
                }
+               usb_chip[chip->index] = NULL;
                mutex_unlock(&register_mutex);
                snd_card_free_when_closed(card);
        } else {
index 938dff5f9cef5dcab423514921f0c5a76a862e05..82a8d14c26af26671513990291db6426c2de05c4 100644 (file)
        .idProduct = prod, \
        .bInterfaceClass = USB_CLASS_VENDOR_SPEC
 
+/* Creative/E-Mu devices */
+{
+       USB_DEVICE(0x041e, 0x3010),
+       .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+               .vendor_name = "Creative Labs",
+               .product_name = "Sound Blaster MP3+",
+               .ifnum = QUIRK_NO_INTERFACE
+       }
+},
+{
+       /* E-Mu 0202 USB */
+       .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
+       .idVendor = 0x041e,
+       .idProduct = 0x3f02,
+       .bInterfaceClass = USB_CLASS_AUDIO,
+},
+{
+       /* E-Mu 0404 USB */
+       .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
+       .idVendor = 0x041e,
+       .idProduct = 0x3f04,
+       .bInterfaceClass = USB_CLASS_AUDIO,
+},
+
 /*
  * Logitech QuickCam: bDeviceClass is vendor-specific, so generic interface
  * class matches do not take effect without an explicit ID match.
        .bInterfaceClass = USB_CLASS_AUDIO,
        .bInterfaceSubClass = USB_SUBCLASS_AUDIO_CONTROL
 },
-/* E-Mu devices */
-{
-       .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
-       .idVendor = 0x041e,
-       .idProduct = 0x3f02,
-       .bInterfaceClass = USB_CLASS_AUDIO,
-},
-{
-       .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
-       .idVendor = 0x041e,
-       .idProduct = 0x3f04,
-       .bInterfaceClass = USB_CLASS_AUDIO,
-},
+
 /*
  * Yamaha devices
  */
@@ -1165,19 +1177,6 @@ YAMAHA_DEVICE(0x7010, "UB99"),
                }
        }
 },
-{
-       USB_DEVICE(0x582, 0x00a6),
-       .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
-               .vendor_name = "Roland",
-               .product_name = "Juno-G",
-               .ifnum = 0,
-               .type = QUIRK_MIDI_FIXED_ENDPOINT,
-               .data = & (const struct snd_usb_midi_endpoint_info) {
-                       .out_cables = 0x0001,
-                       .in_cables  = 0x0001
-               }
-       }
-},
 {      /*
         * This quirk is for the "Advanced" modes of the Edirol UA-25.
         * If the switch is not in an advanced setting, the UA-25 has
@@ -1335,6 +1334,19 @@ YAMAHA_DEVICE(0x7010, "UB99"),
        }
 },
        /* TODO: add Edirol MD-P1 support */
+{
+       USB_DEVICE(0x582, 0x00a6),
+       .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+               .vendor_name = "Roland",
+               .product_name = "Juno-G",
+               .ifnum = 0,
+               .type = QUIRK_MIDI_FIXED_ENDPOINT,
+               .data = & (const struct snd_usb_midi_endpoint_info) {
+                       .out_cables = 0x0001,
+                       .in_cables  = 0x0001
+               }
+       }
+},
 {
        /* Roland SH-201 */
        USB_DEVICE(0x0582, 0x00ad),
@@ -1719,17 +1731,6 @@ YAMAHA_DEVICE(0x7010, "UB99"),
        }
 },
 
-{
-       /* Creative Sound Blaster MP3+ */
-       USB_DEVICE(0x041e, 0x3010),
-       .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
-               .vendor_name = "Creative Labs",
-               .product_name = "Sound Blaster MP3+",
-               .ifnum = QUIRK_NO_INTERFACE
-       }
-       
-},
-
 /* Emagic devices */
 {
        USB_DEVICE(0x086a, 0x0001),